[PATCH 1/5] wined3d: Avoid looking up shaders for shader stages that didn't change.

Henri Verbeet hverbeet at codeweavers.com
Wed Aug 21 01:29:27 CDT 2013


---
 dlls/wined3d/arb_program_shader.c  |   4 +-
 dlls/wined3d/ati_fragment_shader.c |   2 +-
 dlls/wined3d/context.c             |  12 ++--
 dlls/wined3d/glsl_shader.c         | 110 ++++++++++++++++++++++---------------
 dlls/wined3d/state.c               |  12 ++--
 dlls/wined3d/wined3d_private.h     |   3 +-
 6 files changed, 88 insertions(+), 55 deletions(-)

diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index 032ff14..1ba41b0 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -6493,7 +6493,7 @@ static void fragment_prog_arbfp(struct wined3d_context *context, const struct wi
         }
         else if (use_pshader)
         {
-            context->select_shader = 1;
+            context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_PIXEL;
         }
         return;
     }
@@ -6543,7 +6543,7 @@ static void fragment_prog_arbfp(struct wined3d_context *context, const struct wi
         context->last_was_pshader = TRUE;
     }
 
-    context->select_shader = 1;
+    context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_PIXEL;
 }
 
 /* We can't link the fog states to the fragment state directly since the
diff --git a/dlls/wined3d/ati_fragment_shader.c b/dlls/wined3d/ati_fragment_shader.c
index d3c01f2..cf35f64 100644
--- a/dlls/wined3d/ati_fragment_shader.c
+++ b/dlls/wined3d/ati_fragment_shader.c
@@ -942,7 +942,7 @@ static void atifs_apply_pixelshader(struct wined3d_context *context, const struc
      * startup, and blitting disables all shaders and dirtifies all shader
      * states. If atifs can deal with this it keeps the rest of the code
      * simpler. */
