r300g: share the VS-output-mapping state with SWTCL

And associated cleanups.
This commit is contained in:
Marek Olšák
2010-03-07 02:32:09 +01:00
parent 6f4a19ca56
commit 4f541db80c
4 changed files with 97 additions and 149 deletions
+35 -31
View File
@@ -1087,67 +1087,71 @@ static void* r300_create_vs_state(struct pipe_context* pipe,
{
struct r300_context* r300 = r300_context(pipe);
struct r300_vertex_shader* vs = CALLOC_STRUCT(r300_vertex_shader);
r300_vertex_shader_common_init(vs, shader);
if (r300_screen(pipe->screen)->caps->has_tcl) {
struct r300_vertex_shader* vs = CALLOC_STRUCT(r300_vertex_shader);
/* Copy state directly into shader. */
vs->state = *shader;
vs->state.tokens = tgsi_dup_tokens(shader->tokens);
tgsi_scan_shader(shader->tokens, &vs->info);
return (void*)vs;
r300_translate_vertex_shader(r300, vs);
} else {
return draw_create_vertex_shader(r300->draw, shader);
vs->draw_vs = draw_create_vertex_shader(r300->draw, shader);
}
return vs;
}
static void r300_bind_vs_state(struct pipe_context* pipe, void* shader)
{
struct r300_context* r300 = r300_context(pipe);
struct r300_vertex_shader* vs = (struct r300_vertex_shader*)shader;
if (vs == NULL) {
r300->vs_state.state = NULL;
return;
}
if (vs == r300->vs_state.state) {
return;
}
r300->vs_state.state = vs;
// VS output mapping for HWTCL or stream mapping for SWTCL to the RS block
if (r300->fs) {
r300_vertex_shader_setup_wpos(r300);
}
memcpy(r300->vap_output_state.state, &vs->vap_out,
sizeof(struct r300_vap_output_state));
r300->vap_output_state.dirty = TRUE;
/* The majority of the RS block bits is dependent on the vertex shader. */
r300->rs_block_state.dirty = TRUE; /* Will be updated before the emission. */
if (r300_screen(pipe->screen)->caps->has_tcl) {
struct r300_vertex_shader* vs = (struct r300_vertex_shader*)shader;
if (vs == NULL) {
r300->vs_state.state = NULL;
return;
} else if (!vs->translated) {
r300_translate_vertex_shader(r300, vs);
}
UPDATE_STATE(shader, r300->vs_state);
r300->vs_state.dirty = TRUE;
r300->vs_state.size = vs->code.length + 9;
r300->rs_block_state.dirty = TRUE; /* Will be updated before the emission. */
r300->vap_output_state.dirty = TRUE;
r300->pvs_flush.dirty = TRUE;
if (r300->fs) {
r300_vertex_shader_setup_wpos(r300);
}
r300->dirty_state |= R300_NEW_VERTEX_SHADER_CONSTANTS;
} else {
draw_flush(r300->draw);
draw_bind_vertex_shader(r300->draw,
(struct draw_vertex_shader*)shader);
(struct draw_vertex_shader*)vs->draw_vs);
}
}
static void r300_delete_vs_state(struct pipe_context* pipe, void* shader)
{
struct r300_context* r300 = r300_context(pipe);
struct r300_vertex_shader* vs = (struct r300_vertex_shader*)shader;
if (r300_screen(pipe->screen)->caps->has_tcl) {
struct r300_vertex_shader* vs = (struct r300_vertex_shader*)shader;
rc_constants_destroy(&vs->code.constants);
FREE((void*)vs->state.tokens);
FREE(shader);
} else {
draw_delete_vertex_shader(r300->draw,
(struct draw_vertex_shader*)shader);
(struct draw_vertex_shader*)vs->draw_vs);
}
FREE((void*)vs->state.tokens);
FREE(shader);
}
static void r300_set_constant_buffer(struct pipe_context *pipe,
@@ -433,16 +433,12 @@ static void r300_update_derived_shader_state(struct r300_context* r300)
{
struct r300_vertex_shader* vs = r300->vs_state.state;
struct r300_screen* r300screen = r300_screen(r300->context.screen);
struct r300_vap_output_state *vap_out =
(struct r300_vap_output_state*)r300->vap_output_state.state;
r300_update_rs_block(r300, &vs->outputs, &r300->fs->inputs);
if (r300screen->caps->has_tcl) {
memcpy(vap_out, vs->hwfmt, sizeof(uint)*4);
r300_vertex_psc(r300);
} else {
/* XXX set vap_out */
memset(&r300->vertex_info, 0, sizeof(struct vertex_info));
r300_draw_emit_all_attribs(r300);
draw_compute_vertex_size(&r300->vertex_info);
+53 -110
View File
@@ -89,95 +89,41 @@ static void r300_shader_read_vs_outputs(
assert(0);
}
}
/* WPOS is a straight copy of POSITION and it's always emitted. */
vs_outputs->wpos = i;
}
static void r300_shader_vap_output_fmt(struct r300_vertex_shader* vs)
/* This function sets up:
* - VAP mapping, which maps VS registers to output semantics and
* at the same time it indicates which attributes are enabled and should
* be rasterized.
* - Stream mapping to VS outputs if TCL is not present. */
static void r300_init_vs_output_mapping(struct r300_vertex_shader* vs)
{
struct r300_shader_semantics* vs_outputs = &vs->outputs;
uint32_t* hwfmt = vs->hwfmt;
int i, gen_count;
struct r300_vap_output_state *vap_out = &vs->vap_out;
int *stream_loc = vs->stream_loc_notcl;
int i, gen_count, tabi = 0;
boolean any_bcolor_used = vs_outputs->bcolor[0] != ATTR_UNUSED ||
vs_outputs->bcolor[1] != ATTR_UNUSED;
/* Do the actual vertex_info setup.
*
* vertex_info has four uints of hardware-specific data in it.
* vinfo.hwfmt[0] is R300_VAP_VTX_STATE_CNTL
* vinfo.hwfmt[1] is R300_VAP_VSM_VTX_ASSM
* vinfo.hwfmt[2] is R300_VAP_OUTPUT_VTX_FMT_0
* vinfo.hwfmt[3] is R300_VAP_OUTPUT_VTX_FMT_1 */
hwfmt[0] = 0x5555; /* XXX this is classic Mesa bonghits */
vap_out->vap_vtx_state_cntl = 0x5555; /* XXX this is classic Mesa bonghits */
/* Position. */
if (vs_outputs->pos != ATTR_UNUSED) {
hwfmt[1] |= R300_INPUT_CNTL_POS;
hwfmt[2] |= R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT;
vap_out->vap_vsm_vtx_assm |= R300_INPUT_CNTL_POS;
vap_out->vap_out_vtx_fmt[0] |= R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT;
stream_loc[tabi++] = 0;
} else {
assert(0);
}
/* Point size. */
if (vs_outputs->psize != ATTR_UNUSED) {
hwfmt[2] |= R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT;
}
vap_out->vap_out_vtx_fmt[0] |= R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT;
/* Colors. */
for (i = 0; i < ATTR_COLOR_COUNT; i++) {
if (vs_outputs->color[i] != ATTR_UNUSED || any_bcolor_used ||
vs_outputs->color[1] != ATTR_UNUSED) {
hwfmt[1] |= R300_INPUT_CNTL_COLOR;
hwfmt[2] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT << i;
}
}
/* Back-face colors. */
if (any_bcolor_used) {
for (i = 0; i < ATTR_COLOR_COUNT; i++) {
hwfmt[1] |= R300_INPUT_CNTL_COLOR;
hwfmt[2] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT << (2+i);
}
}
/* Texture coordinates. */
gen_count = 0;
for (i = 0; i < ATTR_GENERIC_COUNT; i++) {
if (vs_outputs->generic[i] != ATTR_UNUSED) {
hwfmt[1] |= (R300_INPUT_CNTL_TC0 << gen_count);
hwfmt[3] |= (4 << (3 * gen_count));
gen_count++;
}
}
/* Fog coordinates. */
if (vs_outputs->fog != ATTR_UNUSED) {
hwfmt[1] |= (R300_INPUT_CNTL_TC0 << gen_count);
hwfmt[3] |= (4 << (3 * gen_count));
gen_count++;
}
/* XXX magic */
assert(gen_count <= 8);
/* WPOS. */
vs->wpos_tex_output = gen_count;
}
/* Sets up stream mapping to equivalent VS outputs if TCL is bypassed
* or isn't present. */
static void r300_stream_locations_notcl(
struct r300_shader_semantics* vs_outputs,
int* stream_loc)
{
int i, tabi = 0, gen_count;
boolean any_bcolor_used = vs_outputs->bcolor[0] != ATTR_UNUSED ||
vs_outputs->bcolor[1] != ATTR_UNUSED;
/* Position. */
stream_loc[tabi++] = 0;
/* Point size. */
if (vs_outputs->psize != ATTR_UNUSED) {
stream_loc[tabi++] = 1;
}
@@ -185,6 +131,9 @@ static void r300_stream_locations_notcl(
for (i = 0; i < ATTR_COLOR_COUNT; i++) {
if (vs_outputs->color[i] != ATTR_UNUSED || any_bcolor_used ||
vs_outputs->color[1] != ATTR_UNUSED) {
vap_out->vap_vsm_vtx_assm |= R300_INPUT_CNTL_COLOR;
vap_out->vap_out_vtx_fmt[0] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT << i;
stream_loc[tabi++] = 2 + i;
}
}
@@ -192,6 +141,9 @@ static void r300_stream_locations_notcl(
/* Back-face colors. */
if (any_bcolor_used) {
for (i = 0; i < ATTR_COLOR_COUNT; i++) {
vap_out->vap_vsm_vtx_assm |= R300_INPUT_CNTL_COLOR;
vap_out->vap_out_vtx_fmt[0] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT << (2+i);
stream_loc[tabi++] = 4 + i;
}
}
@@ -200,6 +152,9 @@ static void r300_stream_locations_notcl(
gen_count = 0;
for (i = 0; i < ATTR_GENERIC_COUNT; i++) {
if (vs_outputs->generic[i] != ATTR_UNUSED) {
vap_out->vap_vsm_vtx_assm |= (R300_INPUT_CNTL_TC0 << gen_count);
vap_out->vap_out_vtx_fmt[1] |= (4 << (3 * gen_count));
assert(tabi < 16);
stream_loc[tabi++] = 6 + gen_count;
gen_count++;
@@ -208,17 +163,22 @@ static void r300_stream_locations_notcl(
/* Fog coordinates. */
if (vs_outputs->fog != ATTR_UNUSED) {
vap_out->vap_vsm_vtx_assm |= (R300_INPUT_CNTL_TC0 << gen_count);
vap_out->vap_out_vtx_fmt[1] |= (4 << (3 * gen_count));
assert(tabi < 16);
stream_loc[tabi++] = 6 + gen_count;
gen_count++;
}
/* XXX magic */
assert(gen_count <= 8);
/* WPOS. */
if (vs_outputs->wpos != ATTR_UNUSED) {
assert(tabi < 16);
stream_loc[tabi++] = 6 + gen_count;
gen_count++;
}
vs->wpos_tex_output = gen_count;
assert(tabi < 16);
stream_loc[tabi++] = 6 + gen_count;
for (; tabi < 16;) {
stream_loc[tabi++] = -1;
@@ -294,26 +254,16 @@ static void set_vertex_inputs_outputs(struct r300_vertex_program_compiler * c)
}
}
static void r300_insert_wpos(struct r300_vertex_program_compiler* c,
struct r300_shader_semantics* outputs)
void r300_vertex_shader_common_init(struct r300_vertex_shader *vs,
const struct pipe_shader_state *shader)
{
int i, lastOutput = 0;
/* Copy state directly into shader. */
vs->state = *shader;
vs->state.tokens = tgsi_dup_tokens(shader->tokens);
tgsi_scan_shader(shader->tokens, &vs->info);
/* 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;
r300_shader_read_vs_outputs(&vs->info, &vs->outputs);
r300_init_vs_output_mapping(vs);
}
void r300_translate_vertex_shader(struct r300_context* r300,
@@ -322,9 +272,6 @@ void r300_translate_vertex_shader(struct r300_context* r300,
struct r300_vertex_program_compiler compiler;
struct tgsi_to_rc ttr;
/* Initialize. */
r300_shader_read_vs_outputs(&vs->info, &vs->outputs);
/* Setup the compiler */
rc_init(&compiler.Base);
@@ -348,10 +295,7 @@ void r300_translate_vertex_shader(struct r300_context* r300,
compiler.SetHwInputOutput = &set_vertex_inputs_outputs;
/* Insert the WPOS output. */
r300_insert_wpos(&compiler, &vs->outputs);
r300_shader_vap_output_fmt(vs);
r300_stream_locations_notcl(&vs->outputs, vs->stream_loc_notcl);
rc_copy_output(&compiler.Base, 0, vs->outputs.wpos);
/* Invoke the compiler */
r3xx_compile_vertex_program(&compiler);
@@ -363,30 +307,29 @@ void r300_translate_vertex_shader(struct r300_context* r300,
/* And, finally... */
rc_destroy(&compiler.Base);
vs->translated = TRUE;
}
boolean r300_vertex_shader_setup_wpos(struct r300_context* r300)
{
struct r300_vertex_shader* vs = r300->vs_state.state;
struct r300_vap_output_state *vap_out = &vs->vap_out;
int tex_output = vs->wpos_tex_output;
uint32_t tex_fmt = R300_INPUT_CNTL_TC0 << tex_output;
uint32_t* hwfmt = vs->hwfmt;
if (r300->fs->inputs.wpos != ATTR_UNUSED) {
/* Enable WPOS in VAP. */
if (!(hwfmt[1] & tex_fmt)) {
hwfmt[1] |= tex_fmt;
hwfmt[3] |= (4 << (3 * tex_output));
if (!(vap_out->vap_vsm_vtx_assm & tex_fmt)) {
vap_out->vap_vsm_vtx_assm |= tex_fmt;
vap_out->vap_out_vtx_fmt[1] |= (4 << (3 * tex_output));
assert(tex_output < 8);
return TRUE;
}
} else {
/* Disable WPOS in VAP. */
if (hwfmt[1] & tex_fmt) {
hwfmt[1] &= ~tex_fmt;
hwfmt[3] &= ~(4 << (3 * tex_output));
if (vap_out->vap_vsm_vtx_assm & tex_fmt) {
vap_out->vap_vsm_vtx_assm &= ~tex_fmt;
vap_out->vap_out_vtx_fmt[1] &= ~(4 << (3 * tex_output));
return TRUE;
}
}
+9 -4
View File
@@ -28,6 +28,7 @@
#include "tgsi/tgsi_scan.h"
#include "radeon_code.h"
#include "r300_context.h"
#include "r300_shader_semantics.h"
struct r300_context;
@@ -38,7 +39,7 @@ struct r300_vertex_shader {
struct tgsi_shader_info info;
struct r300_shader_semantics outputs;
uint hwfmt[4];
struct r300_vap_output_state vap_out;
/* Stream locations for SWTCL or if TCL is bypassed. */
int stream_loc_notcl[16];
@@ -46,13 +47,17 @@ struct r300_vertex_shader {
/* Output stream location for WPOS. */
int wpos_tex_output;
/* Has this shader been translated yet? */
boolean translated;
/* HWTCL-specific. */
/* Machine code (if translated) */
struct r300_vertex_program_code code;
/* SWTCL-specific. */
void *draw_vs;
};
void r300_vertex_shader_common_init(struct r300_vertex_shader *vs,
const struct pipe_shader_state *shader);
void r300_translate_vertex_shader(struct r300_context* r300,
struct r300_vertex_shader* vs);