[Mesa-dev] [PATCH 6/6] i965: Use NIR for lowering texture swizzle
Jason Ekstrand
jason at jlekstrand.net
Thu Nov 12 12:13:28 PST 2015
Now that nir_lower_tex can do texture swizzle lowering, we can use that
instead of repeating more-or-less the same code in both backends. This
both allows us to share code and means that things like the tg4
work-arounds are somewhat simpler because they don't have to take the
swizzle into account.
---
src/mesa/drivers/dri/i965/brw_fs.h | 4 -
src/mesa/drivers/dri/i965/brw_fs_visitor.cpp | 105 ++++---------------------
src/mesa/drivers/dri/i965/brw_nir.c | 14 +++-
src/mesa/drivers/dri/i965/brw_vec4.h | 4 -
src/mesa/drivers/dri/i965/brw_vec4_nir.cpp | 24 +++---
src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp | 93 ++--------------------
6 files changed, 47 insertions(+), 197 deletions(-)
diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h
index 8a181d7..145d60d 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.h
+++ b/src/mesa/drivers/dri/i965/brw_fs.h
@@ -115,10 +115,6 @@ public:
void setup_uniform_clipplane_values(gl_clip_plane *clip_planes);
void compute_clip_distance(gl_clip_plane *clip_planes);
- uint32_t gather_channel(int orig_chan, uint32_t sampler);
- void swizzle_result(ir_texture_opcode op, int dest_components,
- fs_reg orig_val, uint32_t sampler);
-
fs_inst *get_instruction_generating_reg(fs_inst *start,
fs_inst *end,
const fs_reg ®);
diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
index faf304c..bb1e5c9 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
@@ -116,24 +116,6 @@ fs_visitor::emit_texture(ir_texture_opcode op,
{
fs_inst *inst = NULL;
- if (op == ir_tg4) {
- /* When tg4 is used with the degenerate ZERO/ONE swizzles, don't bother
- * emitting anything other than setting up the constant result.
- */
- int swiz = GET_SWZ(key_tex->swizzles[sampler], gather_component);
- if (swiz == SWIZZLE_ZERO || swiz == SWIZZLE_ONE) {
-
- fs_reg res = vgrf(glsl_type::vec4_type);
- this->result = res;
-
- for (int i=0; i<4; i++) {
- bld.MOV(res, fs_reg(swiz == SWIZZLE_ZERO ? 0.0f : 1.0f));
- res = offset(res, bld, 1);
- }
- return;
- }
- }
-
if (op == ir_query_levels) {
/* textureQueryLevels() is implemented in terms of TXS so we need to
* pass a valid LOD argument.
@@ -200,8 +182,15 @@ fs_visitor::emit_texture(ir_texture_opcode op,
inst->offset = offset_value.fixed_hw_reg.dw1.ud;
if (op == ir_tg4) {
- inst->offset |=
- gather_channel(gather_component, sampler) << 16; /* M0.2:16-17 */
+ if (gather_component == 1 &&
+ key_tex->gather_channel_quirk_mask & (1 << sampler)) {
+ /* gather4 sampler is broken for green channel on RG32F --
+ * we must ask for blue instead.
+ */
+ inst->offset |= 2 << 16;
+ } else {
+ inst->offset |= gather_component << 16;
+ }
if (devinfo->gen == 6)
emit_gen6_gather_wa(key_tex->gen6_gather_wa[sampler], dst);
@@ -225,7 +214,12 @@ fs_visitor::emit_texture(ir_texture_opcode op,
bld.LOAD_PAYLOAD(dst, fixed_payload, components, 0);
}
- swizzle_result(op, dest_type->vector_elements, dst, sampler);
+ if (op == ir_query_levels) {
+ /* # levels is in .w */
+ dst = offset(dst, bld, 3);
+ }
+
+ this->result = dst;
}
/**
@@ -258,75 +252,6 @@ fs_visitor::emit_gen6_gather_wa(uint8_t wa, fs_reg dst)
}
}
-/**
- * Set up the gather channel based on the swizzle, for gather4.
- */
-uint32_t
-fs_visitor::gather_channel(int orig_chan, uint32_t sampler)
-{
- int swiz = GET_SWZ(key_tex->swizzles[sampler], orig_chan);
- switch (swiz) {
- case SWIZZLE_X: return 0;
- case SWIZZLE_Y:
- /* gather4 sampler is broken for green channel on RG32F --
- * we must ask for blue instead.
- */
- if (key_tex->gather_channel_quirk_mask & (1 << sampler))
- return 2;
- return 1;
- case SWIZZLE_Z: return 2;
- case SWIZZLE_W: return 3;
- default:
- unreachable("Not reached"); /* zero, one swizzles handled already */
- }
-}
-
-/**
- * Swizzle the result of a texture result. This is necessary for
- * EXT_texture_swizzle as well as DEPTH_TEXTURE_MODE for shadow comparisons.
- */
-void
-fs_visitor::swizzle_result(ir_texture_opcode op, int dest_components,
- fs_reg orig_val, uint32_t sampler)
-{
- if (op == ir_query_levels) {
- /* # levels is in .w */
- this->result = offset(orig_val, bld, 3);
- return;
- }
-
- this->result = orig_val;
-
- /* txs,lod don't actually sample the texture, so swizzling the result
- * makes no sense.
- */
- if (op == ir_txs || op == ir_lod || op == ir_tg4)
- return;
-
- if (dest_components == 1) {
- /* Ignore DEPTH_TEXTURE_MODE swizzling. */
- } else if (key_tex->swizzles[sampler] != SWIZZLE_NOOP) {
- fs_reg swizzled_result = vgrf(glsl_type::vec4_type);
- swizzled_result.type = orig_val.type;
-
- for (int i = 0; i < 4; i++) {
- int swiz = GET_SWZ(key_tex->swizzles[sampler], i);
- fs_reg l = swizzled_result;
- l = offset(l, bld, i);
-
- if (swiz == SWIZZLE_ZERO) {
- bld.MOV(l, fs_reg(0.0f));
- } else if (swiz == SWIZZLE_ONE) {
- bld.MOV(l, fs_reg(1.0f));
- } else {
- bld.MOV(l, offset(orig_val, bld,
- GET_SWZ(key_tex->swizzles[sampler], i)));
- }
- }
- this->result = swizzled_result;
- }
-}
-
/** Emits a dummy fragment shader consisting of magenta for bringup purposes. */
void
fs_visitor::emit_dummy_fs()
diff --git a/src/mesa/drivers/dri/i965/brw_nir.c b/src/mesa/drivers/dri/i965/brw_nir.c
index 3999a60..2b339ba 100644
--- a/src/mesa/drivers/dri/i965/brw_nir.c
+++ b/src/mesa/drivers/dri/i965/brw_nir.c
@@ -414,8 +414,20 @@ brw_nir_apply_sampler_key(nir_shader *nir,
tex_options.saturate_r = key_tex->gl_clamp_mask[2];
}
- if (nir_lower_tex(nir, &tex_options))
+ /* Prior to Haswell, we have to fake texture swizzle */
+ for (unsigned s = 0; s < MAX_SAMPLERS; s++) {
+ if (key_tex->swizzles[s] == SWIZZLE_NOOP)
+ continue;
+
+ tex_options.swizzle_result |= (1 << s);
+ for (unsigned c = 0; c < 4; c++)
+ tex_options.swizzles[s][c] = GET_SWZ(key_tex->swizzles[s], c);
+ }
+
+ if (nir_lower_tex(nir, &tex_options)) {
+ nir_validate_shader(nir);
nir_optimize(nir, is_scalar);
+ }
}
enum brw_reg_type
diff --git a/src/mesa/drivers/dri/i965/brw_vec4.h b/src/mesa/drivers/dri/i965/brw_vec4.h
index ec8abf4..3f67432 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4.h
+++ b/src/mesa/drivers/dri/i965/brw_vec4.h
@@ -275,13 +275,9 @@ public:
bool is_cube_array,
uint32_t sampler, src_reg sampler_reg);
- uint32_t gather_channel(unsigned gather_component, uint32_t sampler);
src_reg emit_mcs_fetch(const glsl_type *coordinate_type, src_reg coordinate,
src_reg sampler);
void emit_gen6_gather_wa(uint8_t wa, dst_reg dst);
- void swizzle_result(ir_texture_opcode op, dst_reg dest,
- src_reg orig_val, uint32_t sampler,
- const glsl_type *dest_type);
void emit_ndc_computation();
void emit_psiz_and_flags(dst_reg reg);
diff --git a/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp b/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp
index e0d5a14..dae8cf4 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp
@@ -1580,17 +1580,6 @@ vec4_visitor::nir_emit_texture(nir_tex_instr *instr)
nir_tex_instr_dest_size(instr));
dst_reg dest = get_nir_dest(instr->dest, instr->dest_type);
- /* When tg4 is used with the degenerate ZERO/ONE swizzles, don't bother
- * emitting anything other than setting up the constant result.
- */
- if (instr->op == nir_texop_tg4) {
- int swiz = GET_SWZ(key_tex->swizzles[sampler], instr->component);
- if (swiz == SWIZZLE_ZERO || swiz == SWIZZLE_ONE) {
- emit(MOV(dest, src_reg(swiz == SWIZZLE_ONE ? 1.0f : 0.0f)));
- return;
- }
- }
-
/* Load the texture operation sources */
for (unsigned i = 0; i < instr->num_srcs; i++) {
switch (instr->src[i].src_type) {
@@ -1702,8 +1691,17 @@ vec4_visitor::nir_emit_texture(nir_tex_instr *instr)
}
/* Stuff the channel select bits in the top of the texture offset */
- if (instr->op == nir_texop_tg4)
- constant_offset |= gather_channel(instr->component, sampler) << 16;
+ if (instr->op == nir_texop_tg4) {
+ if (instr->component == 1 &&
+ (key_tex->gather_channel_quirk_mask & (1 << sampler))) {
+ /* gather4 sampler is broken for green channel on RG32F --
+ * we must ask for blue instead.
+ */
+ constant_offset |= 2 << 16;
+ } else {
+ constant_offset |= instr->component << 16;
+ }
+ }
ir_texture_opcode op = ir_texture_opcode_for_nir_texop(instr->op);
diff --git a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
index 94759af..af61a06 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
@@ -915,8 +915,7 @@ vec4_visitor::emit_texture(ir_texture_opcode op,
unreachable("Unrecognized tex op");
}
- vec4_instruction *inst = new(mem_ctx) vec4_instruction(
- opcode, dst_reg(this, dest_type));
+ vec4_instruction *inst = new(mem_ctx) vec4_instruction(opcode, dest);
inst->offset = constant_offset;
@@ -1067,8 +1066,13 @@ vec4_visitor::emit_texture(ir_texture_opcode op,
emit_gen6_gather_wa(key_tex->gen6_gather_wa[sampler], inst->dst);
}
- swizzle_result(op, dest,
- src_reg(inst->dst), sampler, dest_type);
+ if (op == ir_query_levels) {
+ /* # levels is in .w */
+ src_reg swizzled(dest);
+ swizzled.swizzle = BRW_SWIZZLE4(SWIZZLE_W, SWIZZLE_W,
+ SWIZZLE_W, SWIZZLE_W);
+ emit(MOV(dest, swizzled));
+ }
}
/**
@@ -1098,87 +1102,6 @@ vec4_visitor::emit_gen6_gather_wa(uint8_t wa, dst_reg dst)
}
}
-/**
- * Set up the gather channel based on the swizzle, for gather4.
- */
-uint32_t
-vec4_visitor::gather_channel(unsigned gather_component, uint32_t sampler)
-{
- int swiz = GET_SWZ(key_tex->swizzles[sampler], gather_component);
- switch (swiz) {
- case SWIZZLE_X: return 0;
- case SWIZZLE_Y:
- /* gather4 sampler is broken for green channel on RG32F --
- * we must ask for blue instead.
- */
- if (key_tex->gather_channel_quirk_mask & (1 << sampler))
- return 2;
- return 1;
- case SWIZZLE_Z: return 2;
- case SWIZZLE_W: return 3;
- default:
- unreachable("Not reached"); /* zero, one swizzles handled already */
- }
-}
-
-void
-vec4_visitor::swizzle_result(ir_texture_opcode op, dst_reg dest,
- src_reg orig_val, uint32_t sampler,
- const glsl_type *dest_type)
-{
- int s = key_tex->swizzles[sampler];
-
- dst_reg swizzled_result = dest;
-
- if (op == ir_query_levels) {
- /* # levels is in .w */
- orig_val.swizzle = BRW_SWIZZLE4(SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W);
- emit(MOV(swizzled_result, orig_val));
- return;
- }
-
- if (op == ir_txs || dest_type == glsl_type::float_type
- || s == SWIZZLE_NOOP || op == ir_tg4) {
- emit(MOV(swizzled_result, orig_val));
- return;
- }
-
-
- int zero_mask = 0, one_mask = 0, copy_mask = 0;
- int swizzle[4] = {0};
-
- for (int i = 0; i < 4; i++) {
- switch (GET_SWZ(s, i)) {
- case SWIZZLE_ZERO:
- zero_mask |= (1 << i);
- break;
- case SWIZZLE_ONE:
- one_mask |= (1 << i);
- break;
- default:
- copy_mask |= (1 << i);
- swizzle[i] = GET_SWZ(s, i);
- break;
- }
- }
-
- if (copy_mask) {
- orig_val.swizzle = BRW_SWIZZLE4(swizzle[0], swizzle[1], swizzle[2], swizzle[3]);
- swizzled_result.writemask = copy_mask;
- emit(MOV(swizzled_result, orig_val));
- }
-
- if (zero_mask) {
- swizzled_result.writemask = zero_mask;
- emit(MOV(swizzled_result, src_reg(0.0f)));
- }
-
- if (one_mask) {
- swizzled_result.writemask = one_mask;
- emit(MOV(swizzled_result, src_reg(1.0f)));
- }
-}
-
void
vec4_visitor::gs_emit_vertex(int stream_id)
{
--
2.5.0.400.gff86faf
More information about the mesa-dev
mailing list