-    context->select_shader = 1;
+    context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_PIXEL;
 }
 
 static void atifs_srgbwriteenable(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index 123e9b1..dd0c1a9 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -1624,7 +1624,9 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
     {
         GL_EXTCALL(glProvokingVertexEXT(GL_FIRST_VERTEX_CONVENTION_EXT));
     }
-    ret->select_shader = 1;
+    ret->shader_update_mask = (1 << WINED3D_SHADER_TYPE_PIXEL)
+            | (1 << WINED3D_SHADER_TYPE_VERTEX)
+            | (1 << WINED3D_SHADER_TYPE_GEOMETRY);
 
     /* If this happens to be the first context for the device, dummy textures
      * are not created yet. In that case, they will be created (and bound) by
@@ -1901,7 +1903,9 @@ static void SetupForBlit(const struct wined3d_device *device, struct wined3d_con
 
     /* Disable shaders */
     device->shader_backend->shader_disable(device->shader_priv, context);
-    context->select_shader = 1;
+    context->shader_update_mask = (1 << WINED3D_SHADER_TYPE_PIXEL)
+            | (1 << WINED3D_SHADER_TYPE_VERTEX)
+            | (1 << WINED3D_SHADER_TYPE_GEOMETRY);
 
     context->blit_w = rt_size.cx;
     context->blit_h = rt_size.cy;
@@ -2379,10 +2383,10 @@ BOOL context_apply_draw_state(struct wined3d_context *context, struct wined3d_de
         state_table[rep].apply(context, state, rep);
     }
 
-    if (context->select_shader)
+    if (context->shader_update_mask)
     {
         device->shader_backend->shader_select(device->shader_priv, context, state);
-        context->select_shader = 0;
+        context->shader_update_mask = 0;
     }
 
     if (context->constant_update_mask)
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index a5b8c3b..4faf859 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -5843,23 +5843,40 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const
     GLhandleARB programId                  = 0;
     GLhandleARB reorder_shader_id          = 0;
     unsigned int i;
-    struct ps_compile_args ps_compile_args;
-    struct vs_compile_args vs_compile_args;
-    GLhandleARB vs_id, gs_id, ps_id;
+    GLhandleARB vs_id = 0;
+    GLhandleARB gs_id = 0;
+    GLhandleARB ps_id = 0;
     struct list *ps_list, *vs_list;
     struct wined3d_device *device = context->swapchain->device;
 
-    if (use_vs(state))
+    if (!(context->shader_update_mask & (1 << WINED3D_SHADER_TYPE_VERTEX)))
     {
+        vs_id = priv->glsl_program->vs.id;
+        vs_list = &priv->glsl_program->vs.shader_entry;
+
+        if (use_vs(state))
+        {
+            vshader = state->vertex_shader;
+            gshader = state->geometry_shader;
+
+            if (!(context->shader_update_mask & (1 << WINED3D_SHADER_TYPE_GEOMETRY))
+                    && priv->glsl_program->gs.id)
+                gs_id = priv->glsl_program->gs.id;
+            else if (gshader)
+                gs_id = find_glsl_geometry_shader(context, &priv->shader_buffer, gshader);
+        }
+    }
+    else if (use_vs(state))
+    {
+        struct vs_compile_args vs_compile_args;
         vshader = state->vertex_shader;
+
         find_vs_compile_args(state, vshader, &vs_compile_args);
         vs_id = find_glsl_vshader(context, &priv->shader_buffer, vshader, &vs_compile_args);
         vs_list = &vshader->linked_programs;
 
         if ((gshader = state->geometry_shader))
             gs_id = find_glsl_geometry_shader(context, &priv->shader_buffer, gshader);
-        else
-            gs_id = 0;
     }
     else if (priv->vertex_pipe == &glsl_vertex_pipe)
     {
@@ -5870,17 +5887,19 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const
         ffp_shader = shader_glsl_find_ffp_vertex_shader(priv, gl_info, &settings);
         vs_id = ffp_shader->id;
         vs_list = &ffp_shader->linked_programs;
-
-        gs_id = 0;
     }
-    else
+
+    if (!(context->shader_update_mask & (1 << WINED3D_SHADER_TYPE_PIXEL)))
     {
-        vs_id = 0;
-        gs_id = 0;
-    }
+        ps_id = priv->glsl_program->ps.id;
+        ps_list = &priv->glsl_program->ps.shader_entry;
 
-    if (use_ps(state))
+        if (use_ps(state))
+            pshader = state->pixel_shader;
+    }
+    else if (use_ps(state))
     {
+        struct ps_compile_args ps_compile_args;
         pshader = state->pixel_shader;
         find_ps_compile_args(state, pshader, &ps_compile_args);
         ps_id = find_glsl_pshader(context, &priv->shader_buffer,
@@ -5897,10 +5916,6 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const
         ps_id = ffp_shader->id;
         ps_list = &ffp_shader->linked_programs;
     }
-    else
-    {
-        ps_id = 0;
-    }
 
     if ((!vs_id && !gs_id && !ps_id) || (entry = get_glsl_program_entry(priv, vs_id, gs_id, ps_id)))
     {
@@ -6320,6 +6335,7 @@ static void shader_glsl_destroy(struct wined3d_shader *shader)
     struct glsl_shader_private *shader_data = shader->backend_data;
     struct wined3d_device *device = shader->device;
     struct shader_glsl_priv *priv = device->shader_priv;
+    BOOL invalidate_current_program = FALSE;
     const struct wined3d_gl_info *gl_info;
     const struct list *linked_programs;
     struct wined3d_context *context;
@@ -6347,22 +6363,22 @@ static void shader_glsl_destroy(struct wined3d_shader *shader)
             {
                 struct glsl_ps_compiled_shader *gl_shaders = shader_data->gl_shaders.ps;
 
-                LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs,
-                        struct glsl_shader_prog_link, ps.shader_entry)
-                {
-                    delete_glsl_program_entry(priv, gl_info, entry);
-                }
-
                 for (i = 0; i < shader_data->num_gl_shaders; ++i)
                 {
                     TRACE("Deleting pixel shader %u.\n", gl_shaders[i].prgId);
                     if (priv->glsl_program && priv->glsl_program->ps.id == gl_shaders[i].prgId)
-                        shader_glsl_disable(priv, context);
+                        invalidate_current_program = TRUE;
                     GL_EXTCALL(glDeleteObjectARB(gl_shaders[i].prgId));
                     checkGLcall("glDeleteObjectARB");
                 }
                 HeapFree(GetProcessHeap(), 0, shader_data->gl_shaders.ps);
 
+                LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs,
+                        struct glsl_shader_prog_link, ps.shader_entry)
+                {
+                    delete_glsl_program_entry(priv, gl_info, entry);
+                }
+
                 break;
             }
 
