r300g: share the VS-output-mapping state with SWTCL
And associated cleanups.
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user