st/mesa: remove excessive shader state dirtying
authorMarek Olšák <marek.olsak@amd.com>
Sun, 17 Jul 2016 18:37:58 +0000 (20:37 +0200)
committerMarek Olšák <marek.olsak@amd.com>
Sat, 30 Jul 2016 13:02:14 +0000 (15:02 +0200)
This just needs to be done by st_validate_state.

v2: add "shaders_may_be_dirty" flags for not skipping st_validate_state
    on _NEW_PROGRAM to detect real shader changes

Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
src/mesa/state_tracker/st_atom.c
src/mesa/state_tracker/st_cb_bitmap.c
src/mesa/state_tracker/st_cb_compute.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_draw.c

index ef50ef9df9a70038fbdff3401a9da0014618b5c8..06c523e8b8eb3cca135695d3cd5be56a53c8538f 100644 (file)
@@ -72,6 +72,14 @@ static void check_program_state( struct st_context *st )
 
    if (ctx->GeometryProgram._Current != &st->gp->Base)
       st->dirty |= ST_NEW_GEOMETRY_PROGRAM;
+
+   if (ctx->TessCtrlProgram._Current != &st->tcp->Base)
+      st->dirty |= ST_NEW_TESSCTRL_PROGRAM;
+
+   if (ctx->TessEvalProgram._Current != &st->tep->Base)
+      st->dirty |= ST_NEW_TESSEVAL_PROGRAM;
+
+   st->gfx_shaders_may_be_dirty = false;
 }
 
 static void check_attrib_edgeflag(struct st_context *st)
@@ -135,8 +143,13 @@ void st_validate_state( struct st_context *st, enum st_pipeline pipeline )
          pipeline_mask &= ~ST_NEW_GS_RESOURCES;
       if (!ctx->Transform.ClipPlanesEnabled)
          pipeline_mask &= ~ST_NEW_CLIP_STATE;
+
       break;
    case ST_PIPELINE_COMPUTE:
+      if (ctx->ComputeProgram._Current != &st->cp->Base)
+         st->dirty |= ST_NEW_COMPUTE_PROGRAM;
+
+      st->compute_shader_may_be_dirty = false;
       pipeline_mask = ST_PIPELINE_COMPUTE_STATE_MASK;
       break;
    default:
