r300g: implement gl_FrontFacing
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user