@@ -6370,22 +6386,22 @@ static void shader_glsl_destroy(struct wined3d_shader *shader)
             {
                 struct glsl_vs_compiled_shader *gl_shaders = shader_data->gl_shaders.vs;
 
-                LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs,
-                        struct glsl_shader_prog_link, vs.shader_entry)
-                {
-                    delete_glsl_program_entry(priv, gl_info, entry);
-                }
-
                 for (i = 0; i < shader_data->num_gl_shaders; ++i)
                 {
                     TRACE("Deleting vertex shader %u.\n", gl_shaders[i].prgId);
                     if (priv->glsl_program && priv->glsl_program->vs.id == gl_shaders[i].prgId)
-                        shader_glsl_disable(priv, context);
+                        invalidate_current_program = TRUE;
                     GL_EXTCALL(glDeleteObjectARB(gl_shaders[i].prgId));
                     checkGLcall("glDeleteObjectARB");
                 }
                 HeapFree(GetProcessHeap(), 0, shader_data->gl_shaders.vs);
 
+                LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs,
+                        struct glsl_shader_prog_link, vs.shader_entry)
+                {
+                    delete_glsl_program_entry(priv, gl_info, entry);
+                }
+
                 break;
             }
 
@@ -6393,22 +6409,22 @@ static void shader_glsl_destroy(struct wined3d_shader *shader)
             {
                 struct glsl_gs_compiled_shader *gl_shaders = shader_data->gl_shaders.gs;
 
-                LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs,
-                        struct glsl_shader_prog_link, gs.shader_entry)
-                {
-                    delete_glsl_program_entry(priv, gl_info, entry);
-                }
-
                 for (i = 0; i < shader_data->num_gl_shaders; ++i)
                 {
                     TRACE("Deleting geometry shader %u.\n", gl_shaders[i].id);
                     if (priv->glsl_program && priv->glsl_program->gs.id == gl_shaders[i].id)
-                        shader_glsl_disable(priv, context);
+                        invalidate_current_program = TRUE;
                     GL_EXTCALL(glDeleteObjectARB(gl_shaders[i].id));
                     checkGLcall("glDeleteObjectARB");
                 }
                 HeapFree(GetProcessHeap(), 0, shader_data->gl_shaders.gs);
 
+                LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs,
+                        struct glsl_shader_prog_link, gs.shader_entry)
+                {
+                    delete_glsl_program_entry(priv, gl_info, entry);
+                }
+
                 break;
             }
 
@@ -6418,6 +6434,14 @@ static void shader_glsl_destroy(struct wined3d_shader *shader)
         }
     }
 
+    if (invalidate_current_program)
+    {
+        shader_glsl_disable(priv, context);
+        context->shader_update_mask = (1 << WINED3D_SHADER_TYPE_PIXEL)
+                | (1 << WINED3D_SHADER_TYPE_VERTEX)
+                | (1 << WINED3D_SHADER_TYPE_GEOMETRY);
+    }
+
     HeapFree(GetProcessHeap(), 0, shader->backend_data);
     shader->backend_data = NULL;
 
