[Mesa-dev] [PATCH 3/3] r600g: implement fragment and vertex color clamp
Jerome Glisse
j.glisse at gmail.com
Fri Jun 24 12:38:50 PDT 2011
On Fri, Jun 24, 2011 at 12:29 PM, Vadim Girlin <vadimgirlin at gmail.com> wrote:
> Fixes https://bugs.freedesktop.org/show_bug.cgi?id=38440
>
> Signed-off-by: Vadim Girlin <vadimgirlin at 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 at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
>
More information about the mesa-dev
mailing list