[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