@@ -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)
@@ -377,31 +406,37 @@ HRESULT CDirect3DEvents9::DrawPrimitiveShader(IDirect3DDevice9* pDevice, D3DPRIM
377406 else
378407 {
379408 // Yes shader for this texture
380- CShaderInstance* pShaderInstance = pShaderItem->m_pShaderInstance ;
409+ SResolvedShaderState shaderState;
410+ if (!TryResolveShaderState (pShaderItem, shaderState) || !shaderState.pEffect )
411+ {
412+ if (!bIsLayer)
413+ return DrawPrimitiveGuarded (pDevice, PrimitiveType, StartVertex, PrimitiveCount);
414+ return D3D_OK;
415+ }
416+
417+ CShaderInstance* pShaderInstance = shaderState.pInstance ;
418+ CEffectWrap* pEffectWrap = shaderState.pEffectWrap ;
419+ ID3DXEffect* pD3DEffect = shaderState.pEffect ;
381420
382421 // Apply custom parameters
383422 pShaderInstance->ApplyShaderParameters ();
384423 // Apply common parameters
385- pShaderInstance-> m_pEffectWrap ->ApplyCommonHandles ();
424+ pEffectWrap ->ApplyCommonHandles ();
386425 // Apply mapped parameters
387- pShaderInstance-> m_pEffectWrap ->ApplyMappedHandles ();
426+ pEffectWrap ->ApplyMappedHandles ();
388427
389428 // Remember vertex shader if original draw was using it
390429 IDirect3DVertexShader9* pOriginalVertexShader = NULL ;
391430 pDevice->GetVertexShader (&pOriginalVertexShader);
392431
393432 // Do shader passes
394- ID3DXEffect* pD3DEffect = pShaderInstance-> m_pEffectWrap -> m_pD3DEffect ;
395- bool bEffectDeviceTemporarilyLost = false ;
396- bool bEffectDeviceOperational = true ;
397- if (pD3DEffect)
433+ bool bEffectDeviceTemporarilyLost = false ;
434+ bool bEffectDeviceOperational = true ;
435+ IDirect3DDevice9* pEffectDevice = nullptr ;
436+ if (SUCCEEDED ( pD3DEffect-> GetDevice (&pEffectDevice)) && pEffectDevice )
398437 {
399- IDirect3DDevice9* pEffectDevice = nullptr ;
400- if (SUCCEEDED (pD3DEffect->GetDevice (&pEffectDevice)) && pEffectDevice)
401- {
402- bEffectDeviceOperational = IsDeviceOperational (pEffectDevice, &bEffectDeviceTemporarilyLost);
403- SAFE_RELEASE (pEffectDevice);
404- }
438+ bEffectDeviceOperational = IsDeviceOperational (pEffectDevice, &bEffectDeviceTemporarilyLost);
439+ SAFE_RELEASE (pEffectDevice);
405440 }
406441
407442 if (!bEffectDeviceOperational)
@@ -414,7 +449,7 @@ HRESULT CDirect3DEvents9::DrawPrimitiveShader(IDirect3DDevice9* pDevice, D3DPRIM
414449
415450 DWORD dwFlags = D3DXFX_DONOTSAVESHADERSTATE; // D3DXFX_DONOTSAVE(SHADER|SAMPLER)STATE
416451 uint uiNumPasses = 0 ;
417- HRESULT hrBegin = pShaderInstance-> m_pEffectWrap ->Begin (&uiNumPasses, dwFlags);
452+ HRESULT hrBegin = pEffectWrap ->Begin (&uiNumPasses, dwFlags);
418453 if (FAILED (hrBegin) || uiNumPasses == 0 )
419454 {
420455 if (FAILED (hrBegin) && hrBegin != D3DERR_DEVICELOST && hrBegin != D3DERR_DEVICENOTRESET)
@@ -462,7 +497,7 @@ HRESULT CDirect3DEvents9::DrawPrimitiveShader(IDirect3DDevice9* pDevice, D3DPRIM
462497 bCompletedAnyPass = true ;
463498 }
464499
465- HRESULT hrEnd = pShaderInstance-> m_pEffectWrap ->End (bEffectDeviceOperational && !bEncounteredDeviceLoss);
500+ HRESULT hrEnd = pEffectWrap ->End (bEffectDeviceOperational && !bEncounteredDeviceLoss);
466501 if (FAILED (hrEnd) && hrEnd != D3DERR_DEVICELOST && hrEnd != D3DERR_DEVICENOTRESET)
467502 WriteDebugEvent (SString (" DrawPrimitiveShader: End failed %08x" , hrEnd));
468503
@@ -603,23 +638,30 @@ HRESULT CDirect3DEvents9::DrawIndexedPrimitiveShader(IDirect3DDevice9* pDevice,
603638 // See if we should use the previously setup shader
604639 if (g_pActiveShader)
605640 {
641+ SResolvedShaderState activeState;
642+ if (!TryResolveShaderState (g_pActiveShader, activeState) || !activeState.pEffect )
643+ {
644+ CloseActiveShader (false );
645+ if (!bIsLayer)
646+ return DrawIndexedPrimitiveGuarded (pDevice, PrimitiveType, BaseVertexIndex, MinVertexIndex, NumVertices, startIndex, primCount);
647+ return D3D_OK;
648+ }
649+
606650 dassert (pShaderItem == g_pActiveShader);
607651 g_pDeviceState->FrameStats .iNumShadersReuseSetup ++;
608652
609653 // Transfer any state changes to the active shader, but ensure the device still accepts work
610- CShaderInstance* pShaderInstance = g_pActiveShader->m_pShaderInstance ;
611- ID3DXEffect* pActiveEffect = pShaderInstance->m_pEffectWrap ->m_pD3DEffect ;
654+ CShaderInstance* pShaderInstance = activeState.pInstance ;
655+ CEffectWrap* pActiveEffectWrap = activeState.pEffectWrap ;
656+ ID3DXEffect* pActiveEffect = activeState.pEffect ;
612657
613658 bool bDeviceTemporarilyLost = false ;
614659 bool bDeviceOperational = true ;
615- if (pActiveEffect)
660+ IDirect3DDevice9* pEffectDevice = nullptr ;
661+ if (SUCCEEDED (pActiveEffect->GetDevice (&pEffectDevice)) && pEffectDevice)
616662 {
617- IDirect3DDevice9* pEffectDevice = nullptr ;
618- if (SUCCEEDED (pActiveEffect->GetDevice (&pEffectDevice)) && pEffectDevice)
619- {
620- bDeviceOperational = IsDeviceOperational (pEffectDevice, &bDeviceTemporarilyLost);
621- SAFE_RELEASE (pEffectDevice);
622- }
663+ bDeviceOperational = IsDeviceOperational (pEffectDevice, &bDeviceTemporarilyLost);
664+ SAFE_RELEASE (pEffectDevice);
623665 }
624666
625667 if (!bDeviceOperational)
@@ -628,11 +670,11 @@ HRESULT CDirect3DEvents9::DrawIndexedPrimitiveShader(IDirect3DDevice9* pDevice,
628670 return D3D_OK;
629671 }
630672
631- bool bChanged = pShaderInstance-> m_pEffectWrap ->ApplyCommonHandles ();
632- bChanged |= pShaderInstance-> m_pEffectWrap ->ApplyMappedHandles ();
673+ bool bChanged = pActiveEffectWrap ->ApplyCommonHandles ();
674+ bChanged |= pActiveEffectWrap ->ApplyMappedHandles ();
633675 if (bChanged)
634676 {
635- HRESULT hrCommit = pShaderInstance-> m_pEffectWrap -> m_pD3DEffect ->CommitChanges ();
677+ HRESULT hrCommit = pActiveEffect ->CommitChanges ();
636678 if (FAILED (hrCommit))
637679 {
638680 if (hrCommit != D3DERR_DEVICELOST && hrCommit != D3DERR_DEVICENOTRESET)
@@ -647,11 +689,21 @@ HRESULT CDirect3DEvents9::DrawIndexedPrimitiveShader(IDirect3DDevice9* pDevice,
647689 g_pDeviceState->FrameStats .iNumShadersFullSetup ++;
648690
649691 // Yes shader for this texture
650- CShaderInstance* pShaderInstance = pShaderItem->m_pShaderInstance ;
692+ SResolvedShaderState shaderState;
693+ if (!TryResolveShaderState (pShaderItem, shaderState) || !shaderState.pEffect )
694+ {
695+ if (!bIsLayer)
696+ return DrawIndexedPrimitiveGuarded (pDevice, PrimitiveType, BaseVertexIndex, MinVertexIndex, NumVertices, startIndex, primCount);
697+ return D3D_OK;
698+ }
699+
700+ CShaderInstance* pShaderInstance = shaderState.pInstance ;
701+ CEffectWrap* pEffectWrap = shaderState.pEffectWrap ;
702+ ID3DXEffect* pD3DEffect = shaderState.pEffect ;
651703
652704 // Add normal stream if shader wants it
653705 CAdditionalVertexStreamManager* pAdditionalStreamManager = CAdditionalVertexStreamManager::GetExistingSingleton ();
654- if (pShaderInstance-> m_pEffectWrap ->m_pEffectTemplate ->m_bRequiresNormals && pAdditionalStreamManager)
706+ if (pEffectWrap ->m_pEffectTemplate ->m_bRequiresNormals && pAdditionalStreamManager)
655707 {
656708 // Find/create/set additional vertex stream
657709 pAdditionalStreamManager->MaybeSetAdditionalVertexStream (PrimitiveType, BaseVertexIndex, MinVertexIndex, NumVertices, startIndex, primCount);
@@ -660,26 +712,22 @@ HRESULT CDirect3DEvents9::DrawIndexedPrimitiveShader(IDirect3DDevice9* pDevice,
660712 // Apply custom parameters
661713 pShaderInstance->ApplyShaderParameters ();
662714 // Apply common parameters
663- pShaderInstance-> m_pEffectWrap ->ApplyCommonHandles ();
715+ pEffectWrap ->ApplyCommonHandles ();
664716 // Apply mapped parameters
665- pShaderInstance-> m_pEffectWrap ->ApplyMappedHandles ();
717+ pEffectWrap ->ApplyMappedHandles ();
666718
667719 // Remember vertex shader if original draw was using it
668720 IDirect3DVertexShader9* pOriginalVertexShader = NULL ;
669721 pDevice->GetVertexShader (&pOriginalVertexShader);
670722
671723 // Do shader passes
672- ID3DXEffect* pD3DEffect = pShaderInstance-> m_pEffectWrap -> m_pD3DEffect ;
673- bool bEffectDeviceTemporarilyLost = false ;
674- bool bEffectDeviceOperational = true ;
675- if (pD3DEffect)
724+ bool bEffectDeviceTemporarilyLost = false ;
725+ bool bEffectDeviceOperational = true ;
726+ IDirect3DDevice9* pEffectDevice = nullptr ;
727+ if (SUCCEEDED ( pD3DEffect-> GetDevice (&pEffectDevice)) && pEffectDevice )
676728 {
677- IDirect3DDevice9* pEffectDevice = nullptr ;
678- if (SUCCEEDED (pD3DEffect->GetDevice (&pEffectDevice)) && pEffectDevice)
679- {
680- bEffectDeviceOperational = IsDeviceOperational (pEffectDevice, &bEffectDeviceTemporarilyLost);
681- SAFE_RELEASE (pEffectDevice);
682- }
729+ bEffectDeviceOperational = IsDeviceOperational (pEffectDevice, &bEffectDeviceTemporarilyLost);
730+ SAFE_RELEASE (pEffectDevice);
683731 }
684732
685733 if (!bEffectDeviceOperational)
@@ -694,7 +742,7 @@ HRESULT CDirect3DEvents9::DrawIndexedPrimitiveShader(IDirect3DDevice9* pDevice,
694742
695743 DWORD dwFlags = D3DXFX_DONOTSAVESHADERSTATE; // D3DXFX_DONOTSAVE(SHADER|SAMPLER)STATE
696744 uint uiNumPasses = 0 ;
697- HRESULT hrBegin = pShaderInstance-> m_pEffectWrap ->Begin (&uiNumPasses, dwFlags);
745+ HRESULT hrBegin = pEffectWrap ->Begin (&uiNumPasses, dwFlags);
698746 if (FAILED (hrBegin) || uiNumPasses == 0 )
699747 {
700748 if (FAILED (hrBegin) && hrBegin != D3DERR_DEVICELOST && hrBegin != D3DERR_DEVICENOTRESET)
@@ -735,6 +783,7 @@ HRESULT CDirect3DEvents9::DrawIndexedPrimitiveShader(IDirect3DDevice9* pDevice,
735783 {
736784 // Make this the active shader for possible reuse
737785 dassert (dwFlags == D3DXFX_DONOTSAVESHADERSTATE);
786+ pShaderItem->AddRef ();
738787 g_pActiveShader = pShaderItem;
739788 SAFE_RELEASE (pOriginalVertexShader);
740789 return D3D_OK;
@@ -754,7 +803,7 @@ HRESULT CDirect3DEvents9::DrawIndexedPrimitiveShader(IDirect3DDevice9* pDevice,
754803 bCompletedAnyPass = true ;
755804 }
756805
757- HRESULT hrEnd = pShaderInstance-> m_pEffectWrap ->End (bEffectDeviceOperational && !bEncounteredDeviceLoss);
806+ HRESULT hrEnd = pEffectWrap ->End (bEffectDeviceOperational && !bEncounteredDeviceLoss);
758807 if (FAILED (hrEnd) && hrEnd != D3DERR_DEVICELOST && hrEnd != D3DERR_DEVICENOTRESET)
759808 WriteDebugEvent (SString (" DrawIndexedPrimitiveShader: End failed %08x" , hrEnd));
760809
@@ -787,10 +836,15 @@ HRESULT CDirect3DEvents9::DrawIndexedPrimitiveShader(IDirect3DDevice9* pDevice,
787836// ///////////////////////////////////////////////////////////
788837void CDirect3DEvents9::CloseActiveShader (bool bDeviceOperational)
789838{
790- if (!g_pActiveShader)
839+ CShaderItem* pShaderItem = g_pActiveShader;
840+ g_pActiveShader = nullptr ;
841+ if (!pShaderItem)
791842 return ;
792843
793- ID3DXEffect* pD3DEffect = g_pActiveShader->m_pShaderInstance ->m_pEffectWrap ->m_pD3DEffect ;
844+ SResolvedShaderState shaderState;
845+ bool bHasShaderState = TryResolveShaderState (pShaderItem, shaderState);
846+
847+ ID3DXEffect* pD3DEffect = bHasShaderState ? shaderState.pEffect : nullptr ;
794848 IDirect3DDevice9* pDevice = g_pGraphics ? g_pGraphics->GetDevice () : nullptr ;
795849
796850 bool bAllowDeviceWork = bDeviceOperational;
@@ -809,8 +863,8 @@ void CDirect3DEvents9::CloseActiveShader(bool bDeviceOperational)
809863 }
810864
811865 // When the device is lost we intentionally skip touching the GPU beyond the required End call; the effect will be reset later.
812- g_pActiveShader-> m_pShaderInstance -> m_pEffectWrap -> End (bAllowDeviceWork);
813- g_pActiveShader = nullptr ;
866+ if (bHasShaderState)
867+ shaderState. pEffectWrap -> End (bAllowDeviceWork) ;
814868
815869 if (CAdditionalVertexStreamManager* pAdditionalStreamManager = CAdditionalVertexStreamManager::GetExistingSingleton ())
816870 pAdditionalStreamManager->MaybeUnsetAdditionalVertexStream ();
@@ -821,6 +875,8 @@ void CDirect3DEvents9::CloseActiveShader(bool bDeviceOperational)
821875 pDevice->SetVertexShader (nullptr );
822876 pDevice->SetPixelShader (nullptr );
823877 }
878+
879+ pShaderItem->Release ();
824880}
825881
826882// ///////////////////////////////////////////////////////////
@@ -1925,7 +1981,10 @@ IDirect3DVertexBuffer9* CDirect3DEvents9::GetRealVertexBuffer(IDirect3DVertexBuf
19251981
19261982 // If so, use the original vertex buffer
19271983 if (pProxy)
1984+ {
19281985 pStreamData = pProxy->GetOriginal ();
1986+ SAFE_RELEASE (pProxy);
1987+ }
19291988 }
19301989
19311990 return pStreamData;
@@ -1948,7 +2007,10 @@ IDirect3DIndexBuffer9* CDirect3DEvents9::GetRealIndexBuffer(IDirect3DIndexBuffer
19482007
19492008 // If so, use the original index buffer
19502009 if (pProxy)
2010+ {
19512011 pIndexData = pProxy->GetOriginal ();
2012+ SAFE_RELEASE (pProxy);
2013+ }
19522014 }
19532015 return pIndexData;
19542016}
@@ -1970,7 +2032,10 @@ IDirect3DBaseTexture9* CDirect3DEvents9::GetRealTexture(IDirect3DBaseTexture9* p
19702032
19712033 // If so, use the original texture
19722034 if (pProxy)
2035+ {
19732036 pTexture = pProxy->GetOriginal ();
2037+ SAFE_RELEASE (pProxy);
2038+ }
19742039 }
19752040 return pTexture;
19762041}
@@ -2036,6 +2101,8 @@ HRESULT CDirect3DEvents9::SetVertexDeclaration(IDirect3DDevice9* pDevice, IDirec
20362101 CProxyDirect3DDevice9::SD3DVertexDeclState* pInfo = MapFind (g_pProxyDevice->m_VertexDeclMap , pProxy);
20372102 if (pInfo)
20382103 g_pDeviceState->VertexDeclState = *pInfo;
2104+
2105+ SAFE_RELEASE (pProxy);
20392106 }
20402107 }
20412108
@@ -2054,26 +2121,33 @@ ERenderFormat CDirect3DEvents9::DiscoverReadableDepthFormat(IDirect3DDevice9* pD
20542121 IDirect3D9* pD3D = NULL ;
20552122 pDevice->GetDirect3D (&pD3D);
20562123
2057- // Formats to check for
2058- ERenderFormat checkList[] = {RFORMAT_INTZ, RFORMAT_DF24, RFORMAT_DF16, RFORMAT_RAWZ};
2124+ ERenderFormat discoveredFormat = RFORMAT_UNKNOWN;
20592125
2060- D3DDISPLAYMODE displayMode;
2061- if (pD3D->GetAdapterDisplayMode (D3DADAPTER_DEFAULT, &displayMode) == D3D_OK)
2126+ if (pD3D)
20622127 {
2063- for (uint i = 0 ; i < NUMELMS (checkList); i++)
2128+ // Formats to check for
2129+ ERenderFormat checkList[] = {RFORMAT_INTZ, RFORMAT_DF24, RFORMAT_DF16, RFORMAT_RAWZ};
2130+
2131+ D3DDISPLAYMODE displayMode;
2132+ if (pD3D->GetAdapterDisplayMode (D3DADAPTER_DEFAULT, &displayMode) == D3D_OK)
20642133 {
2065- D3DFORMAT DepthFormat = (D3DFORMAT)checkList[i];
2134+ for (uint i = 0 ; i < NUMELMS (checkList); i++)
2135+ {
2136+ D3DFORMAT DepthFormat = (D3DFORMAT)checkList[i];
20662137
2067- // Can use this format?
2068- if (D3D_OK != pD3D->CheckDeviceFormat (D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, displayMode.Format , D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, DepthFormat))
2069- continue ;
2138+ // Can use this format?
2139+ if (D3D_OK != pD3D->CheckDeviceFormat (D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, displayMode.Format , D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, DepthFormat))
2140+ continue ;
20702141
2071- // Don't check for compatibility with multisampling, as we turn AA off when using readable depth buffer
2142+ // Don't check for compatibility with multisampling, as we turn AA off when using readable depth buffer
20722143
2073- // Found a working format
2074- return checkList[i];
2144+ // Found a working format
2145+ discoveredFormat = checkList[i];
2146+ break ;
2147+ }
20752148 }
20762149 }
20772150
2078- return RFORMAT_UNKNOWN;
2151+ SAFE_RELEASE (pD3D);
2152+ return discoveredFormat;
20792153}
0 commit comments