gallium: fix vertex program output translation/mapping bug
authorBrian Paul <brian.paul@tungstengraphics.com>
Mon, 18 Aug 2008 22:10:01 +0000 (16:10 -0600)
committerBrian Paul <brian.paul@tungstengraphics.com>
Mon, 18 Aug 2008 22:10:01 +0000 (16:10 -0600)
In some cases, the vertex program output's semantic info didn't match up
with the fragment program's input semantic info.  This info is now explicitly
passed into the st_translate_fragment_program() function.

src/mesa/state_tracker/st_atom_shader.c
src/mesa/state_tracker/st_cb_drawpixels.c
src/mesa/state_tracker/st_program.c
src/mesa/state_tracker/st_program.h

index 4fa304ede0fc62c0a85ccdcf87b653e6b3666d38..6594e59e94b0d051b6538caf350bc95660eb0295 100644 (file)
@@ -39,6 +39,7 @@
 
 #include "main/imports.h"
 #include "main/mtypes.h"
+#include "main/macros.h"
 #include "shader/program.h"
 
 #include "pipe/p_context.h"
@@ -71,6 +72,8 @@ struct translated_vertex_program
 
    /** 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;
@@ -176,17 +179,22 @@ find_translated_vp(struct st_context *st,
       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)) {
@@ -195,8 +203,11 @@ find_translated_vp(struct st_context *st,
             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++;
                }
             }
@@ -208,19 +219,27 @@ find_translated_vp(struct st_context *st,
                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
@@ -228,14 +247,33 @@ find_translated_vp(struct st_context *st,
        */
       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
 
@@ -243,7 +281,9 @@ find_translated_vp(struct st_context *st,
 
       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;
 
index db0c9fbd09cdb57c7de25fc9de58226bb928f93a..0c5e21d4ff07c3f53a6bf412ee2f3591b384d8a2 100644 (file)
@@ -294,7 +294,7 @@ st_make_passthrough_vertex_shader(struct st_context *st, GLboolean passColor)
    }
 
    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;
 
index 59314a32322d3eb812d74a085d7516d8aa01e4aa..325d95e8658ba7a4a30e5710e4de23167834cd20 100644 (file)
@@ -71,15 +71,17 @@ mem_dup(const void *src, uint size)
 
 /**
  * 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];
@@ -172,6 +174,20 @@ st_translate_vertex_program(struct st_context *st,
       }
    }
 
+#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;
@@ -203,10 +219,6 @@ st_translate_vertex_program(struct st_context *st,
             defaultOutputMapping[attr] = slot;
          }
 
-         /*
-         printf("Output %u -> slot %u\n", attr, slot);
-         */
-
          switch (attr) {
          case VERT_RESULT_HPOS:
             assert(slot == 0);
@@ -248,15 +260,21 @@ st_translate_vertex_program(struct st_context *st,
          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++;
+            }
          }
       }
    }
@@ -347,8 +365,6 @@ st_translate_fragment_program(struct st_context *st,
    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];
@@ -378,23 +394,23 @@ st_translate_fragment_program(struct st_context *st,
 
          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:
@@ -405,15 +421,15 @@ st_translate_fragment_program(struct st_context *st,
          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;
          }
       }
@@ -467,8 +483,8 @@ st_translate_fragment_program(struct st_context *st,
                                 /* 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,
index 086e9391aa956f8443aaf8264b384e53175f5c8b..078e2c42a6960bf60c8cb9d34e6384e37e7ccb3d 100644 (file)
@@ -58,6 +58,9 @@ struct st_fragment_program
    /** 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;
 
@@ -143,6 +146,9 @@ st_translate_fragment_program(struct st_context *st,
 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