On Fri, Jun 24, 2011 at 12:29 PM, Vadim Girlin <vadimgir...@gmail.com> wrote: > Fixes https://bugs.freedesktop.org/show_bug.cgi?id=38440 > > Signed-off-by: Vadim Girlin <vadimgir...@gmail.com>
As discussed previously, there is better to handle this. I think best solution is to always add the instruction and to conditionally execute them thanks to the boolean constant. If this reveal to have a too big impact on shader, other solution i see is adding a cf block with those instructions and to enable or disable that block (cf_nop) and reupload shader that would avoid a rebuild. But as a mean time solution i think this patch is ok Cheers, Jerome > --- > src/gallium/drivers/r600/evergreen_state.c | 2 + > src/gallium/drivers/r600/r600_pipe.c | 2 +- > src/gallium/drivers/r600/r600_pipe.h | 7 +++- > src/gallium/drivers/r600/r600_shader.c | 52 > +++++++++++++++++++++++--- > src/gallium/drivers/r600/r600_shader.h | 1 + > src/gallium/drivers/r600/r600_state.c | 2 + > src/gallium/drivers/r600/r600_state_common.c | 30 ++++++++++++++- > 7 files changed, 87 insertions(+), 9 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 38801d6..12599bf 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 63ddd39..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,8 @@ 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; > @@ -265,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 904cc69..2e5d4a6 100644 > --- a/src/gallium/drivers/r600/r600_shader.c > +++ b/src/gallium/drivers/r600/r600_shader.c > @@ -118,9 +118,9 @@ static int r600_pipe_shader(struct pipe_context *ctx, > struct r600_pipe_shader *s > return 0; > } > > -static int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct > r600_shader *shader); > +static int r600_shader_from_tgsi(struct r600_pipe_context * rctx, struct > r600_pipe_shader *pipeshader); > > -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,10 @@ 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); > + r = r600_shader_from_tgsi(rctx, shader); > if (r) { > R600_ERR("translation from TGSI failed !\n"); > return r; > @@ -159,6 +159,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)); > } > > /* > @@ -594,8 +596,10 @@ static int tgsi_split_literal_constant(struct > r600_shader_ctx *ctx) > return 0; > } > > -static int r600_shader_from_tgsi(const struct tgsi_token *tokens, struct > r600_shader *shader) > +static int r600_shader_from_tgsi(struct r600_pipe_context * rctx, struct > r600_pipe_shader *pipeshader) > { > + struct r600_shader *shader = &pipeshader->shader; > + struct tgsi_token *tokens = pipeshader->tokens; > struct tgsi_full_immediate *immediate; > struct tgsi_full_property *property; > struct r600_shader_ctx ctx; > @@ -616,6 +620,9 @@ static int r600_shader_from_tgsi(const struct tgsi_token > *tokens, struct r600_sh > shader->processor_type = ctx.type; > ctx.bc->type = shader->processor_type; > > + shader->clamp_color = (((ctx.type == TGSI_PROCESSOR_FRAGMENT) && > rctx->clamp_fragment_color) || > + ((ctx.type == TGSI_PROCESSOR_VERTEX) && > rctx->clamp_vertex_color)); > + > /* register allocations */ > /* Values [0,127] correspond to GPR[0..127]. > * Values [128,159] correspond to constant buffer bank 0 > @@ -725,8 +732,41 @@ 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 (shader->clamp_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..c1e00f3 100644 > --- a/src/gallium/drivers/r600/r600_shader.h > +++ b/src/gallium/drivers/r600/r600_shader.h > @@ -46,6 +46,7 @@ struct r600_shader { > enum radeon_family family; > boolean uses_kill; > boolean fs_write_all; > + boolean clamp_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 259f426..f1b0fc3 100644 > --- a/src/gallium/drivers/r600/r600_state_common.c > +++ b/src/gallium/drivers/r600/r600_state_common.c > @@ -28,6 +28,7 @@ > #include <util/u_format.h> > #include <pipebuffer/pb_buffer.h> > #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; > @@ -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; > } > @@ -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); > } > @@ -531,6 +538,21 @@ static void r600_vertex_buffer_update(struct > r600_pipe_context *rctx) > } > } > > +static int r600_shader_rebuild(struct pipe_context * ctx, struct > r600_pipe_shader * shader) > +{ > + struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; > + int r; > + > + 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; > @@ -574,6 +596,12 @@ void r600_draw_vbo(struct pipe_context *ctx, const > struct pipe_draw_info *info) > if (r600_conv_pipe_prim(draw.info.mode, &prim)) > return; > > + if (rctx->vs_shader->shader.clamp_color != rctx->clamp_vertex_color) > + r600_shader_rebuild(ctx, rctx->vs_shader); > + > + if (rctx->ps_shader->shader.clamp_color != rctx->clamp_fragment_color) > + r600_shader_rebuild(ctx, rctx->ps_shader); > + > if (rctx->spi_dirty) > r600_spi_update(rctx); > > -- > 1.7.5.4 > > _______________________________________________ > mesa-dev mailing list > mesa-dev@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/mesa-dev > _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev