summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Ekstrand <[email protected]>2015-11-11 18:30:31 -0800
committerJason Ekstrand <[email protected]>2015-11-23 11:04:49 -0800
commit8537b4ab762ec4249acf23164e0e5a943d2d05af (patch)
tree18cbe3413933b3190a020333ccc772513ec35e49
parent6921b17107d1a55582b174e6937fae22cdc65ee4 (diff)
nir/lower_tex: Add support for lowering texture swizzle
Reviewed-by: Connor Abbott <[email protected]>
-rw-r--r--src/glsl/nir/nir.h13
-rw-r--r--src/glsl/nir/nir_lower_tex.c67
2 files changed, 80 insertions, 0 deletions
diff --git a/src/glsl/nir/nir.h b/src/glsl/nir/nir.h
index 1baef19812b..524717a0fda 100644
--- a/src/glsl/nir/nir.h
+++ b/src/glsl/nir/nir.h
@@ -2019,6 +2019,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 6dea8377c28..93ebf8e78a9 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;