st/mesa: add compute shader states
authorSamuel Pitoiset <samuel.pitoiset@gmail.com>
Thu, 7 Jan 2016 21:02:43 +0000 (22:02 +0100)
committerSamuel Pitoiset <samuel.pitoiset@gmail.com>
Sat, 13 Feb 2016 15:00:54 +0000 (16:00 +0100)
Changes from v2:
 - use as much common code as possible (eg. st_basic_variant)

Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Reviewed-by: Ilia Mirkin <imirkin@alum.mit.edu>
src/mesa/state_tracker/st_atom.c
src/mesa/state_tracker/st_atom.h
src/mesa/state_tracker/st_atom_shader.c
src/mesa/state_tracker/st_cb_program.c
src/mesa/state_tracker/st_context.c
src/mesa/state_tracker/st_context.h
src/mesa/state_tracker/st_extensions.c
src/mesa/state_tracker/st_program.c
src/mesa/state_tracker/st_program.h

index 2d89512e8542c3d1eae62fb9505cf4cbca3aa7a5..3427a92972f061d3b08e845cea964fba904671bd 100644 (file)
@@ -98,7 +98,7 @@ static const struct st_tracked_state *render_atoms[] =
  */
 static const struct st_tracked_state *compute_atoms[] =
 {
-   /* will be updated in the next commit */
+   &st_update_cp,
 };
 
 
index 77e2163e467097f9806700dd18e243220c4f13ca..ef33645eaa792b28b270d0881ad5faf071f3d02f 100644 (file)
@@ -58,6 +58,7 @@ extern const struct st_tracked_state st_update_gp;
 extern const struct st_tracked_state st_update_tep;
 extern const struct st_tracked_state st_update_tcp;
 extern const struct st_tracked_state st_update_vp;
+extern const struct st_tracked_state st_update_cp;
 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;
index c8650a5899ad8227d0790e285144045bbb7e9d9a..a88f0352746a6f4da91534771326da3b92ed2dd4 100644 (file)
@@ -255,3 +255,35 @@ const struct st_tracked_state st_update_tep = {
    },
    update_tep                                  /* update */
 };
+
+
+
+static void
+update_cp( struct st_context *st )
+{
+   struct st_compute_program *stcp;
+
+   if (!st->ctx->ComputeProgram._Current) {
+      cso_set_compute_shader_handle(st->cso_context, NULL);
+      return;
+   }
+
+   stcp = st_compute_program(st->ctx->ComputeProgram._Current);
+   assert(stcp->Base.Base.Target == GL_COMPUTE_PROGRAM_NV);
+
+   st->cp_variant = st_get_cp_variant(st, &stcp->tgsi, &stcp->variants);
+
+   st_reference_compprog(st, &st->cp, stcp);
+
+   cso_set_compute_shader_handle(st->cso_context,
+                                 st->cp_variant->driver_shader);
+}
+
+const struct st_tracked_state st_update_cp = {
+   "st_update_cp",                     /* name */
+   {                                   /* dirty */
+      0,                               /* mesa */
+      ST_NEW_COMPUTE_PROGRAM           /* st */
+   },
+   update_cp                           /* update */
+};
index ca493d84715d65f94399ca7098d506931aabbdb5..27cc0f3d154d3c80f3cfa9d5d9384f5ba39065bd 100644 (file)
@@ -74,6 +74,9 @@ st_bind_program(struct gl_context *ctx, GLenum target, struct gl_program *prog)
    case GL_TESS_EVALUATION_PROGRAM_NV:
       st->dirty.st |= ST_NEW_TESSEVAL_PROGRAM;
       break;
+   case GL_COMPUTE_PROGRAM_NV:
+      st->dirty_cp.st |= ST_NEW_COMPUTE_PROGRAM;
+      break;
    }
 }
 
@@ -92,6 +95,7 @@ st_use_program(struct gl_context *ctx, struct gl_shader_program *shProg)
    st->dirty.st |= ST_NEW_GEOMETRY_PROGRAM;
    st->dirty.st |= ST_NEW_TESSCTRL_PROGRAM;
    st->dirty.st |= ST_NEW_TESSEVAL_PROGRAM;
