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

Replace RHW=INFINITY with RHW=1

Fixes invisible gauge needles in NASCAR Racing 3 (issue #83).
This commit is contained in:
narzoul 2021-01-12 20:17:52 +01:00
parent e9a2bdc83f
commit 324b4a77f0
9 changed files with 113 additions and 36 deletions

View File

@ -205,7 +205,7 @@ namespace D3dDdi
data.pSurfList[0].pSysMem)
{
m_drawPrimitive.addSysMemVertexBuffer(data.hResource,
static_cast<BYTE*>(const_cast<void*>(data.pSurfList[0].pSysMem)), data.Fvf);
static_cast<BYTE*>(const_cast<void*>(data.pSurfList[0].pSysMem)));
}
return S_OK;
}

View File

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

View File

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

View File

@ -1,5 +1,8 @@
#include <Common/Log.h>
#include <D3dDdi/Device.h>
#include <D3dDdi/DeviceState.h>
#include <D3dDdi/DrawPrimitive.h>
#include <D3dDdi/Log/DeviceFuncsLog.h>
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)

View File

@ -1,6 +1,7 @@
#pragma once
#include <array>
#include <map>
#include <vector>
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<ShaderConstF> m_vertexShaderConst;
std::vector<BOOL> m_vertexShaderConstB;
std::vector<ShaderConstI> m_vertexShaderConstI;
std::map<HANDLE, std::vector<D3DDDIVERTEXELEMENT>> m_vertexShaderDecls;
HANDLE m_vertexShaderDecl;
HANDLE m_vertexShaderFunc;
D3DDDIARG_WINFO m_wInfo;

View File

@ -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<D3DTLVERTEX*>(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<INT>(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<D3DTLVERTEX*>(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<const BYTE*>(umBuffer), data.Stride, 0);
return setSysMemStreamSource(static_cast<const BYTE*>(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<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

@ -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<D3DDDIVERTEXELEMENT>& 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<HANDLE, SysMemVertexBuffer> m_sysMemVertexBuffers;
std::map<HANDLE, BYTE*> m_sysMemVertexBuffers;
BatchedPrimitives m_batched;
bool m_isHwVertexProcessingUsed;
};
}

View File

@ -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<DWORD>(val);
}
std::ostream& operator<<(std::ostream& os, const D3DDDIVERTEXELEMENT& val)
{
return Compat::LogStruct(os)
<< val.Stream
<< val.Offset
<< static_cast<UINT>(val.Type)
<< static_cast<UINT>(val.Method)
<< static_cast<UINT>(val.Usage)
<< static_cast<UINT>(val.UsageIndex);
}

View File

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