diff --git a/DDrawCompat/D3dDdi/DeviceState.cpp b/DDrawCompat/D3dDdi/DeviceState.cpp index 912b128..8cc7410 100644 --- a/DDrawCompat/D3dDdi/DeviceState.cpp +++ b/DDrawCompat/D3dDdi/DeviceState.cpp @@ -1,3 +1,5 @@ +#include + #include #include #include @@ -5,6 +7,7 @@ #include #include #include +#include #define LOG_DS LOG_DEBUG << "DeviceState::" << __func__ << ": " @@ -70,6 +73,7 @@ namespace D3dDdi , m_changedStates(0) , m_maxChangedTextureStage(0) , m_changedTextureStageStates{} + , m_vsVertexFixup(createVertexShader(g_vsVertexFixup)) { const UINT D3DBLENDOP_ADD = 1; const UINT UNINITIALIZED_STATE = 0xBAADBAAD; @@ -194,6 +198,17 @@ namespace D3dDdi updateConfig(); } + std::unique_ptr DeviceState::createVertexShader(const BYTE* code, UINT size) + { + D3DDDIARG_CREATEVERTEXSHADERFUNC data = {}; + data.Size = size; + if (FAILED(m_device.getOrigVtable().pfnCreateVertexShaderFunc(m_device, &data, reinterpret_cast(code)))) + { + return nullptr; + } + return { data.ShaderHandle, ResourceDeleter(m_device, m_device.getOrigVtable().pfnDeleteVertexShaderFunc) }; + } + HRESULT DeviceState::deleteShader(HANDLE shader, HANDLE State::* shaderMember, HRESULT(APIENTRY* origDeleteShaderFunc)(HANDLE, HANDLE)) { @@ -280,12 +295,24 @@ namespace D3dDdi const D3DDDIVERTEXELEMENT* vertexElements) { LOG_DEBUG << Compat::array(vertexElements, data->NumVertexElements); - HRESULT result = m_device.getOrigVtable().pfnCreateVertexShaderDecl(m_device, data, vertexElements); - if (SUCCEEDED(result)) + + const UINT D3DDECLUSAGE_POSITION = 0; + const UINT D3DDECLUSAGE_POSITIONT = 9; + for (UINT i = 0; i < data->NumVertexElements; ++i) { - m_vertexShaderDecls[data->ShaderHandle].assign(vertexElements, vertexElements + data->NumVertexElements); + if (D3DDECLUSAGE_POSITIONT == vertexElements[i].Usage) + { + std::vector ve(vertexElements, vertexElements + data->NumVertexElements); + ve[i].Usage = D3DDECLUSAGE_POSITION; + HRESULT result = m_device.getOrigVtable().pfnCreateVertexShaderDecl(m_device, data, ve.data()); + if (SUCCEEDED(result)) + { + m_swVertexShaderDecls.insert(data->ShaderHandle); + } + return result; + } } - return result; + return m_device.getOrigVtable().pfnCreateVertexShaderDecl(m_device, data, vertexElements); } HRESULT DeviceState::pfnDeletePixelShader(HANDLE shader) @@ -295,15 +322,10 @@ namespace D3dDdi HRESULT DeviceState::pfnDeleteVertexShaderDecl(HANDLE shader) { - const bool isCurrentShader = shader == m_current.vertexShaderDecl; HRESULT result = deleteShader(shader, &State::vertexShaderDecl, m_device.getOrigVtable().pfnDeleteVertexShaderDecl); if (SUCCEEDED(result)) { - m_vertexShaderDecls.erase(shader); - if (isCurrentShader) - { - m_device.getDrawPrimitive().setVertexShaderDecl({}); - } + m_swVertexShaderDecls.erase(shader); } return result; } @@ -675,15 +697,6 @@ namespace D3dDdi { if (setShader(decl, m_current.vertexShaderDecl, m_device.getOrigVtable().pfnSetVertexShaderDecl)) { - auto it = m_vertexShaderDecls.find(decl); - if (it != m_vertexShaderDecls.end()) - { - m_device.getDrawPrimitive().setVertexShaderDecl(it->second); - } - else - { - m_device.getDrawPrimitive().setVertexShaderDecl({}); - } LOG_DS << decl; } } @@ -696,12 +709,14 @@ namespace D3dDdi } } - void DeviceState::setViewport(const D3DDDIARG_VIEWPORTINFO& viewport) + bool DeviceState::setViewport(const D3DDDIARG_VIEWPORTINFO& viewport) { if (setData(viewport, m_current.viewport, m_device.getOrigVtable().pfnSetViewport)) { LOG_DS << viewport; + return true; } + return false; } void DeviceState::setWInfo(const D3DDDIARG_WINFO& wInfo) @@ -712,12 +727,14 @@ namespace D3dDdi } } - void DeviceState::setZRange(const D3DDDIARG_ZRANGE& zRange) + bool DeviceState::setZRange(const D3DDDIARG_ZRANGE& zRange) { if (setData(zRange, m_current.zRange, m_device.getOrigVtable().pfnSetZRange)) { LOG_DS << zRange; + return true; } + return false; } template @@ -745,11 +762,12 @@ namespace D3dDdi m_changedTextureStageStates[i].set(D3DDDITSS_MAXANISOTROPY); } m_maxChangedTextureStage = m_changedTextureStageStates.size() - 1; + updateVertexFixupConstants(); } void DeviceState::updateMisc() { - setViewport(m_app.viewport); + bool updateConstants = setViewport(m_app.viewport); auto wInfo = m_app.wInfo; if (1.0f == wInfo.WNear && 1.0f == wInfo.WFar) @@ -758,7 +776,12 @@ namespace D3dDdi } setWInfo(wInfo); - setZRange(m_app.zRange); + updateConstants |= setZRange(m_app.zRange); + + if (updateConstants) + { + updateVertexFixupConstants(); + } } void DeviceState::updateRenderStates() @@ -794,7 +817,14 @@ namespace D3dDdi { setPixelShader(m_app.pixelShader); setVertexShaderDecl(m_app.vertexShaderDecl); - setVertexShaderFunc(m_app.vertexShaderFunc); + if (m_swVertexShaderDecls.find(m_current.vertexShaderDecl) != m_swVertexShaderDecls.end()) + { + setVertexShaderFunc(m_vsVertexFixup.get()); + } + else + { + setVertexShaderFunc(m_app.vertexShaderFunc); + } } void DeviceState::updateStreamSource() @@ -864,4 +894,22 @@ namespace D3dDdi m_changedTextureStageStates[stage].reset(); } } + + void DeviceState::updateVertexFixupConstants() + { + D3DDDIARG_SETVERTEXSHADERCONST data = {}; + data.Register = 254; + data.Count = 2; + + const float apc = Config::alternatePixelCenter.get(); + const auto& vp = m_current.viewport; + const auto& zr = m_current.zRange; + + ShaderConstF registers[2] = { + { apc - vp.X - vp.Width / 2, apc - vp.Y - vp.Height / 2, -zr.MinZ, 0.0f }, + { 2.0f / vp.Width, -2.0f / vp.Height, 1.0f / (zr.MaxZ - zr.MinZ), 1.0f } + }; + + m_device.getOrigVtable().pfnSetVertexShaderConst(m_device, &data, registers); + } } diff --git a/DDrawCompat/D3dDdi/DeviceState.h b/DDrawCompat/D3dDdi/DeviceState.h index 75dc3f7..aeb1ea8 100644 --- a/DDrawCompat/D3dDdi/DeviceState.h +++ b/DDrawCompat/D3dDdi/DeviceState.h @@ -4,10 +4,12 @@ #include #include -#include +#include +#include #include #include +#include const UINT D3DTEXF_NONE = 0; const UINT D3DTEXF_POINT = 1; @@ -130,6 +132,13 @@ namespace D3dDdi D3DDDIARG_ZRANGE zRange; }; + template + std::unique_ptr createVertexShader(const BYTE(&code)[N]) + { + return createVertexShader(code, N); + } + + std::unique_ptr DeviceState::createVertexShader(const BYTE* code, UINT size); HRESULT deleteShader(HANDLE shader, HANDLE State::* shaderMember, HRESULT(APIENTRY* origDeleteShaderFunc)(HANDLE, HANDLE)); @@ -157,9 +166,9 @@ namespace D3dDdi void setTextureStageState(const D3DDDIARG_TEXTURESTAGESTATE& tss); void setVertexShaderDecl(HANDLE decl); void setVertexShaderFunc(HANDLE shader); - void setViewport(const D3DDDIARG_VIEWPORTINFO& viewport); + bool setViewport(const D3DDDIARG_VIEWPORTINFO& viewport); void setWInfo(const D3DDDIARG_WINFO& wInfo); - void setZRange(const D3DDDIARG_ZRANGE& zRange); + bool setZRange(const D3DDDIARG_ZRANGE& zRange); void updateMisc(); void updateRenderStates(); @@ -168,6 +177,7 @@ namespace D3dDdi void updateStreamSource(); void updateTextureColorKey(UINT stage); void updateTextureStages(); + void updateVertexFixupConstants(); Device& m_device; State m_app; @@ -178,10 +188,11 @@ namespace D3dDdi std::array m_vertexShaderConst; std::array m_vertexShaderConstB; std::array m_vertexShaderConstI; - std::map> m_vertexShaderDecls; + std::set m_swVertexShaderDecls; UINT m_changedStates; UINT m_maxChangedTextureStage; BitSet m_changedRenderStates; std::array, 8> m_changedTextureStageStates; + std::unique_ptr m_vsVertexFixup; }; } diff --git a/DDrawCompat/D3dDdi/DrawPrimitive.cpp b/DDrawCompat/D3dDdi/DrawPrimitive.cpp index 86e735b..2eef343 100644 --- a/DDrawCompat/D3dDdi/DrawPrimitive.cpp +++ b/DDrawCompat/D3dDdi/DrawPrimitive.cpp @@ -56,7 +56,6 @@ 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"); @@ -622,23 +621,6 @@ namespace D3dDdi INT DrawPrimitive::loadVertices(UINT count) { auto vertices = m_batched.vertices.data(); - if (!m_isHwVertexProcessingUsed) - { - const float pixelOffset = Config::alternatePixelCenter.get(); - 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; - } - v->sx += pixelOffset; - v->sy += pixelOffset; - offset += m_streamSource.stride; - } - } - if (m_vertexBuffer) { UINT size = count * m_streamSource.stride; @@ -766,18 +748,4 @@ namespace D3dDdi } 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 d8b6467..29029e6 100644 --- a/DDrawCompat/D3dDdi/DrawPrimitive.h +++ b/DDrawCompat/D3dDdi/DrawPrimitive.h @@ -26,7 +26,6 @@ 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 @@ -86,6 +85,5 @@ namespace D3dDdi StreamSource m_streamSource; 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 792eba0..38a88f3 100644 --- a/DDrawCompat/D3dDdi/Log/DeviceFuncsLog.cpp +++ b/DDrawCompat/D3dDdi/Log/DeviceFuncsLog.cpp @@ -272,6 +272,15 @@ std::ostream& operator<<(std::ostream& os, const D3DDDIARG_UNLOCK& val) << Compat::hex(val.Flags.Value); } +std::ostream& operator<<(std::ostream& os, const D3DDDIARG_VIEWPORTINFO& val) +{ + return Compat::LogStruct(os) + << val.X + << val.Y + << val.Width + << val.Height; +} + std::ostream& operator<<(std::ostream& os, const D3DDDIARG_WINFO& val) { return Compat::LogStruct(os) diff --git a/DDrawCompat/D3dDdi/Log/DeviceFuncsLog.h b/DDrawCompat/D3dDdi/Log/DeviceFuncsLog.h index 3ff698c..17e1043 100644 --- a/DDrawCompat/D3dDdi/Log/DeviceFuncsLog.h +++ b/DDrawCompat/D3dDdi/Log/DeviceFuncsLog.h @@ -34,6 +34,7 @@ std::ostream& operator<<(std::ostream& os, const D3DDDIARG_SETSTREAMSOURCEUM& va std::ostream& operator<<(std::ostream& os, const D3DDDIARG_SETVERTEXSHADERCONST& val); std::ostream& operator<<(std::ostream& os, const D3DDDIARG_TEXTURESTAGESTATE& val); std::ostream& operator<<(std::ostream& os, const D3DDDIARG_UNLOCK& val); +std::ostream& operator<<(std::ostream& os, const D3DDDIARG_VIEWPORTINFO& val); std::ostream& operator<<(std::ostream& os, const D3DDDIARG_WINFO& val); std::ostream& operator<<(std::ostream& os, const D3DDDIARG_ZRANGE& val); std::ostream& operator<<(std::ostream& os, const D3DDDIBOX& val); diff --git a/DDrawCompat/DDrawCompat.vcxproj b/DDrawCompat/DDrawCompat.vcxproj index 6361d2e..b0ebd19 100644 --- a/DDrawCompat/DDrawCompat.vcxproj +++ b/DDrawCompat/DDrawCompat.vcxproj @@ -435,6 +435,14 @@ + + Vertex + Vertex + Vertex + g_vs%(Filename) + g_vs%(Filename) + g_vs%(Filename) + diff --git a/DDrawCompat/DDrawCompat.vcxproj.filters b/DDrawCompat/DDrawCompat.vcxproj.filters index 385c937..6f5a6b4 100644 --- a/DDrawCompat/DDrawCompat.vcxproj.filters +++ b/DDrawCompat/DDrawCompat.vcxproj.filters @@ -821,6 +821,9 @@ Shaders + + Shaders + diff --git a/DDrawCompat/Direct3d/Log.cpp b/DDrawCompat/Direct3d/Log.cpp index 163eb71..0a806e4 100644 --- a/DDrawCompat/Direct3d/Log.cpp +++ b/DDrawCompat/Direct3d/Log.cpp @@ -131,3 +131,44 @@ std::ostream& operator<<(std::ostream& os, const D3DVERTEXBUFFERDESC& data) << Compat::hex(data.dwFVF) << data.dwNumVertices; } + +std::ostream& operator<<(std::ostream& os, const D3DVIEWPORT& data) +{ + return Compat::LogStruct(os) + << data.dwX + << data.dwY + << data.dwWidth + << data.dwHeight + << data.dvScaleX + << data.dvScaleY + << data.dvMaxX + << data.dvMaxY + << data.dvMinZ + << data.dvMaxZ; +} + +std::ostream& operator<<(std::ostream& os, const D3DVIEWPORT2& data) +{ + return Compat::LogStruct(os) + << data.dwX + << data.dwY + << data.dwWidth + << data.dwHeight + << data.dvClipX + << data.dvClipY + << data.dvClipWidth + << data.dvClipHeight + << data.dvMinZ + << data.dvMaxZ; +} + +std::ostream& operator<<(std::ostream& os, const D3DVIEWPORT7& data) +{ + return Compat::LogStruct(os) + << data.dwX + << data.dwY + << data.dwWidth + << data.dwHeight + << data.dvMinZ + << data.dvMaxZ; +} diff --git a/DDrawCompat/Direct3d/Log.h b/DDrawCompat/Direct3d/Log.h index 6607755..0d2c443 100644 --- a/DDrawCompat/Direct3d/Log.h +++ b/DDrawCompat/Direct3d/Log.h @@ -17,3 +17,6 @@ std::ostream& operator<<(std::ostream& os, const D3DMATERIAL7& data); std::ostream& operator<<(std::ostream& os, const D3DRECT& data); std::ostream& operator<<(std::ostream& os, const D3DSTATUS& data); std::ostream& operator<<(std::ostream& os, const D3DVERTEXBUFFERDESC& data); +std::ostream& operator<<(std::ostream& os, const D3DVIEWPORT& data); +std::ostream& operator<<(std::ostream& os, const D3DVIEWPORT2& data); +std::ostream& operator<<(std::ostream& os, const D3DVIEWPORT7& data); diff --git a/DDrawCompat/Shaders/VertexFixup.hlsl b/DDrawCompat/Shaders/VertexFixup.hlsl new file mode 100644 index 0000000..af1c6ce --- /dev/null +++ b/DDrawCompat/Shaders/VertexFixup.hlsl @@ -0,0 +1,23 @@ +float4 g_offset : register(c254); +float4 g_multiplier : register(c255); + +struct VS +{ + float4 pos : POSITION; + float fog : FOG; + float4 color[2] : COLOR; + float4 tex[8] : TEXCOORD; +}; + +VS main(const VS i) +{ + const float w = (i.pos.w > 0 && 1 / i.pos.w > 0) ? 1 / i.pos.w : 1; + + VS o = i; + o.pos = (i.pos + g_offset) * g_multiplier; + o.pos.z = saturate(o.pos.z); + o.pos.xyz *= w; + o.pos.w = w; + o.fog = i.color[1].a; + return o; +}