diff --git a/src/d3d8/d3d8_buffer.h b/src/d3d8/d3d8_buffer.h index 6ffcdaeb8ce..8d8f903a53c 100644 --- a/src/d3d8/d3d8_buffer.h +++ b/src/d3d8/d3d8_buffer.h @@ -50,8 +50,8 @@ namespace dxvk { protected: - const D3D8Options* m_options; - const DWORD m_usage; + const D3D8Options* m_options = nullptr; + const DWORD m_usage = 0; }; diff --git a/src/d3d8/d3d8_caps.h b/src/d3d8/d3d8_caps.h index ea1a78136da..0b5c816c461 100644 --- a/src/d3d8/d3d8_caps.h +++ b/src/d3d8/d3d8_caps.h @@ -9,4 +9,4 @@ namespace dxvk::d8caps { constexpr float ZBIAS_SCALE = -1.0f / ((1u << 16) - 1); // Consider D16 precision constexpr float ZBIAS_SCALE_INV = 1 / ZBIAS_SCALE; -} +} \ No newline at end of file diff --git a/src/d3d8/d3d8_device.cpp b/src/d3d8/d3d8_device.cpp index 5c830b8430d..47c9c0fa9c1 100644 --- a/src/d3d8/d3d8_device.cpp +++ b/src/d3d8/d3d8_device.cpp @@ -8,29 +8,6 @@ namespace dxvk { - static constexpr DWORD isFVF(DWORD Handle) { - return (Handle & D3DFVF_RESERVED0) == 0; - } - - static constexpr DWORD getShaderHandle(DWORD Index) { - return (Index << 1) | D3DFVF_RESERVED0; - } - - static constexpr DWORD getShaderIndex(DWORD Handle) { - if ((Handle & D3DFVF_RESERVED0) != 0) { - return ((Handle & ~(D3DFVF_RESERVED0)) >> 1) - 1; - } else { - return Handle; - } - } - - struct D3D8VertexShaderInfo { - Com pVertexDecl; - Com pVertexShader; - std::vector declaration; - std::vector function; - }; - D3D8Device::D3D8Device( D3D8Interface* pParent, Com&& pDevice, @@ -139,7 +116,6 @@ namespace dxvk { } HRESULT STDMETHODCALLTYPE D3D8Device::TestCooperativeLevel() { - // Equivalent of D3D11/DXGI present tests. return GetD3D9()->TestCooperativeLevel(); } @@ -162,16 +138,17 @@ namespace dxvk { HRESULT STDMETHODCALLTYPE D3D8Device::GetDeviceCaps(D3DCAPS8* pCaps) { d3d9::D3DCAPS9 caps9; + HRESULT res = GetD3D9()->GetDeviceCaps(&caps9); + if (unlikely(FAILED(res))) + return res; - if (likely(SUCCEEDED(res))) - ConvertCaps8(caps9, pCaps); + ConvertCaps8(caps9, pCaps); - return res; + return D3D_OK; } HRESULT STDMETHODCALLTYPE D3D8Device::GetDisplayMode(D3DDISPLAYMODE* pMode) { - // swap chain 0 return GetD3D9()->GetDisplayMode(0, reinterpret_cast(pMode)); } @@ -187,16 +164,16 @@ namespace dxvk { return GetD3D9()->SetCursorProperties(XHotSpot, YHotSpot, D3D8Surface::GetD3D9Nullable(surf)); } - void STDMETHODCALLTYPE D3D8Device::SetCursorPosition(UINT XScreenSpace, UINT YScreenSpace, DWORD Flags) { + void STDMETHODCALLTYPE D3D8Device::SetCursorPosition(UINT XScreenSpace, UINT YScreenSpace, DWORD Flags) { GetD3D9()->SetCursorPosition(XScreenSpace, YScreenSpace, Flags); } // Microsoft d3d8.h in the DirectX 9 SDK uses a different function signature... - void STDMETHODCALLTYPE D3D8Device::SetCursorPosition(int X, int Y, DWORD Flags) { + void STDMETHODCALLTYPE D3D8Device::SetCursorPosition(int X, int Y, DWORD Flags) { GetD3D9()->SetCursorPosition(X, Y, Flags); } - BOOL STDMETHODCALLTYPE D3D8Device::ShowCursor(BOOL bShow) { + BOOL STDMETHODCALLTYPE D3D8Device::ShowCursor(BOOL bShow) { return GetD3D9()->ShowCursor(bShow); } @@ -214,18 +191,18 @@ namespace dxvk { ¶ms, &pSwapChain9 ); + if (unlikely(FAILED(res))) + return res; - if (likely(SUCCEEDED(res))) - *ppSwapChain = ref(new D3D8SwapChain(this, pPresentationParameters, std::move(pSwapChain9))); + *ppSwapChain = ref(new D3D8SwapChain(this, pPresentationParameters, std::move(pSwapChain9))); - return res; + return D3D_OK; } HRESULT STDMETHODCALLTYPE D3D8Device::Reset(D3DPRESENT_PARAMETERS* pPresentationParameters) { D3D8DeviceLock lock = LockDevice(); HRESULT res = m_parent->ValidatePresentationParameters(pPresentationParameters); - if (unlikely(FAILED(res))) return res; @@ -236,11 +213,12 @@ namespace dxvk { d3d9::D3DPRESENT_PARAMETERS params = ConvertPresentParameters9(pPresentationParameters); res = GetD3D9()->Reset(¶ms); + if (unlikely(FAILED(res))) + return res; - if (likely(SUCCEEDED(res))) - RecreateBackBuffersAndAutoDepthStencil(); + RecreateBackBuffersAndAutoDepthStencil(); - return res; + return D3D_OK; } HRESULT STDMETHODCALLTYPE D3D8Device::Present( @@ -250,7 +228,9 @@ namespace dxvk { const RGNDATA* pDirtyRegion) { D3D8DeviceLock lock = LockDevice(); - m_batcher->EndFrame(); + if (unlikely(ShouldBatch())) + m_batcher->EndFrame(); + StateChange(); return GetD3D9()->Present(pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion); } @@ -269,13 +249,10 @@ namespace dxvk { if (iBackBuffer >= m_backBuffers.size() || m_backBuffers[iBackBuffer] == nullptr) { Com pSurface9; HRESULT res = GetD3D9()->GetBackBuffer(0, iBackBuffer, (d3d9::D3DBACKBUFFER_TYPE)Type, &pSurface9); + if (unlikely(FAILED(res))) + return res; - if (likely(SUCCEEDED(res))) { - m_backBuffers[iBackBuffer] = new D3D8Surface(this, D3DPOOL_DEFAULT, std::move(pSurface9)); - *ppBackBuffer = m_backBuffers[iBackBuffer].ref(); - } - - return res; + m_backBuffers[iBackBuffer] = new D3D8Surface(this, D3DPOOL_DEFAULT, std::move(pSurface9)); } *ppBackBuffer = m_backBuffers[iBackBuffer].ref(); @@ -289,12 +266,10 @@ namespace dxvk { void STDMETHODCALLTYPE D3D8Device::SetGammaRamp(DWORD Flags, const D3DGAMMARAMP* pRamp) { StateChange(); - // For swap chain 0 GetD3D9()->SetGammaRamp(0, Flags, reinterpret_cast(pRamp)); } void STDMETHODCALLTYPE D3D8Device::GetGammaRamp(D3DGAMMARAMP* pRamp) { - // For swap chain 0 GetD3D9()->GetGammaRamp(0, reinterpret_cast(pRamp)); } @@ -323,7 +298,7 @@ namespace dxvk { if (m_d3d8Options.placeP8InScratch && Format == D3DFMT_P8) Pool = D3DPOOL_SCRATCH; - Com pTex9 = nullptr; + Com pTex9; HRESULT res = GetD3D9()->CreateTexture( Width, Height, @@ -333,11 +308,19 @@ namespace dxvk { d3d9::D3DPOOL(Pool), &pTex9, NULL); + if (unlikely(FAILED(res))) + return res; - if (likely(SUCCEEDED(res))) - *ppTexture = ref(new D3D8Texture2D(this, Pool, std::move(pTex9))); + IDirect3DTexture8* tex = new D3D8Texture2D(this, Pool, std::move(pTex9)); - return res; + if (unlikely(m_d3d8Options.textureUAFGuard)) { + D3D8DeviceLock lock = LockDevice(); + m_validTextures.insert(tex); + } + + *ppTexture = ref(tex); + + return D3D_OK; } HRESULT STDMETHODCALLTYPE D3D8Device::CreateVolumeTexture( @@ -362,7 +345,7 @@ namespace dxvk { if (unlikely(isD3D9ExclusiveFormat(Format))) return D3DERR_INVALIDCALL; - Com pVolume9 = nullptr; + Com pVolume9; HRESULT res = GetD3D9()->CreateVolumeTexture( Width, Height, Depth, Levels, Usage, @@ -370,11 +353,19 @@ namespace dxvk { d3d9::D3DPOOL(Pool), &pVolume9, NULL); + if (unlikely(FAILED(res))) + return res; - if (likely(SUCCEEDED(res))) - *ppVolumeTexture = ref(new D3D8Texture3D(this, Pool, std::move(pVolume9))); + IDirect3DVolumeTexture8* tex = new D3D8Texture3D(this, Pool, std::move(pVolume9)); - return res; + if (unlikely(m_d3d8Options.textureUAFGuard)) { + D3D8DeviceLock lock = LockDevice(); + m_validTextures.insert(tex); + } + + *ppVolumeTexture = ref(tex); + + return D3D_OK; } HRESULT STDMETHODCALLTYPE D3D8Device::CreateCubeTexture( @@ -397,7 +388,7 @@ namespace dxvk { if (unlikely(isD3D9ExclusiveFormat(Format))) return D3DERR_INVALIDCALL; - Com pCube9 = nullptr; + Com pCube9; HRESULT res = GetD3D9()->CreateCubeTexture( EdgeLength, Levels, @@ -406,11 +397,19 @@ namespace dxvk { d3d9::D3DPOOL(Pool), &pCube9, NULL); + if (unlikely(FAILED(res))) + return res; - if (likely(SUCCEEDED(res))) - *ppCubeTexture = ref(new D3D8TextureCube(this, Pool, std::move(pCube9))); + IDirect3DCubeTexture8* tex = new D3D8TextureCube(this, Pool, std::move(pCube9)); - return res; + if (unlikely(m_d3d8Options.textureUAFGuard)) { + D3D8DeviceLock lock = LockDevice(); + m_validTextures.insert(tex); + } + + *ppCubeTexture = ref(tex); + + return D3D_OK; } HRESULT STDMETHODCALLTYPE D3D8Device::CreateVertexBuffer( @@ -429,13 +428,14 @@ namespace dxvk { return D3D_OK; } - Com pVertexBuffer9 = nullptr; + Com pVertexBuffer9; HRESULT res = GetD3D9()->CreateVertexBuffer(Length, Usage, FVF, d3d9::D3DPOOL(Pool), &pVertexBuffer9, NULL); + if (unlikely(FAILED(res))) + return res; - if (likely(SUCCEEDED(res))) - *ppVertexBuffer = ref(new D3D8VertexBuffer(this, std::move(pVertexBuffer9), Pool, Usage)); + *ppVertexBuffer = ref(new D3D8VertexBuffer(this, std::move(pVertexBuffer9), Pool, Usage)); - return res; + return D3D_OK; } HRESULT STDMETHODCALLTYPE D3D8Device::CreateIndexBuffer( @@ -449,13 +449,14 @@ namespace dxvk { if (unlikely(ppIndexBuffer == nullptr)) return D3DERR_INVALIDCALL; - Com pIndexBuffer9 = nullptr; + Com pIndexBuffer9; HRESULT res = GetD3D9()->CreateIndexBuffer(Length, Usage, d3d9::D3DFORMAT(Format), d3d9::D3DPOOL(Pool), &pIndexBuffer9, NULL); + if (unlikely(FAILED(res))) + return res; - if (likely(SUCCEEDED(res))) - *ppIndexBuffer = ref(new D3D8IndexBuffer(this, std::move(pIndexBuffer9), Pool, Usage)); + *ppIndexBuffer = ref(new D3D8IndexBuffer(this, std::move(pIndexBuffer9), Pool, Usage)); - return res; + return D3D_OK; } HRESULT STDMETHODCALLTYPE D3D8Device::CreateRenderTarget( @@ -481,7 +482,7 @@ namespace dxvk { if (unlikely(!isRenderTargetFormat(Format))) return D3DERR_INVALIDCALL; - Com pSurf9 = nullptr; + Com pSurf9; HRESULT res = GetD3D9()->CreateRenderTarget( Width, Height, @@ -491,11 +492,12 @@ namespace dxvk { Lockable, &pSurf9, NULL); + if (unlikely(FAILED(res))) + return res; - if (likely(SUCCEEDED(res))) - *ppSurface = ref(new D3D8Surface(this, D3DPOOL_DEFAULT, std::move(pSurf9))); + *ppSurface = ref(new D3D8Surface(this, D3DPOOL_DEFAULT, std::move(pSurf9))); - return res; + return D3D_OK; } HRESULT STDMETHODCALLTYPE D3D8Device::CreateDepthStencilSurface( @@ -517,7 +519,7 @@ namespace dxvk { if (unlikely(isD3D9ExclusiveFormat(Format))) return D3DERR_INVALIDCALL; - Com pSurf9 = nullptr; + Com pSurf9; HRESULT res = GetD3D9()->CreateDepthStencilSurface( Width, Height, @@ -527,11 +529,12 @@ namespace dxvk { FALSE, // z-buffer discarding is not used in D3D8 &pSurf9, NULL); + if (unlikely(FAILED(res))) + return res; - if (likely(SUCCEEDED(res))) - *ppSurface = ref(new D3D8Surface(this, D3DPOOL_DEFAULT, std::move(pSurf9))); + *ppSurface = ref(new D3D8Surface(this, D3DPOOL_DEFAULT, std::move(pSurf9))); - return res; + return D3D_OK; } HRESULT STDMETHODCALLTYPE D3D8Device::CreateImageSurface( @@ -555,9 +558,9 @@ namespace dxvk { return D3DERR_INVALIDCALL; const bool isSupportedSurfaceFormat = m_bridge->IsSupportedSurfaceFormat(d3d9::D3DFORMAT(Format)); - D3DPOOL pool = isSupportedSurfaceFormat ? D3DPOOL_SYSTEMMEM : D3DPOOL_SCRATCH; + const D3DPOOL pool = isSupportedSurfaceFormat ? D3DPOOL_SYSTEMMEM : D3DPOOL_SCRATCH; - Com pSurf = nullptr; + Com pSurf; HRESULT res = GetD3D9()->CreateOffscreenPlainSurface( Width, Height, @@ -565,11 +568,12 @@ namespace dxvk { d3d9::D3DPOOL(pool), &pSurf, NULL); + if (unlikely(FAILED(res))) + return res; - if (likely(SUCCEEDED(res))) - *ppSurface = ref(new D3D8Surface(this, pool, std::move(pSurf))); + *ppSurface = ref(new D3D8Surface(this, pool, std::move(pSurf))); - return res; + return D3D_OK; } // Copies texture rect in system mem using memcpy. @@ -664,14 +668,14 @@ namespace dxvk { * The following table shows the possible combinations of source * and destination surface pools, and how we handle each of them. * - * ┌────────────┬───────────────────────────┬───────────────────────┬───────────────────────┬──────────────────────┐ - * │ Src/Dst │ DEFAULT │ MANAGED │ SYSTEMMEM │ SCRATCH │ - * ├────────────┼───────────────────────────┼───────────────────────┼───────────────────────┼──────────────────────┤ - * │ DEFAULT │ StretchRect │ GetRenderTargetData │ GetRenderTargetData │ GetRenderTargetData │ - * │ MANAGED │ UpdateTextureFromBuffer │ memcpy │ memcpy │ memcpy │ - * │ SYSTEMMEM │ UpdateSurface │ memcpy │ memcpy │ memcpy │ - * │ SCRATCH │ memcpy + UpdateSurface │ memcpy │ memcpy │ memcpy │ - * └────────────┴───────────────────────────┴───────────────────────┴───────────────────────┴──────────────────────┘ + * ┌────────────┬───────────────────────────┬───────────────────────┬───────────────────────┬──────────────────────┐ + * │ Src/Dst │ DEFAULT │ MANAGED │ SYSTEMMEM │ SCRATCH │ + * ├────────────┼───────────────────────────┼───────────────────────┼───────────────────────┼──────────────────────┤ + * │ DEFAULT │ StretchRect │ GetRenderTargetData │ GetRenderTargetData │ GetRenderTargetData │ + * │ MANAGED │ UpdateTextureFromBuffer │ memcpy │ memcpy │ memcpy │ + * │ SYSTEMMEM │ UpdateSurface │ memcpy │ memcpy │ memcpy │ + * │ SCRATCH │ memcpy + UpdateSurface │ memcpy │ memcpy │ memcpy │ + * └────────────┴───────────────────────────┴───────────────────────┴───────────────────────┴──────────────────────┘ */ HRESULT STDMETHODCALLTYPE D3D8Device::CopyRects( IDirect3DSurface8* pSourceSurface, @@ -1024,8 +1028,8 @@ namespace dxvk { // needs to be readjusted and reset. StateChange(); res = GetD3D9()->SetRenderTarget(0, D3D8Surface::GetD3D9Nullable(surf)); - - if (unlikely(FAILED(res))) return res; + if (unlikely(FAILED(res))) + return res; m_renderTarget = surf; } @@ -1038,13 +1042,13 @@ namespace dxvk { if (m_renderTarget != nullptr && zStencil != nullptr) { D3DSURFACE_DESC rtDesc; res = m_renderTarget->GetDesc(&rtDesc); - - if (unlikely(FAILED(res))) return res; + if (unlikely(FAILED(res))) + return res; D3DSURFACE_DESC dsDesc; res = zStencil->GetDesc(&dsDesc); - - if (unlikely(FAILED(res))) return res; + if (unlikely(FAILED(res))) + return res; if (unlikely(dsDesc.Width < rtDesc.Width || dsDesc.Height < rtDesc.Height)) @@ -1070,18 +1074,16 @@ namespace dxvk { return D3DERR_INVALIDCALL; if (unlikely(m_renderTarget == nullptr)) { - Com pRT9 = nullptr; - HRESULT res = GetD3D9()->GetRenderTarget(0, &pRT9); // use RT index 0 - - if (likely(SUCCEEDED(res))) { - m_renderTarget = new D3D8Surface(this, D3DPOOL_DEFAULT, std::move(pRT9)); - *ppRenderTarget = m_renderTarget.ref(); - } + Com pRT9; + HRESULT res = GetD3D9()->GetRenderTarget(0, &pRT9); + if (unlikely(FAILED(res))) + return res; - return res; + m_renderTarget = new D3D8Surface(this, D3DPOOL_DEFAULT, std::move(pRT9)); } *ppRenderTarget = m_renderTarget.ref(); + return D3D_OK; } @@ -1094,24 +1096,27 @@ namespace dxvk { return D3DERR_INVALIDCALL; if (unlikely(m_depthStencil == nullptr)) { - Com pStencil9 = nullptr; + Com pStencil9; HRESULT res = GetD3D9()->GetDepthStencilSurface(&pStencil9); + if (unlikely(FAILED(res))) + return res; - if (likely(SUCCEEDED(res))) { - m_depthStencil = new D3D8Surface(this, D3DPOOL_DEFAULT, std::move(pStencil9)); - *ppZStencilSurface = m_depthStencil.ref(); - } - - return res; + m_depthStencil = new D3D8Surface(this, D3DPOOL_DEFAULT, std::move(pStencil9)); } *ppZStencilSurface = m_depthStencil.ref(); + return D3D_OK; } - HRESULT STDMETHODCALLTYPE D3D8Device::BeginScene() { return GetD3D9()->BeginScene(); } + HRESULT STDMETHODCALLTYPE D3D8Device::BeginScene() { + return GetD3D9()->BeginScene(); + } - HRESULT STDMETHODCALLTYPE D3D8Device::EndScene() { StateChange(); return GetD3D9()->EndScene(); } + HRESULT STDMETHODCALLTYPE D3D8Device::EndScene() { + StateChange(); + return GetD3D9()->EndScene(); + } HRESULT STDMETHODCALLTYPE D3D8Device::Clear( DWORD Count, @@ -1238,16 +1243,16 @@ namespace dxvk { Com pStateBlock9; HRESULT res = GetD3D9()->CreateStateBlock(d3d9::D3DSTATEBLOCKTYPE(Type), &pStateBlock9); + if (unlikely(FAILED(res))) + return res; - if (likely(SUCCEEDED(res))) { - m_token++; - m_stateBlocks.emplace(std::piecewise_construct, - std::forward_as_tuple(m_token), - std::forward_as_tuple(this, stateBlockType, pStateBlock9.ptr())); - *pToken = m_token; - } + m_token++; + m_stateBlocks.emplace(std::piecewise_construct, + std::forward_as_tuple(m_token), + std::forward_as_tuple(this, stateBlockType, pStateBlock9.ptr())); + *pToken = m_token; - return res; + return D3D_OK; } HRESULT STDMETHODCALLTYPE D3D8Device::CaptureStateBlock(DWORD Token) { @@ -1258,7 +1263,6 @@ namespace dxvk { return D3DERR_INVALIDCALL; auto stateBlockIter = m_stateBlocks.find(Token); - if (unlikely(stateBlockIter == m_stateBlocks.end())) { Logger::warn(str::format("D3D8Device::CaptureStateBlock: Invalid token: ", std::hex, Token)); return D3D_OK; @@ -1277,7 +1281,6 @@ namespace dxvk { StateChange(); auto stateBlockIter = m_stateBlocks.find(Token); - if (unlikely(stateBlockIter == m_stateBlocks.end())) { Logger::warn(str::format("D3D8Device::ApplyStateBlock: Invalid token: ", std::hex, Token)); return D3D_OK; @@ -1294,7 +1297,6 @@ namespace dxvk { return D3DERR_INVALIDCALL; auto stateBlockIter = m_stateBlocks.find(Token); - if (unlikely(stateBlockIter == m_stateBlocks.end())) { Logger::warn(str::format("D3D8Device::DeleteStateBlock: Invalid token: ", std::hex, Token)); return D3D_OK; @@ -1318,17 +1320,17 @@ namespace dxvk { return D3DERR_INVALIDCALL; HRESULT res = GetD3D9()->BeginStateBlock(); + if (unlikely(FAILED(res))) + return res; - if (likely(SUCCEEDED(res))) { - m_token++; - auto stateBlockIterPair = m_stateBlocks.emplace(std::piecewise_construct, - std::forward_as_tuple(m_token), - std::forward_as_tuple(this)); - m_recorder = &stateBlockIterPair.first->second; - m_recorderToken = m_token; - } + m_token++; + auto stateBlockIterPair = m_stateBlocks.emplace(std::piecewise_construct, + std::forward_as_tuple(m_token), + std::forward_as_tuple(this)); + m_recorder = &stateBlockIterPair.first->second; + m_recorderToken = m_token; - return res; + return D3D_OK; } HRESULT STDMETHODCALLTYPE D3D8Device::EndStateBlock(DWORD* pToken) { @@ -1339,17 +1341,17 @@ namespace dxvk { Com pStateBlock; HRESULT res = GetD3D9()->EndStateBlock(&pStateBlock); + if (unlikely(FAILED(res))) + return res; - if (likely(SUCCEEDED(res))) { - m_recorder->SetD3D9(std::move(pStateBlock)); + m_recorder->SetD3D9(std::move(pStateBlock)); - *pToken = m_recorderToken; + *pToken = m_recorderToken; - m_recorder = nullptr; - m_recorderToken = 0; - } + m_recorder = nullptr; + m_recorderToken = 0; - return res; + return D3D_OK; } HRESULT STDMETHODCALLTYPE D3D8Device::SetClipStatus(const D3DCLIPSTATUS8* pClipStatus) { @@ -1383,7 +1385,9 @@ namespace dxvk { if (unlikely(ShouldRecord())) return m_recorder->SetTexture(Stage, pTexture); - D3D8Texture2D* tex = static_cast(pTexture); + const bool isValidTexture = !m_d3d8Options.textureUAFGuard + || m_validTextures.find(pTexture) != m_validTextures.end(); + D3D8Texture2D* tex = isValidTexture ? static_cast(pTexture) : nullptr; // Splinter Cell: Force perspective divide when a shadow map is bound to slot 0 if (unlikely(m_d3d8Options.shadowPerspectiveDivide && Stage == 0)) { @@ -1411,11 +1415,12 @@ namespace dxvk { StateChange(); HRESULT res = GetD3D9()->SetTexture(Stage, D3D8Texture2D::GetD3D9Nullable(tex)); + if (unlikely(FAILED(res))) + return res; - if (likely(SUCCEEDED(res))) - m_textures[Stage] = tex; + m_textures[Stage] = tex; - return res; + return D3D_OK; } HRESULT STDMETHODCALLTYPE D3D8Device::GetTextureStageState( @@ -1427,8 +1432,7 @@ namespace dxvk { if (stateType != -1u) { // if the type has been remapped to a sampler state type: return GetD3D9()->GetSamplerState(Stage, stateType, pValue); - } - else { + } else { return GetD3D9()->GetTextureStageState(Stage, d3d9::D3DTEXTURESTAGESTATETYPE(Type), pValue); } } @@ -1498,7 +1502,8 @@ namespace dxvk { return GetD3D9()->DrawIndexedPrimitive( d3d9::D3DPRIMITIVETYPE(PrimitiveType), - static_cast(std::min(m_baseVertexIndex, static_cast(std::numeric_limits::max()))), // set by SetIndices + static_cast(std::min(m_baseVertexIndex, // set by SetIndices() + static_cast(std::numeric_limits::max()))), MinVertexIndex, NumVertices, StartIndex, @@ -1517,7 +1522,11 @@ namespace dxvk { // Stream 0 is set to null by this call m_streams[0] = D3D8VBO {nullptr, 0}; - return GetD3D9()->DrawPrimitiveUP(d3d9::D3DPRIMITIVETYPE(PrimitiveType), PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride); + return GetD3D9()->DrawPrimitiveUP( + d3d9::D3DPRIMITIVETYPE(PrimitiveType), + PrimitiveCount, + pVertexStreamZeroData, + VertexStreamZeroStride); } HRESULT STDMETHODCALLTYPE D3D8Device::DrawIndexedPrimitiveUP( @@ -1556,6 +1565,7 @@ namespace dxvk { IDirect3DVertexBuffer8* pDestBuffer, DWORD Flags) { D3D8VertexBuffer* buffer = static_cast(pDestBuffer); + return GetD3D9()->ProcessVertices( SrcStartIndex, DestIndex, @@ -1593,18 +1603,18 @@ namespace dxvk { D3D8VertexBuffer* buffer = static_cast(pStreamData); HRESULT res = GetD3D9()->SetStreamSource(StreamNumber, D3D8VertexBuffer::GetD3D9Nullable(buffer), 0, Stride); + if (unlikely(FAILED(res))) + return res; - if (likely(SUCCEEDED(res))) { - if (unlikely(ShouldBatch())) - m_batcher->SetStream(StreamNumber, buffer, Stride); + if (unlikely(ShouldBatch())) + m_batcher->SetStream(StreamNumber, buffer, Stride); - m_streams[StreamNumber].buffer = buffer; - // The previous stride is preserved if pStreamData is NULL - if (likely(buffer != nullptr)) - m_streams[StreamNumber].stride = Stride; - } + m_streams[StreamNumber].buffer = buffer; + // The previous stride is preserved if pStreamData is NULL + if (likely(buffer != nullptr)) + m_streams[StreamNumber].stride = Stride; - return res; + return D3D_OK; } HRESULT STDMETHODCALLTYPE D3D8Device::GetStreamSource( @@ -1643,17 +1653,17 @@ namespace dxvk { D3D8IndexBuffer* buffer = static_cast(pIndexData); HRESULT res = GetD3D9()->SetIndices(D3D8IndexBuffer::GetD3D9Nullable(buffer)); + if (unlikely(FAILED(res))) + return res; - if (likely(SUCCEEDED(res))) { - if (unlikely(ShouldBatch())) - m_batcher->SetIndices(buffer, BaseVertexIndex); + if (unlikely(ShouldBatch())) + m_batcher->SetIndices(buffer, BaseVertexIndex); - m_indices = buffer; - // used by DrawIndexedPrimitive - m_baseVertexIndex = BaseVertexIndex; - } + m_indices = buffer; + // used by DrawIndexedPrimitive + m_baseVertexIndex = BaseVertexIndex; - return res; + return D3D_OK; } HRESULT STDMETHODCALLTYPE D3D8Device::GetIndices( @@ -1706,7 +1716,7 @@ namespace dxvk { HRESULT STDMETHODCALLTYPE D3D8Device::SetRenderState(D3DRENDERSTATETYPE State, DWORD Value) { D3D8DeviceLock lock = LockDevice(); - d3d9::D3DRENDERSTATETYPE State9 = (d3d9::D3DRENDERSTATETYPE)State; + d3d9::D3DRENDERSTATETYPE State9 = d3d9::D3DRENDERSTATETYPE(State); switch (State) { // Most render states translate 1:1 to D3D9 @@ -1781,7 +1791,7 @@ namespace dxvk { if (unlikely(pValue == nullptr)) return D3DERR_INVALIDCALL; - d3d9::D3DRENDERSTATETYPE State9 = (d3d9::D3DRENDERSTATETYPE)State; + d3d9::D3DRENDERSTATETYPE State9 = d3d9::D3DRENDERSTATETYPE(State); switch (State) { // Most render states translate 1:1 to D3D9 @@ -1822,8 +1832,6 @@ namespace dxvk { return GetD3D9()->GetRenderState(State9, pValue); } - // Vertex Shaders // - HRESULT STDMETHODCALLTYPE D3D8Device::CreateVertexShader( const DWORD* pDeclaration, const DWORD* pFunction, @@ -1848,46 +1856,43 @@ namespace dxvk { Com pVertexShader; if (pFunction != nullptr) { res = GetD3D9()->CreateVertexShader(translatedVS.function.data(), &pVertexShader); + if (unlikely(FAILED(res))) + return res; } else { // pFunction is NULL: fixed function pipeline pVertexShader = nullptr; } - if (likely(SUCCEEDED(res))) { - D3D8VertexShaderInfo& info = m_vertexShaders.emplace_back(); - - info.pVertexDecl = std::move(pVertexDecl); - info.pVertexShader = std::move(pVertexShader); + D3D8VertexShaderInfo& info = m_vertexShaders.emplace_back(); - // Store D3D8 bytecodes in the shader info - for (uint32_t i = 0; pDeclaration[i] != D3DVSD_END(); i++) - info.declaration.push_back(pDeclaration[i]); - info.declaration.push_back(D3DVSD_END()); + info.pVertexDecl = std::move(pVertexDecl); + info.pVertexShader = std::move(pVertexShader); - if (pFunction != nullptr) { - for (uint32_t i = 0; pFunction[i] != D3DVS_END(); i++) - info.function.push_back(pFunction[i]); - info.function.push_back(D3DVS_END()); - } + // Store D3D8 bytecodes in the shader info + for (uint32_t i = 0; pDeclaration[i] != D3DVSD_END(); i++) + info.declaration.push_back(pDeclaration[i]); + info.declaration.push_back(D3DVSD_END()); - // Set bit to indicate this is not an FVF - *pHandle = getShaderHandle(m_vertexShaders.size()); + if (pFunction != nullptr) { + for (uint32_t i = 0; pFunction[i] != D3DVS_END(); i++) + info.function.push_back(pFunction[i]); + info.function.push_back(D3DVS_END()); } - return res; + // Set bit to indicate this is not an FVF + *pHandle = getShaderHandle(m_vertexShaders.size()); + + return D3D_OK; } inline D3D8VertexShaderInfo* getVertexShaderInfo(D3D8Device* device, DWORD Handle) { - Handle = getShaderIndex(Handle); - if (unlikely(Handle >= device->m_vertexShaders.size())) { Logger::debug(str::format("D3D8: Invalid vertex shader index ", std::hex, Handle)); return nullptr; } D3D8VertexShaderInfo& info = device->m_vertexShaders[Handle]; - if (unlikely(info.pVertexDecl == nullptr && info.pVertexShader == nullptr)) { Logger::debug(str::format("D3D8: Application provided deleted vertex shader ", std::hex, Handle)); return nullptr; @@ -1907,7 +1912,6 @@ namespace dxvk { // Check for extra bit that indicates this is not an FVF if (!isFVF(Handle)) { - D3D8VertexShaderInfo* info = getVertexShaderInfo(this, Handle); if (!info) @@ -1917,27 +1921,21 @@ namespace dxvk { GetD3D9()->SetVertexDeclaration(info->pVertexDecl.ptr()); res = GetD3D9()->SetVertexShader(info->pVertexShader.ptr()); + if (unlikely(FAILED(res))) + return res; - if (likely(SUCCEEDED(res))) { - // Cache current shader - m_currentVertexShader = Handle; - } - - return res; - + m_currentVertexShader = Handle; } else if (m_currentVertexShader != Handle) { StateChange(); //GetD3D9()->SetVertexDeclaration(nullptr); GetD3D9()->SetVertexShader(nullptr); res = GetD3D9()->SetFVF(Handle); + if (unlikely(FAILED(res))) + return res; - if (likely(SUCCEEDED(res))) { - // Cache current FVF - m_currentVertexShader = Handle; - } - - return res; + // Cache current FVF + m_currentVertexShader = Handle; } return D3D_OK; @@ -1959,7 +1957,6 @@ namespace dxvk { d3d9::IDirect3DVertexShader9* pVertexShader; HRESULT res = GetD3D9()->GetVertexShader(&pVertexShader); - if (FAILED(res) || pVertexShader == nullptr) { return GetD3D9()->GetFVF(pHandle); } @@ -1969,11 +1966,11 @@ namespace dxvk { if (info.pVertexShader == pVertexShader) { *pHandle = getShaderHandle(i); - return res; + return D3D_OK; } } - return res; + return D3D_OK; */ } @@ -2071,18 +2068,17 @@ namespace dxvk { Com pPixelShader; HRESULT res = GetD3D9()->CreatePixelShader(pFunction, &pPixelShader); + if (unlikely(FAILED(res))) + return res; - if (likely(SUCCEEDED(res))) { - m_pixelShaders.push_back(std::move(pPixelShader)); - // Still set the shader bit, to prevent conflicts with NULL. - *pHandle = getShaderHandle(m_pixelShaders.size()); - } + m_pixelShaders.push_back(std::move(pPixelShader)); + // Still set the shader bit, to prevent conflicts with NULL. + *pHandle = getShaderHandle(m_pixelShaders.size()); - return res; + return D3D_OK; } inline d3d9::IDirect3DPixelShader9* getPixelShaderPtr(D3D8Device* device, DWORD Handle) { - Handle = getShaderIndex(Handle); if (unlikely(Handle >= device->m_pixelShaders.size())) { @@ -2121,13 +2117,13 @@ namespace dxvk { StateChange(); HRESULT res = GetD3D9()->SetPixelShader(pPixelShader); + if (unlikely(FAILED(res))) + return res; - if (likely(SUCCEEDED(res))) { - // Cache current pixel shader - m_currentPixelShader = Handle; - } + // Cache current pixel shader + m_currentPixelShader = Handle; - return res; + return D3D_OK; } HRESULT STDMETHODCALLTYPE D3D8Device::GetPixelShader(DWORD* pHandle) { diff --git a/src/d3d8/d3d8_device.h b/src/d3d8/d3d8_device.h index fe9ec844ec2..73a173de6e4 100644 --- a/src/d3d8/d3d8_device.h +++ b/src/d3d8/d3d8_device.h @@ -6,7 +6,7 @@ #include "d3d8_buffer.h" #include "d3d8_swapchain.h" #include "d3d8_state_block.h" -#include "d3d8_d3d9_util.h" +#include "d3d8_util.h" #include "d3d8_caps.h" #include "d3d8_batch.h" @@ -15,6 +15,7 @@ #include #include #include +#include #include namespace dxvk { @@ -383,7 +384,7 @@ namespace dxvk { m_presentParams.BackBufferCount = std::max(m_presentParams.BackBufferCount, 1u); // Reset D3D8 exclusive render states - m_linePattern = {}; + m_linePattern = { }; m_zVisible = 0; // Purge cached objects @@ -418,6 +419,14 @@ namespace dxvk { m_depthStencil = m_autoDepthStencil; } + void RemoveValidTexture(IDirect3DBaseTexture8* tex) { + D3D8DeviceLock lock = LockDevice(); + + auto textureIter = m_validTextures.find(tex); + if (likely(textureIter != m_validTextures.end())) + m_validTextures.erase(textureIter); + } + friend d3d9::IDirect3DPixelShader9* getPixelShaderPtr(D3D8Device* device, DWORD Handle); friend D3D8VertexShaderInfo* getVertexShaderInfo(D3D8Device* device, DWORD Handle); @@ -431,39 +440,41 @@ namespace dxvk { D3DPRESENT_PARAMETERS m_presentParams; // Value of D3DRS_LINEPATTERN - D3DLINEPATTERN m_linePattern = {}; + D3DLINEPATTERN m_linePattern = { }; // Value of D3DRS_ZVISIBLE (although the RS is not supported, its value is stored) - DWORD m_zVisible = 0; + DWORD m_zVisible = 0; bool m_shadowPerspectiveDivide = false; - D3D8StateBlock* m_recorder = nullptr; - DWORD m_recorderToken = 0; - DWORD m_token = 0; - std::unordered_map m_stateBlocks; - D3D8Batcher* m_batcher = nullptr; + D3D8StateBlock* m_recorder = nullptr; + DWORD m_recorderToken = 0; + DWORD m_token = 0; + std::unordered_map m_stateBlocks; + D3D8Batcher* m_batcher = nullptr; struct D3D8VBO { Com buffer = nullptr; UINT stride = 0; }; - std::array, d8caps::MAX_TEXTURE_STAGES> m_textures; - std::array m_streams; + std::array, d8caps::MAX_TEXTURE_STAGES> m_textures; + std::array m_streams; + + std::unordered_set m_validTextures; - Com m_indices; - UINT m_baseVertexIndex = 0; + Com m_indices; + UINT m_baseVertexIndex = 0; std::vector> m_backBuffers; Com m_autoDepthStencil; - Com m_renderTarget; - Com m_depthStencil; + Com m_renderTarget; + Com m_depthStencil; - std::vector m_vertexShaders; - std::vector> m_pixelShaders; - DWORD m_currentVertexShader = 0; // can be FVF or vs index (marked by D3DFVF_RESERVED0) - DWORD m_currentPixelShader = 0; + std::vector m_vertexShaders; + std::vector> m_pixelShaders; + DWORD m_currentVertexShader = 0; // can be FVF or vs index (marked by D3DFVF_RESERVED0) + DWORD m_currentPixelShader = 0; D3DDEVTYPE m_deviceType; HWND m_window; diff --git a/src/d3d8/d3d8_device_child.h b/src/d3d8/d3d8_device_child.h index fe9d0640119..c1b99094539 100644 --- a/src/d3d8/d3d8_device_child.h +++ b/src/d3d8/d3d8_device_child.h @@ -34,7 +34,7 @@ namespace dxvk { uint32_t oldRefCount, refCount; do { - oldRefCount = this->m_refCount.load(std::memory_order_acquire); + oldRefCount = this->m_refCount.load(); // clamp value to 0 to prevent underruns if (unlikely(!oldRefCount)) @@ -42,10 +42,7 @@ namespace dxvk { refCount = oldRefCount - 1; - } while (!this->m_refCount.compare_exchange_weak(oldRefCount, - refCount, - std::memory_order_release, - std::memory_order_acquire)); + } while (!this->m_refCount.compare_exchange_weak(oldRefCount, refCount)); if (unlikely(!refCount)) { auto* pDevice = GetDevice(); @@ -63,6 +60,7 @@ namespace dxvk { return D3DERR_INVALIDCALL; *ppDevice = ref(GetDevice()); + return D3D_OK; } diff --git a/src/d3d8/d3d8_include.h b/src/d3d8/d3d8_include.h index fc2cda77e26..86e077eaf61 100644 --- a/src/d3d8/d3d8_include.h +++ b/src/d3d8/d3d8_include.h @@ -12,18 +12,18 @@ // Declare __uuidof for D3D8 interfaces #ifdef __CRT_UUID_DECL -__CRT_UUID_DECL(IDirect3D8, 0x1DD9E8DA,0x1C77,0x4D40,0xB0,0xCF,0x98,0xFE,0xFD,0xFF,0x95,0x12); -__CRT_UUID_DECL(IDirect3DDevice8, 0x7385E5DF,0x8FE8,0x41D5,0x86,0xB6,0xD7,0xB4,0x85,0x47,0xB6,0xCF); -__CRT_UUID_DECL(IDirect3DResource8, 0x1B36BB7B,0x09B7,0x410A,0xB4,0x45,0x7D,0x14,0x30,0xD7,0xB3,0x3F); -__CRT_UUID_DECL(IDirect3DVertexBuffer8, 0x8AEEEAC7,0x05F9,0x44D4,0xB5,0x91,0x00,0x0B,0x0D,0xF1,0xCB,0x95); -__CRT_UUID_DECL(IDirect3DVolume8, 0xBD7349F5,0x14F1,0x42E4,0x9C,0x79,0x97,0x23,0x80,0xDB,0x40,0xC0); -__CRT_UUID_DECL(IDirect3DSwapChain8, 0x928C088B,0x76B9,0x4C6B,0xA5,0x36,0xA5,0x90,0x85,0x38,0x76,0xCD); -__CRT_UUID_DECL(IDirect3DSurface8, 0xB96EEBCA,0xB326,0x4EA5,0x88,0x2F,0x2F,0xF5,0xBA,0xE0,0x21,0xDD); -__CRT_UUID_DECL(IDirect3DIndexBuffer8, 0x0E689C9A,0x053D,0x44A0,0x9D,0x92,0xDB,0x0E,0x3D,0x75,0x0F,0x86); -__CRT_UUID_DECL(IDirect3DBaseTexture8, 0xB4211CFA,0x51B9,0x4A9F,0xAB,0x78,0xDB,0x99,0xB2,0xBB,0x67,0x8E); -__CRT_UUID_DECL(IDirect3DTexture8, 0xE4CDD575,0x2866,0x4F01,0xB1,0x2E,0x7E,0xEC,0xE1,0xEC,0x93,0x58); -__CRT_UUID_DECL(IDirect3DCubeTexture8, 0x3EE5B968,0x2ACA,0x4C34,0x8B,0xB5,0x7E,0x0C,0x3D,0x19,0xB7,0x50); -__CRT_UUID_DECL(IDirect3DVolumeTexture8, 0x4B8AAAFA,0x140F,0x42BA,0x91,0x31,0x59,0x7E,0xAF,0xAA,0x2E,0xAD); +__CRT_UUID_DECL(IDirect3D8, 0x1DD9E8DA, 0x1C77, 0x4D40, 0xB0, 0xCF, 0x98, 0xFE, 0xFD, 0xFF, 0x95, 0x12); +__CRT_UUID_DECL(IDirect3DDevice8, 0x7385E5DF, 0x8FE8, 0x41D5, 0x86, 0xB6, 0xD7, 0xB4, 0x85, 0x47, 0xB6, 0xCF); +__CRT_UUID_DECL(IDirect3DResource8, 0x1B36BB7B, 0x09B7, 0x410A, 0xB4, 0x45, 0x7D, 0x14, 0x30, 0xD7, 0xB3, 0x3F); +__CRT_UUID_DECL(IDirect3DVertexBuffer8, 0x8AEEEAC7, 0x05F9, 0x44D4, 0xB5, 0x91, 0x00, 0x0B, 0x0D, 0xF1, 0xCB, 0x95); +__CRT_UUID_DECL(IDirect3DVolume8, 0xBD7349F5, 0x14F1, 0x42E4, 0x9C, 0x79, 0x97, 0x23, 0x80, 0xDB, 0x40, 0xC0); +__CRT_UUID_DECL(IDirect3DSwapChain8, 0x928C088B, 0x76B9, 0x4C6B, 0xA5, 0x36, 0xA5, 0x90, 0x85, 0x38, 0x76, 0xCD); +__CRT_UUID_DECL(IDirect3DSurface8, 0xB96EEBCA, 0xB326, 0x4EA5, 0x88, 0x2F, 0x2F, 0xF5, 0xBA, 0xE0, 0x21, 0xDD); +__CRT_UUID_DECL(IDirect3DIndexBuffer8, 0x0E689C9A, 0x053D, 0x44A0, 0x9D, 0x92, 0xDB, 0x0E, 0x3D, 0x75, 0x0F, 0x86); +__CRT_UUID_DECL(IDirect3DBaseTexture8, 0xB4211CFA, 0x51B9, 0x4A9F, 0xAB, 0x78, 0xDB, 0x99, 0xB2, 0xBB, 0x67, 0x8E); +__CRT_UUID_DECL(IDirect3DTexture8, 0xE4CDD575, 0x2866, 0x4F01, 0xB1, 0x2E, 0x7E, 0xEC, 0xE1, 0xEC, 0x93, 0x58); +__CRT_UUID_DECL(IDirect3DCubeTexture8, 0x3EE5B968, 0x2ACA, 0x4C34, 0x8B, 0xB5, 0x7E, 0x0C, 0x3D, 0x19, 0xB7, 0x50); +__CRT_UUID_DECL(IDirect3DVolumeTexture8, 0x4B8AAAFA, 0x140F, 0x42BA, 0x91, 0x31, 0x59, 0x7E, 0xAF, 0xAA, 0x2E, 0xAD); #elif defined(_MSC_VER) interface DECLSPEC_UUID("1DD9E8DA-1C77-4D40-B0CF-98FEFDFF9512") IDirect3D8; interface DECLSPEC_UUID("7385E5DF-8FE8-41D5-86B6-D7B48547B6CF") IDirect3DDevice8; @@ -56,31 +56,13 @@ interface DECLSPEC_UUID("4B8AAAFA-140F-42BA-9131-597EAFAA2EAD") IDirect3DVolumeT #define D3DRECT_DEFINED #define D3DMATRIX_DEFINED -// Temporarily override __CRT_UUID_DECL to allow usage in d3d9 namespace +// Temporarily undefine __CRT_UUID_DECL +// to allow imports in the d3d9 namespace #pragma push_macro("__CRT_UUID_DECL") #ifdef __CRT_UUID_DECL #undef __CRT_UUID_DECL #endif -#ifdef __MINGW32__ -#define __CRT_UUID_DECL(type,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ -} \ - extern "C++" template<> struct __mingw_uuidof_s { static constexpr IID __uuid_inst = {l,w1,w2, {b1,b2,b3,b4,b5,b6,b7,b8}}; }; \ - extern "C++" template<> constexpr const GUID &__mingw_uuidof() { return __mingw_uuidof_s::__uuid_inst; } \ - extern "C++" template<> constexpr const GUID &__mingw_uuidof() { return __mingw_uuidof_s::__uuid_inst; } \ -namespace d3d9 { - -#elif defined(__GNUC__) -#define __CRT_UUID_DECL(type, a, b, c, d, e, f, g, h, i, j, k) \ -} \ - extern "C++" { template <> constexpr GUID __uuidof_helper() { return GUID{a,b,c,{d,e,f,g,h,i,j,k}}; } } \ - extern "C++" { template <> constexpr GUID __uuidof_helper() { return __uuidof_helper(); } } \ - extern "C++" { template <> constexpr GUID __uuidof_helper() { return __uuidof_helper(); } } \ - extern "C++" { template <> constexpr GUID __uuidof_helper() { return __uuidof_helper(); } } \ - extern "C++" { template <> constexpr GUID __uuidof_helper() { return __uuidof_helper(); } } \ -namespace d3d9 { -#endif - #endif // defined(__MINGW32__) || defined(__GNUC__) @@ -98,10 +80,37 @@ namespace d3d9 { // Indicates d3d9:: namespace is in-use. #define DXVK_D3D9_NAMESPACE + #if defined(__MINGW32__) || defined(__GNUC__) #pragma pop_macro("__CRT_UUID_DECL") + +// Declare __uuidof for D3D9 interfaces, directly within the d3d9:: namespace +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(d3d9::IDirect3D9, 0x81BDCBCA, 0x64D4, 0x426D, 0xAE, 0x8D, 0xAD, 0x01, 0x47, 0xF4, 0x27, 0x5C); +__CRT_UUID_DECL(d3d9::IDirect3DVolume9, 0x24F416E6, 0x1F67, 0x4AA7, 0xB8, 0x8E, 0xD3, 0x3F, 0x6F, 0x31, 0x28, 0xA1); +__CRT_UUID_DECL(d3d9::IDirect3DSwapChain9, 0x794950F2, 0xADFC, 0x458A, 0x90, 0x5E, 0x10, 0xA1, 0x0B, 0x0B, 0x50, 0x3B); +__CRT_UUID_DECL(d3d9::IDirect3DResource9, 0x05EEC05D, 0x8F7D, 0x4362, 0xB9, 0x99, 0xD1, 0xBA, 0xF3, 0x57, 0xC7, 0x04); +__CRT_UUID_DECL(d3d9::IDirect3DSurface9, 0x0CFBAF3A, 0x9FF6, 0x429A, 0x99, 0xB3, 0xA2, 0x79, 0x6A, 0xF8, 0xB8, 0x9B); +__CRT_UUID_DECL(d3d9::IDirect3DVertexBuffer9, 0xB64BB1B5, 0xFD70, 0x4DF6, 0xBF, 0x91, 0x19, 0xD0, 0xA1, 0x24, 0x55, 0xE3); +__CRT_UUID_DECL(d3d9::IDirect3DIndexBuffer9, 0x7C9DD65E, 0xD3F7, 0x4529, 0xAC, 0xEE, 0x78, 0x58, 0x30, 0xAC, 0xDE, 0x35); +__CRT_UUID_DECL(d3d9::IDirect3DBaseTexture9, 0x580CA87E, 0x1D3C, 0x4D54, 0x99, 0x1D, 0xB7, 0xD3, 0xE3, 0xC2, 0x98, 0xCE); +__CRT_UUID_DECL(d3d9::IDirect3DCubeTexture9, 0xFFF32F81, 0xD953, 0x473A, 0x92, 0x23, 0x93, 0xD6, 0x52, 0xAB, 0xA9, 0x3F); +__CRT_UUID_DECL(d3d9::IDirect3DTexture9, 0x85C31227, 0x3DE5, 0x4F00, 0x9B, 0x3A, 0xF1, 0x1A, 0xC3, 0x8C, 0x18, 0xB5); +__CRT_UUID_DECL(d3d9::IDirect3DVolumeTexture9, 0x2518526C, 0xE789, 0x4111, 0xA7, 0xB9, 0x47, 0xEF, 0x32, 0x8D, 0x13, 0xE6); +__CRT_UUID_DECL(d3d9::IDirect3DVertexDeclaration9, 0xDD13C59C, 0x36FA, 0x4098, 0xA8, 0xFB, 0xC7, 0xED, 0x39, 0xDC, 0x85, 0x46); +__CRT_UUID_DECL(d3d9::IDirect3DVertexShader9, 0xEFC5557E, 0x6265, 0x4613, 0x8A, 0x94, 0x43, 0x85, 0x78, 0x89, 0xEB, 0x36); +__CRT_UUID_DECL(d3d9::IDirect3DPixelShader9, 0x6D3BDBDC, 0x5B02, 0x4415, 0xB8, 0x52, 0xCE, 0x5E, 0x8B, 0xCC, 0xB2, 0x89); +__CRT_UUID_DECL(d3d9::IDirect3DStateBlock9, 0xB07C4FE5, 0x310D, 0x4BA8, 0xA2, 0x3C, 0x4F, 0x0F, 0x20, 0x6F, 0x21, 0x8B); +__CRT_UUID_DECL(d3d9::IDirect3DQuery9, 0xD9771460, 0xA695, 0x4F26, 0xBB, 0xD3, 0x27, 0xB8, 0x40, 0xB5, 0x41, 0xCC); +__CRT_UUID_DECL(d3d9::IDirect3DDevice9, 0xD0223B96, 0xBF7A, 0x43FD, 0x92, 0xBD, 0xA4, 0x3B, 0x0D, 0x82, 0xB9, 0xEB); +__CRT_UUID_DECL(d3d9::IDirect3D9Ex, 0x02177241, 0x69FC, 0x400C, 0x8F, 0xF1, 0x93, 0xA4, 0x4D, 0xF6, 0x86, 0x1D); +__CRT_UUID_DECL(d3d9::IDirect3DSwapChain9Ex, 0x91886CAF, 0x1C3D, 0x4D2E, 0xA0, 0xAB, 0x3E, 0x4C, 0x7D, 0x8D, 0x33, 0x03); +__CRT_UUID_DECL(d3d9::IDirect3DDevice9Ex, 0xB18B10CE, 0x2649, 0x405A, 0x87, 0x0F, 0x95, 0xF7, 0x77, 0xD4, 0x31, 0x3A); #endif +#endif // defined(__MINGW32__) || defined(__GNUC__) + + //for some reason we need to specify __declspec(dllexport) for MinGW #if defined(__WINE__) || !defined(_WIN32) #define DLLEXPORT __attribute__((visibility("default"))) diff --git a/src/d3d8/d3d8_interface.cpp b/src/d3d8/d3d8_interface.cpp index 2eccaba60f8..a68f0cc4c4c 100644 --- a/src/d3d8/d3d8_interface.cpp +++ b/src/d3d8/d3d8_interface.cpp @@ -27,7 +27,6 @@ namespace dxvk { // cache adapter modes and mode counts for each d3d9 format for (d3d9::D3DFORMAT fmt : ADAPTER_FORMATS) { - const UINT modeCount = m_d3d9->GetAdapterModeCount(adapter, fmt); for (UINT mode = 0; mode < modeCount; mode++) { @@ -74,7 +73,6 @@ namespace dxvk { d3d9::D3DADAPTER_IDENTIFIER9 identifier9; HRESULT res = m_d3d9->GetAdapterIdentifier(Adapter, Flags, &identifier9); - if (unlikely(FAILED(res))) return res; @@ -93,7 +91,7 @@ namespace dxvk { return D3D_OK; } - HRESULT __stdcall D3D8Interface::EnumAdapterModes( + HRESULT STDMETHODCALLTYPE D3D8Interface::EnumAdapterModes( UINT Adapter, UINT Mode, D3DDISPLAYMODE* pMode) { @@ -109,7 +107,7 @@ namespace dxvk { return D3D_OK; } - HRESULT __stdcall D3D8Interface::CreateDevice( + HRESULT STDMETHODCALLTYPE D3D8Interface::CreateDevice( UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, @@ -122,11 +120,10 @@ namespace dxvk { return D3DERR_INVALIDCALL; HRESULT res = ValidatePresentationParameters(pPresentationParameters); - if (unlikely(FAILED(res))) return res; - Com pDevice9 = nullptr; + Com pDevice9; d3d9::D3DPRESENT_PARAMETERS params = ConvertPresentParameters9(pPresentationParameters); res = m_d3d9->CreateDevice( Adapter, @@ -136,7 +133,6 @@ namespace dxvk { ¶ms, &pDevice9 ); - if (unlikely(FAILED(res))) return res; diff --git a/src/d3d8/d3d8_interface.h b/src/d3d8/d3d8_interface.h index 97837d05cb1..36c31bb2ca3 100644 --- a/src/d3d8/d3d8_interface.h +++ b/src/d3d8/d3d8_interface.h @@ -1,7 +1,7 @@ #pragma once #include "d3d8_include.h" -#include "d3d8_d3d9_util.h" +#include "d3d8_util.h" #include "d3d8_options.h" #include "d3d8_format.h" #include "../d3d9/d3d9_bridge.h" @@ -150,12 +150,13 @@ namespace dxvk { return D3DERR_INVALIDCALL; d3d9::D3DCAPS9 caps9; - HRESULT res = m_d3d9->GetDeviceCaps(Adapter, (d3d9::D3DDEVTYPE)DeviceType, &caps9); + HRESULT res = m_d3d9->GetDeviceCaps(Adapter, d3d9::D3DDEVTYPE(DeviceType), &caps9); + if (unlikely(FAILED(res))) + return res; - if (likely(SUCCEEDED(res))) - ConvertCaps8(caps9, pCaps); + ConvertCaps8(caps9, pCaps); - return res; + return D3D_OK; } HMONITOR STDMETHODCALLTYPE GetAdapterMonitor(UINT Adapter) { @@ -186,4 +187,4 @@ namespace dxvk { D3D8Options m_d3d8Options; }; -} +} \ No newline at end of file diff --git a/src/d3d8/d3d8_main.cpp b/src/d3d8/d3d8_main.cpp index 1e7acfb8563..30f4d20954e 100644 --- a/src/d3d8/d3d8_main.cpp +++ b/src/d3d8/d3d8_main.cpp @@ -110,7 +110,7 @@ extern "C" { const size_t errorMessageSize = errorMessage.size() + 1; // Wine tests call HeapFree() on the returned error string, // so the expectation is for it to be allocated on the heap. - *pErrorString = (char*) HeapAlloc(GetProcessHeap(), 0, errorMessageSize); + *pErrorString = static_cast(HeapAlloc(GetProcessHeap(), 0, errorMessageSize)); if (*pErrorString) memcpy(*pErrorString, errorMessage.c_str(), errorMessageSize); } diff --git a/src/d3d8/d3d8_options.cpp b/src/d3d8/d3d8_options.cpp index ea8dbc65d04..9c0bae0a6d6 100644 --- a/src/d3d8/d3d8_options.cpp +++ b/src/d3d8/d3d8_options.cpp @@ -54,4 +54,16 @@ namespace dxvk { } } + D3D8Options::D3D8Options(const Config& config) { + auto forceVsDeclStr = config.getOption("d3d8.forceVsDecl", ""); + + this->batching = config.getOption ("d3d8.batching", false); + this->placeP8InScratch = config.getOption ("d3d8.placeP8InScratch", false); + this->forceLegacyDiscard = config.getOption ("d3d8.forceLegacyDiscard", false); + this->shadowPerspectiveDivide = config.getOption ("d3d8.shadowPerspectiveDivide", false); + this->textureUAFGuard = config.getOption ("d3d8.textureUAFGuard", false); + + parseVsDecl(forceVsDeclStr); + } + } diff --git a/src/d3d8/d3d8_options.h b/src/d3d8/d3d8_options.h index 09f448cc8ea..a3778985369 100644 --- a/src/d3d8/d3d8_options.h +++ b/src/d3d8/d3d8_options.h @@ -4,10 +4,19 @@ #include "../d3d9/d3d9_bridge.h" #include "../util/config/config.h" +#include +#include + namespace dxvk { struct D3D8Options { + void parseVsDecl(const std::string& decl); + + D3D8Options() {}; + + D3D8Options(const Config& config); + /// Override application vertex shader declarations. std::vector> forceVsDecl; @@ -23,19 +32,9 @@ namespace dxvk { /// Force D3DTTFF_PROJECTED for the necessary stages when a depth texture is bound to slot 0. bool shadowPerspectiveDivide; - D3D8Options() {} - - D3D8Options(const Config& config) { - auto forceVsDeclStr = config.getOption("d3d8.forceVsDecl", ""); - batching = config.getOption ("d3d8.batching", false); - placeP8InScratch = config.getOption ("d3d8.placeP8InScratch", false); - forceLegacyDiscard = config.getOption ("d3d8.forceLegacyDiscard", false); - shadowPerspectiveDivide = config.getOption ("d3d8.shadowPerspectiveDivide", false); + /// Keep track of live texture objects and validate them during SetTexture calls. + bool textureUAFGuard; - parseVsDecl(forceVsDeclStr); - } - - void parseVsDecl(const std::string& decl); }; } diff --git a/src/d3d8/d3d8_resource.h b/src/d3d8/d3d8_resource.h index 4966adec162..e4a90a005e5 100644 --- a/src/d3d8/d3d8_resource.h +++ b/src/d3d8/d3d8_resource.h @@ -29,18 +29,16 @@ namespace dxvk { DWORD SizeOfData, DWORD Flags) final { HRESULT hr; + if (Flags & D3DSPD_IUNKNOWN) { if(unlikely(SizeOfData != sizeof(IUnknown*))) return D3DERR_INVALIDCALL; - IUnknown* unknown = - const_cast( - reinterpret_cast(pData)); - hr = m_privateData.setInterface( - refguid, unknown); + + IUnknown* unknown = const_cast(reinterpret_cast(pData)); + hr = m_privateData.setInterface(refguid, unknown); + } else { + hr = m_privateData.setData(refguid, SizeOfData, pData); } - else - hr = m_privateData.setData( - refguid, SizeOfData, pData); if (unlikely(FAILED(hr))) return D3DERR_INVALIDCALL; diff --git a/src/d3d8/d3d8_shader.cpp b/src/d3d8/d3d8_shader.cpp index 3d03dc1f3bc..c0a5397c9d9 100644 --- a/src/d3d8/d3d8_shader.cpp +++ b/src/d3d8/d3d8_shader.cpp @@ -85,13 +85,13 @@ namespace dxvk { */ constexpr DWORD encodeDestRegister(d3d9::D3DSHADER_PARAM_REGISTER_TYPE type, UINT reg) { DWORD token = 0; - token |= reg & 0x7FF; // bits 0:10 num - token |= ((type & 0x07) << 28); // bits 28:30 type[0:2] - token |= ((type & 0x18) >> 3) << 11; // bits 11:12 type[3:4] - // UINT addrMode : 1; // bit 13 hasRelative - token |= 0b1111 << 16; // bits 16:19 DxsoRegMask - // UINT resultModifier : 3; // bits 20:23 - // UINT resultShift : 3; // bits 24:27 + token |= reg & 0x7FF; // bits 0:10 num + token |= ((type & 0x07) << 28); // bits 28:30 type[0:2] + token |= ((type & 0x18) >> 3) << 11; // bits 11:12 type[3:4] + // UINT addrMode : 1; // bit 13 hasRelative + token |= 0b1111 << 16; // bits 16:19 DxsoRegMask + // UINT resultModifier : 3; // bits 20:23 + // UINT resultShift : 3; // bits 24:27 token |= 1u << 31; // bit 31 always 1 return token; } @@ -123,7 +123,6 @@ namespace dxvk { HRESULT res = D3D_OK; - std::vector& tokens = pTranslatedVS.function; std::vector defs; // Constant definitions // shaderInputRegisters: @@ -279,6 +278,8 @@ namespace dxvk { } if (pFunction != nullptr) { + std::vector& tokens = pTranslatedVS.function; + // Copy first token (version) tokens.push_back(pFunction[0]); diff --git a/src/d3d8/d3d8_shader.h b/src/d3d8/d3d8_shader.h index 5016c0e6c85..c72e624c963 100644 --- a/src/d3d8/d3d8_shader.h +++ b/src/d3d8/d3d8_shader.h @@ -5,15 +5,22 @@ namespace dxvk { - struct D3D9VertexShaderCode { - d3d9::D3DVERTEXELEMENT9 declaration[MAXD3DDECLLENGTH + 1]; - std::vector function; - }; + struct D3D9VertexShaderCode { + d3d9::D3DVERTEXELEMENT9 declaration[MAXD3DDECLLENGTH + 1]; + std::vector function; + }; - HRESULT TranslateVertexShader8( - const DWORD* pDeclaration, - const DWORD* pFunction, - const D3D8Options& overrides, - D3D9VertexShaderCode& pTranslatedVS); + struct D3D8VertexShaderInfo { + Com pVertexDecl; + Com pVertexShader; + std::vector declaration; + std::vector function; + }; + + HRESULT TranslateVertexShader8( + const DWORD* pDeclaration, + const DWORD* pFunction, + const D3D8Options& overrides, + D3D9VertexShaderCode& pTranslatedVS); } \ No newline at end of file diff --git a/src/d3d8/d3d8_state_block.h b/src/d3d8/d3d8_state_block.h index 1cfee0aaa5d..7bec260dbbb 100644 --- a/src/d3d8/d3d8_state_block.h +++ b/src/d3d8/d3d8_state_block.h @@ -140,4 +140,4 @@ namespace dxvk { }; -} +} \ No newline at end of file diff --git a/src/d3d8/d3d8_subresource.h b/src/d3d8/d3d8_subresource.h index 06fddec3fca..d47a242857b 100644 --- a/src/d3d8/d3d8_subresource.h +++ b/src/d3d8/d3d8_subresource.h @@ -57,4 +57,4 @@ namespace dxvk { }; -} +} \ No newline at end of file diff --git a/src/d3d8/d3d8_surface.cpp b/src/d3d8/d3d8_surface.cpp index 69cb1e4b43e..cb27f37b628 100644 --- a/src/d3d8/d3d8_surface.cpp +++ b/src/d3d8/d3d8_surface.cpp @@ -1,7 +1,7 @@ #include "d3d8_surface.h" #include "d3d8_device.h" -#include "d3d8_d3d9_util.h" +#include "d3d8_util.h" namespace dxvk { @@ -27,11 +27,12 @@ namespace dxvk { d3d9::D3DSURFACE_DESC desc; HRESULT res = GetD3D9()->GetDesc(&desc); + if (unlikely(FAILED(res))) + return res; - if (likely(SUCCEEDED(res))) - ConvertSurfaceDesc8(&desc, pDesc); + ConvertSurfaceDesc8(&desc, pDesc); - return res; + return D3D_OK; } HRESULT STDMETHODCALLTYPE D3D8Surface::LockRect( @@ -61,18 +62,17 @@ namespace dxvk { // NOTE: This adds a D3DPOOL_DEFAULT resource to the // device, which counts as losable during device reset - Com image = nullptr; + Com image; HRESULT res = GetParent()->GetD3D9()->CreateRenderTarget( desc.Width, desc.Height, desc.Format, d3d9::D3DMULTISAMPLE_NONE, 0, FALSE, &image, NULL); - if (FAILED(res)) throw DxvkError("D3D8: Failed to create blit image"); return image; } -} +} \ No newline at end of file diff --git a/src/d3d8/d3d8_swapchain.cpp b/src/d3d8/d3d8_swapchain.cpp index 844cc5fece2..88baff6d547 100644 --- a/src/d3d8/d3d8_swapchain.cpp +++ b/src/d3d8/d3d8_swapchain.cpp @@ -25,16 +25,14 @@ namespace dxvk { if (BackBuffer >= m_backBuffers.size() || m_backBuffers[BackBuffer] == nullptr) { Com pSurface9; HRESULT res = GetD3D9()->GetBackBuffer(BackBuffer, (d3d9::D3DBACKBUFFER_TYPE)Type, &pSurface9); + if (unlikely(FAILED(res))) + return res; - if (likely(SUCCEEDED(res))) { - m_backBuffers[BackBuffer] = new D3D8Surface(GetParent(), D3DPOOL_DEFAULT, std::move(pSurface9)); - *ppBackBuffer = m_backBuffers[BackBuffer].ref(); - } - - return res; + m_backBuffers[BackBuffer] = new D3D8Surface(GetParent(), D3DPOOL_DEFAULT, std::move(pSurface9)); } *ppBackBuffer = m_backBuffers[BackBuffer].ref(); + return D3D_OK; } diff --git a/src/d3d8/d3d8_texture.cpp b/src/d3d8/d3d8_texture.cpp index 273ec38c312..63240e3c66e 100644 --- a/src/d3d8/d3d8_texture.cpp +++ b/src/d3d8/d3d8_texture.cpp @@ -1,6 +1,7 @@ #include "d3d8_texture.h" -#include "d3d8_d3d9_util.h" +#include "d3d8_device.h" +#include "d3d8_util.h" namespace dxvk { @@ -13,6 +14,11 @@ namespace dxvk { : D3D8Texture2DBase(pDevice, Pool, std::move(pTexture), pTexture->GetLevelCount()) { } + D3D8Texture2D::~D3D8Texture2D() { + if (unlikely(m_parent->GetOptions()->textureUAFGuard)) + m_parent->RemoveValidTexture(this); + } + D3DRESOURCETYPE STDMETHODCALLTYPE D3D8Texture2D::GetType() { return D3DRTYPE_TEXTURE; } HRESULT STDMETHODCALLTYPE D3D8Texture2D::GetLevelDesc(UINT Level, D3DSURFACE_DESC* pDesc) { @@ -21,11 +27,12 @@ namespace dxvk { d3d9::D3DSURFACE_DESC surf; HRESULT res = GetD3D9()->GetLevelDesc(Level, &surf); + if (unlikely(FAILED(res))) + return res; - if (likely(SUCCEEDED(res))) - ConvertSurfaceDesc8(&surf, pDesc); + ConvertSurfaceDesc8(&surf, pDesc); - return res; + return D3D_OK; } HRESULT STDMETHODCALLTYPE D3D8Texture2D::GetSurfaceLevel(UINT Level, IDirect3DSurface8** ppSurfaceLevel) { @@ -56,6 +63,11 @@ namespace dxvk { Com&& pVolumeTexture) : D3D8Texture3DBase(pDevice, Pool, std::move(pVolumeTexture), pVolumeTexture->GetLevelCount()) {} + D3D8Texture3D::~D3D8Texture3D() { + if (unlikely(m_parent->GetOptions()->textureUAFGuard)) + m_parent->RemoveValidTexture(this); + } + D3DRESOURCETYPE STDMETHODCALLTYPE D3D8Texture3D::GetType() { return D3DRTYPE_VOLUMETEXTURE; } HRESULT STDMETHODCALLTYPE D3D8Texture3D::GetLevelDesc(UINT Level, D3DVOLUME_DESC *pDesc) { @@ -64,11 +76,12 @@ namespace dxvk { d3d9::D3DVOLUME_DESC vol; HRESULT res = GetD3D9()->GetLevelDesc(Level, &vol); + if (unlikely(FAILED(res))) + return res; - if (likely(SUCCEEDED(res))) - ConvertVolumeDesc8(&vol, pDesc); + ConvertVolumeDesc8(&vol, pDesc); - return res; + return D3D_OK; } HRESULT STDMETHODCALLTYPE D3D8Texture3D::GetVolumeLevel(UINT Level, IDirect3DVolume8** ppVolumeLevel) { @@ -105,6 +118,11 @@ namespace dxvk { : D3D8TextureCubeBase(pDevice, Pool, std::move(pTexture), pTexture->GetLevelCount() * CUBE_FACES) { } + D3D8TextureCube::~D3D8TextureCube() { + if (unlikely(m_parent->GetOptions()->textureUAFGuard)) + m_parent->RemoveValidTexture(this); + } + D3DRESOURCETYPE STDMETHODCALLTYPE D3D8TextureCube::GetType() { return D3DRTYPE_CUBETEXTURE; } HRESULT STDMETHODCALLTYPE D3D8TextureCube::GetLevelDesc(UINT Level, D3DSURFACE_DESC* pDesc) { @@ -113,11 +131,12 @@ namespace dxvk { d3d9::D3DSURFACE_DESC surf; HRESULT res = GetD3D9()->GetLevelDesc(Level, &surf); + if (unlikely(FAILED(res))) + return res; - if (likely(SUCCEEDED(res))) - ConvertSurfaceDesc8(&surf, pDesc); + ConvertSurfaceDesc8(&surf, pDesc); - return res; + return D3D_OK; } HRESULT STDMETHODCALLTYPE D3D8TextureCube::GetCubeMapSurface( diff --git a/src/d3d8/d3d8_texture.h b/src/d3d8/d3d8_texture.h index 8d4750e272f..b5e8e9ef441 100644 --- a/src/d3d8/d3d8_texture.h +++ b/src/d3d8/d3d8_texture.h @@ -118,6 +118,8 @@ namespace dxvk { const D3DPOOL Pool, Com&& pTexture); + ~D3D8Texture2D(); + D3DRESOURCETYPE STDMETHODCALLTYPE GetType() final; HRESULT STDMETHODCALLTYPE GetLevelDesc(UINT Level, D3DSURFACE_DESC* pDesc); @@ -146,6 +148,8 @@ namespace dxvk { const D3DPOOL Pool, Com&& pVolumeTexture); + ~D3D8Texture3D(); + D3DRESOURCETYPE STDMETHODCALLTYPE GetType() final; HRESULT STDMETHODCALLTYPE GetLevelDesc(UINT Level, D3DVOLUME_DESC *pDesc); @@ -174,6 +178,8 @@ namespace dxvk { const D3DPOOL Pool, Com&& pTexture); + ~D3D8TextureCube(); + D3DRESOURCETYPE STDMETHODCALLTYPE GetType() final; HRESULT STDMETHODCALLTYPE GetLevelDesc(UINT Level, D3DSURFACE_DESC* pDesc); diff --git a/src/d3d8/d3d8_d3d9_util.h b/src/d3d8/d3d8_util.h similarity index 95% rename from src/d3d8/d3d8_d3d9_util.h rename to src/d3d8/d3d8_util.h index 8d8677a4a51..ddeae164f1b 100644 --- a/src/d3d8/d3d8_d3d9_util.h +++ b/src/d3d8/d3d8_util.h @@ -1,8 +1,5 @@ #pragma once -// Utility functions for converting -// between DirectX8 and DirectX9 types. - #include "d3d8_include.h" #include "d3d8_format.h" #include "d3d8_options.h" @@ -191,4 +188,20 @@ namespace dxvk { } } + inline DWORD isFVF(DWORD Handle) { + return (Handle & D3DFVF_RESERVED0) == 0; + } + + inline DWORD getShaderHandle(DWORD Index) { + return (Index << 1) | D3DFVF_RESERVED0; + } + + inline DWORD getShaderIndex(DWORD Handle) { + if ((Handle & D3DFVF_RESERVED0) != 0) { + return ((Handle & ~(D3DFVF_RESERVED0)) >> 1) - 1; + } else { + return Handle; + } + } + } diff --git a/src/d3d8/d3d8_volume.cpp b/src/d3d8/d3d8_volume.cpp index f7e40595af9..f3fa87a8da5 100644 --- a/src/d3d8/d3d8_volume.cpp +++ b/src/d3d8/d3d8_volume.cpp @@ -1,6 +1,6 @@ #include "d3d8_volume.h" -#include "d3d8_d3d9_util.h" +#include "d3d8_util.h" namespace dxvk { @@ -18,11 +18,12 @@ namespace dxvk { d3d9::D3DVOLUME_DESC desc; HRESULT res = GetD3D9()->GetDesc(&desc); + if (unlikely(FAILED(res))) + return res; - if (likely(SUCCEEDED(res))) - ConvertVolumeDesc8(&desc, pDesc); + ConvertVolumeDesc8(&desc, pDesc); - return res; + return D3D_OK; } HRESULT STDMETHODCALLTYPE D3D8Volume::LockBox(D3DLOCKED_BOX* pLockedBox, CONST D3DBOX* pBox, DWORD Flags) { diff --git a/src/d3d8/d3d8_wrapped_object.h b/src/d3d8/d3d8_wrapped_object.h index f445ca7ec9c..afb015a8600 100644 --- a/src/d3d8/d3d8_wrapped_object.h +++ b/src/d3d8/d3d8_wrapped_object.h @@ -64,4 +64,4 @@ namespace dxvk { }; -} +} \ No newline at end of file diff --git a/src/d3d9/d3d9_device_child.h b/src/d3d9/d3d9_device_child.h index 0866c7d8190..f8e499287cd 100644 --- a/src/d3d9/d3d9_device_child.h +++ b/src/d3d9/d3d9_device_child.h @@ -28,7 +28,7 @@ namespace dxvk { uint32_t oldRefCount, refCount; do { - oldRefCount = this->m_refCount.load(std::memory_order_acquire); + oldRefCount = this->m_refCount.load(); // clamp value to 0 to prevent underruns if (unlikely(!oldRefCount)) @@ -36,10 +36,7 @@ namespace dxvk { refCount = oldRefCount - 1; - } while (!this->m_refCount.compare_exchange_weak(oldRefCount, - refCount, - std::memory_order_release, - std::memory_order_acquire)); + } while (!this->m_refCount.compare_exchange_weak(oldRefCount, refCount)); if (unlikely(!refCount)) { auto* pDevice = GetDevice(); @@ -74,4 +71,4 @@ namespace dxvk { }; -} \ No newline at end of file +} diff --git a/src/util/config/config.cpp b/src/util/config/config.cpp index d76f1f3d2e9..23a92abd1d6 100644 --- a/src/util/config/config.cpp +++ b/src/util/config/config.cpp @@ -1156,84 +1156,85 @@ namespace dxvk { /* D3D8 GAMES */ /**********************************************/ - /* D&D - The Temple Of Elemental Evil */ + /* D&D - The Temple Of Elemental Evil */ { R"(\\ToEE(a)?\.exe$)", {{ { "d3d9.allowDiscard", "False" }, }} }, - /* Duke Nukem Forever (2001) */ + /* Duke Nukem Forever (2001) */ { R"(\\DukeForever\.exe$)", {{ - { "d3d9.maxFrameRate", "60" }, + { "d3d9.maxFrameRate", "-60" }, }} }, - /* Anito: Defend a Land Enraged */ + /* Anito: Defend a Land Enraged */ { R"(\\Anito\.exe$)", {{ { "d3d9.memoryTrackTest", "True" }, { "d3d9.maxAvailableMemory", "1024" }, }} }, - /* Red Faction * - * Fixes crashing when starting a new game */ + /* Red Faction * + * Fixes crashing when starting a new game */ { R"(\\RF\.exe$)", {{ { "d3d9.allowDirectBufferMapping", "False" }, }} }, - /* Commandos 3 * - * The game doesn't use NOOVERWRITE properly * - * and reads from actively modified buffers, * - * which causes graphical glitches at times */ + /* Commandos 3 * + * The game doesn't use NOOVERWRITE properly * + * and reads from actively modified buffers, * + * which causes graphical glitches at times */ { R"(\\Commandos3\.exe$)", {{ { "d3d9.allowDirectBufferMapping", "False" }, }} }, - /* Motor City Online */ + /* Motor City Online */ { R"(\\MCity_d\.exe$)", {{ - { "d3d9.cachedDynamicBuffers", "True" }, + { "d3d9.cachedWriteOnlyBuffers", "True" }, { "d3d8.batching", "True" }, }} }, - /* Railroad Tycoon 3 */ + /* Railroad Tycoon 3 */ { R"(\\RT3\.exe$)", {{ - { "d3d9.maxFrameRate", "60" }, + { "d3d9.maxFrameRate", "-60" }, }} }, - /* Pure Pinball 2.0 REDUX * - * This game reads from undeclared vs inputs * - * but somehow works on native. Let's just * - * change its declaration to make them work. */ + /* Pure Pinball 2.0 REDUX * + * This game reads from undeclared vs inputs * + * but somehow works on native. Let's just * + * change its declaration to make them work. */ { R"(\\Pure Pinball 2\.0 REDUX\.exe$)", {{ { "d3d8.forceVsDecl", "0:2,4:2,7:4,9:1,8:1" }, }} }, - /* Need for Speed III: Hot Pursuit * - (with the "Modern Patch") */ + /* Need for Speed III: Hot Pursuit * + * (with the "Modern Patch") */ { R"(\\nfs3\.exe$)", {{ - { "d3d9.cachedDynamicBuffers", "True" }, + { "d3d9.cachedWriteOnlyBuffers", "True" }, { "d3d8.batching", "True" }, }} }, /* Need for Speed: High Stakes / Road * - Challenge (with the "Modern Patch") - * - Won't actually render anything in game * - without a memory limit in place */ + * Challenge (with the "Modern Patch") - * + * Won't actually render anything in game * + * without a memory limit in place */ { R"(\\nfs4\.exe$)", {{ - { "d3d9.cachedDynamicBuffers", "True" }, + { "d3d9.cachedWriteOnlyBuffers", "True" }, { "d3d9.memoryTrackTest", "True" }, { "d3d9.maxAvailableMemory", "1024" }, { "d3d8.batching", "True" }, + { "ddraw.forceSWVP", "True" }, }} }, /* Need for Speed: Hot Pursuit 2 */ { R"(\\NFSHP2\.exe$)", {{ - { "d3d9.cachedDynamicBuffers", "True" }, + { "d3d9.cachedWriteOnlyBuffers", "True" }, }} }, /* Project I.G.I. 2: Covert Strike * * Very stuttery frametime with own framecap */ { R"(\\igi2\.exe$)", {{ - { "d3d9.maxFrameRate", "60" }, + { "d3d9.maxFrameRate", "-60" }, }} }, - /* Treasure Planet: Battle at Procyon * - * Declares v5 as color but shader uses v6 */ + /* Treasure Planet: Battle at Procyon * + * Declares v5 as color but shader uses v6 */ { R"(\\TP_Win32\.exe$)", {{ { "d3d8.forceVsDecl", "0:2,3:2,6:4,7:1" }, }} }, - /* Scrapland (Remastered) */ + /* Scrapland (Remastered) */ { R"(\\Scrap\.exe$)", {{ { "d3d9.deferSurfaceCreation", "True" }, }} }, /* V-Rally 3 */ { R"(\\VRally3(Demo)?\.exe$)", {{ - { "d3d9.maxFrameRate", "60" }, + { "d3d9.maxFrameRate", "-60" }, }} }, /* Soldiers: Heroes Of World War II * * Fills up all available memory and hangs * @@ -1245,11 +1246,11 @@ namespace dxvk { /* Cossacks II: Napoleonic Wars & * * Battle for Europe */ { R"(\\Cossacks II.*\\engine\.exe$)", {{ - { "d3d9.maxFrameRate", "60" }, + { "d3d9.maxFrameRate", "-60" }, }} }, /* Alexander */ { R"(\\Alexander\\Data\\engine\.exe$)", {{ - { "d3d9.maxFrameRate", "60" }, + { "d3d9.maxFrameRate", "-60" }, }} }, /* 3DMark2001 (SE) * * Fixes a drastic performance drop in the * @@ -1259,21 +1260,21 @@ namespace dxvk { }} }, /* Delta Force: Black Hawk Down */ { R"(\\dfbhd\.exe$)", {{ - { "d3d9.cachedDynamicBuffers", "True" }, + { "d3d9.cachedWriteOnlyBuffers", "True" }, }} }, /* X2: The Threat */ { R"(\\X2\.exe$)", {{ - { "d3d9.cachedDynamicBuffers", "True" }, + { "d3d9.cachedWriteOnlyBuffers", "True" }, }} }, /* The Lord of the Rings: * * The Fellowship of the Ring */ { R"(\\Fellowship\.exe$)", {{ - { "d3d9.maxFrameRate", "60" }, + { "d3d9.maxFrameRate", "-60" }, { "d3d8.placeP8InScratch", "True" }, }} }, /* Art of Murder FBI Confidential - CPU perf */ { R"(\\Art of Murder - FBI Confidential\\game\.exe$)", {{ - { "d3d9.cachedDynamicBuffers", "True" }, + { "d3d9.cachedWriteOnlyBuffers", "True" }, }} }, /* Max Payne 1 - Stalls waiting for an index buffer */ { R"(\\MaxPayne\.exe$)", {{ @@ -1281,42 +1282,42 @@ namespace dxvk { }} }, /* Z: Steel Soldiers */ { R"(\\z2\.exe$)", {{ - { "d3d9.cachedDynamicBuffers", "True" }, + { "d3d9.cachedWriteOnlyBuffers", "True" }, }} }, /* FIFA Football 2003 */ { R"(\\fifa2003(demo)?\.exe$)", {{ - { "d3d9.cachedDynamicBuffers", "True" }, + { "d3d9.cachedWriteOnlyBuffers", "True" }, }} }, /* Splinter Cell: Pandora Tomorrow (Retail) * * Missing shadows without dref scaling and * * broken inputs and physics above 60 FPS */ { R"(\\offline\\system\\SplinterCell2\.exe$)", {{ - { "d3d9.maxFrameRate", "60" }, + { "d3d9.maxFrameRate", "-60" }, { "d3d8.scaleDref", "24" }, }} }, /* Splinter Cell: Pandora Tomorrow (Steam) * * Broken inputs and physics above 60 FPS */ { R"(\\Splinter Cell Pandora Tomorrow\\system\\SplinterCell2\.exe$)", {{ - { "d3d9.maxFrameRate", "60" }, + { "d3d9.maxFrameRate", "-60" }, }} }, /* Chrome: Gold Edition * * Broken character model motion at high FPS */ { R"(\\Chrome(Single|Net)\.exe$)", {{ - { "d3d9.maxFrameRate", "60" }, + { "d3d9.maxFrameRate", "-60" }, }} }, /* Rayman 3: Hoodlum Havoc * * Missing geometry and textures without * * legacy DISCARD behavior */ { R"(\\Rayman3\.exe$)", {{ - { "d3d9.maxFrameRate", "60" }, + { "d3d9.maxFrameRate", "-60" }, { "d3d8.forceLegacyDiscard", "True" }, }} }, /* Tom Clancy's Splinter Cell * * Fixes shadow buffers, broken physics * * above 60 FPS and game freezing on alt-tab */ - { R"(\\splintercell\.exe$)", {{ - { "d3d9.customVendorId", "10de" }, - { "d3d9.maxFrameRate", "60" }, + { R"(\\splintercell\.exe$)", {{ + { "d3d9.hideAmdGpu", "True" }, + { "d3d9.maxFrameRate", "-60" }, { "d3d8.scaleDref", "24" }, { "d3d8.shadowPerspectiveDivide", "True" }, }} }, @@ -1326,7 +1327,7 @@ namespace dxvk { { R"(\\GTR (- FIA GT Rac(e)?ing Game|Demo)\\(GTR(Demo)?|(3D)?Config)\.exe$)", {{ { "d3d9.maxAvailableMemory", "1024" }, { "d3d9.memoryTrackTest", "True" }, - { "d3d9.cachedDynamicBuffers", "True" }, + { "d3d9.cachedWriteOnlyBuffers", "True" }, }} }, /* Comanche 4 - Only enables the FSAA option * * if it detects a device ID of 0x025x. */ @@ -1351,10 +1352,25 @@ namespace dxvk { { R"(\\Smash up Derby\\cars\.exe$)", {{ { "d3d9.allowDirectBufferMapping", "False" }, }} }, + /* Age of Pirates: Caribbean Tales * + * Crashes due to a texture UAF otherwise */ + { R"(\\(Age of Pirates|Sea Dogs).*Caribbean Tales\\ENGINE\.exe$)", {{ + { "d3d8.textureUAFGuard", "True" }, + }} }, + /* Age of Pirates 2: City of Abandoned Ships * + * Crashes due to a texture UAF otherwise */ + { R"(\\(Age of Pirates|Sea Dogs).*City of Abandoned Ships\\START\.exe$)", {{ + { "d3d8.textureUAFGuard", "True" }, + }} }, /* Mafia - Improves poor texture filtering */ { R"(\\Mafia\\Game\.exe$)", {{ { "d3d9.samplerAnisotropy", "16" }, }} }, + /* Manhunt * + * Broken AI behavior above 60 FPS (game bug) */ + { R"(\\manhunt\.exe$)", {{ + { "d3d9.maxFrameRate", "-60" }, + }} }, /**********************************************/ /* D3D7 GAMES */