nir/lower_tex: Add support for lowering texture swizzle

Reviewed-by: Connor Abbott <cwabbott0@gmail.com>
This commit is contained in:
Jason Ekstrand 2015-11-11 18:30:31 -08:00
parent 6921b17107
commit 8537b4ab76
2 changed files with 80 additions and 0 deletions

View file

@ -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,

View file

@ -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;