From c7c6f1c8984c8e2e0e9cb62d85ab2df0a9742027 Mon Sep 17 00:00:00 2001 From: Vadim Girlin Date: Tue, 21 Jun 2011 07:32:18 +0400 Subject: [PATCH] r600g: fragment/vertex color clamping Clamping is done in the shaders by adding "MOV_SAT R,R" instructions for each color output before the export. Shaders are rebuilt when needed if clamping state changes. Tested on evergreen. --- src/gallium/drivers/r600/evergreen_state.c | 2 + src/gallium/drivers/r600/r600_pipe.c | 2 +- src/gallium/drivers/r600/r600_pipe.h | 8 ++++- src/gallium/drivers/r600/r600_shader.c | 47 +++++++++++++++++++++++-- src/gallium/drivers/r600/r600_shader.h | 2 + src/gallium/drivers/r600/r600_state.c | 2 + src/gallium/drivers/r600/r600_state_common.c | 43 +++++++++++++++++++++-- 7 files changed, 96 insertions(+), 10 deletions(-) diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c index f86e4d4..dfe7896 100644 --- a/src/gallium/drivers/r600/evergreen_state.c +++ b/src/gallium/drivers/r600/evergreen_state.c @@ -256,6 +256,8 @@ static void *evergreen_create_rs_state(struct pipe_context *ctx, } rstate = &rs->rstate; + rs->clamp_vertex_color = state->clamp_vertex_color; + rs->clamp_fragment_color = state->clamp_fragment_color; rs->flatshade = state->flatshade; rs->sprite_coord_enable = state->sprite_coord_enable; diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c index a0d145d..1131db5 100644 --- a/src/gallium/drivers/r600/r600_pipe.c +++ b/src/gallium/drivers/r600/r600_pipe.c @@ -377,6 +377,7 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param) case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: case PIPE_CAP_SM3: case PIPE_CAP_SEAMLESS_CUBE_MAP: + case PIPE_CAP_FRAGMENT_COLOR_CLAMP_CONTROL: return 1; /* Supported except the original R600. */ @@ -392,7 +393,6 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param) /* Unsupported features. */ case PIPE_CAP_STREAM_OUTPUT: case PIPE_CAP_PRIMITIVE_RESTART: - case PIPE_CAP_FRAGMENT_COLOR_CLAMP_CONTROL: case PIPE_CAP_TGSI_INSTANCEID: case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h index 9941bbf..dc9aad0 100644 --- a/src/gallium/drivers/r600/r600_pipe.h +++ b/src/gallium/drivers/r600/r600_pipe.h @@ -88,6 +88,8 @@ struct r600_pipe_sampler_view { struct r600_pipe_rasterizer { struct r600_pipe_state rstate; + boolean clamp_vertex_color; + boolean clamp_fragment_color; boolean flatshade; unsigned sprite_coord_enable; float offset_units; @@ -125,6 +127,7 @@ struct r600_pipe_shader { struct r600_bo *bo; struct r600_bo *bo_fetch; struct r600_vertex_element vertex_elements; + struct tgsi_token *tokens; }; struct r600_pipe_sampler_state { @@ -202,6 +205,9 @@ struct r600_pipe_context { struct pipe_query *saved_render_cond; unsigned saved_render_cond_mode; /* shader information */ + boolean clamp_vertex_color; + boolean clamp_fragment_color; + boolean spi_dirty; unsigned sprite_coord_enable; boolean flatshade; boolean export_16bpc; @@ -264,7 +270,7 @@ void r600_init_query_functions(struct r600_pipe_context *rctx); void r600_init_context_resource_functions(struct r600_pipe_context *r600); /* r600_shader.c */ -int r600_pipe_shader_create(struct pipe_context *ctx, struct r600_pipe_shader *shader, const struct tgsi_token *tokens); +int r600_pipe_shader_create(struct pipe_context *ctx, struct r600_pipe_shader *shader); void r600_pipe_shader_destroy(struct pipe_context *ctx, struct r600_pipe_shader *shader); int r600_find_vs_semantic_index(struct r600_shader *vs, struct r600_shader *ps, int id); diff --git a/src/gallium/drivers/r600/r600_shader.c b/src/gallium/drivers/r600/r600_shader.c index 0268108..c994c5c 100644 --- a/src/gallium/drivers/r600/r600_shader.c +++ b/src/gallium/drivers/r600/r600_shader.c @@ -120,7 +120,7 @@ static int r600_pipe_shader(struct pipe_context *ctx, struct r600_pipe_shader *s static int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_shader *shader); -int r600_pipe_shader_create(struct pipe_context *ctx, struct r600_pipe_shader *shader, const struct tgsi_token *tokens) +int r600_pipe_shader_create(struct pipe_context *ctx, struct r600_pipe_shader *shader) { static int dump_shaders = -1; struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; @@ -133,10 +133,12 @@ int r600_pipe_shader_create(struct pipe_context *ctx, struct r600_pipe_shader *s if (dump_shaders) { fprintf(stderr, "--------------------------------------------------------------\n"); - tgsi_dump(tokens, 0); + tgsi_dump(shader->tokens, 0); } shader->shader.family = r600_get_family(rctx->radeon); - r = r600_shader_from_tgsi(tokens, &shader->shader); + shader->shader.clamp_vertex_color = rctx->clamp_vertex_color; + shader->shader.clamp_fragment_color = rctx->clamp_fragment_color; + r = r600_shader_from_tgsi(shader->tokens, &shader->shader); if (r) { R600_ERR("translation from TGSI failed !\n"); return r; @@ -159,6 +161,8 @@ void r600_pipe_shader_destroy(struct pipe_context *ctx, struct r600_pipe_shader r600_bo_reference(rctx->radeon, &shader->bo, NULL); r600_bc_clear(&shader->shader.bc); + + memset(&shader->shader, 0 , sizeof(struct r600_shader)); } /* @@ -725,8 +729,43 @@ static int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct r600_sh goto out_err; } } - /* export output */ + noutput = shader->noutput; + + /* clamp color outputs */ + if (((ctx.type == TGSI_PROCESSOR_VERTEX) && shader->clamp_vertex_color) || + ((ctx.type == TGSI_PROCESSOR_FRAGMENT) && shader->clamp_fragment_color)) { + + for (i = 0; i < noutput; i++) { + if (shader->output[i].name == TGSI_SEMANTIC_COLOR || + shader->output[i].name == TGSI_SEMANTIC_BCOLOR) { + + int j; + for (j = 0; j < 4; j++) { + struct r600_bc_alu alu; + memset(&alu, 0, sizeof(struct r600_bc_alu)); + + /* MOV_SAT R, R */ + alu.inst = BC_INST(ctx.bc, V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_MOV); + alu.dst.sel = shader->output[i].gpr; + alu.dst.chan = j; + alu.dst.write = 1; + alu.dst.clamp = 1; + alu.src[0].sel = alu.dst.sel; + alu.src[0].chan = j; + + if (j == 3) { + alu.last = 1; + } + r = r600_bc_add_alu(ctx.bc, &alu); + if (r) + return r; + } + } + } + } + + /* export output */ for (i = 0, pos0 = 0; i < noutput; i++) { memset(&output[i], 0, sizeof(struct r600_bc_output)); output[i].gpr = shader->output[i].gpr; diff --git a/src/gallium/drivers/r600/r600_shader.h b/src/gallium/drivers/r600/r600_shader.h index 8f96ce5..3b920c7 100644 --- a/src/gallium/drivers/r600/r600_shader.h +++ b/src/gallium/drivers/r600/r600_shader.h @@ -46,6 +46,8 @@ struct r600_shader { enum radeon_family family; boolean uses_kill; boolean fs_write_all; + boolean clamp_vertex_color; + boolean clamp_fragment_color; }; #endif diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c index 91da7c5..be07f5f 100644 --- a/src/gallium/drivers/r600/r600_state.c +++ b/src/gallium/drivers/r600/r600_state.c @@ -299,6 +299,8 @@ static void *r600_create_rs_state(struct pipe_context *ctx, } rstate = &rs->rstate; + rs->clamp_vertex_color = state->clamp_vertex_color; + rs->clamp_fragment_color = state->clamp_fragment_color; rs->flatshade = state->flatshade; rs->sprite_coord_enable = state->sprite_coord_enable; diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c index 816508a..0b59535 100644 --- a/src/gallium/drivers/r600/r600_state_common.c +++ b/src/gallium/drivers/r600/r600_state_common.c @@ -28,6 +28,7 @@ #include #include #include "pipe/p_shader_tokens.h" +#include "tgsi/tgsi_parse.h" #include "r600_formats.h" #include "r600_pipe.h" #include "r600d.h" @@ -99,6 +100,8 @@ void r600_bind_rs_state(struct pipe_context *ctx, void *state) if (state == NULL) return; + rctx->clamp_vertex_color = rs->clamp_vertex_color; + rctx->clamp_fragment_color = rs->clamp_fragment_color; rctx->flatshade = rs->flatshade; rctx->sprite_coord_enable = rs->sprite_coord_enable; rctx->rasterizer = rs; @@ -112,7 +115,7 @@ void r600_bind_rs_state(struct pipe_context *ctx, void *state) r600_polygon_offset_update(rctx); } if (rctx->ps_shader && rctx->vs_shader) - r600_spi_update(rctx); + rctx->spi_dirty = true; } void r600_delete_rs_state(struct pipe_context *ctx, void *state) @@ -257,7 +260,9 @@ void *r600_create_shader_state(struct pipe_context *ctx, struct r600_pipe_shader *shader = CALLOC_STRUCT(r600_pipe_shader); int r; - r = r600_pipe_shader_create(ctx, shader, state->tokens); + shader->tokens = tgsi_dup_tokens(state->tokens); + + r = r600_pipe_shader_create(ctx, shader); if (r) { return NULL; } @@ -274,7 +279,7 @@ void r600_bind_ps_shader(struct pipe_context *ctx, void *state) r600_context_pipe_state_set(&rctx->ctx, &rctx->ps_shader->rstate); } if (rctx->ps_shader && rctx->vs_shader) { - r600_spi_update(rctx); + rctx->spi_dirty = true; r600_adjust_gprs(rctx); } } @@ -289,7 +294,7 @@ void r600_bind_vs_shader(struct pipe_context *ctx, void *state) r600_context_pipe_state_set(&rctx->ctx, &rctx->vs_shader->rstate); } if (rctx->ps_shader && rctx->vs_shader) { - r600_spi_update(rctx); + rctx->spi_dirty = true; r600_adjust_gprs(rctx); } } @@ -303,6 +308,7 @@ void r600_delete_ps_shader(struct pipe_context *ctx, void *state) rctx->ps_shader = NULL; } + free(shader->tokens); r600_pipe_shader_destroy(ctx, shader); free(shader); } @@ -316,6 +322,7 @@ void r600_delete_vs_shader(struct pipe_context *ctx, void *state) rctx->vs_shader = NULL; } + free(shader->tokens); r600_pipe_shader_destroy(ctx, shader); free(shader); } @@ -392,6 +399,7 @@ static void r600_spi_update(struct r600_pipe_context *rctx) } r600_context_pipe_state_set(&rctx->ctx, rstate); + rctx->spi_dirty = false; } void r600_set_constant_buffer(struct pipe_context *ctx, uint shader, uint index, @@ -530,6 +538,27 @@ static void r600_vertex_buffer_update(struct r600_pipe_context *rctx) } } +/* rebuild shaders if clamping state changed */ +static int r600_shader_update(struct pipe_context * ctx, struct r600_pipe_shader * shader) +{ + struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; + int r; + + if ((shader->shader.processor_type == TGSI_PROCESSOR_VERTEX && + shader->shader.clamp_vertex_color!=rctx->clamp_vertex_color) || + (shader->shader.processor_type == TGSI_PROCESSOR_FRAGMENT && + shader->shader.clamp_fragment_color!=rctx->clamp_fragment_color)) { + + r600_pipe_shader_destroy(ctx, shader); + r = r600_pipe_shader_create(ctx, shader); + if (r) { + return r; + } + r600_context_pipe_state_set(&rctx->ctx, &shader->rstate); + } + return 0; +} + void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info) { struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; @@ -609,6 +638,12 @@ void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info) return; } + r600_shader_update(ctx, rctx->vs_shader); + r600_shader_update(ctx, rctx->ps_shader); + + if (rctx->spi_dirty) + r600_spi_update(rctx); + if (rctx->alpha_ref_dirty) r600_update_alpha_ref(rctx); -- 1.7.5.4