Merge pull request #1757 from PatrickvL/indexed_quads
Speed up drawing indexed quads
This commit is contained in:
commit
ff5e0d3441
File diff suppressed because it is too large
Load Diff
|
@ -1181,36 +1181,40 @@ D3DMULTISAMPLE_TYPE EmuXB2PC_D3DMultiSampleFormat(DWORD Type)
|
|||
}
|
||||
|
||||
// lookup table for converting vertex count to primitive count
|
||||
UINT EmuD3DVertexToPrimitive[11][2] =
|
||||
{
|
||||
const unsigned g_XboxPrimitiveTypeInfo[11][2] =
|
||||
{
|
||||
// First number is the starting number of vertices the draw requires
|
||||
// Second number the number of vertices per primitive
|
||||
// Example : Triangle list, has no starting vertices, and uses 3 vertices for each triangle
|
||||
// Example : Triangle strip, starts with 2 vertices, and adds 1 for each triangle
|
||||
{0, 0}, // NULL
|
||||
{1, 0}, // X_D3DPT_POINTLIST
|
||||
{2, 0}, // X_D3DPT_LINELIST
|
||||
{1, 1}, // X_D3DPT_LINELOOP
|
||||
{1, 1}, // X_D3DPT_LINESTRIP
|
||||
{3, 0}, // X_D3DPT_TRIANGLELIST
|
||||
{1, 2}, // X_D3DPT_TRIANGLESTRIP
|
||||
{1, 2}, // X_D3DPT_TRIANGLEFAN
|
||||
{4, 0}, // X_D3DPT_QUADLIST
|
||||
{2, 2}, // X_D3DPT_QUADSTRIP
|
||||
{1, 0}, // X_D3DPT_POLYGON
|
||||
{0, 1}, // X_D3DPT_POINTLIST
|
||||
{0, 2}, // X_D3DPT_LINELIST
|
||||
{1, 1}, // X_D3DPT_LINELOOP
|
||||
{1, 1}, // X_D3DPT_LINESTRIP
|
||||
{0, 3}, // X_D3DPT_TRIANGLELIST
|
||||
{2, 1}, // X_D3DPT_TRIANGLESTRIP
|
||||
{2, 1}, // X_D3DPT_TRIANGLEFAN
|
||||
{0, 4}, // X_D3DPT_QUADLIST
|
||||
{2, 2}, // X_D3DPT_QUADSTRIP
|
||||
{0, 1}, // X_D3DPT_POLYGON
|
||||
};
|
||||
|
||||
// conversion table for xbox->pc primitive types
|
||||
D3DPRIMITIVETYPE EmuPrimitiveTypeLookup[] =
|
||||
const D3DPRIMITIVETYPE g_XboxPrimitiveTypeToHost[] =
|
||||
{
|
||||
/* NULL = 0 */ (D3DPRIMITIVETYPE)0,
|
||||
/* D3DPT_POINTLIST = 1, */ D3DPT_POINTLIST,
|
||||
/* D3DPT_LINELIST = 2, */ D3DPT_LINELIST,
|
||||
/* D3DPT_LINELOOP = 3, Xbox */ D3DPT_LINESTRIP,
|
||||
/* D3DPT_LINESTRIP = 4, */ D3DPT_LINESTRIP,
|
||||
/* D3DPT_TRIANGLELIST = 5, */ D3DPT_TRIANGLELIST,
|
||||
/* D3DPT_TRIANGLESTRIP = 6, */ D3DPT_TRIANGLESTRIP,
|
||||
/* D3DPT_TRIANGLEFAN = 7, */ D3DPT_TRIANGLEFAN,
|
||||
/* D3DPT_QUADLIST = 8, Xbox */ D3DPT_TRIANGLELIST,
|
||||
/* D3DPT_QUADSTRIP = 9, Xbox */ D3DPT_TRIANGLESTRIP,
|
||||
/* D3DPT_POLYGON = 10, Xbox */ D3DPT_TRIANGLEFAN,
|
||||
/* D3DPT_MAX = 11, */ (D3DPRIMITIVETYPE)11
|
||||
/* NULL = 0 */ (D3DPRIMITIVETYPE)0,
|
||||
/* X_D3DPT_POINTLIST = 1, */ D3DPT_POINTLIST,
|
||||
/* X_D3DPT_LINELIST = 2, */ D3DPT_LINELIST,
|
||||
/* X_D3DPT_LINELOOP = 3, Xbox */ D3DPT_LINESTRIP,
|
||||
/* X_D3DPT_LINESTRIP = 4, */ D3DPT_LINESTRIP,
|
||||
/* X_D3DPT_TRIANGLELIST = 5, */ D3DPT_TRIANGLELIST,
|
||||
/* X_D3DPT_TRIANGLESTRIP = 6, */ D3DPT_TRIANGLESTRIP,
|
||||
/* X_D3DPT_TRIANGLEFAN = 7, */ D3DPT_TRIANGLEFAN,
|
||||
/* X_D3DPT_QUADLIST = 8, Xbox */ D3DPT_TRIANGLELIST,
|
||||
/* X_D3DPT_QUADSTRIP = 9, Xbox */ D3DPT_TRIANGLESTRIP,
|
||||
/* X_D3DPT_POLYGON = 10, Xbox */ D3DPT_TRIANGLEFAN,
|
||||
/* X_D3DPT_MAX = 11, */ (D3DPRIMITIVETYPE)11
|
||||
};
|
||||
|
||||
void EmuUnswizzleBox
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
|
||||
#include "core\hle\D3D8\XbD3D8Types.h"
|
||||
|
||||
#define VERTICES_PER_DOT 1
|
||||
#define VERTICES_PER_LINE 2
|
||||
#define VERTICES_PER_TRIANGLE 3
|
||||
#define VERTICES_PER_QUAD 4
|
||||
#define TRIANGLES_PER_QUAD 2
|
||||
|
@ -231,46 +233,41 @@ inline D3DSTENCILOP EmuXB2PC_D3DSTENCILOP(XTL::X_D3DSTENCILOP Value)
|
|||
}
|
||||
|
||||
// table used for vertex->primitive count conversion
|
||||
extern UINT EmuD3DVertexToPrimitive[XTL::X_D3DPT_POLYGON + 1][2];
|
||||
extern const UINT g_XboxPrimitiveTypeInfo[XTL::X_D3DPT_POLYGON + 1][2];
|
||||
|
||||
inline bool IsValidXboxVertexCount(XTL::X_D3DPRIMITIVETYPE XboxPrimitiveType, UINT VertexCount)
|
||||
{
|
||||
assert(XboxPrimitiveType < XTL::X_D3DPT_MAX);
|
||||
|
||||
inline bool EmuD3DValidVertexCount(XTL::X_D3DPRIMITIVETYPE XboxPrimitiveType, UINT VertexCount)
|
||||
{
|
||||
// Are there more vertices than required for setup?
|
||||
if (VertexCount > EmuD3DVertexToPrimitive[XboxPrimitiveType][1])
|
||||
if (VertexCount > g_XboxPrimitiveTypeInfo[XboxPrimitiveType][0])
|
||||
// Are the additional vertices exact multiples of the required additional vertices per primitive?
|
||||
if (0 == ((VertexCount - EmuD3DVertexToPrimitive[XboxPrimitiveType][1]) % EmuD3DVertexToPrimitive[XboxPrimitiveType][0]))
|
||||
if (0 == ((VertexCount - g_XboxPrimitiveTypeInfo[XboxPrimitiveType][0]) % g_XboxPrimitiveTypeInfo[XboxPrimitiveType][1]))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// convert from vertex count to primitive count (Xbox)
|
||||
inline int EmuD3DVertex2PrimitiveCount(XTL::X_D3DPRIMITIVETYPE PrimitiveType, int VertexCount)
|
||||
inline unsigned ConvertXboxVertexCountToPrimitiveCount(XTL::X_D3DPRIMITIVETYPE XboxPrimitiveType, unsigned VertexCount)
|
||||
{
|
||||
return (VertexCount - EmuD3DVertexToPrimitive[PrimitiveType][1]) / EmuD3DVertexToPrimitive[PrimitiveType][0];
|
||||
assert(XboxPrimitiveType < XTL::X_D3DPT_MAX);
|
||||
|
||||
return (VertexCount - g_XboxPrimitiveTypeInfo[XboxPrimitiveType][0]) / g_XboxPrimitiveTypeInfo[XboxPrimitiveType][1];
|
||||
}
|
||||
|
||||
// convert from primitive count to vertex count (Xbox)
|
||||
inline int EmuD3DPrimitive2VertexCount(XTL::X_D3DPRIMITIVETYPE PrimitiveType, int PrimitiveCount)
|
||||
{
|
||||
return (PrimitiveCount * EmuD3DVertexToPrimitive[PrimitiveType][0]) + EmuD3DVertexToPrimitive[PrimitiveType][1];
|
||||
}
|
||||
|
||||
|
||||
// conversion table for xbox->pc primitive types
|
||||
extern D3DPRIMITIVETYPE EmuPrimitiveTypeLookup[];
|
||||
extern const D3DPRIMITIVETYPE g_XboxPrimitiveTypeToHost[];
|
||||
|
||||
// convert xbox->pc primitive type
|
||||
inline D3DPRIMITIVETYPE EmuXB2PC_D3DPrimitiveType(XTL::X_D3DPRIMITIVETYPE PrimitiveType)
|
||||
inline D3DPRIMITIVETYPE EmuXB2PC_D3DPrimitiveType(XTL::X_D3DPRIMITIVETYPE XboxPrimitiveType)
|
||||
{
|
||||
if((DWORD)PrimitiveType == 0x7FFFFFFF)
|
||||
return D3DPT_FORCE_DWORD;
|
||||
|
||||
return EmuPrimitiveTypeLookup[PrimitiveType];
|
||||
}
|
||||
|
||||
inline int EmuD3DIndexCountToVertexCount(XTL::X_D3DPRIMITIVETYPE XboxPrimitiveType, int IndexCount)
|
||||
{
|
||||
return IndexCount;
|
||||
if (XboxPrimitiveType >= XTL::X_D3DPT_MAX) {
|
||||
LOG_TEST_CASE("XboxPrimitiveType too large");
|
||||
return D3DPT_FORCE_DWORD;
|
||||
}
|
||||
|
||||
return g_XboxPrimitiveTypeToHost[XboxPrimitiveType];
|
||||
}
|
||||
|
||||
extern void EmuUnswizzleBox
|
||||
|
|
|
@ -258,8 +258,8 @@ void HLE_draw_inline_elements(NV2AState *d)
|
|||
CxbxDrawContext DrawContext = {};
|
||||
|
||||
DrawContext.XboxPrimitiveType = (XTL::X_D3DPRIMITIVETYPE)pg->primitive_mode;
|
||||
DrawContext.dwVertexCount = EmuD3DIndexCountToVertexCount(DrawContext.XboxPrimitiveType, uiIndexCount);
|
||||
DrawContext.pIndexData = d->pgraph.inline_elements; // Used by GetVerticesInBuffer
|
||||
DrawContext.dwVertexCount = uiIndexCount;
|
||||
DrawContext.pXboxIndexData = d->pgraph.inline_elements;
|
||||
|
||||
CxbxDrawIndexed(DrawContext);
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "common\util\hasher.h"
|
||||
#include "core\kernel\support\Emu.h"
|
||||
#include "core\hle\D3D8\Direct3D9\Direct3D9.h" // For g_pD3DDevice
|
||||
#include "core\hle\D3D8\Direct3D9\WalkIndexBuffer.h" // for WalkIndexBuffer
|
||||
#include "core\hle\D3D8\ResourceTracker.h"
|
||||
#include "core\hle\D3D8\XbPushBuffer.h" // for DxbxFVF_GetNumberOfTextureCoordinates
|
||||
#include "core\hle\D3D8\XbVertexBuffer.h"
|
||||
|
@ -84,7 +85,7 @@ void CxbxPatchedStream::Activate(CxbxDrawContext *pDrawContext, UINT uiStream) c
|
|||
//DEBUG_D3DRESULT(hRet, "g_pD3DDevice->SetStreamSource");
|
||||
if (FAILED(hRet)) {
|
||||
CxbxKrnlCleanup("Failed to set the type patched buffer as the new stream source!\n");
|
||||
// TODO : Cartoon hits the above case when the vertex cache size is 0.
|
||||
// TODO : test-case : XDK Cartoon hits the above case when the vertex cache size is 0.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -115,27 +116,6 @@ CxbxVertexBufferConverter::CxbxVertexBufferConverter()
|
|||
m_pVertexShaderInfo = nullptr;
|
||||
}
|
||||
|
||||
size_t GetVerticesInBuffer(DWORD dwOffset, DWORD dwVertexCount, PWORD pIndexData, DWORD dwIndexBase)
|
||||
{
|
||||
// If we are drawing from an offset, we know that the vertex count must have offset vertices
|
||||
// before the first drawn vertices
|
||||
dwVertexCount += dwOffset;
|
||||
if (pIndexData == xbnullptr) {
|
||||
return dwVertexCount;
|
||||
}
|
||||
|
||||
// We are an indexed draw, so we have to parse the index buffer
|
||||
// The highest index we see can be used to determine the vertex buffer size
|
||||
DWORD highestVertexIndex = 0;
|
||||
for (DWORD i = 0; i < dwVertexCount; i++) {
|
||||
if (highestVertexIndex < pIndexData[i]) {
|
||||
highestVertexIndex = pIndexData[i];
|
||||
}
|
||||
}
|
||||
|
||||
return dwIndexBase + highestVertexIndex + 1;
|
||||
}
|
||||
|
||||
int CountActiveD3DStreams()
|
||||
{
|
||||
int lastStreamIndex = 0;
|
||||
|
@ -630,7 +610,8 @@ void CxbxVertexBufferConverter::ConvertStream
|
|||
break;
|
||||
}
|
||||
case XTL::X_D3DVSDT_NONE: { // 0x02:
|
||||
// Test-case : WWE RAW2
|
||||
// Test-case : WWE RAW2
|
||||
// Test-case : PetitCopter
|
||||
LOG_TEST_CASE("X_D3DVSDT_NONE");
|
||||
// No host element data (but Xbox size can be above zero, when used for X_D3DVSD_MASK_SKIP*
|
||||
break;
|
||||
|
@ -783,12 +764,24 @@ void CxbxVertexBufferConverter::Apply(CxbxDrawContext *pDrawContext)
|
|||
m_pVertexShaderInfo = &(GetCxbxVertexShader(g_Xbox_VertexShader_Handle)->VertexShaderInfo);
|
||||
}
|
||||
|
||||
pDrawContext->VerticesInBuffer = GetVerticesInBuffer(
|
||||
pDrawContext->dwStartVertex,
|
||||
pDrawContext->dwVertexCount,
|
||||
pDrawContext->pIndexData,
|
||||
pDrawContext->dwIndexBase
|
||||
);
|
||||
// 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?
|
||||
if (pDrawContext->HighIndex == 0) {
|
||||
// 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)
|
||||
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;
|
||||
}
|
||||
|
||||
// Get the number of streams
|
||||
m_uiNbrStreams = GetNbrStreams(pDrawContext);
|
||||
|
@ -812,9 +805,9 @@ void CxbxVertexBufferConverter::Apply(CxbxDrawContext *pDrawContext)
|
|||
// handled by d3d :
|
||||
// Test-case : XDK Samples (FocusBlur, MotionBlur, Trees, PaintEffect, PlayField)
|
||||
// No need to set : pDrawContext->XboxPrimitiveType = X_D3DPT_TRIANGLESTRIP;
|
||||
pDrawContext->dwHostPrimitiveCount = EmuD3DVertex2PrimitiveCount(XTL::X_D3DPT_TRIANGLESTRIP, pDrawContext->dwVertexCount);
|
||||
pDrawContext->dwHostPrimitiveCount = ConvertXboxVertexCountToPrimitiveCount(XTL::X_D3DPT_TRIANGLESTRIP, pDrawContext->dwVertexCount);
|
||||
} else {
|
||||
pDrawContext->dwHostPrimitiveCount = EmuD3DVertex2PrimitiveCount(pDrawContext->XboxPrimitiveType, pDrawContext->dwVertexCount);
|
||||
pDrawContext->dwHostPrimitiveCount = ConvertXboxVertexCountToPrimitiveCount(pDrawContext->XboxPrimitiveType, pDrawContext->dwVertexCount);
|
||||
}
|
||||
|
||||
if (pDrawContext->XboxPrimitiveType == XTL::X_D3DPT_POLYGON) {
|
||||
|
|
|
@ -36,16 +36,17 @@ typedef struct _CxbxDrawContext
|
|||
IN XTL::X_D3DPRIMITIVETYPE XboxPrimitiveType;
|
||||
IN DWORD dwVertexCount;
|
||||
IN DWORD dwStartVertex; // Only D3DDevice_DrawVertices sets this (potentially higher than default 0)
|
||||
IN PWORD pIndexData;
|
||||
IN DWORD dwIndexBase;
|
||||
IN size_t VerticesInBuffer;
|
||||
IN PWORD pXboxIndexData; // Set by D3DDevice_DrawIndexedVertices, D3DDevice_DrawIndexedVerticesUP and HLE_draw_inline_elements
|
||||
IN DWORD dwBaseVertexIndex; // Set to g_XboxBaseVertexIndex in D3DDevice_DrawIndexedVertices
|
||||
IN INDEX16 LowIndex, HighIndex; // Set when pXboxIndexData is set
|
||||
IN size_t VerticesInBuffer; // Set by CxbxVertexBufferConverter::Apply
|
||||
// Data if Draw...UP call
|
||||
IN PVOID pXboxVertexStreamZeroData;
|
||||
IN UINT uiXboxVertexStreamZeroStride;
|
||||
// Values to be used on host
|
||||
OUT PVOID pHostVertexStreamZeroData;
|
||||
OUT UINT uiHostVertexStreamZeroStride;
|
||||
OUT DWORD dwHostPrimitiveCount;
|
||||
OUT DWORD dwHostPrimitiveCount; // Set by CxbxVertexBufferConverter::Apply
|
||||
}
|
||||
CxbxDrawContext;
|
||||
|
||||
|
|
|
@ -911,6 +911,11 @@ static void VshWriteShader(VSH_XBOX_SHADER *pShader,
|
|||
// We count down from the highest available on the host because Xbox titles don't use values that high, and we read from c192 (one above maximum Xbox c191 constant) and up
|
||||
static int temporaryRegisterBase = g_D3DCaps.VS20Caps.NumTemps - 13;
|
||||
moveConstantsToTemporaries << "mov r" << (temporaryRegisterBase + i) << ", c" << (CXBX_D3DVS_CONSTREG_VERTEXDATA4F_BASE + i) << "\n";
|
||||
// test-case : Blade II (before menu's)
|
||||
// test-case : Namco Museum 50th Anniversary (at boot)
|
||||
// test-case : Pac-Man World 2 (at boot)
|
||||
// test-case : The Simpsons Road Rage (leaving menu's, before entering in-game)
|
||||
// test-case : The SpongeBob SquarePants Movie (before menu's)
|
||||
LOG_TEST_CASE("Shader uses undeclared Vertex Input Registers");
|
||||
i++;
|
||||
continue;
|
||||
|
@ -1813,7 +1818,8 @@ private:
|
|||
{
|
||||
DWORD regNum = (XboxToken & X_D3DVSD_VERTEXREGMASK) >> X_D3DVSD_VERTEXREGSHIFT;
|
||||
if (regNum >= hostTemporaryRegisterCount /*12 for D3D8, D3D9 value depends on host GPU */) {
|
||||
// Lego Star Wars hits this
|
||||
// test-case : BLiNX: the time sweeper
|
||||
// test-case : Lego Star Wars
|
||||
LOG_TEST_CASE("RegNum > NumTemps");
|
||||
}
|
||||
return regNum;
|
||||
|
@ -1823,7 +1829,7 @@ private:
|
|||
{
|
||||
DWORD regNum = (XboxToken & X_D3DVSD_VERTEXREGINMASK) >> X_D3DVSD_VERTEXREGINSHIFT;
|
||||
if (regNum >= hostTemporaryRegisterCount /*12 for D3D8, D3D9 value depends on host GPU */) {
|
||||
// Lego Star Wars hits this
|
||||
// test-case : Lego Star Wars
|
||||
LOG_TEST_CASE("RegNum > NumTemps");
|
||||
}
|
||||
return regNum;
|
||||
|
|
|
@ -147,10 +147,9 @@ bool VerifySymbolAddressAgainstXRef(char *SymbolName, xbaddr Address, int XRef)
|
|||
return true;
|
||||
}
|
||||
|
||||
// For XREF_D3DTSS_TEXCOORDINDEX, Kabuki Warriors hits this case
|
||||
CxbxPopupMessage(LOG_LEVEL::WARNING, CxbxMsgDlgIcon_Warn,
|
||||
"Verification of %s failed : XREF was 0x%.8X while lookup gave 0x%.8X", SymbolName, XRefAddr, Address);
|
||||
// For XREF_D3DTSS_TEXCOORDINDEX, Kabuki Warriors hits this case
|
||||
// test case : Kabuki Warriors (for XREF_D3DTSS_TEXCOORDINDEX)
|
||||
return false;
|
||||
}*/
|
||||
|
||||
|
|
|
@ -3282,7 +3282,7 @@ bool EmuX86_DecodeException(LPEXCEPTION_POINTERS e)
|
|||
// We do not emulate processor specific registers just yet
|
||||
// Some titles attempt to manually set the TSC via this instruction
|
||||
// This needs fixing eventually, but should be acceptible to ignore for now!
|
||||
// Chase: Hollywood Stunt Driver hits this
|
||||
// test-case : Chase: Hollywood Stunt Driver
|
||||
EmuLog(LOG_LEVEL::WARNING, "WRMSR instruction ignored");
|
||||
break;
|
||||
case I_XOR:
|
||||
|
|
Loading…
Reference in New Issue