Mesa (master): r600g: implement fragment and vertex color clamp

Jerome Glisse glisse at kemper.freedesktop.org
Fri Jun 24 19:34:26 UTC 2011


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

Author: Vadim Girlin <vadimgirlin at gmail.com>
Date:   Fri Jun 24 20:29:13 2011 +0400

r600g: implement fragment and vertex color clamp

Fixes https://bugs.freedesktop.org/show_bug.cgi?id=38440

Signed-off-by: Vadim Girlin <vadimgirlin at gmail.com>

---

 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);
 




More information about the mesa-commit mailing list