From d42efb9e8df6ef872ab4f142e3daf1b6cb9eff11 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 8 Sep 2010 08:41:57 +1000 Subject: [PATCH] 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 bf3d31cd2b0..b62354fe91a 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 9e65fcdd4fa..0d75d99310e 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 7829a479c2e..d8188ae6562 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 239c1a3adeb..eb370698bbd 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 948ae61c2e5..55723360bf6 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 a047a49a6c5..54a61ddfb33 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 b9938f117a8..4be77865fbd 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 1273cd62a28..b643157f56a 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 7c722c07cbe..fba4a2b3b8a 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 780a867f95e..93b0cf1a534 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 5367af5850e..0f8a2d74616 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 cf26ecfe231..0a8cb73e7dc 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 71d65f0feab..23eed81e04d 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 09d79d498d8..06f6c7773d2 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"}, -- 2.30.2