r300g: implement gl_FrontFacing

This commit is contained in:
Marek Olšák
2010-08-10 14:21:05 +02:00
parent cc732bf894
commit 683ef52e19
5 changed files with 97 additions and 7 deletions
+14 -1
View File
@@ -72,6 +72,11 @@ void r300_shader_read_fs_inputs(struct tgsi_shader_info* info,
fs_inputs->wpos = i;
break;
case TGSI_SEMANTIC_FACE:
assert(index == 0);
fs_inputs->face = i;
break;
default:
fprintf(stderr, "r300: FP: Unknown input semantic: %i\n",
info->input_semantic_name[i]);
@@ -120,6 +125,9 @@ static void allocate_hardware_inputs(
allocate(mydata, inputs->color[i], reg++);
}
}
if (inputs->face != ATTR_UNUSED) {
allocate(mydata, inputs->face, reg++);
}
for (i = 0; i < ATTR_GENERIC_COUNT; i++) {
if (inputs->generic[i] != ATTR_UNUSED) {
allocate(mydata, inputs->generic[i], reg++);
@@ -360,13 +368,14 @@ static void r300_translate_fragment_shader(
{
struct r300_fragment_program_compiler compiler;
struct tgsi_to_rc ttr;
int wpos;
int wpos, face;
unsigned i;
tgsi_scan_shader(tokens, &shader->info);
r300_shader_read_fs_inputs(&shader->info, &shader->inputs);
wpos = shader->inputs.wpos;
face = shader->inputs.face;
/* Setup the compiler. */
memset(&compiler, 0, sizeof(compiler));
@@ -406,6 +415,10 @@ static void r300_translate_fragment_shader(
rc_transform_fragment_wpos(&compiler.Base, wpos, wpos, TRUE);
}
if (face != ATTR_UNUSED) {
rc_transform_fragment_face(&compiler.Base, face);
}
/* Invoke the compiler */
r3xx_compile_fragment_program(&compiler);
@@ -38,6 +38,7 @@ struct r300_shader_semantics {
int psize;
int color[ATTR_COLOR_COUNT];
int bcolor[ATTR_COLOR_COUNT];
int face;
int generic[ATTR_GENERIC_COUNT];
int fog;
int wpos;
@@ -50,6 +51,7 @@ static INLINE void r300_shader_semantics_reset(
info->pos = ATTR_UNUSED;
info->psize = ATTR_UNUSED;
info->face = ATTR_UNUSED;
info->fog = ATTR_UNUSED;
info->wpos = ATTR_UNUSED;
+37 -6
View File
@@ -46,6 +46,11 @@ enum r300_rs_swizzle {
SWIZ_0001,
};
enum r300_rs_col_write_type {
WRITE_COLOR = 0,
WRITE_FACE
};
static void r300_draw_emit_attrib(struct r300_context* r300,
enum attrib_emit emit,
enum interp_mode interp,
@@ -203,8 +208,10 @@ static void r300_rs_col(struct r300_rs_block* rs, int id, int ptr,
rs->inst[id] |= R300_RS_INST_COL_ID(id);
}
static void r300_rs_col_write(struct r300_rs_block* rs, int id, int fp_offset)
static void r300_rs_col_write(struct r300_rs_block* rs, int id, int fp_offset,
enum r300_rs_col_write_type type)
{
assert(type != WRITE_COLOR);
rs->inst[id] |= R300_RS_INST_COL_CN_WRITE |
R300_RS_INST_COL_ADDR(fp_offset);
}
@@ -252,10 +259,16 @@ static void r500_rs_col(struct r300_rs_block* rs, int id, int ptr,
rs->inst[id] |= R500_RS_INST_COL_ID(id);
}
static void r500_rs_col_write(struct r300_rs_block* rs, int id, int fp_offset)
static void r500_rs_col_write(struct r300_rs_block* rs, int id, int fp_offset,
enum r300_rs_col_write_type type)
{
rs->inst[id] |= R500_RS_INST_COL_CN_WRITE |
R500_RS_INST_COL_ADDR(fp_offset);
if (type == WRITE_FACE)
rs->inst[id] |= R500_RS_INST_COL_CN_WRITE_BACKFACE |
R500_RS_INST_COL_ADDR(fp_offset);
else
rs->inst[id] |= R500_RS_INST_COL_CN_WRITE |
R500_RS_INST_COL_ADDR(fp_offset);
}
static void r500_rs_tex(struct r300_rs_block* rs, int id, int ptr,
@@ -305,7 +318,7 @@ static void r300_update_rs_block(struct r300_context *r300)
struct r300_rs_block rs = {0};
int i, col_count = 0, tex_count = 0, fp_offset = 0, count, loc = 0, tex_ptr = 0;
void (*rX00_rs_col)(struct r300_rs_block*, int, int, enum r300_rs_swizzle);
void (*rX00_rs_col_write)(struct r300_rs_block*, int, int);
void (*rX00_rs_col_write)(struct r300_rs_block*, int, int, enum r300_rs_col_write_type);
void (*rX00_rs_tex)(struct r300_rs_block*, int, int, enum r300_rs_swizzle);
void (*rX00_rs_tex_write)(struct r300_rs_block*, int, int);
boolean any_bcolor_used = vs_outputs->bcolor[0] != ATTR_UNUSED ||
@@ -350,7 +363,7 @@ static void r300_update_rs_block(struct r300_context *r300)
/* Write it to the FS input register if it's needed by the FS. */
if (fs_inputs->color[i] != ATTR_UNUSED) {
rX00_rs_col_write(&rs, col_count, fp_offset);
rX00_rs_col_write(&rs, col_count, fp_offset, WRITE_COLOR);
fp_offset++;
DBG(r300, DBG_RS,
@@ -398,6 +411,24 @@ static void r300_update_rs_block(struct r300_context *r300)
}
}
/* gl_FrontFacing.
* Note that we can use either the two-sided color selection based on
* the front and back vertex shader colors, or gl_FrontFacing,
* but not both! It locks up otherwise.
*
* In Direct3D 9, the two-sided color selection can be used
* with shaders 2.0 only, while gl_FrontFacing can be used
* with shaders 3.0 only. The hardware apparently hasn't been designed
* to support both at the same time. */
if (r300->screen->caps.is_r500 && fs_inputs->face != ATTR_UNUSED &&
!(any_bcolor_used && r300->two_sided_color)) {
rX00_rs_col(&rs, col_count, col_count, SWIZ_XYZW);
rX00_rs_col_write(&rs, col_count, fp_offset, WRITE_FACE);
fp_offset++;
col_count++;
DBG(r300, DBG_RS, "r300: Rasterized FACE written to FS.\n");
}
/* Rasterize texture coordinates. */
for (i = 0; i < ATTR_GENERIC_COUNT && tex_count < 8; i++) {
bool sprite_coord = !!(r300->sprite_coord_enable & (1 << i));
@@ -307,3 +307,46 @@ void rc_transform_fragment_wpos(struct radeon_compiler * c, unsigned wpos, unsig
}
}
/**
* The FACE input in hardware contains 1 if it's a back face, 0 otherwise.
* Gallium and OpenGL define it the other way around.
*
* So let's just negate FACE at the beginning of the shader and rewrite the rest
* of the shader to read from the newly allocated temporary.
*/
void rc_transform_fragment_face(struct radeon_compiler *c, unsigned face)
{
unsigned tempregi = rc_find_free_temporary(c);
struct rc_instruction *inst_add;
struct rc_instruction *inst;
/* perspective divide */
inst_add = rc_insert_new_instruction(c, &c->Program.Instructions);
inst_add->U.I.Opcode = RC_OPCODE_ADD;
inst_add->U.I.DstReg.File = RC_FILE_TEMPORARY;
inst_add->U.I.DstReg.Index = tempregi;
inst_add->U.I.DstReg.WriteMask = RC_MASK_X;
inst_add->U.I.SrcReg[0].File = RC_FILE_NONE;
inst_add->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_1111;
inst_add->U.I.SrcReg[1].File = RC_FILE_INPUT;
inst_add->U.I.SrcReg[1].Index = face;
inst_add->U.I.SrcReg[1].Swizzle = RC_SWIZZLE_XXXX;
inst_add->U.I.SrcReg[1].Negate = RC_MASK_XYZW;
for (inst = inst_add->Next; inst != &c->Program.Instructions; inst = inst->Next) {
const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode);
unsigned i;
for(i = 0; i < opcode->NumSrcRegs; i++) {
if (inst->U.I.SrcReg[i].File == RC_FILE_INPUT &&
inst->U.I.SrcReg[i].Index == face) {
inst->U.I.SrcReg[i].File = RC_FILE_TEMPORARY;
inst->U.I.SrcReg[i].Index = tempregi;
}
}
}
}
@@ -81,6 +81,7 @@ void rc_move_output(struct radeon_compiler * c, unsigned output, unsigned new_ou
void rc_copy_output(struct radeon_compiler * c, unsigned output, unsigned dup_output);
void rc_transform_fragment_wpos(struct radeon_compiler * c, unsigned wpos, unsigned new_input,
int full_vtransform);
void rc_transform_fragment_face(struct radeon_compiler *c, unsigned face);
struct r300_fragment_program_compiler {
struct radeon_compiler Base;