diff options
| -rw-r--r-- | src/mesa/state_tracker/st_atom.c | 3 | ||||
| -rw-r--r-- | src/mesa/state_tracker/st_atom.h | 3 | ||||
| -rw-r--r-- | src/mesa/state_tracker/st_atom_shader.c | 326 | ||||
| -rw-r--r-- | src/mesa/state_tracker/st_cb_bitmap.c | 5 | ||||
| -rw-r--r-- | src/mesa/state_tracker/st_cb_drawpixels.c | 8 | ||||
| -rw-r--r-- | src/mesa/state_tracker/st_cb_program.c | 43 | ||||
| -rw-r--r-- | src/mesa/state_tracker/st_context.h | 2 | ||||
| -rw-r--r-- | src/mesa/state_tracker/st_debug.c | 3 | ||||
| -rw-r--r-- | src/mesa/state_tracker/st_draw.c | 2 | ||||
| -rw-r--r-- | src/mesa/state_tracker/st_draw_feedback.c | 8 | ||||
| -rw-r--r-- | src/mesa/state_tracker/st_program.c | 265 | ||||
| -rw-r--r-- | src/mesa/state_tracker/st_program.h | 75 | 
12 files changed, 275 insertions, 468 deletions
| diff --git a/src/mesa/state_tracker/st_atom.c b/src/mesa/state_tracker/st_atom.c index ca15ce1b47..dfce955fd9 100644 --- a/src/mesa/state_tracker/st_atom.c +++ b/src/mesa/state_tracker/st_atom.c @@ -46,7 +46,8 @@ static const struct st_tracked_state *atoms[] =     &st_update_clip,     &st_finalize_textures, -   &st_update_shader, +   &st_update_fp, +   &st_update_vp,     &st_update_rasterizer,     &st_update_polygon_stipple, diff --git a/src/mesa/state_tracker/st_atom.h b/src/mesa/state_tracker/st_atom.h index c7cffd85c8..f34b49203b 100644 --- a/src/mesa/state_tracker/st_atom.h +++ b/src/mesa/state_tracker/st_atom.h @@ -47,7 +47,8 @@ void st_validate_state( struct st_context *st );  extern const struct st_tracked_state st_update_framebuffer;  extern const struct st_tracked_state st_update_clip;  extern const struct st_tracked_state st_update_depth_stencil_alpha; -extern const struct st_tracked_state st_update_shader; +extern const struct st_tracked_state st_update_fp; +extern const struct st_tracked_state st_update_vp;  extern const struct st_tracked_state st_update_rasterizer;  extern const struct st_tracked_state st_update_polygon_stipple;  extern const struct st_tracked_state st_update_viewport; diff --git a/src/mesa/state_tracker/st_atom_shader.c b/src/mesa/state_tracker/st_atom_shader.c index ee649be885..09baff875b 100644 --- a/src/mesa/state_tracker/st_atom_shader.c +++ b/src/mesa/state_tracker/st_atom_shader.c @@ -56,82 +56,18 @@  #include "st_mesa_to_tgsi.h" -/** - * This represents a vertex program, especially translated to match - * the inputs of a particular fragment shader. - */ -struct translated_vertex_program -{ -   struct st_vertex_program *master; - -   /** The fragment shader "signature" this vertex shader is meant for: */ -   GLbitfield frag_inputs; - -   /** Compared against master vertex program's serialNo: */ -   GLuint serialNo; - -   /** 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; - -   struct translated_vertex_program *next;  /**< next in linked list */ -}; - - - -/** - * Given a vertex program output attribute, return the corresponding - * fragment program input attribute. - * \return -1 for vertex outputs that have no corresponding fragment input - */ -static GLint -vp_out_to_fp_in(GLuint vertResult) -{ -   if (vertResult >= VERT_RESULT_TEX0 && -       vertResult < VERT_RESULT_TEX0 + MAX_TEXTURE_COORD_UNITS) -      return FRAG_ATTRIB_TEX0 + (vertResult - VERT_RESULT_TEX0); -   if (vertResult >= VERT_RESULT_VAR0 && -       vertResult < VERT_RESULT_VAR0 + MAX_VARYING) -      return FRAG_ATTRIB_VAR0 + (vertResult - VERT_RESULT_VAR0); -   switch (vertResult) { -   case VERT_RESULT_HPOS: -      return FRAG_ATTRIB_WPOS; -   case VERT_RESULT_COL0: -      return FRAG_ATTRIB_COL0; -   case VERT_RESULT_COL1: -      return FRAG_ATTRIB_COL1; -   case VERT_RESULT_FOGC: -      return FRAG_ATTRIB_FOGC; -   default: -      /* Back-face colors, edge flags, etc */ -      return -1; -   } -} - -/** - * Find a translated vertex program that corresponds to stvp and - * has outputs matched to stfp's inputs. - * This performs vertex and fragment translation (to TGSI) when needed. +/* + * Translate fragment program if needed.   */ -static struct translated_vertex_program * -find_translated_vp(struct st_context *st, -                   struct st_vertex_program *stvp, -                   struct st_fragment_program *stfp) +static void +translate_fp(struct st_context *st, +             struct st_fragment_program *stfp)  { -   static const GLuint UNUSED = ~0; -   struct translated_vertex_program *xvp;     const GLbitfield fragInputsRead = stfp->Base.Base.InputsRead; -   /* -    * Translate fragment program if needed. -    */     if (!stfp->state.tokens) {        GLuint inAttr, numIn = 0; @@ -141,7 +77,7 @@ find_translated_vp(struct st_context *st,              numIn++;           }           else { -            stfp->input_to_slot[inAttr] = UNUSED; +            stfp->input_to_slot[inAttr] = -1;           }        } @@ -151,170 +87,63 @@ find_translated_vp(struct st_context *st,        st_translate_fragment_program(st, stfp, stfp->input_to_slot);     } +} -   /* See if we've got a translated vertex program whose outputs match -    * the fragment program's inputs. -    * XXX This could be a hash lookup, using InputsRead as the key. -    */ -   for (xvp = stfp->vertex_programs; xvp; xvp = xvp->next) { -      if (xvp->master == stvp && xvp->frag_inputs == fragInputsRead) { -         break; -      } -   } - -   /* No?  Allocate translated vp object now */ -   if (!xvp) { -      xvp = ST_CALLOC_STRUCT(translated_vertex_program); -      xvp->frag_inputs = fragInputsRead; -      xvp->master = stvp; -      xvp->next = stfp->vertex_programs; -      stfp->vertex_programs = xvp; -   } +/** + * Find a translated vertex program that corresponds to stvp and + * has outputs matched to stfp's inputs. + * This performs vertex and fragment translation (to TGSI) when needed. + */ +static struct st_vp_varient * +find_translated_vp(struct st_context *st, +                   struct st_vertex_program *stvp ) +{ +   struct st_vp_varient *vpv; +   struct st_vp_varient_key key; -   /* See if we need to translate vertex program to TGSI form */ -   if (xvp->serialNo != stvp->serialNo) { -      GLuint outAttr; -      const GLbitfield outputsWritten = stvp->Base.Base.OutputsWritten; -      GLuint numVpOuts = 0; -      GLboolean emitPntSize = GL_FALSE, emitBFC0 = GL_FALSE, emitBFC1 = GL_FALSE; -      GLbitfield usedGenerics = 0x0; -      GLbitfield usedOutputSlots = 0x0; +   /* Nothing in our key yet.  This will change: +    */ +   memset(&key, 0, sizeof key); +   key.dummy = 0; -      /* Compute mapping of vertex program outputs to slots, which depends -       * on the fragment program's input->slot mapping. +   /* Do we need to throw away old translations after a change in the +    * GL program string? +    */ +   if (stvp->serialNo != stvp->lastSerialNo) { +      /* These may have changed if the program string changed.         */ -      for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) { -         /* 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 */ -            GLuint slot = 0; -            xvp->output_to_slot[VERT_RESULT_HPOS] = slot; -            xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_POSITION; -            xvp->output_to_semantic_index[outAttr] = 0; -            numVpOuts++; -            usedOutputSlots |= (1 << slot); -         } -         else if (outputsWritten & (1 << outAttr)) { -            /* see if the frag prog wants this vert output */ -            GLint fpInAttrib = vp_out_to_fp_in(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++; -                  usedOutputSlots |= (1 << vpOutSlot); -               } -               else { -#if 0 /*debug*/ -                  printf("VP output %d not used by FP\n", outAttr); -#endif -               } -            } -            else if (outAttr == VERT_RESULT_PSIZ) -               emitPntSize = GL_TRUE; -            else if (outAttr == VERT_RESULT_BFC0) -               emitBFC0 = GL_TRUE; -            else if (outAttr == VERT_RESULT_BFC1) -               emitBFC1 = GL_TRUE; -         } -#if 0 /*debug*/ -         printf("assign vp output_to_slot[%d] = %d\n", outAttr,  -                xvp->output_to_slot[outAttr]); -#endif -      } - -      /* must do these last */ -      if (emitPntSize) { -         GLuint slot = numVpOuts++; -         xvp->output_to_slot[VERT_RESULT_PSIZ] = slot; -         xvp->output_to_semantic_name[VERT_RESULT_PSIZ] = TGSI_SEMANTIC_PSIZE; -         xvp->output_to_semantic_index[VERT_RESULT_PSIZ] = 0; -         usedOutputSlots |= (1 << slot); -      } -      if (emitBFC0) { -         GLuint slot = numVpOuts++; -         xvp->output_to_slot[VERT_RESULT_BFC0] = slot; -         xvp->output_to_semantic_name[VERT_RESULT_BFC0] = TGSI_SEMANTIC_COLOR; -         xvp->output_to_semantic_index[VERT_RESULT_BFC0] = 0; -         usedOutputSlots |= (1 << slot); -      } -      if (emitBFC1) { -         GLuint slot = numVpOuts++; -         xvp->output_to_slot[VERT_RESULT_BFC1] = slot; -         xvp->output_to_semantic_name[VERT_RESULT_BFC1] = TGSI_SEMANTIC_COLOR; -         xvp->output_to_semantic_index[VERT_RESULT_BFC1] = 1; -         usedOutputSlots |= (1 << slot); -      } - -      /* build usedGenerics mask */ -      usedGenerics = 0x0; -      for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) { -         if (xvp->output_to_semantic_name[outAttr] == TGSI_SEMANTIC_GENERIC) { -            usedGenerics |= (1 << xvp->output_to_semantic_index[outAttr]); -         } -      } +      st_prepare_vertex_program( st, stvp ); -      /* For each vertex program output that doesn't match up to a fragment -       * program input, map the vertex program output to a free slot and -       * free generic attribute. +      /* We are now up-to-date:         */ -      for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) { -         if (outputsWritten & (1 << outAttr)) { -            if (xvp->output_to_slot[outAttr] == UNUSED) { -               GLint freeGeneric = _mesa_ffs(~usedGenerics) - 1; -               GLint freeSlot = _mesa_ffs(~usedOutputSlots) - 1; -               usedGenerics |= (1 << freeGeneric); -               usedOutputSlots |= (1 << freeSlot); -               xvp->output_to_slot[outAttr] = freeSlot; -               xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_GENERIC; -               xvp->output_to_semantic_index[outAttr] = freeGeneric; -            } -         } - -#if 0 /*debug*/ -         printf("vp output_to_slot[%d] = %d\n", outAttr,  -                xvp->output_to_slot[outAttr]); -#endif +      stvp->lastSerialNo = stvp->serialNo; +   } +    +   /* See if we've got a translated vertex program whose outputs match +    * the fragment program's inputs. +    */ +   for (vpv = stvp->varients; vpv; vpv = vpv->next) { +      if (memcmp(&vpv->key, &key, sizeof key) == 0) { +         break;        } +   } -      assert(stvp->Base.Base.NumInstructions > 1); - -      st_translate_vertex_program(st, stvp, xvp->output_to_slot, -                                  xvp->output_to_semantic_name, -                                  xvp->output_to_semantic_index); - -      xvp->vp = stvp; - -      /* translated VP is up to date now */ -      xvp->serialNo = stvp->serialNo; +   /* No?  Perform new translation here. */ +   if (!vpv) { +      vpv = st_translate_vertex_program(st, stvp, &key); +      if (!vpv) +         return NULL; +       +      vpv->next = stvp->varients; +      stvp->varients = vpv;     } -   return xvp; +   return vpv;  } -void -st_free_translated_vertex_programs(struct st_context *st, -                                   struct translated_vertex_program *xvp) -{ -   struct translated_vertex_program *next; - -   while (xvp) { -      next = xvp->next; -      _mesa_free(xvp); -      xvp = next; -   } -}  static void * @@ -328,32 +157,19 @@ get_passthrough_fs(struct st_context *st)     return st->passthrough_fs;  } -  static void -update_linkage( struct st_context *st ) +update_fp( struct st_context *st )  { -   struct st_vertex_program *stvp;     struct st_fragment_program *stfp; -   struct translated_vertex_program *xvp; - -   /* find active shader and params -- Should be covered by -    * ST_NEW_VERTEX_PROGRAM -    */ -   assert(st->ctx->VertexProgram._Current); -   stvp = st_vertex_program(st->ctx->VertexProgram._Current); -   assert(stvp->Base.Base.Target == GL_VERTEX_PROGRAM_ARB);     assert(st->ctx->FragmentProgram._Current);     stfp = st_fragment_program(st->ctx->FragmentProgram._Current);     assert(stfp->Base.Base.Target == GL_FRAGMENT_PROGRAM_ARB); -   xvp = find_translated_vp(st, stvp, stfp); +   translate_fp(st, stfp); -   st_reference_vertprog(st, &st->vp, stvp);     st_reference_fragprog(st, &st->fp, stfp); -   cso_set_vertex_shader_handle(st->cso_context, stvp->driver_shader); -     if (st->missing_textures) {        /* use a pass-through frag shader that uses no textures */        void *fs = get_passthrough_fs(st); @@ -362,16 +178,48 @@ update_linkage( struct st_context *st )     else {        cso_set_fragment_shader_handle(st->cso_context, stfp->driver_shader);     } +} + +const struct st_tracked_state st_update_fp = { +   "st_update_fp",					/* name */ +   {							/* dirty */ +      0,						/* mesa */ +      ST_NEW_FRAGMENT_PROGRAM                           /* st */ +   }, +   update_fp  					/* update */ +}; + + + + +static void +update_vp( struct st_context *st ) +{ +   struct st_vertex_program *stvp; + +   /* find active shader and params -- Should be covered by +    * ST_NEW_VERTEX_PROGRAM +    */ +   assert(st->ctx->VertexProgram._Current); +   stvp = st_vertex_program(st->ctx->VertexProgram._Current); +   assert(stvp->Base.Base.Target == GL_VERTEX_PROGRAM_ARB); + +   st->vp_varient = find_translated_vp(st, stvp); + +   st_reference_vertprog(st, &st->vp, stvp); + +   cso_set_vertex_shader_handle(st->cso_context,  +                                st->vp_varient->driver_shader); -   st->vertex_result_to_slot = xvp->output_to_slot; +   st->vertex_result_to_slot = stvp->result_to_output;  } -const struct st_tracked_state st_update_shader = { -   "st_update_shader",					/* name */ +const struct st_tracked_state st_update_vp = { +   "st_update_vp",					/* name */     {							/* dirty */        0,						/* mesa */ -      ST_NEW_VERTEX_PROGRAM | ST_NEW_FRAGMENT_PROGRAM	/* st */ +      ST_NEW_VERTEX_PROGRAM                             /* st */     }, -   update_linkage					/* update */ +   update_vp					/* update */  }; diff --git a/src/mesa/state_tracker/st_cb_bitmap.c b/src/mesa/state_tracker/st_cb_bitmap.c index a22fa68299..226d1ab14c 100644 --- a/src/mesa/state_tracker/st_cb_bitmap.c +++ b/src/mesa/state_tracker/st_cb_bitmap.c @@ -169,11 +169,6 @@ make_bitmap_fragment_program(GLcontext *ctx, GLuint samplerIndex)     stfp = (struct st_fragment_program *) p;     stfp->Base.UsesKill = GL_TRUE; -   /* No need to send this incomplete program down to hardware: -    * -    * st_translate_fragment_program(ctx->st, stfp, NULL); -    */ -     return stfp;  } diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c index 13e454b7a7..60394731f7 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/src/mesa/state_tracker/st_cb_drawpixels.c @@ -927,7 +927,7 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,     struct pipe_context *pipe = st->pipe;     struct pipe_screen *screen = pipe->screen;     struct st_renderbuffer *rbRead; -   struct st_vertex_program *stvp; +   void *driver_vp;     struct st_fragment_program *stfp;     struct pipe_texture *pt;     GLfloat *color; @@ -976,14 +976,14 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,        rbRead = st_get_color_read_renderbuffer(ctx);        color = NULL;        stfp = combined_drawpix_fragment_program(ctx); -      stvp = st_make_passthrough_vertex_shader(st, GL_FALSE); +      driver_vp = st_make_passthrough_vertex_shader(st, GL_FALSE);     }     else {        assert(type == GL_DEPTH);        rbRead = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer);        color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];        stfp = make_fragment_shader_z(st); -      stvp = st_make_passthrough_vertex_shader(st, GL_TRUE); +      driver_vp = st_make_passthrough_vertex_shader(st, GL_TRUE);     }     srcFormat = rbRead->texture->format; @@ -1116,7 +1116,7 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,     draw_textured_quad(ctx, dstx, dsty, ctx->Current.RasterPos[2],                        width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY,                        pt,  -                      stvp->driver_shader,  +                      driver_vp,                         stfp->driver_shader,                        color, GL_TRUE); diff --git a/src/mesa/state_tracker/st_cb_program.c b/src/mesa/state_tracker/st_cb_program.c index b2d5c39a3a..8c276f8128 100644 --- a/src/mesa/state_tracker/st_cb_program.c +++ b/src/mesa/state_tracker/st_cb_program.c @@ -138,24 +138,7 @@ st_delete_program(GLcontext *ctx, struct gl_program *prog)     case GL_VERTEX_PROGRAM_ARB:        {           struct st_vertex_program *stvp = (struct st_vertex_program *) prog; - -         if (stvp->driver_shader) { -            cso_delete_vertex_shader(st->cso_context, stvp->driver_shader); -            stvp->driver_shader = NULL; -         } - -         if (stvp->draw_shader) { -#if FEATURE_feedback || FEATURE_drawpix -            /* this would only have been allocated for the RasterPos path */ -            draw_delete_vertex_shader(st->draw, stvp->draw_shader); -            stvp->draw_shader = NULL; -#endif -         } - -         if (stvp->state.tokens) { -            st_free_tokens(stvp->state.tokens); -            stvp->state.tokens = NULL; -         } +         st_vp_release_varients( st, stvp );        }        break;     case GL_FRAGMENT_PROGRAM_ARB: @@ -177,8 +160,6 @@ st_delete_program(GLcontext *ctx, struct gl_program *prog)              _mesa_reference_program(ctx, &prg, NULL);              stfp->bitmap_program = NULL;           } - -         st_free_translated_vertex_programs(st, stfp->vertex_programs);        }        break;     default: @@ -219,8 +200,6 @@ static void st_program_string_notify( GLcontext *ctx,           stfp->state.tokens = NULL;        } -      stfp->param_state = stfp->Base.Base.Parameters->StateFlags; -        if (st->fp == stfp)  	 st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;     } @@ -229,25 +208,7 @@ static void st_program_string_notify( GLcontext *ctx,        stvp->serialNo++; -      if (stvp->driver_shader) { -         cso_delete_vertex_shader(st->cso_context, stvp->driver_shader); -         stvp->driver_shader = NULL; -      } - -      if (stvp->draw_shader) { -#if FEATURE_feedback || FEATURE_drawpix -         /* this would only have been allocated for the RasterPos path */ -         draw_delete_vertex_shader(st->draw, stvp->draw_shader); -         stvp->draw_shader = NULL; -#endif -      } - -      if (stvp->state.tokens) { -         st_free_tokens(stvp->state.tokens); -         stvp->state.tokens = NULL; -      } - -      stvp->param_state = stvp->Base.Base.Parameters->StateFlags; +      st_vp_release_varients( st, stvp );        if (st->vp == stvp)  	 st->dirty.st |= ST_NEW_VERTEX_PROGRAM; diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index 18adb35e87..b760728658 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -127,6 +127,8 @@ struct st_context     struct st_vertex_program *vp;    /**< Currently bound vertex program */     struct st_fragment_program *fp;  /**< Currently bound fragment program */ +   struct st_vp_varient *vp_varient; +     struct gl_texture_object *default_texture;     struct { diff --git a/src/mesa/state_tracker/st_debug.c b/src/mesa/state_tracker/st_debug.c index 3009cde9d5..6e699ca552 100644 --- a/src/mesa/state_tracker/st_debug.c +++ b/src/mesa/state_tracker/st_debug.c @@ -86,7 +86,8 @@ st_print_current(void)     }  #endif -   tgsi_dump( st->vp->state.tokens, 0 ); +   if (st->vp->varients) +      tgsi_dump( st->vp->varients[0].state.tokens, 0 );     if (st->vp->Base.Base.Parameters)        _mesa_print_parameter_list(st->vp->Base.Base.Parameters); diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c index c76bff9181..337c21a6c4 100644 --- a/src/mesa/state_tracker/st_draw.c +++ b/src/mesa/state_tracker/st_draw.c @@ -563,7 +563,7 @@ st_draw_vbo(GLcontext *ctx,     /* must get these after state validation! */     vp = ctx->st->vp; -   vs = &ctx->st->vp->state; +   vs = &ctx->st->vp_varient->state;  #if 0     if (MESA_VERBOSE & VERBOSE_GLSL) { diff --git a/src/mesa/state_tracker/st_draw_feedback.c b/src/mesa/state_tracker/st_draw_feedback.c index b2d682ef64..d793f820bc 100644 --- a/src/mesa/state_tracker/st_draw_feedback.c +++ b/src/mesa/state_tracker/st_draw_feedback.c @@ -120,10 +120,10 @@ st_feedback_draw_vbo(GLcontext *ctx,     /* must get these after state validation! */     vp = ctx->st->vp; -   vs = &st->vp->state; +   vs = &st->vp_varient->state; -   if (!st->vp->draw_shader) { -      st->vp->draw_shader = draw_create_vertex_shader(draw, vs); +   if (!st->vp_varient->draw_shader) { +      st->vp_varient->draw_shader = draw_create_vertex_shader(draw, vs);     }     /* @@ -136,7 +136,7 @@ st_feedback_draw_vbo(GLcontext *ctx,     draw_set_viewport_state(draw, &st->state.viewport);     draw_set_clip_state(draw, &st->state.clip);     draw_set_rasterizer_state(draw, &st->state.rasterizer); -   draw_bind_vertex_shader(draw, st->vp->draw_shader); +   draw_bind_vertex_shader(draw, st->vp_varient->draw_shader);     set_feedback_vertex_format(ctx);     /* loop over TGSI shader inputs to determine vertex buffer diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c index 5450b59a2d..6a2b99cf1b 100644 --- a/src/mesa/state_tracker/st_program.c +++ b/src/mesa/state_tracker/st_program.c @@ -49,6 +49,36 @@  #include "st_mesa_to_tgsi.h"  #include "cso_cache/cso_context.h" +   /* Clean out any old compilations: +    */ +void +st_vp_release_varients( struct st_context *st, +                        struct st_vertex_program *stvp ) +{ +   struct st_vp_varient *vpv; + +   for (vpv = stvp->varients; vpv; ) { +      struct st_vp_varient *next = vpv->next; + +      if (vpv->driver_shader)  +         cso_delete_vertex_shader(st->cso_context, vpv->driver_shader); +       +      if (vpv->draw_shader) +         draw_delete_vertex_shader( st->draw, vpv->draw_shader ); +       +      if (vpv->state.tokens) +         st_free_tokens(vpv->state.tokens); +       +      FREE( vpv ); + +      vpv = next; +   } + +   stvp->varients = NULL; +} + + +  /**   * Translate a Mesa vertex shader into a TGSI shader. @@ -58,22 +88,13 @@   * \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 ubyte *outputSemanticName, -                            const ubyte *outputSemanticIndex) +st_prepare_vertex_program(struct st_context *st, +                            struct st_vertex_program *stvp)  { -   struct pipe_context *pipe = st->pipe; -   GLuint defaultOutputMapping[VERT_RESULT_MAX]; -   GLuint attr, i; -   GLuint num_generic = 0; - -   uint vs_num_inputs = 0; +   GLuint attr; -   ubyte vs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS]; -   ubyte vs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS]; -   uint vs_num_outputs = 0; +   stvp->num_inputs = 0; +   stvp->num_outputs = 0;     if (stvp->Base.IsPositionInvariant)        _mesa_insert_mvp_code(st->ctx, &stvp->Base); @@ -84,92 +105,56 @@ st_translate_vertex_program(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; - -         vs_num_inputs++; -      } -   } - -#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]); +         stvp->input_to_index[attr] = stvp->num_inputs; +         stvp->index_to_input[stvp->num_inputs] = attr; +         stvp->num_inputs++;        }     } -#endif - -   /* initialize output semantics to defaults */ -   for (i = 0; i < PIPE_MAX_SHADER_OUTPUTS; i++) { -      assert(i < Elements(vs_output_semantic_name)); -      vs_output_semantic_name[i] = TGSI_SEMANTIC_GENERIC; -      vs_output_semantic_index[i] = 0; -   } -   num_generic = 0; -   /* -    * Determine number of outputs, the (default) output register -    * mapping and the semantic information for each output. +   /* Compute mapping of vertex program outputs to slots.      */     for (attr = 0; attr < VERT_RESULT_MAX; attr++) { -      if (stvp->Base.Base.OutputsWritten & (1 << attr)) { -         GLuint slot; - -         /* XXX -          * Pass in the fragment program's input's semantic info. -          * Use the generic semantic indexes from there, instead of -          * guessing below. -          */ +      if ((stvp->Base.Base.OutputsWritten & (1 << attr)) == 0) { +         stvp->result_to_output[attr] = ~0; +      } +      else { +         unsigned slot = stvp->num_outputs++; -         if (outputMapping) { -            slot = outputMapping[attr]; -            assert(slot != ~0); -         } -         else { -            slot = vs_num_outputs; -            vs_num_outputs++; -            defaultOutputMapping[attr] = slot; -         } +         stvp->result_to_output[attr] = slot;           switch (attr) {           case VERT_RESULT_HPOS: -            assert(slot == 0); -            vs_output_semantic_name[slot] = TGSI_SEMANTIC_POSITION; -            vs_output_semantic_index[slot] = 0; +            stvp->output_semantic_name[slot] = TGSI_SEMANTIC_POSITION; +            stvp->output_semantic_index[slot] = 0;              break;           case VERT_RESULT_COL0: -            vs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR; -            vs_output_semantic_index[slot] = 0; +            stvp->output_semantic_name[slot] = TGSI_SEMANTIC_COLOR; +            stvp->output_semantic_index[slot] = 0;              break;           case VERT_RESULT_COL1: -            vs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR; -            vs_output_semantic_index[slot] = 1; +            stvp->output_semantic_name[slot] = TGSI_SEMANTIC_COLOR; +            stvp->output_semantic_index[slot] = 1;              break;           case VERT_RESULT_BFC0: -            vs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR; -            vs_output_semantic_index[slot] = 0; +            stvp->output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR; +            stvp->output_semantic_index[slot] = 0;              break;           case VERT_RESULT_BFC1: -            vs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR; -            vs_output_semantic_index[slot] = 1; +            stvp->output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR; +            stvp->output_semantic_index[slot] = 1;              break;           case VERT_RESULT_FOGC: -            vs_output_semantic_name[slot] = TGSI_SEMANTIC_FOG; -            vs_output_semantic_index[slot] = 0; +            stvp->output_semantic_name[slot] = TGSI_SEMANTIC_FOG; +            stvp->output_semantic_index[slot] = 0;              break;           case VERT_RESULT_PSIZ: -            vs_output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE; -            vs_output_semantic_index[slot] = 0; +            stvp->output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE; +            stvp->output_semantic_index[slot] = 0;              break;           case VERT_RESULT_EDGE:              assert(0);              break; +           case VERT_RESULT_TEX0:           case VERT_RESULT_TEX1:           case VERT_RESULT_TEX2: @@ -178,87 +163,50 @@ st_translate_vertex_program(struct st_context *st,           case VERT_RESULT_TEX5:           case VERT_RESULT_TEX6:           case VERT_RESULT_TEX7: -            /* fall-through */ +            stvp->output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; +            stvp->output_semantic_index[slot] = attr - VERT_RESULT_TEX0; +            break; +           case VERT_RESULT_VAR0: -            /* fall-through */           default: -            assert(slot < Elements(vs_output_semantic_name)); -            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++; -            } +            assert(attr < VERT_RESULT_MAX); +            stvp->output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; +            stvp->output_semantic_index[slot] = (FRAG_ATTRIB_VAR0 -  +                                                FRAG_ATTRIB_TEX0 + +                                                attr -  +                                                VERT_RESULT_VAR0); +            break;           }        }     } +} -   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; -   } - -#if 0 /* debug */ -   { -      GLuint i; -      printf("outputMapping? %d\n", outputMapping ? 1 : 0); -      if (outputMapping) { -         printf("attr -> slot\n"); -         for (i = 0; i < 16;  i++) { -            printf(" %2d       %3d\n", i, outputMapping[i]); -         } -      } -      printf("slot    sem_name  sem_index\n"); -      for (i = 0; i < vs_num_outputs; i++) { -         printf(" %2d         %d         %d\n", -                i, -                vs_output_semantic_name[i], -                vs_output_semantic_index[i]); -      } -   } -#endif -   /* free old shader state, if any */ -   if (stvp->state.tokens) { -      st_free_tokens(stvp->state.tokens); -      stvp->state.tokens = NULL; -   } -   if (stvp->driver_shader) { -      cso_delete_vertex_shader(st->cso_context, stvp->driver_shader); -      stvp->driver_shader = NULL; -   } +struct st_vp_varient * +st_translate_vertex_program(struct st_context *st, +                            struct st_vertex_program *stvp, +                            const struct st_vp_varient_key *key) +{ +   struct st_vp_varient *vpv = CALLOC_STRUCT(st_vp_varient); +   struct pipe_context *pipe = st->pipe; -   stvp->state.tokens =  +   vpv->state.tokens =         st_translate_mesa_program(st->ctx,                                  TGSI_PROCESSOR_VERTEX,                                  &stvp->Base.Base,                                  /* inputs */ -                                vs_num_inputs, +                                stvp->num_inputs,                                  stvp->input_to_index,                                  NULL, /* input semantic name */                                  NULL, /* input semantic index */                                  NULL,                                  /* outputs */ -                                vs_num_outputs, -                                outputMapping, -                                vs_output_semantic_name, -                                vs_output_semantic_index ); +                                stvp->num_outputs, +                                stvp->result_to_output, +                                stvp->output_semantic_name, +                                stvp->output_semantic_index ); -   stvp->num_inputs = vs_num_inputs; -   stvp->driver_shader = pipe->create_vs_state(pipe, &stvp->state); +   vpv->driver_shader = pipe->create_vs_state(pipe, &vpv->state);     if ((ST_DEBUG & DEBUG_TGSI) && (ST_DEBUG & DEBUG_MESA)) {        _mesa_print_program(&stvp->Base.Base); @@ -266,9 +214,11 @@ st_translate_vertex_program(struct st_context *st,     }     if (ST_DEBUG & DEBUG_TGSI) { -      tgsi_dump( stvp->state.tokens, 0 ); +      tgsi_dump( vpv->state.tokens, 0 );        debug_printf("\n");     } + +   return vpv;  } @@ -291,7 +241,6 @@ st_translate_fragment_program(struct st_context *st,     GLuint attr;     const GLbitfield inputsRead = stfp->Base.Base.InputsRead;     GLuint vslot = 0; -   GLuint num_generic = 0;     uint fs_num_inputs = 0; @@ -341,14 +290,25 @@ st_translate_fragment_program(struct st_context *st,              break;           case FRAG_ATTRIB_FACE:              stfp->input_semantic_name[slot] = TGSI_SEMANTIC_FACE; -            stfp->input_semantic_index[slot] = num_generic++; +            stfp->input_semantic_index[slot] = 0;              interpMode[slot] = TGSI_INTERPOLATE_CONSTANT;              break; -         case FRAG_ATTRIB_PNTC: -            stfp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; -            stfp->input_semantic_index[slot] = num_generic++; -            interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; -            break; + +            /* In most cases, there is nothing special about these +             * inputs, so adopt a convention to use the generic +             * semantic name and the mesa FRAG_ATTRIB_ number as the +             * index.  +             *  +             * All that is required is that the vertex shader labels +             * its own outputs similarly, and that the vertex shader +             * generates at least every output required by the +             * fragment shader plus fixed-function hardware (such as +             * BFC). +             *  +             * There is no requirement that semantic indexes start at +             * zero or be restricted to a particular range -- nobody +             * should be building tables based on semantic index. +             */           case FRAG_ATTRIB_TEX0:           case FRAG_ATTRIB_TEX1:           case FRAG_ATTRIB_TEX2: @@ -357,16 +317,17 @@ st_translate_fragment_program(struct st_context *st,           case FRAG_ATTRIB_TEX5:           case FRAG_ATTRIB_TEX6:           case FRAG_ATTRIB_TEX7: -            stfp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; -            stfp->input_semantic_index[slot] = num_generic++; -            interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; -            break; +         case FRAG_ATTRIB_PNTC:           case FRAG_ATTRIB_VAR0: -            /* fall-through */           default: +            /* Actually, let's try and zero-base this just for +             * readability of the generated TGSI. +             */ +            assert(attr >= FRAG_ATTRIB_TEX0); +            stfp->input_semantic_index[slot] = (attr - FRAG_ATTRIB_TEX0);              stfp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; -            stfp->input_semantic_index[slot] = num_generic++;              interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; +            break;           }        }     } diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h index e2e5eddef2..88aadbd751 100644 --- a/src/mesa/state_tracker/st_program.h +++ b/src/mesa/state_tracker/st_program.h @@ -64,41 +64,70 @@ struct st_fragment_program     struct pipe_shader_state state;     void *driver_shader; -   GLuint param_state; - -   /** List of vertex programs which have been translated such that their -    * outputs match this fragment program's inputs. -    */ -   struct translated_vertex_program *vertex_programs; -     /** Program prefixed with glBitmap prologue */     struct st_fragment_program *bitmap_program;     uint bitmap_sampler;  }; + +struct st_vp_varient_key +{ +   char dummy;                  /* currently unused */ +}; + + +/** + * This represents a vertex program, especially translated to match + * the inputs of a particular fragment shader. + */ +struct st_vp_varient +{ +   /* Parameters which generated this translated version of a vertex +    * shader: +    */ +   struct st_vp_varient_key key; + +   /** TGSI tokens -- why? +    */ +   struct pipe_shader_state state; + +   /** Driver's compiled shader */ +   void *driver_shader; + +   /** For using our private draw module (glRasterPos) */ +   struct draw_vertex_shader *draw_shader; + +   /** Next in linked list */ +   struct st_vp_varient *next;   +}; + + + +  /**   * Derived from Mesa gl_fragment_program:   */  struct st_vertex_program  {     struct gl_vertex_program Base;  /**< The Mesa vertex program */ -   GLuint serialNo; +   GLuint serialNo, lastSerialNo;     /** maps a Mesa VERT_ATTRIB_x to a packed TGSI input index */     GLuint input_to_index[VERT_ATTRIB_MAX];     /** maps a TGSI input index back to a Mesa VERT_ATTRIB_x */     GLuint index_to_input[PIPE_MAX_SHADER_INPUTS]; -     GLuint num_inputs; -   struct pipe_shader_state state; -   void *driver_shader; +   /** Maps VERT_RESULT_x to slot */ +   GLuint result_to_output[VERT_RESULT_MAX]; +   ubyte output_semantic_name[VERT_RESULT_MAX]; +   ubyte output_semantic_index[VERT_RESULT_MAX]; +   GLuint num_outputs; -   /** For using our private draw module (glRasterPos) */ -   struct draw_vertex_shader *draw_shader; - -   GLuint param_state; +   /** List of translated varients of this vertex program. +    */ +   struct st_vp_varient *varients;  }; @@ -143,13 +172,21 @@ st_translate_fragment_program(struct st_context *st,                                const GLuint inputMapping[]); +/* Called after program string change, discard all previous + * compilation results. + */  extern void +st_prepare_vertex_program(struct st_context *st, +                          struct st_vertex_program *stvp); + +extern struct st_vp_varient *  st_translate_vertex_program(struct st_context *st, -                            struct st_vertex_program *vp, -                            const GLuint vert_output_to_slot[], -                            const ubyte *fs_input_semantic_name, -                            const ubyte *fs_input_semantic_index); +                            struct st_vertex_program *stvp, +                            const struct st_vp_varient_key *key); +void +st_vp_release_varients( struct st_context *st, +                        struct st_vertex_program *stvp );  extern void  st_print_shaders(GLcontext *ctx); | 
