From 7cc4f47afe2dbb112b0a84cb557160872e71c016 Mon Sep 17 00:00:00 2001 From: Matteo Bruni Date: Mon, 20 Aug 2012 22:34:58 +0200 Subject: [PATCH] wined3d: Force ARB shader programs reselection on bool/int constant changes. The ARB shader backend hardcodes some constant-dependent state in the shader itself (e.g. branch taken/not taken). So, we have to make sure to update the selected ARB shader when the application modifies non-float constants. --- dlls/wined3d/arb_program_shader.c | 38 ++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index c8799df333..c1a0718786 100644 --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -625,6 +625,8 @@ static void shader_arb_vs_local_constants(const struct arb_vs_compiled_shader *g checkGLcall("Load vs int consts"); } +static void shader_arb_select(const struct wined3d_context *context, BOOL usePS, BOOL useVS); + /** * Loads the app-supplied constants into the currently set ARB_[vertex/fragment]_programs. * @@ -632,13 +634,38 @@ static void shader_arb_vs_local_constants(const struct arb_vs_compiled_shader *g * worry about the Integers or Booleans */ /* GL locking is done by the caller (state handler) */ -static void shader_arb_load_constants(const struct wined3d_context *context, char usePixelShader, char useVertexShader) +static void shader_arb_load_constants_internal(const struct wined3d_context *context, + char usePixelShader, char useVertexShader, BOOL from_shader_select) { struct wined3d_device *device = context->swapchain->device; - const struct wined3d_state *state = &device->stateBlock->state; + const struct wined3d_stateblock *stateblock = device->stateBlock; + const struct wined3d_state *state = &stateblock->state; const struct wined3d_gl_info *gl_info = context->gl_info; struct shader_arb_priv *priv = device->shader_priv; + if (!from_shader_select) + { + const struct wined3d_shader *vshader = state->vertex_shader, *pshader = state->pixel_shader; + if (vshader + && (stateblock->changed.vertexShaderConstantsB & vshader->reg_maps.boolean_constants + || (!gl_info->supported[NV_VERTEX_PROGRAM2_OPTION] + && (stateblock->changed.vertexShaderConstantsI + & vshader->reg_maps.integer_constants & ~vshader->reg_maps.local_int_consts)))) + { + TRACE("bool/integer vertex shader constants potentially modified, forcing shader reselection.\n"); + shader_arb_select(context, usePixelShader, useVertexShader); + } + else if (pshader + && (stateblock->changed.pixelShaderConstantsB & pshader->reg_maps.boolean_constants + || (!gl_info->supported[NV_FRAGMENT_PROGRAM_OPTION] + && (stateblock->changed.pixelShaderConstantsI + & pshader->reg_maps.integer_constants & ~pshader->reg_maps.local_int_consts)))) + { + TRACE("bool/integer pixel shader constants potentially modified, forcing shader reselection.\n"); + shader_arb_select(context, usePixelShader, useVertexShader); + } + } + if (context != priv->last_context) { memset(priv->vshader_const_dirty, 1, @@ -676,6 +703,11 @@ static void shader_arb_load_constants(const struct wined3d_context *context, cha } } +static void shader_arb_load_constants(const struct wined3d_context *context, char ps, char vs) +{ + shader_arb_load_constants_internal(context, ps, vs, FALSE); +} + static void shader_arb_update_float_vertex_constants(struct wined3d_device *device, UINT start, UINT count) { struct wined3d_context *context = context_get_current(); @@ -4662,7 +4694,7 @@ static void shader_arb_select(const struct wined3d_context *context, BOOL usePS, priv->pshader_const_dirty[i] = 1; } /* Also takes care of loading local constants */ - shader_arb_load_constants(context, TRUE, FALSE); + shader_arb_load_constants_internal(context, TRUE, FALSE, TRUE); } else { -- 2.32.0.93.g670b81a890