i965: Use NIR for lowering texture swizzle

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.

Reviewed-by: Connor Abbott <cwabbott0@gmail.com>
This commit is contained in:
Jason Ekstrand
2015-11-11 18:41:37 -08:00
parent 8537b4ab76
commit d9b8fde963
6 changed files with 44 additions and 196 deletions
-4
View File
@@ -116,10 +116,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 &reg);
+15 -90
View File
@@ -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, brw_imm_f(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.
@@ -220,8 +202,15 @@ fs_visitor::emit_texture(ir_texture_opcode op,
inst->offset = offset_value.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);
@@ -245,7 +234,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;
}
/**
@@ -278,75 +272,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, brw_imm_f(0.0f));
} else if (swiz == SWIZZLE_ONE) {
bld.MOV(l, brw_imm_f(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()
+10
View File
@@ -435,6 +435,16 @@ brw_nir_apply_sampler_key(nir_shader *nir,
tex_options.saturate_r = key_tex->gl_clamp_mask[2];
}
/* 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 = nir_optimize(nir, is_scalar);
-4
View File
@@ -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);
+11 -13
View File
@@ -1590,17 +1590,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, brw_imm_f(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) {
@@ -1716,8 +1705,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);
+8 -85
View File
@@ -920,8 +920,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;
@@ -1072,8 +1071,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));
}
}
/**
@@ -1103,87 +1107,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, brw_imm_f(0.0f)));
}
if (one_mask) {
swizzled_result.writemask = one_mask;
emit(MOV(swizzled_result, brw_imm_f(1.0f)));
}
}
void
vec4_visitor::gs_emit_vertex(int stream_id)
{