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:
parent
075287b16a
commit
8b393ea498
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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" />
|
||||
|
@ -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">
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
23
DDrawCompat/Shaders/VertexFixup.hlsl
Normal file
23
DDrawCompat/Shaders/VertexFixup.hlsl
Normal 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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user