Module: wine Branch: master Commit: dd8905543ba0052adc7d26a0b14595aea5bad4f5 URL: http://source.winehq.org/git/wine.git/?a=commit;h=dd8905543ba0052adc7d26a0b1...
Author: Stefan Dösinger stefan@codeweavers.com Date: Thu Nov 20 02:55:17 2008 +0100
wined3d: Pass some stateblock values around directly.
This was suggested by Ivan quite a while ago, and we need it to better handle conflicting texture format corrections and similar stateblock value changes which until now required a recompilation of the entire shader
---
dlls/wined3d/arb_program_shader.c | 4 ++- dlls/wined3d/glsl_shader.c | 4 ++- dlls/wined3d/pixelshader.c | 53 ++++++++++++++++++++++++------------ dlls/wined3d/wined3d_private.h | 12 +++++++- 4 files changed, 52 insertions(+), 21 deletions(-)
diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index 5c6e29f..20e731b 100644 --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -1895,8 +1895,10 @@ static void shader_arb_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) { }
if (usePS) { + struct ps_compile_args compile_args; TRACE("Using pixel shader\n"); - pixelshader_compile(This->stateBlock->pixelShader); + find_ps_compile_args((IWineD3DPixelShaderImpl *) This->stateBlock->pixelShader, This->stateBlock, &compile_args); + pixelshader_compile(This->stateBlock->pixelShader, &compile_args);
priv->current_fprogram_id = ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.prgId;
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index d850ba8..92a6a36 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -3234,7 +3234,9 @@ static void set_glsl_shader_program(IWineD3DDevice *iface, BOOL use_ps, BOOL use vshader_id = 0; } if(use_ps) { - pixelshader_compile(pshader); + struct ps_compile_args compile_args; + find_ps_compile_args((IWineD3DPixelShaderImpl*)This->stateBlock->pixelShader, This->stateBlock, &compile_args); + pixelshader_compile(pshader, &compile_args); pshader_id = ((IWineD3DBaseShaderImpl*)pshader)->baseShader.prgId; } else { pshader_id = 0; diff --git a/dlls/wined3d/pixelshader.c b/dlls/wined3d/pixelshader.c index cb5d227..1ce2849 100644 --- a/dlls/wined3d/pixelshader.c +++ b/dlls/wined3d/pixelshader.c @@ -384,13 +384,12 @@ static HRESULT WINAPI IWineD3DPixelShaderImpl_SetFunction(IWineD3DPixelShader *i return WINED3D_OK; }
-HRESULT pixelshader_compile(IWineD3DPixelShader *iface) { +HRESULT pixelshader_compile(IWineD3DPixelShader *iface, struct ps_compile_args *args) {
IWineD3DPixelShaderImpl *This =(IWineD3DPixelShaderImpl *)iface; IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device; CONST DWORD *function = This->baseShader.function; UINT i, sampler; - IWineD3DBaseTextureImpl *texture; HRESULT hr;
TRACE("(%p) : function %p\n", iface, function); @@ -399,15 +398,13 @@ HRESULT pixelshader_compile(IWineD3DPixelShader *iface) { * changed. */ if (This->baseShader.is_compiled) { - char srgbenabled = deviceImpl->stateBlock->renderState[WINED3DRS_SRGBWRITEENABLE] ? 1 : 0; for(i = 0; i < This->baseShader.num_sampled_samplers; i++) { sampler = This->baseShader.sampled_samplers[i]; - texture = (IWineD3DBaseTextureImpl *) deviceImpl->stateBlock->textures[sampler]; - if(texture && texture->baseTexture.shader_conversion_group != This->baseShader.sampled_format[sampler]) { + if(args->format_conversion[sampler] != This->baseShader.sampled_format[sampler]) { WARN("Recompiling shader %p due to format change on sampler %d\n", This, sampler); WARN("Old format group %s, new is %s\n", debug_d3dformat(This->baseShader.sampled_format[sampler]), - debug_d3dformat(texture->baseTexture.shader_conversion_group)); + debug_d3dformat(args->format_conversion[sampler])); goto recompile; } } @@ -415,7 +412,7 @@ HRESULT pixelshader_compile(IWineD3DPixelShader *iface) { /* TODO: Check projected textures */ /* TODO: Check texture types(2D, Cube, 3D) */
- if(srgbenabled != This->srgb_enabled && This->srgb_mode_hardcoded) { + if(args->srgb_correction != This->srgb_enabled && This->srgb_mode_hardcoded) { WARN("Recompiling shader because srgb correction is different and hardcoded\n"); goto recompile; } @@ -433,17 +430,8 @@ HRESULT pixelshader_compile(IWineD3DPixelShader *iface) { } } if(This->baseShader.hex_version >= WINED3DPS_VERSION(3,0)) { - if(((IWineD3DDeviceImpl *) This->baseShader.device)->strided_streams.u.s.position_transformed) { - if(This->vertexprocessing != pretransformed) { - WARN("Recompiling shader because pretransformed vertices are provided, which wasn't the case before\n"); - goto recompile; - } - } else if(!use_vs((IWineD3DDeviceImpl *) This->baseShader.device) && - This->vertexprocessing != fixedfunction) { - WARN("Recompiling shader because fixed function vp is in use, which wasn't the case before\n"); - goto recompile; - } else if(This->vertexprocessing != vertexshader) { - WARN("Recompiling shader because vertex shaders are in use, which wasn't the case before\n"); + if(args->vp_mode != This->vertexprocessing) { + WARN("Recompiling shader because the vertex processing mode changed\n"); goto recompile; } } @@ -515,3 +503,32 @@ const IWineD3DPixelShaderVtbl IWineD3DPixelShader_Vtbl = IWineD3DPixelShaderImpl_GetDevice, IWineD3DPixelShaderImpl_GetFunction }; + +void find_ps_compile_args(IWineD3DPixelShaderImpl *shader, IWineD3DStateBlockImpl *stateblock, struct ps_compile_args *args) { + UINT i, sampler; + IWineD3DBaseTextureImpl *tex; + + args->srgb_correction = stateblock->renderState[WINED3DRS_SRGBWRITEENABLE] ? 1 : 0; + + memset(args->format_conversion, 0, sizeof(args->format_conversion)); + for(i = 0; i < shader->baseShader.num_sampled_samplers; i++) { + sampler = shader->baseShader.sampled_samplers[i]; + tex = (IWineD3DBaseTextureImpl *) stateblock->textures[sampler]; + if(!tex) { + args->format_conversion[sampler] = WINED3DFMT_UNKNOWN; + continue; + } + args->format_conversion[sampler] = tex->baseTexture.shader_conversion_group; + } + if(shader->baseShader.hex_version >= WINED3DPS_VERSION(3,0)) { + if(((IWineD3DDeviceImpl *) shader->baseShader.device)->strided_streams.u.s.position_transformed) { + args->vp_mode = pretransformed; + } else if(use_vs((IWineD3DDeviceImpl *) shader->baseShader.device)) { + args->vp_mode = vertexshader; + } else { + args->vp_mode = fixedfunction; + } + } else { + args->vp_mode = vertexshader; + } +} diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 015d7c0..847d11d 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2337,6 +2337,15 @@ struct stb_const_desc { UINT const_num; };
+/* Stateblock dependent parameters which have to be hardcoded + * into the shader code + */ +struct ps_compile_args { + BOOL srgb_correction; + WINED3DFORMAT format_conversion[MAX_FRAGMENT_SAMPLERS]; + enum vertexprocessing_mode vp_mode; +}; + typedef struct IWineD3DPixelShaderImpl { /* IUnknown parts */ const IWineD3DPixelShaderVtbl *lpVtbl; @@ -2369,7 +2378,8 @@ typedef struct IWineD3DPixelShaderImpl {
extern const SHADER_OPCODE IWineD3DPixelShaderImpl_shader_ins[]; extern const IWineD3DPixelShaderVtbl IWineD3DPixelShader_Vtbl; -HRESULT pixelshader_compile(IWineD3DPixelShader *iface); +HRESULT pixelshader_compile(IWineD3DPixelShader *iface, struct ps_compile_args *args); +void find_ps_compile_args(IWineD3DPixelShaderImpl *shader, IWineD3DStateBlockImpl *stateblock, struct ps_compile_args *args);
/* sRGB correction constants */ static const float srgb_cmp = 0.0031308;