vertex buffer glitch fixes
This commit is contained in:
parent
0b57f61923
commit
0495630eb1
|
@ -3633,6 +3633,7 @@ HRESULT WINAPI XTL::EmuIDirect3DResource8_Register
|
|||
// TODO: HACK: Temporary?
|
||||
if(X_Format == 0x2E)
|
||||
{
|
||||
EmuCleanup("D3DFMT_LIN_D24S8 not yet supported!");
|
||||
X_Format = 0x12;
|
||||
Format = D3DFMT_A8R8G8B8;
|
||||
}
|
||||
|
@ -3852,19 +3853,19 @@ HRESULT WINAPI XTL::EmuIDirect3DResource8_Register
|
|||
{
|
||||
if(bSwizzled)
|
||||
{
|
||||
if((DWORD)pSrc == 0x80000000)
|
||||
{
|
||||
// TODO: Fix or handle this situation..?
|
||||
}
|
||||
else
|
||||
{
|
||||
XTL::EmuXGUnswizzleRect
|
||||
(
|
||||
pSrc + dwMipOffs, dwMipWidth, dwMipHeight, dwDepth, LockedRect.pBits,
|
||||
LockedRect.Pitch, iRect, iPoint, dwBPP
|
||||
);
|
||||
}
|
||||
if((DWORD)pSrc == 0x80000000)
|
||||
{
|
||||
// TODO: Fix or handle this situation..?
|
||||
}
|
||||
else
|
||||
{
|
||||
XTL::EmuXGUnswizzleRect
|
||||
(
|
||||
pSrc + dwMipOffs, dwMipWidth, dwMipHeight, dwDepth, LockedRect.pBits,
|
||||
LockedRect.Pitch, iRect, iPoint, dwBPP
|
||||
);
|
||||
}
|
||||
}
|
||||
else if(bCompressed)
|
||||
{
|
||||
// NOTE: compressed size is (dwWidth/2)*(dwHeight/2)/2, so each level divides by 4
|
||||
|
|
|
@ -44,6 +44,8 @@ bool XTL::g_bBrkPush = false;
|
|||
|
||||
bool g_bPBSkipPusher = false;
|
||||
|
||||
static void DbgDumpMesh(WORD *pIndexData, DWORD dwCount);
|
||||
|
||||
// pushbuffer execution emulation
|
||||
void XTL::EmuExecutePushBuffer
|
||||
(
|
||||
|
@ -58,6 +60,10 @@ void XTL::EmuExecutePushBuffer
|
|||
EmuCleanup("PushBuffer has fixups\n");
|
||||
|
||||
DWORD *pdwPushData = (DWORD*)pPushBuffer->Data;
|
||||
PVOID pIndexData = 0;
|
||||
|
||||
// cache of last 4 indices
|
||||
WORD pIBMem[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
|
||||
|
||||
D3DPRIMITIVETYPE PCPrimitiveType = (D3DPRIMITIVETYPE)-1;
|
||||
X_D3DPRIMITIVETYPE XBPrimitiveType = X_D3DPT_INVALID;
|
||||
|
@ -65,10 +71,6 @@ void XTL::EmuExecutePushBuffer
|
|||
// TODO: This technically should be enabled
|
||||
XTL::EmuUpdateDeferredStates();
|
||||
|
||||
// g_pD3DDevice8->Clear(0, NULL, D3DCLEAR_ZBUFFER, 0, 1.0, NULL);
|
||||
// g_pD3DDevice8->SetRenderState(D3DRS_ZENABLE, FALSE);
|
||||
// g_pD3DDevice8->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
|
||||
|
||||
#ifdef _DEBUG_TRACK_PB
|
||||
bool bShowPB = false;
|
||||
|
||||
|
@ -87,7 +89,8 @@ void XTL::EmuExecutePushBuffer
|
|||
}
|
||||
#endif
|
||||
|
||||
// NOTE: I believe 0x1808 is actually a seperate command, but I need to verify this.
|
||||
static LPDIRECT3DINDEXBUFFER8 pIndexBuffer=0;
|
||||
static uint maxIBSize = 0;
|
||||
|
||||
while(true)
|
||||
{
|
||||
|
@ -129,29 +132,135 @@ void XTL::EmuExecutePushBuffer
|
|||
PCPrimitiveType = EmuPrimitiveType(XBPrimitiveType);
|
||||
}
|
||||
}
|
||||
else // NVPB_InlineArray
|
||||
else if(dwMethod == 0x1808) // NVPB_FixLoop
|
||||
{
|
||||
PVOID pIndexData = 0;
|
||||
BOOL bInc = *pdwPushData & 0x40000000;
|
||||
|
||||
BOOL bFix = (dwMethod != 0x00001818);
|
||||
|
||||
if(bFix)
|
||||
#ifdef _DEBUG_TRACK_PB
|
||||
if(bShowPB)
|
||||
{
|
||||
if(bInc)
|
||||
dwCount = ((*pdwPushData - (0x40000000 | 0x00001818)) >> 18);
|
||||
printf(" NVPB_FixLoop(%d)\n", dwCount);
|
||||
printf("\n");
|
||||
printf(" Index Array Data...\n");
|
||||
|
||||
dwMethod = 0x1818;
|
||||
WORD *pwVal = (WORD*)(pdwPushData + 1);
|
||||
|
||||
for(uint s=0;s<dwCount;s++)
|
||||
{
|
||||
if(s%8 == 0) printf("\n ");
|
||||
|
||||
printf(" %.04X", *pwVal++);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
WORD *pwVal = (WORD*)(pdwPushData + 1);
|
||||
for(uint mi=0;mi<dwCount;mi++)
|
||||
{
|
||||
pIBMem[mi+2] = pwVal[mi];
|
||||
}
|
||||
|
||||
pdwPushData++;
|
||||
// perform rendering
|
||||
if(pIBMem[0] != 0xFFFF)
|
||||
{
|
||||
HRESULT hRet;
|
||||
|
||||
pIndexData = pdwPushData;
|
||||
// TODO: depreciate maxIBSize after N milliseconds..then N milliseconds later drop down to new highest
|
||||
if((dwCount*2 + 2*2) > maxIBSize)
|
||||
{
|
||||
if(pIndexBuffer != 0)
|
||||
{
|
||||
pIndexBuffer->Release();
|
||||
}
|
||||
|
||||
hRet = g_pD3DDevice8->CreateIndexBuffer(dwCount*2 + 2*2, 0, D3DFMT_INDEX16, D3DPOOL_MANAGED, &pIndexBuffer);
|
||||
|
||||
maxIBSize = dwCount*2 + 2*2;
|
||||
}
|
||||
else
|
||||
{
|
||||
hRet = D3D_OK;
|
||||
}
|
||||
|
||||
if(FAILED(hRet))
|
||||
EmuCleanup("Unable to create index buffer for PushBuffer emulation (0x1808, dwCount : %d)", dwCount);
|
||||
|
||||
// copy index data
|
||||
{
|
||||
WORD *pData=0;
|
||||
|
||||
pIndexBuffer->Lock(0, dwCount*2 + 2*2, (UCHAR**)&pData, NULL);
|
||||
|
||||
memcpy(pData, pIBMem, dwCount*2 + 2*2);
|
||||
|
||||
pIndexBuffer->Unlock();
|
||||
}
|
||||
|
||||
// render indexed vertices
|
||||
{
|
||||
UINT PrimitiveCount = EmuD3DVertex2PrimitiveCount(XBPrimitiveType, dwCount + 2);
|
||||
VertexPatchDesc VPDesc;
|
||||
|
||||
VPDesc.dwVertexCount = dwCount;
|
||||
VPDesc.PrimitiveType = XBPrimitiveType;
|
||||
VPDesc.dwPrimitiveCount = PrimitiveCount;
|
||||
VPDesc.dwOffset = 0;
|
||||
VPDesc.pVertexStreamZeroData = 0;
|
||||
VPDesc.uiVertexStreamZeroStride = 0;
|
||||
// TODO: Set the current shader and let the patcher handle it..
|
||||
VPDesc.hVertexShader = g_CurrentVertexShader;
|
||||
|
||||
VertexPatcher VertPatch;
|
||||
|
||||
bool bPatched = VertPatch.Apply(&VPDesc);
|
||||
|
||||
g_pD3DDevice8->SetIndices(pIndexBuffer, 0);
|
||||
|
||||
#ifdef _DEBUG_TRACK_PB
|
||||
if(!g_PBTrackDisable.exists((PVOID)pPushBuffer->Data))
|
||||
{
|
||||
#endif
|
||||
|
||||
if(!g_bPBSkipPusher)
|
||||
{
|
||||
if(IsValidCurrentShader())
|
||||
{
|
||||
g_pD3DDevice8->DrawIndexedPrimitive
|
||||
(
|
||||
PCPrimitiveType, 0, 8*1024*1024, 0, PrimitiveCount
|
||||
// PCPrimitiveType, 0, dwCount*2, 0, PrimitiveCount
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _DEBUG_TRACK_PB
|
||||
}
|
||||
#endif
|
||||
|
||||
VertPatch.Restore();
|
||||
|
||||
g_pD3DDevice8->SetIndices(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
pdwPushData += dwCount;
|
||||
}
|
||||
else if(dwMethod == 0x1800) // NVPB_InlineArray
|
||||
{
|
||||
BOOL bInc = *pdwPushData & 0x40000000;
|
||||
|
||||
if(bInc)
|
||||
{
|
||||
dwCount = ((*pdwPushData - (0x40000000 | 0x00001818)) >> 18)*2 + 2;
|
||||
}
|
||||
|
||||
pIndexData = ++pdwPushData;
|
||||
|
||||
#ifdef _DEBUG_TRACK_PB
|
||||
if(bShowPB)
|
||||
{
|
||||
printf(" NVPB_InlineArray(0x%.08X)...\n", pIndexData);
|
||||
printf(" NVPB_InlineArray(0x%.08X, %d)...\n", pIndexData, dwCount);
|
||||
printf("\n");
|
||||
printf(" Index Array Data...\n");
|
||||
|
||||
|
@ -198,29 +307,28 @@ void XTL::EmuExecutePushBuffer
|
|||
|
||||
// release ptr
|
||||
pActiveVB->Unlock();
|
||||
|
||||
DbgDumpMesh(pIndexData, dwCount);
|
||||
}
|
||||
#endif
|
||||
|
||||
pdwPushData += dwCount - (bInc ? 0 : 1);
|
||||
|
||||
|
||||
pdwPushData += (dwCount/2) - (bInc ? 0 : 2);
|
||||
|
||||
// perform rendering
|
||||
{
|
||||
static LPDIRECT3DINDEXBUFFER8 pIndexBuffer=0;
|
||||
static uint maxSize = 0;
|
||||
|
||||
HRESULT hRet;
|
||||
|
||||
// TODO: depreciate maxSize after N milliseconds..then N milliseconds later drop down to new highest
|
||||
if(dwCount*4 > maxSize)
|
||||
// TODO: depreciate maxIBSize after N milliseconds..then N milliseconds later drop down to new highest
|
||||
if(dwCount*2 > maxIBSize)
|
||||
{
|
||||
if(pIndexBuffer != 0)
|
||||
{
|
||||
pIndexBuffer->Release();
|
||||
}
|
||||
|
||||
hRet = g_pD3DDevice8->CreateIndexBuffer(dwCount*4, 0, D3DFMT_INDEX16, D3DPOOL_MANAGED, &pIndexBuffer);
|
||||
hRet = g_pD3DDevice8->CreateIndexBuffer(dwCount*2, 0, D3DFMT_INDEX16, D3DPOOL_MANAGED, &pIndexBuffer);
|
||||
|
||||
maxSize = dwCount*4;
|
||||
maxIBSize = dwCount*2;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -234,19 +342,30 @@ void XTL::EmuExecutePushBuffer
|
|||
{
|
||||
WORD *pData=0;
|
||||
|
||||
pIndexBuffer->Lock(0, dwCount*4, (UCHAR**)&pData, NULL);
|
||||
pIndexBuffer->Lock(0, dwCount*2, (UCHAR**)&pData, NULL);
|
||||
|
||||
memcpy(pData, pIndexData, dwCount*4);
|
||||
memcpy(pData, pIndexData, dwCount*2);
|
||||
|
||||
// remember last 2 indices
|
||||
if(dwCount >= 2)
|
||||
{
|
||||
pIBMem[0] = pData[dwCount - 2];
|
||||
pIBMem[1] = pData[dwCount - 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
pIBMem[0] = 0xFFFF;
|
||||
}
|
||||
|
||||
pIndexBuffer->Unlock();
|
||||
}
|
||||
|
||||
// render indexed vertices
|
||||
{
|
||||
UINT PrimitiveCount = EmuD3DVertex2PrimitiveCount(XBPrimitiveType, dwCount * 2);
|
||||
UINT PrimitiveCount = EmuD3DVertex2PrimitiveCount(XBPrimitiveType, dwCount);
|
||||
VertexPatchDesc VPDesc;
|
||||
|
||||
VPDesc.dwVertexCount = dwCount * 2;
|
||||
VPDesc.dwVertexCount = dwCount;
|
||||
VPDesc.PrimitiveType = XBPrimitiveType;
|
||||
VPDesc.dwPrimitiveCount = PrimitiveCount;
|
||||
VPDesc.dwOffset = 0;
|
||||
|
@ -309,6 +428,12 @@ void XTL::EmuExecutePushBuffer
|
|||
g_pD3DDevice8->SetIndices(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
pdwPushData--;
|
||||
}
|
||||
else
|
||||
{
|
||||
EmuCleanup("Unknown PushBuffer Operation (0x%.04X, %d)", dwMethod, dwCount);
|
||||
}
|
||||
|
||||
pdwPushData++;
|
||||
|
@ -329,3 +454,129 @@ void XTL::EmuExecutePushBuffer
|
|||
Sleep(500);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _DEBUG_TRACK_PB
|
||||
void DbgDumpMesh(WORD *pIndexData, DWORD dwCount)
|
||||
{
|
||||
if(!XTL::IsValidCurrentShader() || (dwCount == 0))
|
||||
return;
|
||||
|
||||
XTL::IDirect3DVertexBuffer8 *pActiveVB = NULL;
|
||||
|
||||
XTL::D3DVERTEXBUFFER_DESC VBDesc;
|
||||
|
||||
BYTE *pVBData = 0;
|
||||
UINT uiStride;
|
||||
|
||||
// retrieve stream data
|
||||
g_pD3DDevice8->GetStreamSource(0, &pActiveVB, &uiStride);
|
||||
|
||||
char szFileName[128];
|
||||
sprintf(szFileName, "C:\\TurokMesh-0x%.08X.x", pIndexData);
|
||||
FILE *dbgVertices = fopen(szFileName, "wt");
|
||||
|
||||
// retrieve stream desc
|
||||
pActiveVB->GetDesc(&VBDesc);
|
||||
|
||||
// unlock just in case
|
||||
pActiveVB->Unlock();
|
||||
|
||||
// grab ptr
|
||||
pActiveVB->Lock(0, 0, &pVBData, D3DLOCK_READONLY);
|
||||
|
||||
// print out stream data
|
||||
{
|
||||
uint32 maxIndex = 0;
|
||||
|
||||
WORD *pwChk = (WORD*)pIndexData;
|
||||
|
||||
for(uint chk=0;chk<dwCount;chk++)
|
||||
{
|
||||
DWORD x = *pwChk++;
|
||||
|
||||
if(x > maxIndex)
|
||||
maxIndex = x;
|
||||
}
|
||||
|
||||
if(maxIndex > ((VBDesc.Size/uiStride) - 1))
|
||||
maxIndex = (VBDesc.Size / uiStride) - 1;
|
||||
|
||||
fprintf(dbgVertices, "xof 0303txt 0032\n");
|
||||
fprintf(dbgVertices, "\n");
|
||||
fprintf(dbgVertices, "//\n");
|
||||
fprintf(dbgVertices, "// Vertex Stream Data (0x%.08X)...\n", pActiveVB);
|
||||
fprintf(dbgVertices, "//\n");
|
||||
fprintf(dbgVertices, "// Format : %d\n", VBDesc.Format);
|
||||
fprintf(dbgVertices, "// Size : %d bytes\n", VBDesc.Size);
|
||||
fprintf(dbgVertices, "// FVF : 0x%.08X\n", VBDesc.FVF);
|
||||
fprintf(dbgVertices, "// iCount : %d\n", dwCount/2);
|
||||
fprintf(dbgVertices, "//\n");
|
||||
fprintf(dbgVertices, "\n");
|
||||
fprintf(dbgVertices, "Frame SCENE_ROOT {\n");
|
||||
fprintf(dbgVertices, "\n");
|
||||
fprintf(dbgVertices, " FrameTransformMatrix {\n");
|
||||
fprintf(dbgVertices, " 1.000000,0.000000,0.000000,0.000000,\n");
|
||||
fprintf(dbgVertices, " 0.000000,1.000000,0.000000,0.000000,\n");
|
||||
fprintf(dbgVertices, " 0.000000,0.000000,1.000000,0.000000,\n");
|
||||
fprintf(dbgVertices, " 0.000000,0.000000,0.000000,1.000000;;\n");
|
||||
fprintf(dbgVertices, " }\n");
|
||||
fprintf(dbgVertices, "\n");
|
||||
fprintf(dbgVertices, " Frame Turok1 {\n");
|
||||
fprintf(dbgVertices, "\n");
|
||||
fprintf(dbgVertices, " FrameTransformMatrix {\n");
|
||||
fprintf(dbgVertices, " 1.000000,0.000000,0.000000,0.000000,\n");
|
||||
fprintf(dbgVertices, " 0.000000,1.000000,0.000000,0.000000,\n");
|
||||
fprintf(dbgVertices, " 0.000000,0.000000,1.000000,0.000000,\n");
|
||||
fprintf(dbgVertices, " 0.000000,0.000000,0.000000,1.000000;;\n");
|
||||
fprintf(dbgVertices, " }\n");
|
||||
fprintf(dbgVertices, "\n");
|
||||
fprintf(dbgVertices, " Mesh {\n");
|
||||
fprintf(dbgVertices, " %d;\n", maxIndex+1);
|
||||
|
||||
uint max = maxIndex+1;
|
||||
for(uint v=0;v<max;v++)
|
||||
{
|
||||
fprintf(dbgVertices, " %f;%f;%f;%s\n",
|
||||
*(FLOAT*)&pVBData[v*uiStride+0],
|
||||
*(FLOAT*)&pVBData[v*uiStride+4],
|
||||
*(FLOAT*)&pVBData[v*uiStride+8],
|
||||
(v < (max - 1)) ? "," : ";");
|
||||
}
|
||||
|
||||
fprintf(dbgVertices, " %d;\n", dwCount - 2);
|
||||
|
||||
WORD *pwVal = (WORD*)pIndexData;
|
||||
|
||||
max = dwCount;
|
||||
|
||||
DWORD a = *pwVal++;
|
||||
DWORD b = *pwVal++;
|
||||
DWORD c = *pwVal++;
|
||||
|
||||
DWORD la = a,lb = b,lc = c;
|
||||
|
||||
for(uint i=2;i<max;i++)
|
||||
{
|
||||
fprintf(dbgVertices, " 3;%d,%d,%d;%s\n",
|
||||
a,b,c, (i < (max - 1)) ? "," : ";");
|
||||
|
||||
a = b;
|
||||
b = c;
|
||||
c = *pwVal++;
|
||||
|
||||
la = a;
|
||||
lb = b;
|
||||
lc = c;
|
||||
}
|
||||
|
||||
fprintf(dbgVertices, " }\n");
|
||||
fprintf(dbgVertices, " }\n");
|
||||
fprintf(dbgVertices, "}\n");
|
||||
|
||||
fclose(dbgVertices);
|
||||
}
|
||||
|
||||
// release ptr
|
||||
pActiveVB->Unlock();
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -226,4 +226,4 @@ uint32 ResourceTracker::get_count(void)
|
|||
this->Unlock();
|
||||
|
||||
return uiCount;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue