1
0
mirror of https://github.com/narzoul/DDrawCompat synced 2024-12-30 08:55:36 +01:00

Fix vertex positions via vertex shader

This commit is contained in:
narzoul 2021-12-20 00:30:59 +01:00
parent 075287b16a
commit 8b393ea498
11 changed files with 175 additions and 62 deletions

View File

@ -1,3 +1,5 @@
#include <algorithm>
#include <Config/Config.h>
#include <Common/Log.h>
#include <D3dDdi/Device.h>
@ -5,6 +7,7 @@
#include <D3dDdi/DrawPrimitive.h>
#include <D3dDdi/Log/DeviceFuncsLog.h>
#include <D3dDdi/Resource.h>
#include <Shaders/VertexFixup.h>
#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<void, ResourceDeleter> DeviceState::createVertexShader(const BYTE* code, UINT size)
{
D3DDDIARG_CREATEVERTEXSHADERFUNC data = {};
data.Size = size;
if (FAILED(m_device.getOrigVtable().pfnCreateVertexShaderFunc(m_device, &data, reinterpret_cast<const UINT*>(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<D3DDDIVERTEXELEMENT> 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 <typename SetShaderConstData, typename ShaderConstArray, typename Register>
@ -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);
}
}

View File

@ -4,10 +4,12 @@
#include <d3dumddi.h>
#include <array>
#include <map>
#include <set>
#include <memory>
#include <vector>
#include <Common/BitSet.h>
#include <D3dDdi/ResourceDeleter.h>
const UINT D3DTEXF_NONE = 0;
const UINT D3DTEXF_POINT = 1;
@ -130,6 +132,13 @@ namespace D3dDdi
D3DDDIARG_ZRANGE zRange;
};
template <int N>
std::unique_ptr<void, ResourceDeleter> createVertexShader(const BYTE(&code)[N])
{
return createVertexShader(code, N);
}
std::unique_ptr<void, ResourceDeleter> 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<ShaderConstF, 256> m_vertexShaderConst;
std::array<ShaderConstB, 16> m_vertexShaderConstB;
std::array<ShaderConstI, 16> m_vertexShaderConstI;
std::map<HANDLE, std::vector<D3DDDIVERTEXELEMENT>> m_vertexShaderDecls;
std::set<HANDLE> m_swVertexShaderDecls;
UINT m_changedStates;
UINT m_maxChangedTextureStage;
BitSet<D3DDDIRS_ZENABLE, D3DDDIRS_BLENDOPALPHA> m_changedRenderStates;
std::array<BitSet<D3DDDITSS_TEXTUREMAP, D3DDDITSS_TEXTURECOLORKEYVAL>, 8> m_changedTextureStageStates;
std::unique_ptr<void, ResourceDeleter> m_vsVertexFixup;
};
}

View File

@ -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<D3DTLVERTEX*>(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<D3DDDIVERTEXELEMENT>& decl)
{
m_isHwVertexProcessingUsed = true;
const UINT D3DDECLUSAGE_POSITIONT = 9;
for (auto& vertexElement : decl)
{
if (D3DDECLUSAGE_POSITIONT == vertexElement.Usage)
{
m_isHwVertexProcessingUsed = false;
return;
}
}
}
}

View File

@ -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<D3DDDIVERTEXELEMENT>& decl);
private:
struct BatchedPrimitives
@ -86,6 +85,5 @@ namespace D3dDdi
StreamSource m_streamSource;
std::map<HANDLE, BYTE*> m_sysMemVertexBuffers;
BatchedPrimitives m_batched;
bool m_isHwVertexProcessingUsed;
};
}

View File

@ -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)

View File

@ -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);

View File

@ -435,6 +435,14 @@
<FxCompile Include="Shaders\GenBilinear.hlsl" />
<FxCompile Include="Shaders\PaletteLookup.hlsl" />
<FxCompile Include="Shaders\TextureSampler.hlsl" />
<FxCompile Include="Shaders\VertexFixup.hlsl">
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Vertex</ShaderType>
<ShaderType Condition="'$(Configuration)|$(Platform)'=='ReleaseWithDebugLogs|Win32'">Vertex</ShaderType>
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Vertex</ShaderType>
<VariableName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">g_vs%(Filename)</VariableName>
<VariableName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">g_vs%(Filename)</VariableName>
<VariableName Condition="'$(Configuration)|$(Platform)'=='ReleaseWithDebugLogs|Win32'">g_vs%(Filename)</VariableName>
</FxCompile>
</ItemGroup>
<ItemGroup>
<Image Include="arrow.bmp" />

View File

@ -821,6 +821,9 @@
<FxCompile Include="Shaders\TextureSampler.hlsl">
<Filter>Shaders</Filter>
</FxCompile>
<FxCompile Include="Shaders\VertexFixup.hlsl">
<Filter>Shaders</Filter>
</FxCompile>
</ItemGroup>
<ItemGroup>
<Image Include="arrow.bmp">

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}