Merge pull request #2048 from CookiePLMonster/vertex-stream-cache-optimization
Optimize vertex stream cache for partial buffer access
This commit is contained in:
commit
362c93801f
|
@ -6864,7 +6864,7 @@ void CxbxDrawIndexed(CxbxDrawContext &DrawContext)
|
||||||
// for an explanation on the function of the BaseVertexIndex, MinVertexIndex, NumVertices and StartIndex arguments.
|
// for an explanation on the function of the BaseVertexIndex, MinVertexIndex, NumVertices and StartIndex arguments.
|
||||||
HRESULT hRet = g_pD3DDevice->DrawIndexedPrimitive(
|
HRESULT hRet = g_pD3DDevice->DrawIndexedPrimitive(
|
||||||
/* PrimitiveType = */EmuXB2PC_D3DPrimitiveType(DrawContext.XboxPrimitiveType),
|
/* PrimitiveType = */EmuXB2PC_D3DPrimitiveType(DrawContext.XboxPrimitiveType),
|
||||||
BaseVertexIndex,
|
/* BaseVertexIndex, = */-CacheEntry.LowIndex, // Base vertex index has been accounted for in the stream conversion, now we need to "un-offset" the index buffer
|
||||||
/* MinVertexIndex = */CacheEntry.LowIndex,
|
/* MinVertexIndex = */CacheEntry.LowIndex,
|
||||||
/* NumVertices = */(CacheEntry.HighIndex - CacheEntry.LowIndex) + 1,
|
/* NumVertices = */(CacheEntry.HighIndex - CacheEntry.LowIndex) + 1,
|
||||||
/* startIndex = DrawContext.dwStartVertex = */0,
|
/* startIndex = DrawContext.dwStartVertex = */0,
|
||||||
|
@ -7516,9 +7516,6 @@ xbox::void_xt WINAPI xbox::EMUPATCH(D3DDevice_DrawVertices)
|
||||||
// Draw quadlists using a single 'quad-to-triangle mapping' index buffer :
|
// Draw quadlists using a single 'quad-to-triangle mapping' index buffer :
|
||||||
// Assure & activate that special index buffer :
|
// Assure & activate that special index buffer :
|
||||||
CxbxAssureQuadListD3DIndexBuffer(/*NrOfQuadIndices=*/DrawContext.dwVertexCount);
|
CxbxAssureQuadListD3DIndexBuffer(/*NrOfQuadIndices=*/DrawContext.dwVertexCount);
|
||||||
// This API's StartVertex argument is multiplied by vertex stride and added to the start of the vertex buffer;
|
|
||||||
// BaseVertexIndex offers the same functionality on host :
|
|
||||||
UINT BaseVertexIndex = DrawContext.dwStartVertex;
|
|
||||||
// Convert quad vertex count to triangle vertex count :
|
// Convert quad vertex count to triangle vertex count :
|
||||||
UINT NumVertices = QuadToTriangleVertexCount(DrawContext.dwVertexCount);
|
UINT NumVertices = QuadToTriangleVertexCount(DrawContext.dwVertexCount);
|
||||||
// Convert quad primitive count to triangle primitive count :
|
// Convert quad primitive count to triangle primitive count :
|
||||||
|
@ -7528,7 +7525,7 @@ xbox::void_xt WINAPI xbox::EMUPATCH(D3DDevice_DrawVertices)
|
||||||
// Emulate drawing quads by drawing each quad with two indexed triangles :
|
// Emulate drawing quads by drawing each quad with two indexed triangles :
|
||||||
HRESULT hRet = g_pD3DDevice->DrawIndexedPrimitive(
|
HRESULT hRet = g_pD3DDevice->DrawIndexedPrimitive(
|
||||||
/*PrimitiveType=*/D3DPT_TRIANGLELIST,
|
/*PrimitiveType=*/D3DPT_TRIANGLELIST,
|
||||||
BaseVertexIndex,
|
/*BaseVertexIndex=*/0, // Base vertex index has been accounted for in the stream conversion
|
||||||
/*MinVertexIndex=*/0,
|
/*MinVertexIndex=*/0,
|
||||||
NumVertices,
|
NumVertices,
|
||||||
/*startIndex=*/0,
|
/*startIndex=*/0,
|
||||||
|
@ -7542,7 +7539,7 @@ xbox::void_xt WINAPI xbox::EMUPATCH(D3DDevice_DrawVertices)
|
||||||
// if (StartVertex > 0) LOG_TEST_CASE("StartVertex > 0 (non-quad)"); // Verified test case : XDK Sample (PlayField)
|
// if (StartVertex > 0) LOG_TEST_CASE("StartVertex > 0 (non-quad)"); // Verified test case : XDK Sample (PlayField)
|
||||||
HRESULT hRet = g_pD3DDevice->DrawPrimitive(
|
HRESULT hRet = g_pD3DDevice->DrawPrimitive(
|
||||||
EmuXB2PC_D3DPrimitiveType(DrawContext.XboxPrimitiveType),
|
EmuXB2PC_D3DPrimitiveType(DrawContext.XboxPrimitiveType),
|
||||||
DrawContext.dwStartVertex,
|
/*StartVertex=*/0, // Start vertex has been accounted for in the stream conversion
|
||||||
DrawContext.dwHostPrimitiveCount
|
DrawContext.dwHostPrimitiveCount
|
||||||
);
|
);
|
||||||
DEBUG_D3DRESULT(hRet, "g_pD3DDevice->DrawPrimitive");
|
DEBUG_D3DRESULT(hRet, "g_pD3DDevice->DrawPrimitive");
|
||||||
|
@ -7553,8 +7550,8 @@ xbox::void_xt WINAPI xbox::EMUPATCH(D3DDevice_DrawVertices)
|
||||||
LOG_TEST_CASE("X_D3DPT_LINELOOP"); // TODO : Text-cases needed
|
LOG_TEST_CASE("X_D3DPT_LINELOOP"); // TODO : Text-cases needed
|
||||||
|
|
||||||
assert(DrawContext.dwBaseVertexIndex == 0); // if this fails, it needs to be added to LowIndex and HighIndex :
|
assert(DrawContext.dwBaseVertexIndex == 0); // if this fails, it needs to be added to LowIndex and HighIndex :
|
||||||
INDEX16 LowIndex = (INDEX16)DrawContext.dwStartVertex;
|
INDEX16 LowIndex = 0;
|
||||||
INDEX16 HighIndex = (INDEX16)(DrawContext.dwStartVertex + DrawContext.dwHostPrimitiveCount);
|
INDEX16 HighIndex = (INDEX16)(DrawContext.dwHostPrimitiveCount);
|
||||||
// Draw the closing line using a helper function (which will SetIndices)
|
// Draw the closing line using a helper function (which will SetIndices)
|
||||||
CxbxDrawIndexedClosingLine(LowIndex, HighIndex);
|
CxbxDrawIndexedClosingLine(LowIndex, HighIndex);
|
||||||
// NOTE : We don't restore the previously active index buffer
|
// NOTE : We don't restore the previously active index buffer
|
||||||
|
|
|
@ -261,9 +261,7 @@ void CxbxVertexBufferConverter::ConvertStream
|
||||||
UINT HostStreamNumber = XboxStreamNumber; // Use Xbox stream index on host
|
UINT HostStreamNumber = XboxStreamNumber; // Use Xbox stream index on host
|
||||||
uint8_t *pXboxVertexData = xbox::zeroptr;
|
uint8_t *pXboxVertexData = xbox::zeroptr;
|
||||||
UINT uiXboxVertexStride = 0;
|
UINT uiXboxVertexStride = 0;
|
||||||
UINT uiVertexCount = 0;
|
|
||||||
UINT uiHostVertexStride = 0;
|
UINT uiHostVertexStride = 0;
|
||||||
DWORD dwHostVertexDataSize = 0;
|
|
||||||
uint8_t *pHostVertexData = nullptr;
|
uint8_t *pHostVertexData = nullptr;
|
||||||
IDirect3DVertexBuffer *pNewHostVertexBuffer = nullptr;
|
IDirect3DVertexBuffer *pNewHostVertexBuffer = nullptr;
|
||||||
|
|
||||||
|
@ -275,9 +273,7 @@ void CxbxVertexBufferConverter::ConvertStream
|
||||||
|
|
||||||
pXboxVertexData = (uint8_t *)pDrawContext->pXboxVertexStreamZeroData;
|
pXboxVertexData = (uint8_t *)pDrawContext->pXboxVertexStreamZeroData;
|
||||||
uiXboxVertexStride = pDrawContext->uiXboxVertexStreamZeroStride;
|
uiXboxVertexStride = pDrawContext->uiXboxVertexStreamZeroStride;
|
||||||
uiVertexCount = pDrawContext->VerticesInBuffer;
|
|
||||||
uiHostVertexStride = (bNeedVertexPatching) ? pVertexShaderStreamInfo->HostVertexStride : uiXboxVertexStride;
|
uiHostVertexStride = (bNeedVertexPatching) ? pVertexShaderStreamInfo->HostVertexStride : uiXboxVertexStride;
|
||||||
dwHostVertexDataSize = uiVertexCount * uiHostVertexStride;
|
|
||||||
} else {
|
} else {
|
||||||
xbox::X_STREAMINPUT& XboxStreamInput = GetXboxVertexStreamInput(XboxStreamNumber);
|
xbox::X_STREAMINPUT& XboxStreamInput = GetXboxVertexStreamInput(XboxStreamNumber);
|
||||||
xbox::X_D3DVertexBuffer *pXboxVertexBuffer = XboxStreamInput.VertexBuffer;
|
xbox::X_D3DVertexBuffer *pXboxVertexBuffer = XboxStreamInput.VertexBuffer;
|
||||||
|
@ -298,14 +294,11 @@ void CxbxVertexBufferConverter::ConvertStream
|
||||||
|
|
||||||
pXboxVertexData += XboxStreamInput.Offset;
|
pXboxVertexData += XboxStreamInput.Offset;
|
||||||
uiXboxVertexStride = XboxStreamInput.Stride;
|
uiXboxVertexStride = XboxStreamInput.Stride;
|
||||||
// Set a new (exact) vertex count
|
|
||||||
uiVertexCount = pDrawContext->VerticesInBuffer;
|
|
||||||
// Dxbx note : Don't overwrite pDrawContext.dwVertexCount with uiVertexCount, because an indexed draw
|
// Dxbx note : Don't overwrite pDrawContext.dwVertexCount with uiVertexCount, because an indexed draw
|
||||||
// can (and will) use less vertices than the supplied nr of indexes. Thix fixes
|
// can (and will) use less vertices than the supplied nr of indexes. Thix fixes
|
||||||
// the missing parts in the CompressedVertices sample (in Vertex shader mode).
|
// the missing parts in the CompressedVertices sample (in Vertex shader mode).
|
||||||
|
|
||||||
uiHostVertexStride = (bNeedVertexPatching) ? pVertexShaderStreamInfo->HostVertexStride : uiXboxVertexStride;
|
uiHostVertexStride = (bNeedVertexPatching) ? pVertexShaderStreamInfo->HostVertexStride : uiXboxVertexStride;
|
||||||
dwHostVertexDataSize = uiVertexCount * uiHostVertexStride;
|
|
||||||
|
|
||||||
// Copy stream for patching and caching.
|
// Copy stream for patching and caching.
|
||||||
bNeedStreamCopy = true;
|
bNeedStreamCopy = true;
|
||||||
|
@ -327,7 +320,17 @@ void CxbxVertexBufferConverter::ConvertStream
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now we have enough information to hash the existing resource and find it in our cache!
|
// Now we have enough information to hash the existing resource and find it in our cache!
|
||||||
DWORD xboxVertexDataSize = uiVertexCount * uiXboxVertexStride;
|
// To avoid hashing and converting unused vertices, identify the "interesting" region
|
||||||
|
// basing on the index/starting vertex data
|
||||||
|
if (pDrawContext->pXboxIndexData != nullptr) {
|
||||||
|
pXboxVertexData += (pDrawContext->dwBaseVertexIndex + pDrawContext->LowIndex) * uiXboxVertexStride;
|
||||||
|
} else {
|
||||||
|
pXboxVertexData += pDrawContext->dwStartVertex * uiXboxVertexStride;
|
||||||
|
}
|
||||||
|
|
||||||
|
const UINT uiVertexCount = pDrawContext->NumVerticesToUse;
|
||||||
|
const DWORD dwHostVertexDataSize = uiVertexCount * uiHostVertexStride;
|
||||||
|
const DWORD xboxVertexDataSize = uiVertexCount * uiXboxVertexStride;
|
||||||
uint64_t vertexDataHash = ComputeHash(pXboxVertexData, xboxVertexDataSize);
|
uint64_t vertexDataHash = ComputeHash(pXboxVertexData, xboxVertexDataSize);
|
||||||
uint64_t pVertexShaderSteamInfoHash = 0;
|
uint64_t pVertexShaderSteamInfoHash = 0;
|
||||||
|
|
||||||
|
@ -634,9 +637,6 @@ void CxbxVertexBufferConverter::Apply(CxbxDrawContext *pDrawContext)
|
||||||
|
|
||||||
m_pCxbxVertexDeclaration = CxbxGetVertexDeclaration();
|
m_pCxbxVertexDeclaration = CxbxGetVertexDeclaration();
|
||||||
|
|
||||||
// If we are drawing from an offset, we know that the vertex count must have
|
|
||||||
// 'offset' vertices before the first drawn vertices
|
|
||||||
pDrawContext->VerticesInBuffer = pDrawContext->dwStartVertex + pDrawContext->dwVertexCount;
|
|
||||||
// When this is an indexed draw, take the index buffer into account
|
// When this is an indexed draw, take the index buffer into account
|
||||||
if (pDrawContext->pXboxIndexData) {
|
if (pDrawContext->pXboxIndexData) {
|
||||||
// Is the highest index in this buffer not set yet?
|
// Is the highest index in this buffer not set yet?
|
||||||
|
@ -646,11 +646,13 @@ void CxbxVertexBufferConverter::Apply(CxbxDrawContext *pDrawContext)
|
||||||
LOG_TEST_CASE("HighIndex == 0"); // TODO : If this is never hit, replace entire block by assert(pDrawContext->HighIndex > 0);
|
LOG_TEST_CASE("HighIndex == 0"); // TODO : If this is never hit, replace entire block by assert(pDrawContext->HighIndex > 0);
|
||||||
WalkIndexBuffer(pDrawContext->LowIndex, pDrawContext->HighIndex, pDrawContext->pXboxIndexData, pDrawContext->dwVertexCount);
|
WalkIndexBuffer(pDrawContext->LowIndex, pDrawContext->HighIndex, pDrawContext->pXboxIndexData, pDrawContext->dwVertexCount);
|
||||||
}
|
}
|
||||||
// Convert highest index (including the base offset) into a count
|
// Convert the range of indices into a count
|
||||||
DWORD dwHighestVertexCount = pDrawContext->dwBaseVertexIndex + pDrawContext->HighIndex + 1;
|
pDrawContext->NumVerticesToUse = pDrawContext->HighIndex - pDrawContext->LowIndex + 1;
|
||||||
// Use the biggest vertex count that can be reached
|
}
|
||||||
if (pDrawContext->VerticesInBuffer < dwHighestVertexCount)
|
else {
|
||||||
pDrawContext->VerticesInBuffer = dwHighestVertexCount;
|
// If we are drawing from an offset, we know that the vertex count must have
|
||||||
|
// 'offset' vertices before the first drawn vertices
|
||||||
|
pDrawContext->NumVerticesToUse = pDrawContext->dwVertexCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the number of streams
|
// Get the number of streams
|
||||||
|
|
|
@ -40,7 +40,7 @@ typedef struct _CxbxDrawContext
|
||||||
IN PWORD pXboxIndexData; // Set by D3DDevice_DrawIndexedVertices, D3DDevice_DrawIndexedVerticesUP and HLE_draw_inline_elements
|
IN PWORD pXboxIndexData; // Set by D3DDevice_DrawIndexedVertices, D3DDevice_DrawIndexedVerticesUP and HLE_draw_inline_elements
|
||||||
IN DWORD dwBaseVertexIndex; // Set to g_Xbox_BaseVertexIndex in D3DDevice_DrawIndexedVertices
|
IN DWORD dwBaseVertexIndex; // Set to g_Xbox_BaseVertexIndex in D3DDevice_DrawIndexedVertices
|
||||||
IN INDEX16 LowIndex, HighIndex; // Set when pXboxIndexData is set
|
IN INDEX16 LowIndex, HighIndex; // Set when pXboxIndexData is set
|
||||||
IN size_t VerticesInBuffer; // Set by CxbxVertexBufferConverter::Apply
|
IN UINT NumVerticesToUse; // Set by CxbxVertexBufferConverter::Apply
|
||||||
// Data if Draw...UP call
|
// Data if Draw...UP call
|
||||||
IN PVOID pXboxVertexStreamZeroData;
|
IN PVOID pXboxVertexStreamZeroData;
|
||||||
IN UINT uiXboxVertexStreamZeroStride;
|
IN UINT uiXboxVertexStreamZeroStride;
|
||||||
|
|
Loading…
Reference in New Issue