vertex buffer glitch fixes

This commit is contained in:
Aaron Robinson 2004-04-15 05:49:12 +00:00
parent 0b57f61923
commit 0495630eb1
4 changed files with 297 additions and 45 deletions

BIN
Cxbx.opt

Binary file not shown.

View File

@ -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

View File

@ -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

View File

@ -226,4 +226,4 @@ uint32 ResourceTracker::get_count(void)
this->Unlock();
return uiCount;
}
}