Mesa (master): st/mesa: add st_variant base class to simplify code for shader variants

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Nov 26 20:15:51 UTC 2019


Module: Mesa
Branch: master
Commit: ed1ff99da7026de3bb10ab4219f75424116124b1
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=ed1ff99da7026de3bb10ab4219f75424116124b1

Author: Marek Olšák <marek.olsak at amd.com>
Date:   Mon Nov 25 17:58:45 2019 -0500

st/mesa: add st_variant base class to simplify code for shader variants

Reviewed-by: Timothy Arceri <tarceri at itsqueeze.com>

---

 src/mesa/state_tracker/st_atom_shader.c   |  18 +-
 src/mesa/state_tracker/st_cb_bitmap.c     |   2 +-
 src/mesa/state_tracker/st_cb_drawpixels.c |   4 +-
 src/mesa/state_tracker/st_cb_program.c    |  31 +--
 src/mesa/state_tracker/st_glsl_to_nir.cpp |   8 +-
 src/mesa/state_tracker/st_program.c       | 310 +++++++++---------------------
 src/mesa/state_tracker/st_program.h       |  75 ++++----
 src/mesa/state_tracker/st_shader_cache.c  |   8 +-
 8 files changed, 149 insertions(+), 307 deletions(-)

diff --git a/src/mesa/state_tracker/st_atom_shader.c b/src/mesa/state_tracker/st_atom_shader.c
index b18b33e5000..10d21905780 100644
--- a/src/mesa/state_tracker/st_atom_shader.c
+++ b/src/mesa/state_tracker/st_atom_shader.c
@@ -109,10 +109,10 @@ st_update_fp( struct st_context *st )
    if (st->shader_has_one_variant[MESA_SHADER_FRAGMENT] &&
        !stfp->ati_fs && /* ATI_fragment_shader always has multiple variants */
        !stfp->Base.ExternalSamplersUsed && /* external samplers need variants */
-       stfp->fp_variants &&
-       !stfp->fp_variants->key.drawpixels &&
-       !stfp->fp_variants->key.bitmap) {
-      shader = stfp->fp_variants->driver_shader;
+       stfp->variants &&
+       !st_fp_variant(stfp->variants)->key.drawpixels &&
+       !st_fp_variant(stfp->variants)->key.bitmap) {
+      shader = stfp->variants->driver_shader;
    } else {
       struct st_fp_variant_key key;
 
@@ -160,7 +160,7 @@ st_update_fp( struct st_context *st )
 
       key.external = st_get_external_sampler_key(st, &stfp->Base);
 
-      shader = st_get_fp_variant(st, stfp, &key)->driver_shader;
+      shader = st_get_fp_variant(st, stfp, &key)->base.driver_shader;
    }
 
    st_reference_prog(st, &st->fp, stfp);
@@ -186,9 +186,9 @@ st_update_vp( struct st_context *st )
    assert(stvp->Base.Target == GL_VERTEX_PROGRAM_ARB);
 
    if (st->shader_has_one_variant[MESA_SHADER_VERTEX] &&
-       stvp->vp_variants &&
-       stvp->vp_variants->key.passthrough_edgeflags == st->vertdata_edgeflags) {
-      st->vp_variant = stvp->vp_variants;
+       stvp->variants &&
+       st_vp_variant(stvp->variants)->key.passthrough_edgeflags == st->vertdata_edgeflags) {
+      st->vp_variant = st_vp_variant(stvp->variants);
    } else {
       struct st_common_variant_key key;
 
@@ -236,7 +236,7 @@ st_update_vp( struct st_context *st )
    st_reference_prog(st, &st->vp, stvp);
 
    cso_set_vertex_shader_handle(st->cso_context, 
-                                st->vp_variant->driver_shader);
+                                st->vp_variant->base.driver_shader);
 }
 
 
