From bf9833946a4a28c6511374f6adff4ba0185f36a2 Mon Sep 17 00:00:00 2001 From: narzoul Date: Sun, 29 Jan 2023 23:48:50 +0100 Subject: [PATCH] Fixed texture stage count determination --- DDrawCompat/D3dDdi/DeviceState.cpp | 39 +++++++++++++++++++------- DDrawCompat/D3dDdi/DeviceState.h | 5 +++- DDrawCompat/D3dDdi/DrawPrimitive.cpp | 3 +- DDrawCompat/D3dDdi/ShaderAssembler.cpp | 6 ++++ DDrawCompat/D3dDdi/ShaderAssembler.h | 1 + 5 files changed, 42 insertions(+), 12 deletions(-) diff --git a/DDrawCompat/D3dDdi/DeviceState.cpp b/DDrawCompat/D3dDdi/DeviceState.cpp index 309d062..0a8c8a6 100644 --- a/DDrawCompat/D3dDdi/DeviceState.cpp +++ b/DDrawCompat/D3dDdi/DeviceState.cpp @@ -47,11 +47,13 @@ namespace D3dDdi , m_vertexShaderConst{} , m_vertexShaderConstB{} , m_vertexShaderConstI{} + , m_vertexDecl(nullptr) , m_changedStates(0) , m_maxChangedTextureStage(0) , m_changedTextureStageStates{} , m_vsVertexFixup(createVertexShader(g_vsVertexFixup)) , m_textureResource{} + , m_pixelShader(nullptr) , m_isLocked(false) , m_spriteMode(false) { @@ -275,11 +277,15 @@ namespace D3dDdi return m_textureResource[stage]; } + UINT DeviceState::getTextureStageCount() const + { + return m_pixelShader ? m_pixelShader->textureStageCount : 0; + } + const DeviceState::VertexDecl& DeviceState::getVertexDecl() const { static const VertexDecl emptyDecl = {}; - auto it = m_vertexShaderDecls.find(m_app.vertexShaderDecl); - return it != m_vertexShaderDecls.end() ? it->second : emptyDecl; + return m_vertexDecl ? *m_vertexDecl : emptyDecl; } bool DeviceState::isColorKeyUsed() @@ -290,7 +296,8 @@ namespace D3dDdi } bool used = false; - for (UINT i = 0; i < getVertexDecl().textureStageCount && !used; ++i) + UINT textureStageCount = getTextureStageCount(); + for (UINT i = 0; i < textureStageCount && !used; ++i) { used = !m_app.textureStageState[i][D3DDDITSS_DISABLETEXTURECOLORKEY]; } @@ -426,15 +433,17 @@ namespace D3dDdi HRESULT DeviceState::pfnCreatePixelShader(D3DDDIARG_CREATEPIXELSHADER* data, const UINT* code) { + ShaderAssembler shaderAssembler(code, data->CodeSize); LOG_DEBUG << "Pixel shader bytecode: " << Compat::hexDump(code, data->CodeSize); - LOG_DEBUG << ShaderAssembler(code, data->CodeSize).disassemble(); + LOG_DEBUG << shaderAssembler.disassemble(); HRESULT result = m_device.getOrigVtable().pfnCreatePixelShader(m_device, data, code); if (SUCCEEDED(result)) { m_pixelShaders.emplace(data->ShaderHandle, PixelShader{ std::vector(code, code + data->CodeSize / 4), std::unique_ptr( - nullptr, ResourceDeleter(m_device, m_device.getOrigVtable().pfnDeleteVertexShaderFunc)) }); + nullptr, ResourceDeleter(m_device, m_device.getOrigVtable().pfnDeleteVertexShaderFunc)), + shaderAssembler.getTextureStageCount(), false }); } return result; } @@ -459,10 +468,6 @@ namespace D3dDdi { decl.texCoordOffset[vertexElements[i].UsageIndex] = vertexElements[i].Offset; decl.texCoordType[vertexElements[i].UsageIndex] = vertexElements[i].Type; - if (vertexElements[i].UsageIndex >= decl.textureStageCount) - { - decl.textureStageCount = vertexElements[i].UsageIndex + 1; - } } else if (D3DDECLUSAGE_POSITIONT == vertexElements[i].Usage) { @@ -487,6 +492,10 @@ namespace D3dDdi auto it = m_pixelShaders.find(shader); if (it != m_pixelShaders.end()) { + if (m_pixelShader == &it->second) + { + m_pixelShader = nullptr; + } if (it->second.modifiedPixelShader) { deleteShader(it->second.modifiedPixelShader.release(), &State::pixelShader, @@ -500,9 +509,14 @@ namespace D3dDdi HRESULT DeviceState::pfnDeleteVertexShaderDecl(HANDLE shader) { + const bool isCurrent = m_app.vertexShaderDecl == shader; HRESULT result = deleteShader(shader, &State::vertexShaderDecl, m_device.getOrigVtable().pfnDeleteVertexShaderDecl); if (SUCCEEDED(result)) { + if (isCurrent) + { + m_vertexDecl = nullptr; + } m_vertexShaderDecls.erase(shader); } return result; @@ -525,6 +539,8 @@ namespace D3dDdi { m_app.pixelShader = shader; m_changedStates |= CS_SHADER; + auto it = m_pixelShaders.find(shader); + m_pixelShader = it != m_pixelShaders.end() ? &it->second : nullptr; return S_OK; } @@ -636,6 +652,8 @@ namespace D3dDdi { m_app.vertexShaderDecl = shader; m_changedStates |= CS_SHADER; + auto it = m_vertexShaderDecls.find(shader); + m_vertexDecl = it != m_vertexShaderDecls.end() ? &it->second : nullptr; return S_OK; } @@ -669,7 +687,8 @@ namespace D3dDdi void DeviceState::prepareTextures() { - for (UINT stage = 0; stage < getVertexDecl().textureStageCount; ++stage) + UINT textureStageCount = getTextureStageCount(); + for (UINT stage = 0; stage < textureStageCount; ++stage) { auto resource = getTextureResource(stage); if (resource) diff --git a/DDrawCompat/D3dDdi/DeviceState.h b/DDrawCompat/D3dDdi/DeviceState.h index 603f479..0d02fe2 100644 --- a/DDrawCompat/D3dDdi/DeviceState.h +++ b/DDrawCompat/D3dDdi/DeviceState.h @@ -80,7 +80,6 @@ namespace D3dDdi std::vector elements; std::array texCoordOffset; std::array texCoordType; - UINT textureStageCount; bool isTransformed; }; @@ -130,6 +129,7 @@ namespace D3dDdi const State& getAppState() const { return m_app; } const State& getCurrentState() const { return m_current; } Resource* getTextureResource(UINT stage); + UINT getTextureStageCount() const; const VertexDecl& getVertexDecl() const; HANDLE getVertexFixupDecl() const { return m_vsVertexFixup.get(); } bool isLocked() const { return m_isLocked; } @@ -153,6 +153,7 @@ namespace D3dDdi { std::vector tokens; std::unique_ptr modifiedPixelShader; + UINT textureStageCount; bool isModified; }; @@ -217,6 +218,7 @@ namespace D3dDdi std::array m_vertexShaderConstB; std::array m_vertexShaderConstI; std::map m_vertexShaderDecls; + VertexDecl* m_vertexDecl; UINT m_changedStates; UINT m_maxChangedTextureStage; UINT m_usedTextureStages; @@ -225,6 +227,7 @@ namespace D3dDdi std::unique_ptr m_vsVertexFixup; std::array m_textureResource; std::map m_pixelShaders; + PixelShader* m_pixelShader; bool m_isLocked; bool m_spriteMode; }; diff --git a/DDrawCompat/D3dDdi/DrawPrimitive.cpp b/DDrawCompat/D3dDdi/DrawPrimitive.cpp index f595ddd..0804140 100644 --- a/DDrawCompat/D3dDdi/DrawPrimitive.cpp +++ b/DDrawCompat/D3dDdi/DrawPrimitive.cpp @@ -829,9 +829,10 @@ namespace D3dDdi auto& state = m_device.getState(); auto& appState = state.getAppState(); auto& decl = state.getVertexDecl(); + auto textureStageCount = state.getTextureStageCount(); auto vertices = m_streamSource.vertices + baseVertexIndex * m_streamSource.stride; - for (UINT stage = 0; stage < decl.textureStageCount; ++stage) + for (UINT stage = 0; stage < textureStageCount; ++stage) { const UINT D3DDECLTYPE_FLOAT2 = 1; if (!appState.textures[stage] || diff --git a/DDrawCompat/D3dDdi/ShaderAssembler.cpp b/DDrawCompat/D3dDdi/ShaderAssembler.cpp index 505773a..f2098d3 100644 --- a/DDrawCompat/D3dDdi/ShaderAssembler.cpp +++ b/DDrawCompat/D3dDdi/ShaderAssembler.cpp @@ -696,6 +696,12 @@ namespace D3dDdi return static_cast(m_tokens.front() >> 16); } + UINT ShaderAssembler::getTextureStageCount() + { + auto usedSamplers = getUsedRegisterNumbers(D3DSPR_SAMPLER); + return usedSamplers.empty() ? 0 : (*usedSamplers.rbegin() + 1); + } + template Token ShaderAssembler::getToken(UINT offset) const { diff --git a/DDrawCompat/D3dDdi/ShaderAssembler.h b/DDrawCompat/D3dDdi/ShaderAssembler.h index 49fe06e..2e56d7d 100644 --- a/DDrawCompat/D3dDdi/ShaderAssembler.h +++ b/DDrawCompat/D3dDdi/ShaderAssembler.h @@ -16,6 +16,7 @@ namespace D3dDdi bool addAlphaTest(UINT alphaRef); std::string disassemble(); + UINT getTextureStageCount(); const std::vector& getTokens() const { return m_tokens; } private: