From 47ea099a9221892afe8bd465ec31e26272696a4c Mon Sep 17 00:00:00 2001 From: ergo720 <45463469+ergo720@users.noreply.github.com> Date: Sat, 10 Oct 2020 17:20:54 +0200 Subject: [PATCH] Use std::vector for g_InlineVertexBuffer_Table instead of realloc --- src/core/hle/D3D8/Direct3D9/Direct3D9.cpp | 18 ++++++-- src/core/hle/D3D8/XbVertexBuffer.cpp | 54 ++++++++++++++++++++++- src/core/hle/D3D8/XbVertexBuffer.h | 27 +++++++----- 3 files changed, 82 insertions(+), 17 deletions(-) diff --git a/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp b/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp index 541834118..0090d9b8b 100644 --- a/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp +++ b/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp @@ -4606,20 +4606,30 @@ xbox::void_xt WINAPI xbox::EMUPATCH(D3DDevice_SetVertexData4f) // Grow g_InlineVertexBuffer_Table to contain at least current, and a potentially next vertex if (g_InlineVertexBuffer_TableLength <= g_InlineVertexBuffer_TableOffset + 1) { + UINT InlineVertexBuffer_TableLength_Original = g_InlineVertexBuffer_TableLength; if (g_InlineVertexBuffer_TableLength == 0) { g_InlineVertexBuffer_TableLength = PAGE_SIZE / sizeof(struct _D3DIVB); } else { g_InlineVertexBuffer_TableLength *= 2; } - g_InlineVertexBuffer_Table = (struct _D3DIVB*)realloc(g_InlineVertexBuffer_Table, sizeof(struct _D3DIVB) * g_InlineVertexBuffer_TableLength); - EmuLog(LOG_LEVEL::DEBUG, "Reallocated g_InlineVertexBuffer_Table to %d entries", g_InlineVertexBuffer_TableLength); + for (unsigned i = 0; i < (g_InlineVertexBuffer_TableLength - InlineVertexBuffer_TableLength_Original); ++i) { + g_InlineVertexBuffer_Table.emplace_back(_D3DIVB{}); + } + + EmuLog(LOG_LEVEL::DEBUG, "Expanded g_InlineVertexBuffer_Table to %u entries", g_InlineVertexBuffer_TableLength); + + // Sanity check: ensure that g_InlineVertexBuffer_Table is not growing indefinetly. This can happen if D3DDevice_Begin and D3DDevice_End + // are not patched, since they both reset g_InlineVertexBuffer_TableOffset back to zero, thus preventing further growth + if (g_InlineVertexBuffer_TableLength > 50000) { + LOG_TEST_CASE("g_InlineVertexBuffer_TableLength > 50000! This probably means that g_InlineVertexBuffer_Table is growing indefinitely."); + } } // Is this the initial call after D3DDevice_Begin() ? if (g_InlineVertexBuffer_FVF == 0) { // Set first vertex to zero (preventing leaks from prior Begin/End calls) - memset(&g_InlineVertexBuffer_Table[0], 0, sizeof(g_InlineVertexBuffer_Table[0])); + g_InlineVertexBuffer_Table[0] = {}; // Handle persistent vertex attribute flags, by resetting non-persistent colors // to their default value (and leaving the persistent colors alone - see the @@ -4692,7 +4702,7 @@ xbox::void_xt WINAPI xbox::EMUPATCH(D3DDevice_SetVertexData4f) // Start a new vertex g_InlineVertexBuffer_TableOffset++; // Copy all attributes of the previous vertex (if any) to the new vertex - memcpy(&g_InlineVertexBuffer_Table[g_InlineVertexBuffer_TableOffset], &g_InlineVertexBuffer_Table[o], sizeof(g_InlineVertexBuffer_Table[o])); + g_InlineVertexBuffer_Table[g_InlineVertexBuffer_TableOffset] = g_InlineVertexBuffer_Table[o]; break; } diff --git a/src/core/hle/D3D8/XbVertexBuffer.cpp b/src/core/hle/D3D8/XbVertexBuffer.cpp index 37814ff4f..dda6afa65 100644 --- a/src/core/hle/D3D8/XbVertexBuffer.cpp +++ b/src/core/hle/D3D8/XbVertexBuffer.cpp @@ -47,7 +47,7 @@ // Inline vertex buffer emulation extern xbox::X_D3DPRIMITIVETYPE g_InlineVertexBuffer_PrimitiveType = xbox::X_D3DPT_INVALID; extern DWORD g_InlineVertexBuffer_FVF = 0; -extern struct _D3DIVB *g_InlineVertexBuffer_Table = nullptr; + std::vector<_D3DIVB> g_InlineVertexBuffer_Table; extern UINT g_InlineVertexBuffer_TableLength = 0; extern UINT g_InlineVertexBuffer_TableOffset = 0; @@ -69,6 +69,58 @@ uint32_t GetPixelContainerWidth(xbox::X_D3DPixelContainer* pPixelContainer); uint32_t GetPixelContainerHeight(xbox::X_D3DPixelContainer* pPixelContainer); void ApplyXboxMultiSampleOffsetAndScale(float& x, float& y); +_D3DIVB::_D3DIVB() +{ + Position.x = 0.0f; + Position.y = 0.0f; + Position.z = 0.0f; + Rhw = 0.0f; + for (unsigned i = 0; i < 4; ++i) { + Blend[i] = 0.0f; + } + Normal.x = 0.0f; + Normal.y = 0.0f; + Normal.z = 0.0f; + Diffuse = 0u; + Specular = 0u; + Fog = 0.0f; + BackDiffuse = 0u; + BackSpecular = 0u; + for (unsigned i = 0; i < 4; ++i) { + TexCoord[i].x = 0.0f; + TexCoord[i].y = 0.0f; + TexCoord[i].z = 0.0f; + TexCoord[i].w = 0.0f; + } +} + +struct _D3DIVB &_D3DIVB::operator=(const struct _D3DIVB &Val) +{ + Position.x = Val.Position.x; + Position.y = Val.Position.y; + Position.z = Val.Position.z; + Rhw = Val.Rhw; + for (unsigned i = 0; i < 4; ++i) { + Blend[i] = Val.Blend[i]; + } + Normal.x = Val.Normal.x; + Normal.y = Val.Normal.y; + Normal.z = Val.Normal.z; + Diffuse = Val.Diffuse; + Specular = Val.Specular; + Fog = Val.Fog; + BackDiffuse = Val.BackDiffuse; + BackSpecular = Val.BackSpecular; + for (unsigned i = 0; i < 4; ++i) { + TexCoord[i].x = Val.TexCoord[i].x; + TexCoord[i].y = Val.TexCoord[i].y; + TexCoord[i].z = Val.TexCoord[i].z; + TexCoord[i].w = Val.TexCoord[i].w; + } + + return *this; +} + void CxbxPatchedStream::Activate(CxbxDrawContext *pDrawContext, UINT uiStream) const { //LOG_INIT // Allows use of DEBUG_D3DRESULT diff --git a/src/core/hle/D3D8/XbVertexBuffer.h b/src/core/hle/D3D8/XbVertexBuffer.h index 1f9ff7012..654560d36 100644 --- a/src/core/hle/D3D8/XbVertexBuffer.h +++ b/src/core/hle/D3D8/XbVertexBuffer.h @@ -103,25 +103,28 @@ class CxbxVertexBufferConverter extern xbox::X_D3DPRIMITIVETYPE g_InlineVertexBuffer_PrimitiveType; extern DWORD g_InlineVertexBuffer_FVF; -extern struct _D3DIVB +struct _D3DIVB { D3DXVECTOR3 Position; // X_D3DVSDE_POSITION (*) > D3DFVF_XYZ / D3DFVF_XYZRHW FLOAT Rhw; // X_D3DVSDE_VERTEX (*) > D3DFVF_XYZ / D3DFVF_XYZRHW - FLOAT Blend[4]; // X_D3DVSDE_BLENDWEIGHT > D3DFVF_XYZB1 (and 3 more up to D3DFVF_XYZB4) + FLOAT Blend[4]; // X_D3DVSDE_BLENDWEIGHT > D3DFVF_XYZB1 (and 3 more up to D3DFVF_XYZB4) D3DXVECTOR3 Normal; // X_D3DVSDE_NORMAL > D3DFVF_NORMAL - D3DCOLOR Diffuse; // X_D3DVSDE_DIFFUSE > D3DFVF_DIFFUSE - D3DCOLOR Specular; // X_D3DVSDE_SPECULAR > D3DFVF_SPECULAR - FLOAT Fog; // X_D3DVSDE_FOG > D3DFVF_FOG unavailable; TODO : How to handle? - D3DCOLOR BackDiffuse; // X_D3DVSDE_BACKDIFFUSE > D3DFVF_BACKDIFFUSE unavailable; TODO : How to handle? - D3DCOLOR BackSpecular; // X_D3DVSDE_BACKSPECULAR > D3DFVF_BACKSPECULAR unavailable; TODO : How to handle? + D3DCOLOR Diffuse; // X_D3DVSDE_DIFFUSE > D3DFVF_DIFFUSE + D3DCOLOR Specular; // X_D3DVSDE_SPECULAR > D3DFVF_SPECULAR + FLOAT Fog; // X_D3DVSDE_FOG > D3DFVF_FOG unavailable; TODO : How to handle? + D3DCOLOR BackDiffuse; // X_D3DVSDE_BACKDIFFUSE > D3DFVF_BACKDIFFUSE unavailable; TODO : How to handle? + D3DCOLOR BackSpecular; // X_D3DVSDE_BACKSPECULAR > D3DFVF_BACKSPECULAR unavailable; TODO : How to handle? D3DXVECTOR4 TexCoord[4]; // X_D3DVSDE_TEXCOORD0 > D3DFVF_TEX1 (and 4 more up to D3DFVF_TEX4) - // (*) X_D3DVSDE_POSITION and X_D3DVSDE_VERTEX both set Position, but Rhw seems optional, - // hence, selection for D3DFVF_XYZ or D3DFVF_XYZRHW is rather fuzzy. We DO know that once - // D3DFVF_NORMAL is given, D3DFVF_XYZRHW is forbidden (see D3DDevice_SetVertexData4f) -} -*g_InlineVertexBuffer_Table; + // (*) X_D3DVSDE_POSITION and X_D3DVSDE_VERTEX both set Position, but Rhw seems optional, + // hence, selection for D3DFVF_XYZ or D3DFVF_XYZRHW is rather fuzzy. We DO know that once + // D3DFVF_NORMAL is given, D3DFVF_XYZRHW is forbidden (see D3DDevice_SetVertexData4f) + _D3DIVB(); + struct _D3DIVB &operator=(const struct _D3DIVB &Val); +}; + +extern std::vector<_D3DIVB> g_InlineVertexBuffer_Table; extern UINT g_InlineVertexBuffer_TableLength; extern UINT g_InlineVertexBuffer_TableOffset;