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

Added VertexFixup setting

See issues  and .
This commit is contained in:
narzoul 2024-06-23 19:35:03 +02:00
parent f2ea02b960
commit 0b974e2dd7
9 changed files with 230 additions and 27 deletions

@ -48,6 +48,7 @@
#include <Config/Settings/TextureFilter.h>
#include <Config/Settings/ThreadPriorityBoost.h>
#include <Config/Settings/VertexBufferMemoryType.h>
#include <Config/Settings/VertexFixup.h>
#include <Config/Settings/VSync.h>
#include <Config/Settings/WinVersionLie.h>
@ -103,6 +104,7 @@ namespace Config
Settings::TextureFilter textureFilter;
Settings::ThreadPriorityBoost threadPriorityBoost;
Settings::VertexBufferMemoryType vertexBufferMemoryType;
Settings::VertexFixup vertexFixup;
Settings::VSync vSync;
Settings::WinVersionLie winVersionLie;
}

@ -0,0 +1,22 @@
#pragma once
#include <Config/EnumSetting.h>
namespace Config
{
namespace Settings
{
class VertexFixup : public EnumSetting
{
public:
enum Values { CPU, GPU };
VertexFixup()
: EnumSetting("VertexFixup", "gpu", { "cpu", "gpu" })
{
}
};
}
extern Settings::VertexFixup vertexFixup;
}

@ -5,6 +5,7 @@
#include <Config/Settings/SpriteFilter.h>
#include <Config/Settings/SpriteTexCoord.h>
#include <Config/Settings/TextureFilter.h>
#include <Config/Settings/VertexFixup.h>
#include <Common/Comparison.h>
#include <Common/Log.h>
#include <D3dDdi/Device.h>
@ -88,6 +89,8 @@ namespace D3dDdi
, m_vertexShaderConstB{}
, m_vertexShaderConstI{}
, m_vertexDecl(nullptr)
, m_vertexFixupConfig(Config::vertexFixup.get())
, m_vertexFixupData{}
, m_changedStates(0)
, m_maxChangedTextureStage(0)
, m_texCoordIndexes(0)
@ -100,6 +103,8 @@ namespace D3dDdi
const UINT D3DBLENDOP_ADD = 1;
const UINT UNINITIALIZED_STATE = 0xBAADBAAD;
m_vertexFixupData.multiplier[3] = 1.0f;
m_device.getOrigVtable().pfnSetDepthStencil(m_device, &m_current.depthStencil);
m_device.getOrigVtable().pfnSetRenderTarget(m_device, &m_current.renderTarget);
m_device.getOrigVtable().pfnSetViewport(m_device, &m_current.viewport);
@ -298,6 +303,10 @@ namespace D3dDdi
{
updateTextureStages();
}
if (m_changedStates & CS_VERTEX_FIXUP)
{
updateVertexFixupShaderConst();
}
m_changedStates = 0;
m_maxChangedTextureStage = 0;
@ -1012,18 +1021,10 @@ namespace D3dDdi
auto resource = (texture == m_app.textures[stage]) ? getTextureResource(stage) : m_device.getResource(texture);
if (resource)
{
D3DDDIARG_SETVERTEXSHADERCONST data = {};
data.Register = 253;
data.Count = 1;
auto& si = resource->getFixedDesc().pSurfList[0];
ShaderConstF reg = { static_cast<float>(si.Width), static_cast<float>(si.Height),
m_vertexShaderConst[253][2], m_vertexShaderConst[253][3] };
if (0 != memcmp(&reg, &m_vertexShaderConst[data.Register], sizeof(reg)))
{
pfnSetVertexShaderConst(&data, &reg);
}
m_vertexFixupData.texCoordAdj[0] = static_cast<float>(si.Width);
m_vertexFixupData.texCoordAdj[1] = static_cast<float>(si.Height);
m_changedStates |= CS_VERTEX_FIXUP;
}
}
@ -1107,6 +1108,7 @@ namespace D3dDdi
m_changedStates |= CS_RENDER_STATE | CS_RENDER_TARGET | CS_SHADER | CS_TEXTURE_STAGE;
m_changedRenderStates.set(D3DDDIRS_COLORKEYENABLE);
m_changedRenderStates.set(D3DDDIRS_MULTISAMPLEANTIALIAS);
m_vertexFixupConfig = Config::vertexFixup.get();
for (auto& ps : m_pixelShaders)
{
@ -1211,7 +1213,7 @@ namespace D3dDdi
{
const float sx = static_cast<float>(scaledVp.Width) / vp.Width;
const float sy = static_cast<float>(scaledVp.Height) / vp.Height;
updateVertexFixupConstants(vp.Width, vp.Height, sx, sy);
updateVertexFixupData(vp.Width, vp.Height, sx, sy);
}
const bool isScissorRectNeeded = isTransformed && 0 != memcmp(&vp, &m_app.viewport, sizeof(vp));
@ -1230,7 +1232,16 @@ namespace D3dDdi
{
setPixelShader(mapPixelShader(m_app.pixelShader));
setVertexShaderDecl(m_app.vertexShaderDecl);
setVertexShaderFunc(getVertexDecl().isTransformed ? getVsVertexFixup() : m_app.vertexShaderFunc);
if (Config::Settings::VertexFixup::GPU == m_vertexFixupConfig &&
getVertexDecl().isTransformed)
{
setVertexShaderFunc(getVsVertexFixup());
}
else
{
setVertexShaderFunc(m_app.vertexShaderFunc);
}
}
void DeviceState::updateStreamSource()
@ -1321,25 +1332,51 @@ namespace D3dDdi
}
}
void DeviceState::updateVertexFixupConstants(UINT width, UINT height, float sx, float sy)
void DeviceState::updateVertexFixupData(UINT width, UINT height, float sx, float sy)
{
D3DDDIARG_SETVERTEXSHADERCONST data = {};
data.Register = 253;
data.Count = 3;
const float stc = static_cast<float>(Config::spriteTexCoord.getParam()) / 100;
const float apc = Config::alternatePixelCenter.get();
const auto& zr = m_current.zRange;
ShaderConstF registers[3] = {
{ m_vertexShaderConst[253][0], m_vertexShaderConst[253][1], stc, stc },
{ 0.5f + apc - 0.5f / sx - width / 2, 0.5f + apc - 0.5f / sy - height / 2, -zr.MinZ, 0.0f },
{ 2.0f / width, -2.0f / height, 1.0f / (zr.MaxZ - zr.MinZ), 1.0f }
};
m_vertexFixupData.texCoordAdj[2] = stc;
m_vertexFixupData.texCoordAdj[3] = stc;
if (0 != memcmp(registers, &m_vertexShaderConst[data.Register], sizeof(registers)))
if (Config::Settings::VertexFixup::GPU == m_vertexFixupConfig)
{
pfnSetVertexShaderConst(&data, registers);
m_vertexFixupData.offset[0] = 0.5f + apc - 0.5f / sx - width / 2;
m_vertexFixupData.offset[1] = 0.5f + apc - 0.5f / sy - height / 2;
m_vertexFixupData.offset[2] = -zr.MinZ;
m_vertexFixupData.multiplier[0] = 2.0f / width;
m_vertexFixupData.multiplier[1] = -2.0f / height;
m_vertexFixupData.multiplier[2] = 1.0f / (zr.MaxZ - zr.MinZ);
}
else
{
m_vertexFixupData.offset[0] = 0.5f + apc - 0.5f / sx;
m_vertexFixupData.offset[1] = 0.5f + apc - 0.5f / sy;
m_vertexFixupData.multiplier[0] = sx;
m_vertexFixupData.multiplier[1] = sy;
}
m_changedStates |= CS_VERTEX_FIXUP;
}
void DeviceState::updateVertexFixupShaderConst()
{
if (m_current.vertexShaderFunc == m_app.vertexShaderFunc)
{
return;
}
D3DDDIARG_SETVERTEXSHADERCONST data = {};
data.Register = 253;
data.Count = 3;
if (0 != memcmp(&m_vertexFixupData, &m_vertexShaderConst[data.Register], sizeof(m_vertexFixupData)))
{
pfnSetVertexShaderConst(&data, &m_vertexFixupData.texCoordAdj);
}
}
}

