More Index Buffer work
This commit is contained in:
parent
7939ca665d
commit
7b60aa1020
|
@ -754,6 +754,9 @@ void CxbxKrnlInit
|
|||
// initialize grapchics
|
||||
DbgPrintf("EmuMain: Initializing render window.\n");
|
||||
XTL::CxbxInitWindow(pXbeHeader, dwXbeHeaderSize);
|
||||
|
||||
EmuHLEIntercept(pXbeHeader);
|
||||
|
||||
if (bLLE_GPU)
|
||||
{
|
||||
DbgPrintf("EmuMain: Initializing OpenGL.\n");
|
||||
|
@ -765,7 +768,6 @@ void CxbxKrnlInit
|
|||
XTL::EmuD3DInit();
|
||||
}
|
||||
|
||||
EmuHLEIntercept(pXbeHeader);
|
||||
// Apply Media Patches to bypass Anti-Piracy checks
|
||||
// Required until we perfect emulation of X2 DVD Authentication
|
||||
// See: https://multimedia.cx/eggs/xbox-sphinx-protocol/
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
// ******************************************************************
|
||||
#define _CXBXKRNL_INTERNAL
|
||||
#define _XBOXKRNL_DEFEXTRN_
|
||||
#include "xxhash32.h"
|
||||
|
||||
// prevent name collisions
|
||||
namespace xboxkrnl
|
||||
|
@ -53,6 +54,7 @@ namespace xboxkrnl
|
|||
#include "EmuAlloc.h"
|
||||
#include "MemoryManager.h"
|
||||
#include "EmuXTL.h"
|
||||
#include "HLEDatabase.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <process.h>
|
||||
|
@ -172,6 +174,9 @@ struct EmuD3D8CreateDeviceProxyData
|
|||
}
|
||||
g_EmuCDPD = {0};
|
||||
|
||||
// TODO: This should be a D3DDevice structure
|
||||
BYTE g_XboxD3DDevice[ONE_MB] = { 0 };
|
||||
|
||||
VOID XTL::CxbxInitWindow(Xbe::Header *XbeHeader, uint32 XbeHeaderSize)
|
||||
{
|
||||
g_EmuShared->GetXBVideo(&g_XBVideo);
|
||||
|
@ -1499,32 +1504,17 @@ static void EmuUnswizzleTextureStages()
|
|||
}
|
||||
|
||||
typedef struct {
|
||||
DWORD IndexData;
|
||||
DWORD IndexEnd;
|
||||
XTL::IDirect3DIndexBuffer8* pHostIndexBuffer;
|
||||
DWORD Hash = 0;
|
||||
DWORD IndexCount = 0;;
|
||||
XTL::IDirect3DIndexBuffer8* pHostIndexBuffer = nullptr;
|
||||
} ConvertedIndexBuffer;
|
||||
|
||||
std::vector<ConvertedIndexBuffer> g_ConvertedIndexBuffers;
|
||||
std::map<PWORD, ConvertedIndexBuffer> g_ConvertedIndexBuffers;
|
||||
|
||||
void CxbxRemoveIndexBuffer(PWORD pData)
|
||||
{
|
||||
// Now, see if we already have a (partial) index buffer for this range :
|
||||
ConvertedIndexBuffer* pConvertedIndexBuffer = nullptr;
|
||||
|
||||
auto it = g_ConvertedIndexBuffers.begin();
|
||||
for (; it != g_ConvertedIndexBuffers.end(); ++it) {
|
||||
// Check if we found an index buffer containing this pointer
|
||||
if ((DWORD)it->IndexData <= (DWORD)pData && (DWORD)pData < (DWORD)it->IndexEnd) {
|
||||
pConvertedIndexBuffer = &(*it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pConvertedIndexBuffer != nullptr) {
|
||||
DbgPrintf("DxbxRemoveIndexBuffer: Removing buffer for 0x%08x-0x%08x", pConvertedIndexBuffer->IndexData, pConvertedIndexBuffer->IndexEnd);
|
||||
pConvertedIndexBuffer->pHostIndexBuffer->Release();
|
||||
g_ConvertedIndexBuffers.erase(it);
|
||||
}
|
||||
// HACK: Never Free
|
||||
return;
|
||||
}
|
||||
|
||||
void CxbxUpdateActiveIndexBuffer
|
||||
|
@ -1534,116 +1524,66 @@ void CxbxUpdateActiveIndexBuffer
|
|||
UINT &uiStartIndex
|
||||
)
|
||||
{
|
||||
PWORD pwInitialStart = pIndexData; // Remember this to calculate StartIndex later!
|
||||
PWORD pwIndexEnd = pIndexData + IndexCount;
|
||||
bool MustCopy = false;
|
||||
|
||||
// Note : We assume that all outdated index buffer(s) are already removed,
|
||||
// so that we'll never merge with buffers already destroyed on the Xbox side!
|
||||
|
||||
// Now, see if we already have a (partial) index buffer for this range :
|
||||
ConvertedIndexBuffer* pConvertedIndexBuffer = nullptr;
|
||||
|
||||
for (auto it = g_ConvertedIndexBuffers.begin(); it != g_ConvertedIndexBuffers.end(); ++it) {
|
||||
// Check if the given index range overlaps with this buffer :
|
||||
if ((DWORD)pIndexData > (DWORD)it->IndexEnd) {
|
||||
// new buffer starts beyond current (so no overlap)
|
||||
}
|
||||
else if ((DWORD)pwIndexEnd < (DWORD)it->IndexData) {
|
||||
// new buffer end before current (so no overlap)
|
||||
}
|
||||
else {
|
||||
// The new and current buffer overlap - we found a merge candidate!
|
||||
break;
|
||||
}
|
||||
|
||||
pConvertedIndexBuffer = &(*it);
|
||||
}
|
||||
|
||||
// Did we find a merge candidate?
|
||||
if (pConvertedIndexBuffer == nullptr) {
|
||||
DbgPrintf("DxbxUpdateActiveIndexBuffer: Creating new buffer for 0x%08x-0x%08x (%d indices)\n", pIndexData, pwIndexEnd, pwIndexEnd - pIndexData);
|
||||
|
||||
// No merge, so add a new converted index buffer to the chain :
|
||||
// If the index buffer is not already in our data structure, add it
|
||||
if(g_ConvertedIndexBuffers.find(pIndexData) == g_ConvertedIndexBuffers.end()) {
|
||||
ConvertedIndexBuffer buffer;
|
||||
g_ConvertedIndexBuffers.push_back(buffer);
|
||||
g_ConvertedIndexBuffers[pIndexData] = buffer;
|
||||
};
|
||||
|
||||
pConvertedIndexBuffer = &g_ConvertedIndexBuffers.back();
|
||||
MustCopy = true;
|
||||
}
|
||||
else {
|
||||
// We found an existing index buffer, see if we must extend it's bounds :
|
||||
if ((DWORD)pIndexData < pConvertedIndexBuffer->IndexData) {
|
||||
MustCopy = true; // The merge has a new start pointer
|
||||
}
|
||||
else {
|
||||
pIndexData = (PWORD)pConvertedIndexBuffer->IndexData; // The merge keeps the old start pointer
|
||||
}
|
||||
|
||||
if ((DWORD)pwIndexEnd > pConvertedIndexBuffer->IndexEnd) {
|
||||
MustCopy = true; // The merge has a new end pointer
|
||||
}
|
||||
else {
|
||||
pwIndexEnd = (PWORD)pConvertedIndexBuffer->IndexEnd; // The merge keeps the old end pointer
|
||||
}
|
||||
|
||||
// TODO : What if this grow causes two (or more) existing ranges to overlap - we should merge them all...
|
||||
// TOOD : What if the index buffer exceeds D3DCaps.MaxVertexIndex ?
|
||||
|
||||
// TODO : If not MustCopy, Add a CRC check on the contents (forcing MustCopy) ?
|
||||
|
||||
if (MustCopy) {
|
||||
DbgPrintf("DxbxUpdateActiveIndexBuffer: Enlarging buffer to 0x%08x-0x%08x (%d indices)\n", pIndexData, pwIndexEnd, pwIndexEnd - pIndexData);
|
||||
|
||||
// Remove previous native buffer (this might leave one stale reference,
|
||||
// but this one will be released automatically in the next SetIndices call) :
|
||||
pConvertedIndexBuffer->pHostIndexBuffer->Release();
|
||||
pConvertedIndexBuffer->pHostIndexBuffer = nullptr;
|
||||
}
|
||||
// If the size has changed, free the buffer so it will be re-created
|
||||
if (g_ConvertedIndexBuffers[pIndexData].pHostIndexBuffer != nullptr &&
|
||||
g_ConvertedIndexBuffers[pIndexData].IndexCount != IndexCount) {
|
||||
g_ConvertedIndexBuffers[pIndexData].Hash = 0;
|
||||
g_ConvertedIndexBuffers[pIndexData].IndexCount = 0;
|
||||
g_ConvertedIndexBuffers[pIndexData].pHostIndexBuffer->Release();
|
||||
g_ConvertedIndexBuffers[pIndexData].pHostIndexBuffer = nullptr;
|
||||
}
|
||||
|
||||
HRESULT hRet;
|
||||
|
||||
if (MustCopy) {
|
||||
// Remember the (new) buffer bounds :
|
||||
pConvertedIndexBuffer->IndexData = (DWORD)pIndexData;
|
||||
pConvertedIndexBuffer->IndexEnd = (DWORD)pwIndexEnd;
|
||||
IndexCount = pwIndexEnd - pIndexData; // Calculate the number of WORD's between start & end
|
||||
|
||||
// Create a new native index buffer of the above determined size :
|
||||
hRet = g_pD3DDevice8->CreateIndexBuffer(
|
||||
// If we need to create an index buffer, do so.
|
||||
if (g_ConvertedIndexBuffers[pIndexData].pHostIndexBuffer == nullptr) {
|
||||
// Create a new native index buffer of the above determined size :
|
||||
HRESULT hRet = g_pD3DDevice8->CreateIndexBuffer(
|
||||
IndexCount * 2,
|
||||
D3DUSAGE_WRITEONLY,
|
||||
XTL::D3DFMT_INDEX16,
|
||||
XTL::D3DPOOL_MANAGED,
|
||||
&pConvertedIndexBuffer->pHostIndexBuffer);
|
||||
&g_ConvertedIndexBuffers[pIndexData].pHostIndexBuffer);
|
||||
|
||||
if (FAILED(hRet)) {
|
||||
CxbxKrnlCleanup("DxbxUpdateActiveIndexBuffer: IndexBuffer Create Failed!");
|
||||
}
|
||||
}
|
||||
|
||||
// If the data needs updating, do so
|
||||
uint32_t uiHash = XXHash32::hash(pIndexData, IndexCount * 2, 0);
|
||||
if (uiHash != g_ConvertedIndexBuffers[pIndexData].Hash) {
|
||||
g_ConvertedIndexBuffers[pIndexData].IndexCount = IndexCount;
|
||||
|
||||
// Copy the xbox indexes into this native buffer :
|
||||
BYTE* pData = nullptr;
|
||||
|
||||
pConvertedIndexBuffer->pHostIndexBuffer->Lock(0, 0, &pData, 0);
|
||||
g_ConvertedIndexBuffers[pIndexData].pHostIndexBuffer->Lock(0, 0, &pData, 0);
|
||||
if (pData == nullptr) {
|
||||
CxbxKrnlCleanup("DxbxUpdateActiveIndexBuffer: Could not lock index buffer!");
|
||||
}
|
||||
|
||||
DbgPrintf("DxbxUpdateActiveIndexBuffer: Copying %d indices (D3DFMT_INDEX16)\n", IndexCount);
|
||||
memcpy(pData, pIndexData, IndexCount * 2); // TODO : Why does this crash at the 4th copy in Cartoon sample?
|
||||
memcpy(pData, pIndexData, IndexCount * 2);
|
||||
|
||||
pConvertedIndexBuffer->pHostIndexBuffer->Unlock();
|
||||
g_ConvertedIndexBuffers[pIndexData].pHostIndexBuffer->Unlock();
|
||||
}
|
||||
|
||||
DWORD index = 0;
|
||||
// Determine the vertex index from D3D
|
||||
index = *(DWORD*)(g_XboxD3DDevice + 0x1C);
|
||||
|
||||
// Activate the new native index buffer :
|
||||
hRet = g_pD3DDevice8->SetIndices(pConvertedIndexBuffer->pHostIndexBuffer, 0);
|
||||
HRESULT hRet = g_pD3DDevice8->SetIndices(g_ConvertedIndexBuffers[pIndexData].pHostIndexBuffer, index);
|
||||
if (FAILED(hRet)) {
|
||||
CxbxKrnlCleanup("DxbxUpdateActiveIndexBuffer: SetIndices Failed!");
|
||||
}
|
||||
|
||||
// Make sure the caller knows what StartIndex it has to use to point to the indicated index start pointer :
|
||||
uiStartIndex = (UINT)pwInitialStart - (UINT)pConvertedIndexBuffer->IndexData;
|
||||
uiStartIndex = 0;
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
|
@ -1705,8 +1645,9 @@ HRESULT WINAPI XTL::EMUPATCH(Direct3D_CreateDevice)
|
|||
// Wait until proxy is completed
|
||||
while(g_EmuCDPD.bReady)
|
||||
Sleep(10);
|
||||
|
||||
|
||||
|
||||
// Set the Xbox g_pD3DDevice pointer to our D3D Device object
|
||||
*((DWORD*)XRefDataBase[XREF_D3DDEVICE]) = (DWORD)g_XboxD3DDevice;
|
||||
|
||||
return g_EmuCDPD.hRet;
|
||||
}
|
||||
|
@ -5335,7 +5276,7 @@ ULONG WINAPI XTL::EMUPATCH(D3DResource_AddRef)
|
|||
ULONG uRet = (++(pThis->Common)) & X_D3DCOMMON_REFCOUNT_MASK;
|
||||
|
||||
// Index buffers don't have a native resource assigned
|
||||
if (!(pThis->Common & X_D3DCOMMON_TYPE_INDEXBUFFER)) {
|
||||
if (pThis->Common & X_D3DCOMMON_TYPE_MASK != X_D3DCOMMON_TYPE_INDEXBUFFER) {
|
||||
EmuVerifyResourceIsRegistered(pThis);
|
||||
|
||||
// If this is the first reference on a surface
|
||||
|
@ -5395,7 +5336,7 @@ ULONG WINAPI XTL::EMUPATCH(D3DResource_Release)
|
|||
}
|
||||
|
||||
EMUPATCH(D3DDevice_EnableOverlay)(FALSE);
|
||||
} else if (pThis->Common & X_D3DCOMMON_TYPE_INDEXBUFFER) {
|
||||
} else if ((pThis->Common & X_D3DCOMMON_TYPE_MASK) == X_D3DCOMMON_TYPE_INDEXBUFFER) {
|
||||
if ((pThis->Common & X_D3DCOMMON_REFCOUNT_MASK) == 1) {
|
||||
CxbxRemoveIndexBuffer((PWORD)GetDataFromXboxResource(pThis));
|
||||
}
|
||||
|
@ -5420,8 +5361,10 @@ ULONG WINAPI XTL::EMUPATCH(D3DResource_Release)
|
|||
D3DRESOURCETYPE Type = pResource8->GetType();
|
||||
#endif
|
||||
|
||||
uRet = pResource8->Release();
|
||||
if(uRet == 0)
|
||||
/*
|
||||
* Temporarily disable this until we figure out correct reference counting!
|
||||
uRet = pResource8->Release();
|
||||
if(uRet == 0 && pThis->Common)
|
||||
{
|
||||
DbgPrintf("EmuIDirect3DResource8_Release : Cleaned up a Resource!\n");
|
||||
|
||||
|
@ -5434,7 +5377,7 @@ ULONG WINAPI XTL::EMUPATCH(D3DResource_Release)
|
|||
#endif
|
||||
|
||||
//delete pThis;
|
||||
}
|
||||
} */
|
||||
}
|
||||
|
||||
pThis->Common--; // Release
|
||||
|
@ -7705,7 +7648,6 @@ XTL::X_D3DVertexBuffer* WINAPI XTL::EMUPATCH(D3DDevice_GetStreamSource2)
|
|||
X_D3DVertexBuffer* pVertexBuffer = EmuNewD3DVertexBuffer();
|
||||
g_pD3DDevice8->GetStreamSource(StreamNumber, &pVertexBuffer->EmuVertexBuffer8, pStride);
|
||||
|
||||
|
||||
return pVertexBuffer;
|
||||
}
|
||||
|
||||
|
@ -8113,6 +8055,8 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_DrawIndexedVertices)
|
|||
|
||||
VertPatch.Restore();
|
||||
|
||||
g_pD3DDevice8->SetIndices(NULL, 0);
|
||||
|
||||
// Execute callback procedure
|
||||
if( g_CallbackType == X_D3DCALLBACK_WRITE )
|
||||
{
|
||||
|
|
|
@ -138,8 +138,13 @@ void EmuHLEIntercept(Xbe::Header *pXbeHeader)
|
|||
CxbxKrnlCleanup("EmuD3DDeferredTextureState was not found!");
|
||||
}
|
||||
|
||||
if (g_HLECache.find("D3DDEVICE") == g_HLECache.end()) {
|
||||
CxbxKrnlCleanup("D3DDEVICE was not found!");
|
||||
}
|
||||
|
||||
XTL::EmuD3DDeferredRenderState = (DWORD*)g_HLECache["D3DDeferredRenderState"];
|
||||
XTL::EmuD3DDeferredTextureState = (DWORD*)g_HLECache["D3DDeferredTextureState"];
|
||||
XRefDataBase[XREF_D3DDEVICE] = g_HLECache["D3DDEVICE"];
|
||||
|
||||
// TODO: Move this into a function rather than duplicating from HLE scanning code
|
||||
for (int v = 0; v<44; v++) {
|
||||
|
@ -150,6 +155,7 @@ void EmuHLEIntercept(Xbe::Header *pXbeHeader)
|
|||
for (int v = 0; v<32; v++)
|
||||
XTL::EmuD3DDeferredTextureState[v + s * 32] = X_D3DTSS_UNK;
|
||||
}
|
||||
|
||||
g_HLECacheUsed = true;
|
||||
}
|
||||
|
||||
|
@ -385,6 +391,8 @@ void EmuHLEIntercept(Xbe::Header *pXbeHeader)
|
|||
XRefDataBase[XREF_D3DDEVICE] = DerivedAddr_D3DDevice;
|
||||
}
|
||||
|
||||
g_HLECache["D3DDEVICE"] = DerivedAddr_D3DDevice;
|
||||
|
||||
// Temporary verification - is XREF_D3DRS_CULLMODE derived correctly?
|
||||
if (XRefDataBase[XREF_D3DRS_CULLMODE] != DerivedAddr_D3DRS_CULLMODE)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue