From 324b4a77f0bb2858f3673eae31e7f705e7b08598 Mon Sep 17 00:00:00 2001 From: narzoul Date: Tue, 12 Jan 2021 20:17:52 +0100 Subject: [PATCH] Replace RHW=INFINITY with RHW=1 Fixes invisible gauge needles in NASCAR Racing 3 (issue #83). --- DDrawCompat/D3dDdi/Device.cpp | 2 +- DDrawCompat/D3dDdi/Device.h | 1 + DDrawCompat/D3dDdi/DeviceFuncs.cpp | 1 + DDrawCompat/D3dDdi/DeviceState.cpp | 43 +++++++++++++++- DDrawCompat/D3dDdi/DeviceState.h | 3 ++ DDrawCompat/D3dDdi/DrawPrimitive.cpp | 61 +++++++++++++++-------- DDrawCompat/D3dDdi/DrawPrimitive.h | 18 +++---- DDrawCompat/D3dDdi/Log/DeviceFuncsLog.cpp | 18 +++++++ DDrawCompat/D3dDdi/Log/DeviceFuncsLog.h | 2 + 9 files changed, 113 insertions(+), 36 deletions(-) diff --git a/DDrawCompat/D3dDdi/Device.cpp b/DDrawCompat/D3dDdi/Device.cpp index dd133ab..8c155e6 100644 --- a/DDrawCompat/D3dDdi/Device.cpp +++ b/DDrawCompat/D3dDdi/Device.cpp @@ -205,7 +205,7 @@ namespace D3dDdi data.pSurfList[0].pSysMem) { m_drawPrimitive.addSysMemVertexBuffer(data.hResource, - static_cast(const_cast(data.pSurfList[0].pSysMem)), data.Fvf); + static_cast(const_cast(data.pSurfList[0].pSysMem))); } return S_OK; } diff --git a/DDrawCompat/D3dDdi/Device.h b/DDrawCompat/D3dDdi/Device.h index 818077f..d5c1eae 100644 --- a/DDrawCompat/D3dDdi/Device.h +++ b/DDrawCompat/D3dDdi/Device.h @@ -48,6 +48,7 @@ namespace D3dDdi HRESULT unlock(const D3DDDIARG_UNLOCK* data); Adapter& getAdapter() const { return m_adapter; } + DrawPrimitive& getDrawPrimitive() { return m_drawPrimitive; } const D3DDDI_DEVICEFUNCS& getOrigVtable() const { return m_origVtable; } Resource* getResource(HANDLE resource); DeviceState& getState() { return m_state; } diff --git a/DDrawCompat/D3dDdi/DeviceFuncs.cpp b/DDrawCompat/D3dDdi/DeviceFuncs.cpp index 0e2fbb8..4f23b42 100644 --- a/DDrawCompat/D3dDdi/DeviceFuncs.cpp +++ b/DDrawCompat/D3dDdi/DeviceFuncs.cpp @@ -61,6 +61,7 @@ namespace D3dDdi vtable.pfnSetStreamSourceUm = &DEVICE_FUNC(setStreamSourceUm); vtable.pfnUnlock = &DEVICE_FUNC(unlock); + SET_DEVICE_STATE_FUNC(pfnCreateVertexShaderDecl); SET_DEVICE_STATE_FUNC(pfnDeletePixelShader); SET_DEVICE_STATE_FUNC(pfnDeleteVertexShaderDecl); SET_DEVICE_STATE_FUNC(pfnDeleteVertexShaderFunc); diff --git a/DDrawCompat/D3dDdi/DeviceState.cpp b/DDrawCompat/D3dDdi/DeviceState.cpp index 9be6498..54f4777 100644 --- a/DDrawCompat/D3dDdi/DeviceState.cpp +++ b/DDrawCompat/D3dDdi/DeviceState.cpp @@ -1,5 +1,8 @@ +#include #include #include +#include +#include namespace { @@ -35,6 +38,19 @@ namespace D3dDdi } } + HRESULT DeviceState::pfnCreateVertexShaderDecl( + D3DDDIARG_CREATEVERTEXSHADERDECL* data, + const D3DDDIVERTEXELEMENT* vertexElements) + { + LOG_DEBUG << Compat::array(vertexElements, data->NumVertexElements); + HRESULT result = m_device.getOrigVtable().pfnCreateVertexShaderDecl(m_device, data, vertexElements); + if (SUCCEEDED(result)) + { + m_vertexShaderDecls[data->ShaderHandle].assign(vertexElements, vertexElements + data->NumVertexElements); + } + return result; + } + HRESULT DeviceState::pfnDeletePixelShader(HANDLE shader) { return deleteShader(shader, m_pixelShader, m_device.getOrigVtable().pfnDeletePixelShader); @@ -42,7 +58,17 @@ namespace D3dDdi HRESULT DeviceState::pfnDeleteVertexShaderDecl(HANDLE shader) { - return deleteShader(shader, m_vertexShaderDecl, m_device.getOrigVtable().pfnDeleteVertexShaderDecl); + const bool isCurrentShader = shader == m_vertexShaderDecl; + HRESULT result = deleteShader(shader, m_vertexShaderDecl, m_device.getOrigVtable().pfnDeleteVertexShaderDecl); + if (SUCCEEDED(result)) + { + m_vertexShaderDecls.erase(shader); + if (isCurrentShader) + { + m_device.getDrawPrimitive().setVertexShaderDecl({}); + } + } + return result; } HRESULT DeviceState::pfnDeleteVertexShaderFunc(HANDLE shader) @@ -132,7 +158,20 @@ namespace D3dDdi HRESULT DeviceState::pfnSetVertexShaderDecl(HANDLE shader) { - return setShader(shader, m_vertexShaderDecl, m_device.getOrigVtable().pfnSetVertexShaderDecl); + HRESULT result = setShader(shader, m_vertexShaderDecl, m_device.getOrigVtable().pfnSetVertexShaderDecl); + if (SUCCEEDED(result)) + { + auto it = m_vertexShaderDecls.find(shader); + if (it != m_vertexShaderDecls.end()) + { + m_device.getDrawPrimitive().setVertexShaderDecl(it->second); + } + else + { + m_device.getDrawPrimitive().setVertexShaderDecl({}); + } + } + return result; } HRESULT DeviceState::pfnSetVertexShaderFunc(HANDLE shader) diff --git a/DDrawCompat/D3dDdi/DeviceState.h b/DDrawCompat/D3dDdi/DeviceState.h index 7876e02..d25fa9b 100644 --- a/DDrawCompat/D3dDdi/DeviceState.h +++ b/DDrawCompat/D3dDdi/DeviceState.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include namespace D3dDdi @@ -12,6 +13,7 @@ namespace D3dDdi public: DeviceState(Device& device); + HRESULT pfnCreateVertexShaderDecl(D3DDDIARG_CREATEVERTEXSHADERDECL* data, const D3DDDIVERTEXELEMENT* vertexElements); HRESULT pfnDeletePixelShader(HANDLE shader); HRESULT pfnDeleteVertexShaderDecl(HANDLE shader); HRESULT pfnDeleteVertexShaderFunc(HANDLE shader); @@ -65,6 +67,7 @@ namespace D3dDdi std::vector m_vertexShaderConst; std::vector m_vertexShaderConstB; std::vector m_vertexShaderConstI; + std::map> m_vertexShaderDecls; HANDLE m_vertexShaderDecl; HANDLE m_vertexShaderFunc; D3DDDIARG_WINFO m_wInfo; diff --git a/DDrawCompat/D3dDdi/DrawPrimitive.cpp b/DDrawCompat/D3dDdi/DrawPrimitive.cpp index 35c9f74..aa572cc 100644 --- a/DDrawCompat/D3dDdi/DrawPrimitive.cpp +++ b/DDrawCompat/D3dDdi/DrawPrimitive.cpp @@ -55,6 +55,7 @@ namespace D3dDdi , m_indexBuffer(device, m_vertexBuffer ? INDEX_BUFFER_SIZE : 0) , m_streamSource{} , m_batched{} + , m_isHwVertexProcessingUsed(false) { LOG_ONCE("Dynamic vertex buffers are " << (m_vertexBuffer ? "" : "not ") << "available"); LOG_ONCE("Dynamic index buffers are " << (m_indexBuffer ? "" : "not ") << "available"); @@ -68,9 +69,9 @@ namespace D3dDdi } } - void DrawPrimitive::addSysMemVertexBuffer(HANDLE resource, BYTE* vertices, UINT fvf) + void DrawPrimitive::addSysMemVertexBuffer(HANDLE resource, BYTE* vertices) { - m_sysMemVertexBuffers[resource] = { vertices, fvf }; + m_sysMemVertexBuffers[resource] = vertices; } void DrawPrimitive::appendIndexedVertices(const UINT16* indices, UINT count, @@ -517,15 +518,6 @@ namespace D3dDdi return S_OK; } - void DrawPrimitive::fixFirstVertexRhw() - { - auto firstVertex = reinterpret_cast(m_batched.vertices.data()); - if ((m_streamSource.fvf & D3DFVF_XYZRHW) && 0.0f == firstVertex->rhw) - { - firstVertex->rhw = 1.0f; - } - } - HRESULT DrawPrimitive::flush(const UINT* flagBuffer) { D3DDDIARG_DRAWPRIMITIVE data = {}; @@ -535,8 +527,7 @@ namespace D3dDdi if (m_streamSource.vertices) { - fixFirstVertexRhw(); - data.VStart = loadVertices(m_batched.vertices.data(), getBatchedVertexCount()); + data.VStart = loadVertices(getBatchedVertexCount()); } clearBatchedPrimitives(); @@ -562,8 +553,7 @@ namespace D3dDdi if (m_streamSource.vertices) { - fixFirstVertexRhw(); - INT baseVertexIndex = loadVertices(m_batched.vertices.data(), data.NumVertices) - data.MinIndex; + INT baseVertexIndex = loadVertices(data.NumVertices) - data.MinIndex; data.BaseVertexOffset = baseVertexIndex * static_cast(m_streamSource.stride); } @@ -623,8 +613,23 @@ namespace D3dDdi return -1; } - INT DrawPrimitive::loadVertices(const void* vertices, UINT count) + INT DrawPrimitive::loadVertices(UINT count) { + auto vertices = m_batched.vertices.data(); + if (!m_isHwVertexProcessingUsed) + { + UINT offset = 0; + for (UINT i = 0; i < count; ++i) + { + auto v = reinterpret_cast(vertices + offset); + if (0 == v->rhw || INFINITY == v->rhw) + { + v->rhw = 1; + } + offset += m_streamSource.stride; + } + } + if (m_vertexBuffer) { UINT size = count * m_streamSource.stride; @@ -710,24 +715,24 @@ namespace D3dDdi auto it = m_sysMemVertexBuffers.find(data.hVertexBuffer); if (it != m_sysMemVertexBuffers.end()) { - return setSysMemStreamSource(it->second.vertices, data.Stride, it->second.fvf); + return setSysMemStreamSource(it->second, data.Stride); } flushPrimitives(); HRESULT result = m_origVtable.pfnSetStreamSource(m_device, &data); if (SUCCEEDED(result)) { - m_streamSource = { nullptr, data.Stride, 0 }; + m_streamSource = { nullptr, data.Stride }; } return result; } HRESULT DrawPrimitive::setStreamSourceUm(const D3DDDIARG_SETSTREAMSOURCEUM& data, const void* umBuffer) { - return setSysMemStreamSource(static_cast(umBuffer), data.Stride, 0); + return setSysMemStreamSource(static_cast(umBuffer), data.Stride); } - HRESULT DrawPrimitive::setSysMemStreamSource(const BYTE* vertices, UINT stride, UINT fvf) + HRESULT DrawPrimitive::setSysMemStreamSource(const BYTE* vertices, UINT stride) { HRESULT result = S_OK; if (!m_streamSource.vertices || stride != m_streamSource.stride) @@ -748,8 +753,22 @@ namespace D3dDdi if (SUCCEEDED(result)) { - m_streamSource = { vertices, stride, fvf }; + m_streamSource = { vertices, stride }; } return result; } + + void DrawPrimitive::setVertexShaderDecl(const std::vector& decl) + { + m_isHwVertexProcessingUsed = true; + const UINT D3DDECLUSAGE_POSITIONT = 9; + for (auto& vertexElement : decl) + { + if (D3DDECLUSAGE_POSITIONT == vertexElement.Usage) + { + m_isHwVertexProcessingUsed = false; + return; + } + } + } } diff --git a/DDrawCompat/D3dDdi/DrawPrimitive.h b/DDrawCompat/D3dDdi/DrawPrimitive.h index e99a42e..d3901ef 100644 --- a/DDrawCompat/D3dDdi/DrawPrimitive.h +++ b/DDrawCompat/D3dDdi/DrawPrimitive.h @@ -17,7 +17,7 @@ namespace D3dDdi public: DrawPrimitive(Device& device); - void addSysMemVertexBuffer(HANDLE resource, BYTE* vertices, UINT fvf); + void addSysMemVertexBuffer(HANDLE resource, BYTE* vertices); void removeSysMemVertexBuffer(HANDLE resource); HRESULT flushPrimitives(const UINT* flagBuffer = nullptr); @@ -26,6 +26,7 @@ namespace D3dDdi HRESULT drawIndexed(D3DDDIARG_DRAWINDEXEDPRIMITIVE2 data, const UINT16* indices, const UINT* flagBuffer); HRESULT setStreamSource(const D3DDDIARG_SETSTREAMSOURCE& data); HRESULT setStreamSourceUm(const D3DDDIARG_SETSTREAMSOURCEUM& data, const void* umBuffer); + void setVertexShaderDecl(const std::vector& decl); private: struct BatchedPrimitives @@ -43,13 +44,6 @@ namespace D3dDdi { const BYTE* vertices; UINT stride; - UINT fvf; - }; - - struct SysMemVertexBuffer - { - BYTE* vertices; - UINT fvf; }; void appendIndexedVertices(const UINT16* indices, UINT count, @@ -75,23 +69,23 @@ namespace D3dDdi void convertIndexedTriangleFanToList(UINT startPrimitive, UINT primitiveCount); void convertIndexedTriangleStripToList(UINT startPrimitive, UINT primitiveCount); void convertToTriangleList(); - void fixFirstVertexRhw(); HRESULT flush(const UINT* flagBuffer); HRESULT flushIndexed(const UINT* flagBuffer); INT loadIndices(const void* indices, UINT count); - INT loadVertices(const void* vertices, UINT count); + INT loadVertices(UINT count); UINT getBatchedVertexCount() const; void rebaseIndices(); void repeatLastBatchedVertex(); - HRESULT setSysMemStreamSource(const BYTE* vertices, UINT stride, UINT fvf); + HRESULT setSysMemStreamSource(const BYTE* vertices, UINT stride); HANDLE m_device; const D3DDDI_DEVICEFUNCS& m_origVtable; DynamicVertexBuffer m_vertexBuffer; DynamicIndexBuffer m_indexBuffer; StreamSource m_streamSource; - std::map m_sysMemVertexBuffers; + std::map m_sysMemVertexBuffers; BatchedPrimitives m_batched; + bool m_isHwVertexProcessingUsed; }; } diff --git a/DDrawCompat/D3dDdi/Log/DeviceFuncsLog.cpp b/DDrawCompat/D3dDdi/Log/DeviceFuncsLog.cpp index 895e190..646054a 100644 --- a/DDrawCompat/D3dDdi/Log/DeviceFuncsLog.cpp +++ b/DDrawCompat/D3dDdi/Log/DeviceFuncsLog.cpp @@ -95,6 +95,13 @@ std::ostream& operator<<(std::ostream& os, const D3DDDIARG_CREATERESOURCE2& val) << Compat::hex(val.Flags2.Value); } +std::ostream& operator<<(std::ostream& os, const D3DDDIARG_CREATEVERTEXSHADERDECL& val) +{ + return Compat::LogStruct(os) + << val.NumVertexElements + << val.ShaderHandle; +} + std::ostream& operator<<(std::ostream& os, const D3DDDIARG_DRAWINDEXEDPRIMITIVE& val) { return Compat::LogStruct(os) @@ -474,3 +481,14 @@ std::ostream& operator<<(std::ostream& os, D3DDDITEXTURESTAGESTATETYPE val) return os << "D3DDDITSS_" << static_cast(val); } + +std::ostream& operator<<(std::ostream& os, const D3DDDIVERTEXELEMENT& val) +{ + return Compat::LogStruct(os) + << val.Stream + << val.Offset + << static_cast(val.Type) + << static_cast(val.Method) + << static_cast(val.Usage) + << static_cast(val.UsageIndex); +} diff --git a/DDrawCompat/D3dDdi/Log/DeviceFuncsLog.h b/DDrawCompat/D3dDdi/Log/DeviceFuncsLog.h index 323eb83..d253b86 100644 --- a/DDrawCompat/D3dDdi/Log/DeviceFuncsLog.h +++ b/DDrawCompat/D3dDdi/Log/DeviceFuncsLog.h @@ -14,6 +14,7 @@ std::ostream& operator<<(std::ostream& os, const D3DDDIARG_CLEAR& val); std::ostream& operator<<(std::ostream& os, const D3DDDIARG_COLORFILL& val); std::ostream& operator<<(std::ostream& os, const D3DDDIARG_CREATERESOURCE& val); std::ostream& operator<<(std::ostream& os, const D3DDDIARG_CREATERESOURCE2& val); +std::ostream& operator<<(std::ostream& os, const D3DDDIARG_CREATEVERTEXSHADERDECL& val); std::ostream& operator<<(std::ostream& os, const D3DDDIARG_DRAWINDEXEDPRIMITIVE& val); std::ostream& operator<<(std::ostream& os, const D3DDDIARG_DRAWINDEXEDPRIMITIVE2& val); std::ostream& operator<<(std::ostream& os, const D3DDDIARG_DRAWPRIMITIVE& val); @@ -36,3 +37,4 @@ std::ostream& operator<<(std::ostream& os, const D3DDDIARG_ZRANGE& val); std::ostream& operator<<(std::ostream& os, const D3DDDIBOX& val); std::ostream& operator<<(std::ostream& os, D3DDDIRENDERSTATETYPE val); std::ostream& operator<<(std::ostream& os, D3DDDITEXTURESTAGESTATETYPE val); +std::ostream& operator<<(std::ostream& os, const D3DDDIVERTEXELEMENT& val);