Skip to content

Commit

Permalink
[d3d8] RefCount refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
WinterSnowfall committed Apr 3, 2023
1 parent 2c56a1a commit 86165b7
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 26 deletions.
2 changes: 1 addition & 1 deletion src/d3d8/d3d8_blit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ namespace dxvk {
case D3DPOOL_SYSTEMMEM: {

// RT (DEFAULT) -> SYSTEMMEM: Use GetRenderTargetData as fast path if possible
if ((srcDesc.Usage & D3DUSAGE_RENDERTARGET || m_renderTarget == src)) {
if ((srcDesc.Usage & D3DUSAGE_RENDERTARGET || m_renderTarget.ptr() == src.ptr())) {

// GetRenderTargetData works if the formats and sizes match
if (srcDesc.MultiSampleType == d3d9::D3DMULTISAMPLE_NONE
Expand Down
101 changes: 79 additions & 22 deletions src/d3d8/d3d8_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,14 +151,15 @@ namespace dxvk {
UINT iBackBuffer,
D3DBACKBUFFER_TYPE Type,
IDirect3DSurface8** ppBackBuffer) {
InitReturnPtr(ppBackBuffer);

if (iBackBuffer >= m_backBuffers.size() || m_backBuffers[iBackBuffer] == nullptr) {
Com<d3d9::IDirect3DSurface9> pSurface9;
HRESULT res = GetD3D9()->GetBackBuffer(0, iBackBuffer, (d3d9::D3DBACKBUFFER_TYPE)Type, &pSurface9);

if (FAILED(res)) return res;

m_backBuffers[iBackBuffer] = ref(new D3D8Surface(this, std::move(pSurface9)));
m_backBuffers[iBackBuffer] = new D3D8Surface(this, std::move(pSurface9));
*ppBackBuffer = m_backBuffers[iBackBuffer].ref();

return res;
Expand Down Expand Up @@ -368,30 +369,62 @@ namespace dxvk {

if (pRenderTarget != NULL) {
D3D8Surface* surf = static_cast<D3D8Surface*>(pRenderTarget);
res = GetD3D9()->SetRenderTarget(0, surf->GetD3D9());

if (FAILED(res)) return res;
D3DSURFACE_DESC rtDesc;
surf->GetDesc(&rtDesc);

if (unlikely(!(rtDesc.Usage & D3DUSAGE_RENDERTARGET)))
return D3DERR_INVALIDCALL;

if(likely(m_renderTarget.ptr() != surf)) {
res = GetD3D9()->SetRenderTarget(0, surf->GetD3D9());

if (FAILED(res)) return res;

m_renderTarget = ref(surf);
// keep a temporary ref on the prev RT, since this could be a swap
D3D8Surface* pRenderTargetSwap = m_renderTargetPrev.ref();
m_renderTargetPrev = m_renderTarget;
m_renderTarget = surf;
SAFE_RELEASE(pRenderTargetSwap);
}
}

// SetDepthStencilSurface is a separate call
D3D8Surface* zStencil = static_cast<D3D8Surface*>(pNewZStencil);
res = GetD3D9()->SetDepthStencilSurface(D3D8Surface::GetD3D9Nullable(zStencil));

if (FAILED(res)) return res;
if(pNewZStencil != NULL) {
D3DSURFACE_DESC zsDesc;
zStencil->GetDesc(&zsDesc);

m_depthStencil = ref(zStencil);
return res;
if (unlikely(!(zsDesc.Usage & D3DUSAGE_DEPTHSTENCIL)))
return D3DERR_INVALIDCALL;
}

if(likely(m_depthStencil.ptr() != zStencil)) {
res = GetD3D9()->SetDepthStencilSurface(D3D8Surface::GetD3D9Nullable(zStencil));

if (FAILED(res)) return res;

// keep a temporary ref on the prev DS, since this could be a swap
D3D8Surface* pDepthStencilSwap = m_depthStencilPrev.ref();
m_depthStencilPrev = m_depthStencil;
m_depthStencil = zStencil;
SAFE_RELEASE(pDepthStencilSwap);
}

return D3D_OK;
}

HRESULT STDMETHODCALLTYPE GetRenderTarget(IDirect3DSurface8** ppRenderTarget) {
InitReturnPtr(ppRenderTarget);

if (unlikely(m_renderTarget == nullptr)) {
Com<d3d9::IDirect3DSurface9> pRT9 = nullptr;
HRESULT res = GetD3D9()->GetRenderTarget(0, &pRT9); // use RT index 0

m_renderTarget = ref(new D3D8Surface(this, std::move(pRT9)));
if(FAILED(res)) return res;

m_renderTarget = new D3D8Surface(this, std::move(pRT9));

*ppRenderTarget = m_renderTarget.ref();
return res;
Expand All @@ -402,12 +435,15 @@ namespace dxvk {
}

HRESULT STDMETHODCALLTYPE GetDepthStencilSurface(IDirect3DSurface8** ppZStencilSurface) {
InitReturnPtr(ppZStencilSurface);

if (unlikely(m_depthStencil == nullptr)) {
Com<d3d9::IDirect3DSurface9> pStencil9 = nullptr;
HRESULT res = GetD3D9()->GetDepthStencilSurface(&pStencil9);

m_depthStencil = ref(new D3D8Surface(this, std::move(pStencil9)));
if(FAILED(res)) return res;

m_depthStencil = new D3D8Surface(this, std::move(pStencil9));

*ppZStencilSurface = m_depthStencil.ref();
return res;
Expand Down Expand Up @@ -567,9 +603,13 @@ namespace dxvk {

D3D8Texture2D* tex = static_cast<D3D8Texture2D*>(pTexture);

m_textures[Stage] = ref(tex);
if(likely(m_textures[Stage].ptr() != tex)) {
m_textures[Stage] = tex;

return GetD3D9()->SetTexture(Stage, D3D8Texture2D::GetD3D9Nullable(tex));
}

return GetD3D9()->SetTexture(Stage, D3D8Texture2D::GetD3D9Nullable(tex));
return D3D_OK;
}

HRESULT STDMETHODCALLTYPE GetTextureStageState(
Expand Down Expand Up @@ -723,9 +763,15 @@ namespace dxvk {

D3D8VertexBuffer* buffer = static_cast<D3D8VertexBuffer*>(pStreamData);

m_streams[StreamNumber] = D3D8VBO {buffer, Stride};
const D3D8VBO& vbo = m_streams[StreamNumber];

if(likely(vbo.buffer.ptr() != buffer || vbo.stride != Stride)) {
m_streams[StreamNumber] = D3D8VBO {buffer, Stride};

return GetD3D9()->SetStreamSource(StreamNumber, D3D8VertexBuffer::GetD3D9Nullable(buffer), 0, Stride);
}

return GetD3D9()->SetStreamSource(StreamNumber, D3D8VertexBuffer::GetD3D9Nullable(buffer), 0, Stride);
return D3D_OK;
}

HRESULT STDMETHODCALLTYPE GetStreamSource(
Expand Down Expand Up @@ -761,16 +807,23 @@ namespace dxvk {

D3D8IndexBuffer* buffer = static_cast<D3D8IndexBuffer*>(pIndexData);

m_indices = buffer;
if(likely(m_indices.ptr() != buffer)) {
m_indices = buffer;

return GetD3D9()->SetIndices(D3D8IndexBuffer::GetD3D9Nullable(buffer));
}

return GetD3D9()->SetIndices(D3D8IndexBuffer::GetD3D9Nullable(buffer));
return D3D_OK;
}

HRESULT STDMETHODCALLTYPE GetIndices(
IDirect3DIndexBuffer8** ppIndexData,
UINT* pBaseVertexIndex) {
InitReturnPtr(ppIndexData);

*ppIndexData = m_indices.ptr();
*pBaseVertexIndex = m_baseVertexIndex;

return D3D_OK;
}

Expand Down Expand Up @@ -831,7 +884,9 @@ namespace dxvk {
}
m_frontBuffer = nullptr;
m_renderTarget = nullptr;
m_renderTargetPrev = nullptr;
m_depthStencil = nullptr;
m_depthStencilPrev = nullptr;
}

friend d3d9::IDirect3DPixelShader9* getPixelShaderPtr(D3D8DeviceEx* device, DWORD Handle);
Expand All @@ -849,23 +904,25 @@ namespace dxvk {
D3D8StateBlock* m_recorder = nullptr;

struct D3D8VBO {
Com<D3D8VertexBuffer> buffer = nullptr;
UINT stride = 0;
Com<D3D8VertexBuffer, false> buffer = nullptr;
UINT stride = 0;
};

// Remember to fill() these in the constructor!
std::array<Com<IDirect3DBaseTexture8>, d8caps::MAX_TEXTURE_STAGES> m_textures;
std::array<Com<D3D8Texture2D, false>, d8caps::MAX_TEXTURE_STAGES> m_textures;
std::array<D3D8VBO, d8caps::MAX_STREAMS> m_streams;

Com<D3D8IndexBuffer> m_indices;
INT m_baseVertexIndex = 0;
Com<D3D8IndexBuffer, false> m_indices;
INT m_baseVertexIndex = 0;

// TODO: Which of these should be a private ref
std::vector<Com<D3D8Surface, false>> m_backBuffers;
Com<D3D8Surface> m_frontBuffer;

Com<D3D8Surface> m_renderTarget;
Com<D3D8Surface, false> m_renderTarget;
Com<D3D8Surface, false> m_renderTargetPrev;
Com<D3D8Surface, false> m_depthStencil;
Com<D3D8Surface, false> m_depthStencilPrev;

std::vector<D3D8VertexShaderInfo> m_vertexShaders;
std::vector<d3d9::IDirect3DPixelShader9*> m_pixelShaders;
Expand Down
4 changes: 4 additions & 0 deletions src/d3d8/d3d8_device_child.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ namespace dxvk {
}

ULONG STDMETHODCALLTYPE Release() {
// ignore Release calls on objects with 0 refCount
if(unlikely(!this->m_refCount))
return this->m_refCount;

uint32_t refCount = --this->m_refCount;
if (unlikely(!refCount)) {
auto* pDevice = GetDevice();
Expand Down
7 changes: 5 additions & 2 deletions src/d3d8/d3d8_state_block.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@ HRESULT dxvk::D3D8StateBlock::Capture() {
if (m_capture.ps) m_device->GetPixelShader(&m_pixelShader);

for (DWORD stage = 0; stage < m_textures.size(); stage++)
if (m_capture.textures.get(stage))
if (m_capture.textures.get(stage)) {
m_device->GetTexture(stage, &m_textures[stage]);
// we are adding a needless ref when calling GetTexture, so release it
SAFE_RELEASE(m_textures[stage]);
}

if (m_capture.indices) m_device->GetIndices(&m_indices, &m_baseVertexIndex);

Expand All @@ -32,7 +35,7 @@ HRESULT dxvk::D3D8StateBlock::Apply() {

for (DWORD stage = 0; stage < m_textures.size(); stage++)
if (m_capture.textures.get(stage))
m_device->SetTexture(stage, m_textures[stage] );
m_device->SetTexture(stage, m_textures[stage]);

if (m_capture.indices) m_device->SetIndices(m_indices, m_baseVertexIndex);

Expand Down
2 changes: 1 addition & 1 deletion src/d3d8/d3d8_texture.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ namespace dxvk {
return ptr;
}

std::vector<Com<SubresourceType>> m_subresources;
std::vector<Com<SubresourceType, false>> m_subresources;

};

Expand Down

0 comments on commit 86165b7

Please sign in to comment.