Mesa (st-mesa-per-context-shaders): st/mesa: implement geometry shader varients

Brian Paul brianp at kemper.freedesktop.org
Mon Dec 13 21:09:04 UTC 2010


Module: Mesa
Branch: st-mesa-per-context-shaders
Commit: e12d6791c5e4bff60bb2e6c04414b1b4d1325f3e
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=e12d6791c5e4bff60bb2e6c04414b1b4d1325f3e

Author: Brian Paul <brianp at vmware.com>
Date:   Mon Dec 13 13:38:12 2010 -0700

st/mesa: implement geometry shader varients

Only needed in order to support per-context gallium shaders.

---

 src/mesa/state_tracker/st_atom_shader.c |   39 ++++------
 src/mesa/state_tracker/st_cb_program.c  |   28 +------
 src/mesa/state_tracker/st_context.h     |    1 +
 src/mesa/state_tracker/st_program.c     |  132 ++++++++++++++++++++++++-------
 src/mesa/state_tracker/st_program.h     |   50 +++++++++---
 5 files changed, 165 insertions(+), 85 deletions(-)

diff --git a/src/mesa/state_tracker/st_atom_shader.c b/src/mesa/state_tracker/st_atom_shader.c
index 94890e9..a0e8565 100644
--- a/src/mesa/state_tracker/st_atom_shader.c
+++ b/src/mesa/state_tracker/st_atom_shader.c
@@ -50,21 +50,6 @@
 #include "st_program.h"
 
 
-
-/*
- * Translate geometry program if needed.
- */
-static void
-translate_gp(struct st_context *st,
-             struct st_geometry_program *stgp)
-{
-   if (!stgp->tgsi.tokens) {
-      assert(stgp->Base.Base.NumInstructions > 1);
-
-      st_translate_geometry_program(st, stgp);
-   }
-}
-
 /**
  * Find a translated vertex program that corresponds to stvp and
  * has outputs matched to stfp's inputs.
@@ -224,14 +209,16 @@ const struct st_tracked_state st_update_vp = {
       _NEW_POLYGON,					/* mesa */
       ST_NEW_VERTEX_PROGRAM | ST_NEW_EDGEFLAGS_DATA	/* st */
    },
-   update_vp					/* update */
+   update_vp						/* update */
 };
 
