#include "main/imports.h"
#include "main/mtypes.h"
+#include "main/macros.h"
#include "shader/program.h"
#include "pipe/p_context.h"
/** Maps VERT_RESULT_x to slot */
GLuint output_to_slot[VERT_RESULT_MAX];
+ ubyte output_to_semantic_name[VERT_RESULT_MAX];
+ ubyte output_to_semantic_index[VERT_RESULT_MAX];
/** Pointer to the translated vertex program */
struct st_vertex_program *vp;
const GLbitfield outputsWritten = stvp->Base.Base.OutputsWritten;
GLuint numVpOuts = 0;
GLboolean emitPntSize = GL_FALSE, emitBFC0 = GL_FALSE, emitBFC1 = GL_FALSE;
+ GLint maxGeneric;
/* Compute mapping of vertex program outputs to slots, which depends
* on the fragment program's input->slot mapping.
*/
for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
- /* set default: */
+ /* set defaults: */
xvp->output_to_slot[outAttr] = UNUSED;
+ xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_COUNT;
+ xvp->output_to_semantic_index[outAttr] = 99;
if (outAttr == VERT_RESULT_HPOS) {
/* always put xformed position into slot zero */
xvp->output_to_slot[VERT_RESULT_HPOS] = 0;
+ xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_POSITION;
+ xvp->output_to_semantic_index[outAttr] = 0;
numVpOuts++;
}
else if (outputsWritten & (1 << outAttr)) {
if (fpInAttrib >= 0) {
GLuint fpInSlot = stfp->input_to_slot[fpInAttrib];
if (fpInSlot != ~0) {
+ /* match this vp output to the fp input */
GLuint vpOutSlot = stfp->input_map[fpInSlot];
xvp->output_to_slot[outAttr] = vpOutSlot;
+ xvp->output_to_semantic_name[outAttr] = stfp->input_semantic_name[fpInSlot];
+ xvp->output_to_semantic_index[outAttr] = stfp->input_semantic_index[fpInSlot];
numVpOuts++;
}
}
emitBFC1 = GL_TRUE;
}
#if 0 /*debug*/
- printf("assign output_to_slot[%d] = %d\n", outAttr,
+ printf("assign vp output_to_slot[%d] = %d\n", outAttr,
xvp->output_to_slot[outAttr]);
#endif
}
/* must do these last */
- if (emitPntSize)
+ if (emitPntSize) {
xvp->output_to_slot[VERT_RESULT_PSIZ] = numVpOuts++;
- if (emitBFC0)
+ xvp->output_to_semantic_name[VERT_RESULT_PSIZ] = TGSI_SEMANTIC_PSIZE;
+ xvp->output_to_semantic_index[VERT_RESULT_PSIZ] = 0;
+ }
+ if (emitBFC0) {
xvp->output_to_slot[VERT_RESULT_BFC0] = numVpOuts++;
- if (emitBFC1)
+ xvp->output_to_semantic_name[VERT_RESULT_BFC0] = TGSI_SEMANTIC_COLOR;
+ xvp->output_to_semantic_index[VERT_RESULT_BFC0] = 0;
+ }
+ if (emitBFC1) {
xvp->output_to_slot[VERT_RESULT_BFC1] = numVpOuts++;
-
+ xvp->output_to_semantic_name[VERT_RESULT_BFC0] = TGSI_SEMANTIC_COLOR;
+ xvp->output_to_semantic_index[VERT_RESULT_BFC0] = 1;
+ }
/* Unneeded vertex program outputs will go to this slot.
* We could use this info to do dead code elimination in the
*/
dummySlot = numVpOuts;
- /* Map vert program outputs that aren't used to the dummy slot */
+ /* find max GENERIC slot index */
+ maxGeneric = -1;
+ for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
+ if (xvp->output_to_semantic_name[outAttr] == TGSI_SEMANTIC_GENERIC) {
+ maxGeneric = MAX2(maxGeneric,
+ xvp->output_to_semantic_index[outAttr]);
+ }
+ }
+
+ /* Map vert program outputs that aren't used to the dummy slot
+ * (and an unused generic attribute slot).
+ */
for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
if (outputsWritten & (1 << outAttr)) {
- if (xvp->output_to_slot[outAttr] == UNUSED)
+ if (xvp->output_to_slot[outAttr] == UNUSED) {
xvp->output_to_slot[outAttr] = dummySlot;
+ xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_GENERIC;
+ xvp->output_to_semantic_index[outAttr] = maxGeneric + 1;
+ }
+
+ assert(xvp->output_to_semantic_name[outAttr] != TGSI_SEMANTIC_COUNT);
+ assert(xvp->output_to_semantic_index[outAttr] != 99);
}
+
+
#if 0 /*debug*/
- printf("output_to_slot[%d] = %d\n", outAttr,
+ printf("vp output_to_slot[%d] = %d\n", outAttr,
xvp->output_to_slot[outAttr]);
#endif
assert(stvp->Base.Base.NumInstructions > 1);
- st_translate_vertex_program(st, stvp, xvp->output_to_slot);
+ st_translate_vertex_program(st, stvp, xvp->output_to_slot,
+ xvp->output_to_semantic_name,
+ xvp->output_to_semantic_index);
xvp->vp = stvp;
}
stvp = (struct st_vertex_program *) p;
- st_translate_vertex_program(st, stvp, NULL);
+ st_translate_vertex_program(st, stvp, NULL, NULL, NULL);
st->drawpix.vert_shaders[passColor] = stvp;
/**
* Translate a Mesa vertex shader into a TGSI shader.
- * \param outputMapping to map vertex program output registers to TGSI
- * output slots
+ * \param outputMapping to map vertex program output registers (VERT_RESULT_x)
+ * to TGSI output slots
* \param tokensOut destination for TGSI tokens
* \return pointer to cached pipe_shader object.
*/
void
st_translate_vertex_program(struct st_context *st,
struct st_vertex_program *stvp,
- const GLuint outputMapping[])
+ const GLuint outputMapping[],
+ const ubyte *outputSemanticName,
+ const ubyte *outputSemanticIndex)
{
struct pipe_context *pipe = st->pipe;
struct tgsi_token tokens[ST_MAX_SHADER_TOKENS];
}
}
+#if 0
+ if (outputMapping && outputSemanticName) {
+ printf("VERT_RESULT written out_slot semantic_name semantic_index\n");
+ for (attr = 0; attr < VERT_RESULT_MAX; attr++) {
+ printf(" %-2d %c %3d %2d %2d\n",
+ attr,
+ ((stvp->Base.Base.OutputsWritten & (1 << attr)) ? 'Y' : ' '),
+ outputMapping[attr],
+ outputSemanticName[attr],
+ outputSemanticIndex[attr]);
+ }
+ }
+#endif
+
/* initialize output semantics to defaults */
for (i = 0; i < PIPE_MAX_SHADER_OUTPUTS; i++) {
vs_output_semantic_name[i] = TGSI_SEMANTIC_GENERIC;
defaultOutputMapping[attr] = slot;
}
- /*
- printf("Output %u -> slot %u\n", attr, slot);
- */
-
switch (attr) {
case VERT_RESULT_HPOS:
assert(slot == 0);
case VERT_RESULT_TEX5:
case VERT_RESULT_TEX6:
case VERT_RESULT_TEX7:
- vs_output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
- vs_output_semantic_index[slot] = num_generic++;
- break;
+ /* fall-through */
case VERT_RESULT_VAR0:
/* fall-through */
default:
- assert(attr - VERT_RESULT_VAR0 < MAX_VARYING);
- vs_output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
- vs_output_semantic_index[slot] = num_generic++;
+ if (outputSemanticName) {
+ /* use provided semantic into */
+ assert(outputSemanticName[attr] != TGSI_SEMANTIC_COUNT);
+ vs_output_semantic_name[slot] = outputSemanticName[attr];
+ vs_output_semantic_index[slot] = outputSemanticIndex[attr];
+ }
+ else {
+ /* use default semantic info */
+ vs_output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+ vs_output_semantic_index[slot] = num_generic++;
+ }
}
}
}
GLuint num_generic = 0;
GLuint num_tokens;
- ubyte fs_input_semantic_name[PIPE_MAX_SHADER_INPUTS];
- ubyte fs_input_semantic_index[PIPE_MAX_SHADER_INPUTS];
uint fs_num_inputs = 0;
ubyte fs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS];
switch (attr) {
case FRAG_ATTRIB_WPOS:
- fs_input_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
- fs_input_semantic_index[slot] = 0;
+ stfp->input_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
+ stfp->input_semantic_index[slot] = 0;
interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
break;
case FRAG_ATTRIB_COL0:
- fs_input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
- fs_input_semantic_index[slot] = 0;
+ stfp->input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+ stfp->input_semantic_index[slot] = 0;
interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
break;
case FRAG_ATTRIB_COL1:
- fs_input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
- fs_input_semantic_index[slot] = 1;
+ stfp->input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+ stfp->input_semantic_index[slot] = 1;
interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
break;
case FRAG_ATTRIB_FOGC:
- fs_input_semantic_name[slot] = TGSI_SEMANTIC_FOG;
- fs_input_semantic_index[slot] = 0;
+ stfp->input_semantic_name[slot] = TGSI_SEMANTIC_FOG;
+ stfp->input_semantic_index[slot] = 0;
interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
break;
case FRAG_ATTRIB_TEX0:
case FRAG_ATTRIB_TEX5:
case FRAG_ATTRIB_TEX6:
case FRAG_ATTRIB_TEX7:
- fs_input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
- fs_input_semantic_index[slot] = num_generic++;
+ stfp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+ stfp->input_semantic_index[slot] = num_generic++;
interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
break;
case FRAG_ATTRIB_VAR0:
/* fall-through */
default:
- fs_input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
- fs_input_semantic_index[slot] = num_generic++;
+ stfp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+ stfp->input_semantic_index[slot] = num_generic++;
interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
}
}
/* inputs */
fs_num_inputs,
inputMapping,
- fs_input_semantic_name,
- fs_input_semantic_index,
+ stfp->input_semantic_name,
+ stfp->input_semantic_index,
interpMode,
/* outputs */
fs_num_outputs,
/** map FP input back to VP output */
GLuint input_map[PIPE_MAX_SHADER_INPUTS];
+ ubyte input_semantic_name[PIPE_MAX_SHADER_INPUTS];
+ ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS];
+
struct pipe_shader_state state;
void *driver_shader;
extern void
st_translate_vertex_program(struct st_context *st,
struct st_vertex_program *vp,
- const GLuint vert_output_to_slot[]);
+ const GLuint vert_output_to_slot[],
+ const ubyte *fs_input_semantic_name,
+ const ubyte *fs_input_semantic_index);
+
#endif