From ff767f4984198e85477c0aee3fa49844caae6a60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20D=C3=B6singer?= Date: Mon, 24 Nov 2008 11:52:12 +0100 Subject: [PATCH] wined3d: Make the shader backend call CompileShader. A number of considerations contribute to this: 1) The shader backend knows best which shader(s) it needs. GLSL needs both, arb only one 2) The shader backend may pass some parameters to the compilation code(e.g. which pixel format fixup to use) 3) The structures used in (2) are different in vs and ps, so a baseshader::Compile won't work 4) The structures in (2) are wined3d-private structures, so having a public method in the vtable won't work(its a bad idea anyway). --- dlls/wined3d/arb_program_shader.c | 10 ++++----- dlls/wined3d/device.c | 2 +- dlls/wined3d/glsl_shader.c | 15 +++++++++++-- dlls/wined3d/pixelshader.c | 37 ++++++++++++++++++++----------- dlls/wined3d/state.c | 8 ------- dlls/wined3d/vertexshader.c | 3 +-- dlls/wined3d/wined3d_private.h | 2 ++ include/wine/wined3d_interface.h | 8 ++----- 8 files changed, 47 insertions(+), 38 deletions(-) diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index 12148e6f509..5c6e29f806f 100644 --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -1876,6 +1876,7 @@ static void shader_arb_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) { if (useVS) { TRACE("Using vertex shader\n"); + IWineD3DVertexShaderImpl_CompileShader(This->stateBlock->vertexShader); priv->current_vprogram_id = ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.prgId; @@ -1895,6 +1896,7 @@ static void shader_arb_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) { if (usePS) { TRACE("Using pixel shader\n"); + pixelshader_compile(This->stateBlock->pixelShader); priv->current_fprogram_id = ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.prgId; @@ -3065,9 +3067,7 @@ static void fragment_prog_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, unsigned int i; if(isStateDirty(context, STATE_RENDER(WINED3DRS_FOGENABLE))) { - if(use_pshader) { - IWineD3DPixelShader_CompileShader(stateblock->pixelShader); - } else if(device->shader_backend == &arb_program_shader_backend && context->last_was_pshader) { + if(!use_pshader && device->shader_backend == &arb_program_shader_backend && context->last_was_pshader) { /* Reload fixed function constants since they collide with the pixel shader constants */ for(i = 0; i < MAX_TEXTURES; i++) { set_bumpmat_arbfp(STATE_TEXTURESTAGE(i, WINED3DTSS_BUMPENVMAT00), stateblock, context); @@ -3078,9 +3078,7 @@ static void fragment_prog_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, return; } - if(use_pshader) { - IWineD3DPixelShader_CompileShader(stateblock->pixelShader); - } else { + if(!use_pshader) { /* Find or create a shader implementing the fixed function pipeline settings, then activate it */ gen_ffp_frag_op(stateblock, &settings, FALSE); desc = (struct arbfp_ffp_desc *) find_ffp_frag_shader(priv->fragment_shaders, &settings); diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index be0bdb2217f..aa9fa35b35c 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -3854,7 +3854,7 @@ static void device_map_vsamplers(IWineD3DDeviceImpl *This, BOOL ps) { IWineD3DPixelShaderImpl *pshader = (IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader; /* Make sure the shader's reg_maps are up to date. This is only relevant for 1.x pixelshaders. */ - IWineD3DPixelShader_CompileShader((IWineD3DPixelShader *)pshader); + IWineD3DPixelShader_UpdateSamplers((IWineD3DPixelShader *)pshader); pshader_sampler_tokens = pshader->baseShader.reg_maps.samplers; } diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index bb9a8717cdc..d850ba8139a 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -3225,9 +3225,20 @@ static void set_glsl_shader_program(IWineD3DDevice *iface, BOOL use_ps, BOOL use GLhandleARB reorder_shader_id = 0; int i; char glsl_name[8]; + GLhandleARB vshader_id, pshader_id; - GLhandleARB vshader_id = use_vs ? ((IWineD3DBaseShaderImpl*)vshader)->baseShader.prgId : 0; - GLhandleARB pshader_id = use_ps ? ((IWineD3DBaseShaderImpl*)pshader)->baseShader.prgId : 0; + if(use_vs) { + IWineD3DVertexShaderImpl_CompileShader(vshader); + vshader_id = ((IWineD3DBaseShaderImpl*)vshader)->baseShader.prgId; + } else { + vshader_id = 0; + } + if(use_ps) { + pixelshader_compile(pshader); + pshader_id = ((IWineD3DBaseShaderImpl*)pshader)->baseShader.prgId; + } else { + pshader_id = 0; + } entry = get_glsl_program_entry(priv, vshader_id, pshader_id); if (entry) { priv->glsl_program = entry; diff --git a/dlls/wined3d/pixelshader.c b/dlls/wined3d/pixelshader.c index 246b58addf0..cb5d2273f1d 100644 --- a/dlls/wined3d/pixelshader.c +++ b/dlls/wined3d/pixelshader.c @@ -384,13 +384,14 @@ static HRESULT WINAPI IWineD3DPixelShaderImpl_SetFunction(IWineD3DPixelShader *i return WINED3D_OK; } -static HRESULT WINAPI IWineD3DPixelShaderImpl_CompileShader(IWineD3DPixelShader *iface) { +HRESULT pixelshader_compile(IWineD3DPixelShader *iface) { 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); @@ -465,17 +466,8 @@ static HRESULT WINAPI IWineD3DPixelShaderImpl_CompileShader(IWineD3DPixelShader return WINED3D_OK; } - if (WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) == 1) { - shader_reg_maps *reg_maps = &This->baseShader.reg_maps; - HRESULT hr; - - /* Second pass: figure out which registers are used, what the semantics are, etc.. */ - memset(reg_maps, 0, sizeof(shader_reg_maps)); - hr = shader_get_registers_used((IWineD3DBaseShader*)This, reg_maps, - This->semantics_in, NULL, This->baseShader.function, deviceImpl->stateBlock); - if (FAILED(hr)) return hr; - /* FIXME: validate reg_maps against OpenGL */ - } + hr = IWineD3DPixelShader_UpdateSamplers(iface); + if(FAILED(hr)) return hr; /* Reset fields tracking stateblock values being hardcoded in the shader */ This->baseShader.num_sampled_samplers = 0; @@ -489,6 +481,25 @@ static HRESULT WINAPI IWineD3DPixelShaderImpl_CompileShader(IWineD3DPixelShader return WINED3D_OK; } +static HRESULT WINAPI IWineD3DPixelShaderImpl_UpdateSamplers(IWineD3DPixelShader *iface) { + IWineD3DPixelShaderImpl *This =(IWineD3DPixelShaderImpl *)iface; + + if (WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) == 1) { + IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device; + shader_reg_maps *reg_maps = &This->baseShader.reg_maps; + HRESULT hr; + + /* Second pass: figure out which registers are used, what the semantics are, etc.. */ + memset(reg_maps, 0, sizeof(shader_reg_maps)); + hr = shader_get_registers_used((IWineD3DBaseShader*)This, reg_maps, + This->semantics_in, NULL, This->baseShader.function, deviceImpl->stateBlock); + return hr; + /* FIXME: validate reg_maps against OpenGL */ + } else { + return WINED3D_OK; + } +} + const IWineD3DPixelShaderVtbl IWineD3DPixelShader_Vtbl = { /*** IUnknown methods ***/ @@ -499,8 +510,8 @@ const IWineD3DPixelShaderVtbl IWineD3DPixelShader_Vtbl = IWineD3DPixelShaderImpl_GetParent, /*** IWineD3DBaseShader methods ***/ IWineD3DPixelShaderImpl_SetFunction, - IWineD3DPixelShaderImpl_CompileShader, /*** IWineD3DPixelShader methods ***/ + IWineD3DPixelShaderImpl_UpdateSamplers, IWineD3DPixelShaderImpl_GetDevice, IWineD3DPixelShaderImpl_GetFunction }; diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c index b9d28d4720c..f3cdb881e42 100644 --- a/dlls/wined3d/state.c +++ b/dlls/wined3d/state.c @@ -3518,9 +3518,6 @@ void apply_pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DC * if a different texture was bound. I don't have to do anything. */ } - - /* Compile and bind the shader */ - IWineD3DPixelShader_CompileShader(stateblock->pixelShader); } else { /* Disabled the pixel shader - color ops weren't applied * while it was enabled, so re-apply them. @@ -4511,11 +4508,6 @@ static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, W state_normalize(STATE_RENDER(WINED3DRS_NORMALIZENORMALS), stateblock, context); } } else { - /* We compile the shader here because we need the vertex declaration - * in order to determine if we need to do any swizzling for D3DCOLOR - * registers. If the shader is already compiled this call will do nothing. */ - IWineD3DVertexShader_CompileShader(stateblock->vertexShader); - if(!context->last_was_vshader) { int i; static BOOL warned = FALSE; diff --git a/dlls/wined3d/vertexshader.c b/dlls/wined3d/vertexshader.c index 05c6d6dec77..10986614e54 100644 --- a/dlls/wined3d/vertexshader.c +++ b/dlls/wined3d/vertexshader.c @@ -563,7 +563,7 @@ static inline BOOL swizzled_attribs_differ(IWineD3DVertexShaderImpl *This, IWine return FALSE; } -static HRESULT WINAPI IWineD3DVertexShaderImpl_CompileShader(IWineD3DVertexShader *iface) { +HRESULT IWineD3DVertexShaderImpl_CompileShader(IWineD3DVertexShader *iface) { IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface; IWineD3DVertexDeclarationImpl *vdecl; CONST DWORD *function = This->baseShader.function; @@ -626,7 +626,6 @@ const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl = IWineD3DVertexShaderImpl_GetParent, /*** IWineD3DBaseShader methods ***/ IWineD3DVertexShaderImpl_SetFunction, - IWineD3DVertexShaderImpl_CompileShader, /*** IWineD3DVertexShader methods ***/ IWineD3DVertexShaderImpl_GetDevice, IWineD3DVertexShaderImpl_GetFunction, diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index e3d35f248b0..015d7c08e41 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2320,6 +2320,7 @@ typedef struct IWineD3DVertexShaderImpl { } IWineD3DVertexShaderImpl; extern const SHADER_OPCODE IWineD3DVertexShaderImpl_shader_ins[]; extern const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl; +HRESULT IWineD3DVertexShaderImpl_CompileShader(IWineD3DVertexShader *iface); /***************************************************************************** * IDirect3DPixelShader implementation structure @@ -2368,6 +2369,7 @@ typedef struct IWineD3DPixelShaderImpl { extern const SHADER_OPCODE IWineD3DPixelShaderImpl_shader_ins[]; extern const IWineD3DPixelShaderVtbl IWineD3DPixelShader_Vtbl; +HRESULT pixelshader_compile(IWineD3DPixelShader *iface); /* sRGB correction constants */ static const float srgb_cmp = 0.0031308; diff --git a/include/wine/wined3d_interface.h b/include/wine/wined3d_interface.h index 27797c670f9..6d5f7e57912 100644 --- a/include/wine/wined3d_interface.h +++ b/include/wine/wined3d_interface.h @@ -1458,7 +1458,6 @@ DECLARE_INTERFACE_(IWineD3DBaseShader,IWineD3DBase) STDMETHOD(GetParent)(THIS_ IUnknown **pParent) PURE; /*** IWineD3DBaseShader methods ***/ STDMETHOD(SetFunction)(THIS_ CONST DWORD *pFunction) PURE; - STDMETHOD(CompileShader)(THIS) PURE; }; #undef INTERFACE @@ -1471,7 +1470,6 @@ DECLARE_INTERFACE_(IWineD3DBaseShader,IWineD3DBase) #define IWineD3DBaseShader_GetParent(p,a) (p)->lpVtbl->GetParent(p,a) /*** IWineD3DBaseShader methods ***/ #define IWineD3DBaseShader_SetFunction(p,a) (p)->lpVtbl->SetFunction(p,a) -#define IWineD3DBaseShader_CompileShader(p) (p)->lpVtbl->CompileShader(p) #endif /***************************************************************************** @@ -1488,7 +1486,6 @@ DECLARE_INTERFACE_(IWineD3DVertexShader,IWineD3DBaseShader) STDMETHOD(GetParent)(THIS_ IUnknown **pParent) PURE; /*** IWineD3DBaseShader methods ***/ STDMETHOD(SetFunction)(THIS_ CONST DWORD *pFunction) PURE; - STDMETHOD(CompileShader)(THIS) PURE; /*** IWineD3DVertexShader methods ***/ STDMETHOD(GetDevice)(THIS_ IWineD3DDevice** ppDevice) PURE; STDMETHOD(GetFunction)(THIS_ VOID *pData, UINT *pSizeOfData) PURE; @@ -1506,7 +1503,6 @@ DECLARE_INTERFACE_(IWineD3DVertexShader,IWineD3DBaseShader) #define IWineD3DVertexShader_GetParent(p,a) (p)->lpVtbl->GetParent(p,a) /*** IWineD3DBaseShader methods ***/ #define IWineD3DVertexShader_SetFunction(p,a) (p)->lpVtbl->SetFunction(p,a) -#define IWineD3DVertexShader_CompileShader(p) (p)->lpVtbl->CompileShader(p) /*** IWineD3DVertexShader methods ***/ #define IWineD3DVertexShader_GetDevice(p,a) (p)->lpVtbl->GetDevice(p,a) #define IWineD3DVertexShader_GetFunction(p,a,b) (p)->lpVtbl->GetFunction(p,a,b) @@ -1528,8 +1524,8 @@ DECLARE_INTERFACE_(IWineD3DPixelShader,IWineD3DBaseShader) STDMETHOD(GetParent)(THIS_ IUnknown **pParent) PURE; /*** IWineD3DBaseShader methods ***/ STDMETHOD(SetFunction)(THIS_ CONST DWORD *pFunction) PURE; - STDMETHOD(CompileShader)(THIS) PURE; /*** IWineD3DPixelShader methods ***/ + STDMETHOD(UpdateSamplers)(THIS) PURE; STDMETHOD(GetDevice)(THIS_ IWineD3DDevice** ppDevice) PURE; STDMETHOD(GetFunction)(THIS_ VOID* pData, UINT* pSizeOfData) PURE; }; @@ -1544,8 +1540,8 @@ DECLARE_INTERFACE_(IWineD3DPixelShader,IWineD3DBaseShader) #define IWineD3DPixelShader_GetParent(p,a) (p)->lpVtbl->GetParent(p,a) /*** IWineD3DBaseShader methods ***/ #define IWineD3DPixelShader_SetFunction(p,a) (p)->lpVtbl->SetFunction(p,a) -#define IWineD3DPixelShader_CompileShader(p) (p)->lpVtbl->CompileShader(p) /*** IWineD3DPixelShader methods ***/ +#define IWineD3DPixelShader_UpdateSamplers(p) (p)->lpVtbl->UpdateSamplers(p) #define IWineD3DPixelShader_GetDevice(p,a) (p)->lpVtbl->GetDevice(p,a) #define IWineD3DPixelShader_GetFunction(p,a,b) (p)->lpVtbl->GetFunction(p,a,b) #endif