[Mesa-dev] [PATCH 09/11] r600: handle image size support.

Dave Airlie airlied at gmail.com
Wed Nov 15 00:11:10 UTC 2017


From: Dave Airlie <airlied at redhat.com>

This adds support for the RESQ opcode with the workaround
required due to hw bugs for buffers and cube arrays.

Signed-off-by: Dave Airlie <airlied at redhat.com>
---
 src/gallium/drivers/r600/r600_shader.c       | 78 ++++++++++++++++++++++++++--
 src/gallium/drivers/r600/r600_shader.h       |  2 +
 src/gallium/drivers/r600/r600_state_common.c | 30 +++++++++--
 3 files changed, 101 insertions(+), 9 deletions(-)

diff --git a/src/gallium/drivers/r600/r600_shader.c b/src/gallium/drivers/r600/r600_shader.c
index 17b0099..37a8cea 100644
--- a/src/gallium/drivers/r600/r600_shader.c
+++ b/src/gallium/drivers/r600/r600_shader.c
@@ -3077,6 +3077,7 @@ static int r600_shader_from_tgsi(struct r600_context *rctx,
 		shader->two_side = key.ps.color_two_side;
 		shader->atomic_base = key.ps.first_atomic_counter;
 		shader->rat_base = key.ps.nr_cbufs;
+		shader->image_size_const_offset = key.ps.image_size_const_offset;
 		break;
 	default:
 		break;
@@ -6809,12 +6810,12 @@ static int do_vtx_fetch_inst(struct r600_shader_ctx *ctx, boolean src_requires_l
 	return 0;
 }
 
-static int r600_do_buffer_txq(struct r600_shader_ctx *ctx)
+static int r600_do_buffer_txq(struct r600_shader_ctx *ctx, int reg_idx, int offset)
 {
 	struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
 	struct r600_bytecode_alu alu;
 	int r;
-	int id = tgsi_tex_get_src_gpr(ctx, 1);
+	int id = tgsi_tex_get_src_gpr(ctx, reg_idx) + offset;
 
 	memset(&alu, 0, sizeof(struct r600_bytecode_alu));
 	alu.op = ALU_OP1_MOV;
@@ -6891,7 +6892,7 @@ static int tgsi_tex(struct r600_shader_ctx *ctx)
 	if (inst->Texture.Texture == TGSI_TEXTURE_BUFFER) {
 		if (inst->Instruction.Opcode == TGSI_OPCODE_TXQ) {
 			ctx->shader->uses_tex_buffers = true;
-			return r600_do_buffer_txq(ctx);
+			return r600_do_buffer_txq(ctx, 1, 0);
 		}
 		else if (inst->Instruction.Opcode == TGSI_OPCODE_TXF) {
 			if (ctx->bc->chip_class < EVERGREEN)
@@ -8199,6 +8200,73 @@ static int tgsi_atomic_op(struct r600_shader_ctx *ctx)
 	return 0;
 }
 
+static int tgsi_resq(struct r600_shader_ctx *ctx)
+{
+	struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
+	unsigned sampler_index_mode;
+	struct r600_bytecode_tex tex;
+	int r;
+	boolean has_txq_cube_array_z = false;
+
+	if (inst->Memory.Texture == TGSI_TEXTURE_BUFFER) {
+		ctx->shader->uses_tex_buffers = true;
+		return r600_do_buffer_txq(ctx, 0, ctx->shader->image_size_const_offset);
+	}
+
+	if (inst->Memory.Texture == TGSI_TEXTURE_CUBE_ARRAY &&
+	    inst->Dst[0].Register.WriteMask & 4) {
+		ctx->shader->has_txq_cube_array_z_comp = true;
+		has_txq_cube_array_z = true;
+	}
+
+	sampler_index_mode = inst->Src[0].Indirect.Index == 2 ? 2 : 0; // CF_INDEX_1 : CF_INDEX_NONE
+	if (sampler_index_mode)
+		egcm_load_index_reg(ctx->bc, 1, false);
+
+
+	/* does this shader want a num layers from TXQ for a cube array? */
+	if (has_txq_cube_array_z) {
+		int id = tgsi_tex_get_src_gpr(ctx, 0) + ctx->shader->image_size_const_offset;
+		struct r600_bytecode_alu alu;
+
+		memset(&alu, 0, sizeof(struct r600_bytecode_alu));
+		alu.op = ALU_OP1_MOV;
+
+		alu.src[0].sel = R600_SHADER_BUFFER_INFO_SEL;
+		/* channel 1 or 3 of each word */
+		alu.src[0].sel += (id / 2);
+		alu.src[0].chan = ((id % 2) * 2) + 1;
+		alu.src[0].kc_bank = R600_BUFFER_INFO_CONST_BUFFER;
+		tgsi_dst(ctx, &inst->Dst[0], 2, &alu.dst);
+		alu.last = 1;
+		r = r600_bytecode_add_alu(ctx->bc, &alu);
+		if (r)
+			return r;
+		/* disable writemask from texture instruction */
+		inst->Dst[0].Register.WriteMask &= ~4;
+	}
+	memset(&tex, 0, sizeof(struct r600_bytecode_tex));
+	tex.op = ctx->inst_info->op;
+	tex.sampler_id = R600_IMAGE_REAL_RESOURCE_OFFSET + inst->Src[0].Register.Index;
+	tex.sampler_index_mode = sampler_index_mode;
+	tex.resource_id = tex.sampler_id;
+	tex.resource_index_mode = sampler_index_mode;
+	tex.src_sel_x = 4;
+	tex.src_sel_y = 4;
+	tex.src_sel_z = 4;
+	tex.src_sel_w = 4;
+	tex.dst_sel_x = (inst->Dst[0].Register.WriteMask & 1) ? 0 : 7;
+	tex.dst_sel_y = (inst->Dst[0].Register.WriteMask & 2) ? 1 : 7;
+	tex.dst_sel_z = (inst->Dst[0].Register.WriteMask & 4) ? 2 : 7;
+	tex.dst_sel_w = (inst->Dst[0].Register.WriteMask & 8) ? 3 : 7;
+	tex.dst_gpr = ctx->file_offset[inst->Dst[0].Register.File] + inst->Dst[0].Register.Index;
+	r = r600_bytecode_add_tex(ctx->bc, &tex);
+	if (r)
+		return r;
+
+	return 0;
+}
+
 static int tgsi_lrp(struct r600_shader_ctx *ctx)
 {
 	struct tgsi_full_instruction *inst = &ctx->parse.FullToken.FullInstruction;
@@ -9849,7 +9917,7 @@ static const struct r600_shader_tgsi_instruction eg_shader_tgsi_instruction[] =
 	[TGSI_OPCODE_ENDSUB]	= { ALU_OP0_NOP, tgsi_unsupported},
 	[103]			= { FETCH_OP_GET_TEXTURE_RESINFO, tgsi_tex},
 	[TGSI_OPCODE_TXQS]	= { FETCH_OP_GET_NUMBER_OF_SAMPLES, tgsi_tex},
-	[TGSI_OPCODE_RESQ]	= { ALU_OP0_NOP, tgsi_unsupported},
+	[TGSI_OPCODE_RESQ]     	= { FETCH_OP_GET_TEXTURE_RESINFO, tgsi_resq},
 	[106]			= { ALU_OP0_NOP, tgsi_unsupported},
 	[TGSI_OPCODE_NOP]	= { ALU_OP0_NOP, tgsi_unsupported},
 	[TGSI_OPCODE_FSEQ]	= { ALU_OP2_SETE_DX10, tgsi_op2},
@@ -10072,7 +10140,7 @@ static const struct r600_shader_tgsi_instruction cm_shader_tgsi_instruction[] =
 	[TGSI_OPCODE_ENDSUB]	= { ALU_OP0_NOP, tgsi_unsupported},
 	[103]			= { FETCH_OP_GET_TEXTURE_RESINFO, tgsi_tex},
 	[TGSI_OPCODE_TXQS]	= { FETCH_OP_GET_NUMBER_OF_SAMPLES, tgsi_tex},
-	[TGSI_OPCODE_RESQ]	= { ALU_OP0_NOP, tgsi_unsupported},
+	[TGSI_OPCODE_RESQ]     	= { FETCH_OP_GET_TEXTURE_RESINFO, tgsi_resq},
 	[106]			= { ALU_OP0_NOP, tgsi_unsupported},
 	[TGSI_OPCODE_NOP]	= { ALU_OP0_NOP, tgsi_unsupported},
 	[TGSI_OPCODE_FSEQ]	= { ALU_OP2_SETE_DX10, tgsi_op2},
diff --git a/src/gallium/drivers/r600/r600_shader.h b/src/gallium/drivers/r600/r600_shader.h
index ccbcd67..5d6501c 100644
--- a/src/gallium/drivers/r600/r600_shader.h
+++ b/src/gallium/drivers/r600/r600_shader.h
@@ -119,12 +119,14 @@ struct r600_shader {
 	boolean			uses_images;
 	uint8_t                 atomic_base;
 	uint8_t			rat_base;
+	uint8_t                 image_size_const_offset;
 };
 
 union r600_shader_key {
 	struct {
 		unsigned	nr_cbufs:4;
 		unsigned        first_atomic_counter:4;
+		unsigned        image_size_const_offset:5;
 		unsigned	color_two_side:1;
 		unsigned	alpha_to_one:1;
 	} ps;
diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c
index 1bd0a76..b8d4b8f 100644
--- a/src/gallium/drivers/r600/r600_state_common.c
+++ b/src/gallium/drivers/r600/r600_state_common.c
@@ -799,6 +799,8 @@ static inline void r600_shader_selector_key(const struct pipe_context *ctx,
 		key->gs.tri_strip_adj_fix = rctx->gs_tri_strip_adj_fix;
 		break;
 	case PIPE_SHADER_FRAGMENT: {
+		if (rctx->ps_shader->info.images_declared)
+			key->ps.image_size_const_offset = util_last_bit(rctx->samplers[PIPE_SHADER_FRAGMENT].views.enabled_mask);
 		key->ps.first_atomic_counter = r600_get_hw_atomic_count(ctx, PIPE_SHADER_FRAGMENT);
 		key->ps.color_two_side = rctx->rasterizer && rctx->rasterizer->two_side;
 		key->ps.alpha_to_one = rctx->alpha_to_one &&
@@ -1330,29 +1332,49 @@ static void r600_setup_buffer_constants(struct r600_context *rctx, int shader_ty
 static void eg_setup_buffer_constants(struct r600_context *rctx, int shader_type)
 {
 	struct r600_textures_info *samplers = &rctx->samplers[shader_type];
-	int bits;
+	struct r600_image_state *images = NULL;
+	int bits, sview_bits;
 	uint32_t array_size;
 	int i;
 	uint32_t *constants;
 	uint32_t base_offset;
-	if (!samplers->views.dirty_buffer_constants)
+
+	if (shader_type == PIPE_SHADER_FRAGMENT)
+		images = &rctx->fragment_images;
+
+	if (!samplers->views.dirty_buffer_constants &&
+	    (images && !images->dirty_buffer_constants))
 		return;
 
+	if (images)
+		images->dirty_buffer_constants = FALSE;
 	samplers->views.dirty_buffer_constants = FALSE;
 
-	bits = util_last_bit(samplers->views.enabled_mask);
+	bits = sview_bits = util_last_bit(samplers->views.enabled_mask);
+	if (images)
+		bits += util_last_bit(images->enabled_mask);
 	array_size = bits * 2 * sizeof(uint32_t) * 4;
 
 	constants = r600_alloc_buf_consts(rctx, shader_type, array_size,
 					  &base_offset);
 
-	for (i = 0; i < bits; i++) {
+	for (i = 0; i < sview_bits; i++) {
 		if (samplers->views.enabled_mask & (1 << i)) {
 			uint32_t offset = (base_offset / 4) + i * 2;
 			constants[offset] = samplers->views.views[i]->base.texture->width0 / util_format_get_blocksize(samplers->views.views[i]->base.format);
 			constants[offset + 1] = samplers->views.views[i]->base.texture->array_size / 6;
 		}
 	}
+	if (images) {
+		for (i = sview_bits; i < bits; i++) {
+			int idx = i - sview_bits;
+			if (images->enabled_mask & (1 << idx)) {
+				uint32_t offset = (base_offset / 4) + i * 2;
+				constants[offset] = images->views[i].base.resource->width0 / util_format_get_blocksize(images->views[i].base.format);
+				constants[offset + 1] = images->views[i].base.resource->array_size / 6;
+			}
+		}
+	}
 }
 
 /* set sample xy locations as array of fragment shader constants */
-- 
2.9.5



More information about the mesa-dev mailing list