st/mesa: determine states used or affected by shaders at compile time
authorMarek Olšák <marek.olsak@amd.com>
Tue, 2 Aug 2016 14:40:50 +0000 (16:40 +0200)
committerMarek Olšák <marek.olsak@amd.com>
Fri, 12 Aug 2016 16:49:24 +0000 (18:49 +0200)
At compile time, each shader determines which ST_NEW flags should be set
at shader bind time.

This just sets the new field for all shaders. The next commit will use it.

v2: small code unification

Tested-by: Edmondo Tommasina <edmondo.tommasina@gmail.com>
Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com> (v1)
src/mesa/state_tracker/st_glsl_to_tgsi.cpp
src/mesa/state_tracker/st_program.c
src/mesa/state_tracker/st_program.h

index 362559fbe0d6eb6c0bae1a406429045c566660f0..3e5b322b9d108f13da02bf2131b74e3196e807b7 100644 (file)
@@ -6664,6 +6664,37 @@ get_mesa_program_tgsi(struct gl_context *ctx,
    return prog;
 }
 
+static void
+set_affected_state_flags(uint64_t *states,
+                         struct gl_program *prog,
+                         struct gl_linked_shader *shader,
+                         uint64_t new_constants,
+                         uint64_t new_sampler_views,
+                         uint64_t new_samplers,
+                         uint64_t new_images,
+                         uint64_t new_ubos,
+                         uint64_t new_ssbos,
+                         uint64_t new_atomics)
+{
+   if (prog->Parameters->NumParameters)
+      *states |= new_constants;
+
+   if (shader->num_samplers)
+      *states |= new_sampler_views | new_samplers;
+
+   if (shader->NumImages)
+      *states |= new_images;
+
+   if (shader->NumUniformBlocks)
+      *states |= new_ubos;
+
+   if (shader->NumShaderStorageBlocks)
+      *states |= new_ssbos;
+
+   if (shader->NumAtomicBuffers)
+      *states |= new_atomics;
+}
+
 static struct gl_program *
 get_mesa_program(struct gl_context *ctx,
                  struct gl_shader_program *shader_program,
@@ -6673,17 +6704,131 @@ get_mesa_program(struct gl_context *ctx,
    unsigned ptarget = st_shader_stage_to_ptarget(shader->Stage);
    enum pipe_shader_ir preferred_ir = (enum pipe_shader_ir)
       pscreen->get_shader_param(pscreen, ptarget, PIPE_SHADER_CAP_PREFERRED_IR);
+   struct gl_program *prog = NULL;
+
    if (preferred_ir == PIPE_SHADER_IR_NIR) {
       /* TODO only for GLSL VS/FS for now: */
       switch (shader->Stage) {
       case MESA_SHADER_VERTEX:
       case MESA_SHADER_FRAGMENT:
-         return st_nir_get_mesa_program(ctx, shader_program, shader);
+         prog = st_nir_get_mesa_program(ctx, shader_program, shader);
       default:
          break;
       }
+   } else {
+      prog = get_mesa_program_tgsi(ctx, shader_program, shader);
+   }
+
+   if (prog) {
+      uint64_t *states;
+
+      /* This determines which states will be updated when the shader is
+       * bound.
+       */
+      switch (shader->Stage) {
+      case MESA_SHADER_VERTEX:
+         states = &((struct st_vertex_program*)prog)->affected_states;
+
+         *states = ST_NEW_VS_STATE |
+                   ST_NEW_RASTERIZER |
+                   ST_NEW_VERTEX_ARRAYS;
+
+         set_affected_state_flags(states, prog, shader,
+                                  ST_NEW_VS_CONSTANTS,
+                                  ST_NEW_VS_SAMPLER_VIEWS,
+                                  ST_NEW_RENDER_SAMPLERS,
+                                  ST_NEW_VS_IMAGES,
+                                  ST_NEW_VS_UBOS,
+                                  ST_NEW_VS_SSBOS,
+                                  ST_NEW_VS_ATOMICS);
+         break;
+
+      case MESA_SHADER_TESS_CTRL:
+         states = &((struct st_tessctrl_program*)prog)->affected_states;
+
+         *states = ST_NEW_TCS_STATE;
+
+         set_affected_state_flags(states, prog, shader,
+                                  ST_NEW_TCS_CONSTANTS,
+                                  ST_NEW_TCS_SAMPLER_VIEWS,
+                                  ST_NEW_RENDER_SAMPLERS,
+                                  ST_NEW_TCS_IMAGES,
+                                  ST_NEW_TCS_UBOS,
+                                  ST_NEW_TCS_SSBOS,
+                                  ST_NEW_TCS_ATOMICS);
+         break;
+
+      case MESA_SHADER_TESS_EVAL:
+         states = &((struct st_tesseval_program*)prog)->affected_states;
+
+         *states = ST_NEW_TES_STATE |
+                   ST_NEW_RASTERIZER;
+
+         set_affected_state_flags(states, prog, shader,
+                                  ST_NEW_TES_CONSTANTS,
+                                  ST_NEW_TES_SAMPLER_VIEWS,
+                                  ST_NEW_RENDER_SAMPLERS,
+                                  ST_NEW_TES_IMAGES,
+                                  ST_NEW_TES_UBOS,
+                                  ST_NEW_TES_SSBOS,
+                                  ST_NEW_TES_ATOMICS);
+         break;
+
+      case MESA_SHADER_GEOMETRY:
+         states = &((struct st_geometry_program*)prog)->affected_states;
+
+         *states = ST_NEW_GS_STATE |
+                   ST_NEW_RASTERIZER;
+
+         set_affected_state_flags(states, prog, shader,
+                                  ST_NEW_GS_CONSTANTS,
+                                  ST_NEW_GS_SAMPLER_VIEWS,
+                                  ST_NEW_RENDER_SAMPLERS,
+                                  ST_NEW_GS_IMAGES,
+                                  ST_NEW_GS_UBOS,
+                                  ST_NEW_GS_SSBOS,
+                                  ST_NEW_GS_ATOMICS);
+         break;
+
+      case MESA_SHADER_FRAGMENT:
+         states = &((struct st_fragment_program*)prog)->affected_states;
+
+         /* gl_FragCoord and glDrawPixels always use constants. */
+         *states = ST_NEW_FS_STATE |
+                   ST_NEW_SAMPLE_SHADING |
+                   ST_NEW_FS_CONSTANTS;
+
+         set_affected_state_flags(states, prog, shader,
+                                  ST_NEW_FS_CONSTANTS,
+                                  ST_NEW_FS_SAMPLER_VIEWS,
+                                  ST_NEW_RENDER_SAMPLERS,
+                                  ST_NEW_FS_IMAGES,
+                                  ST_NEW_FS_UBOS,
+                                  ST_NEW_FS_SSBOS,
+                                  ST_NEW_FS_ATOMICS);
+         break;
+
+      case MESA_SHADER_COMPUTE:
+         states = &((struct st_compute_program*)prog)->affected_states;
+
+         *states = ST_NEW_CS_STATE;
+
+         set_affected_state_flags(states, prog, shader,
+                                  ST_NEW_CS_CONSTANTS,
+                                  ST_NEW_CS_SAMPLER_VIEWS,
+                                  ST_NEW_CS_SAMPLERS,
+                                  ST_NEW_CS_IMAGES,
+                                  ST_NEW_CS_UBOS,
+                                  ST_NEW_CS_SSBOS,
+                                  ST_NEW_CS_ATOMICS);
+         break;
+
+      default:
+         unreachable("unhandled shader stage");
+      }
    }
-   return get_mesa_program_tgsi(ctx, shader_program, shader);
+
+   return prog;
 }
 
 
index e297bb1d5d58efad2276da8afc17feab136261ad..03a685c4db6b070c5ac99bfb779f3eb2e1fe523e 100644 (file)
@@ -364,9 +364,23 @@ st_translate_vertex_program(struct st_context *st,
    output_semantic_name[num_outputs] = TGSI_SEMANTIC_EDGEFLAG;
    output_semantic_index[num_outputs] = 0;
 
-   if (!stvp->glsl_to_tgsi && !stvp->shader_program)
+   /* ARB_vp: */
+   if (!stvp->glsl_to_tgsi && !stvp->shader_program) {
       _mesa_remove_output_reads(&stvp->Base.Base, PROGRAM_OUTPUT);
 
+      /* This determines which states will be updated when the assembly
+       * shader is bound.
+       */
+      stvp->affected_states = ST_NEW_VS_STATE |
+                              ST_NEW_RASTERIZER |
+                              ST_NEW_VERTEX_ARRAYS;
+
+      if (stvp->Base.Base.Parameters->NumParameters)
+         stvp->affected_states |= ST_NEW_VS_CONSTANTS;
+
+      /* No samplers are allowed in ARB_vp. */
+   }
+
    if (stvp->shader_program) {
       nir_shader *nir = st_glsl_to_nir(st, &stvp->Base.Base,
                                        stvp->shader_program,
@@ -593,10 +607,31 @@ st_translate_fragment_program(struct st_context *st,
 
    memset(inputSlotToAttr, ~0, sizeof(inputSlotToAttr));
 
+   /* Non-GLSL programs: */
    if (!stfp->glsl_to_tgsi && !stfp->shader_program) {
       _mesa_remove_output_reads(&stfp->Base.Base, PROGRAM_OUTPUT);
       if (st->ctx->Const.GLSLFragCoordIsSysVal)
          _mesa_program_fragment_position_to_sysval(&stfp->Base.Base);
+
+      /* This determines which states will be updated when the assembly
+       * shader is bound.
+       *
+       * fragment.position and glDrawPixels always use constants.
+       */
+      stfp->affected_states = ST_NEW_FS_STATE |
+                              ST_NEW_SAMPLE_SHADING |
+                              ST_NEW_FS_CONSTANTS;
+
+      if (stfp->ati_fs) {
+         /* Just set them for ATI_fs unconditionally. */
+         stfp->affected_states |= ST_NEW_FS_SAMPLER_VIEWS |
+                                  ST_NEW_RENDER_SAMPLERS;
+      } else {
+         /* ARB_fp */
+         if (stfp->Base.Base.SamplersUsed)
+            stfp->affected_states |= ST_NEW_FS_SAMPLER_VIEWS |
+                                     ST_NEW_RENDER_SAMPLERS;
+      }
    }
 
    /*
index e6db1069025fc7d55c656619c628df4090c01b6a..8e11bf02fa913d0e0c573b997dfb4004d2b77415 100644 (file)
@@ -107,6 +107,7 @@ struct st_fragment_program
    struct pipe_shader_state tgsi;
    struct glsl_to_tgsi_visitor* glsl_to_tgsi;
    struct ati_fragment_shader *ati_fs;
+   uint64_t affected_states; /**< ST_NEW_* flags to mark dirty when binding */
 
    /* used when bypassing glsl_to_tgsi: */
    struct gl_shader_program *shader_program;
@@ -166,6 +167,7 @@ struct st_vertex_program
    struct gl_vertex_program Base;  /**< The Mesa vertex program */
    struct pipe_shader_state tgsi;
    struct glsl_to_tgsi_visitor* glsl_to_tgsi;
+   uint64_t affected_states; /**< ST_NEW_* flags to mark dirty when binding */
 
    /* used when bypassing glsl_to_tgsi: */
    struct gl_shader_program *shader_program;
@@ -214,6 +216,7 @@ struct st_geometry_program
    struct gl_geometry_program Base;  /**< The Mesa geometry program */
    struct pipe_shader_state tgsi;
    struct glsl_to_tgsi_visitor* glsl_to_tgsi;
+   uint64_t affected_states; /**< ST_NEW_* flags to mark dirty when binding */
 
    struct st_basic_variant *variants;
 };
@@ -227,6 +230,7 @@ struct st_tessctrl_program
    struct gl_tess_ctrl_program Base;  /**< The Mesa tess ctrl program */
    struct pipe_shader_state tgsi;
    struct glsl_to_tgsi_visitor* glsl_to_tgsi;
+   uint64_t affected_states; /**< ST_NEW_* flags to mark dirty when binding */
 
    struct st_basic_variant *variants;
 };
@@ -240,6 +244,7 @@ struct st_tesseval_program
    struct gl_tess_eval_program Base;  /**< The Mesa tess eval program */
    struct pipe_shader_state tgsi;
    struct glsl_to_tgsi_visitor* glsl_to_tgsi;
+   uint64_t affected_states; /**< ST_NEW_* flags to mark dirty when binding */
 
    struct st_basic_variant *variants;
 };
@@ -253,6 +258,7 @@ 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;
+   uint64_t affected_states; /**< ST_NEW_* flags to mark dirty when binding */
 
    struct st_basic_variant *variants;
 };