[Mesa-dev] [PATCH] r600g: implement two-sided lighting (v3)
Vadim Girlin
vadimgirlin at gmail.com
Thu Jan 5 20:13:18 PST 2012
v2: select the colors in the pixel shader
v3: fix rs state creation for pre-evergreen
Signed-off-by: Vadim Girlin <vadimgirlin at gmail.com>
---
src/gallium/drivers/r600/evergreen_state.c | 1 +
src/gallium/drivers/r600/r600_pipe.h | 2 +
src/gallium/drivers/r600/r600_shader.c | 153 +++++++++++++++++++++----
src/gallium/drivers/r600/r600_shader.h | 1 +
src/gallium/drivers/r600/r600_state.c | 1 +
src/gallium/drivers/r600/r600_state_common.c | 2 +
6 files changed, 135 insertions(+), 25 deletions(-)
diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c
index ed75ae3..d387a1a 100644
--- a/src/gallium/drivers/r600/evergreen_state.c
+++ b/src/gallium/drivers/r600/evergreen_state.c
@@ -902,6 +902,7 @@ static void *evergreen_create_rs_state(struct pipe_context *ctx,
rs->clamp_fragment_color = state->clamp_fragment_color;
rs->flatshade = state->flatshade;
rs->sprite_coord_enable = state->sprite_coord_enable;
+ rs->two_side = state->light_twoside;
clip_rule = state->scissor ? 0xAAAA : 0xFFFF;
diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h
index 447b9dc..bd0b8fe 100644
--- a/src/gallium/drivers/r600/r600_pipe.h
+++ b/src/gallium/drivers/r600/r600_pipe.h
@@ -108,6 +108,7 @@ struct r600_pipe_rasterizer {
boolean clamp_vertex_color;
boolean clamp_fragment_color;
boolean flatshade;
+ boolean two_side;
unsigned sprite_coord_enable;
float offset_units;
float offset_scale;
@@ -218,6 +219,7 @@ struct r600_pipe_context {
/* shader information */
boolean clamp_vertex_color;
boolean clamp_fragment_color;
+ boolean two_side;
unsigned sprite_coord_enable;
boolean export_16bpc;
unsigned alpha_ref;
diff --git a/src/gallium/drivers/r600/r600_shader.c b/src/gallium/drivers/r600/r600_shader.c
index ad4aded..240ca66 100644
--- a/src/gallium/drivers/r600/r600_shader.c
+++ b/src/gallium/drivers/r600/r600_shader.c
@@ -191,6 +191,8 @@ struct r600_shader_ctx {
boolean input_linear;
boolean input_perspective;
int num_interp_gpr;
+ int face_gpr;
+ int colors_used;
};
struct r600_shader_tgsi_instruction {
@@ -374,12 +376,6 @@ static int r600_spi_sid(struct r600_shader_io * io)
/* For generic params simply use sid from tgsi */
index = io->sid;
} else {
-
- /* FIXME: two-side rendering is broken in r600g, this will
- * keep old functionality */
- if (name == TGSI_SEMANTIC_BCOLOR)
- name = TGSI_SEMANTIC_COLOR;
-
/* For non-generic params - pack name and sid into 8 bits */
index = 0x80 | (name<<3) | (io->sid);
}
@@ -393,6 +389,51 @@ static int r600_spi_sid(struct r600_shader_io * io)
return index;
};
+/* turn input into interpolate on EG */
+static int evergreen_interp_input(struct r600_shader_ctx *ctx, int index)
+{
+ int r = 0;
+
+ if (ctx->shader->input[index].spi_sid) {
+ ctx->shader->input[index].lds_pos = ctx->shader->nlds++;
+ if (ctx->shader->input[index].interpolate > 0) {
+ r = evergreen_interp_alu(ctx, index);
+ } else {
+ r = evergreen_interp_flat(ctx, index);
+ }
+ }
+ return r;
+}
+
+static int select_twoside_color(struct r600_shader_ctx *ctx, int front, int back)
+{
+ struct r600_bytecode_alu alu;
+ int i, r;
+ int gpr_front = ctx->shader->input[front].gpr;
+ int gpr_back = ctx->shader->input[back].gpr;
+
+ for (i = 0; i < 4; i++) {
+ memset(&alu, 0, sizeof(alu));
+ alu.inst = CTX_INST(V_SQ_ALU_WORD1_OP3_SQ_OP3_INST_CNDGT);
+ alu.is_op3 = 1;
+ alu.dst.write = 1;
+ alu.dst.sel = gpr_front;
+ alu.src[0].sel = ctx->face_gpr;
+ alu.src[1].sel = gpr_front;
+ alu.src[2].sel = gpr_back;
+
+ alu.dst.chan = i;
+ alu.src[1].chan = i;
+ alu.src[2].chan = i;
+ alu.last = (i==3);
+
+ if ((r = r600_bytecode_add_alu(ctx->bc, &alu)))
+ return r;
+ }
+
+ return 0;
+}
+
static int tgsi_declaration(struct r600_shader_ctx *ctx)
{
struct tgsi_full_declaration *d = &ctx->parse.FullToken.FullDeclaration;
@@ -408,15 +449,15 @@ static int tgsi_declaration(struct r600_shader_ctx *ctx)
ctx->shader->input[i].interpolate = d->Declaration.Interpolate;
ctx->shader->input[i].centroid = d->Declaration.Centroid;
ctx->shader->input[i].gpr = ctx->file_offset[TGSI_FILE_INPUT] + d->Range.First;
- if (ctx->type == TGSI_PROCESSOR_FRAGMENT && ctx->bc->chip_class >= EVERGREEN) {
- /* turn input into interpolate on EG */
- if (ctx->shader->input[i].spi_sid) {
- ctx->shader->input[i].lds_pos = ctx->shader->nlds++;
- if (ctx->shader->input[i].interpolate > 0) {
- evergreen_interp_alu(ctx, i);
- } else {
- evergreen_interp_flat(ctx, i);
- }
+ if (ctx->type == TGSI_PROCESSOR_FRAGMENT) {
+ if (ctx->shader->input[i].name == TGSI_SEMANTIC_FACE)
+ ctx->face_gpr = ctx->shader->input[i].gpr;
+ else if (ctx->shader->input[i].name == TGSI_SEMANTIC_COLOR)
+ ctx->colors_used++;
+ if (ctx->bc->chip_class >= EVERGREEN) {
+ r = evergreen_interp_input(ctx, i);
+ if (r)
+ return r;
}
}
break;
@@ -690,6 +731,47 @@ static int tgsi_split_literal_constant(struct r600_shader_ctx *ctx)
return 0;
}
+static int process_twoside_color_inputs(struct r600_shader_ctx *ctx)
+{
+ int i, r, count = ctx->shader->ninput;
+
+ /* additional inputs will be allocated right after the existing inputs,
+ * we won't need them after the color selection, so we don't need to
+ * reserve these gprs for the rest of the shader code and to adjust
+ * output offsets etc. */
+ int gpr = ctx->file_offset[TGSI_FILE_INPUT] +
+ ctx->info.file_max[TGSI_FILE_INPUT] + 1;
+
+ if (ctx->face_gpr == -1) {
+ i = ctx->shader->ninput++;
+ ctx->shader->input[i].name = TGSI_SEMANTIC_FACE;
+ ctx->shader->input[i].spi_sid = 0;
+ ctx->shader->input[i].gpr = gpr++;
+ ctx->face_gpr = ctx->shader->input[i].gpr;
+ }
+
+ for (i = 0; i < count; i++) {
+ if (ctx->shader->input[i].name == TGSI_SEMANTIC_COLOR) {
+ int ni = ctx->shader->ninput++;
+ memcpy(&ctx->shader->input[ni],&ctx->shader->input[i], sizeof(struct r600_shader_io));
+ ctx->shader->input[ni].name = TGSI_SEMANTIC_BCOLOR;
+ ctx->shader->input[ni].spi_sid = r600_spi_sid(&ctx->shader->input[ni]);
+ ctx->shader->input[ni].gpr = gpr++;
+
+ if (ctx->bc->chip_class >= EVERGREEN) {
+ r = evergreen_interp_input(ctx, ni);
+ if (r)
+ return r;
+ }
+
+ r = select_twoside_color(ctx, i, ni);
+ if (r)
+ return r;
+ }
+ }
+ return 0;
+}
+
static int r600_shader_from_tgsi(struct r600_pipe_context * rctx, struct r600_pipe_shader *pipeshader)
{
struct r600_shader *shader = &pipeshader->shader;
@@ -713,6 +795,11 @@ static int r600_shader_from_tgsi(struct r600_pipe_context * rctx, struct r600_pi
shader->processor_type = ctx.type;
ctx.bc->type = shader->processor_type;
+ ctx.face_gpr = -1;
+ ctx.colors_used = 0;
+
+ shader->two_side = (ctx.type == TGSI_PROCESSOR_FRAGMENT) && rctx->two_side;
+
shader->clamp_color = (((ctx.type == TGSI_PROCESSOR_FRAGMENT) && rctx->clamp_fragment_color) ||
((ctx.type == TGSI_PROCESSOR_VERTEX) && rctx->clamp_vertex_color));
@@ -792,6 +879,31 @@ static int r600_shader_from_tgsi(struct r600_pipe_context * rctx, struct r600_pi
goto out_err;
break;
case TGSI_TOKEN_TYPE_INSTRUCTION:
+ break;
+ case TGSI_TOKEN_TYPE_PROPERTY:
+ property = &ctx.parse.FullToken.FullProperty;
+ if (property->Property.PropertyName == TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS) {
+ if (property->u[0].Data == 1)
+ shader->fs_write_all = TRUE;
+ }
+ break;
+ default:
+ R600_ERR("unsupported token type %d\n", ctx.parse.FullToken.Token.Type);
+ r = -EINVAL;
+ goto out_err;
+ }
+ }
+
+ if (shader->two_side && ctx.colors_used) {
+ if ((r = process_twoside_color_inputs(&ctx)))
+ return r;
+ }
+
+ tgsi_parse_init(&ctx.parse, tokens);
+ while (!tgsi_parse_end_of_tokens(&ctx.parse)) {
+ tgsi_parse_token(&ctx.parse);
+ switch (ctx.parse.FullToken.Token.Type) {
+ case TGSI_TOKEN_TYPE_INSTRUCTION:
r = tgsi_is_supported(&ctx);
if (r)
goto out_err;
@@ -814,17 +926,8 @@ static int r600_shader_from_tgsi(struct r600_pipe_context * rctx, struct r600_pi
if (r)
goto out_err;
break;
- case TGSI_TOKEN_TYPE_PROPERTY:
- property = &ctx.parse.FullToken.FullProperty;
- if (property->Property.PropertyName == TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS) {
- if (property->u[0].Data == 1)
- shader->fs_write_all = TRUE;
- }
- break;
default:
- R600_ERR("unsupported token type %d\n", ctx.parse.FullToken.Token.Type);
- r = -EINVAL;
- goto out_err;
+ break;
}
}
diff --git a/src/gallium/drivers/r600/r600_shader.h b/src/gallium/drivers/r600/r600_shader.h
index 9990ba6..530a776 100644
--- a/src/gallium/drivers/r600/r600_shader.h
+++ b/src/gallium/drivers/r600/r600_shader.h
@@ -47,6 +47,7 @@ struct r600_shader {
boolean uses_kill;
boolean fs_write_all;
boolean clamp_color;
+ boolean two_side;
unsigned nr_cbufs;
};
diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c
index 12157ff..8bdc6af 100644
--- a/src/gallium/drivers/r600/r600_state.c
+++ b/src/gallium/drivers/r600/r600_state.c
@@ -954,6 +954,7 @@ static void *r600_create_rs_state(struct pipe_context *ctx,
rs->clamp_fragment_color = state->clamp_fragment_color;
rs->flatshade = state->flatshade;
rs->sprite_coord_enable = state->sprite_coord_enable;
+ rs->two_side = state->light_twoside;
clip_rule = state->scissor ? 0xAAAA : 0xFFFF;
/* offset */
diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c
index 054ab90..7f8aad6 100644
--- a/src/gallium/drivers/r600/r600_state_common.c
+++ b/src/gallium/drivers/r600/r600_state_common.c
@@ -103,6 +103,7 @@ void r600_bind_rs_state(struct pipe_context *ctx, void *state)
rctx->clamp_fragment_color = rs->clamp_fragment_color;
rctx->sprite_coord_enable = rs->sprite_coord_enable;
+ rctx->two_side = rs->two_side;
rctx->rasterizer = rs;
@@ -564,6 +565,7 @@ static void r600_update_derived_state(struct r600_pipe_context *rctx)
}
if ((rctx->ps_shader->shader.clamp_color != rctx->clamp_fragment_color) ||
+ (rctx->ps_shader->shader.two_side != rctx->two_side) ||
((rctx->chip_class >= EVERGREEN) && rctx->ps_shader->shader.fs_write_all &&
(rctx->ps_shader->shader.nr_cbufs != rctx->nr_cbufs))) {
r600_shader_rebuild(&rctx->context, rctx->ps_shader);
--
1.7.7.5
More information about the mesa-dev
mailing list