+
+
 static void
 update_gp( struct st_context *st )
 {
-
    struct st_geometry_program *stgp;
+   struct st_gp_varient_key key;
 
    if (!st->ctx->GeometryProgram._Current) {
       cso_set_geometry_shader_handle(st->cso_context, NULL);
@@ -241,18 +228,22 @@ update_gp( struct st_context *st )
    stgp = st_geometry_program(st->ctx->GeometryProgram._Current);
    assert(stgp->Base.Base.Target == MESA_GEOMETRY_PROGRAM);
 
-   translate_gp(st, stgp);
+   memset(&key, 0, sizeof(key));
+   key.st = st;
+
+   st->gp_varient = st_get_gp_varient(st, stgp, &key);
 
    st_reference_geomprog(st, &st->gp, stgp);
 
-   cso_set_geometry_shader_handle(st->cso_context, stgp->driver_shader);
+   cso_set_geometry_shader_handle(st->cso_context,
+                                  st->gp_varient->driver_shader);
 }
 
 const struct st_tracked_state st_update_gp = {
-   "st_update_gp",					/* name */
-   {							/* dirty */
-      0,						/* mesa */
-      ST_NEW_GEOMETRY_PROGRAM                           /* st */
+   "st_update_gp",			/* name */
+   {					/* dirty */
+      0,				/* mesa */
+      ST_NEW_GEOMETRY_PROGRAM           /* st */
    },
-   update_gp  					/* update */
+   update_gp  				/* update */
 };
diff --git a/src/mesa/state_tracker/st_cb_program.c b/src/mesa/state_tracker/st_cb_program.c
index 25a135a..08d29ae 100644
--- a/src/mesa/state_tracker/st_cb_program.c
+++ b/src/mesa/state_tracker/st_cb_program.c
@@ -150,12 +150,10 @@ st_delete_program(struct gl_context *ctx, struct gl_program *prog)
       break;
    case MESA_GEOMETRY_PROGRAM:
       {
-         struct st_geometry_program *stgp = (struct st_geometry_program *) prog;
+         struct st_geometry_program *stgp =
+            (struct st_geometry_program *) prog;
 
-         if (stgp->driver_shader) {
-            cso_delete_geometry_shader(st->cso_context, stgp->driver_shader);
-            stgp->driver_shader = NULL;
-         }
+         st_gp_release_varients(st, stgp);
 
          if (stgp->tgsi.tokens) {
             st_free_tokens((void *) stgp->tgsi.tokens);
@@ -167,26 +165,13 @@ st_delete_program(struct gl_context *ctx, struct gl_program *prog)
       {
          struct st_fragment_program *stfp =
             (struct st_fragment_program *) prog;
-         st_fp_release_varients(st, stfp);
-#if 0
 
-         if (stfp->driver_shader) {
-            cso_delete_fragment_shader(st->cso_context, stfp->driver_shader);
-            stfp->driver_shader = NULL;
-         }
+         st_fp_release_varients(st, stfp);
          
          if (stfp->tgsi.tokens) {
             st_free_tokens(stfp->tgsi.tokens);
             stfp->tgsi.tokens = NULL;
          }
-
-         if (stfp->bitmap_program) {
-            struct gl_program *prg = &stfp->bitmap_program->Base.Base;
-            _mesa_reference_program(ctx, &prg, NULL);
-            stfp->bitmap_program = NULL;
-         }
-#endif
-
       }
       break;
    default:
@@ -230,10 +215,7 @@ static GLboolean st_program_string_notify( struct gl_context *ctx,
 
       stgp->serialNo++;
 
-      if (stgp->driver_shader) {
-         cso_delete_geometry_shader(st->cso_context, stgp->driver_shader);
-         stgp->driver_shader = NULL;
-      }
+      st_gp_release_varients(st, stgp);
 
       if (stgp->tgsi.tokens) {
          st_free_tokens((void *) stgp->tgsi.tokens);
diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h
index 4559769..2656522 100644
--- a/src/mesa/state_tracker/st_context.h
+++ b/src/mesa/state_tracker/st_context.h
@@ -132,6 +132,7 @@ struct st_context
 
    struct st_vp_varient *vp_varient;
    struct st_fp_varient *fp_varient;
+   struct st_gp_varient *gp_varient;
 
    struct gl_texture_object *default_texture;
 
diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c
index 795d875..18c90b7 100644
--- a/src/mesa/state_tracker/st_program.c
+++ b/src/mesa/state_tracker/st_program.c
@@ -130,6 +130,38 @@ st_fp_release_varients(struct st_context *st, struct st_fragment_program *stfp)
 }
 
 
+/**
+ * Delete a geometry program varient.  Note the caller must unlink
+ * the varient from the linked list.
+ */
+static void
+delete_gp_varient(struct st_context *st, struct st_gp_varient *gpv)
+{
+   if (gpv->driver_shader) 
+      cso_delete_geometry_shader(st->cso_context, gpv->driver_shader);
+      
+   FREE(gpv);
+}
+
+
+/**
+ * Free all varients of a geometry program.
+ */
+void
+st_gp_release_varients(struct st_context *st, struct st_geometry_program *stgp)
+{
+   struct st_gp_varient *gpv;
+
+   for (gpv = stgp->varients; gpv; ) {
+      struct st_gp_varient *next = gpv->next;
+      delete_gp_varient(st, gpv);
+      gpv = next;
+   }
+
+   stgp->varients = NULL;
+}
+
+
 
 
 /**
@@ -330,7 +362,7 @@ fail:
  * the key.
  * \return  new fragment program variant
  */
-struct st_fp_varient *
+static struct st_fp_varient *
 st_translate_fragment_program(struct st_context *st,
                               struct st_fragment_program *stfp,
                               const struct st_fp_varient_key *key)
@@ -591,10 +623,13 @@ st_get_fp_varient(struct st_context *st,
 }
 
 
-
-void
+/**
+ * Translate a geometry program to create a new varient.
+ */
+static struct st_gp_varient *
 st_translate_geometry_program(struct st_context *st,
-                              struct st_geometry_program *stgp)
+                              struct st_geometry_program *stgp,
+                              const struct st_gp_varient_key *key)
 {
    GLuint inputMapping[GEOM_ATTRIB_MAX];
    GLuint outputMapping[GEOM_RESULT_MAX];
@@ -617,12 +652,19 @@ st_translate_geometry_program(struct st_context *st,
    GLuint maxSlot = 0;
    struct ureg_program *ureg;
 
+   struct st_gp_varient *gpv;
+
+   gpv = CALLOC_STRUCT(st_gp_varient);
+   if (!gpv)
+      return NULL;
+
    _mesa_remove_output_reads(&stgp->Base.Base, PROGRAM_OUTPUT);
    _mesa_remove_output_reads(&stgp->Base.Base, PROGRAM_VARYING);
 
    ureg = ureg_create( TGSI_PROCESSOR_GEOMETRY );
    if (ureg == NULL) {
-      return;
+      FREE(gpv);
+      return NULL;
    }
 
    /* which vertex output goes to the first geometry input */
@@ -652,7 +694,7 @@ st_translate_geometry_program(struct st_context *st,
          } else
             ++gs_builtin_inputs;
 
-#if 1
+#if 0
          debug_printf("input map at %d = %d\n",
                       slot + gs_array_offset, stgp->input_map[slot + gs_array_offset]);
 #endif
@@ -794,37 +836,35 @@ st_translate_geometry_program(struct st_context *st,
       st_free_tokens(stgp->tgsi.tokens);
       stgp->tgsi.tokens = NULL;
    }
-   if (stgp->driver_shader) {
-      cso_delete_geometry_shader(st->cso_context, stgp->driver_shader);
-      stgp->driver_shader = NULL;
-   }
 
    ureg_property_gs_input_prim(ureg, stgp->Base.InputType);
    ureg_property_gs_output_prim(ureg, stgp->Base.OutputType);
    ureg_property_gs_max_vertices(ureg, stgp->Base.VerticesOut);
 
-   error  = st_translate_mesa_program(st->ctx,
-                                      TGSI_PROCESSOR_GEOMETRY,
-                                      ureg,
-                                      &stgp->Base.Base,
-                                      /* inputs */
-                                      gs_num_inputs,
-                                      inputMapping,
-                                      stgp->input_semantic_name,
-                                      stgp->input_semantic_index,
-                                      NULL,
-                                      /* outputs */
-                                      gs_num_outputs,
-                                      outputMapping,
-                                      gs_output_semantic_name,
-                                      gs_output_semantic_index,
-                                      FALSE);
-
+   error = st_translate_mesa_program(st->ctx,
+                                     TGSI_PROCESSOR_GEOMETRY,
+                                     ureg,
+                                     &stgp->Base.Base,
+                                     /* inputs */
+                                     gs_num_inputs,
+                                     inputMapping,
+                                     stgp->input_semantic_name,
+                                     stgp->input_semantic_index,
+                                     NULL,
+                                     /* outputs */
+                                     gs_num_outputs,
+                                     outputMapping,
+                                     gs_output_semantic_name,
+                                     gs_output_semantic_index,
+                                     FALSE);
 
    stgp->num_inputs = gs_num_inputs;
    stgp->tgsi.tokens = ureg_get_tokens( ureg, NULL );
    ureg_destroy( ureg );
-   stgp->driver_shader = pipe->create_gs_state(pipe, &stgp->tgsi);
+
+   /* fill in new varient */
+   gpv->driver_shader = pipe->create_gs_state(pipe, &stgp->tgsi);
+   gpv->key = *key;
 
    if ((ST_DEBUG & DEBUG_TGSI) && (ST_DEBUG & DEBUG_MESA)) {
       _mesa_print_program(&stgp->Base.Base);
@@ -835,8 +875,44 @@ st_translate_geometry_program(struct st_context *st,
       tgsi_dump(stgp->tgsi.tokens, 0);
       debug_printf("\n");
    }
+
+   return gpv;
+}
+
+
+/**
+ * Get/create geometry program variant.
+ */
+struct st_gp_varient *
+st_get_gp_varient(struct st_context *st,
+                  struct st_geometry_program *stgp,
+                  const struct st_gp_varient_key *key)
+{
+   struct st_gp_varient *gpv;
+
+   /* Search for existing varient */
+   for (gpv = stgp->varients; gpv; gpv = gpv->next) {
+      if (memcmp(&gpv->key, key, sizeof(*key)) == 0) {
+         break;
+      }
+   }
+
+   if (!gpv) {
+      /* create new */
+      gpv = st_translate_geometry_program(st, stgp, key);
+      if (gpv) {
+         /* insert into list */
+         gpv->next = stgp->varients;
+         stgp->varients = gpv;
+      }
+   }
+
+   return gpv;
 }
 
+
+
+
 /**
  * Debug- print current shader text
  */
diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h
index acbecc9..245866b 100644
--- a/src/mesa/state_tracker/st_program.h
+++ b/src/mesa/state_tracker/st_program.h
@@ -154,6 +154,29 @@ struct st_vertex_program
    struct st_vp_varient *varients;
 };
 
+
+
+struct st_gp_varient_key
+{
+   struct st_context *st;          /**< variants are per-context */
+   /* no other fields yet */
+};
+
+
+/**
+ * Geometry program variant.
+ */
+struct st_gp_varient
+{
+   /* Parameters which generated this translated version of a vertex */
+   struct st_gp_varient_key key;
+
+   void *driver_shader;
+
+   struct st_gp_varient *next;
+};
+
+
 /**
  * Derived from Mesa gl_geometry_program:
  */
@@ -179,9 +202,12 @@ struct st_geometry_program
    ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS];
 
    struct pipe_shader_state tgsi;
-   void *driver_shader;
+
+   struct st_gp_varient *varients;
 };
 
+
+
 static INLINE struct st_fragment_program *
 st_fragment_program( struct gl_fragment_program *fp )
 {
@@ -233,19 +259,17 @@ st_reference_fragprog(struct st_context *st,
 
 
 extern struct st_fp_varient *
-st_translate_fragment_program(struct st_context *st,
-                              struct st_fragment_program *fp,
-                              const struct st_fp_varient_key *key);
-
-extern struct st_fp_varient *
 st_get_fp_varient(struct st_context *st,
                   struct st_fragment_program *stfp,
                   const struct st_fp_varient_key *key);
 
 
-extern void
-st_translate_geometry_program(struct st_context *st,
-                              struct st_geometry_program *stgp);
+extern struct st_gp_varient *
+st_get_gp_varient(struct st_context *st,
+                  struct st_geometry_program *stgp,
+                  const struct st_gp_varient_key *key);
+
+
 
 /* Called after program string change, discard all previous
  * compilation results.
@@ -259,7 +283,8 @@ st_translate_vertex_program(struct st_context *st,
                             struct st_vertex_program *stvp,
                             const struct st_vp_varient_key *key);
 
-void
+
+extern void
 st_vp_release_varients( struct st_context *st,
                         struct st_vertex_program *stvp );
 
@@ -268,6 +293,11 @@ st_fp_release_varients( struct st_context *st,
                         struct st_fragment_program *stfp );
 
 extern void
+st_gp_release_varients(struct st_context *st,
+                       struct st_geometry_program *stgp);
+
+
+extern void
 st_print_shaders(struct gl_context *ctx);
 
 extern void




More information about the mesa-commit mailing list