Addressed code review remarks, by adding explanations in comments and renaming a few arguments

This commit is contained in:
patrickvl 2019-10-24 16:48:59 +02:00 committed by PatrickvL
parent eb9f610780
commit ec25283551
2 changed files with 65 additions and 34 deletions

View File

@ -161,10 +161,10 @@ static CxbxVertexBufferConverter VertexBufferConverter = {};
static IDirect3DIndexBuffer *g_pClosingLineLoopHostIndexBuffer = nullptr; static IDirect3DIndexBuffer *g_pClosingLineLoopHostIndexBuffer = nullptr;
static IDirect3DIndexBuffer *g_pQuadToTriangleHostIndexBuffer = nullptr; static IDirect3DIndexBuffer *g_pQuadToTriangleHostIndexBuffer = nullptr;
static UINT g_QuadToTriangleHostIndexBuffer_Size = 0; // = NrOfQuadVertices static UINT g_QuadToTriangleHostIndexBuffer_Size = 0; // = NrOfQuadIndices
static INDEX16 *g_pQuadToTriangleIndexData = nullptr; static INDEX16 *g_pQuadToTriangleIndexData = nullptr;
static UINT g_QuadToTriangleIndexData_Size = 0; // = NrOfQuadVertices static UINT g_QuadToTriangleIndexData_Size = 0; // = NrOfQuadIndices
static IDirect3DSurface *g_DefaultHostDepthBufferSuface = NULL; static IDirect3DSurface *g_DefaultHostDepthBufferSuface = NULL;
XTL::X_D3DSurface *g_XboxBackBufferSurface = NULL; XTL::X_D3DSurface *g_XboxBackBufferSurface = NULL;
@ -2469,8 +2469,18 @@ constexpr UINT QuadToTriangleVertexCount(UINT NrOfQuadVertices)
bool bUseClockWiseWindingOrder = true; // TODO : Should this be fetched from X_D3DRS_FRONTFACE (or X_D3DRS_CULLMODE)? bool bUseClockWiseWindingOrder = true; // TODO : Should this be fetched from X_D3DRS_FRONTFACE (or X_D3DRS_CULLMODE)?
// TODO : Move to own file // TODO : Move to own file
// This function convertes quad to triangle indices.
// When pXboxQuadIndexData is set, original quad indices are read from this buffer
// (this use-case is for when an indexed quad draw is to be emulated).
// When pXboxQuadIndexData is null, quad-emulating indices are generated
// (this use-case is for when a non-indexed quad draw is to be emulated).
// The number of indices to generate is specified through uNrOfTriangleIndices.
// Resulting triangle indices are written to pTriangleIndexData, which must
// be pre-allocated to fit the output data.
// (Note, this function is marked 'constexpr' to allow the compiler to optimize
// the case when pXboxQuadIndexData is null)
constexpr void CxbxConvertQuadListToTriangleListIndices( constexpr void CxbxConvertQuadListToTriangleListIndices(
INDEX16* pQuadIndexData, INDEX16* pXboxQuadIndexData,
unsigned uNrOfTriangleIndices, unsigned uNrOfTriangleIndices,
INDEX16* pTriangleIndexData) INDEX16* pTriangleIndexData)
{ {
@ -2482,25 +2492,25 @@ constexpr void CxbxConvertQuadListToTriangleListIndices(
while (i + (VERTICES_PER_TRIANGLE * TRIANGLES_PER_QUAD) <= uNrOfTriangleIndices) { while (i + (VERTICES_PER_TRIANGLE * TRIANGLES_PER_QUAD) <= uNrOfTriangleIndices) {
if (bUseClockWiseWindingOrder) { if (bUseClockWiseWindingOrder) {
// ABCD becomes ABC+CDA, so this is triangle 1 : // ABCD becomes ABC+CDA, so this is triangle 1 :
pTriangleIndexData[i + 0] = pQuadIndexData ? pQuadIndexData[j + 0] : j + 0; // A pTriangleIndexData[i + 0] = pXboxQuadIndexData ? pXboxQuadIndexData[j + 0] : j + 0; // A
pTriangleIndexData[i + 1] = pQuadIndexData ? pQuadIndexData[j + 1] : j + 1; // B pTriangleIndexData[i + 1] = pXboxQuadIndexData ? pXboxQuadIndexData[j + 1] : j + 1; // B
pTriangleIndexData[i + 2] = pQuadIndexData ? pQuadIndexData[j + 2] : j + 2; // C pTriangleIndexData[i + 2] = pXboxQuadIndexData ? pXboxQuadIndexData[j + 2] : j + 2; // C
i += VERTICES_PER_TRIANGLE; i += VERTICES_PER_TRIANGLE;
// And this is triangle 2 : // And this is triangle 2 :
pTriangleIndexData[i + 0] = pQuadIndexData ? pQuadIndexData[j + 2] : j + 2; // C pTriangleIndexData[i + 0] = pXboxQuadIndexData ? pXboxQuadIndexData[j + 2] : j + 2; // C
pTriangleIndexData[i + 1] = pQuadIndexData ? pQuadIndexData[j + 3] : j + 3; // D pTriangleIndexData[i + 1] = pXboxQuadIndexData ? pXboxQuadIndexData[j + 3] : j + 3; // D
pTriangleIndexData[i + 2] = pQuadIndexData ? pQuadIndexData[j + 0] : j + 0; // A pTriangleIndexData[i + 2] = pXboxQuadIndexData ? pXboxQuadIndexData[j + 0] : j + 0; // A
i += VERTICES_PER_TRIANGLE; i += VERTICES_PER_TRIANGLE;
} else { } else {
// ABCD becomes ADC+CBA, so this is triangle 1 : // ABCD becomes ADC+CBA, so this is triangle 1 :
pTriangleIndexData[i + 0] = pQuadIndexData ? pQuadIndexData[j + 0] : j + 0; // A pTriangleIndexData[i + 0] = pXboxQuadIndexData ? pXboxQuadIndexData[j + 0] : j + 0; // A
pTriangleIndexData[i + 1] = pQuadIndexData ? pQuadIndexData[j + 3] : j + 3; // D pTriangleIndexData[i + 1] = pXboxQuadIndexData ? pXboxQuadIndexData[j + 3] : j + 3; // D
pTriangleIndexData[i + 2] = pQuadIndexData ? pQuadIndexData[j + 2] : j + 2; // C pTriangleIndexData[i + 2] = pXboxQuadIndexData ? pXboxQuadIndexData[j + 2] : j + 2; // C
i += VERTICES_PER_TRIANGLE; i += VERTICES_PER_TRIANGLE;
// And this is triangle 2 : // And this is triangle 2 :
pTriangleIndexData[i + 0] = pQuadIndexData ? pQuadIndexData[j + 2] : j + 2; // C pTriangleIndexData[i + 0] = pXboxQuadIndexData ? pXboxQuadIndexData[j + 2] : j + 2; // C
pTriangleIndexData[i + 1] = pQuadIndexData ? pQuadIndexData[j + 1] : j + 1; // B pTriangleIndexData[i + 1] = pXboxQuadIndexData ? pXboxQuadIndexData[j + 1] : j + 1; // B
pTriangleIndexData[i + 2] = pQuadIndexData ? pQuadIndexData[j + 0] : j + 0; // A pTriangleIndexData[i + 2] = pXboxQuadIndexData ? pXboxQuadIndexData[j + 0] : j + 0; // A
i += VERTICES_PER_TRIANGLE; i += VERTICES_PER_TRIANGLE;
} }
@ -2510,11 +2520,20 @@ constexpr void CxbxConvertQuadListToTriangleListIndices(
} }
// TODO : Move to own file // TODO : Move to own file
INDEX16* CxbxCreateQuadListToTriangleListIndexData(INDEX16* pQuadIndexData, unsigned QuadVertexCount) // Called from EMUPATCH(D3DDevice_DrawIndexedVerticesUP) when PrimitiveType == X_D3DPT_QUADLIST.
// This API receives the number of vertices to draw (VertexCount), the index data that references
// vertices and a single stream of vertex data. The number of vertices to draw indicates the number
// of indices that are going to be fetched. The vertex data is referenced up to the highest index
// number present in the index data.
// To emulate drawing indexed quads, g_pD3DDevice->DrawIndexedPrimitiveUP is called on host,
// whereby the quad indices are converted to triangle indices. This implies for every four
// quad indices, we have to generate (two times three is) six triangle indices. (Note, that
// vertex data undergoes it's own Xbox-to-host conversion, independent from these indices.)
INDEX16* CxbxCreateQuadListToTriangleListIndexData(INDEX16* pXboxQuadIndexData, unsigned QuadVertexCount)
{ {
UINT NrOfTriangleVertices = QuadToTriangleVertexCount(QuadVertexCount); UINT NrOfTriangleIndices = QuadToTriangleVertexCount(QuadVertexCount);
INDEX16* pQuadToTriangleIndexBuffer = (INDEX16*)malloc(NrOfTriangleVertices * sizeof(INDEX16)); INDEX16* pQuadToTriangleIndexBuffer = (INDEX16*)malloc(NrOfTriangleIndices * sizeof(INDEX16));
CxbxConvertQuadListToTriangleListIndices(pQuadIndexData, NrOfTriangleVertices, pQuadToTriangleIndexBuffer); CxbxConvertQuadListToTriangleListIndices(pXboxQuadIndexData, NrOfTriangleIndices, pQuadToTriangleIndexBuffer);
return pQuadToTriangleIndexBuffer; return pQuadToTriangleIndexBuffer;
} }
@ -6518,35 +6537,46 @@ constexpr unsigned int IndicesPerPage = PAGE_SIZE / sizeof(INDEX16);
constexpr unsigned int InputQuadsPerPage = ((IndicesPerPage * VERTICES_PER_QUAD) / VERTICES_PER_TRIANGLE) / TRIANGLES_PER_QUAD; constexpr unsigned int InputQuadsPerPage = ((IndicesPerPage * VERTICES_PER_QUAD) / VERTICES_PER_TRIANGLE) / TRIANGLES_PER_QUAD;
// TODO : Move to own file // TODO : Move to own file
INDEX16 *CxbxAssureQuadListIndexData(UINT NrOfQuadVertices) // Called by CxbxDrawPrimitiveUP (indirectly by D3DDevice_DrawVerticesUP,
// EmuExecutePushBufferRaw and EmuFlushIVB) when PrimitiveType == X_D3DPT_QUADLIST.
// Emulated by calling g_pD3DDevice->DrawIndexedPrimitiveUP with index data that maps
// quads to triangles. This function creates the index buffer that is needed for this;
// For every quad that must be drawn, we generate indices for two triangles.
// Note, that the resulting index data can be re-used for later comparable draw calls
// and only needs to grow when current length doesn't suffices for a larger draw.
INDEX16 *CxbxAssureQuadListIndexData(UINT NrOfQuadIndices)
{ {
if (g_QuadToTriangleIndexData_Size < NrOfQuadVertices) if (g_QuadToTriangleIndexData_Size < NrOfQuadIndices)
{ {
g_QuadToTriangleIndexData_Size = RoundUp(NrOfQuadVertices, InputQuadsPerPage); g_QuadToTriangleIndexData_Size = RoundUp(NrOfQuadIndices, InputQuadsPerPage);
UINT NrOfTriangleVertices = QuadToTriangleVertexCount(g_QuadToTriangleIndexData_Size); UINT NrOfTriangleIndices = QuadToTriangleVertexCount(g_QuadToTriangleIndexData_Size);
if (g_pQuadToTriangleIndexData != nullptr) { if (g_pQuadToTriangleIndexData != nullptr) {
free(g_pQuadToTriangleIndexData); free(g_pQuadToTriangleIndexData);
} }
g_pQuadToTriangleIndexData = (INDEX16 *)malloc(NrOfTriangleVertices * sizeof(INDEX16)); g_pQuadToTriangleIndexData = (INDEX16 *)malloc(NrOfTriangleIndices * sizeof(INDEX16));
CxbxConvertQuadListToTriangleListIndices(nullptr, NrOfTriangleVertices, g_pQuadToTriangleIndexData); CxbxConvertQuadListToTriangleListIndices(nullptr, NrOfTriangleIndices, g_pQuadToTriangleIndexData);
} }
return g_pQuadToTriangleIndexData; return g_pQuadToTriangleIndexData;
} }
// TODO : Move to own file // TODO : Move to own file
void CxbxAssureQuadListD3DIndexBuffer(UINT NrOfQuadVertices) // Makes a D3D IndexBuffer active that contains quadlist-to-trianglelist indices.
// Uses CxbxAssureQuadListIndexData to populate the index buffer with.
// Note, that the resulting index buffer can be re-used for later comparable draw calls
// and only needs to grow when current length doesn't sufficesw for a larger draw.
void CxbxAssureQuadListD3DIndexBuffer(UINT NrOfQuadIndices)
{ {
LOG_INIT // Allows use of DEBUG_D3DRESULT LOG_INIT // Allows use of DEBUG_D3DRESULT
HRESULT hRet; HRESULT hRet;
if (g_QuadToTriangleHostIndexBuffer_Size < NrOfQuadVertices) if (g_QuadToTriangleHostIndexBuffer_Size < NrOfQuadIndices)
{ {
// Round the number of indices up so we'll allocate whole pages // Round the number of indices up so we'll allocate whole pages
g_QuadToTriangleHostIndexBuffer_Size = RoundUp(NrOfQuadVertices, InputQuadsPerPage); g_QuadToTriangleHostIndexBuffer_Size = RoundUp(NrOfQuadIndices, InputQuadsPerPage);
UINT NrOfTriangleVertices = QuadToTriangleVertexCount(g_QuadToTriangleHostIndexBuffer_Size); // 4 > 6 UINT NrOfTriangleIndices = QuadToTriangleVertexCount(g_QuadToTriangleHostIndexBuffer_Size); // 4 > 6
// Create a new native index buffer of the above determined size : // Create a new native index buffer of the above determined size :
if (g_pQuadToTriangleHostIndexBuffer != nullptr) { if (g_pQuadToTriangleHostIndexBuffer != nullptr) {
@ -6555,7 +6585,7 @@ void CxbxAssureQuadListD3DIndexBuffer(UINT NrOfQuadVertices)
} }
// Create a new native index buffer of the above determined size : // Create a new native index buffer of the above determined size :
g_pQuadToTriangleHostIndexBuffer = CxbxCreateIndexBuffer(NrOfTriangleVertices); g_pQuadToTriangleHostIndexBuffer = CxbxCreateIndexBuffer(NrOfTriangleIndices);
if (g_pQuadToTriangleHostIndexBuffer == nullptr) if (g_pQuadToTriangleHostIndexBuffer == nullptr)
CxbxKrnlCleanup("CxbxAssureQuadListD3DIndexBuffer : IndexBuffer Create Failed!"); CxbxKrnlCleanup("CxbxAssureQuadListD3DIndexBuffer : IndexBuffer Create Failed!");
@ -6566,7 +6596,7 @@ void CxbxAssureQuadListD3DIndexBuffer(UINT NrOfQuadVertices)
if (pHostIndexBufferData == nullptr) if (pHostIndexBufferData == nullptr)
CxbxKrnlCleanup("CxbxAssureQuadListD3DIndexBuffer : Could not lock index buffer!"); CxbxKrnlCleanup("CxbxAssureQuadListD3DIndexBuffer : Could not lock index buffer!");
CxbxConvertQuadListToTriangleListIndices(nullptr, NrOfTriangleVertices, pHostIndexBufferData); memcpy(pHostIndexBufferData, CxbxAssureQuadListIndexData(NrOfTriangleIndices), NrOfTriangleIndices * sizeof(INDEX16));
g_pQuadToTriangleHostIndexBuffer->Unlock(); g_pQuadToTriangleHostIndexBuffer->Unlock();
} }
@ -6610,7 +6640,7 @@ void CxbxDrawIndexedClosingLine(INDEX16 LowIndex, INDEX16 HighIndex)
hRet = g_pD3DDevice->DrawIndexedPrimitive( hRet = g_pD3DDevice->DrawIndexedPrimitive(
/*PrimitiveType=*/D3DPT_LINELIST, /*PrimitiveType=*/D3DPT_LINELIST,
/*BaseVertexIndex=*/0, // Note : Callers must apply BaseVertexIndex to the LowIndex and HighIndex argument values /*BaseVertexIndex=*/0, // Note : Callers must apply BaseVertexIndex to the LowIndex and HighIndex argument values
/*MinVertrexIndex=*/LowIndex, /*MinVertexIndex=*/LowIndex,
/*NumVertices=*/VERTICES_PER_LINE, /*NumVertices=*/VERTICES_PER_LINE,
/*startIndex=*/0, /*startIndex=*/0,
/*primCount=*/1 /*primCount=*/1
@ -6990,7 +7020,7 @@ VOID WINAPI XTL::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(/*NrOfQuadVertices=*/DrawContext.dwVertexCount); CxbxAssureQuadListD3DIndexBuffer(/*NrOfQuadIndices=*/DrawContext.dwVertexCount);
// Convert quad vertex-count & start to triangle vertex count & start : // Convert quad vertex-count & start to triangle vertex count & start :
UINT startIndex = QuadToTriangleVertexCount(DrawContext.dwStartVertex); UINT startIndex = QuadToTriangleVertexCount(DrawContext.dwStartVertex);
UINT primCount = DrawContext.dwHostPrimitiveCount * TRIANGLES_PER_QUAD; UINT primCount = DrawContext.dwHostPrimitiveCount * TRIANGLES_PER_QUAD;

View File

@ -767,8 +767,9 @@ void CxbxVertexBufferConverter::Apply(CxbxDrawContext *pDrawContext)
// If we are drawing from an offset, we know that the vertex count must have // If we are drawing from an offset, we know that the vertex count must have
// 'offset' vertices before the first drawn vertices // 'offset' vertices before the first drawn vertices
pDrawContext->VerticesInBuffer = pDrawContext->dwStartVertex + pDrawContext->dwVertexCount; pDrawContext->VerticesInBuffer = pDrawContext->dwStartVertex + pDrawContext->dwVertexCount;
// Whhen 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?
if (pDrawContext->HighIndex == 0) { if (pDrawContext->HighIndex == 0) {
// TODO : Instead of calling WalkIndexBuffer here, set LowIndex and HighIndex // TODO : Instead of calling WalkIndexBuffer here, set LowIndex and HighIndex
// in all callers that end up here (since they might be able to avoid the call) // in all callers that end up here (since they might be able to avoid the call)