summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/r600/r600_shader.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/r600/r600_shader.c')
-rw-r--r--src/gallium/drivers/r600/r600_shader.c133
1 files changed, 130 insertions, 3 deletions
diff --git a/src/gallium/drivers/r600/r600_shader.c b/src/gallium/drivers/r600/r600_shader.c
index c56efda5347..0b586f3aedb 100644
--- a/src/gallium/drivers/r600/r600_shader.c
+++ b/src/gallium/drivers/r600/r600_shader.c
@@ -1177,13 +1177,14 @@ static int r600_shader_from_tgsi(struct r600_screen *rscreen,
use_llvm = debug_get_bool_option("R600_LLVM", TRUE);
#endif
ctx.bc = &shader->bc;
ctx.shader = shader;
ctx.native_integers = true;
- r600_bytecode_init(ctx.bc, rscreen->chip_class, rscreen->family);
+ r600_bytecode_init(ctx.bc, rscreen->chip_class, rscreen->family,
+ rscreen->msaa_texture_support);
ctx.tokens = tokens;
tgsi_scan_shader(tokens, &ctx.info);
tgsi_parse_init(&ctx.parse, tokens);
ctx.type = ctx.parse.FullHeader.Processor.Processor;
shader->processor_type = ctx.type;
ctx.bc->type = shader->processor_type;
@@ -3793,16 +3794,21 @@ static int tgsi_tex(struct r600_shader_ctx *ctx)
struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
struct r600_bytecode_tex tex;
struct r600_bytecode_alu alu;
unsigned src_gpr;
int r, i, j;
int opcode;
+ bool read_compressed_msaa = ctx->bc->msaa_texture_mode == MSAA_TEXTURE_COMPRESSED &&
+ inst->Instruction.Opcode == TGSI_OPCODE_TXF &&
+ (inst->Texture.Texture == TGSI_TEXTURE_2D_MSAA ||
+ inst->Texture.Texture == TGSI_TEXTURE_2D_ARRAY_MSAA);
/* Texture fetch instructions can only use gprs as source.
* Also they cannot negate the source or take the absolute value */
- const boolean src_requires_loading = inst->Instruction.Opcode != TGSI_OPCODE_TXQ_LZ &&
- tgsi_tex_src_requires_loading(ctx, 0);
+ const boolean src_requires_loading = (inst->Instruction.Opcode != TGSI_OPCODE_TXQ_LZ &&
+ tgsi_tex_src_requires_loading(ctx, 0)) ||
+ read_compressed_msaa;
boolean src_loaded = FALSE;
unsigned sampler_src_reg = inst->Instruction.Opcode == TGSI_OPCODE_TXQ_LZ ? 0 : 1;
uint8_t offset_x = 0, offset_y = 0, offset_z = 0;
src_gpr = tgsi_tex_get_src_gpr(ctx, 0);
@@ -4067,12 +4073,133 @@ static int tgsi_tex(struct r600_shader_ctx *ctx)
return r;
}
src_loaded = TRUE;
src_gpr = ctx->temp_reg;
}
+ /* Obtain the sample index for reading a compressed MSAA color texture.
+ * To read the FMASK, we use the ldfptr instruction, which tells us
+ * where the samples are stored.
+ * For uncompressed 8x MSAA surfaces, ldfptr should return 0x76543210,
+ * which is the identity mapping. Each nibble says which physical sample
+ * should be fetched to get that sample.
+ *
+ * Assume src.z contains the sample index. It should be modified like this:
+ * src.z = (ldfptr() >> (src.z * 4)) & 0xF;
+ * Then fetch the texel with src.
+ */
+ if (read_compressed_msaa) {
+ unsigned sample_chan = inst->Texture.Texture == TGSI_TEXTURE_2D_MSAA ? 3 : 4;
+ unsigned temp = r600_get_temp(ctx);
+ assert(src_loaded);
+
+ /* temp.w = ldfptr() */
+ memset(&tex, 0, sizeof(struct r600_bytecode_tex));
+ tex.inst = SQ_TEX_INST_LD;
+ tex.inst_mod = 1; /* to indicate this is ldfptr */
+ tex.sampler_id = tgsi_tex_get_src_gpr(ctx, sampler_src_reg);
+ tex.resource_id = tex.sampler_id + R600_MAX_CONST_BUFFERS;
+ tex.src_gpr = src_gpr;
+ tex.dst_gpr = temp;
+ tex.dst_sel_x = 7; /* mask out these components */
+ tex.dst_sel_y = 7;
+ tex.dst_sel_z = 7;
+ tex.dst_sel_w = 0; /* store X */
+ tex.src_sel_x = 0;
+ tex.src_sel_y = 1;
+ tex.src_sel_z = 2;
+ tex.src_sel_w = 3;
+ tex.offset_x = offset_x;
+ tex.offset_y = offset_y;
+ tex.offset_z = offset_z;
+ r = r600_bytecode_add_tex(ctx->bc, &tex);
+ if (r)
+ return r;
+
+ /* temp.x = sample_index*4 */
+ if (ctx->bc->chip_class == CAYMAN) {
+ for (i = 0 ; i < 4; i++) {
+ memset(&alu, 0, sizeof(struct r600_bytecode_alu));
+ alu.inst = ctx->inst_info->r600_opcode;
+ alu.src[0].sel = src_gpr;
+ alu.src[0].chan = sample_chan;
+ alu.src[1].sel = V_SQ_ALU_SRC_LITERAL;
+ alu.src[1].value = 4;
+ alu.dst.sel = temp;
+ alu.dst.chan = i;
+ alu.dst.write = i == 0;
+ if (i == 3)
+ alu.last = 1;
+ r = r600_bytecode_add_alu(ctx->bc, &alu);
+ if (r)
+ return r;
+ }
+ } else {
+ memset(&alu, 0, sizeof(struct r600_bytecode_alu));
+ alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MULLO_INT);
+ alu.src[0].sel = src_gpr;
+ alu.src[0].chan = sample_chan;
+ alu.src[1].sel = V_SQ_ALU_SRC_LITERAL;
+ alu.src[1].value = 4;
+ alu.dst.sel = temp;
+ alu.dst.chan = 0;
+ alu.dst.write = 1;
+ alu.last = 1;
+ r = r600_bytecode_add_alu(ctx->bc, &alu);
+ if (r)
+ return r;
+ }
+
+ /* sample_index = temp.w >> temp.x */
+ memset(&alu, 0, sizeof(struct r600_bytecode_alu));
+ alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_LSHR_INT);
+ alu.src[0].sel = temp;
+ alu.src[0].chan = 3;
+ alu.src[1].sel = temp;
+ alu.src[1].chan = 0;
+ alu.dst.sel = src_gpr;
+ alu.dst.chan = sample_chan;
+ alu.dst.write = 1;
+ alu.last = 1;
+ r = r600_bytecode_add_alu(ctx->bc, &alu);
+ if (r)
+ return r;
+
+ /* sample_index & 0xF */
+ memset(&alu, 0, sizeof(struct r600_bytecode_alu));
+ alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_AND_INT);
+ alu.src[0].sel = src_gpr;
+ alu.src[0].chan = sample_chan;
+ alu.src[1].sel = V_SQ_ALU_SRC_LITERAL;
+ alu.src[1].value = 0xF;
+ alu.dst.sel = src_gpr;
+ alu.dst.chan = sample_chan;
+ alu.dst.write = 1;
+ alu.last = 1;
+ r = r600_bytecode_add_alu(ctx->bc, &alu);
+ if (r)
+ return r;
+#if 0
+ /* visualize the FMASK */
+ for (i = 0; i < 4; i++) {
+ memset(&alu, 0, sizeof(struct r600_bytecode_alu));
+ alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_INT_TO_FLT);
+ alu.src[0].sel = src_gpr;
+ alu.src[0].chan = sample_chan;
+ alu.dst.sel = ctx->file_offset[inst->Dst[0].Register.File] + inst->Dst[0].Register.Index;
+ alu.dst.chan = i;
+ alu.dst.write = 1;
+ alu.last = 1;
+ r = r600_bytecode_add_alu(ctx->bc, &alu);
+ if (r)
+ return r;
+ }
+ return 0;
+#endif
+ }
+
opcode = ctx->inst_info->r600_opcode;
if (inst->Texture.Texture == TGSI_TEXTURE_SHADOW1D ||
inst->Texture.Texture == TGSI_TEXTURE_SHADOW2D ||
inst->Texture.Texture == TGSI_TEXTURE_SHADOWRECT ||
inst->Texture.Texture == TGSI_TEXTURE_SHADOWCUBE ||
inst->Texture.Texture == TGSI_TEXTURE_SHADOW1D_ARRAY ||