@ -109,6 +109,13 @@ namespace D3dDdi
bool isTransformed;
};
struct VertexFixupData
{
ShaderConstF texCoordAdj;
ShaderConstF offset;
ShaderConstF multiplier;
};
DeviceState(Device& device);
HRESULT pfnCreatePixelShader(D3DDDIARG_CREATEPIXELSHADER* data, const UINT* code);
@ -153,9 +160,11 @@ namespace D3dDdi
void flush();
const State& getAppState() const { return m_app; }
const State& getCurrentState() const { return m_current; }
bool getSpriteMode() const { return m_spriteMode; }
Resource* getTextureResource(UINT stage);
UINT getTextureStageCount() const;
const VertexDecl& getVertexDecl() const;
const VertexFixupData& getVertexFixupData() const { return m_vertexFixupData; }
bool isLocked() const { return m_isLocked; }
void onDestroyResource(Resource* resource, HANDLE resourceHandle);
void updateConfig();
@ -168,7 +177,8 @@ namespace D3dDdi
CS_RENDER_TARGET = 1 << 1,
CS_SHADER = 1 << 2,
CS_STREAM_SOURCE = 1 << 3,
CS_TEXTURE_STAGE = 1 << 4
CS_TEXTURE_STAGE = 1 << 4,
CS_VERTEX_FIXUP = 1 << 5
};
struct PixelShader
@ -230,7 +240,8 @@ namespace D3dDdi
void updateShaders();
void updateTextureColorKey(UINT stage);
void updateTextureStages();
void updateVertexFixupConstants(UINT width, UINT height, float sx, float sy);
void updateVertexFixupData(UINT width, UINT height, float sx, float sy);
void updateVertexFixupShaderConst();
Device& m_device;
State m_app;
@ -243,6 +254,8 @@ namespace D3dDdi
std::array<ShaderConstI, 16> m_vertexShaderConstI;
std::map<HANDLE, VertexDecl> m_vertexShaderDecls;
VertexDecl* m_vertexDecl;
UINT m_vertexFixupConfig;
VertexFixupData m_vertexFixupData;
UINT m_changedStates;
UINT m_maxChangedTextureStage;
UINT m_texCoordIndexes;

@ -12,6 +12,14 @@ namespace
const UINT INDEX_BUFFER_SIZE = D3DMAXNUMPRIMITIVES * 3 * sizeof(UINT16);
const UINT VERTEX_BUFFER_SIZE = 1024 * 1024;
enum VertexFixupFlags
{
VF_XY = 1 << 0,
VF_Z = 1 << 1,
VF_RHW = 1 << 2,
VF_TEXCOORD = 1 << 3
};
UINT getVertexCount(D3DPRIMITIVETYPE primitiveType, UINT primitiveCount)
{
switch (primitiveType)
@ -57,6 +65,7 @@ namespace D3dDdi
, m_indexBuffer(device, m_vertexBuffer ? INDEX_BUFFER_SIZE : 0)
, m_streamSource{}
, m_batched{}
, m_vertexFixupFlags(0)
{
LOG_ONCE("Dynamic vertex buffers are " << (m_vertexBuffer ? "" : "not ") << "available");
LOG_ONCE("Dynamic index buffers are " << (m_indexBuffer ? "" : "not ") << "available");
@ -325,6 +334,74 @@ namespace D3dDdi
{
auto vertices = m_streamSource.vertices + base * m_streamSource.stride;
m_batched.vertices.insert(m_batched.vertices.end(), vertices, vertices + count * m_streamSource.stride);
if (0 == m_vertexFixupFlags)
{
return;
}
auto& vertexFixupData = m_device.getState().getVertexFixupData();
auto firstVertex = &m_batched.vertices[m_batched.vertices.size() - count * m_streamSource.stride];
if (m_vertexFixupFlags & VF_XY)
{
auto vPos = firstVertex;
for (unsigned i = 0; i < count; ++i)
{
auto v = reinterpret_cast<D3DTLVERTEX*>(vPos);
v->sx += vertexFixupData.offset[0];
v->sy += vertexFixupData.offset[1];
v->sx *= vertexFixupData.multiplier[0];
v->sy *= vertexFixupData.multiplier[1];
vPos += m_streamSource.stride;
}
}
if (m_vertexFixupFlags & VF_Z)
{
auto zPos = reinterpret_cast<BYTE*>(&reinterpret_cast<D3DTLVERTEX*>(firstVertex)->sz);
for (unsigned i = 0; i < count; ++i)
{
auto& z = *reinterpret_cast<float*>(zPos);
if (z > 1)
{
z = 1;
}
zPos += m_streamSource.stride;
}
}
if (m_vertexFixupFlags & VF_RHW)
{
auto rhwPos = reinterpret_cast<BYTE*>(&reinterpret_cast<D3DTLVERTEX*>(firstVertex)->rhw);
for (unsigned i = 0; i < count; ++i)
{
auto& rhw = *reinterpret_cast<float*>(rhwPos);
if (0 == rhw || INFINITY == rhw)
{
rhw = 1;
}
rhwPos += m_streamSource.stride;
}
}
if (m_vertexFixupFlags & VF_TEXCOORD)
{
auto tcPos = firstVertex + m_device.getState().getVertexDecl().texCoordOffset[0];
for (unsigned i = 0; i < count; ++i)
{
float* tc = reinterpret_cast<float*>(tcPos);
tc[0] *= vertexFixupData.texCoordAdj[0];
tc[1] *= vertexFixupData.texCoordAdj[1];
tc[0] += vertexFixupData.texCoordAdj[2];
tc[1] += vertexFixupData.texCoordAdj[3];
tc[0] = roundf(tc[0]);
tc[1] = roundf(tc[1]);
tc[0] /= vertexFixupData.texCoordAdj[0];
tc[1] /= vertexFixupData.texCoordAdj[1];
tcPos += m_streamSource.stride;
}
}
}
void DrawPrimitive::clearBatchedPrimitives()
@ -456,6 +533,7 @@ namespace D3dDdi
{
auto& state = m_device.getState();
auto vertexCount = getVertexCount(data.PrimitiveType, data.PrimitiveCount);
m_vertexFixupFlags = 0;
if (!state.isLocked())
{
if (0 == m_batched.primitiveCount)
@ -477,6 +555,7 @@ namespace D3dDdi
state.setSpriteMode(false);
}
state.flush();
setVertexFixupFlags(data.VStart, 0);
}
if (0 == m_batched.primitiveCount || flagBuffer ||
@ -521,6 +600,7 @@ namespace D3dDdi
auto indexCount = getVertexCount(data.PrimitiveType, data.PrimitiveCount);
auto vStart = data.BaseVertexOffset / static_cast<INT>(m_streamSource.stride);
m_vertexFixupFlags = 0;
if (!state.isLocked())
{
if (m_streamSource.vertices && data.PrimitiveType >= D3DPT_TRIANGLELIST)
@ -537,6 +617,7 @@ namespace D3dDdi
state.setSpriteMode(false);
}
state.flush();
setVertexFixupFlags(vStart, indices[0]);
}
auto [min, max] = std::minmax_element(indices, indices + indexCount);
@ -870,4 +951,44 @@ namespace D3dDdi
}
}
}
void DrawPrimitive::setVertexFixupFlags(INT baseVertexIndex, UINT16 index)
{
auto& state = m_device.getState();
if (!state.getVertexDecl().isTransformed ||
state.getCurrentState().vertexShaderFunc != state.getAppState().vertexShaderFunc)
{
return;
}
auto& vertexFixupData = state.getVertexFixupData();
if (0 != vertexFixupData.offset[0] ||
0 != vertexFixupData.offset[1] ||
1 != vertexFixupData.multiplier[0] ||
1 != vertexFixupData.multiplier[1])
{
m_vertexFixupFlags |= VF_XY;
}
auto vertex = reinterpret_cast<const D3DTLVERTEX*>(
m_streamSource.vertices + (baseVertexIndex + index) * m_streamSource.stride);
if (vertex->sz > 0)
{
m_vertexFixupFlags |= VF_Z;
}
if (0 == vertex->rhw || INFINITY == vertex->rhw)
{
m_vertexFixupFlags |= VF_RHW;
}
const UINT D3DDECLTYPE_FLOAT2 = 1;
if (state.getSpriteMode() &&
Config::Settings::SpriteTexCoord::ROUND == Config::spriteTexCoord.get() &&
0 != Config::spriteTexCoord.getParam() &&
D3DDECLTYPE_FLOAT2 == state.getVertexDecl().texCoordType[0])
{
m_vertexFixupFlags |= VF_TEXCOORD;
}
}
}

