Skip to content

Commit

Permalink
Track and release state block tokens on device destruction (#176)
Browse files Browse the repository at this point in the history
  • Loading branch information
WinterSnowfall authored Sep 11, 2024
1 parent d3d0ee4 commit 18bce66
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 8 deletions.
6 changes: 3 additions & 3 deletions source/d3d8to9.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ class Direct3DDevice8 : public IDirect3DDevice8

private:
void ApplyClipPlanes();
void ReleaseShaders();
void ReleaseShadersAndStateBlocks();

Direct3D8 *const D3D;
IDirect3DDevice9 *const ProxyInterface;
Expand All @@ -175,8 +175,8 @@ class Direct3DDevice8 : public IDirect3DDevice8
float StoredClipPlanes[MAX_CLIP_PLANES][4] = {};
DWORD ClipPlaneRenderState = 0;

// Store Shader Handles so they can be destroyed later to mirror D3D8 behavior
std::unordered_set<DWORD> PixelShaderHandles, VertexShaderHandles;
// Store Shader Handles and State Block Tokens so they can be destroyed later to mirror D3D8 behavior
std::unordered_set<DWORD> PixelShaderHandles, VertexShaderHandles, StateBlockTokens;
unsigned int VertexShaderAndDeclarationCount = 0;
};

Expand Down
27 changes: 22 additions & 5 deletions source/d3d8to9_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ ULONG STDMETHODCALLTYPE Direct3DDevice8::Release()

// Shaders are destroyed alongside the device that created them in D3D8 but not in D3D9
// so we Release all the shaders when the device releases to mirror that behaviour
if (LastRefCount !=0 && LastRefCount == (VertexShaderAndDeclarationCount + PixelShaderHandles.size()))
if (LastRefCount != 0 && LastRefCount == (VertexShaderAndDeclarationCount + PixelShaderHandles.size() + StateBlockTokens.size()))
{
ProxyInterface->AddRef();
ReleaseShaders();
ReleaseShadersAndStateBlocks();
LastRefCount = ProxyInterface->Release();
assert(LastRefCount == 0);
}
Expand Down Expand Up @@ -783,7 +783,12 @@ HRESULT STDMETHODCALLTYPE Direct3DDevice8::EndStateBlock(DWORD *pToken)
if (pToken == nullptr)
return D3DERR_INVALIDCALL;

return ProxyInterface->EndStateBlock(reinterpret_cast<IDirect3DStateBlock9 **>(pToken));
HRESULT hr = ProxyInterface->EndStateBlock(reinterpret_cast<IDirect3DStateBlock9 **>(pToken));

if (SUCCEEDED(hr))
StateBlockTokens.insert(*pToken);

return hr;
}
HRESULT STDMETHODCALLTYPE Direct3DDevice8::ApplyStateBlock(DWORD Token)
{
Expand All @@ -806,6 +811,8 @@ HRESULT STDMETHODCALLTYPE Direct3DDevice8::DeleteStateBlock(DWORD Token)

reinterpret_cast<IDirect3DStateBlock9 *>(Token)->Release();

StateBlockTokens.erase(Token);

return D3D_OK;
}
HRESULT STDMETHODCALLTYPE Direct3DDevice8::CreateStateBlock(D3DSTATEBLOCKTYPE Type, DWORD *pToken)
Expand All @@ -817,7 +824,12 @@ HRESULT STDMETHODCALLTYPE Direct3DDevice8::CreateStateBlock(D3DSTATEBLOCKTYPE Ty
if (pToken == nullptr)
return D3DERR_INVALIDCALL;

return ProxyInterface->CreateStateBlock(Type, reinterpret_cast<IDirect3DStateBlock9 **>(pToken));
HRESULT hr = ProxyInterface->CreateStateBlock(Type, reinterpret_cast<IDirect3DStateBlock9 **>(pToken));

if (SUCCEEDED(hr))
StateBlockTokens.insert(*pToken);

return hr;
}
HRESULT STDMETHODCALLTYPE Direct3DDevice8::SetClipStatus(const D3DCLIPSTATUS8 *pClipStatus)
{
Expand Down Expand Up @@ -2181,7 +2193,7 @@ void Direct3DDevice8::ApplyClipPlanes()
}
}

void Direct3DDevice8::ReleaseShaders()
void Direct3DDevice8::ReleaseShadersAndStateBlocks()
{
for (auto Handle : PixelShaderHandles)
{
Expand All @@ -2194,4 +2206,9 @@ void Direct3DDevice8::ReleaseShaders()
}
VertexShaderHandles.clear();
VertexShaderAndDeclarationCount = 0;
for (auto Token : StateBlockTokens)
{
DeleteStateBlock(Token);
}
StateBlockTokens.clear();
}

0 comments on commit 18bce66

Please sign in to comment.