@@ -6887,7 +6911,7 @@ static void glsl_vertex_pipe_vp_free(struct wined3d_device *device)
 static void glsl_vertex_pipe_shader(struct wined3d_context *context,
         const struct wined3d_state *state, DWORD state_id)
 {
-    context->select_shader = 1;
+    context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_VERTEX;
 }
 
 static void glsl_vertex_pipe_projection(struct wined3d_context *context,
@@ -6896,7 +6920,7 @@ static void glsl_vertex_pipe_projection(struct wined3d_context *context,
     /* Table fog behavior depends on the projection matrix. */
     if (state->render_states[WINED3D_RS_FOGENABLE]
             && state->render_states[WINED3D_RS_FOGTABLEMODE] != WINED3D_FOG_NONE)
-        context->select_shader = 1;
+        context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_VERTEX;
     transform_projection(context, state, state_id);
 }
 
@@ -7160,7 +7184,7 @@ static void glsl_fragment_pipe_shader(struct wined3d_context *context,
 {
     context->last_was_pshader = use_ps(state);
 
-    context->select_shader = 1;
+    context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_PIXEL;
 }
 
 static void glsl_fragment_pipe_fog(struct wined3d_context *context,
@@ -7171,7 +7195,7 @@ static void glsl_fragment_pipe_fog(struct wined3d_context *context,
     DWORD fogstart = state->render_states[WINED3D_RS_FOGSTART];
     DWORD fogend = state->render_states[WINED3D_RS_FOGEND];
 
-    context->select_shader = 1;
+    context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_PIXEL;
 
     if (!state->render_states[WINED3D_RS_FOGENABLE])
         return;
@@ -7200,7 +7224,7 @@ static void glsl_fragment_pipe_fog(struct wined3d_context *context,
 static void glsl_fragment_pipe_tex_transform(struct wined3d_context *context,
         const struct wined3d_state *state, DWORD state_id)
 {
-    context->select_shader = 1;
+    context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_PIXEL;
 }
 
 static void glsl_fragment_pipe_invalidate_constants(struct wined3d_context *context,
diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c
index ffc3101..b43fda8 100644
--- a/dlls/wined3d/state.c
+++ b/dlls/wined3d/state.c
@@ -607,7 +607,7 @@ void state_clipping(struct wined3d_context *context, const struct wined3d_state
      * The enabled / disabled planes are hardcoded into the shader. Update the
      * shader to update the enabled clipplanes. In case of fixed function, we
      * need to update the clipping field from ffp_vertex_settings. */
-    context->select_shader = 1;
+    context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_VERTEX;
 
     /* TODO: Keep track of previously enabled clipplanes to avoid unnecessary resetting
      * of already set values
@@ -3731,12 +3731,12 @@ void apply_pixelshader(struct wined3d_context *context, const struct wined3d_sta
         context->last_was_pshader = FALSE;
     }
 
-    context->select_shader = 1;
+    context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_PIXEL;
 }
 
 static void state_geometry_shader(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
-    context->select_shader = 1;
+    context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_GEOMETRY;
 }
 
 static void shader_bumpenv(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
@@ -4630,7 +4630,7 @@ void vertexdeclaration(struct wined3d_context *context, const struct wined3d_sta
     }
 
     context->last_was_vshader = useVertexShaderFunction;
-    context->select_shader = 1;
+    context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_VERTEX;
 
     if (updateFog)
         context_apply_state(context, state, STATE_RENDER(WINED3D_RS_FOGVERTEXMODE));
@@ -4644,6 +4644,10 @@ void vertexdeclaration(struct wined3d_context *context, const struct wined3d_sta
             if (!isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_TEXTURE0 + i)))
                 transform_texture(context, state, STATE_TEXTURESTAGE(i, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS));
         }
+
+        if (use_ps(state) && state->pixel_shader->reg_maps.shader_version.major == 1
+                && state->pixel_shader->reg_maps.shader_version.minor <= 3)
+            context->shader_update_mask |= 1 << WINED3D_SHADER_TYPE_PIXEL;
     }
 
     if (transformed != wasrhw && !isStateDirty(context, STATE_RENDER(WINED3D_RS_ZENABLE)))
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 49aacc1..12dd2c6 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1092,9 +1092,10 @@ struct wined3d_context
     DWORD current : 1;
     DWORD destroyed : 1;
     DWORD valid : 1;
-    DWORD select_shader : 1;
+    DWORD padding : 1;
     DWORD texShaderBumpMap : 8;         /* MAX_TEXTURES, 8 */
     DWORD lastWasPow2Texture : 8;       /* MAX_TEXTURES, 8 */
+    DWORD shader_update_mask;
     DWORD constant_update_mask;
     DWORD                   numbered_array_mask;
     GLenum                  tracking_parm;     /* Which source is tracking current colour         */
-- 
1.8.1.5




More information about the wine-patches mailing list