@ -71,6 +71,7 @@ namespace D3dDdi
HRESULT flush(const UINT* flagBuffer);
HRESULT flushIndexed(const UINT* flagBuffer);
bool isSprite(INT baseVertexIndex, UINT16 index0, UINT16 index1, UINT16 index2);
void setVertexFixupFlags(INT baseVertexIndex, UINT16 index);
INT loadIndices(const void* indices, UINT count);
INT loadVertices(UINT count);
UINT getBatchedVertexCount() const;
@ -87,5 +88,6 @@ namespace D3dDdi
StreamSource m_streamSource;
std::map<HANDLE, BYTE*> m_sysMemVertexBuffers;
BatchedPrimitives m_batched;
UINT m_vertexFixupFlags;
};
}

@ -214,6 +214,7 @@
<ClInclude Include="Config\Settings\TextureFilter.h" />
<ClInclude Include="Config\Settings\ThreadPriorityBoost.h" />
<ClInclude Include="Config\Settings\VertexBufferMemoryType.h" />
<ClInclude Include="Config\Settings\VertexFixup.h" />
<ClInclude Include="Config\Settings\VSync.h" />
<ClInclude Include="Config\Settings\WinVersionLie.h" />
<ClInclude Include="D3dDdi\Adapter.h" />

@ -717,6 +717,9 @@
<ClInclude Include="Common\Disasm.h">
<Filter>Header Files\Common</Filter>
</ClInclude>
<ClInclude Include="Config\Settings\VertexFixup.h">
<Filter>Header Files\Config\Settings</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Gdi\Gdi.cpp">

@ -25,6 +25,7 @@
#include <Config/Settings/StatsPosY.h>
#include <Config/Settings/StatsTransparency.h>
#include <Config/Settings/TextureFilter.h>
#include <Config/Settings/VertexFixup.h>
#include <Config/Settings/VSync.h>
#include <D3dDdi/Device.h>
#include <Gdi/GuiThread.h>
@ -66,6 +67,7 @@ namespace
{ &Config::statsPosY, []() { Gdi::GuiThread::getStatsWindow()->updatePos(); } },
{ &Config::statsTransparency, [&]() { Gdi::GuiThread::getStatsWindow()->setAlpha(Config::statsTransparency.get()); }},
{ &Config::textureFilter, &D3dDdi::Device::updateAllConfig },
{ &Config::vertexFixup, &D3dDdi::Device::updateAllConfig },
{ &Config::vSync }
};
}