intel/vec4: Inline emit_texture and move helpers to brw_vec4_nir.cpp
emit_texture() only has one caller, nir_emit_texture(). We may as well inline that. Move the associated helper functions for emitting sampler messages there as well, to keep associated code nearby. Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/5183 Reviewed-by: Caio Oliveira <caio.oliveira@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14191>
This commit is contained in:
parent
92d194427d
commit
d3f4f23ca3
|
@ -254,20 +254,6 @@ public:
|
||||||
void emit_pack_unorm_4x8(const dst_reg &dst, const src_reg &src0);
|
void emit_pack_unorm_4x8(const dst_reg &dst, const src_reg &src0);
|
||||||
void emit_pack_snorm_4x8(const dst_reg &dst, const src_reg &src0);
|
void emit_pack_snorm_4x8(const dst_reg &dst, const src_reg &src0);
|
||||||
|
|
||||||
void emit_texture(nir_texop op,
|
|
||||||
dst_reg dest,
|
|
||||||
int dest_components,
|
|
||||||
src_reg coordinate,
|
|
||||||
int coord_components,
|
|
||||||
src_reg shadow_comparator,
|
|
||||||
src_reg lod, src_reg lod2,
|
|
||||||
src_reg sample_index,
|
|
||||||
uint32_t constant_offset,
|
|
||||||
src_reg offset_value,
|
|
||||||
src_reg mcs,
|
|
||||||
uint32_t surface, src_reg surface_reg,
|
|
||||||
src_reg sampler_reg);
|
|
||||||
|
|
||||||
src_reg emit_mcs_fetch(const glsl_type *coordinate_type, src_reg coordinate,
|
src_reg emit_mcs_fetch(const glsl_type *coordinate_type, src_reg coordinate,
|
||||||
src_reg surface);
|
src_reg surface);
|
||||||
void emit_gfx6_gather_wa(uint8_t wa, dst_reg dst);
|
void emit_gfx6_gather_wa(uint8_t wa, dst_reg dst);
|
||||||
|
@ -302,8 +288,6 @@ public:
|
||||||
void dump_instruction(const backend_instruction *inst) const;
|
void dump_instruction(const backend_instruction *inst) const;
|
||||||
void dump_instruction(const backend_instruction *inst, FILE *file) const;
|
void dump_instruction(const backend_instruction *inst, FILE *file) const;
|
||||||
|
|
||||||
bool is_high_sampler(src_reg sampler);
|
|
||||||
|
|
||||||
bool optimize_predicate(nir_alu_instr *instr, enum brw_predicate *predicate);
|
bool optimize_predicate(nir_alu_instr *instr, enum brw_predicate *predicate);
|
||||||
|
|
||||||
void emit_conversion_from_double(dst_reg dst, src_reg src);
|
void emit_conversion_from_double(dst_reg dst, src_reg src);
|
||||||
|
|
|
@ -1944,6 +1944,15 @@ vec4_visitor::nir_emit_jump(nir_jump_instr *instr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
is_high_sampler(const struct intel_device_info *devinfo, src_reg sampler)
|
||||||
|
{
|
||||||
|
if (devinfo->verx10 != 75)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return sampler.file != IMM || sampler.ud >= 16;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
vec4_visitor::nir_emit_texture(nir_tex_instr *instr)
|
vec4_visitor::nir_emit_texture(nir_tex_instr *instr)
|
||||||
{
|
{
|
||||||
|
@ -2083,12 +2092,258 @@ vec4_visitor::nir_emit_texture(nir_tex_instr *instr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
emit_texture(instr->op, dest, nir_tex_instr_dest_size(instr),
|
enum opcode opcode;
|
||||||
coordinate, instr->coord_components,
|
switch (instr->op) {
|
||||||
shadow_comparator,
|
case nir_texop_tex: opcode = SHADER_OPCODE_TXL; break;
|
||||||
lod, lod2, sample_index,
|
case nir_texop_txl: opcode = SHADER_OPCODE_TXL; break;
|
||||||
constant_offset, offset_value, mcs,
|
case nir_texop_txd: opcode = SHADER_OPCODE_TXD; break;
|
||||||
texture, texture_reg, sampler_reg);
|
case nir_texop_txf: opcode = SHADER_OPCODE_TXF; break;
|
||||||
|
case nir_texop_txf_ms: opcode = SHADER_OPCODE_TXF_CMS; break;
|
||||||
|
case nir_texop_txs: opcode = SHADER_OPCODE_TXS; break;
|
||||||
|
case nir_texop_query_levels: opcode = SHADER_OPCODE_TXS; break;
|
||||||
|
case nir_texop_texture_samples: opcode = SHADER_OPCODE_SAMPLEINFO; break;
|
||||||
|
case nir_texop_tg4:
|
||||||
|
opcode = offset_value.file != BAD_FILE ? SHADER_OPCODE_TG4_OFFSET
|
||||||
|
: SHADER_OPCODE_TG4;
|
||||||
|
break;
|
||||||
|
case nir_texop_samples_identical: {
|
||||||
|
/* There are some challenges implementing this for vec4, and it seems
|
||||||
|
* unlikely to be used anyway. For now, just return false ways.
|
||||||
|
*/
|
||||||
|
emit(MOV(dest, brw_imm_ud(0u)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case nir_texop_txb:
|
||||||
|
case nir_texop_lod:
|
||||||
|
unreachable("Implicit LOD is only valid inside fragment shaders.");
|
||||||
|
default:
|
||||||
|
unreachable("Unrecognized tex op");
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4_instruction *inst = new(mem_ctx) vec4_instruction(opcode, dest);
|
||||||
|
|
||||||
|
inst->offset = constant_offset;
|
||||||
|
|
||||||
|
/* The message header is necessary for:
|
||||||
|
* - Gfx4 (always)
|
||||||
|
* - Texel offsets
|
||||||
|
* - Gather channel selection
|
||||||
|
* - Sampler indices too large to fit in a 4-bit value.
|
||||||
|
* - Sampleinfo message - takes no parameters, but mlen = 0 is illegal
|
||||||
|
*/
|
||||||
|
inst->header_size =
|
||||||
|
(devinfo->ver < 5 ||
|
||||||
|
inst->offset != 0 ||
|
||||||
|
opcode == SHADER_OPCODE_TG4 ||
|
||||||
|
opcode == SHADER_OPCODE_TG4_OFFSET ||
|
||||||
|
opcode == SHADER_OPCODE_SAMPLEINFO ||
|
||||||
|
is_high_sampler(devinfo, sampler_reg)) ? 1 : 0;
|
||||||
|
inst->base_mrf = 2;
|
||||||
|
inst->mlen = inst->header_size;
|
||||||
|
inst->dst.writemask = WRITEMASK_XYZW;
|
||||||
|
inst->shadow_compare = shadow_comparator.file != BAD_FILE;
|
||||||
|
|
||||||
|
inst->src[1] = texture_reg;
|
||||||
|
inst->src[2] = sampler_reg;
|
||||||
|
|
||||||
|
/* MRF for the first parameter */
|
||||||
|
int param_base = inst->base_mrf + inst->header_size;
|
||||||
|
|
||||||
|
if (opcode == SHADER_OPCODE_TXS) {
|
||||||
|
int writemask = devinfo->ver == 4 ? WRITEMASK_W : WRITEMASK_X;
|
||||||
|
emit(MOV(dst_reg(MRF, param_base, lod.type, writemask), lod));
|
||||||
|
inst->mlen++;
|
||||||
|
} else if (opcode == SHADER_OPCODE_SAMPLEINFO) {
|
||||||
|
inst->dst.writemask = WRITEMASK_X;
|
||||||
|
} else {
|
||||||
|
/* Load the coordinate */
|
||||||
|
/* FINISHME: gl_clamp_mask and saturate */
|
||||||
|
int coord_mask = (1 << instr->coord_components) - 1;
|
||||||
|
int zero_mask = 0xf & ~coord_mask;
|
||||||
|
|
||||||
|
emit(MOV(dst_reg(MRF, param_base, coordinate.type, coord_mask),
|
||||||
|
coordinate));
|
||||||
|
inst->mlen++;
|
||||||
|
|
||||||
|
if (zero_mask != 0) {
|
||||||
|
emit(MOV(dst_reg(MRF, param_base, coordinate.type, zero_mask),
|
||||||
|
brw_imm_d(0)));
|
||||||
|
}
|
||||||
|
/* Load the shadow comparator */
|
||||||
|
if (shadow_comparator.file != BAD_FILE &&
|
||||||
|
opcode != SHADER_OPCODE_TXD &&
|
||||||
|
opcode != SHADER_OPCODE_TG4_OFFSET) {
|
||||||
|
emit(MOV(dst_reg(MRF, param_base + 1, shadow_comparator.type,
|
||||||
|
WRITEMASK_X),
|
||||||
|
shadow_comparator));
|
||||||
|
inst->mlen++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Load the LOD info */
|
||||||
|
switch (opcode) {
|
||||||
|
case SHADER_OPCODE_TXL: {
|
||||||
|
int mrf, writemask;
|
||||||
|
if (devinfo->ver >= 5) {
|
||||||
|
mrf = param_base + 1;
|
||||||
|
if (shadow_comparator.file != BAD_FILE) {
|
||||||
|
writemask = WRITEMASK_Y;
|
||||||
|
/* mlen already incremented */
|
||||||
|
} else {
|
||||||
|
writemask = WRITEMASK_X;
|
||||||
|
inst->mlen++;
|
||||||
|
}
|
||||||
|
} else /* devinfo->ver == 4 */ {
|
||||||
|
mrf = param_base;
|
||||||
|
writemask = WRITEMASK_W;
|
||||||
|
}
|
||||||
|
emit(MOV(dst_reg(MRF, mrf, lod.type, writemask), lod));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SHADER_OPCODE_TXF:
|
||||||
|
emit(MOV(dst_reg(MRF, param_base, lod.type, WRITEMASK_W), lod));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SHADER_OPCODE_TXF_CMS:
|
||||||
|
emit(MOV(dst_reg(MRF, param_base + 1, sample_index.type, WRITEMASK_X),
|
||||||
|
sample_index));
|
||||||
|
if (devinfo->ver >= 7) {
|
||||||
|
/* MCS data is in the first channel of `mcs`, but we need to get it into
|
||||||
|
* the .y channel of the second vec4 of params, so replicate .x across
|
||||||
|
* the whole vec4 and then mask off everything except .y
|
||||||
|
*/
|
||||||
|
mcs.swizzle = BRW_SWIZZLE_XXXX;
|
||||||
|
emit(MOV(dst_reg(MRF, param_base + 1, glsl_type::uint_type, WRITEMASK_Y),
|
||||||
|
mcs));
|
||||||
|
}
|
||||||
|
inst->mlen++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SHADER_OPCODE_TXD: {
|
||||||
|
const brw_reg_type type = lod.type;
|
||||||
|
|
||||||
|
if (devinfo->ver >= 5) {
|
||||||
|
lod.swizzle = BRW_SWIZZLE4(SWIZZLE_X,SWIZZLE_X,SWIZZLE_Y,SWIZZLE_Y);
|
||||||
|
lod2.swizzle = BRW_SWIZZLE4(SWIZZLE_X,SWIZZLE_X,SWIZZLE_Y,SWIZZLE_Y);
|
||||||
|
emit(MOV(dst_reg(MRF, param_base + 1, type, WRITEMASK_XZ), lod));
|
||||||
|
emit(MOV(dst_reg(MRF, param_base + 1, type, WRITEMASK_YW), lod2));
|
||||||
|
inst->mlen++;
|
||||||
|
|
||||||
|
if (nir_tex_instr_dest_size(instr) == 3 ||
|
||||||
|
shadow_comparator.file != BAD_FILE) {
|
||||||
|
lod.swizzle = BRW_SWIZZLE_ZZZZ;
|
||||||
|
lod2.swizzle = BRW_SWIZZLE_ZZZZ;
|
||||||
|
emit(MOV(dst_reg(MRF, param_base + 2, type, WRITEMASK_X), lod));
|
||||||
|
emit(MOV(dst_reg(MRF, param_base + 2, type, WRITEMASK_Y), lod2));
|
||||||
|
inst->mlen++;
|
||||||
|
|
||||||
|
if (shadow_comparator.file != BAD_FILE) {
|
||||||
|
emit(MOV(dst_reg(MRF, param_base + 2,
|
||||||
|
shadow_comparator.type, WRITEMASK_Z),
|
||||||
|
shadow_comparator));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else /* devinfo->ver == 4 */ {
|
||||||
|
emit(MOV(dst_reg(MRF, param_base + 1, type, WRITEMASK_XYZ), lod));
|
||||||
|
emit(MOV(dst_reg(MRF, param_base + 2, type, WRITEMASK_XYZ), lod2));
|
||||||
|
inst->mlen += 2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SHADER_OPCODE_TG4_OFFSET:
|
||||||
|
if (shadow_comparator.file != BAD_FILE) {
|
||||||
|
emit(MOV(dst_reg(MRF, param_base, shadow_comparator.type, WRITEMASK_W),
|
||||||
|
shadow_comparator));
|
||||||
|
}
|
||||||
|
|
||||||
|
emit(MOV(dst_reg(MRF, param_base + 1, glsl_type::ivec2_type, WRITEMASK_XY),
|
||||||
|
offset_value));
|
||||||
|
inst->mlen++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
emit(inst);
|
||||||
|
|
||||||
|
/* fixup num layers (z) for cube arrays: hardware returns faces * layers;
|
||||||
|
* spec requires layers.
|
||||||
|
*/
|
||||||
|
if (instr->op == nir_texop_txs && devinfo->ver < 7) {
|
||||||
|
/* Gfx4-6 return 0 instead of 1 for single layer surfaces. */
|
||||||
|
emit_minmax(BRW_CONDITIONAL_GE, writemask(inst->dst, WRITEMASK_Z),
|
||||||
|
src_reg(inst->dst), brw_imm_d(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (devinfo->ver == 6 && instr->op == nir_texop_tg4) {
|
||||||
|
emit_gfx6_gather_wa(key_tex->gfx6_gather_wa[texture], inst->dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instr->op == nir_texop_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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
src_reg
|
||||||
|
vec4_visitor::emit_mcs_fetch(const glsl_type *coordinate_type,
|
||||||
|
src_reg coordinate, src_reg surface)
|
||||||
|
{
|
||||||
|
vec4_instruction *inst =
|
||||||
|
new(mem_ctx) vec4_instruction(SHADER_OPCODE_TXF_MCS,
|
||||||
|
dst_reg(this, glsl_type::uvec4_type));
|
||||||
|
inst->base_mrf = 2;
|
||||||
|
inst->src[1] = surface;
|
||||||
|
inst->src[2] = brw_imm_ud(0); /* sampler */
|
||||||
|
inst->mlen = 1;
|
||||||
|
|
||||||
|
const int param_base = inst->base_mrf;
|
||||||
|
|
||||||
|
/* parameters are: u, v, r, lod; lod will always be zero due to api restrictions */
|
||||||
|
int coord_mask = (1 << coordinate_type->vector_elements) - 1;
|
||||||
|
int zero_mask = 0xf & ~coord_mask;
|
||||||
|
|
||||||
|
emit(MOV(dst_reg(MRF, param_base, coordinate_type, coord_mask),
|
||||||
|
coordinate));
|
||||||
|
|
||||||
|
emit(MOV(dst_reg(MRF, param_base, coordinate_type, zero_mask),
|
||||||
|
brw_imm_d(0)));
|
||||||
|
|
||||||
|
emit(inst);
|
||||||
|
return src_reg(inst->dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply workarounds for Gfx6 gather with UINT/SINT
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
vec4_visitor::emit_gfx6_gather_wa(uint8_t wa, dst_reg dst)
|
||||||
|
{
|
||||||
|
if (!wa)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int width = (wa & WA_8BIT) ? 8 : 16;
|
||||||
|
dst_reg dst_f = dst;
|
||||||
|
dst_f.type = BRW_REGISTER_TYPE_F;
|
||||||
|
|
||||||
|
/* Convert from UNORM to UINT */
|
||||||
|
emit(MUL(dst_f, src_reg(dst_f), brw_imm_f((float)((1 << width) - 1))));
|
||||||
|
emit(MOV(dst, src_reg(dst_f)));
|
||||||
|
|
||||||
|
if (wa & WA_SIGN) {
|
||||||
|
/* Reinterpret the UINT value as a signed INT value by
|
||||||
|
* shifting the sign bit into place, then shifting back
|
||||||
|
* preserving sign.
|
||||||
|
*/
|
||||||
|
emit(SHL(dst, src_reg(dst), brw_imm_d(32 - width)));
|
||||||
|
emit(ASR(dst, src_reg(dst), brw_imm_d(32 - width)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -788,284 +788,6 @@ vec4_visitor::emit_uniformize(const src_reg &src)
|
||||||
return src_reg(dst);
|
return src_reg(dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
src_reg
|
|
||||||
vec4_visitor::emit_mcs_fetch(const glsl_type *coordinate_type,
|
|
||||||
src_reg coordinate, src_reg surface)
|
|
||||||
{
|
|
||||||
vec4_instruction *inst =
|
|
||||||
new(mem_ctx) vec4_instruction(SHADER_OPCODE_TXF_MCS,
|
|
||||||
dst_reg(this, glsl_type::uvec4_type));
|
|
||||||
inst->base_mrf = 2;
|
|
||||||
inst->src[1] = surface;
|
|
||||||
inst->src[2] = brw_imm_ud(0); /* sampler */
|
|
||||||
inst->mlen = 1;
|
|
||||||
|
|
||||||
const int param_base = inst->base_mrf;
|
|
||||||
|
|
||||||
/* parameters are: u, v, r, lod; lod will always be zero due to api restrictions */
|
|
||||||
int coord_mask = (1 << coordinate_type->vector_elements) - 1;
|
|
||||||
int zero_mask = 0xf & ~coord_mask;
|
|
||||||
|
|
||||||
emit(MOV(dst_reg(MRF, param_base, coordinate_type, coord_mask),
|
|
||||||
coordinate));
|
|
||||||
|
|
||||||
emit(MOV(dst_reg(MRF, param_base, coordinate_type, zero_mask),
|
|
||||||
brw_imm_d(0)));
|
|
||||||
|
|
||||||
emit(inst);
|
|
||||||
return src_reg(inst->dst);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
vec4_visitor::is_high_sampler(src_reg sampler)
|
|
||||||
{
|
|
||||||
if (devinfo->verx10 != 75)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return sampler.file != IMM || sampler.ud >= 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
vec4_visitor::emit_texture(nir_texop op,
|
|
||||||
dst_reg dest,
|
|
||||||
int dest_components,
|
|
||||||
src_reg coordinate,
|
|
||||||
int coord_components,
|
|
||||||
src_reg shadow_comparator,
|
|
||||||
src_reg lod, src_reg lod2,
|
|
||||||
src_reg sample_index,
|
|
||||||
uint32_t constant_offset,
|
|
||||||
src_reg offset_value,
|
|
||||||
src_reg mcs,
|
|
||||||
uint32_t surface,
|
|
||||||
src_reg surface_reg,
|
|
||||||
src_reg sampler_reg)
|
|
||||||
{
|
|
||||||
enum opcode opcode;
|
|
||||||
switch (op) {
|
|
||||||
case nir_texop_tex: opcode = SHADER_OPCODE_TXL; break;
|
|
||||||
case nir_texop_txl: opcode = SHADER_OPCODE_TXL; break;
|
|
||||||
case nir_texop_txd: opcode = SHADER_OPCODE_TXD; break;
|
|
||||||
case nir_texop_txf: opcode = SHADER_OPCODE_TXF; break;
|
|
||||||
case nir_texop_txf_ms: opcode = SHADER_OPCODE_TXF_CMS; break;
|
|
||||||
case nir_texop_txs: opcode = SHADER_OPCODE_TXS; break;
|
|
||||||
case nir_texop_query_levels: opcode = SHADER_OPCODE_TXS; break;
|
|
||||||
case nir_texop_texture_samples: opcode = SHADER_OPCODE_SAMPLEINFO; break;
|
|
||||||
case nir_texop_tg4:
|
|
||||||
opcode = offset_value.file != BAD_FILE ? SHADER_OPCODE_TG4_OFFSET
|
|
||||||
: SHADER_OPCODE_TG4;
|
|
||||||
break;
|
|
||||||
case nir_texop_samples_identical: {
|
|
||||||
/* There are some challenges implementing this for vec4, and it seems
|
|
||||||
* unlikely to be used anyway. For now, just return false ways.
|
|
||||||
*/
|
|
||||||
emit(MOV(dest, brw_imm_ud(0u)));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case nir_texop_txb:
|
|
||||||
case nir_texop_lod:
|
|
||||||
unreachable("Implicit LOD is only valid inside fragment shaders.");
|
|
||||||
default:
|
|
||||||
unreachable("Unrecognized tex op");
|
|
||||||
}
|
|
||||||
|
|
||||||
vec4_instruction *inst = new(mem_ctx) vec4_instruction(opcode, dest);
|
|
||||||
|
|
||||||
inst->offset = constant_offset;
|
|
||||||
|
|
||||||
/* The message header is necessary for:
|
|
||||||
* - Gfx4 (always)
|
|
||||||
* - Texel offsets
|
|
||||||
* - Gather channel selection
|
|
||||||
* - Sampler indices too large to fit in a 4-bit value.
|
|
||||||
* - Sampleinfo message - takes no parameters, but mlen = 0 is illegal
|
|
||||||
*/
|
|
||||||
inst->header_size =
|
|
||||||
(devinfo->ver < 5 ||
|
|
||||||
inst->offset != 0 ||
|
|
||||||
opcode == SHADER_OPCODE_TG4 ||
|
|
||||||
opcode == SHADER_OPCODE_TG4_OFFSET ||
|
|
||||||
opcode == SHADER_OPCODE_SAMPLEINFO ||
|
|
||||||
is_high_sampler(sampler_reg)) ? 1 : 0;
|
|
||||||
inst->base_mrf = 2;
|
|
||||||
inst->mlen = inst->header_size;
|
|
||||||
inst->dst.writemask = WRITEMASK_XYZW;
|
|
||||||
inst->shadow_compare = shadow_comparator.file != BAD_FILE;
|
|
||||||
|
|
||||||
inst->src[1] = surface_reg;
|
|
||||||
inst->src[2] = sampler_reg;
|
|
||||||
|
|
||||||
/* MRF for the first parameter */
|
|
||||||
int param_base = inst->base_mrf + inst->header_size;
|
|
||||||
|
|
||||||
if (opcode == SHADER_OPCODE_TXS) {
|
|
||||||
int writemask = devinfo->ver == 4 ? WRITEMASK_W : WRITEMASK_X;
|
|
||||||
emit(MOV(dst_reg(MRF, param_base, lod.type, writemask), lod));
|
|
||||||
inst->mlen++;
|
|
||||||
} else if (opcode == SHADER_OPCODE_SAMPLEINFO) {
|
|
||||||
inst->dst.writemask = WRITEMASK_X;
|
|
||||||
} else {
|
|
||||||
/* Load the coordinate */
|
|
||||||
/* FINISHME: gl_clamp_mask and saturate */
|
|
||||||
int coord_mask = (1 << coord_components) - 1;
|
|
||||||
int zero_mask = 0xf & ~coord_mask;
|
|
||||||
|
|
||||||
emit(MOV(dst_reg(MRF, param_base, coordinate.type, coord_mask),
|
|
||||||
coordinate));
|
|
||||||
inst->mlen++;
|
|
||||||
|
|
||||||
if (zero_mask != 0) {
|
|
||||||
emit(MOV(dst_reg(MRF, param_base, coordinate.type, zero_mask),
|
|
||||||
brw_imm_d(0)));
|
|
||||||
}
|
|
||||||
/* Load the shadow comparator */
|
|
||||||
if (shadow_comparator.file != BAD_FILE &&
|
|
||||||
opcode != SHADER_OPCODE_TXD &&
|
|
||||||
opcode != SHADER_OPCODE_TG4_OFFSET) {
|
|
||||||
emit(MOV(dst_reg(MRF, param_base + 1, shadow_comparator.type,
|
|
||||||
WRITEMASK_X),
|
|
||||||
shadow_comparator));
|
|
||||||
inst->mlen++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Load the LOD info */
|
|
||||||
switch (opcode) {
|
|
||||||
case SHADER_OPCODE_TXL: {
|
|
||||||
int mrf, writemask;
|
|
||||||
if (devinfo->ver >= 5) {
|
|
||||||
mrf = param_base + 1;
|
|
||||||
if (shadow_comparator.file != BAD_FILE) {
|
|
||||||
writemask = WRITEMASK_Y;
|
|
||||||
/* mlen already incremented */
|
|
||||||
} else {
|
|
||||||
writemask = WRITEMASK_X;
|
|
||||||
inst->mlen++;
|
|
||||||
}
|
|
||||||
} else /* devinfo->ver == 4 */ {
|
|
||||||
mrf = param_base;
|
|
||||||
writemask = WRITEMASK_W;
|
|
||||||
}
|
|
||||||
emit(MOV(dst_reg(MRF, mrf, lod.type, writemask), lod));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case SHADER_OPCODE_TXF:
|
|
||||||
emit(MOV(dst_reg(MRF, param_base, lod.type, WRITEMASK_W), lod));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SHADER_OPCODE_TXF_CMS:
|
|
||||||
emit(MOV(dst_reg(MRF, param_base + 1, sample_index.type, WRITEMASK_X),
|
|
||||||
sample_index));
|
|
||||||
if (devinfo->ver >= 7) {
|
|
||||||
/* MCS data is in the first channel of `mcs`, but we need to get it into
|
|
||||||
* the .y channel of the second vec4 of params, so replicate .x across
|
|
||||||
* the whole vec4 and then mask off everything except .y
|
|
||||||
*/
|
|
||||||
mcs.swizzle = BRW_SWIZZLE_XXXX;
|
|
||||||
emit(MOV(dst_reg(MRF, param_base + 1, glsl_type::uint_type, WRITEMASK_Y),
|
|
||||||
mcs));
|
|
||||||
}
|
|
||||||
inst->mlen++;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SHADER_OPCODE_TXD: {
|
|
||||||
const brw_reg_type type = lod.type;
|
|
||||||
|
|
||||||
if (devinfo->ver >= 5) {
|
|
||||||
lod.swizzle = BRW_SWIZZLE4(SWIZZLE_X,SWIZZLE_X,SWIZZLE_Y,SWIZZLE_Y);
|
|
||||||
lod2.swizzle = BRW_SWIZZLE4(SWIZZLE_X,SWIZZLE_X,SWIZZLE_Y,SWIZZLE_Y);
|
|
||||||
emit(MOV(dst_reg(MRF, param_base + 1, type, WRITEMASK_XZ), lod));
|
|
||||||
emit(MOV(dst_reg(MRF, param_base + 1, type, WRITEMASK_YW), lod2));
|
|
||||||
inst->mlen++;
|
|
||||||
|
|
||||||
if (dest_components == 3 || shadow_comparator.file != BAD_FILE) {
|
|
||||||
lod.swizzle = BRW_SWIZZLE_ZZZZ;
|
|
||||||
lod2.swizzle = BRW_SWIZZLE_ZZZZ;
|
|
||||||
emit(MOV(dst_reg(MRF, param_base + 2, type, WRITEMASK_X), lod));
|
|
||||||
emit(MOV(dst_reg(MRF, param_base + 2, type, WRITEMASK_Y), lod2));
|
|
||||||
inst->mlen++;
|
|
||||||
|
|
||||||
if (shadow_comparator.file != BAD_FILE) {
|
|
||||||
emit(MOV(dst_reg(MRF, param_base + 2,
|
|
||||||
shadow_comparator.type, WRITEMASK_Z),
|
|
||||||
shadow_comparator));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else /* devinfo->ver == 4 */ {
|
|
||||||
emit(MOV(dst_reg(MRF, param_base + 1, type, WRITEMASK_XYZ), lod));
|
|
||||||
emit(MOV(dst_reg(MRF, param_base + 2, type, WRITEMASK_XYZ), lod2));
|
|
||||||
inst->mlen += 2;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case SHADER_OPCODE_TG4_OFFSET:
|
|
||||||
if (shadow_comparator.file != BAD_FILE) {
|
|
||||||
emit(MOV(dst_reg(MRF, param_base, shadow_comparator.type, WRITEMASK_W),
|
|
||||||
shadow_comparator));
|
|
||||||
}
|
|
||||||
|
|
||||||
emit(MOV(dst_reg(MRF, param_base + 1, glsl_type::ivec2_type, WRITEMASK_XY),
|
|
||||||
offset_value));
|
|
||||||
inst->mlen++;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
emit(inst);
|
|
||||||
|
|
||||||
/* fixup num layers (z) for cube arrays: hardware returns faces * layers;
|
|
||||||
* spec requires layers.
|
|
||||||
*/
|
|
||||||
if (op == nir_texop_txs && devinfo->ver < 7) {
|
|
||||||
/* Gfx4-6 return 0 instead of 1 for single layer surfaces. */
|
|
||||||
emit_minmax(BRW_CONDITIONAL_GE, writemask(inst->dst, WRITEMASK_Z),
|
|
||||||
src_reg(inst->dst), brw_imm_d(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (devinfo->ver == 6 && op == nir_texop_tg4) {
|
|
||||||
emit_gfx6_gather_wa(key_tex->gfx6_gather_wa[surface], inst->dst);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (op == nir_texop_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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply workarounds for Gfx6 gather with UINT/SINT
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
vec4_visitor::emit_gfx6_gather_wa(uint8_t wa, dst_reg dst)
|
|
||||||
{
|
|
||||||
if (!wa)
|
|
||||||
return;
|
|
||||||
|
|
||||||
int width = (wa & WA_8BIT) ? 8 : 16;
|
|
||||||
dst_reg dst_f = dst;
|
|
||||||
dst_f.type = BRW_REGISTER_TYPE_F;
|
|
||||||
|
|
||||||
/* Convert from UNORM to UINT */
|
|
||||||
emit(MUL(dst_f, src_reg(dst_f), brw_imm_f((float)((1 << width) - 1))));
|
|
||||||
emit(MOV(dst, src_reg(dst_f)));
|
|
||||||
|
|
||||||
if (wa & WA_SIGN) {
|
|
||||||
/* Reinterpret the UINT value as a signed INT value by
|
|
||||||
* shifting the sign bit into place, then shifting back
|
|
||||||
* preserving sign.
|
|
||||||
*/
|
|
||||||
emit(SHL(dst, src_reg(dst), brw_imm_d(32 - width)));
|
|
||||||
emit(ASR(dst, src_reg(dst), brw_imm_d(32 - width)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
vec4_visitor::gs_emit_vertex(int /* stream_id */)
|
vec4_visitor::gs_emit_vertex(int /* stream_id */)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue