[Mesa-dev] [PATCH 5/6] nir/lower_tex: Add support for lowering texture swizzle
Jason Ekstrand
jason at jlekstrand.net
Thu Nov 12 12:13:27 PST 2015
---
src/glsl/nir/nir.h | 13 +++++++++
src/glsl/nir/nir_lower_tex.c | 67 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 80 insertions(+)
diff --git a/src/glsl/nir/nir.h b/src/glsl/nir/nir.h
index 53dea7f..a07380e 100644
--- a/src/glsl/nir/nir.h
+++ b/src/glsl/nir/nir.h
@@ -2006,6 +2006,19 @@ typedef struct nir_lower_tex_options {
unsigned saturate_s;
unsigned saturate_t;
unsigned saturate_r;
+
+ /* Bitmask of samplers that need swizzling.
+ *
+ * If (swizzle_result & (1 << sampler_index)), then the swizzle in
+ * swizzles[sampler_index] is applied to the result of the texturing
+ * operation.
+ */
+ unsigned swizzle_result;
+
+ /* A swizzle for each sampler. Values 0-3 represent x, y, z, or w swizzles
+ * while 4 and 5 represent 0 and 1 respectively.
+ */
+ uint8_t swizzles[32][4];
} nir_lower_tex_options;
bool nir_lower_tex(nir_shader *shader,
diff --git a/src/glsl/nir/nir_lower_tex.c b/src/glsl/nir/nir_lower_tex.c
index 6dea837..93ebf8e 100644
--- a/src/glsl/nir/nir_lower_tex.c
+++ b/src/glsl/nir/nir_lower_tex.c
@@ -215,6 +215,66 @@ saturate_src(nir_builder *b, nir_tex_instr *tex, unsigned sat_mask)
}
}
+static nir_ssa_def *
+get_zero_or_one(nir_builder *b, nir_alu_type type, uint8_t swizzle_val)
+{
+ nir_const_value v;
+
+ memset(&v, 0, sizeof(v));
+
+ if (swizzle_val == 4) {
+ v.u[0] = v.u[1] = v.u[2] = v.u[3] = 0;
+ } else {
+ assert(swizzle_val == 5);
+ if (type == nir_type_float)
+ v.f[0] = v.f[1] = v.f[2] = v.f[3] = 1.0;
+ else
+ v.u[0] = v.u[1] = v.u[2] = v.u[3] = 1;
+ }
+
+ return nir_build_imm(b, 4, v);
+}
+
+static void
+swizzle_result(nir_builder *b, nir_tex_instr *tex, const uint8_t swizzle[4])
+{
+ assert(tex->dest.is_ssa);
+
+ b->cursor = nir_after_instr(&tex->instr);
+
+ nir_ssa_def *swizzled;
+ if (tex->op == nir_texop_tg4) {
+ if (swizzle[tex->component] < 4) {
+ /* This one's easy */
+ tex->component = swizzle[tex->component];
+ return;
+ } else {
+ swizzled = get_zero_or_one(b, tex->dest_type, swizzle[tex->component]);
+ }
+ } else {
+ assert(nir_tex_instr_dest_size(tex) == 4);
+ if (swizzle[0] < 4 && swizzle[1] < 4 &&
+ swizzle[2] < 4 && swizzle[3] < 4) {
+ unsigned swiz[4] = { swizzle[0], swizzle[1], swizzle[2], swizzle[3] };
+ /* We have no 0's or 1's, just emit a swizzling MOV */
+ swizzled = nir_swizzle(b, &tex->dest.ssa, swiz, 4, false);
+ } else {
+ nir_ssa_def *srcs[4];
+ for (unsigned i = 0; i < 4; i++) {
+ if (swizzle[i] < 4) {
+ srcs[i] = nir_channel(b, &tex->dest.ssa, swizzle[i]);
+ } else {
+ srcs[i] = get_zero_or_one(b, tex->dest_type, swizzle[i]);
+ }
+ }
+ swizzled = nir_vec(b, srcs, 4);
+ }
+ }
+
+ nir_ssa_def_rewrite_uses_after(&tex->dest.ssa, nir_src_for_ssa(swizzled),
+ swizzled->parent_instr);
+}
+
static bool
nir_lower_tex_block(nir_block *block, void *void_state)
{
@@ -256,6 +316,13 @@ nir_lower_tex_block(nir_block *block, void *void_state)
saturate_src(b, tex, sat_mask);
state->progress = true;
}
+
+ if (((1 << tex->sampler_index) & state->options->swizzle_result) &&
+ !nir_tex_instr_is_query(tex) &&
+ !(tex->is_shadow && tex->is_new_style_shadow)) {
+ swizzle_result(b, tex, state->options->swizzles[tex->sampler_index]);
+ state->progress = true;
+ }
}
return true;
--
2.5.0.400.gff86faf
More information about the mesa-dev
mailing list