Mesa (master): r600g: add support for constants in memory buffers.

Dave Airlie airlied at kemper.freedesktop.org
Tue Sep 7 22:51:20 UTC 2010


Module: Mesa
Branch: master
Commit: d42efb9e8df6ef872ab4f142e3daf1b6cb9eff11
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=d42efb9e8df6ef872ab4f142e3daf1b6cb9eff11

Author: Dave Airlie <airlied at redhat.com>
Date:   Wed Sep  8 08:41:57 2010 +1000

r600g: add support for constants in memory buffers.

DX9 constants were in the constant file, and evergreen no longer support
cfile. r600/700 can also use constants in memory buffers, so add the code
(disabled for now) to enable that as precursor for evergreen.

---

 src/gallium/drivers/r600/r600_asm.c        |    8 ++-
 src/gallium/drivers/r600/r600_asm.h        |    2 +
 src/gallium/drivers/r600/r600_buffer.c     |    5 +-
 src/gallium/drivers/r600/r600_context.h    |    6 ++
 src/gallium/drivers/r600/r600_hw_states.c  |   96 +++++++++++++++++++++++++++-
 src/gallium/drivers/r600/r600_screen.c     |    3 +
 src/gallium/drivers/r600/r600_screen.h     |    1 +
 src/gallium/drivers/r600/r600_shader.c     |    8 ++-
 src/gallium/drivers/r600/r600_shader.h     |    1 +
 src/gallium/drivers/r600/r600_state.c      |   51 +--------------
 src/gallium/drivers/r600/r600_states_inc.h |   12 ++++
 src/gallium/drivers/r600/radeon.h          |    1 +
 src/gallium/winsys/r600/drm/r600_state.c   |    1 +
 src/gallium/winsys/r600/drm/r600_states.h  |   10 +++
 14 files changed, 154 insertions(+), 51 deletions(-)

diff --git a/src/gallium/drivers/r600/r600_asm.c b/src/gallium/drivers/r600/r600_asm.c
index bf3d31c..b62354f 100644
--- a/src/gallium/drivers/r600/r600_asm.c
+++ b/src/gallium/drivers/r600/r600_asm.c
@@ -180,6 +180,10 @@ int r600_bc_add_alu_type(struct r600_bc *bc, const struct r600_bc_alu *alu, int
 	/* each alu use 2 dwords */
 	bc->cf_last->ndw += 2;
 	bc->ndw += 2;
+
+	if (bc->use_mem_constant)
+		bc->cf_last->kcache0_mode = 2;
+
 	return 0;
 }
 
