st/mesa: translate fragment shaders into TGSI when we get them
authorMarek Olšák <marek.olsak@amd.com>
Mon, 5 Oct 2015 01:26:48 +0000 (03:26 +0200)
committerMarek Olšák <marek.olsak@amd.com>
Fri, 9 Oct 2015 20:02:18 +0000 (22:02 +0200)
Reviewed-by: Dave Airlie <airlied@redhat.com>
Reviewed-by: Brian Paul <brianp@vmware.com>
Tested-by: Brian Paul <brianp@vmware.com>
src/mesa/state_tracker/st_cb_program.c
src/mesa/state_tracker/st_debug.c
src/mesa/state_tracker/st_program.c
src/mesa/state_tracker/st_program.h

index 745b4476d426328fd1e44883757be3124a4e0ccb..40eeb0f703ee754b53a027898ff944ca2f5068ea 100644 (file)
@@ -234,6 +234,8 @@ st_program_string_notify( struct gl_context *ctx,
       struct st_fragment_program *stfp = (struct st_fragment_program *) prog;
 
       st_release_fp_variants(st, stfp);
+      if (!st_translate_fragment_program(st, stfp))
+         return false;
 
       if (st->fp == stfp)
         st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
index 50891c112cbef156054f49ff31562533bf72513a..6d859c6ab5b5ec28ec1b017f0bfbf4e19b588080 100644 (file)
@@ -98,7 +98,7 @@ st_print_current(void)
    if (st->vp->Base.Base.Parameters)
       _mesa_print_parameter_list(st->vp->Base.Base.Parameters);
 
-   tgsi_dump( st->fp->variants[0].tgsi.tokens, 0 );
+   tgsi_dump(st->fp->tgsi.tokens, 0);
    if (st->fp->Base.Base.Parameters)
       _mesa_print_parameter_list(st->fp->Base.Base.Parameters);
 }
index 4bdbf8537fbe1bc67a94df3f0983c31d19082956..5eded93650c604360fe22008de5751d133592126 100644 (file)
@@ -114,8 +114,6 @@ delete_fp_variant(struct st_context *st, struct st_fp_variant *fpv)
       cso_delete_fragment_shader(st->cso_context, fpv->driver_shader);
    if (fpv->parameters)
       _mesa_free_parameter_list(fpv->parameters);
-   if (fpv->tgsi.tokens)
-      ureg_free_tokens(fpv->tgsi.tokens);
    free(fpv);
 }
 
@@ -135,6 +133,11 @@ st_release_fp_variants(struct st_context *st, struct st_fragment_program *stfp)
    }
 
    stfp->variants = NULL;
+
+   if (stfp->tgsi.tokens) {
+      ureg_free_tokens(stfp->tgsi.tokens);
+      stfp->tgsi.tokens = NULL;
+   }
 }
 
 
@@ -531,17 +534,12 @@ st_translate_interp(enum glsl_interp_qualifier glsl_qual, bool is_color)
 
 
 /**
- * Translate a Mesa fragment shader into a TGSI shader using extra info in
- * the key.
- * \return  new fragment program variant
+ * Translate a Mesa fragment shader into a TGSI shader.
  */
