r300g: add WPOS

This commit is contained in:
Marek Olšák 2009-12-24 03:10:33 +01:00 committed by Corbin Simpson
parent dc7f309f9c
commit bf60eb3fec
6 changed files with 124 additions and 3 deletions

View File

@ -165,6 +165,28 @@ static const float * get_shader_constant(
vec[3] = 0;
break;
case RC_STATE_R300_VIEWPORT_SCALE:
if (r300->rs_state->enable_vte) {
vec[0] = r300->viewport_state->xscale;
vec[1] = r300->viewport_state->yscale;
vec[2] = r300->viewport_state->zscale;
} else {
vec[0] = 1;
vec[1] = 1;
vec[2] = 1;
}
break;
case RC_STATE_R300_VIEWPORT_OFFSET:
if (r300->rs_state->enable_vte) {
vec[0] = r300->viewport_state->xoffset;
vec[1] = r300->viewport_state->yoffset;
vec[2] = r300->viewport_state->zoffset;
} else {
/* Zeros. */
}
break;
default:
debug_printf("r300: Implementation error: "
"Unknown RC_CONSTANT type %d\n", constant->u.State[0]);

View File

@ -63,6 +63,11 @@ void r300_shader_read_fs_inputs(struct tgsi_shader_info* info,
fs_inputs->fog = i;
break;
case TGSI_SEMANTIC_POSITION:
assert(index == 0);
fs_inputs->wpos = i;
break;
default:
assert(0);
}
@ -114,6 +119,9 @@ static void allocate_hardware_inputs(
if (inputs->fog != ATTR_UNUSED) {
allocate(mydata, inputs->fog, reg++);
}
if (inputs->wpos != ATTR_UNUSED) {
allocate(mydata, inputs->wpos, reg++);
}
}
static void get_compare_state(
@ -144,6 +152,7 @@ static void r300_translate_fragment_shader(
struct r300_fragment_shader* fs = r300->fs;
struct r300_fragment_program_compiler compiler;
struct tgsi_to_rc ttr;
int wpos = fs->inputs.wpos;
/* Setup the compiler. */
memset(&compiler, 0, sizeof(compiler));
@ -171,6 +180,18 @@ static void r300_translate_fragment_shader(
fs->shadow_samplers = compiler.Base.Program.ShadowSamplers;
/**
* Transform the program to support WPOS.
*
* Introduce a small fragment at the start of the program that will be
* the only code that directly reads the WPOS input.
* All other code pieces that reference that input will be rewritten
* to read from a newly allocated temporary. */
if (wpos != ATTR_UNUSED) {
/* Moving the input to some other reg is not really necessary. */
rc_transform_fragment_wpos(&compiler.Base, wpos, wpos, TRUE);
}
/* Invoke the compiler */
r3xx_compile_fragment_program(&compiler);
if (compiler.Base.Error) {

View File

@ -40,6 +40,7 @@ struct r300_shader_semantics {
int bcolor[ATTR_COLOR_COUNT];
int generic[ATTR_GENERIC_COUNT];
int fog;
int wpos;
};
static INLINE void r300_shader_semantics_reset(
@ -50,6 +51,7 @@ static INLINE void r300_shader_semantics_reset(
info->pos = ATTR_UNUSED;
info->psize = ATTR_UNUSED;
info->fog = ATTR_UNUSED;
info->wpos = ATTR_UNUSED;
for (i = 0; i < ATTR_COLOR_COUNT; i++) {
info->color[i] = ATTR_UNUSED;

View File

@ -719,6 +719,9 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state)
r300->dirty_state |= R300_NEW_RS_BLOCK;
r300->dirty_state |= R300_NEW_SCISSOR;
r300->dirty_state |= R300_NEW_VIEWPORT;
if (r300->fs && r300->fs->inputs.wpos != ATTR_UNUSED) {
r300->dirty_state |= R300_NEW_FRAGMENT_SHADER_CONSTANTS;
}
}
/* Free rasterizer state. */
@ -897,6 +900,9 @@ static void r300_set_viewport_state(struct pipe_context* pipe,
}
r300->dirty_state |= R300_NEW_VIEWPORT;
if (r300->fs && r300->fs->inputs.wpos != ATTR_UNUSED) {
r300->dirty_state |= R300_NEW_FRAGMENT_SHADER_CONSTANTS;
}
}
static void r300_set_vertex_buffers(struct pipe_context* pipe,

View File

@ -410,6 +410,26 @@ static void r300_update_rs_block(struct r300_context* r300,
}
}
/* Rasterize WPOS. */
if (vs_outputs->wpos != ATTR_UNUSED) {
/* Always rasterize if it's written by the VS,
* otherwise it locks up. */
rX00_rs_tex(rs, tex_count, tex_count, FALSE);
/* Write it to the FS input register if it's used by the FS. */
if (fs_inputs->wpos != ATTR_UNUSED) {
rX00_rs_tex_write(rs, tex_count, fp_offset);
fp_offset++;
}
tex_count++;
} else {
/* Skip the FS input register, leave it uninitialized. */
/* If we try to set it to (0,0,0,1), it will lock up. */
if (fs_inputs->wpos != ATTR_UNUSED) {
fp_offset++;
}
}
/* Rasterize at least one color, or bad things happen. */
if (col_count == 0 && tex_count == 0) {
rX00_rs_col(rs, 0, 0, TRUE);

View File

@ -33,6 +33,8 @@
#include "radeon_compiler.h"
#include "util/u_math.h"
/* Convert info about VS output semantics into r300_shader_semantics. */
static void r300_shader_read_vs_outputs(
struct tgsi_shader_info* info,
@ -144,6 +146,13 @@ static void r300_shader_vap_output_fmt(
gen_count++;
}
/* WPOS. */
if (vs_outputs->wpos != ATTR_UNUSED) {
hwfmt[1] |= (R300_INPUT_CNTL_TC0 << gen_count);
hwfmt[3] |= (4 << (3 * gen_count));
gen_count++;
}
/* XXX magic */
assert(gen_count <= 8);
}
@ -195,6 +204,13 @@ static void r300_stream_locations_notcl(
gen_count++;
}
/* WPOS. */
if (vs_outputs->wpos != ATTR_UNUSED) {
assert(tabi < 16);
stream_loc[tabi++] = 6 + gen_count;
gen_count++;
}
/* XXX magic */
assert(gen_count <= 8);
@ -246,6 +262,33 @@ static void set_vertex_inputs_outputs(struct r300_vertex_program_compiler * c)
if (outputs->fog != ATTR_UNUSED) {
c->code->outputs[outputs->fog] = reg++;
}
/* WPOS. */
if (outputs->wpos != ATTR_UNUSED) {
c->code->outputs[outputs->wpos] = reg++;
}
}
static void r300_insert_wpos(struct r300_vertex_program_compiler* c,
struct r300_shader_semantics* outputs)
{
int i, lastOutput = 0;
/* Find the max output index. */
lastOutput = MAX2(lastOutput, outputs->psize);
for (i = 0; i < ATTR_COLOR_COUNT; i++) {
lastOutput = MAX2(lastOutput, outputs->color[i]);
lastOutput = MAX2(lastOutput, outputs->bcolor[i]);
}
for (i = 0; i < ATTR_GENERIC_COUNT; i++) {
lastOutput = MAX2(lastOutput, outputs->generic[i]);
}
lastOutput = MAX2(lastOutput, outputs->fog);
/* Set WPOS after the last output. */
lastOutput++;
rc_copy_output(&c->Base, 0, lastOutput); /* out[lastOutput] = out[0]; */
outputs->wpos = lastOutput;
}
void r300_translate_vertex_shader(struct r300_context* r300,
@ -253,11 +296,10 @@ void r300_translate_vertex_shader(struct r300_context* r300,
{
struct r300_vertex_program_compiler compiler;
struct tgsi_to_rc ttr;
boolean use_wpos = TRUE;
/* Initialize. */
r300_shader_read_vs_outputs(&vs->info, &vs->outputs);
r300_shader_vap_output_fmt(&vs->outputs, vs->hwfmt);
r300_stream_locations_notcl(&vs->outputs, vs->stream_loc_notcl);
/* Setup the compiler */
rc_init(&compiler.Base);
@ -277,9 +319,17 @@ void r300_translate_vertex_shader(struct r300_context* r300,
r300_tgsi_to_rc(&ttr, vs->state.tokens);
compiler.RequiredOutputs = ~(~0 << vs->info.num_outputs);
compiler.RequiredOutputs = ~(~0 << (vs->info.num_outputs+use_wpos));
compiler.SetHwInputOutput = &set_vertex_inputs_outputs;
/* Insert the WPOS output. */
if (use_wpos) {
r300_insert_wpos(&compiler, &vs->outputs);
}
r300_shader_vap_output_fmt(&vs->outputs, vs->hwfmt);
r300_stream_locations_notcl(&vs->outputs, vs->stream_loc_notcl);
/* Invoke the compiler */
r3xx_compile_vertex_program(&compiler);
if (compiler.Base.Error) {