Translate mesa vertex/fragment programs to TGSI programs at same time to do proper...
authorBrian <brian.paul@tungstengraphics.com>
Tue, 25 Sep 2007 20:29:11 +0000 (14:29 -0600)
committerBrian <brian.paul@tungstengraphics.com>
Tue, 25 Sep 2007 20:29:11 +0000 (14:29 -0600)
Previously, programs were translated independently during validation.
The problem is the translation to TGSI format, which packs shader
input/outputs into continuous slots, depends on which vertex program is
being paired with which fragment shader.  Now, we look at the outputs
of the vertex program in conjunction with the inputs of the fragment shader
to be sure the attributes match up correctly.

The new 'linked_program_pair' class keeps track of the associations
between vertex and fragment shaders.  It's also the place where the TGSI
tokens are kept since they're no longer per-program state but per-linkage.

Still a few loose ends, like implementing some kind of hash/lookup table
for linked_program_pairs.

14 files changed:
src/mesa/pipe/draw/draw_feedback.c
src/mesa/pipe/tgsi/mesa/mesa_to_tgsi.c
src/mesa/sources
src/mesa/state_tracker/st_atom.c
src/mesa/state_tracker/st_atom.h
src/mesa/state_tracker/st_atom_fs.c
src/mesa/state_tracker/st_atom_vs.c
src/mesa/state_tracker/st_cb_clear.c
src/mesa/state_tracker/st_cb_drawpixels.c
src/mesa/state_tracker/st_cb_feedback.c
src/mesa/state_tracker/st_cb_program.c
src/mesa/state_tracker/st_cb_rasterpos.c
src/mesa/state_tracker/st_context.h
src/mesa/state_tracker/st_program.h

index 3b8400233ed694eb29a7e5856fd4cf1c56c6b08b..ee54db0ad5c1cd0121a48697a082b5f55352570b 100644 (file)
@@ -78,11 +78,9 @@ feedback_vertex(struct draw_stage *stage, const struct vertex_header *vertex)
     * we can either address output buffer 0 (for interleaving) or
     * output buffer i (for non-interleaved).
     */
-#if 0
    for (i = 0; i < feedback->num_attribs; i++) {
-      const uint attr = feedback->attrib[i];
-      const uint slot = stage->draw->vertex_info.attrib_to_slot[attr];
-      const float *src = attr ? vertex->data[slot] : vertex->clip;
+      const uint slot = feedback->attrib[i];
+      const float *src = slot ? vertex->data[slot] : vertex->clip;
       const uint size = feedback->size[i];
       float *dest = fs->dest[i * select];
 
@@ -104,7 +102,6 @@ feedback_vertex(struct draw_stage *stage, const struct vertex_header *vertex)
       }
       fs->dest[i * select] += size;
    }
-#endif
 
    fs->num_vert_emitted++;
 }