-static struct st_fp_variant *
+bool
 st_translate_fragment_program(struct st_context *st,
-                              struct st_fragment_program *stfp,
-                              const struct st_fp_variant_key *key)
+                              struct st_fragment_program *stfp)
 {
-   struct pipe_context *pipe = st->pipe;
-   struct st_fp_variant *variant = CALLOC_STRUCT(st_fp_variant);
    GLuint outputMapping[FRAG_RESULT_MAX];
    GLuint inputMapping[VARYING_SLOT_MAX];
    GLuint inputSlotToAttr[VARYING_SLOT_MAX];
@@ -561,10 +559,6 @@ st_translate_fragment_program(struct st_context *st,
    ubyte fs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS];
    uint fs_num_outputs = 0;
 
-   if (!variant)
-      return NULL;
-
-   assert(!(key->bitmap && key->drawpixels));
    memset(inputSlotToAttr, ~0, sizeof(inputSlotToAttr));
 
    if (!stfp->glsl_to_tgsi)
@@ -772,10 +766,8 @@ st_translate_fragment_program(struct st_context *st,
    }
 
    ureg = ureg_create_with_screen(TGSI_PROCESSOR_FRAGMENT, st->pipe->screen);
-   if (ureg == NULL) {
-      free(variant);
-      return NULL;
-   }
+   if (ureg == NULL)
+      return false;
 
    if (ST_DEBUG & DEBUG_MESA) {
       _mesa_print_program(&stfp->Base.Base);
@@ -845,8 +837,26 @@ st_translate_fragment_program(struct st_context *st,
                                 fs_output_semantic_name,
                                 fs_output_semantic_index);
 
-   variant->tgsi.tokens = ureg_get_tokens(ureg, NULL);
+   stfp->tgsi.tokens = ureg_get_tokens(ureg, NULL);
    ureg_destroy(ureg);
+   return stfp->tgsi.tokens != NULL;
+}
+
+static struct st_fp_variant *
+st_create_fp_variant(struct st_context *st,
+                     struct st_fragment_program *stfp,
+                     const struct st_fp_variant_key *key)
+{
+   struct pipe_context *pipe = st->pipe;
+   struct st_fp_variant *variant = CALLOC_STRUCT(st_fp_variant);
+   struct pipe_shader_state tgsi = {0};
+
+   if (!variant)
+      return NULL;
+
+   tgsi.tokens = stfp->tgsi.tokens;
+
+   assert(!(key->bitmap && key->drawpixels));
 
    /* Emulate features. */
    if (key->clamp_color || key->persample_shading) {
@@ -855,12 +865,11 @@ st_translate_fragment_program(struct st_context *st,
          (key->clamp_color ? TGSI_EMU_CLAMP_COLOR_OUTPUTS : 0) |
          (key->persample_shading ? TGSI_EMU_FORCE_PERSAMPLE_INTERP : 0);
 
-      tokens = tgsi_emulate(variant->tgsi.tokens, flags);
+      tokens = tgsi_emulate(tgsi.tokens, flags);
 
-      if (tokens) {
-         tgsi_free_tokens(variant->tgsi.tokens);
-         variant->tgsi.tokens = tokens;
-      } else
+      if (tokens)
+         tgsi.tokens = tokens;
+      else
          fprintf(stderr, "mesa: cannot emulate deprecated features\n");
    }
 
@@ -870,15 +879,16 @@ st_translate_fragment_program(struct st_context *st,
 
       variant->bitmap_sampler = ffs(~stfp->Base.Base.SamplersUsed) - 1;
 
-      tokens = st_get_bitmap_shader(variant->tgsi.tokens,
+      tokens = st_get_bitmap_shader(tgsi.tokens,
                                     variant->bitmap_sampler,
                                     st->needs_texcoord_semantic,
                                     st->bitmap.tex_format ==
                                     PIPE_FORMAT_L8_UNORM);
 
       if (tokens) {
-         tgsi_free_tokens(variant->tgsi.tokens);
-         variant->tgsi.tokens = tokens;
+         if (tgsi.tokens != stfp->tgsi.tokens)
+            tgsi_free_tokens(tgsi.tokens);
+         tgsi.tokens = tokens;
          variant->parameters =
             _mesa_clone_parameter_list(stfp->Base.Base.Parameters);
       } else
@@ -923,7 +933,7 @@ st_translate_fragment_program(struct st_context *st,
                                                     state);
       }
 
-      tokens = st_get_drawpix_shader(variant->tgsi.tokens,
+      tokens = st_get_drawpix_shader(tgsi.tokens,
                                      st->needs_texcoord_semantic,
                                      key->scaleAndBias, scale_const,
                                      bias_const, key->pixelMaps,
@@ -932,24 +942,27 @@ st_translate_fragment_program(struct st_context *st,
                                      texcoord_const);
 
       if (tokens) {
-         tgsi_free_tokens(variant->tgsi.tokens);
-         variant->tgsi.tokens = tokens;
+         if (tgsi.tokens != stfp->tgsi.tokens)
+            tgsi_free_tokens(tgsi.tokens);
+         tgsi.tokens = tokens;
       } else
          fprintf(stderr, "mesa: cannot create a shader for glDrawPixels\n");
    }
 
    if (ST_DEBUG & DEBUG_TGSI) {
-      tgsi_dump(variant->tgsi.tokens, 0/*TGSI_DUMP_VERBOSE*/);
+      tgsi_dump(tgsi.tokens, 0);
       debug_printf("\n");
    }
 
    /* fill in variant */
-   variant->driver_shader = pipe->create_fs_state(pipe, &variant->tgsi);
+   variant->driver_shader = pipe->create_fs_state(pipe, &tgsi);
    variant->key = *key;
+
+   if (tgsi.tokens != stfp->tgsi.tokens)
+      tgsi_free_tokens(tgsi.tokens);
    return variant;
 }
 
-
 /**
  * Translate fragment program if needed.
  */
@@ -969,7 +982,7 @@ st_get_fp_variant(struct st_context *st,
 
    if (!fpv) {
       /* create new */
-      fpv = st_translate_fragment_program(st, stfp, key);
+      fpv = st_create_fp_variant(st, stfp, key);
       if (fpv) {
          /* insert into list */
          fpv->next = stfp->variants;
index 6f4a6a1b802d89f9c85ca57196fbeba3efd38bdd..d4b5c1f427a6149f9f507ffe89ea020b455d06ee 100644 (file)
@@ -76,8 +76,6 @@ struct st_fp_variant
    /** Parameters which generated this version of fragment program */
    struct st_fp_variant_key key;
 
-   struct pipe_shader_state tgsi;
-
    /** Driver's compiled shader */
    void *driver_shader;
 
@@ -100,6 +98,7 @@ struct st_fp_variant
 struct st_fragment_program
 {
    struct gl_fragment_program Base;
+   struct pipe_shader_state tgsi;
    struct glsl_to_tgsi_visitor* glsl_to_tgsi;
 
    struct st_fp_variant *variants;
@@ -439,6 +438,10 @@ extern bool
 st_translate_vertex_program(struct st_context *st,
                             struct st_vertex_program *stvp);
 
+extern bool
+st_translate_fragment_program(struct st_context *st,
+                              struct st_fragment_program *stfp);
+
 extern void
 st_print_current_vertex_program(void);