From 107e80a79cc4a112a471683a0ff1b670e0264755 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20D=C3=B6singer?= Date: Tue, 4 Mar 2008 02:30:23 +0100 Subject: [PATCH] wined3d: Implement a different constant dirtification algorithm. Add a new property of the shader backend which indicates whether the shader backend is able to dirtify single constants rather than dirtifying vshader and pshader constants as a whole. Depending on this a different Set*ConstantF implementation is used which marks constants dirty. The ARB shader backend uses this and marks constants clean after uploading. --- dlls/wined3d/arb_program_shader.c | 99 +++++++------- dlls/wined3d/baseshader.c | 4 +- dlls/wined3d/context.c | 21 +++ dlls/wined3d/device.c | 217 ++++++++++++++++++++++++++++++ dlls/wined3d/directx.c | 8 ++ dlls/wined3d/glsl_shader.c | 8 +- dlls/wined3d/wined3d_private.h | 6 +- 7 files changed, 314 insertions(+), 49 deletions(-) diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index ae849b21109..0d717a42ba7 100644 --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -48,60 +48,51 @@ WINE_DECLARE_DEBUG_CHANNEL(d3d_constants); * @target_type should be either GL_VERTEX_PROGRAM_ARB (for vertex shaders) * or GL_FRAGMENT_PROGRAM_ARB (for pixel shaders) */ -static void shader_arb_load_constantsF(IWineD3DBaseShaderImpl* This, WineD3D_GL_Info *gl_info, GLuint target_type, - unsigned int max_constants, float* constants, struct list *constant_list) { - constants_entry *constant; +static unsigned int shader_arb_load_constantsF(IWineD3DBaseShaderImpl* This, WineD3D_GL_Info *gl_info, GLuint target_type, + unsigned int max_constants, float* constants, char *dirty_consts) { local_constant* lconst; - DWORD i, j, k; - DWORD *idx; + DWORD i, j; + unsigned int ret; if (TRACE_ON(d3d_shader)) { - LIST_FOR_EACH_ENTRY(constant, constant_list, constants_entry, entry) { - idx = constant->idx; - j = constant->count; - while (j--) { - i = *idx++; - TRACE_(d3d_constants)("Loading constants %i: %f, %f, %f, %f\n", i, + for(i = 0; i < max_constants; i++) { + if(!dirty_consts[i]) continue; + TRACE_(d3d_constants)("Loading constants %i: %f, %f, %f, %f\n", i, constants[i * 4 + 0], constants[i * 4 + 1], constants[i * 4 + 2], constants[i * 4 + 3]); - } } } /* In 1.X pixel shaders constants are implicitly clamped in the range [-1;1] */ if(target_type == GL_FRAGMENT_PROGRAM_ARB && WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) == 1) { float lcl_const[4]; - LIST_FOR_EACH_ENTRY(constant, constant_list, constants_entry, entry) { - idx = constant->idx; - j = constant->count; - while (j--) { - i = *idx++; - k = i * 4; - if(constants[k + 0] > 1.0) lcl_const[0] = 1.0; - else if(constants[k + 0] < -1.0) lcl_const[0] = -1.0; - else lcl_const[0] = constants[k + 0]; + for(i = 0; i < max_constants; i++) { + if(!dirty_consts[i]) continue; + dirty_consts[i] = 0; - if(constants[k + 1] > 1.0) lcl_const[1] = 1.0; - else if(constants[k + 1] < -1.0) lcl_const[1] = -1.0; - else lcl_const[1] = constants[k + 1]; + j = 4 * i; + if(constants[j + 0] > 1.0) lcl_const[0] = 1.0; + else if(constants[j + 0] < -1.0) lcl_const[0] = -1.0; + else lcl_const[0] = constants[j + 0]; - if(constants[k + 2] > 1.0) lcl_const[2] = 1.0; - else if(constants[k + 2] < -1.0) lcl_const[2] = -1.0; - else lcl_const[2] = constants[k + 2]; + if(constants[j + 1] > 1.0) lcl_const[1] = 1.0; + else if(constants[j + 1] < -1.0) lcl_const[1] = -1.0; + else lcl_const[1] = constants[j + 1]; - if(constants[k + 3] > 1.0) lcl_const[3] = 1.0; - else if(constants[k + 3] < -1.0) lcl_const[3] = -1.0; - else lcl_const[3] = constants[k + 3]; + if(constants[j + 2] > 1.0) lcl_const[2] = 1.0; + else if(constants[j + 2] < -1.0) lcl_const[2] = -1.0; + else lcl_const[2] = constants[j + 2]; - GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, i, lcl_const)); - } + if(constants[j + 3] > 1.0) lcl_const[3] = 1.0; + else if(constants[j + 3] < -1.0) lcl_const[3] = -1.0; + else lcl_const[3] = constants[j + 3]; + + GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, i, lcl_const)); } } else { - LIST_FOR_EACH_ENTRY(constant, constant_list, constants_entry, entry) { - idx = constant->idx; - j = constant->count; - while (j--) { - i = *idx++; + for(i = 0; i < max_constants; i++) { + if(dirty_consts[i]) { + dirty_consts[i] = 0; GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, i, constants + (i * 4))); } } @@ -117,10 +108,14 @@ static void shader_arb_load_constantsF(IWineD3DBaseShaderImpl* This, WineD3D_GL_ } } /* Immediate constants are clamped for 1.X shaders at loading times */ + ret = 0; LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) { + dirty_consts[lconst->idx] = 1; /* Dirtify so the non-immediate constant overwrites it next time */ + ret = max(ret, lconst->idx); GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, lconst->idx, (GLfloat*)lconst->value)); } checkGLcall("glProgramEnvParameter4fvARB()"); + return ret; } /** @@ -142,10 +137,11 @@ void shader_arb_load_constants( IWineD3DBaseShaderImpl* vshader = (IWineD3DBaseShaderImpl*) stateBlock->vertexShader; /* Load DirectX 9 float constants for vertex shader */ - shader_arb_load_constantsF(vshader, gl_info, GL_VERTEX_PROGRAM_ARB, - GL_LIMITS(vshader_constantsF), - stateBlock->vertexShaderConstantF, - &stateBlock->set_vconstantsF); + deviceImpl->highest_dirty_vs_const = shader_arb_load_constantsF( + vshader, gl_info, GL_VERTEX_PROGRAM_ARB, + deviceImpl->highest_dirty_vs_const, + stateBlock->vertexShaderConstantF, + deviceImpl->activeContext->vshader_const_dirty); /* Upload the position fixup */ GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, ARB_SHADER_PRIVCONST_POS, deviceImpl->posFixup)); @@ -157,10 +153,12 @@ void shader_arb_load_constants( IWineD3DPixelShaderImpl *psi = (IWineD3DPixelShaderImpl *) pshader; /* Load DirectX 9 float constants for pixel shader */ - shader_arb_load_constantsF(pshader, gl_info, GL_FRAGMENT_PROGRAM_ARB, - GL_LIMITS(pshader_constantsF), - stateBlock->pixelShaderConstantF, - &stateBlock->set_pconstantsF); + deviceImpl->highest_dirty_ps_const = shader_arb_load_constantsF( + pshader, gl_info, GL_FRAGMENT_PROGRAM_ARB, + deviceImpl->highest_dirty_ps_const, + stateBlock->pixelShaderConstantF, + deviceImpl->activeContext->pshader_const_dirty); + if(((IWineD3DPixelShaderImpl *) pshader)->bumpenvmatconst != -1) { /* needsbumpmat stores the stage number from where to load the matrix. bumpenvmatconst stores the * number of the constant to load the matrix into. @@ -177,6 +175,7 @@ void shader_arb_load_constants( */ float *scale = (float *) &stateBlock->textureState[(int) psi->needsbumpmat][WINED3DTSS_BUMPENVLSCALE]; GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, psi->luminanceconst, scale)); + deviceImpl->activeContext->pshader_const_dirty[psi->luminanceconst] = 1; } } if(((IWineD3DPixelShaderImpl *) pshader)->srgb_enabled && @@ -200,6 +199,9 @@ void shader_arb_load_constants( GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, psi->srgb_cmp_const, comparison)); GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, psi->srgb_low_const, mul_low)); checkGLcall("Load sRGB correction constants\n"); + deviceImpl->activeContext->pshader_const_dirty[psi->srgb_low_const] = 1; + deviceImpl->activeContext->pshader_const_dirty[psi->srgb_cmp_const] = 1; + } } } @@ -1769,6 +1771,10 @@ static void shader_arb_free(IWineD3DDevice *iface) { HeapFree(GetProcessHeap(), 0, This->shader_priv); } +static BOOL shader_arb_dirty_const(IWineD3DDevice *iface) { + return TRUE; +} + const shader_backend_t arb_program_shader_backend = { &shader_arb_select, &shader_arb_select_depth_blt, @@ -1778,6 +1784,7 @@ const shader_backend_t arb_program_shader_backend = { &shader_arb_color_correction, &shader_arb_destroy, &shader_arb_alloc, - &shader_arb_free + &shader_arb_free, + &shader_arb_dirty_const }; diff --git a/dlls/wined3d/baseshader.c b/dlls/wined3d/baseshader.c index ed292ce329f..7513cff352b 100644 --- a/dlls/wined3d/baseshader.c +++ b/dlls/wined3d/baseshader.c @@ -1104,6 +1104,7 @@ static void shader_none_color_correction(SHADER_OPCODE_ARG* arg) {} static void shader_none_destroy(IWineD3DBaseShader *iface) {} static HRESULT shader_none_alloc(IWineD3DDevice *iface) {return WINED3D_OK;} static void shader_none_free(IWineD3DDevice *iface) {} +static BOOL shader_none_dirty_const(IWineD3DDevice *iface) {return FALSE;} const shader_backend_t none_shader_backend = { &shader_none_select, @@ -1114,7 +1115,8 @@ const shader_backend_t none_shader_backend = { &shader_none_color_correction, &shader_none_destroy, &shader_none_alloc, - &shader_none_free + &shader_none_free, + &shader_none_dirty_const }; /* ******************************************* diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c index cc9574bddce..4362b6c62c9 100644 --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c @@ -326,6 +326,17 @@ WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *tar ret->surface = (IWineD3DSurface *) target; ret->isPBuffer = create_pbuffer; ret->tid = GetCurrentThreadId(); + if(This->shader_backend->shader_dirtifyable_constants((IWineD3DDevice *) This)) { + /* Create the dirty constants array and initialize them to dirty */ + ret->vshader_const_dirty = HeapAlloc(GetProcessHeap(), 0, + sizeof(*ret->vshader_const_dirty) * GL_LIMITS(vshader_constantsF)); + ret->pshader_const_dirty = HeapAlloc(GetProcessHeap(), 0, + sizeof(*ret->pshader_const_dirty) * GL_LIMITS(pshader_constantsF)); + memset(ret->vshader_const_dirty, 1, + sizeof(*ret->vshader_const_dirty) * GL_LIMITS(vshader_constantsF)); + memset(ret->pshader_const_dirty, 1, + sizeof(*ret->pshader_const_dirty) * GL_LIMITS(pshader_constantsF)); + } TRACE("Successfully created new context %p\n", ret); @@ -478,6 +489,8 @@ void DestroyContext(IWineD3DDeviceImpl *This, WineD3DContext *context) { } else ReleaseDC(context->win_handle, context->hdc); pwglDeleteContext(context->glCtx); + HeapFree(GetProcessHeap(), 0, context->vshader_const_dirty); + HeapFree(GetProcessHeap(), 0, context->pshader_const_dirty); RemoveContextFromArray(This, context); } @@ -900,6 +913,14 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU ERR("Failed to activate the new context\n"); } } + if(This->activeContext->vshader_const_dirty) { + memset(This->activeContext->vshader_const_dirty, 1, + sizeof(This->activeContext->vshader_const_dirty) * GL_LIMITS(vshader_constantsF)); + } + if(This->activeContext->pshader_const_dirty) { + memset(This->activeContext->pshader_const_dirty, 1, + sizeof(This->activeContext->pshader_const_dirty) * GL_LIMITS(pshader_constantsF)); + } This->activeContext = context; } diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 1d7afaa5cc9..3f2d57ebb43 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -2116,6 +2116,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPR if(wined3d_settings.logo) { IWineD3DDeviceImpl_LoadLogo(This, wined3d_settings.logo); } + This->highest_dirty_ps_const = 0; + This->highest_dirty_vs_const = 0; return WINED3D_OK; err_out: @@ -3450,6 +3452,41 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF( return WINED3D_OK; } +static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF_DirtyConst( +IWineD3DDevice *iface, +UINT start, +CONST float *srcData, +UINT count) { + + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + int i; + + TRACE("(iface %p, srcData %p, start %d, count %d)\n", + iface, srcData, start, count); + + /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */ + if (srcData == NULL || start + count > GL_LIMITS(vshader_constantsF) || start > GL_LIMITS(vshader_constantsF)) + return WINED3DERR_INVALIDCALL; + + memcpy(&This->updateStateBlock->vertexShaderConstantF[start * 4], srcData, count * sizeof(float) * 4); + if(TRACE_ON(d3d)) { + for (i = 0; i < count; i++) + TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i, + srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]); + } + + /* We don't want shader constant dirtification to be an O(contexts), so just dirtify the active + * context. On a context switch the old context will be fully dirtified + */ + memset(This->activeContext->vshader_const_dirty + start, 1, + sizeof(*This->activeContext->vshader_const_dirty) * count); + This->highest_dirty_vs_const = max(This->highest_dirty_vs_const, start+count); + + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT); + + return WINED3D_OK; +} + static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF( IWineD3DDevice *iface, UINT start, @@ -3843,6 +3880,41 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF( return WINED3D_OK; } +static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF_DirtyConst( + IWineD3DDevice *iface, + UINT start, + CONST float *srcData, + UINT count) { + + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + int i; + + TRACE("(iface %p, srcData %p, start %d, count %d)\n", + iface, srcData, start, count); + + /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */ + if (srcData == NULL || start + count > GL_LIMITS(pshader_constantsF) || start > GL_LIMITS(pshader_constantsF)) + return WINED3DERR_INVALIDCALL; + + memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, count * sizeof(float) * 4); + if(TRACE_ON(d3d)) { + for (i = 0; i < count; i++) + TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i, + srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]); + } + + /* We don't want shader constant dirtification to be an O(contexts), so just dirtify the active + * context. On a context switch the old context will be fully dirtified + */ + memset(This->activeContext->pshader_const_dirty + start, 1, + sizeof(*This->activeContext->pshader_const_dirty) * count); + This->highest_dirty_ps_const = max(This->highest_dirty_ps_const, start+count); + + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT); + + return WINED3D_OK; +} + static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF( IWineD3DDevice *iface, UINT start, @@ -7423,6 +7495,151 @@ const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl = IWineD3DDeviceImpl_EnumResources }; +const IWineD3DDeviceVtbl IWineD3DDevice_DirtyConst_Vtbl = +{ + /*** IUnknown methods ***/ + IWineD3DDeviceImpl_QueryInterface, + IWineD3DDeviceImpl_AddRef, + IWineD3DDeviceImpl_Release, + /*** IWineD3DDevice methods ***/ + IWineD3DDeviceImpl_GetParent, + /*** Creation methods**/ + IWineD3DDeviceImpl_CreateVertexBuffer, + IWineD3DDeviceImpl_CreateIndexBuffer, + IWineD3DDeviceImpl_CreateStateBlock, + IWineD3DDeviceImpl_CreateSurface, + IWineD3DDeviceImpl_CreateTexture, + IWineD3DDeviceImpl_CreateVolumeTexture, + IWineD3DDeviceImpl_CreateVolume, + IWineD3DDeviceImpl_CreateCubeTexture, + IWineD3DDeviceImpl_CreateQuery, + IWineD3DDeviceImpl_CreateAdditionalSwapChain, + IWineD3DDeviceImpl_CreateVertexDeclaration, + IWineD3DDeviceImpl_CreateVertexDeclarationFromFVF, + IWineD3DDeviceImpl_CreateVertexShader, + IWineD3DDeviceImpl_CreatePixelShader, + IWineD3DDeviceImpl_CreatePalette, + /*** Odd functions **/ + IWineD3DDeviceImpl_Init3D, + IWineD3DDeviceImpl_Uninit3D, + IWineD3DDeviceImpl_SetFullscreen, + IWineD3DDeviceImpl_SetMultithreaded, + IWineD3DDeviceImpl_EvictManagedResources, + IWineD3DDeviceImpl_GetAvailableTextureMem, + IWineD3DDeviceImpl_GetBackBuffer, + IWineD3DDeviceImpl_GetCreationParameters, + IWineD3DDeviceImpl_GetDeviceCaps, + IWineD3DDeviceImpl_GetDirect3D, + IWineD3DDeviceImpl_GetDisplayMode, + IWineD3DDeviceImpl_SetDisplayMode, + IWineD3DDeviceImpl_GetHWND, + IWineD3DDeviceImpl_SetHWND, + IWineD3DDeviceImpl_GetNumberOfSwapChains, + IWineD3DDeviceImpl_GetRasterStatus, + IWineD3DDeviceImpl_GetSwapChain, + IWineD3DDeviceImpl_Reset, + IWineD3DDeviceImpl_SetDialogBoxMode, + IWineD3DDeviceImpl_SetCursorProperties, + IWineD3DDeviceImpl_SetCursorPosition, + IWineD3DDeviceImpl_ShowCursor, + IWineD3DDeviceImpl_TestCooperativeLevel, + /*** Getters and setters **/ + IWineD3DDeviceImpl_SetClipPlane, + IWineD3DDeviceImpl_GetClipPlane, + IWineD3DDeviceImpl_SetClipStatus, + IWineD3DDeviceImpl_GetClipStatus, + IWineD3DDeviceImpl_SetCurrentTexturePalette, + IWineD3DDeviceImpl_GetCurrentTexturePalette, + IWineD3DDeviceImpl_SetDepthStencilSurface, + IWineD3DDeviceImpl_GetDepthStencilSurface, + IWineD3DDeviceImpl_SetFVF, + IWineD3DDeviceImpl_GetFVF, + IWineD3DDeviceImpl_SetGammaRamp, + IWineD3DDeviceImpl_GetGammaRamp, + IWineD3DDeviceImpl_SetIndices, + IWineD3DDeviceImpl_GetIndices, + IWineD3DDeviceImpl_SetBaseVertexIndex, + IWineD3DDeviceImpl_GetBaseVertexIndex, + IWineD3DDeviceImpl_SetLight, + IWineD3DDeviceImpl_GetLight, + IWineD3DDeviceImpl_SetLightEnable, + IWineD3DDeviceImpl_GetLightEnable, + IWineD3DDeviceImpl_SetMaterial, + IWineD3DDeviceImpl_GetMaterial, + IWineD3DDeviceImpl_SetNPatchMode, + IWineD3DDeviceImpl_GetNPatchMode, + IWineD3DDeviceImpl_SetPaletteEntries, + IWineD3DDeviceImpl_GetPaletteEntries, + IWineD3DDeviceImpl_SetPixelShader, + IWineD3DDeviceImpl_GetPixelShader, + IWineD3DDeviceImpl_SetPixelShaderConstantB, + IWineD3DDeviceImpl_GetPixelShaderConstantB, + IWineD3DDeviceImpl_SetPixelShaderConstantI, + IWineD3DDeviceImpl_GetPixelShaderConstantI, + IWineD3DDeviceImpl_SetPixelShaderConstantF_DirtyConst, + IWineD3DDeviceImpl_GetPixelShaderConstantF, + IWineD3DDeviceImpl_SetRenderState, + IWineD3DDeviceImpl_GetRenderState, + IWineD3DDeviceImpl_SetRenderTarget, + IWineD3DDeviceImpl_GetRenderTarget, + IWineD3DDeviceImpl_SetFrontBackBuffers, + IWineD3DDeviceImpl_SetSamplerState, + IWineD3DDeviceImpl_GetSamplerState, + IWineD3DDeviceImpl_SetScissorRect, + IWineD3DDeviceImpl_GetScissorRect, + IWineD3DDeviceImpl_SetSoftwareVertexProcessing, + IWineD3DDeviceImpl_GetSoftwareVertexProcessing, + IWineD3DDeviceImpl_SetStreamSource, + IWineD3DDeviceImpl_GetStreamSource, + IWineD3DDeviceImpl_SetStreamSourceFreq, + IWineD3DDeviceImpl_GetStreamSourceFreq, + IWineD3DDeviceImpl_SetTexture, + IWineD3DDeviceImpl_GetTexture, + IWineD3DDeviceImpl_SetTextureStageState, + IWineD3DDeviceImpl_GetTextureStageState, + IWineD3DDeviceImpl_SetTransform, + IWineD3DDeviceImpl_GetTransform, + IWineD3DDeviceImpl_SetVertexDeclaration, + IWineD3DDeviceImpl_GetVertexDeclaration, + IWineD3DDeviceImpl_SetVertexShader, + IWineD3DDeviceImpl_GetVertexShader, + IWineD3DDeviceImpl_SetVertexShaderConstantB, + IWineD3DDeviceImpl_GetVertexShaderConstantB, + IWineD3DDeviceImpl_SetVertexShaderConstantI, + IWineD3DDeviceImpl_GetVertexShaderConstantI, + IWineD3DDeviceImpl_SetVertexShaderConstantF_DirtyConst, + IWineD3DDeviceImpl_GetVertexShaderConstantF, + IWineD3DDeviceImpl_SetViewport, + IWineD3DDeviceImpl_GetViewport, + IWineD3DDeviceImpl_MultiplyTransform, + IWineD3DDeviceImpl_ValidateDevice, + IWineD3DDeviceImpl_ProcessVertices, + /*** State block ***/ + IWineD3DDeviceImpl_BeginStateBlock, + IWineD3DDeviceImpl_EndStateBlock, + /*** Scene management ***/ + IWineD3DDeviceImpl_BeginScene, + IWineD3DDeviceImpl_EndScene, + IWineD3DDeviceImpl_Present, + IWineD3DDeviceImpl_Clear, + /*** Drawing ***/ + IWineD3DDeviceImpl_DrawPrimitive, + IWineD3DDeviceImpl_DrawIndexedPrimitive, + IWineD3DDeviceImpl_DrawPrimitiveUP, + IWineD3DDeviceImpl_DrawIndexedPrimitiveUP, + IWineD3DDeviceImpl_DrawPrimitiveStrided, + IWineD3DDeviceImpl_DrawIndexedPrimitiveStrided, + IWineD3DDeviceImpl_DrawRectPatch, + IWineD3DDeviceImpl_DrawTriPatch, + IWineD3DDeviceImpl_DeletePatch, + IWineD3DDeviceImpl_ColorFill, + IWineD3DDeviceImpl_UpdateTexture, + IWineD3DDeviceImpl_UpdateSurface, + IWineD3DDeviceImpl_GetFrontBufferData, + /*** object tracking ***/ + IWineD3DDeviceImpl_ResourceReleased, + IWineD3DDeviceImpl_EnumResources +}; const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = { WINED3DRS_ALPHABLENDENABLE , diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index b7c56a6fd2a..f4557ba8b42 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -2876,6 +2876,14 @@ static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, return E_OUTOFMEMORY; } + /* Prefer the vtable with functions optimized for single dirtifyable objects if the shader + * model can deal with that. It is essentially the same, just with adjusted + * Set*ShaderConstantF implementations + */ + if(object->shader_backend->shader_dirtifyable_constants((IWineD3DDevice *) object)) { + object->lpVtbl = &IWineD3DDevice_DirtyConst_Vtbl; + } + /* set the state of the device to valid */ object->state = WINED3D_OK; diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index ae2c9a2db44..68d42453005 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -3326,6 +3326,11 @@ static void shader_glsl_free(IWineD3DDevice *iface) { HeapFree(GetProcessHeap(), 0, This->shader_priv); } +static BOOL shader_glsl_dirty_const(IWineD3DDevice *iface) { + /* TODO: GL_EXT_bindable_uniform can be used to share constants accross shaders */ + return FALSE; +} + const shader_backend_t glsl_shader_backend = { &shader_glsl_select, &shader_glsl_select_depth_blt, @@ -3335,5 +3340,6 @@ const shader_backend_t glsl_shader_backend = { &shader_glsl_color_correction, &shader_glsl_destroy, &shader_glsl_alloc, - &shader_glsl_free + &shader_glsl_free, + &shader_glsl_dirty_const }; diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index f6ac50c63d4..1b44d9f2fd2 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -259,6 +259,7 @@ typedef struct { void (*shader_destroy)(IWineD3DBaseShader *iface); HRESULT (*shader_alloc_private)(IWineD3DDevice *iface); void (*shader_free_private)(IWineD3DDevice *iface); + BOOL (*shader_dirtifyable_constants)(IWineD3DDevice *iface); } shader_backend_t; extern const shader_backend_t glsl_shader_backend; @@ -575,6 +576,8 @@ struct WineD3DContext { char texShaderBumpMap; BOOL fog_coord; + char *vshader_const_dirty, *pshader_const_dirty; + /* The actual opengl context */ HGLRC glCtx; HWND win_handle; @@ -749,6 +752,7 @@ struct IWineD3DDeviceImpl struct list resources; /* a linked list to track resources created by the device */ struct list shaders; /* a linked list to track shaders (pixel and vertex) */ + unsigned int highest_dirty_ps_const, highest_dirty_vs_const; /* Render Target Support */ IWineD3DSurface **render_targets; @@ -842,7 +846,7 @@ struct IWineD3DDeviceImpl struct WineD3DRectPatch *currentPatch; }; -extern const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl; +extern const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl, IWineD3DDevice_DirtyConst_Vtbl; HRESULT IWineD3DDeviceImpl_ClearSurface(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *target, DWORD Count, CONST WINED3DRECT* pRects, DWORD Flags, WINED3DCOLOR Color,