OSDN Git Service

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 3b84002..ee54db0 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 d0d97ab..fa27fd3 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 0d4fdc1..985bd2d 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 fc339b9..326042c 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 6710c1a..94cb7be 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 dd4cdf0..2801985 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 a6c0d15..0f07906 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 639e0ce..367ae06 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 65c5465..619c5d8 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 78cf4c2..537a58f 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 9f46f9e..aee316d 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 2311bdd..661d155 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 3713328..24f0ff9 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 419afa4..355dee5 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