diff --git a/src/mesa/state_tracker/st_cb_bitmap.c b/src/mesa/state_tracker/st_cb_bitmap.c
index 676fb12be55..112af82815a 100644
--- a/src/mesa/state_tracker/st_cb_bitmap.c
+++ b/src/mesa/state_tracker/st_cb_bitmap.c
@@ -212,7 +212,7 @@ setup_render_state(struct gl_context *ctx,
    cso_set_rasterizer(cso, &st->bitmap.rasterizer);
 
    /* fragment shader state: TEX lookup program */
-   cso_set_fragment_shader_handle(cso, fpv->driver_shader);
+   cso_set_fragment_shader_handle(cso, fpv->base.driver_shader);
 
    /* vertex shader state: position + texcoord pass-through */
    cso_set_vertex_shader_handle(cso, st->passthrough_vs);
diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c
index 6b47548d33b..fc11bc3ae47 100644
--- a/src/mesa/state_tracker/st_cb_drawpixels.c
+++ b/src/mesa/state_tracker/st_cb_drawpixels.c
@@ -1363,7 +1363,7 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y,
       fpv = (format != GL_COLOR_INDEX) ? get_color_fp_variant(st) :
                                          get_color_index_fp_variant(st);
 
-      driver_fp = fpv->driver_shader;
+      driver_fp = fpv->base.driver_shader;
 
       if (ctx->Pixel.MapColorFlag && format != GL_COLOR_INDEX) {
          pipe_sampler_view_reference(&sv[1],
@@ -1741,7 +1741,7 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
 
       rbRead = st_get_color_read_renderbuffer(ctx);
 
-      driver_fp = fpv->driver_shader;
+      driver_fp = fpv->base.driver_shader;
 
       if (ctx->Pixel.MapColorFlag) {
          pipe_sampler_view_reference(&sv[1],
diff --git a/src/mesa/state_tracker/st_cb_program.c b/src/mesa/state_tracker/st_cb_program.c
index 0bc6e90ee07..bf0b5e6a05f 100644
--- a/src/mesa/state_tracker/st_cb_program.c
+++ b/src/mesa/state_tracker/st_cb_program.c
@@ -87,12 +87,7 @@ st_delete_program(struct gl_context *ctx, struct gl_program *prog)
    struct st_context *st = st_context(ctx);
    struct st_program *stp = st_program(prog);
 
-   if (prog->Target == GL_VERTEX_PROGRAM_ARB)
-      st_release_vp_variants(st, stp);
-   if (prog->Target == GL_FRAGMENT_PROGRAM_ARB)
-      st_release_fp_variants(st, stp);
-   else
-      st_release_common_variants(st, stp);
+   st_release_variants(st, stp);
 
    if (stp->glsl_to_tgsi)
       free_glsl_to_tgsi_visitor(stp->glsl_to_tgsi);
@@ -117,6 +112,8 @@ st_program_string_notify( struct gl_context *ctx,
    /* GLSL-to-NIR should not end up here. */
    assert(!stp->shader_program);
 
+   st_release_variants(st, stp);
+
    if (target == GL_FRAGMENT_PROGRAM_ARB ||
        target == GL_FRAGMENT_SHADER_ATI) {
       if (target == GL_FRAGMENT_SHADER_ATI) {
@@ -126,15 +123,12 @@ st_program_string_notify( struct gl_context *ctx,
          st_init_atifs_prog(ctx, prog);
       }
 
-      st_release_fp_variants(st, stp);
       if (!st_translate_fragment_program(st, stp))
          return false;
    } else if (target == GL_VERTEX_PROGRAM_ARB) {
-      st_release_vp_variants(st, stp);
       if (!st_translate_vertex_program(st, stp))
          return false;
    } else {
-      st_release_common_variants(st, stp);
       if (!st_translate_common_program(st, stp))
          return false;
    }
@@ -182,23 +176,8 @@ st_get_shader_program_completion_status(struct gl_context *ctx,
       if (!linked || !linked->Program)
          continue;
 
-      switch (i) {
-      case MESA_SHADER_VERTEX:
-         if (st_program(linked->Program)->vp_variants)
-            sh = st_program(linked->Program)->vp_variants->driver_shader;
-         break;
-      case MESA_SHADER_FRAGMENT:
-         if (st_program(linked->Program)->fp_variants)
-            sh = st_program(linked->Program)->fp_variants->driver_shader;
-         break;
-      case MESA_SHADER_TESS_CTRL:
-      case MESA_SHADER_TESS_EVAL:
-      case MESA_SHADER_GEOMETRY:
-      case MESA_SHADER_COMPUTE:
-         if (st_program(linked->Program)->variants)
-            sh = st_program(linked->Program)->variants->driver_shader;
-         break;
-      }
+      if (st_program(linked->Program)->variants)
+         sh = st_program(linked->Program)->variants->driver_shader;
 
       unsigned type = pipe_shader_type_from_mesa(i);
 
diff --git a/src/mesa/state_tracker/st_glsl_to_nir.cpp b/src/mesa/state_tracker/st_glsl_to_nir.cpp
index c7a1e12530d..7a417d98f14 100644
--- a/src/mesa/state_tracker/st_glsl_to_nir.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_nir.cpp
@@ -785,13 +785,7 @@ st_link_nir(struct gl_context *ctx,
 
       st_store_ir_in_disk_cache(st, prog, true);
 
-      if (prog->info.stage == MESA_SHADER_VERTEX)
-	 st_release_vp_variants(st, stp);
-      else if (prog->info.stage == MESA_SHADER_FRAGMENT)
-	 st_release_fp_variants(st, stp);
-      else
-	 st_release_common_variants(st, stp);
-
+      st_release_variants(st, stp);
       st_finalize_program(st, prog);
 
       /* The GLSL IR won't be needed anymore. */
diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c
index 53781e6c01e..2dd9227ddd7 100644
--- a/src/mesa/state_tracker/st_program.c
+++ b/src/mesa/state_tracker/st_program.c
@@ -208,127 +208,23 @@ st_set_prog_affected_state_flags(struct gl_program *prog)
    }
 }
 
-static void
-delete_ir(struct pipe_shader_state *ir)
-{
-   if (ir->tokens) {
-      ureg_free_tokens(ir->tokens);
-      ir->tokens = NULL;
-   }
-
-   /* Note: Any setup of ->ir.nir that has had pipe->create_*_state called on
-    * it has resulted in the driver taking ownership of the NIR.  Those
-    * callers should be NULLing out the nir field in any pipe_shader_state
-    * that might have this called in order to indicate that.
-    *
-    * GLSL IR and ARB programs will have set gl_program->nir to the same
-    * shader as ir->ir.nir, so it will be freed by _mesa_delete_program().
-    */
-}
 
 /**
- * Delete a vertex program variant.  Note the caller must unlink
- * the variant from the linked list.
+ * Delete a shader variant.  Note the caller must unlink the variant from
+ * the linked list.
  */
 static void
-delete_vp_variant(struct st_context *st, struct st_vp_variant *vpv)
-{
-   if (vpv->driver_shader) {
-      if (st->has_shareable_shaders || vpv->key.st == st) {
-         cso_delete_vertex_shader(st->cso_context, vpv->driver_shader);
-      } else {
-         st_save_zombie_shader(vpv->key.st, PIPE_SHADER_VERTEX,
-                               vpv->driver_shader);
-      }
-   }
-
-   if (vpv->draw_shader)
-      draw_delete_vertex_shader( st->draw, vpv->draw_shader );
-
-   if (vpv->tokens)
-      ureg_free_tokens(vpv->tokens);
-
-   free( vpv );
-}
-
-
-
-/**
- * Clean out any old compilations:
- */
-void
-st_release_vp_variants( struct st_context *st,
-                        struct st_program *stvp )
-{
-   struct st_vp_variant *vpv;
-
-   for (vpv = stvp->vp_variants; vpv; ) {
-      struct st_vp_variant *next = vpv->next;
-      delete_vp_variant(st, vpv);
-      vpv = next;
-   }
-
-   stvp->vp_variants = NULL;
-
-   delete_ir(&stvp->state);
-}
-
-
-
-/**
- * Delete a fragment program variant.  Note the caller must unlink
- * the variant from the linked list.
- */
-static void
-delete_fp_variant(struct st_context *st, struct st_fp_variant *fpv)
-{
-   if (fpv->driver_shader) {
-      if (st->has_shareable_shaders || fpv->key.st == st) {
-         cso_delete_fragment_shader(st->cso_context, fpv->driver_shader);
-      } else {
-         st_save_zombie_shader(fpv->key.st, PIPE_SHADER_FRAGMENT,
-                               fpv->driver_shader);
-      }
-   }
-
-   free(fpv);
-}
-
-
-/**
- * Free all variants of a fragment program.
- */
-void
-st_release_fp_variants(struct st_context *st, struct st_program *stfp)
-{
-   struct st_fp_variant *fpv;
-
-   for (fpv = stfp->fp_variants; fpv; ) {
-      struct st_fp_variant *next = fpv->next;
-      delete_fp_variant(st, fpv);
-      fpv = next;
-   }
-
-   stfp->fp_variants = NULL;
-
-   delete_ir(&stfp->state);
-}
-
-
-/**
- * Delete a basic program variant.  Note the caller must unlink
- * the variant from the linked list.
- */
-static void
-delete_common_variant(struct st_context *st, struct st_common_variant *v,
-                      GLenum target)
+delete_variant(struct st_context *st, struct st_variant *v, GLenum target)
 {
    if (v->driver_shader) {
-      if (st->has_shareable_shaders || v->key.st == st) {
+      if (st->has_shareable_shaders || v->st == st) {
          /* The shader's context matches the calling context, or we
           * don't care.
           */
          switch (target) {
+         case GL_VERTEX_PROGRAM_ARB:
+            cso_delete_vertex_shader(st->cso_context, v->driver_shader);
+            break;
          case GL_TESS_CONTROL_PROGRAM_NV:
             cso_delete_tessctrl_shader(st->cso_context, v->driver_shader);
             break;
@@ -338,6 +234,9 @@ delete_common_variant(struct st_context *st, struct st_common_variant *v,
          case GL_GEOMETRY_PROGRAM_NV:
             cso_delete_geometry_shader(st->cso_context, v->driver_shader);
             break;
+         case GL_FRAGMENT_PROGRAM_ARB:
+            cso_delete_fragment_shader(st->cso_context, v->driver_shader);
+            break;
          case GL_COMPUTE_PROGRAM_NV:
             cso_delete_compute_shader(st->cso_context, v->driver_shader);
             break;
@@ -348,24 +247,23 @@ delete_common_variant(struct st_context *st, struct st_common_variant *v,
          /* We can't delete a shader with a context different from the one
           * that created it.  Add it to the creating context's zombie list.
           */
-         enum pipe_shader_type type;
-         switch (target) {
-         case GL_TESS_CONTROL_PROGRAM_NV:
-            type = PIPE_SHADER_TESS_CTRL;
-            break;
-         case GL_TESS_EVALUATION_PROGRAM_NV:
-            type = PIPE_SHADER_TESS_EVAL;
-            break;
-         case GL_GEOMETRY_PROGRAM_NV:
-            type = PIPE_SHADER_GEOMETRY;
-            break;
-         default:
-            unreachable("");
-         }
-         st_save_zombie_shader(v->key.st, type, v->driver_shader);
+         enum pipe_shader_type type =
+            pipe_shader_type_from_mesa(_mesa_program_enum_to_shader_stage(target));
+
+         st_save_zombie_shader(v->st, type, v->driver_shader);
       }
    }
 
+   if (target == GL_VERTEX_PROGRAM_ARB) {
+      struct st_vp_variant *vpv = (struct st_vp_variant *)v;
+
+      if (vpv->draw_shader)
+         draw_delete_vertex_shader( st->draw, vpv->draw_shader );
+
+      if (vpv->tokens)
+         ureg_free_tokens(vpv->tokens);
+   }
+
    free(v);
 }
 
@@ -374,18 +272,31 @@ delete_common_variant(struct st_context *st, struct st_common_variant *v,
  * Free all basic program variants.
  */
 void
-st_release_common_variants(struct st_context *st, struct st_program *p)
+st_release_variants(struct st_context *st, struct st_program *p)
 {
-   struct st_common_variant *v;
+   struct st_variant *v;
 
    for (v = p->variants; v; ) {
-      struct st_common_variant *next = v->next;
-      delete_common_variant(st, v, p->Base.Target);
+      struct st_variant *next = v->next;
+      delete_variant(st, v, p->Base.Target);
       v = next;
    }
 
    p->variants = NULL;
-   delete_ir(&p->state);
+
+   if (p->state.tokens) {
+      ureg_free_tokens(p->state.tokens);
+      p->state.tokens = NULL;
+   }
+
+   /* Note: Any setup of ->ir.nir that has had pipe->create_*_state called on
+    * it has resulted in the driver taking ownership of the NIR.  Those
+    * callers should be NULLing out the nir field in any pipe_shader_state
+    * that might have this called in order to indicate that.
+    *
+    * GLSL IR and ARB programs will have set gl_program->nir to the same
+    * shader as ir->ir.nir, so it will be freed by _mesa_delete_program().
+    */
 }
 
 void
@@ -745,7 +656,7 @@ st_create_vp_variant(struct st_context *st,
       if (ST_DEBUG & DEBUG_PRINT_IR)
          nir_print_shader(state.ir.nir, stderr);
 
-      vpv->driver_shader = pipe->create_vs_state(pipe, &state);
+      vpv->base.driver_shader = pipe->create_vs_state(pipe, &state);
 
       /* When generating a NIR program, we usually don't have TGSI tokens.
        * However, we do create them for ARB_vertex_program / fixed-function VS
@@ -798,7 +709,7 @@ st_create_vp_variant(struct st_context *st,
    if (ST_DEBUG & DEBUG_PRINT_IR)
       tgsi_dump(state.tokens, 0);
 
-   vpv->driver_shader = pipe->create_vs_state(pipe, &state);
+   vpv->base.driver_shader = pipe->create_vs_state(pipe, &state);
    /* Save this for selection/feedback/rasterpos. */
    vpv->tokens = state.tokens;
    return vpv;
@@ -817,7 +728,8 @@ st_get_vp_variant(struct st_context *st,
    struct st_vp_variant *vpv;
 
    /* Search for existing variant */
-   for (vpv = stp->vp_variants; vpv; vpv = vpv->next) {
+   for (vpv = st_vp_variant(stp->variants); vpv;
+        vpv = st_vp_variant(vpv->base.next)) {
       if (memcmp(&vpv->key, key, sizeof(*key)) == 0) {
          break;
       }
@@ -827,16 +739,18 @@ st_get_vp_variant(struct st_context *st,
       /* create now */
       vpv = st_create_vp_variant(st, stp, key);
       if (vpv) {
-          for (unsigned index = 0; index < vpv->num_inputs; ++index) {
-             unsigned attr = stvp->index_to_input[index];
-             if (attr == ST_DOUBLE_ATTRIB_PLACEHOLDER)
-                continue;
-             vpv->vert_attrib_mask |= 1u << attr;
-          }
+         vpv->base.st = key->st;
+
+         for (unsigned index = 0; index < vpv->num_inputs; ++index) {
+            unsigned attr = stvp->index_to_input[index];
+            if (attr == ST_DOUBLE_ATTRIB_PLACEHOLDER)
+               continue;
+            vpv->vert_attrib_mask |= 1u << attr;
+         }
 
          /* insert into list */
-         vpv->next = stp->vp_variants;
-         stp->vp_variants = vpv;
+         vpv->base.next = stp->variants;
+         stp->variants = &vpv->base;
       }
    }
 
@@ -1366,7 +1280,7 @@ st_create_fp_variant(struct st_context *st,
       if (ST_DEBUG & DEBUG_PRINT_IR)
          nir_print_shader(state.ir.nir, stderr);
 
-      variant->driver_shader = pipe->create_fs_state(pipe, &state);
+      variant->base.driver_shader = pipe->create_fs_state(pipe, &state);
       variant->key = *key;
 
       return variant;
@@ -1498,7 +1412,7 @@ st_create_fp_variant(struct st_context *st,
       tgsi_dump(state.tokens, 0);
 
    /* fill in variant */
-   variant->driver_shader = pipe->create_fs_state(pipe, &state);
+   variant->base.driver_shader = pipe->create_fs_state(pipe, &state);
    variant->key = *key;
 
    if (state.tokens != stfp->state.tokens)
@@ -1517,7 +1431,8 @@ st_get_fp_variant(struct st_context *st,
    struct st_fp_variant *fpv;
 
    /* Search for existing variant */
-   for (fpv = stfp->fp_variants; fpv; fpv = fpv->next) {
+   for (fpv = st_fp_variant(stfp->variants); fpv;
+        fpv = st_fp_variant(fpv->base.next)) {
       if (memcmp(&fpv->key, key, sizeof(*key)) == 0) {
          break;
       }
@@ -1527,6 +1442,8 @@ st_get_fp_variant(struct st_context *st,
       /* create new */
       fpv = st_create_fp_variant(st, stfp, key);
       if (fpv) {
+         fpv->base.st = key->st;
+
          if (key->bitmap || key->drawpixels) {
             /* Regular variants should always come before the
              * bitmap & drawpixels variants, (unless there
@@ -1534,17 +1451,17 @@ st_get_fp_variant(struct st_context *st,
              * st_update_fp can take a fast path when
              * shader_has_one_variant is set.
              */
-            if (!stfp->fp_variants) {
-               stfp->fp_variants = fpv;
+            if (!stfp->variants) {
+               stfp->variants = &fpv->base;
             } else {
                /* insert into list after the first one */
-               fpv->next = stfp->fp_variants->next;
-               stfp->fp_variants->next = fpv;
+               fpv->base.next = stfp->variants->next;
+               stfp->variants->next = &fpv->base;
             }
          } else {
             /* insert into list */
-            fpv->next = stfp->fp_variants;
-            stfp->fp_variants = fpv;
+            fpv->base.next = stfp->variants;
+            stfp->variants = &fpv->base;
          }
       }
    }
@@ -1744,25 +1661,24 @@ st_translate_common_program(struct st_context *st,
 /**
  * Get/create a basic program variant.
  */
-struct st_common_variant *
+struct st_variant *
 st_get_common_variant(struct st_context *st,
                       struct st_program *prog,
                       const struct st_common_variant_key *key)
 {
    struct pipe_context *pipe = st->pipe;
-   struct st_common_variant *v;
+   struct st_variant *v;
    struct pipe_shader_state state = {0};
 
    /* Search for existing variant */
    for (v = prog->variants; v; v = v->next) {
-      if (memcmp(&v->key, key, sizeof(*key)) == 0) {
+      if (memcmp(&st_common_variant(v)->key, key, sizeof(*key)) == 0)
          break;
-      }
    }
 
    if (!v) {
       /* create new */
-      v = CALLOC_STRUCT(st_common_variant);
+      v = (struct st_variant*)CALLOC_STRUCT(st_common_variant);
       if (v) {
 	 if (prog->state.type == PIPE_SHADER_IR_NIR) {
             bool finalize = false;
@@ -1837,7 +1753,8 @@ st_get_common_variant(struct st_context *st,
             return NULL;
          }
 
-         v->key = *key;
+         st_common_variant(v)->key = *key;
+         v->st = key->st;
 
          /* insert into list */
          v->next = prog->variants;
@@ -1859,74 +1776,21 @@ destroy_program_variants(struct st_context *st, struct gl_program *target)
    if (!target || target == &_mesa_DummyProgram)
       return;
 
-   switch (target->Target) {
-   case GL_VERTEX_PROGRAM_ARB:
-      {
-         struct st_program *stvp = (struct st_program *) target;
-         struct st_vp_variant *vpv, **prevPtr = &stvp->vp_variants;
-
-         for (vpv = stvp->vp_variants; vpv; ) {
-            struct st_vp_variant *next = vpv->next;
-            if (vpv->key.st == st) {
-               /* unlink from list */
-               *prevPtr = next;
-               /* destroy this variant */
-               delete_vp_variant(st, vpv);
-            }
-            else {
-               prevPtr = &vpv->next;
-            }
-            vpv = next;
-         }
-      }
-      break;
-   case GL_FRAGMENT_PROGRAM_ARB:
-      {
-         struct st_program *stfp =
-            (struct st_program *) target;
-         struct st_fp_variant *fpv, **prevPtr = &stfp->fp_variants;
-
-         for (fpv = stfp->fp_variants; fpv; ) {
-            struct st_fp_variant *next = fpv->next;
-            if (fpv->key.st == st) {
-               /* unlink from list */
-               *prevPtr = next;
-               /* destroy this variant */
-               delete_fp_variant(st, fpv);
-            }
-            else {
-               prevPtr = &fpv->next;
-            }
-            fpv = next;
-         }
+   struct st_program *p = st_program(target);
+   struct st_variant *v, **prevPtr = &p->variants;
+
+   for (v = p->variants; v; ) {
+      struct st_variant *next = v->next;
+      if (v->st == st) {
+         /* unlink from list */
+         *prevPtr = next;
+         /* destroy this variant */
+         delete_variant(st, v, target->Target);
       }
-      break;
-   case GL_GEOMETRY_PROGRAM_NV:
-   case GL_TESS_CONTROL_PROGRAM_NV:
-   case GL_TESS_EVALUATION_PROGRAM_NV:
-   case GL_COMPUTE_PROGRAM_NV:
-      {
-         struct st_program *p = st_program(target);
-         struct st_common_variant *v, **prevPtr = &p->variants;
-
-         for (v = p->variants; v; ) {
-            struct st_common_variant *next = v->next;
-            if (v->key.st == st) {
-               /* unlink from list */
-               *prevPtr = next;
-               /* destroy this variant */
-               delete_common_variant(st, v, target->Target);
-            }
-            else {
-               prevPtr = &v->next;
-            }
-            v = next;
-         }
+      else {
+         prevPtr = &v->next;
       }
-      break;
-   default:
-      _mesa_problem(NULL, "Unexpected program target 0x%x in "
-                    "destroy_program_variants_cb()", target->Target);
+      v = next;
    }
 }
 
diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h
index 9ad23235bcb..62d82c2bf84 100644
--- a/src/mesa/state_tracker/st_program.h
+++ b/src/mesa/state_tracker/st_program.h
@@ -139,27 +139,36 @@ struct st_fp_variant_key
    struct st_external_sampler_key external;
 };
 
+/**
+ * Base class for shader variants.
+ */
+struct st_variant
+{
+   /** next in linked list */
+   struct st_variant *next;
+
+   /** st_context from the shader key */
+   struct st_context *st;
+
+   void *driver_shader;
+};
 
 /**
  * Variant of a fragment program.
  */
 struct st_fp_variant
 {
+   struct st_variant base;
+
    /** Parameters which generated this version of fragment program */
    struct st_fp_variant_key key;
 
-   /** Driver's compiled shader */
-   void *driver_shader;
-
    /** For glBitmap variants */
    uint bitmap_sampler;
 
    /** For glDrawPixels variants */
    unsigned drawpix_sampler;
    unsigned pixelmap_sampler;
-
-   /** next in linked list */
-   struct st_fp_variant *next;
 };
 
 
@@ -190,6 +199,8 @@ struct st_common_variant_key
  */
 struct st_vp_variant
 {
+   struct st_variant base;
+
    /* Parameters which generated this translated version of a vertex
     * shader:
     */
@@ -201,15 +212,9 @@ struct st_vp_variant
     */
    const struct tgsi_token *tokens;
 
-   /** 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_variant *next;  
-
    /** similar to that in st_vertex_program, but with edgeflags info too */
    GLuint num_inputs;
 
@@ -219,16 +224,14 @@ struct st_vp_variant
 
 
 /**
- * Geometry program variant.
+ * Common shader variant.
  */
 struct st_common_variant
 {
+   struct st_variant base;
+
    /* Parameters which generated this variant. */
    struct st_common_variant_key key;
-
-   void *driver_shader;
-
-   struct st_common_variant *next;
 };
 
 
@@ -243,14 +246,10 @@ struct st_program
    struct ati_fragment_shader *ati_fs;
    uint64_t affected_states; /**< ST_NEW_* flags to mark dirty when binding */
 
-  /* used when bypassing glsl_to_tgsi: */
+   /* used when bypassing glsl_to_tgsi: */
    struct gl_shader_program *shader_program;
 
-   union {
-      struct st_common_variant *variants;
-      struct st_vp_variant *vp_variants;
-      struct st_fp_variant *fp_variants;
-   };
+   struct st_variant *variants;
 };
 
 
@@ -285,6 +284,24 @@ st_reference_prog(struct st_context *st,
                            (struct gl_program *) prog);
 }
 
+static inline struct st_common_variant *
+st_common_variant(struct st_variant *v)
+{
+   return (struct st_common_variant*)v;
+}
+
+static inline struct st_vp_variant *
+st_vp_variant(struct st_variant *v)
+{
+   return (struct st_vp_variant*)v;
+}
+
+static inline struct st_fp_variant *
+st_fp_variant(struct st_variant *v)
+{
+   return (struct st_fp_variant*)v;
+}
+
 /**
  * This defines mapping from Mesa VARYING_SLOTs to TGSI GENERIC slots.
  */
@@ -309,21 +326,13 @@ st_get_fp_variant(struct st_context *st,
                   struct st_program *stfp,
                   const struct st_fp_variant_key *key);
 
-extern struct st_common_variant *
+extern struct st_variant *
 st_get_common_variant(struct st_context *st,
                       struct st_program *p,
                       const struct st_common_variant_key *key);
 
 extern void
-st_release_vp_variants( struct st_context *st,
-                        struct st_program *stvp );
-
-extern void
-st_release_fp_variants( struct st_context *st,
-                        struct st_program *stfp );
-
-extern void
-st_release_common_variants(struct st_context *st, struct st_program *p);
+st_release_variants(struct st_context *st, struct st_program *p);
 
 extern void
 st_destroy_program_variants(struct st_context *st);
diff --git a/src/mesa/state_tracker/st_shader_cache.c b/src/mesa/state_tracker/st_shader_cache.c
index 6145281573f..17cd8b0b835 100644
--- a/src/mesa/state_tracker/st_shader_cache.c
+++ b/src/mesa/state_tracker/st_shader_cache.c
@@ -184,9 +184,9 @@ st_deserialise_ir_program(struct gl_context *ctx,
    struct blob_reader blob_reader;
    blob_reader_init(&blob_reader, buffer, size);
 
-   if (prog->info.stage == MESA_SHADER_VERTEX) {
-      st_release_vp_variants(st, stp);
+   st_release_variants(st, stp);
 
+   if (prog->info.stage == MESA_SHADER_VERTEX) {
       struct st_vertex_program *stvp = (struct st_vertex_program *)stp;
       stvp->num_inputs = blob_read_uint32(&blob_reader);
       blob_copy_bytes(&blob_reader, (uint8_t *) stvp->index_to_input,
@@ -195,10 +195,6 @@ st_deserialise_ir_program(struct gl_context *ctx,
                       sizeof(stvp->input_to_index));
       blob_copy_bytes(&blob_reader, (uint8_t *) stvp->result_to_output,
                       sizeof(stvp->result_to_output));
-   } else if (prog->info.stage == MESA_SHADER_FRAGMENT) {
-      st_release_fp_variants(st, stp);
-   } else {
-      st_release_common_variants(st, stp);
    }
 
    if (prog->info.stage == MESA_SHADER_VERTEX ||




More information about the mesa-commit mailing list