diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index 3db3b545fef..e2faaac3158 100644 --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -5821,14 +5821,10 @@ static void set_bumpmat_arbfp(struct wined3d_context *context, const struct wine if (use_ps(state)) { + /* The pixel shader has to know the bump env matrix. Do a constants + * update. */ if (stage && (state->pixel_shader->reg_maps.bumpmat & (1 << stage))) - { - /* The pixel shader has to know the bump env matrix. Do a constants update if it isn't scheduled - * anyway - */ - if (!isStateDirty(context, STATE_PIXELSHADERCONSTANT)) - context_apply_state(context, state, STATE_PIXELSHADERCONSTANT); - } + context->load_constants = 1; if(device->shader_backend == &arb_program_shader_backend) { /* Exit now, don't set the bumpmat below, otherwise we may overwrite pixel shader constants */ @@ -5861,14 +5857,10 @@ static void tex_bumpenvlum_arbfp(struct wined3d_context *context, if (use_ps(state)) { + /* The pixel shader has to know the luminance offset. Do a constants + * update. */ if (stage && (state->pixel_shader->reg_maps.luminanceparams & (1 << stage))) - { - /* The pixel shader has to know the luminance offset. Do a constants update if it - * isn't scheduled anyway - */ - if (!isStateDirty(context, STATE_PIXELSHADERCONSTANT)) - context_apply_state(context, state, STATE_PIXELSHADERCONSTANT); - } + context->load_constants = 1; if(device->shader_backend == &arb_program_shader_backend) { /* Exit now, don't set the bumpmat below, otherwise we may overwrite pixel shader constants */ @@ -6391,7 +6383,6 @@ static void fragment_prog_arbfp(struct wined3d_context *context, const struct wi const struct wined3d_device *device = context->swapchain->device; const struct wined3d_gl_info *gl_info = context->gl_info; struct shader_arb_priv *priv = device->fragment_priv; - BOOL use_vshader = use_vs(state); BOOL use_pshader = use_ps(state); struct ffp_frag_settings settings; const struct arbfp_ffp_desc *desc; @@ -6412,9 +6403,9 @@ static void fragment_prog_arbfp(struct wined3d_context *context, const struct wi state_texfactor_arbfp(context, state, STATE_RENDER(WINED3D_RS_TEXTUREFACTOR)); state_arb_specularenable(context, state, STATE_RENDER(WINED3D_RS_SPECULARENABLE)); } - else if (use_pshader && !isStateDirty(context, context->state_table[STATE_VSHADER].representative)) + else if (use_pshader) { - device->shader_backend->shader_select(context, use_pshader, use_vshader); + context->select_shader = 1; } return; } @@ -6464,24 +6455,8 @@ static void fragment_prog_arbfp(struct wined3d_context *context, const struct wi context->last_was_pshader = TRUE; } - /* Finally, select the shader. If a pixel shader is used, it will be set and enabled by the shader backend. - * If this shader backend is arbfp(most likely), then it will simply overwrite the last fixed function - * replacement shader. If the shader backend is not ARB, it currently is important that the opengl implementation - * type overwrites GL_ARB_fragment_program. This is currently the case with GLSL. If we really want to use - * atifs or nvrc pixel shaders with arb fragment programs we'd have to disable GL_FRAGMENT_PROGRAM_ARB here - * - * Don't call shader_select if the vertex shader is dirty, because it will be called later on by the vertex - * shader handler. - */ - if (!isStateDirty(context, context->state_table[STATE_VSHADER].representative)) - { - device->shader_backend->shader_select(context, use_pshader, use_vshader); - - if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (use_vshader || use_pshader)) - context_apply_state(context, state, STATE_VERTEXSHADERCONSTANT); - } - if (use_pshader) - context_apply_state(context, state, STATE_PIXELSHADERCONSTANT); + context->select_shader = 1; + context->load_constants = 1; } /* 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 5e048789db9..fba55ea8f0c 100644 --- a/dlls/wined3d/ati_fragment_shader.c +++ b/dlls/wined3d/ati_fragment_shader.c @@ -926,9 +926,6 @@ static void textransform(struct wined3d_context *context, const struct wined3d_s static void atifs_apply_pixelshader(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { - const struct wined3d_device *device = context->swapchain->device; - BOOL use_vshader = use_vs(state); - context->last_was_pshader = use_ps(state); /* The ATIFS code does not support pixel shaders currently, but we have to * provide a state handler to call shader_select to select a vertex shader @@ -943,13 +940,8 @@ 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. */ - if (!isStateDirty(context, context->state_table[STATE_VSHADER].representative)) - { - device->shader_backend->shader_select(context, FALSE, use_vshader); - - if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && use_vshader) - context_apply_state(context, state, STATE_VERTEXSHADERCONSTANT); - } + context->select_shader = 1; + context->load_constants = 1; } 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 9ef0dff5339..999adee80f5 100644 --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c @@ -1711,11 +1711,10 @@ static void SetupForBlit(const struct wined3d_device *device, struct wined3d_con /* Disable shaders */ ENTER_GL(); device->shader_backend->shader_select(context, FALSE, FALSE); + context->select_shader = 1; + context->load_constants = 1; LEAVE_GL(); - context_invalidate_state(context, STATE_VSHADER); - context_invalidate_state(context, STATE_PIXELSHADER); - /* Call ENTER_GL() once for all gl calls below. In theory we should not call * helper functions in between gl calls. This function is full of context_invalidate_state * which can safely be called from here, we only lock once instead locking/unlocking @@ -2365,6 +2364,18 @@ BOOL context_apply_draw_state(struct wined3d_context *context, struct wined3d_de state_table[rep].apply(context, state, rep); } + if (context->select_shader) + { + device->shader_backend->shader_select(context, use_ps(state), use_vs(state)); + context->select_shader = 0; + } + + if (context->load_constants) + { + device->shader_backend->shader_load_constants(context, use_ps(state), use_vs(state)); + context->load_constants = 0; + } + if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) { context_check_fbo_status(context, GL_FRAMEBUFFER); diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c index 32e6d73efda..7538721e48b 100644 --- a/dlls/wined3d/state.c +++ b/dlls/wined3d/state.c @@ -599,15 +599,7 @@ static void state_alpha(struct wined3d_context *context, const struct wined3d_st static void shaderconstant(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { - const struct wined3d_device *device = context->swapchain->device; - - /* Vertex and pixel shader states will call a shader upload, don't do - * anything as long one of them has an update pending. */ - if (isStateDirty(context, STATE_VDECL) - || isStateDirty(context, STATE_PIXELSHADER)) - return; - - device->shader_backend->shader_load_constants(context, use_ps(state), use_vs(state)); + context->load_constants = 1; } static void state_clipping(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) @@ -640,12 +632,8 @@ static void state_clipping(struct wined3d_context *context, const struct wined3d /* glEnable(GL_CLIP_PLANEx) doesn't apply to vertex shaders. The enabled / disabled planes are * hardcoded into the shader. Update the shader to update the enabled clipplanes */ - if (!isStateDirty(context, context->state_table[STATE_VSHADER].representative)) - { - device->shader_backend->shader_select(context, use_ps(state), TRUE); - if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT)) - shaderconstant(context, state, STATE_VERTEXSHADERCONSTANT); - } + context->select_shader = 1; + context->load_constants = 1; } /* TODO: Keep track of previously enabled clipplanes to avoid unnecessary resetting @@ -3618,14 +3606,9 @@ static void tex_bumpenvlscale(struct wined3d_context *context, const struct wine DWORD stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1); const struct wined3d_shader *ps = state->pixel_shader; + /* The pixel shader has to know the luminance scale. Do a constants update. */ if (ps && stage && (ps->reg_maps.luminanceparams & (1 << stage))) - { - /* The pixel shader has to know the luminance scale. Do a constants - * update if it isn't scheduled anyway. */ - if (!isStateDirty(context, STATE_PIXELSHADERCONSTANT) - && !isStateDirty(context, STATE_PIXELSHADER)) - shaderconstant(context, state, STATE_PIXELSHADERCONSTANT); - } + context->load_constants = 1; } static void sampler_texmatrix(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) @@ -3738,12 +3721,9 @@ static void sampler(struct wined3d_context *context, const struct wined3d_state void apply_pixelshader(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { - const struct wined3d_device *device = context->swapchain->device; - BOOL use_vshader = use_vs(state); - BOOL use_pshader = use_ps(state); unsigned int i; - if (use_pshader) + if (use_ps(state)) { if (!context->last_was_pshader) { @@ -3776,13 +3756,8 @@ void apply_pixelshader(struct wined3d_context *context, const struct wined3d_sta context->last_was_pshader = FALSE; } - if (!isStateDirty(context, context->state_table[STATE_VSHADER].representative)) - { - device->shader_backend->shader_select(context, use_pshader, use_vshader); - - if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (use_vshader || use_pshader)) - shaderconstant(context, state, STATE_VERTEXSHADERCONSTANT); - } + context->select_shader = 1; + context->load_constants = 1; } static void shader_bumpenvmat(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) @@ -3790,14 +3765,9 @@ static void shader_bumpenvmat(struct wined3d_context *context, const struct wine DWORD stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1); const struct wined3d_shader *ps = state->pixel_shader; + /* The pixel shader has to know the bump env matrix. Do a constants update. */ if (ps && stage && (ps->reg_maps.bumpmat & (1 << stage))) - { - /* The pixel shader has to know the bump env matrix. Do a constants - * update if it isn't scheduled anyway. */ - if (!isStateDirty(context, STATE_PIXELSHADERCONSTANT) - && !isStateDirty(context, STATE_PIXELSHADER)) - shaderconstant(context, state, STATE_PIXELSHADERCONSTANT); - } + context->load_constants = 1; } static void transform_world(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) @@ -4580,7 +4550,6 @@ static void vertexdeclaration(struct wined3d_context *context, const struct wine const struct wined3d_device *device = context->swapchain->device; const struct wined3d_gl_info *gl_info = context->gl_info; BOOL useVertexShaderFunction = use_vs(state); - BOOL usePixelShaderFunction = use_ps(state); BOOL updateFog = FALSE; BOOL transformed; BOOL wasrhw = context->last_was_rhw; @@ -4684,18 +4653,9 @@ static void vertexdeclaration(struct wined3d_context *context, const struct wine } } - /* Vertex and pixel shaders are applied together, so let the last dirty - * state do the application. */ - if (!isStateDirty(context, STATE_PIXELSHADER)) - { - device->shader_backend->shader_select(context, usePixelShaderFunction, useVertexShaderFunction); - - if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) - && (useVertexShaderFunction || usePixelShaderFunction)) - shaderconstant(context, state, STATE_VERTEXSHADERCONSTANT); - } - context->last_was_vshader = useVertexShaderFunction; + context->select_shader = 1; + context->load_constants = 1; if (updateFog) context_apply_state(context, state, STATE_RENDER(WINED3D_RS_FOGVERTEXMODE)); @@ -4753,8 +4713,7 @@ static void viewport_vertexpart(struct wined3d_context *context, const struct wi if (!isStateDirty(context, STATE_RENDER(WINED3D_RS_POINTSCALEENABLE))) state_pscale(context, state, STATE_RENDER(WINED3D_RS_POINTSCALEENABLE)); /* Update the position fixup. */ - if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT)) - shaderconstant(context, state, STATE_VERTEXSHADERCONSTANT); + context->load_constants = 1; } static void light(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index c189963a5f1..e9fd80f599e 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1084,21 +1084,23 @@ struct wined3d_context DWORD tid; /* Thread ID which owns this context at the moment */ /* Stores some information about the context state for optimization */ - WORD render_offscreen : 1; - WORD last_was_rhw : 1; /* true iff last draw_primitive was in xyzrhw mode */ - WORD last_was_pshader : 1; - WORD last_was_vshader : 1; - WORD namedArraysLoaded : 1; - WORD numberedArraysLoaded : 1; - WORD last_was_blit : 1; - WORD last_was_ckey : 1; - WORD fog_coord : 1; - WORD fog_enabled : 1; - WORD num_untracked_materials : 2; /* Max value 2 */ - WORD current : 1; - WORD destroyed : 1; - WORD valid : 1; - WORD padding : 1; + DWORD render_offscreen : 1; + DWORD last_was_rhw : 1; /* true iff last draw_primitive was in xyzrhw mode */ + DWORD last_was_pshader : 1; + DWORD last_was_vshader : 1; + DWORD namedArraysLoaded : 1; + DWORD numberedArraysLoaded : 1; + DWORD last_was_blit : 1; + DWORD last_was_ckey : 1; + DWORD fog_coord : 1; + DWORD fog_enabled : 1; + DWORD num_untracked_materials : 2; /* Max value 2 */ + DWORD current : 1; + DWORD destroyed : 1; + DWORD valid : 1; + DWORD select_shader : 1; + DWORD load_constants : 1; + DWORD padding : 15; BYTE texShaderBumpMap; /* MAX_TEXTURES, 8 */ BYTE lastWasPow2Texture; /* MAX_TEXTURES, 8 */ DWORD numbered_array_mask;