index 5765ed28cef046546c5ad9d00639e8483b77a2d2..0ee19fd2c62d0e059a5e514031163c5894da7ced 100644 (file)
@@ -647,7 +647,8 @@ st_Bitmap(struct gl_context *ctx, GLint x, GLint y,
     * explicitly uploaded in the draw_bitmap_quad() function.
     */
    if ((st->dirty | ctx->NewDriverState) & ~ST_NEW_CONSTANTS &
-       ST_PIPELINE_RENDER_STATE_MASK) {
+       ST_PIPELINE_RENDER_STATE_MASK ||
+       st->gfx_shaders_may_be_dirty) {
       st_validate_state(st, ST_PIPELINE_RENDER);
    }
 
index 677507da2b8adf7900d8564b7c8aa5e604d4967c..88c1ee2cd1cc135b12140318554f383dc4126bf8 100644 (file)
@@ -51,7 +51,8 @@ static void st_dispatch_compute_common(struct gl_context *ctx,
    if (ctx->NewState)
       _mesa_update_state(ctx);
 
-   if ((st->dirty | ctx->NewDriverState) & ST_PIPELINE_COMPUTE_STATE_MASK)
+   if ((st->dirty | ctx->NewDriverState) & ST_PIPELINE_COMPUTE_STATE_MASK ||
+       st->compute_shader_may_be_dirty)
       st_validate_state(st, ST_PIPELINE_COMPUTE);
 
    for (unsigned i = 0; i < 3; i++) {
index 62648964f55b43ca0ebcdd35598538a3ffc5f867..8291edb7d1164566e6b1076a4f4166f849df991a 100644 (file)
 #include "st_atifs_to_tgsi.h"
 
 
-
-/**
- * Called via ctx->Driver.BindProgram() to bind an ARB vertex or
- * fragment program.
- */
-static void
-st_bind_program(struct gl_context *ctx, GLenum target, struct gl_program *prog)
-{
-   struct st_context *st = st_context(ctx);
-
-   switch (target) {
-   case GL_VERTEX_PROGRAM_ARB: 
-      st->dirty |= ST_NEW_VERTEX_PROGRAM;
-      break;
-   case GL_FRAGMENT_PROGRAM_ARB:
-      st->dirty |= ST_NEW_FRAGMENT_PROGRAM;
-      break;
-   case GL_GEOMETRY_PROGRAM_NV:
-      st->dirty |= ST_NEW_GEOMETRY_PROGRAM;
-      break;
-   case GL_TESS_CONTROL_PROGRAM_NV:
-      st->dirty |= ST_NEW_TESSCTRL_PROGRAM;
-      break;
-   case GL_TESS_EVALUATION_PROGRAM_NV:
-      st->dirty |= ST_NEW_TESSEVAL_PROGRAM;
-      break;
-   case GL_COMPUTE_PROGRAM_NV:
-      st->dirty |= ST_NEW_COMPUTE_PROGRAM;
-      break;
-   }
-}
-
-
-/**
- * Called via ctx->Driver.UseProgram() to bind a linked GLSL program
- * (vertex shader + fragment shader).
- */
-static void
-st_use_program(struct gl_context *ctx, struct gl_shader_program *shProg)
-{
-   struct st_context *st = st_context(ctx);
-
-   st->dirty |= ST_NEW_FRAGMENT_PROGRAM;
-   st->dirty |= ST_NEW_VERTEX_PROGRAM;
-   st->dirty |= ST_NEW_GEOMETRY_PROGRAM;
-   st->dirty |= ST_NEW_TESSCTRL_PROGRAM;
-   st->dirty |= ST_NEW_TESSEVAL_PROGRAM;
-   st->dirty |= ST_NEW_COMPUTE_PROGRAM;
-}
-
-
 /**
  * Called via ctx->Driver.NewProgram() to allocate a new vertex or
  * fragment program.
@@ -347,8 +296,6 @@ st_new_ati_fs(struct gl_context *ctx, struct ati_fragment_shader *curProg)
 void
 st_init_program_functions(struct dd_function_table *functions)
 {
-   functions->BindProgram = st_bind_program;
-   functions->UseProgram = st_use_program;
    functions->NewProgram = st_new_program;
    functions->DeleteProgram = st_delete_program;
    functions->ProgramStringNotify = st_program_string_notify;
index 911bec6c52bae28f46354f4e2f466dc233de147d..2ba6efe76445d1f81e5367121757796fbe62bf4c 100644 (file)
@@ -219,6 +219,12 @@ void st_invalidate_state(struct gl_context * ctx, GLbitfield new_state)
    if (st->clamp_vert_color_in_shader && (new_state & _NEW_LIGHT))
       st->dirty |= ST_NEW_VS_STATE;
 
+   /* Which shaders are dirty will be determined manually. */
+   if (new_state & _NEW_PROGRAM) {
+      st->gfx_shaders_may_be_dirty = true;
+      st->compute_shader_may_be_dirty = true;
+   }
+
    /* This is the only core Mesa module we depend upon.
     * No longer use swrast, swsetup, tnl.
     */
index b9ad2a92433cc95da1c0335cc5d8a4034d2b6787..e0f29e3cebfe4bc05ce3945ca3352dab50675875 100644 (file)
@@ -140,6 +140,12 @@ struct st_context
 
    uint64_t dirty; /**< dirty states */
 
+   /* If true, further analysis of states is required to know if something
+    * has changed. Used mainly for shaders.
+    */
+   bool gfx_shaders_may_be_dirty;
+   bool compute_shader_may_be_dirty;
+
    GLboolean vertdata_edgeflags;
    GLboolean edgeflag_culls_prims;
 
index 92eb4a39e9b653b4978ab9d8fb37cadc3a917840..b248dafc9a202d0f5aad873ace7c38c2b9c99e76 100644 (file)
@@ -173,7 +173,8 @@ st_draw_vbo(struct gl_context *ctx,
    st_invalidate_readpix_cache(st);
 
    /* Validate state. */
-   if ((st->dirty | ctx->NewDriverState) & ST_PIPELINE_RENDER_STATE_MASK) {
+   if ((st->dirty | ctx->NewDriverState) & ST_PIPELINE_RENDER_STATE_MASK ||
+       st->gfx_shaders_may_be_dirty) {
       st_validate_state(st, ST_PIPELINE_RENDER);
    }
 
@@ -278,7 +279,8 @@ st_indirect_draw_vbo(struct gl_context *ctx,
    assert(stride);
 
    /* Validate state. */
-   if ((st->dirty | ctx->NewDriverState) & ST_PIPELINE_RENDER_STATE_MASK) {
+   if ((st->dirty | ctx->NewDriverState) & ST_PIPELINE_RENDER_STATE_MASK ||
+       st->gfx_shaders_may_be_dirty) {
       st_validate_state(st, ST_PIPELINE_RENDER);
    }