diff --git a/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp b/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp index e2a474bcf..d9994fb9b 100644 --- a/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp +++ b/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp @@ -6864,7 +6864,7 @@ void CxbxDrawIndexed(CxbxDrawContext &DrawContext) // for an explanation on the function of the BaseVertexIndex, MinVertexIndex, NumVertices and StartIndex arguments. HRESULT hRet = g_pD3DDevice->DrawIndexedPrimitive( /* 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, /* NumVertices = */(CacheEntry.HighIndex - CacheEntry.LowIndex) + 1, /* 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 : // Assure & activate that special index buffer : 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 : UINT NumVertices = QuadToTriangleVertexCount(DrawContext.dwVertexCount); // 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 : HRESULT hRet = g_pD3DDevice->DrawIndexedPrimitive( /*PrimitiveType=*/D3DPT_TRIANGLELIST, - BaseVertexIndex, + /*BaseVertexIndex=*/0, // Base vertex index has been accounted for in the stream conversion /*MinVertexIndex=*/0, NumVertices, /*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) HRESULT hRet = g_pD3DDevice->DrawPrimitive( EmuXB2PC_D3DPrimitiveType(DrawContext.XboxPrimitiveType), - DrawContext.dwStartVertex, + /*StartVertex=*/0, // Start vertex has been accounted for in the stream conversion DrawContext.dwHostPrimitiveCount ); 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 assert(DrawContext.dwBaseVertexIndex == 0); // if this fails, it needs to be added to LowIndex and HighIndex : - INDEX16 LowIndex = (INDEX16)DrawContext.dwStartVertex; - INDEX16 HighIndex = (INDEX16)(DrawContext.dwStartVertex + DrawContext.dwHostPrimitiveCount); + INDEX16 LowIndex = 0; + INDEX16 HighIndex = (INDEX16)(DrawContext.dwHostPrimitiveCount); // Draw the closing line using a helper function (which will SetIndices) CxbxDrawIndexedClosingLine(LowIndex, HighIndex); // NOTE : We don't restore the previously active index buffer diff --git a/src/core/hle/D3D8/XbVertexBuffer.cpp b/src/core/hle/D3D8/XbVertexBuffer.cpp index 01451c5b7..b80783199 100644 --- a/src/core/hle/D3D8/XbVertexBuffer.cpp +++ b/src/core/hle/D3D8/XbVertexBuffer.cpp @@ -261,9 +261,7 @@ void CxbxVertexBufferConverter::ConvertStream UINT HostStreamNumber = XboxStreamNumber; // Use Xbox stream index on host uint8_t *pXboxVertexData = xbox::zeroptr; UINT uiXboxVertexStride = 0; - UINT uiVertexCount = 0; UINT uiHostVertexStride = 0; - DWORD dwHostVertexDataSize = 0; uint8_t *pHostVertexData = nullptr; IDirect3DVertexBuffer *pNewHostVertexBuffer = nullptr; @@ -275,9 +273,7 @@ void CxbxVertexBufferConverter::ConvertStream pXboxVertexData = (uint8_t *)pDrawContext->pXboxVertexStreamZeroData; uiXboxVertexStride = pDrawContext->uiXboxVertexStreamZeroStride; - uiVertexCount = pDrawContext->VerticesInBuffer; uiHostVertexStride = (bNeedVertexPatching) ? pVertexShaderStreamInfo->HostVertexStride : uiXboxVertexStride; - dwHostVertexDataSize = uiVertexCount * uiHostVertexStride; } else { xbox::X_STREAMINPUT& XboxStreamInput = GetXboxVertexStreamInput(XboxStreamNumber); xbox::X_D3DVertexBuffer *pXboxVertexBuffer = XboxStreamInput.VertexBuffer; @@ -298,14 +294,11 @@ void CxbxVertexBufferConverter::ConvertStream pXboxVertexData += XboxStreamInput.Offset; 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 // 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). uiHostVertexStride = (bNeedVertexPatching) ? pVertexShaderStreamInfo->HostVertexStride : uiXboxVertexStride; - dwHostVertexDataSize = uiVertexCount * uiHostVertexStride; // Copy stream for patching and caching. 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! - 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 pVertexShaderSteamInfoHash = 0; @@ -634,9 +637,6 @@ void CxbxVertexBufferConverter::Apply(CxbxDrawContext *pDrawContext) 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 if (pDrawContext->pXboxIndexData) { // 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); WalkIndexBuffer(pDrawContext->LowIndex, pDrawContext->HighIndex, pDrawContext->pXboxIndexData, pDrawContext->dwVertexCount); } - // Convert highest index (including the base offset) into a count - DWORD dwHighestVertexCount = pDrawContext->dwBaseVertexIndex + pDrawContext->HighIndex + 1; - // Use the biggest vertex count that can be reached - if (pDrawContext->VerticesInBuffer < dwHighestVertexCount) - pDrawContext->VerticesInBuffer = dwHighestVertexCount; + // Convert the range of indices into a count + pDrawContext->NumVerticesToUse = pDrawContext->HighIndex - pDrawContext->LowIndex + 1; + } + else { + // 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 diff --git a/src/core/hle/D3D8/XbVertexBuffer.h b/src/core/hle/D3D8/XbVertexBuffer.h index 4fea1cfb0..faad271fc 100644 --- a/src/core/hle/D3D8/XbVertexBuffer.h +++ b/src/core/hle/D3D8/XbVertexBuffer.h @@ -40,7 +40,7 @@ typedef struct _CxbxDrawContext 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 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 IN PVOID pXboxVertexStreamZeroData; IN UINT uiXboxVertexStreamZeroStride;