index d0d97ab0f87b02c87fbcd6366388a4e6ed9afca2..fa27fd3cd0751ef239205ad7558b78c9f960910d 100644 (file)
@@ -476,6 +476,8 @@ make_input_decl(
 {\r
    struct tgsi_full_declaration decl;\r
 \r
+   assert(semantic_name < TGSI_SEMANTIC_COUNT);\r
+\r
    decl = tgsi_default_full_declaration();\r
    decl.Declaration.File = TGSI_FILE_INPUT;\r
    decl.Declaration.Declare = TGSI_DECLARE_RANGE;\r
@@ -500,6 +502,8 @@ make_output_decl(
 {\r
    struct tgsi_full_declaration decl;\r
 \r
+   assert(semantic_name < TGSI_SEMANTIC_COUNT);\r
+\r
    decl = tgsi_default_full_declaration();\r
    decl.Declaration.File = TGSI_FILE_OUTPUT;\r
    decl.Declaration.Declare = TGSI_DECLARE_RANGE;\r
index 0d4fdc15f490e9c87e1097f9eaa86dd1f1ef9741..985bd2dce6f2f68c5d92e6a7b963728045b91932 100644 (file)
@@ -200,14 +200,13 @@ STATETRACKER_SOURCES = \
        state_tracker/st_atom_depth.c \
        state_tracker/st_atom_fixedfunction.c \
        state_tracker/st_atom_framebuffer.c \
-       state_tracker/st_atom_fs.c \
        state_tracker/st_atom_sampler.c \
        state_tracker/st_atom_scissor.c \
+       state_tracker/st_atom_shader.c \
        state_tracker/st_atom_rasterizer.c \
        state_tracker/st_atom_stipple.c \
        state_tracker/st_atom_texture.c \
        state_tracker/st_atom_viewport.c \
-       state_tracker/st_atom_vs.c \
        state_tracker/st_cb_bufferobjects.c \
        state_tracker/st_cb_clear.c \
        state_tracker/st_cb_flush.c \
@@ -224,6 +223,7 @@ STATETRACKER_SOURCES = \
        state_tracker/st_context.c \
        state_tracker/st_draw.c \
        state_tracker/st_format.c \
+       state_tracker/st_program.c \
        state_tracker/st_mipmap_tree.c
 
 SHADER_SOURCES = \
index fc339b91ed7c41c67fad3a4254b68013c892a369..326042cb34c8142f8525d5ef0b648af2a073711c 100644 (file)
@@ -50,8 +50,7 @@ static const struct st_tracked_state *atoms[] =
    &st_update_clip,
 
    &st_update_tnl,
-   &st_update_vs,
-   &st_update_fs,
+   &st_update_shader,
 
    &st_update_rasterizer,
    &st_update_polygon_stipple,
index 6710c1a26956eafcf70468c7ac7c7be070960755..94cb7bee7a7ebd29dec4e780ce9dd655aab7d0fc 100644 (file)
@@ -49,8 +49,7 @@ const struct st_tracked_state st_update_clip;
 const struct st_tracked_state st_update_clear_color;
 const struct st_tracked_state st_update_depth_stencil;
 const struct st_tracked_state st_update_tnl;
-const struct st_tracked_state st_update_fs;
-const struct st_tracked_state st_update_vs;
+const struct st_tracked_state st_update_shader;
 const struct st_tracked_state st_update_rasterizer;
 const struct st_tracked_state st_update_polygon_stipple;
 const struct st_tracked_state st_update_viewport;
index dd4cdf0855eb8cb29e908fd99ef467eb2fb4baa4..28019858f795e8fc522cb1f95a64238273b8db49 100644 (file)
  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  * 
  **************************************************************************/
- /*
-  * Authors:
-  *   Keith Whitwell <keith@tungstengraphics.com>
-  *   Brian Paul
-  */
+
+/*
+ * Authors:
+ *   Keith Whitwell <keith@tungstengraphics.com>
+ *   Brian Paul
+ */
 
 #include "shader/prog_parameter.h"
 
 
 /**
  * Translate a Mesa fragment shader into a TGSI shader.
+ * \param inputMapping  to map fragment program input registers to TGSI
+ *                      input slots
+ * \param tokensOut  destination for TGSI tokens
  * \return  pointer to cached pipe_shader object.
  */
 const struct cso_fragment_shader *
-st_translate_fragment_shader(struct st_context *st,
-                           struct st_fragment_program *stfp)
+st_translate_fragment_shader(const struct st_context *st,
+                             struct st_fragment_program *stfp,
+                             const GLuint inputMapping[],
+                             struct tgsi_token *tokensOut,
+                             GLuint maxTokens)
 {
    GLuint outputMapping[FRAG_RESULT_MAX];
-   GLuint inputMapping[PIPE_MAX_SHADER_INPUTS];
+   GLuint defaultInputMapping[FRAG_ATTRIB_MAX];
    struct pipe_shader_state fs;
    const struct cso_fragment_shader *cso;
    GLuint interpMode[16];  /* XXX size? */
@@ -67,6 +74,7 @@ st_translate_fragment_shader(struct st_context *st,
    /* Check if all fragment programs need the fragment position (in order
     * to do perspective-corrected interpolation).
     */
+   /* XXX temporary! */
    if (st->pipe->get_param(st->pipe, PIPE_PARAM_FS_NEEDS_POS))
       inputsRead |= FRAG_BIT_WPOS;
 
@@ -77,28 +85,32 @@ st_translate_fragment_shader(struct st_context *st,
     */
    for (attr = 0; attr < FRAG_ATTRIB_MAX; attr++) {
       if (inputsRead & (1 << attr)) {
-         inputMapping[attr] = fs.num_inputs;
+         const GLuint slot = fs.num_inputs;
+
+         fs.num_inputs++;
+
+         defaultInputMapping[attr] = slot;
 
          switch (attr) {
          case FRAG_ATTRIB_WPOS:
-            fs.input_semantic_name[fs.num_inputs] = TGSI_SEMANTIC_POSITION;
-            fs.input_semantic_index[fs.num_inputs] = 0;
-            interpMode[fs.num_inputs] = TGSI_INTERPOLATE_CONSTANT;
+            fs.input_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
+            fs.input_semantic_index[slot] = 0;
+            interpMode[slot] = TGSI_INTERPOLATE_CONSTANT;
             break;
          case FRAG_ATTRIB_COL0:
-            fs.input_semantic_name[fs.num_inputs] = TGSI_SEMANTIC_COLOR;
-            fs.input_semantic_index[fs.num_inputs] = 0;
-            interpMode[fs.num_inputs] = TGSI_INTERPOLATE_LINEAR;
+            fs.input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+            fs.input_semantic_index[slot] = 0;
+            interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
             break;
          case FRAG_ATTRIB_COL1:
-            fs.input_semantic_name[fs.num_inputs] = TGSI_SEMANTIC_COLOR;
-            fs.input_semantic_index[fs.num_inputs] = 1;
-            interpMode[fs.num_inputs] = TGSI_INTERPOLATE_LINEAR;
+            fs.input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+            fs.input_semantic_index[slot] = 1;
+            interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
             break;
          case FRAG_ATTRIB_FOGC:
-            fs.input_semantic_name[fs.num_inputs] = TGSI_SEMANTIC_FOG;
-            fs.input_semantic_index[fs.num_inputs] = 0;
-            interpMode[fs.num_inputs] = TGSI_INTERPOLATE_PERSPECTIVE;
+            fs.input_semantic_name[slot] = TGSI_SEMANTIC_FOG;
+            fs.input_semantic_index[slot] = 0;
+            interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
             break;
          case FRAG_ATTRIB_TEX0:
          case FRAG_ATTRIB_TEX1:
@@ -108,19 +120,17 @@ st_translate_fragment_shader(struct st_context *st,
          case FRAG_ATTRIB_TEX5:
          case FRAG_ATTRIB_TEX6:
          case FRAG_ATTRIB_TEX7:
-            fs.input_semantic_name[fs.num_inputs] = TGSI_SEMANTIC_GENERIC;
-            fs.input_semantic_index[fs.num_inputs] = attr - FRAG_ATTRIB_TEX0;
-            interpMode[fs.num_inputs] = TGSI_INTERPOLATE_PERSPECTIVE;
+            fs.input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+            fs.input_semantic_index[slot] = attr - FRAG_ATTRIB_TEX0;
+            interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
             break;
          case FRAG_ATTRIB_VAR0:
             /* fall-through */
          default:
-            fs.input_semantic_name[fs.num_inputs] = TGSI_SEMANTIC_GENERIC;
-            fs.input_semantic_index[fs.num_inputs] = attr - FRAG_ATTRIB_VAR0;
-            interpMode[fs.num_inputs] = TGSI_INTERPOLATE_PERSPECTIVE;
+            fs.input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+            fs.input_semantic_index[slot] = attr - FRAG_ATTRIB_VAR0;
+            interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
          }
-
-         fs.num_inputs++;
       }
    }
 
@@ -145,35 +155,40 @@ st_translate_fragment_shader(struct st_context *st,
       }
    }
 
+   if (!inputMapping)
+      inputMapping = defaultInputMapping;
+
    /* XXX: fix static allocation of tokens:
     */
    tgsi_mesa_compile_fp_program( &stfp->Base,
+                                 /* inputs */
                                  fs.num_inputs,
                                  inputMapping,
                                  fs.input_semantic_name,
                                  fs.input_semantic_index,
                                  interpMode,
+                                 /* outputs */
                                  outputMapping,
-                                 stfp->tokens, ST_FP_MAX_TOKENS );
+                                 /* tokenized result */
+                                 tokensOut, maxTokens);
+
 
-   fs.tokens = &stfp->tokens[0];
+   fs.tokens = tokensOut;
 
    cso = st_cached_fs_state(st, &fs);
    stfp->fs = cso;
 
    if (TGSI_DEBUG)
-      tgsi_dump( stfp->tokens, 0/*TGSI_DUMP_VERBOSE*/ );
+      tgsi_dump( tokensOut, 0/*TGSI_DUMP_VERBOSE*/ );
 
 #if defined(USE_X86_ASM) || defined(SLANG_X86)
    if (stfp->sse2_program.csr == stfp->sse2_program.store)
-      tgsi_emit_sse2_fs( stfp->tokens, &stfp->sse2_program );
+      tgsi_emit_sse2_fs( tokensOut, &stfp->sse2_program );
 
    if (!cso->state.executable)
       ((struct cso_fragment_shader*)cso)->state.executable = (void *) x86_get_func( &stfp->sse2_program );
 #endif
 
-   stfp->dirty = 0;
-
    return cso;
 }
 
@@ -200,8 +215,9 @@ static void update_fs( struct st_context *st )
    }
 
    /* if new binding, or shader has changed */
-   if (st->fp != stfp || stfp->dirty) {
+   if (st->fp != stfp /**|| stfp->dirty**/) {
 
+#if 0
       if (stfp->dirty)
          (void) st_translate_fragment_shader( st, stfp );
 
@@ -210,10 +226,17 @@ static void update_fs( struct st_context *st )
       st->state.fs = stfp->fs;
 
       st->pipe->bind_fs_state(st->pipe, st->state.fs->data);
+#else
+
+      /* NEW */
+      st->dirty.st |= ST_NEW_LINKAGE;
+
+#endif
    }
 }
 
 
+#if 0
 const struct st_tracked_state st_update_fs = {
    .name = "st_update_fs",
    .dirty = {
@@ -222,3 +245,4 @@ const struct st_tracked_state st_update_fs = {
    },
    .update = update_fs
 };
+#endif
index a6c0d159d44c24f8f8746ab83187cd86efe4651b..0f07906a9683439e4c7c77230a76bab42abe3846 100644 (file)
 
 /**
  * Translate a Mesa vertex shader into a TGSI shader.
+ * \param outputMapping  to map vertex program output registers to TGSI
+ *                       output slots
+ * \param tokensOut  destination for TGSI tokens
  * \return  pointer to cached pipe_shader object.
  */
 const struct cso_vertex_shader *
-st_translate_vertex_shader(struct st_context *st,
-                           struct st_vertex_program *stvp)
+st_translate_vertex_shader(const struct st_context *st,
+                           struct st_vertex_program *stvp,
+                           const GLuint outputMapping[],
+                           struct tgsi_token *tokensOut,
+                           GLuint maxTokens)
 {
+   GLuint defaultOutputMapping[VERT_RESULT_MAX];
    struct pipe_shader_state vs;
    const struct cso_vertex_shader *cso;
-   GLuint attr;
+   GLuint attr, i;
 
    memset(&vs, 0, sizeof(vs));
 
@@ -69,31 +76,36 @@ st_translate_vertex_shader(struct st_context *st,
     */
    for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
       if (stvp->Base.Base.InputsRead & (1 << attr)) {
-         stvp->input_to_index[attr] = vs.num_inputs;
-         stvp->index_to_input[vs.num_inputs] = attr;
+         const GLuint slot = vs.num_inputs;
+
+         vs.num_inputs++;
+
+         stvp->input_to_index[attr] = slot;
+         stvp->index_to_input[slot] = attr;
+
          switch (attr) {
          case VERT_ATTRIB_POS:
-            vs.input_semantic_name[vs.num_inputs] = TGSI_SEMANTIC_POSITION;
-            vs.input_semantic_index[vs.num_inputs] = 0;
+            vs.input_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
+            vs.input_semantic_index[slot] = 0;
             break;
          case VERT_ATTRIB_WEIGHT:
             /* fall-through */
          case VERT_ATTRIB_NORMAL:
             /* just label as a generic */
-            vs.input_semantic_name[vs.num_inputs] = TGSI_SEMANTIC_GENERIC;
-            vs.input_semantic_index[vs.num_inputs] = 0;
+            vs.input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+            vs.input_semantic_index[slot] = 0;
             break;
          case VERT_ATTRIB_COLOR0:
-            vs.input_semantic_name[vs.num_inputs] = TGSI_SEMANTIC_COLOR;
-            vs.input_semantic_index[vs.num_inputs] = 0;
+            vs.input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+            vs.input_semantic_index[slot] = 0;
             break;
          case VERT_ATTRIB_COLOR1:
-            vs.input_semantic_name[vs.num_inputs] = TGSI_SEMANTIC_COLOR;
-            vs.input_semantic_index[vs.num_inputs] = 1;
+            vs.input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+            vs.input_semantic_index[slot] = 1;
             break;
          case VERT_ATTRIB_FOG:
-            vs.input_semantic_name[vs.num_inputs] = TGSI_SEMANTIC_FOG;
-            vs.input_semantic_index[vs.num_inputs] = 0;
+            vs.input_semantic_name[slot] = TGSI_SEMANTIC_FOG;
+            vs.input_semantic_index[slot] = 0;
             break;
          case VERT_ATTRIB_TEX0:
          case VERT_ATTRIB_TEX1:
@@ -103,8 +115,8 @@ st_translate_vertex_shader(struct st_context *st,
          case VERT_ATTRIB_TEX5:
          case VERT_ATTRIB_TEX6:
          case VERT_ATTRIB_TEX7:
-            vs.input_semantic_name[vs.num_inputs] = TGSI_SEMANTIC_GENERIC;
-            vs.input_semantic_index[vs.num_inputs] = attr - VERT_ATTRIB_TEX0;
+            vs.input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+            vs.input_semantic_index[slot] = attr - VERT_ATTRIB_TEX0;
             break;
          case VERT_ATTRIB_GENERIC0:
          case VERT_ATTRIB_GENERIC1:
@@ -115,53 +127,71 @@ st_translate_vertex_shader(struct st_context *st,
          case VERT_ATTRIB_GENERIC6:
          case VERT_ATTRIB_GENERIC7:
             assert(attr < VERT_ATTRIB_MAX);
-            vs.input_semantic_name[vs.num_inputs] = TGSI_SEMANTIC_GENERIC;
-            vs.input_semantic_index[vs.num_inputs] = attr - VERT_ATTRIB_GENERIC0;
+            vs.input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+            vs.input_semantic_index[slot] = attr - VERT_ATTRIB_GENERIC0;
             break;
          default:
             assert(0);
          }
-         vs.num_inputs++;
       }
    }
 
+   /* initialize output semantics to defaults */
+   for (i = 0; i < PIPE_MAX_SHADER_OUTPUTS; i++) {
+      vs.output_semantic_name[i] = TGSI_SEMANTIC_GENERIC;
+      vs.output_semantic_index[i] = 0;
+   }
+
    /*
-    * Determine number of outputs, the register mapping and
-    * the semantic information for each vertex output/result.
+    * Determine number of outputs, the (default) output register
+    * mapping and the semantic information for each output.
     */
    for (attr = 0; attr < VERT_RESULT_MAX; attr++) {
       if (stvp->Base.Base.OutputsWritten & (1 << attr)) {
-         /* put this attrib in the next available slot */
-         st->vertex_attrib_to_slot[attr] = vs.num_outputs;
+         GLuint slot;
+
+         if (outputMapping) {
+            slot = outputMapping[attr];
+            assert(slot != ~0);
+         }
+         else {
+            slot = vs.num_outputs;
+            vs.num_outputs++;
+            defaultOutputMapping[attr] = slot;
+         }
+
+         /*
+         printf("Output %u -> slot %u\n", attr, slot);
+         */
 
          switch (attr) {
          case VERT_RESULT_HPOS:
-            vs.output_semantic_name[vs.num_outputs] = TGSI_SEMANTIC_POSITION;
-            vs.output_semantic_index[vs.num_outputs] = 0;
+            vs.output_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
+            vs.output_semantic_index[slot] = 0;
             break;
          case VERT_RESULT_COL0:
-            vs.output_semantic_name[vs.num_outputs] = TGSI_SEMANTIC_COLOR;
-            vs.output_semantic_index[vs.num_outputs] = 0;
+            vs.output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+            vs.output_semantic_index[slot] = 0;
             break;
          case VERT_RESULT_COL1:
-            vs.output_semantic_name[vs.num_outputs] = TGSI_SEMANTIC_COLOR;
-            vs.output_semantic_index[vs.num_outputs] = 1;
+            vs.output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
+            vs.output_semantic_index[slot] = 1;
             break;
          case VERT_RESULT_BFC0:
-            vs.output_semantic_name[vs.num_outputs] = TGSI_SEMANTIC_BCOLOR;
-            vs.output_semantic_index[vs.num_outputs] = 0;
+            vs.output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
+            vs.output_semantic_index[slot] = 0;
             break;
          case VERT_RESULT_BFC1:
-            vs.output_semantic_name[vs.num_outputs] = TGSI_SEMANTIC_BCOLOR;
-            vs.output_semantic_index[vs.num_outputs] = 1;
+            vs.output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
+            vs.output_semantic_index[slot] = 1;
             break;
          case VERT_RESULT_FOGC:
-            vs.output_semantic_name[vs.num_outputs] = TGSI_SEMANTIC_FOG;
-            vs.output_semantic_index[vs.num_outputs] = 0;
+            vs.output_semantic_name[slot] = TGSI_SEMANTIC_FOG;
+            vs.output_semantic_index[slot] = 0;
             break;
          case VERT_RESULT_PSIZ:
-            vs.output_semantic_name[vs.num_outputs] = TGSI_SEMANTIC_PSIZE;
-            vs.output_semantic_index[vs.num_outputs] = 0;
+            vs.output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE;
+            vs.output_semantic_index[slot] = 0;
             break;
          case VERT_RESULT_EDGE:
             assert(0);
@@ -174,46 +204,59 @@ st_translate_vertex_shader(struct st_context *st,
          case VERT_RESULT_TEX5:
          case VERT_RESULT_TEX6:
          case VERT_RESULT_TEX7:
-            vs.output_semantic_name[vs.num_outputs] = TGSI_SEMANTIC_GENERIC;
-            vs.output_semantic_index[vs.num_outputs] = attr - VERT_RESULT_TEX0;
+            vs.output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+            vs.output_semantic_index[slot] = attr - VERT_RESULT_TEX0;
             break;
          case VERT_RESULT_VAR0:
             /* fall-through */
          default:
             assert(attr - VERT_RESULT_VAR0 < MAX_VARYING);
-            vs.output_semantic_name[vs.num_outputs] = TGSI_SEMANTIC_GENERIC;
-            vs.output_semantic_index[vs.num_outputs] = attr - VERT_RESULT_VAR0;
+            vs.output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
+            vs.output_semantic_index[slot] = attr - VERT_RESULT_VAR0;
          }
-
-         vs.num_outputs++;
       }
    }
 
 
+   if (outputMapping) {
+      /* find max output slot referenced to compute vs.num_outputs */
+      GLuint maxSlot = 0;
+      for (attr = 0; attr < VERT_RESULT_MAX; attr++) {
+         if (outputMapping[attr] != ~0 && outputMapping[attr] > maxSlot)
+            maxSlot = outputMapping[attr];
+      }
+      vs.num_outputs = maxSlot + 1;
+   }
+   else {
+      outputMapping = defaultOutputMapping;
+   }
+
    /* XXX: fix static allocation of tokens:
     */
    tgsi_mesa_compile_vp_program( &stvp->Base,
+                                 /* inputs */
                                  vs.num_inputs,
                                  stvp->input_to_index,
                                  vs.input_semantic_name,
                                  vs.input_semantic_index,
+                                 /* outputs */
                                  vs.num_outputs,
-                                 st->vertex_attrib_to_slot,
+                                 outputMapping,
                                  vs.output_semantic_name,
                                  vs.output_semantic_index,
-                                 stvp->tokens, ST_FP_MAX_TOKENS );
-
-   vs.tokens = &stvp->tokens[0];
+                                 /* tokenized result */
+                                 tokensOut, maxTokens);
 
+   vs.tokens = tokensOut;
    cso = st_cached_vs_state(st, &vs);
    stvp->vs = cso;
 
    if (TGSI_DEBUG)
-      tgsi_dump( stvp->tokens, 0 );
+      tgsi_dump( tokensOut, 0 );
 
 #if defined(USE_X86_ASM) || defined(SLANG_X86)
    if (stvp->sse2_program.csr == stvp->sse2_program.store)
-      tgsi_emit_sse2( stvp->tokens, &stvp->sse2_program );
+      tgsi_emit_sse2( tokensOut, &stvp->sse2_program );
 
    if (!cso->state.executable)
       ((struct cso_vertex_shader*)cso)->state.executable = (void *) x86_get_func( &stvp->sse2_program );
@@ -246,6 +289,7 @@ static void update_vs( struct st_context *st )
    }
 
    if (st->vp != stvp || stvp->dirty) {
+#if 0
       if (stvp->dirty)
          (void) st_translate_vertex_shader( st, stvp );
 
@@ -260,10 +304,15 @@ static void update_vs( struct st_context *st )
          tgsi_dump( stvp->tokens, 0 );
 #endif
       st->pipe->bind_vs_state(st->pipe, st->state.vs->data);
+#else
+      /* NEW */
+      st->dirty.st |= ST_NEW_LINKAGE;
+
+#endif
    }
 }
 
-
+#if 0
 const struct st_tracked_state st_update_vs = {
    .name = "st_update_vs",
    .dirty = {
@@ -272,7 +321,4 @@ const struct st_tracked_state st_update_vs = {
    },
    .update = update_vs
 };
-
-
-
-
+#endif
index 639e0ceb40ae2766a38f800fce9a86cfe8ae6d3f..367ae06cf398aa243e9e40bffeef540fb98991aa 100644 (file)
@@ -155,7 +155,8 @@ make_frag_shader(struct st_context *st)
    p->OutputsWritten = (1 << FRAG_RESULT_COLR);
 
    stfp = (struct st_fragment_program *) p;
-   st_translate_fragment_shader(st, stfp);
+   st_translate_fragment_program(st, stfp, NULL,
+                                 stfp->tokens, ST_FP_MAX_TOKENS);
 
    return stfp;
 }
@@ -203,7 +204,8 @@ make_vertex_shader(struct st_context *st)
                         (1 << VERT_RESULT_HPOS));
 
    stvp = (struct st_vertex_program *) p;
-   st_translate_vertex_shader(st, stvp);
+   st_translate_vertex_program(st, stvp, NULL,
+                               stvp->tokens, ST_FP_MAX_TOKENS);
    assert(stvp->vs);
 
    return stvp;
index 65c5465546405f4945315a7fd7a6c561aff87ba8..619c5d8ab7ce21dd9c9f5fd54c2f6c8209c56482 100644 (file)
@@ -92,7 +92,8 @@ make_fragment_shader(struct st_context *st)
    p->OutputsWritten = (1 << FRAG_RESULT_COLR);
 
    stfp = (struct st_fragment_program *) p;
-   st_translate_fragment_shader(st, stfp);
+   st_translate_fragment_program(st, stfp, NULL,
+                                 stfp->tokens, ST_FP_MAX_TOKENS);
 
    return stfp;
 }
@@ -141,7 +142,8 @@ make_vertex_shader(struct st_context *st)
                         (1 << VERT_RESULT_HPOS));
 
    stvp = (struct st_vertex_program *) p;
-   st_translate_vertex_shader(st, stvp);
+   st_translate_vertex_program(st, stvp, NULL,
+                               stvp->tokens, ST_FP_MAX_TOKENS);
 
    return stvp;
 }
index 78cf4c2b4d3ce497db7b404bf97da4eedf58edf9..537a58f39dc42198e88ca05a077a8dcafeceb05a 100644 (file)
@@ -102,13 +102,13 @@ feedback_vertex(GLcontext *ctx, const struct draw_context *draw,
     * color and texcoord attribs to use here.
     */
 
-   slot = st->vertex_attrib_to_slot[VERT_RESULT_COL0];
+   slot = st->vertex_result_to_slot[VERT_RESULT_COL0];
    if (slot)
       color = v->data[slot];
    else
       color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
 
-   slot = st->vertex_attrib_to_slot[VERT_RESULT_TEX0];
+   slot = st->vertex_result_to_slot[VERT_RESULT_TEX0];
    if (slot)
       texcoord = v->data[slot];
    else
index 9f46f9e93f4f52852348339d2c36b25c5cccd01a..aee316df6fc3429271f41ff5159370ca57ee565e 100644 (file)
   *   Keith Whitwell <keith@tungstengraphics.com>
   */
 
+#include "main/glheader.h"
+#include "main/macros.h"
+#include "main/enums.h"
+#include "shader/prog_instruction.h"
+#include "shader/prog_parameter.h"
+#include "shader/program.h"
+#include "shader/programopt.h"
+
 #include "st_context.h"
-#include "st_program.h"    
-#include "glheader.h"
-#include "macros.h"
-#include "enums.h"
-#include "prog_instruction.h"
-#include "prog_parameter.h"
-#include "program.h"
-#include "programopt.h"
+#include "st_program.h"
+#include "st_atom_shader.h"
+
 #include "tnl/tnl.h"
 #include "pipe/tgsi/mesa/tgsi_mesa.h"
 
 
-/* Counter to track program string changes:
+/**
+ * Called via ctx->Driver.BindProgram() to bind an ARB vertex or
+ * fragment program.
  */
-static GLuint program_id = 0;
-
-
 static void st_bind_program( GLcontext *ctx,
                             GLenum target, 
                             struct gl_program *prog )
@@ -62,8 +64,14 @@ static void st_bind_program( GLcontext *ctx,
       st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
       break;
    }
+   st->dirty.st |= ST_NEW_LINKAGE;
 }
 
+
+/**
+ * Called via ctx->Driver.UseProgram() to bind a linked GLSL program
+ * (vertex shader + fragment shader).
+ */
 static void st_use_program( GLcontext *ctx,
                            GLuint program )
 {
@@ -71,6 +79,7 @@ static void st_use_program( GLcontext *ctx,
 
    st->dirty.st |= ST_NEW_VERTEX_PROGRAM;
    st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
+   st->dirty.st |= ST_NEW_LINKAGE;
 }
 
 
@@ -79,14 +88,13 @@ static struct gl_program *st_new_program( GLcontext *ctx,
                                          GLenum target, 
                                          GLuint id )
 {
-//   struct st_context *st = st_context(ctx);
+   struct st_context *st = st_context(ctx);
 
    switch (target) {
    case GL_VERTEX_PROGRAM_ARB: {
       struct st_vertex_program *prog = CALLOC_STRUCT(st_vertex_program);
 
-      prog->id = program_id++;
-      prog->dirty = 1;
+      prog->serialNo = 1;
 
 #if defined(USE_X86_ASM) || defined(SLANG_X86)
       x86_init_func( &prog->sse2_program );
@@ -102,8 +110,7 @@ static struct gl_program *st_new_program( GLcontext *ctx,
    case GL_FRAGMENT_PROGRAM_NV: {
       struct st_fragment_program *prog = CALLOC_STRUCT(st_fragment_program);
 
-      prog->id = program_id++;
-      prog->dirty = 1;
+      prog->serialNo = 1;
 
 #if defined(USE_X86_ASM) || defined(SLANG_X86)
       x86_init_func( &prog->sse2_program );
@@ -118,29 +125,40 @@ static struct gl_program *st_new_program( GLcontext *ctx,
    default:
       return _mesa_new_program(ctx, target, id);
    }
+
+   st->dirty.st |= ST_NEW_LINKAGE;
 }
 
+
 static void st_delete_program( GLcontext *ctx,
                               struct gl_program *prog )
 {
+   struct st_context *st = st_context(ctx);
+
    switch( prog->Target ) {
-   case GL_VERTEX_PROGRAM_ARB: {
+   case GL_VERTEX_PROGRAM_ARB:
+      {
+         struct st_vertex_program *stvp = (struct st_vertex_program *) prog;
 #if defined(USE_X86_ASM) || defined(SLANG_X86)
-      struct st_vertex_program *p = (struct st_vertex_program *) prog;
-
-      x86_release_func( &p->sse2_program );
+         x86_release_func( &stvp->sse2_program );
 #endif
+         st_remove_vertex_program(st, stvp);
+      }
       break;
-   }
-   case GL_FRAGMENT_PROGRAM_ARB: {
+   case GL_FRAGMENT_PROGRAM_ARB:
+      {
+         struct st_fragment_program *stfp
+            = (struct st_fragment_program *) prog;
 #if defined(USE_X86_ASM) || defined(SLANG_X86)
-      struct st_fragment_program *p = (struct st_fragment_program *) prog;
-
-      x86_release_func( &p->sse2_program );
+         x86_release_func( &stfp->sse2_program );
 #endif
+         st_remove_fragment_program(st, stfp);
+      }
       break;
+   default:
+      assert(0); /* problem */
    }
-   }
+
    _mesa_delete_program( ctx, prog );
 }
 
@@ -160,27 +178,31 @@ static void st_program_string_notify( GLcontext *ctx,
    struct st_context *st = st_context(ctx);
 
    if (target == GL_FRAGMENT_PROGRAM_ARB) {
-      struct st_fragment_program *p = (struct st_fragment_program *)prog;
+      struct st_fragment_program *stfp = (struct st_fragment_program *) prog;
 
       if (prog == &ctx->FragmentProgram._Current->Base)
         st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
 
-      p->id = program_id++;
-      p->param_state = p->Base.Base.Parameters->StateFlags;
+      stfp->serialNo++;
+
+      stfp->param_state = stfp->Base.Base.Parameters->StateFlags;
    }
    else if (target == GL_VERTEX_PROGRAM_ARB) {
-      struct st_vertex_program *p = (struct st_vertex_program *)prog;
+      struct st_vertex_program *stvp = (struct st_vertex_program *) prog;
 
       if (prog == &ctx->VertexProgram._Current->Base)
         st->dirty.st |= ST_NEW_VERTEX_PROGRAM;
 
-      p->id = program_id++;
-      p->param_state = p->Base.Base.Parameters->StateFlags;
+      stvp->serialNo++;
+
+      stvp->param_state = stvp->Base.Base.Parameters->StateFlags;
 
       /* Also tell tnl about it:
        */
       _tnl_program_string(ctx, target, prog);
    }
+
+   st->dirty.st |= ST_NEW_LINKAGE;
 }
 
 
index 2311bddc655f92057b59cfdeaee79ac0948b558b..661d155e6da20dad135ba008a02ece9a396df5da 100644 (file)
@@ -53,9 +53,9 @@ static void
 setup_vertex_attribs(GLcontext *ctx)
 {
    struct pipe_context *pipe = ctx->st->pipe;
-#if 0
-   const uint inputAttrs = ctx->st->state.vs->inputs_read;
-   uint attr;
+   const struct cso_vertex_shader *vs = ctx->st->state.vs;
+   const struct st_vertex_program *stvp = ctx->st->vp;
+   uint slot;
 
    /* all attributes come from the default attribute buffer */
    {
@@ -67,20 +67,16 @@ setup_vertex_attribs(GLcontext *ctx)
       pipe->set_vertex_buffer(pipe, 0, &vbuffer);
    }
 
-   for (attr = 0; attr < 16; attr++) {
+   for (slot = 0; slot < vs->state.num_inputs; slot++) {
       struct pipe_vertex_element velement;
+      const GLuint attr = stvp->index_to_input[slot];
 
-      if (inputAttrs & (1 << attr)) {
-         velement.src_offset = attr * 4 * sizeof(GLfloat);
-         velement.vertex_buffer_index = 0;
-         velement.dst_offset = 0;
-         velement.src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
-         pipe->set_vertex_element(pipe, attr, &velement);
-      }
+      velement.src_offset = attr * 4 * sizeof(GLfloat);
+      velement.vertex_buffer_index = 0;
+      velement.dst_offset = 0;
+      velement.src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+      pipe->set_vertex_element(pipe, slot, &velement);
    }
-#else
-   assert(0);
-#endif
 }
 
 
@@ -98,12 +94,11 @@ setup_feedback(GLcontext *ctx)
    feedback.discard = 1;
    feedback.num_attribs = 0;
 
+   /* feedback all results from vertex shader */
    for (i = 0; i < vs->num_outputs; i++) {
-      if (1/***(1 << i) & outputAttrs***/) {
-         feedback.attrib[feedback.num_attribs] = i;
-         feedback.size[feedback.num_attribs] = 4;
-         feedback.num_attribs++;
-      }
+      feedback.attrib[feedback.num_attribs] = i;
+      feedback.size[feedback.num_attribs] = 4;
+      feedback.num_attribs++;
    }
 
    pipe->set_feedback_state(pipe, &feedback);
@@ -261,13 +256,11 @@ update_rasterpos(GLcontext *ctx,
 static void
 st_RasterPos(GLcontext *ctx, const GLfloat v[4])
 {
-   struct pipe_context *pipe = ctx->st->pipe;
+   const struct st_context *st = ctx->st;
+   struct pipe_context *pipe = st->pipe;
    float *buf_map;
    struct pipe_feedback_buffer fb_buf;
 
-   /** XXX TEMPORARILY DISABLE */
-   return;
-
    st_validate_state(ctx->st);
 
    /* setup vertex buffers */
@@ -277,7 +270,7 @@ st_RasterPos(GLcontext *ctx, const GLfloat v[4])
     * Load the default attribute buffer with current attribs.
     */
    {
-      struct pipe_buffer_handle *buf = ctx->st->default_attrib_buffer;
+      struct pipe_buffer_handle *buf = st->default_attrib_buffer;
       const unsigned size = sizeof(ctx->Current.Attrib);
       const void *data = ctx->Current.Attrib;
       /* colors, texcoords, etc */
@@ -313,17 +306,16 @@ st_RasterPos(GLcontext *ctx, const GLfloat v[4])
                                                 PIPE_BUFFER_FLAG_READ);
 
    /* extract values and update rasterpos state */
-#if 0 /* XXX update */
    {
-      const uint outputAttrs = ctx->st->state.vs->outputs_written;
+      const GLuint *outputMapping = st->vertex_result_to_slot;
       const float *pos, *color0, *color1, *tex0;
       float *buf = buf_map;
 
-      assert(outputAttrs & (1 << TGSI_ATTRIB_POS));
+      assert(outputMapping[VERT_RESULT_HPOS] != ~0);
       pos = buf;
       buf += 4;
 
-      if (outputAttrs & (1 << TGSI_ATTRIB_COLOR0)) {
+      if (outputMapping[VERT_RESULT_COL0] != ~0) {
          color0 = buf;
          buf += 4;
       }
@@ -331,7 +323,7 @@ st_RasterPos(GLcontext *ctx, const GLfloat v[4])
          color0 = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
       }
 
-      if (outputAttrs & (1 << TGSI_ATTRIB_COLOR1)) {
+      if (outputMapping[VERT_RESULT_COL1] != ~0) {
          color1 = buf;
          buf += 4;
       }
@@ -339,16 +331,23 @@ st_RasterPos(GLcontext *ctx, const GLfloat v[4])
          color1 = ctx->Current.Attrib[VERT_ATTRIB_COLOR1];
       }
 
+      if (outputMapping[VERT_RESULT_TEX0] != ~0) {
+         tex0 = buf;
+         buf += 4;
+      }
+      else {
+         tex0 = ctx->Current.Attrib[VERT_ATTRIB_TEX0];
+      }
+
       update_rasterpos(ctx, pos, color0, color1, tex0);
    }
-#endif
 
    /* free vertex feedback buffer */
    pipe->winsys->buffer_unmap(pipe->winsys, fb_buf.buffer);
    pipe->winsys->buffer_reference(pipe->winsys, &fb_buf.buffer, NULL);
 
    /* restore pipe state */
-   pipe->set_feedback_state(pipe, &ctx->st->state.feedback);
+   pipe->set_feedback_state(pipe, &st->state.feedback);
 }
 
 
index 3713328eb14dd3c2bffde3f5d63992b50013cc66..24f0ff9aaf3e90ad29c90fb679afad1fc4083c00 100644 (file)
@@ -45,6 +45,8 @@ struct cso_blend;
 #define ST_NEW_MESA                    0x1 /* Mesa state has changed */
 #define ST_NEW_FRAGMENT_PROGRAM        0x2
 #define ST_NEW_VERTEX_PROGRAM          0x4
+#define ST_NEW_LINKAGE                 0x8
+
 
 struct st_state_flags {
    GLuint mesa;
@@ -119,8 +121,8 @@ struct st_context
 
    GLfloat polygon_offset_scale; /* ?? */
 
-   /** Mapping from VERT_ATTRIB_x to post-transformed vertex slot */
-   GLuint vertex_attrib_to_slot[VERT_RESULT_MAX];
+   /** Mapping from VERT_RESULT_x to post-transformed vertex slot */
+   const GLuint *vertex_result_to_slot;
 
    struct st_vertex_program *vp;    /**< Currently bound vertex program */
    struct st_fragment_program *fp;  /**< Currently bound fragment program */
index 419afa4e7860d597fe8a951e1ec05cdc72b59082..355dee574bd69d416cb44070700df128087c3658 100644 (file)
@@ -47,11 +47,11 @@ struct st_fragment_program
 {
    struct gl_fragment_program Base;
    GLboolean error;             /* If program is malformed for any reason. */
-   GLuint id; /**< String id, for tracking ProgramStringNotify changes. */
+
+   GLuint serialNo;
 
    /** The program in TGSI format */
    struct tgsi_token tokens[ST_FP_MAX_TOKENS];
-   GLboolean dirty;
 
 #if defined(USE_X86_ASM) || defined(SLANG_X86)
    struct x86_function  sse2_program;
@@ -68,7 +68,8 @@ struct st_vertex_program
 {
    struct gl_vertex_program Base;  /**< The Mesa vertex program */
    GLboolean error;        /**< Set if program is malformed for any reason. */
-   GLuint id; /**< String id, for tracking ProgramStringNotify changes. */
+
+   GLuint serialNo;
 
    /** maps a Mesa VERT_ATTRIB_x to a packed TGSI input index */
    GLuint input_to_index[MAX_VERTEX_PROGRAM_ATTRIBS];
@@ -77,7 +78,6 @@ struct st_vertex_program
 
    /** The program in TGSI format */
    struct tgsi_token tokens[ST_FP_MAX_TOKENS];
-   GLboolean dirty;
 
 #if defined(USE_X86_ASM) || defined(SLANG_X86)
    struct x86_function  sse2_program;
@@ -90,7 +90,8 @@ struct st_vertex_program
 };
 
 
-extern void st_init_program_functions(struct dd_function_table *functions);
+extern void
+st_init_program_functions(struct dd_function_table *functions);
 
 
 static inline struct st_fragment_program *
@@ -99,6 +100,7 @@ st_fragment_program( struct gl_fragment_program *fp )
    return (struct st_fragment_program *)fp;
 }
 
+
 static inline struct st_vertex_program *
 st_vertex_program( struct gl_vertex_program *vp )
 {
@@ -107,13 +109,18 @@ st_vertex_program( struct gl_vertex_program *vp )
 
 
 extern const struct cso_fragment_shader *
-st_translate_fragment_shader(struct st_context *st,
-                             struct st_fragment_program *fp);
+st_translate_fragment_program(struct st_context *st,
+                              struct st_fragment_program *fp,
+                              const GLuint inputMapping[],
+                              struct tgsi_token *tokens,
+                              GLuint maxTokens);
 
 
 extern const struct cso_vertex_shader *
-st_translate_vertex_shader(struct st_context *st,
-                           struct st_vertex_program *vp);
-
+st_translate_vertex_program(struct st_context *st,
+                            struct st_vertex_program *vp,
+                            const GLuint vert_output_to_slot[],
+                            struct tgsi_token *tokens,
+                            GLuint maxTokens);
 
 #endif