+   st->dirty_cp.st |= ST_NEW_COMPUTE_PROGRAM;
 }
 
 
@@ -123,6 +127,10 @@ st_new_program(struct gl_context *ctx, GLenum target, GLuint id)
       struct st_tesseval_program *prog = ST_CALLOC_STRUCT(st_tesseval_program);
       return _mesa_init_gl_program(&prog->Base.Base, target, id);
    }
+   case GL_COMPUTE_PROGRAM_NV: {
+      struct st_compute_program *prog = ST_CALLOC_STRUCT(st_compute_program);
+      return _mesa_init_gl_program(&prog->Base.Base, target, id);
+   }
    default:
       assert(0);
       return NULL;
@@ -195,6 +203,17 @@ st_delete_program(struct gl_context *ctx, struct gl_program *prog)
             free_glsl_to_tgsi_visitor(sttep->glsl_to_tgsi);
       }
       break;
+   case GL_COMPUTE_PROGRAM_NV:
+      {
+         struct st_compute_program *stcp =
+            (struct st_compute_program *) prog;
+
+         st_release_cp_variants(st, stcp);
+
+         if (stcp->glsl_to_tgsi)
+            free_glsl_to_tgsi_visitor(stcp->glsl_to_tgsi);
+      }
+      break;
    default:
       assert(0); /* problem */
    }
@@ -272,6 +291,17 @@ st_program_string_notify( struct gl_context *ctx,
       if (st->tep == sttep)
          st->dirty.st |= ST_NEW_TESSEVAL_PROGRAM;
    }
+   else if (target == GL_COMPUTE_PROGRAM_NV) {
+      struct st_compute_program *stcp =
+         (struct st_compute_program *) prog;
+
+      st_release_cp_variants(st, stcp);
+      if (!st_translate_compute_program(st, stcp))
+         return false;
+
+      if (st->cp == stcp)
+         st->dirty_cp.st |= ST_NEW_COMPUTE_PROGRAM;
+   }
 
    if (ST_DEBUG & DEBUG_PRECOMPILE ||
        st->shader_has_one_variant[stage])
index b73b0abd55a19f03a71a8cab3451e76c8f34924c..287a4ea0dee64359a4d1d00f7a61f6ef402b51a7 100644 (file)
@@ -446,6 +446,7 @@ void st_destroy_context( struct st_context *st )
    st_reference_vertprog(st, &st->vp, NULL);
    st_reference_tesscprog(st, &st->tcp, NULL);
    st_reference_tesseprog(st, &st->tep, NULL);
+   st_reference_compprog(st, &st->cp, NULL);
 
    /* release framebuffer surfaces */
    for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
index b8f7aa9909fb4ebef708bdc7b6e34130ebdda1ff..3b86710fdd52d823ec2097a561f5d7715f8e053c 100644 (file)
@@ -64,6 +64,7 @@ struct u_upload_mgr;
 #define ST_NEW_SAMPLER_VIEWS           (1 << 11)
 #define ST_NEW_ATOMIC_BUFFER           (1 << 12)
 #define ST_NEW_STORAGE_BUFFER          (1 << 13)
