@@ -32,6 +32,35 @@ static EDiagnosticDebugType ms_DiagnosticDebug = EDiagnosticDebug::NONE;
3232// To reuse shader setups between calls to DrawIndexedPrimitive
3333CShaderItem* g_pActiveShader = NULL ;
3434
35+ namespace
36+ {
37+ struct SResolvedShaderState
38+ {
39+ CShaderInstance* pInstance = nullptr ;
40+ CEffectWrap* pEffectWrap = nullptr ;
41+ ID3DXEffect* pEffect = nullptr ;
42+ };
43+
44+ bool TryResolveShaderState (CShaderItem* pShaderItem, SResolvedShaderState& outState)
45+ {
46+ if (!pShaderItem)
47+ return false ;
48+
49+ CShaderInstance* pInstance = pShaderItem->m_pShaderInstance ;
50+ if (!pInstance)
51+ return false ;
52+
53+ CEffectWrap* pEffectWrap = pInstance->m_pEffectWrap ;
54+ if (!pEffectWrap)
55+ return false ;
56+
57+ outState.pInstance = pInstance;
58+ outState.pEffectWrap = pEffectWrap;
59+ outState.pEffect = pEffectWrap->m_pD3DEffect ;
60+ return true ;
61+ }
62+ }
63+
3564bool CDirect3DEvents9::IsDeviceOperational (IDirect3DDevice9* pDevice, bool * pbTemporarilyLost, HRESULT* pHrCooperativeLevel)
3665{
3766 if (pHrCooperativeLevel)
@@ -375,31 +404,37 @@ HRESULT CDirect3DEvents9::DrawPrimitiveShader(IDirect3DDevice9* pDevice, D3DPRIM
375404 else
376405 {
377406 // Yes shader for this texture
378- CShaderInstance* pShaderInstance = pShaderItem->m_pShaderInstance ;
407+ SResolvedShaderState shaderState;
408+ if (!TryResolveShaderState (pShaderItem, shaderState) || !shaderState.pEffect )
409+ {
410+ if (!bIsLayer)
411+ return DrawPrimitiveGuarded (pDevice, PrimitiveType, StartVertex, PrimitiveCount);
412+ return D3D_OK;
413+ }
414+
415+ CShaderInstance* pShaderInstance = shaderState.pInstance ;
416+ CEffectWrap* pEffectWrap = shaderState.pEffectWrap ;
417+ ID3DXEffect* pD3DEffect = shaderState.pEffect ;
379418
380419 // Apply custom parameters
381420 pShaderInstance->ApplyShaderParameters ();
382421 // Apply common parameters
383- pShaderInstance-> m_pEffectWrap ->ApplyCommonHandles ();
422+ pEffectWrap ->ApplyCommonHandles ();
384423 // Apply mapped parameters
385- pShaderInstance-> m_pEffectWrap ->ApplyMappedHandles ();
424+ pEffectWrap ->ApplyMappedHandles ();
386425
387426 // Remember vertex shader if original draw was using it
388427 IDirect3DVertexShader9* pOriginalVertexShader = NULL ;
389428 pDevice->GetVertexShader (&pOriginalVertexShader);
390429
391430 // Do shader passes
392- ID3DXEffect* pD3DEffect = pShaderInstance-> m_pEffectWrap -> m_pD3DEffect ;
393- bool bEffectDeviceTemporarilyLost = false ;
394- bool bEffectDeviceOperational = true ;
395- if (pD3DEffect)
431+ bool bEffectDeviceTemporarilyLost = false ;
432+ bool bEffectDeviceOperational = true ;
433+ IDirect3DDevice9* pEffectDevice = nullptr ;
434+ if (SUCCEEDED ( pD3DEffect-> GetDevice (&pEffectDevice)) && pEffectDevice )
396435 {
397- IDirect3DDevice9* pEffectDevice = nullptr ;
398- if (SUCCEEDED (pD3DEffect->GetDevice (&pEffectDevice)) && pEffectDevice)
399- {
400- bEffectDeviceOperational = IsDeviceOperational (pEffectDevice, &bEffectDeviceTemporarilyLost);
401- SAFE_RELEASE (pEffectDevice);
402- }
436+ bEffectDeviceOperational = IsDeviceOperational (pEffectDevice, &bEffectDeviceTemporarilyLost);
437+ SAFE_RELEASE (pEffectDevice);
403438 }
404439
405440 if (!bEffectDeviceOperational)
@@ -412,7 +447,7 @@ HRESULT CDirect3DEvents9::DrawPrimitiveShader(IDirect3DDevice9* pDevice, D3DPRIM
412447
413448 DWORD dwFlags = D3DXFX_DONOTSAVESHADERSTATE; // D3DXFX_DONOTSAVE(SHADER|SAMPLER)STATE
414449 uint uiNumPasses = 0 ;
415- HRESULT hrBegin = pShaderInstance-> m_pEffectWrap ->Begin (&uiNumPasses, dwFlags);
450+ HRESULT hrBegin = pEffectWrap ->Begin (&uiNumPasses, dwFlags);
416451 if (FAILED (hrBegin) || uiNumPasses == 0 )
417452 {
418453 if (FAILED (hrBegin) && hrBegin != D3DERR_DEVICELOST && hrBegin != D3DERR_DEVICENOTRESET)
@@ -460,7 +495,7 @@ HRESULT CDirect3DEvents9::DrawPrimitiveShader(IDirect3DDevice9* pDevice, D3DPRIM
460495 bCompletedAnyPass = true ;
461496 }
462497
463- HRESULT hrEnd = pShaderInstance-> m_pEffectWrap ->End (bEffectDeviceOperational && !bEncounteredDeviceLoss);
498+ HRESULT hrEnd = pEffectWrap ->End (bEffectDeviceOperational && !bEncounteredDeviceLoss);
464499 if (FAILED (hrEnd) && hrEnd != D3DERR_DEVICELOST && hrEnd != D3DERR_DEVICENOTRESET)
465500 WriteDebugEvent (SString (" DrawPrimitiveShader: End failed %08x" , hrEnd));
466501
@@ -601,23 +636,30 @@ HRESULT CDirect3DEvents9::DrawIndexedPrimitiveShader(IDirect3DDevice9* pDevice,
601636 // See if we should use the previously setup shader
602637 if (g_pActiveShader)
603638 {
639+ SResolvedShaderState activeState;
640+ if (!TryResolveShaderState (g_pActiveShader, activeState) || !activeState.pEffect )
641+ {
642+ CloseActiveShader (false );
643+ if (!bIsLayer)
644+ return DrawIndexedPrimitiveGuarded (pDevice, PrimitiveType, BaseVertexIndex, MinVertexIndex, NumVertices, startIndex, primCount);
645+ return D3D_OK;
646+ }
647+
604648 dassert (pShaderItem == g_pActiveShader);
605649 g_pDeviceState->FrameStats .iNumShadersReuseSetup ++;
606650
607651 // Transfer any state changes to the active shader, but ensure the device still accepts work
608- CShaderInstance* pShaderInstance = g_pActiveShader->m_pShaderInstance ;
609- ID3DXEffect* pActiveEffect = pShaderInstance->m_pEffectWrap ->m_pD3DEffect ;
652+ CShaderInstance* pShaderInstance = activeState.pInstance ;
653+ CEffectWrap* pActiveEffectWrap = activeState.pEffectWrap ;
654+ ID3DXEffect* pActiveEffect = activeState.pEffect ;
610655
611656 bool bDeviceTemporarilyLost = false ;
612657 bool bDeviceOperational = true ;
613- if (pActiveEffect)
658+ IDirect3DDevice9* pEffectDevice = nullptr ;
659+ if (SUCCEEDED (pActiveEffect->GetDevice (&pEffectDevice)) && pEffectDevice)
614660 {
615- IDirect3DDevice9* pEffectDevice = nullptr ;
616- if (SUCCEEDED (pActiveEffect->GetDevice (&pEffectDevice)) && pEffectDevice)
617- {
618- bDeviceOperational = IsDeviceOperational (pEffectDevice, &bDeviceTemporarilyLost);
619- SAFE_RELEASE (pEffectDevice);
620- }
661+ bDeviceOperational = IsDeviceOperational (pEffectDevice, &bDeviceTemporarilyLost);
662+ SAFE_RELEASE (pEffectDevice);
621663 }
622664
623665 if (!bDeviceOperational)
@@ -626,11 +668,11 @@ HRESULT CDirect3DEvents9::DrawIndexedPrimitiveShader(IDirect3DDevice9* pDevice,
626668 return D3D_OK;
627669 }
628670
629- bool bChanged = pShaderInstance-> m_pEffectWrap ->ApplyCommonHandles ();
630- bChanged |= pShaderInstance-> m_pEffectWrap ->ApplyMappedHandles ();
671+ bool bChanged = pActiveEffectWrap ->ApplyCommonHandles ();
672+ bChanged |= pActiveEffectWrap ->ApplyMappedHandles ();
631673 if (bChanged)
632674 {
633- HRESULT hrCommit = pShaderInstance-> m_pEffectWrap -> m_pD3DEffect ->CommitChanges ();
675+ HRESULT hrCommit = pActiveEffect ->CommitChanges ();
634676 if (FAILED (hrCommit))
635677 {
636678 if (hrCommit != D3DERR_DEVICELOST && hrCommit != D3DERR_DEVICENOTRESET)
@@ -645,11 +687,21 @@ HRESULT CDirect3DEvents9::DrawIndexedPrimitiveShader(IDirect3DDevice9* pDevice,
645687 g_pDeviceState->FrameStats .iNumShadersFullSetup ++;
646688
647689 // Yes shader for this texture
648- CShaderInstance* pShaderInstance = pShaderItem->m_pShaderInstance ;
690+ SResolvedShaderState shaderState;
691+ if (!TryResolveShaderState (pShaderItem, shaderState) || !shaderState.pEffect )
692+ {
693+ if (!bIsLayer)
694+ return DrawIndexedPrimitiveGuarded (pDevice, PrimitiveType, BaseVertexIndex, MinVertexIndex, NumVertices, startIndex, primCount);
695+ return D3D_OK;
696+ }
697+
698+ CShaderInstance* pShaderInstance = shaderState.pInstance ;
699+ CEffectWrap* pEffectWrap = shaderState.pEffectWrap ;
700+ ID3DXEffect* pD3DEffect = shaderState.pEffect ;
649701
650702 // Add normal stream if shader wants it
651703 CAdditionalVertexStreamManager* pAdditionalStreamManager = CAdditionalVertexStreamManager::GetExistingSingleton ();
652- if (pShaderInstance-> m_pEffectWrap ->m_pEffectTemplate ->m_bRequiresNormals && pAdditionalStreamManager)
704+ if (pEffectWrap ->m_pEffectTemplate ->m_bRequiresNormals && pAdditionalStreamManager)
653705 {
654706 // Find/create/set additional vertex stream
655707 pAdditionalStreamManager->MaybeSetAdditionalVertexStream (PrimitiveType, BaseVertexIndex, MinVertexIndex, NumVertices, startIndex, primCount);
@@ -658,26 +710,22 @@ HRESULT CDirect3DEvents9::DrawIndexedPrimitiveShader(IDirect3DDevice9* pDevice,
658710 // Apply custom parameters
659711 pShaderInstance->ApplyShaderParameters ();
660712 // Apply common parameters
661- pShaderInstance-> m_pEffectWrap ->ApplyCommonHandles ();
713+ pEffectWrap ->ApplyCommonHandles ();
662714 // Apply mapped parameters
663- pShaderInstance-> m_pEffectWrap ->ApplyMappedHandles ();
715+ pEffectWrap ->ApplyMappedHandles ();
664716
665717 // Remember vertex shader if original draw was using it
666718 IDirect3DVertexShader9* pOriginalVertexShader = NULL ;
667719 pDevice->GetVertexShader (&pOriginalVertexShader);
668720
669721 // Do shader passes
670- ID3DXEffect* pD3DEffect = pShaderInstance-> m_pEffectWrap -> m_pD3DEffect ;
671- bool bEffectDeviceTemporarilyLost = false ;
672- bool bEffectDeviceOperational = true ;
673- if (pD3DEffect)
722+ bool bEffectDeviceTemporarilyLost = false ;
723+ bool bEffectDeviceOperational = true ;
724+ IDirect3DDevice9* pEffectDevice = nullptr ;
725+ if (SUCCEEDED ( pD3DEffect-> GetDevice (&pEffectDevice)) && pEffectDevice )
674726 {
675- IDirect3DDevice9* pEffectDevice = nullptr ;
676- if (SUCCEEDED (pD3DEffect->GetDevice (&pEffectDevice)) && pEffectDevice)
677- {
678- bEffectDeviceOperational = IsDeviceOperational (pEffectDevice, &bEffectDeviceTemporarilyLost);
679- SAFE_RELEASE (pEffectDevice);
680- }
727+ bEffectDeviceOperational = IsDeviceOperational (pEffectDevice, &bEffectDeviceTemporarilyLost);
728+ SAFE_RELEASE (pEffectDevice);
681729 }
682730
683731 if (!bEffectDeviceOperational)
@@ -692,7 +740,7 @@ HRESULT CDirect3DEvents9::DrawIndexedPrimitiveShader(IDirect3DDevice9* pDevice,
692740
693741 DWORD dwFlags = D3DXFX_DONOTSAVESHADERSTATE; // D3DXFX_DONOTSAVE(SHADER|SAMPLER)STATE
694742 uint uiNumPasses = 0 ;
695- HRESULT hrBegin = pShaderInstance-> m_pEffectWrap ->Begin (&uiNumPasses, dwFlags);
743+ HRESULT hrBegin = pEffectWrap ->Begin (&uiNumPasses, dwFlags);
696744 if (FAILED (hrBegin) || uiNumPasses == 0 )
697745 {
698746 if (FAILED (hrBegin) && hrBegin != D3DERR_DEVICELOST && hrBegin != D3DERR_DEVICENOTRESET)
@@ -733,6 +781,7 @@ HRESULT CDirect3DEvents9::DrawIndexedPrimitiveShader(IDirect3DDevice9* pDevice,
733781 {
734782 // Make this the active shader for possible reuse
735783 dassert (dwFlags == D3DXFX_DONOTSAVESHADERSTATE);
784+ pShaderItem->AddRef ();
736785 g_pActiveShader = pShaderItem;
737786 SAFE_RELEASE (pOriginalVertexShader);
738787 return D3D_OK;
@@ -752,7 +801,7 @@ HRESULT CDirect3DEvents9::DrawIndexedPrimitiveShader(IDirect3DDevice9* pDevice,
752801 bCompletedAnyPass = true ;
753802 }
754803
755- HRESULT hrEnd = pShaderInstance-> m_pEffectWrap ->End (bEffectDeviceOperational && !bEncounteredDeviceLoss);
804+ HRESULT hrEnd = pEffectWrap ->End (bEffectDeviceOperational && !bEncounteredDeviceLoss);
756805 if (FAILED (hrEnd) && hrEnd != D3DERR_DEVICELOST && hrEnd != D3DERR_DEVICENOTRESET)
757806 WriteDebugEvent (SString (" DrawIndexedPrimitiveShader: End failed %08x" , hrEnd));
758807
@@ -785,10 +834,15 @@ HRESULT CDirect3DEvents9::DrawIndexedPrimitiveShader(IDirect3DDevice9* pDevice,
785834// ///////////////////////////////////////////////////////////
786835void CDirect3DEvents9::CloseActiveShader (bool bDeviceOperational)
787836{
788- if (!g_pActiveShader)
837+ CShaderItem* pShaderItem = g_pActiveShader;
838+ g_pActiveShader = nullptr ;
839+ if (!pShaderItem)
789840 return ;
790841
791- ID3DXEffect* pD3DEffect = g_pActiveShader->m_pShaderInstance ->m_pEffectWrap ->m_pD3DEffect ;
842+ SResolvedShaderState shaderState;
843+ bool bHasShaderState = TryResolveShaderState (pShaderItem, shaderState);
844+
845+ ID3DXEffect* pD3DEffect = bHasShaderState ? shaderState.pEffect : nullptr ;
792846 IDirect3DDevice9* pDevice = g_pGraphics ? g_pGraphics->GetDevice () : nullptr ;
793847
794848 bool bAllowDeviceWork = bDeviceOperational;
@@ -807,8 +861,8 @@ void CDirect3DEvents9::CloseActiveShader(bool bDeviceOperational)
807861 }
808862
809863 // When the device is lost we intentionally skip touching the GPU beyond the required End call; the effect will be reset later.
810- g_pActiveShader-> m_pShaderInstance -> m_pEffectWrap -> End (bAllowDeviceWork);
811- g_pActiveShader = nullptr ;
864+ if (bHasShaderState)
865+ shaderState. pEffectWrap -> End (bAllowDeviceWork) ;
812866
813867 if (CAdditionalVertexStreamManager* pAdditionalStreamManager = CAdditionalVertexStreamManager::GetExistingSingleton ())
814868 pAdditionalStreamManager->MaybeUnsetAdditionalVertexStream ();
@@ -819,6 +873,8 @@ void CDirect3DEvents9::CloseActiveShader(bool bDeviceOperational)
819873 pDevice->SetVertexShader (nullptr );
820874 pDevice->SetPixelShader (nullptr );
821875 }
876+
877+ pShaderItem->Release ();
822878}
823879
824880// ///////////////////////////////////////////////////////////
@@ -1923,7 +1979,10 @@ IDirect3DVertexBuffer9* CDirect3DEvents9::GetRealVertexBuffer(IDirect3DVertexBuf
19231979
19241980 // If so, use the original vertex buffer
19251981 if (pProxy)
1982+ {
19261983 pStreamData = pProxy->GetOriginal ();
1984+ SAFE_RELEASE (pProxy);
1985+ }
19271986 }
19281987
19291988 return pStreamData;
@@ -1946,7 +2005,10 @@ IDirect3DIndexBuffer9* CDirect3DEvents9::GetRealIndexBuffer(IDirect3DIndexBuffer
19462005
19472006 // If so, use the original index buffer
19482007 if (pProxy)
2008+ {
19492009 pIndexData = pProxy->GetOriginal ();
2010+ SAFE_RELEASE (pProxy);
2011+ }
19502012 }
19512013 return pIndexData;
19522014}
@@ -1968,7 +2030,10 @@ IDirect3DBaseTexture9* CDirect3DEvents9::GetRealTexture(IDirect3DBaseTexture9* p
19682030
19692031 // If so, use the original texture
19702032 if (pProxy)
2033+ {
19712034 pTexture = pProxy->GetOriginal ();
2035+ SAFE_RELEASE (pProxy);
2036+ }
19722037 }
19732038 return pTexture;
19742039}
@@ -2034,6 +2099,8 @@ HRESULT CDirect3DEvents9::SetVertexDeclaration(IDirect3DDevice9* pDevice, IDirec
20342099 CProxyDirect3DDevice9::SD3DVertexDeclState* pInfo = MapFind (g_pProxyDevice->m_VertexDeclMap , pProxy);
20352100 if (pInfo)
20362101 g_pDeviceState->VertexDeclState = *pInfo;
2102+
2103+ SAFE_RELEASE (pProxy);
20372104 }
20382105 }
20392106
@@ -2052,26 +2119,33 @@ ERenderFormat CDirect3DEvents9::DiscoverReadableDepthFormat(IDirect3DDevice9* pD
20522119 IDirect3D9* pD3D = NULL ;
20532120 pDevice->GetDirect3D (&pD3D);
20542121
2055- // Formats to check for
2056- ERenderFormat checkList[] = {RFORMAT_INTZ, RFORMAT_DF24, RFORMAT_DF16, RFORMAT_RAWZ};
2122+ ERenderFormat discoveredFormat = RFORMAT_UNKNOWN;
20572123
2058- D3DDISPLAYMODE displayMode;
2059- if (pD3D->GetAdapterDisplayMode (D3DADAPTER_DEFAULT, &displayMode) == D3D_OK)
2124+ if (pD3D)
20602125 {
2061- for (uint i = 0 ; i < NUMELMS (checkList); i++)
2126+ // Formats to check for
2127+ ERenderFormat checkList[] = {RFORMAT_INTZ, RFORMAT_DF24, RFORMAT_DF16, RFORMAT_RAWZ};
2128+
2129+ D3DDISPLAYMODE displayMode;
2130+ if (pD3D->GetAdapterDisplayMode (D3DADAPTER_DEFAULT, &displayMode) == D3D_OK)
20622131 {
2063- D3DFORMAT DepthFormat = (D3DFORMAT)checkList[i];
2132+ for (uint i = 0 ; i < NUMELMS (checkList); i++)
2133+ {
2134+ D3DFORMAT DepthFormat = (D3DFORMAT)checkList[i];
20642135
2065- // Can use this format?
2066- if (D3D_OK != pD3D->CheckDeviceFormat (D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, displayMode.Format , D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, DepthFormat))
2067- continue ;
2136+ // Can use this format?
2137+ if (D3D_OK != pD3D->CheckDeviceFormat (D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, displayMode.Format , D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, DepthFormat))
2138+ continue ;
20682139
2069- // Don't check for compatibility with multisampling, as we turn AA off when using readable depth buffer
2140+ // Don't check for compatibility with multisampling, as we turn AA off when using readable depth buffer
20702141
2071- // Found a working format
2072- return checkList[i];
2142+ // Found a working format
2143+ discoveredFormat = checkList[i];
2144+ break ;
2145+ }
20732146 }
20742147 }
20752148
2076- return RFORMAT_UNKNOWN;
2149+ SAFE_RELEASE (pD3D);
2150+ return discoveredFormat;
20772151}
0 commit comments