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:
@@ -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 ®);
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user