+#define ST_NEW_COMPUTE_PROGRAM         (1 << 14)
 
 
 struct st_state_flags {
@@ -174,12 +175,14 @@ struct st_context
    struct st_geometry_program *gp;  /**< Currently bound geometry program */
    struct st_tessctrl_program *tcp; /**< Currently bound tess control program */
    struct st_tesseval_program *tep; /**< Currently bound tess eval program */
+   struct st_compute_program *cp;   /**< Currently bound compute program */
 
    struct st_vp_variant *vp_variant;
    struct st_fp_variant *fp_variant;
    struct st_basic_variant *gp_variant;
    struct st_basic_variant *tcp_variant;
    struct st_basic_variant *tep_variant;
+   struct st_basic_variant *cp_variant;
 
    struct gl_texture_object *default_texture;
 
index feabe6290eb8c8fbb7001c9439419487fc3566a6..556cd65afa1e599e8f5dee619440ba03b6660e70 100644 (file)
@@ -174,9 +174,12 @@ void st_init_limits(struct pipe_screen *screen,
          pc = &c->Program[MESA_SHADER_TESS_EVAL];
          options = &c->ShaderCompilerOptions[MESA_SHADER_TESS_EVAL];
          break;
+      case PIPE_SHADER_COMPUTE:
+         pc = &c->Program[MESA_SHADER_COMPUTE];
+         options = &c->ShaderCompilerOptions[MESA_SHADER_COMPUTE];
+         break;
       default:
-         /* compute shader, etc. */
-         continue;
+         assert(0);
       }
 
       pc->MaxTextureImageUnits =
index 5bd626f861055853ff179951fd06913b65388d40..16627ac78346ee7a6c509fff2d64f47548f7872b 100644 (file)
@@ -158,6 +158,9 @@ delete_basic_variant(struct st_context *st, struct st_basic_variant *v,
       case GL_GEOMETRY_PROGRAM_NV:
          cso_delete_geometry_shader(st->cso_context, v->driver_shader);
          break;
+      case GL_COMPUTE_PROGRAM_NV:
+         cso_delete_compute_shader(st->cso_context, v->driver_shader);
+         break;
       default:
          assert(!"this shouldn't occur");
       }
@@ -192,6 +195,30 @@ st_release_basic_variants(struct st_context *st, GLenum target,
 }
 
 
+/**
+ * Free all variants of a compute program.
+ */
+void
+st_release_cp_variants(struct st_context *st, struct st_compute_program *stcp)
+{
+   struct st_basic_variant **variants = &stcp->variants;
+   struct st_basic_variant *v;
+
+   for (v = *variants; v; ) {
+      struct st_basic_variant *next = v->next;
+      delete_basic_variant(st, v, stcp->Base.Base.Target);
+      v = next;
+   }
+
+   *variants = NULL;
+
+   if (stcp->tgsi.prog) {
+      ureg_free_tokens(stcp->tgsi.prog);
+      stcp->tgsi.prog = NULL;
+   }
+}
+
+
 /**
  * Translate a vertex program.
  */
@@ -1394,6 +1421,57 @@ st_translate_tesseval_program(struct st_context *st,
 }
 
 
+/**
+ * Translate a compute program to create a new variant.
+ */
+bool
+st_translate_compute_program(struct st_context *st,
+                             struct st_compute_program *stcp)
+{
+   return false; /* will be updated in the next commit */
+}
+
+
+/**
+ * Get/create compute program variant.
+ */
+struct st_basic_variant *
+st_get_cp_variant(struct st_context *st,
+                  struct pipe_compute_state *tgsi,
+                  struct st_basic_variant **variants)
+{
+   struct pipe_context *pipe = st->pipe;
+   struct st_basic_variant *v;
+   struct st_basic_variant_key key;
+
+   memset(&key, 0, sizeof(key));
+   key.st = st->has_shareable_shaders ? NULL : st;
+
+   /* Search for existing variant */
+   for (v = *variants; v; v = v->next) {
+      if (memcmp(&v->key, &key, sizeof(key)) == 0) {
+         break;
+      }
+   }
+
+   if (!v) {
+      /* create new */
+      v = CALLOC_STRUCT(st_basic_variant);
+      if (v) {
+         /* fill in new variant */
+         v->driver_shader = pipe->create_compute_state(pipe, tgsi);
+         v->key = key;
+
+         /* insert into list */
+         v->next = *variants;
+         *variants = v;
+      }
+   }
+
+   return v;
+}
+
+
 /**
  * Vert/Geom/Frag programs have per-context variants.  Free all the
  * variants attached to the given program which match the given context.
@@ -1449,14 +1527,17 @@ destroy_program_variants(struct st_context *st, struct gl_program *target)
    case GL_GEOMETRY_PROGRAM_NV:
    case GL_TESS_CONTROL_PROGRAM_NV:
    case GL_TESS_EVALUATION_PROGRAM_NV:
+   case GL_COMPUTE_PROGRAM_NV:
       {
          struct st_geometry_program *gp = (struct st_geometry_program*)target;
          struct st_tessctrl_program *tcp = (struct st_tessctrl_program*)target;
          struct st_tesseval_program *tep = (struct st_tesseval_program*)target;
+         struct st_compute_program *cp = (struct st_compute_program*)target;
          struct st_basic_variant **variants =
             target->Target == GL_GEOMETRY_PROGRAM_NV ? &gp->variants :
             target->Target == GL_TESS_CONTROL_PROGRAM_NV ? &tcp->variants :
             target->Target == GL_TESS_EVALUATION_PROGRAM_NV ? &tep->variants :
+            target->Target == GL_COMPUTE_PROGRAM_NV ? &cp->variants :
             NULL;
          struct st_basic_variant *v, **prevPtr = variants;
 
@@ -1513,6 +1594,7 @@ destroy_shader_program_variants_cb(GLuint key, void *data, void *userData)
    case GL_GEOMETRY_SHADER:
    case GL_TESS_CONTROL_SHADER:
    case GL_TESS_EVALUATION_SHADER:
+   case GL_COMPUTE_SHADER:
       {
          destroy_program_variants(st, shader->Program);
       }
@@ -1629,6 +1711,12 @@ st_precompile_shader_variant(struct st_context *st,
       break;
    }
 
+   case GL_COMPUTE_PROGRAM_NV: {
+      struct st_compute_program *p = (struct st_compute_program *)prog;
+      st_get_cp_variant(st, &p->tgsi, &p->variants);
+      break;
+   }
+
    default:
       assert(0);
    }
index 74f3def6095e33b181c0ab1c59f9716172cab672..028fba99a7483dc33a50224ce715158601397df2 100644 (file)
@@ -231,6 +231,18 @@ struct st_tesseval_program
 };
 
 
+/**
+ * Derived from Mesa gl_compute_program:
+ */
+struct st_compute_program
+{
+   struct gl_compute_program Base;  /**< The Mesa compute program */
+   struct pipe_compute_state tgsi;
+   struct glsl_to_tgsi_visitor* glsl_to_tgsi;
+
+   struct st_basic_variant *variants;
+};
+
 
 static inline struct st_fragment_program *
 st_fragment_program( struct gl_fragment_program *fp )
@@ -263,6 +275,12 @@ st_tesseval_program( struct gl_tess_eval_program *tep )
    return (struct st_tesseval_program *)tep;
 }
 
