r600g: implement two-sided lighting (v3)

v2: select the colors in the pixel shader

v3: fix rs state creation for pre-evergreen

Signed-off-by: Vadim Girlin <vadimgirlin@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
Vadim Girlin
2012-01-06 08:13:18 +04:00
committed by Dave Airlie
parent d84ab821c5
commit 725a820b92
6 changed files with 135 additions and 25 deletions
@@ -906,6 +906,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;
+2
View File
@@ -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;
@@ -217,6 +218,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;
+128 -25
View File
@@ -193,6 +193,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 {
@@ -376,12 +378,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);
}
@@ -395,6 +391,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;
@@ -410,15 +451,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;
@@ -699,6 +740,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;
@@ -722,6 +804,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));
@@ -800,6 +887,31 @@ static int r600_shader_from_tgsi(struct r600_pipe_context * rctx, struct r600_pi
if (r)
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)
@@ -823,17 +935,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;
}
}
+1
View File
@@ -47,6 +47,7 @@ struct r600_shader {
boolean uses_kill;
boolean fs_write_all;
boolean clamp_color;
boolean two_side;
unsigned nr_cbufs;
};
+1
View File
@@ -958,6 +958,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 */
@@ -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;
@@ -568,6 +569,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);