@@ -392,7 +396,9 @@ static int r600_bc_cf_build(struct r600_bc *bc, struct r600_bc_cf *cf)
 	switch (cf->inst) {
 	case (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU << 3):
 	case (V_SQ_CF_ALU_WORD1_SQ_CF_INST_ALU_PUSH_BEFORE << 3):
-		bc->bytecode[id++] = S_SQ_CF_ALU_WORD0_ADDR(cf->addr >> 1);
+		bc->bytecode[id++] = S_SQ_CF_ALU_WORD0_ADDR(cf->addr >> 1) |
+			S_SQ_CF_ALU_WORD0_KCACHE_MODE0(cf->kcache0_mode);
+
 		bc->bytecode[id++] = S_SQ_CF_ALU_WORD1_CF_INST(cf->inst >> 3) |
 					S_SQ_CF_ALU_WORD1_BARRIER(1) |
 					S_SQ_CF_ALU_WORD1_COUNT((cf->ndw / 2) - 1);
diff --git a/src/gallium/drivers/r600/r600_asm.h b/src/gallium/drivers/r600/r600_asm.h
index 9e65fcd..0d75d99 100644
--- a/src/gallium/drivers/r600/r600_asm.h
+++ b/src/gallium/drivers/r600/r600_asm.h
@@ -120,6 +120,7 @@ struct r600_bc_cf {
 	unsigned                        cond;
 	unsigned                        pop_count;
 	unsigned                        cf_addr; /* control flow addr */
+	unsigned                        kcache0_mode;
 	struct list_head		alu;
 	struct list_head		tex;
 	struct list_head		vtx;
@@ -151,6 +152,7 @@ struct r600_cf_callstack {
 struct r600_bc {
 	enum radeon_family		family;
 	int chiprev; /* 0 - r600, 1 - r700, 2 - evergreen */
+	unsigned                        use_mem_constant; 
 	struct list_head		cf;
 	struct r600_bc_cf		*cf_last;
 	unsigned			ndw;
diff --git a/src/gallium/drivers/r600/r600_buffer.c b/src/gallium/drivers/r600/r600_buffer.c
index 7829a47..d8188ae 100644
--- a/src/gallium/drivers/r600/r600_buffer.c
+++ b/src/gallium/drivers/r600/r600_buffer.c
@@ -56,6 +56,9 @@ u32 r600_domain_from_usage(unsigned usage)
 	if (usage & PIPE_BIND_INDEX_BUFFER) {
 	    domain |= RADEON_GEM_DOMAIN_GTT;
 	}
+	if (usage & PIPE_BIND_CONSTANT_BUFFER) {
+	    domain |= RADEON_GEM_DOMAIN_VRAM;
+	}
 
 	return domain;
 }
@@ -79,7 +82,7 @@ struct pipe_resource *r600_buffer_create(struct pipe_screen *screen,
 	rbuffer->base.b.screen = screen;
 	rbuffer->base.vtbl = &r600_buffer_vtbl;
 
-	if (rbuffer->base.b.bind & PIPE_BIND_CONSTANT_BUFFER) {
+	if ((rscreen->use_mem_constant == FALSE) && (rbuffer->base.b.bind & PIPE_BIND_CONSTANT_BUFFER)) {
 		desc.alignment = alignment;
 		desc.usage = rbuffer->base.b.bind;
 		rbuffer->pb = pb_malloc_buffer_create(rbuffer->base.b.width0,
diff --git a/src/gallium/drivers/r600/r600_context.h b/src/gallium/drivers/r600/r600_context.h
index 239c1a3..eb37069 100644
--- a/src/gallium/drivers/r600/r600_context.h
+++ b/src/gallium/drivers/r600/r600_context.h
@@ -260,5 +260,11 @@ uint32_t r600_translate_texformat(enum pipe_format format,
 extern void r600_queries_resume(struct pipe_context *ctx);
 extern void r600_queries_suspend(struct pipe_context *ctx);
 
+void r600_set_constant_buffer_file(struct pipe_context *ctx,
+				   uint shader, uint index,
+				   struct pipe_resource *buffer);
+void r600_set_constant_buffer_mem(struct pipe_context *ctx,
+				  uint shader, uint index,
+				  struct pipe_resource *buffer);
 
 #endif
diff --git a/src/gallium/drivers/r600/r600_hw_states.c b/src/gallium/drivers/r600/r600_hw_states.c
index 948ae61..5572336 100644
--- a/src/gallium/drivers/r600/r600_hw_states.c
+++ b/src/gallium/drivers/r600/r600_hw_states.c
@@ -789,7 +789,8 @@ static void r600_init_config(struct r600_context *rctx)
 		break;
 	}
 
-	rctx->config.states[R600_CONFIG__SQ_CONFIG] |= S_008C00_DX9_CONSTS(1);
+	if (!rctx->screen->use_mem_constant)
+		rctx->config.states[R600_CONFIG__SQ_CONFIG] |= S_008C00_DX9_CONSTS(1);
 
 	rctx->config.states[R600_CONFIG__SQ_CONFIG] |= S_008C00_ALU_INST_PREFER_VECTOR(1);
 	rctx->config.states[R600_CONFIG__SQ_CONFIG] |= S_008C00_PS_PRIO(ps_prio);
@@ -1033,3 +1034,96 @@ struct r600_context_hw_state_vtbl r600_hw_state_vtbl = {
 	.ps_shader = r600_ps_shader,
 	.init_config = r600_init_config,
 };
+
+void r600_set_constant_buffer_file(struct pipe_context *ctx,
+				   uint shader, uint index,
+				   struct pipe_resource *buffer)
+{
+	struct r600_screen *rscreen = r600_screen(ctx->screen);
+	struct r600_context *rctx = r600_context(ctx);
+	unsigned nconstant = 0, i, type, shader_class;
+	struct radeon_state *rstate, *rstates;
+	struct pipe_transfer *transfer;
+	u32 *ptr;
+
+	type = R600_STATE_CONSTANT;
+
+	switch (shader) {
+	case PIPE_SHADER_VERTEX:
+		shader_class = R600_SHADER_VS;
+		rstates = rctx->vs_constant;
+		break;
+	case PIPE_SHADER_FRAGMENT:
+		shader_class = R600_SHADER_PS;
+		rstates = rctx->ps_constant;
+		break;
+	default:
+		R600_ERR("unsupported %d\n", shader);
+		return;
+	}
+	if (buffer && buffer->width0 > 0) {
+		nconstant = buffer->width0 / 16;
+		ptr = pipe_buffer_map(ctx, buffer, PIPE_TRANSFER_READ, &transfer);
+		if (ptr == NULL)
+			return;
+		for (i = 0; i < nconstant; i++) {
+			rstate = &rstates[i];
+			radeon_state_init(rstate, rscreen->rw, type, i, shader_class);
+			rstate->states[R600_PS_CONSTANT__SQ_ALU_CONSTANT0_0] = ptr[i * 4 + 0];
+			rstate->states[R600_PS_CONSTANT__SQ_ALU_CONSTANT1_0] = ptr[i * 4 + 1];
+			rstate->states[R600_PS_CONSTANT__SQ_ALU_CONSTANT2_0] = ptr[i * 4 + 2];
+			rstate->states[R600_PS_CONSTANT__SQ_ALU_CONSTANT3_0] = ptr[i * 4 + 3];
+			if (radeon_state_pm4(rstate))
+				return;
+			radeon_draw_bind(&rctx->draw, rstate);
+		}
+		pipe_buffer_unmap(ctx, buffer, transfer);
+	}
+}
+
+void r600_set_constant_buffer_mem(struct pipe_context *ctx,
+				  uint shader, uint index,
+				  struct pipe_resource *buffer)
+{
+	struct r600_screen *rscreen = r600_screen(ctx->screen);
+	struct r600_context *rctx = r600_context(ctx);
+	unsigned nconstant = 0, i, type, shader_class, size;
+	struct radeon_state *rstate, *rstates;
+	struct r600_resource *rbuffer = (struct r600_resource*)buffer;
+	u32 *ptr;
+
+	type = R600_STATE_CBUF;
+
+	switch (shader) {
+	case PIPE_SHADER_VERTEX:
+		shader_class = R600_SHADER_VS;
+		rstates = rctx->vs_constant;
+		break;
+	case PIPE_SHADER_FRAGMENT:
+		shader_class = R600_SHADER_PS;
+		rstates = rctx->ps_constant;
+		break;
+	default:
+		R600_ERR("unsupported %d\n", shader);
+		return;
+	}
+
+	rstate = &rstates[0];
+
+#define ALIGN_DIVUP(x, y) (((x) + (y) - 1) / (y))
+
+	nconstant = buffer->width0 / 16;
+	size = ALIGN_DIVUP(nconstant, 16);
+		
+	radeon_state_init(rstate, rscreen->rw, type, 0, shader_class);
+	rstate->states[R600_VS_CBUF__ALU_CONST_BUFFER_SIZE_VS_0] = size;
+	rstate->states[R600_VS_CBUF__ALU_CONST_CACHE_VS_0] = 0;
+
+	rstate->bo[0] = radeon_bo_incref(rscreen->rw, rbuffer->bo);
+	rstate->nbo = 1;
+	rstate->placement[0] = RADEON_GEM_DOMAIN_VRAM;
+	if (radeon_state_pm4(rstate))
+		return;
+	radeon_draw_bind(&rctx->draw, rstate);
+}
+
diff --git a/src/gallium/drivers/r600/r600_screen.c b/src/gallium/drivers/r600/r600_screen.c
index a047a49..54a61dd 100644
--- a/src/gallium/drivers/r600/r600_screen.c
+++ b/src/gallium/drivers/r600/r600_screen.c
@@ -240,6 +240,9 @@ struct pipe_screen *r600_screen_create(struct radeon *rw)
 	if (rscreen == NULL) {
 		return NULL;
 	}
+	
+	/* don't enable mem constant for r600 yet */
+	rscreen->use_mem_constant = FALSE;
 
 	switch (family) {
 	case CHIP_R600:
diff --git a/src/gallium/drivers/r600/r600_screen.h b/src/gallium/drivers/r600/r600_screen.h
index b9938f1..4be7786 100644
--- a/src/gallium/drivers/r600/r600_screen.h
+++ b/src/gallium/drivers/r600/r600_screen.h
@@ -52,6 +52,7 @@ struct r600_screen {
 	struct pipe_screen		screen;
 	struct radeon			*rw;
 	enum chip_class			chip_class;
+	boolean use_mem_constant;
 };
 
 static INLINE struct r600_screen *r600_screen(struct pipe_screen *screen)
diff --git a/src/gallium/drivers/r600/r600_shader.c b/src/gallium/drivers/r600/r600_shader.c
index 1273cd6..b643157 100644
--- a/src/gallium/drivers/r600/r600_shader.c
+++ b/src/gallium/drivers/r600/r600_shader.c
@@ -113,6 +113,7 @@ int r600_pipe_shader_create(struct pipe_context *ctx,
 	if (rpshader == NULL)
 		return -ENOMEM;
 	rpshader->shader.family = radeon_get_family(rscreen->rw);
+	rpshader->shader.use_mem_constant = rscreen->use_mem_constant;
 	r = r600_shader_from_tgsi(tokens, &rpshader->shader);
 	if (r) {
 		R600_ERR("translation from TGSI failed !\n");
@@ -311,6 +312,7 @@ int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *s
 	r = r600_bc_init(ctx.bc, shader->family);
 	if (r)
 		return r;
+	ctx.bc->use_mem_constant = shader->use_mem_constant;
 	ctx.tokens = tokens;
 	tgsi_scan_shader(tokens, &ctx.info);
 	tgsi_parse_init(&ctx.parse, tokens);
@@ -346,7 +348,11 @@ int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *s
 						ctx.info.file_count[TGSI_FILE_INPUT];
 	ctx.file_offset[TGSI_FILE_TEMPORARY] = ctx.file_offset[TGSI_FILE_OUTPUT] +
 						ctx.info.file_count[TGSI_FILE_OUTPUT];
-	ctx.file_offset[TGSI_FILE_CONSTANT] = 256;
+	if (ctx.shader->use_mem_constant)
+		ctx.file_offset[TGSI_FILE_CONSTANT] = 128;
+	else
+		ctx.file_offset[TGSI_FILE_CONSTANT] = 256;
+
 	ctx.file_offset[TGSI_FILE_IMMEDIATE] = 253;
 	ctx.temp_reg = ctx.file_offset[TGSI_FILE_TEMPORARY] +
 			ctx.info.file_count[TGSI_FILE_TEMPORARY];
diff --git a/src/gallium/drivers/r600/r600_shader.h b/src/gallium/drivers/r600/r600_shader.h
index 7c722c0..fba4a2b 100644
--- a/src/gallium/drivers/r600/r600_shader.h
+++ b/src/gallium/drivers/r600/r600_shader.h
@@ -43,6 +43,7 @@ struct r600_shader {
 	struct r600_shader_io	output[32];
 	enum radeon_family	family;
 	boolean                 uses_kill;
+	boolean                 use_mem_constant;
 };
 
 #endif
diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c
index 780a867..93b0cf1 100644
--- a/src/gallium/drivers/r600/r600_state.c
+++ b/src/gallium/drivers/r600/r600_state.c
@@ -374,52 +374,6 @@ static void r600_set_clip_state(struct pipe_context *ctx,
 	rctx->clip = rstate;
 }
 
-static void r600_set_constant_buffer(struct pipe_context *ctx,
-					uint shader, uint index,
-					struct pipe_resource *buffer)
-{
-	struct r600_screen *rscreen = r600_screen(ctx->screen);
-	struct r600_context *rctx = r600_context(ctx);
-	unsigned nconstant = 0, i, type, shader_class;
-	struct radeon_state *rstate, *rstates;
-	struct pipe_transfer *transfer;
-	u32 *ptr;
-
-	type = R600_STATE_CONSTANT;
-
-	switch (shader) {
-	case PIPE_SHADER_VERTEX:
-		shader_class = R600_SHADER_VS;
-		rstates = rctx->vs_constant;
-		break;
-	case PIPE_SHADER_FRAGMENT:
-		shader_class = R600_SHADER_PS;
-		rstates = rctx->ps_constant;
-		break;
-	default:
-		R600_ERR("unsupported %d\n", shader);
-		return;
-	}
-	if (buffer && buffer->width0 > 0) {
-		nconstant = buffer->width0 / 16;
-		ptr = pipe_buffer_map(ctx, buffer, PIPE_TRANSFER_READ, &transfer);
-		if (ptr == NULL)
-			return;
-		for (i = 0; i < nconstant; i++) {
-			rstate = &rstates[i];
-			radeon_state_init(rstate, rscreen->rw, type, i, shader_class);
-			rstate->states[R600_PS_CONSTANT__SQ_ALU_CONSTANT0_0] = ptr[i * 4 + 0];
-			rstate->states[R600_PS_CONSTANT__SQ_ALU_CONSTANT1_0] = ptr[i * 4 + 1];
-			rstate->states[R600_PS_CONSTANT__SQ_ALU_CONSTANT2_0] = ptr[i * 4 + 2];
-			rstate->states[R600_PS_CONSTANT__SQ_ALU_CONSTANT3_0] = ptr[i * 4 + 3];
-			if (radeon_state_pm4(rstate))
-				return;
-			radeon_draw_bind(&rctx->draw, rstate);
-		}
-		pipe_buffer_unmap(ctx, buffer, transfer);
-	}
-}
-
 static void r600_set_framebuffer_state(struct pipe_context *ctx,
 					const struct pipe_framebuffer_state *state)
 {
@@ -555,7 +509,10 @@ void r600_init_state_functions(struct r600_context *rctx)
 	rctx->context.delete_vs_state = r600_delete_state;
 	rctx->context.set_blend_color = r600_set_blend_color;
 	rctx->context.set_clip_state = r600_set_clip_state;
-	rctx->context.set_constant_buffer = r600_set_constant_buffer;
+	if (rctx->screen->use_mem_constant)
+		rctx->context.set_constant_buffer = r600_set_constant_buffer_mem;
+	else
+		rctx->context.set_constant_buffer = r600_set_constant_buffer_file;
 	rctx->context.set_fragment_sampler_views = r600_set_ps_sampler_view;
 	rctx->context.set_framebuffer_state = r600_set_framebuffer_state;
 	rctx->context.set_polygon_stipple = r600_set_polygon_stipple;
diff --git a/src/gallium/drivers/r600/r600_states_inc.h b/src/gallium/drivers/r600/r600_states_inc.h
index 5367af5..0f8a2d7 100644
--- a/src/gallium/drivers/r600/r600_states_inc.h
+++ b/src/gallium/drivers/r600/r600_states_inc.h
@@ -262,6 +262,18 @@
 #define R600_PS_SHADER_SIZE		39
 #define R600_PS_SHADER_PM4 128		
 
+/* R600_VS_CBUF */
+#define R600_VS_CBUF__ALU_CONST_BUFFER_SIZE_VS_0		0
+#define R600_VS_CBUF__ALU_CONST_CACHE_VS_0		1
+#define R600_VS_CBUF_SIZE		2
+#define R600_VS_CBUF_PM4 128		
+
+/* R600_PS_CBUF */
+#define R600_PS_CBUF__ALU_CONST_BUFFER_SIZE_PS_0		0
+#define R600_PS_CBUF__ALU_CONST_CACHE_PS_0		1
+#define R600_PS_CBUF_SIZE		2
+#define R600_PS_CBUF_PM4 128		
+
 /* R600_PS_CONSTANT */
 #define R600_PS_CONSTANT__SQ_ALU_CONSTANT0_0		0
 #define R600_PS_CONSTANT__SQ_ALU_CONSTANT1_0		1
diff --git a/src/gallium/drivers/r600/radeon.h b/src/gallium/drivers/r600/radeon.h
index cf26ecf..0a8cb73 100644
--- a/src/gallium/drivers/r600/radeon.h
+++ b/src/gallium/drivers/r600/radeon.h
@@ -194,6 +194,7 @@ enum r600_stype {
 	R600_STATE_DSA,
 	R600_STATE_SHADER,          /* has PS,VS,GS,FS variants */
 	R600_STATE_CONSTANT,        /* has PS,VS,GS,FS variants */
+	R600_STATE_CBUF,        /* has PS,VS,GS,FS variants */
 	R600_STATE_RESOURCE,        /* has PS,VS,GS,FS variants */
 	R600_STATE_SAMPLER,         /* has PS,VS,GS,FS variants */
 	R600_STATE_SAMPLER_BORDER,  /* has PS,VS,GS,FS variants */
diff --git a/src/gallium/winsys/r600/drm/r600_state.c b/src/gallium/winsys/r600/drm/r600_state.c
index 71d65f0..23eed81 100644
--- a/src/gallium/winsys/r600/drm/r600_state.c
+++ b/src/gallium/winsys/r600/drm/r600_state.c
@@ -65,6 +65,7 @@ struct radeon_stype_info r600_stypes[] = {
 	{ R600_STATE_BLEND, 1, 0, r600_state_pm4_generic, SUB_NONE(BLEND), },
 	{ R600_STATE_DSA, 1, 0, r600_state_pm4_generic, SUB_NONE(DSA), },
 	{ R600_STATE_SHADER, 1, 0, r600_state_pm4_shader, { SUB_PS(PS_SHADER), SUB_VS(VS_SHADER) } },
+	{ R600_STATE_CBUF, 1, 0, r600_state_pm4_shader,  { SUB_PS(PS_CBUF), SUB_VS(VS_CBUF) } },
 	{ R600_STATE_CONSTANT, 256, 0x10, r600_state_pm4_generic,  { SUB_PS(PS_CONSTANT), SUB_VS(VS_CONSTANT) } },
 	{ R600_STATE_RESOURCE, 160, 0x1c, r600_state_pm4_resource, { SUB_PS(PS_RESOURCE), SUB_VS(VS_RESOURCE), SUB_GS(GS_RESOURCE), SUB_FS(FS_RESOURCE)} },
 	{ R600_STATE_SAMPLER, 18, 0xc, r600_state_pm4_generic, { SUB_PS(PS_SAMPLER), SUB_VS(VS_SAMPLER), SUB_GS(GS_SAMPLER) } },
diff --git a/src/gallium/winsys/r600/drm/r600_states.h b/src/gallium/winsys/r600/drm/r600_states.h
index 09d79d4..06f6c77 100644
--- a/src/gallium/winsys/r600/drm/r600_states.h
+++ b/src/gallium/winsys/r600/drm/r600_states.h
@@ -269,6 +269,16 @@ static const struct radeon_register R600_names_PS_SHADER[] = {
 	{0x000288CC, 0, 0, "SQ_PGM_CF_OFFSET_PS"},
 };
 
+static const struct radeon_register R600_names_VS_CBUF[] = {
+	{0x00028180, 0, 0, "ALU_CONST_BUFFER_SIZE_VS_0"},
+	{0x00028980, 1, 0, "ALU_CONST_CACHE_VS_0"},
+};
+
+static const struct radeon_register R600_names_PS_CBUF[] = {
+	{0x00028140, 0, 0, "ALU_CONST_BUFFER_SIZE_PS_0"},
+	{0x00028940, 1, 0, "ALU_CONST_CACHE_PS_0"},
+};
+
 static const struct radeon_register R600_names_PS_CONSTANT[] = {
 	{0x00030000, 0, 0, "SQ_ALU_CONSTANT0_0"},
 	{0x00030004, 0, 0, "SQ_ALU_CONSTANT1_0"},




More information about the mesa-commit mailing list