+static inline struct st_compute_program *
+st_compute_program( struct gl_compute_program *cp )
+{
+   return (struct st_compute_program *)cp;
+}
+
 static inline void
 st_reference_vertprog(struct st_context *st,
                       struct st_vertex_program **ptr,
@@ -313,6 +331,16 @@ st_reference_tesseprog(struct st_context *st,
                            (struct gl_program *) prog);
 }
 
+static inline void
+st_reference_compprog(struct st_context *st,
+                      struct st_compute_program **ptr,
+                      struct st_compute_program *prog)
+{
+   _mesa_reference_program(st->ctx,
+                           (struct gl_program **) ptr,
+                           (struct gl_program *) prog);
+}
+
 /**
  * This defines mapping from Mesa VARYING_SLOTs to TGSI GENERIC slots.
  */
@@ -350,6 +378,11 @@ st_get_fp_variant(struct st_context *st,
                   struct st_fragment_program *stfp,
                   const struct st_fp_variant_key *key);
 
+extern struct st_basic_variant *
+st_get_cp_variant(struct st_context *st,
+                  struct pipe_compute_state *tgsi,
+                  struct st_basic_variant **variants);
+
 extern struct st_basic_variant *
 st_get_basic_variant(struct st_context *st,
                      unsigned pipe_shader,
@@ -364,6 +397,10 @@ extern void
 st_release_fp_variants( struct st_context *st,
                         struct st_fragment_program *stfp );
 
+extern void
+st_release_cp_variants(struct st_context *st,
+                        struct st_compute_program *stcp);
+
 extern void
 st_release_basic_variants(struct st_context *st, GLenum target,
                           struct st_basic_variant **variants,
@@ -392,6 +429,10 @@ extern bool
 st_translate_tesseval_program(struct st_context *st,
                               struct st_tesseval_program *sttep);
 
+extern bool
+st_translate_compute_program(struct st_context *st,
+                             struct st_compute_program *stcp);
+
 extern void
 st_print_current_vertex_program(void);