Include a palette hash in the texture lookup key, instead of patching Palette_Lock functions and freeing textures when setting palette's.
To avoid overflowing the resource cache, PruneResourceCache now applies cache eviction as well.
This commit is contained in:
parent
67068303de
commit
5d3cae890c
|
@ -137,7 +137,7 @@ typedef struct {
|
|||
} s_Xbox_Callback;
|
||||
|
||||
static std::queue<s_Xbox_Callback> g_Xbox_CallbackQueue;
|
||||
static bool g_bHack_DisableHostGPUQueries = false; // TODO : Make configurable
|
||||
static bool g_bHack_DisableHostGPUQueries = true; // TODO : Make configurable
|
||||
static IDirect3DQuery *g_pHostQueryWaitForIdle = nullptr;
|
||||
static IDirect3DQuery *g_pHostQueryCallbackEvent = nullptr;
|
||||
|
||||
|
@ -172,7 +172,7 @@ static XTL::DWORD *g_pXbox_BeginPush_Buffer = xbnullptr; // pri
|
|||
static XTL::PVOID g_pXbox_Palette[XTL::X_D3DTS_STAGECOUNT] = { xbnullptr, xbnullptr, xbnullptr, xbnullptr }; // cached palette pointer
|
||||
|
||||
XTL::X_D3DBaseTexture *EmuD3DActiveTexture[XTL::X_D3DTS_STAGECOUNT] = {0,0,0,0}; // Set by our D3DDevice_SetTexture and D3DDevice_SwitchTexture patches
|
||||
static XTL::X_D3DBaseTexture CxbxActiveTextureCopies[XTL::X_D3DTS_STAGECOUNT] = {}; // cached active texture
|
||||
static XTL::X_D3DBaseTexture CxbxActiveTextureCopies[XTL::X_D3DTS_STAGECOUNT] = {}; // Set by D3DDevice_SwitchTexture. Cached active texture
|
||||
|
||||
/* Unused :
|
||||
static XTL::DWORD *g_Xbox_D3DDevice; // TODO: This should be a D3DDevice structure
|
||||
|
@ -741,7 +741,7 @@ bool IsResourceAPixelContainer(XTL::X_D3DResource* pXboxResource)
|
|||
return false;
|
||||
}
|
||||
|
||||
resource_key_t GetHostResourceKey(XTL::X_D3DResource* pXboxResource)
|
||||
resource_key_t GetHostResourceKey(XTL::X_D3DResource* pXboxResource, int iTextureStage = 0)
|
||||
{
|
||||
resource_key_t key = 0;
|
||||
if (pXboxResource != xbnullptr) {
|
||||
|
@ -749,9 +749,20 @@ resource_key_t GetHostResourceKey(XTL::X_D3DResource* pXboxResource)
|
|||
key ^= pXboxResource->Data;
|
||||
key ^= (pXboxResource->Common & X_D3DCOMMON_TYPE_MASK) >> X_D3DCOMMON_TYPE_SHIFT;
|
||||
if (IsResourceAPixelContainer(pXboxResource)) {
|
||||
// Pixel containers have more values they are be identified by:
|
||||
key ^= ((uint64_t)((XTL::X_D3DPixelContainer *)pXboxResource)->Format) << 24;
|
||||
key ^= ((uint64_t)((XTL::X_D3DPixelContainer *)pXboxResource)->Size) << 32;
|
||||
// Pixel containers have more values they must be identified by:
|
||||
auto pPixelContainer = (XTL::X_D3DPixelContainer*)pXboxResource;
|
||||
key ^= ((uint64_t)pPixelContainer->Format) << 24;
|
||||
key ^= ((uint64_t)pPixelContainer->Size) << 32;
|
||||
// For paletized textures, include the current palette hash as well
|
||||
if (GetXboxPixelContainerFormat(pPixelContainer) == XTL::X_D3DFMT_P8) {
|
||||
// Protect for when this gets hit before an actual texture is set
|
||||
if (g_pXbox_Palette[iTextureStage] != xbnullptr) {
|
||||
// This caters for palette changes (only the active one will be used,
|
||||
// any intermediate changes have no effect). Obsolete palette texture
|
||||
// conversions will be pruned together with g_Xbox_Direct3DResources
|
||||
key ^= ComputeHash(g_pXbox_Palette[iTextureStage], 256 * sizeof(D3DCOLOR));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// For other resource types, do include their Xbox resource address (TODO : come up with something better)
|
||||
|
@ -775,6 +786,23 @@ void FreeHostResource(resource_key_t key)
|
|||
}
|
||||
}
|
||||
|
||||
void PruneResourceCache()
|
||||
{
|
||||
// TODO : Implement a better cache eviction algorithm (like least-recently used)
|
||||
// Poor mans cache eviction policy: just clear it once it overflows (5000 entries should be good enough)
|
||||
if (g_Xbox_Direct3DResources.size() < 5000)
|
||||
return;
|
||||
|
||||
auto hostResourceIterator = g_Xbox_Direct3DResources.begin();
|
||||
while (hostResourceIterator != g_Xbox_Direct3DResources.end()) {
|
||||
if (hostResourceIterator->second.pHostResource) {
|
||||
(hostResourceIterator->second.pHostResource)->Release();
|
||||
}
|
||||
hostResourceIterator++;
|
||||
}
|
||||
g_Xbox_Direct3DResources.clear();
|
||||
}
|
||||
|
||||
void ForceResourceRehash(XTL::X_D3DResource* pXboxResource)
|
||||
{
|
||||
auto key = GetHostResourceKey(pXboxResource);
|
||||
|
@ -791,7 +819,7 @@ IDirect3DResource *GetHostResource(XTL::X_D3DResource *pXboxResource, DWORD D3DU
|
|||
|
||||
EmuVerifyResourceIsRegistered(pXboxResource, D3DUsage, iTextureStage, /*dwSize=*/0);
|
||||
|
||||
auto key = GetHostResourceKey(pXboxResource);
|
||||
auto key = GetHostResourceKey(pXboxResource, iTextureStage);
|
||||
auto it = g_Xbox_Direct3DResources.find(key);
|
||||
if (it == g_Xbox_Direct3DResources.end() || !it->second.pHostResource) {
|
||||
EmuLog(LOG_LEVEL::WARNING, "GetHostResource: Resource not registered or does not have a host counterpart!");
|
||||
|
@ -2380,6 +2408,9 @@ static void EmuVerifyResourceIsRegistered(XTL::X_D3DResource *pResource, DWORD D
|
|||
if (pResource->Data == xbnull)
|
||||
return;
|
||||
|
||||
// Before we start, make sure the cache stays limited in size
|
||||
PruneResourceCache();
|
||||
|
||||
auto key = GetHostResourceKey(pResource);
|
||||
auto it = g_Xbox_Direct3DResources.find(key);
|
||||
if (it != g_Xbox_Direct3DResources.end()) {
|
||||
|
@ -7582,72 +7613,14 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetPalette)
|
|||
// g_pD3DDevice9->SetPaletteEntries(Stage?, (PALETTEENTRY*)pPalette->Data);
|
||||
// g_pD3DDevice9->SetCurrentTexturePalette(Stage, Stage);
|
||||
|
||||
if (Stage < XTL::X_D3DTS_STAGECOUNT) {
|
||||
if (g_pXbox_Palette[Stage] != GetDataFromXboxResource(pPalette) && EmuD3DActiveTexture[Stage] != nullptr) {
|
||||
// If the palette for a texture has changed, we need to re-convert the texture
|
||||
FreeHostResource(GetHostResourceKey(EmuD3DActiveTexture[Stage]));
|
||||
}
|
||||
|
||||
// Cache palette data and size
|
||||
if (Stage >= XTL::X_D3DTS_STAGECOUNT) {
|
||||
LOG_TEST_CASE("Stage out of bounds");
|
||||
} else {
|
||||
// Note : Actual update of paletized textures (X_D3DFMT_P8) happens in EmuUpdateActiveTextureStages!
|
||||
g_pXbox_Palette[Stage] = GetDataFromXboxResource(pPalette);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ******************************************************************
|
||||
// * patch: IDirect3DPalette8_Lock
|
||||
// ******************************************************************
|
||||
VOID WINAPI XTL::EMUPATCH(D3DPalette_Lock)
|
||||
(
|
||||
X_D3DPalette *pThis,
|
||||
D3DCOLOR **ppColors,
|
||||
DWORD Flags
|
||||
)
|
||||
{
|
||||
LOG_FUNC_BEGIN
|
||||
LOG_FUNC_ARG(pThis)
|
||||
LOG_FUNC_ARG_OUT(ppColors)
|
||||
LOG_FUNC_ARG(Flags)
|
||||
LOG_FUNC_END;
|
||||
|
||||
XB_trampoline(VOID, WINAPI, D3DPalette_Lock, (X_D3DPalette*, D3DCOLOR**, DWORD));
|
||||
XB_D3DPalette_Lock(pThis, ppColors, Flags);
|
||||
|
||||
// Check if this palette is in use by a texture stage, and force it to be re-converted if yes
|
||||
for (int i = 0; i < XTL::X_D3DTS_STAGECOUNT; i++) {
|
||||
if (EmuD3DActiveTexture[i] != nullptr && g_pXbox_Palette[i] == GetDataFromXboxResource(pThis)) {
|
||||
FreeHostResource(GetHostResourceKey(EmuD3DActiveTexture[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
// * patch: IDirect3DPalette8_Lock2
|
||||
// ******************************************************************
|
||||
D3DCOLOR * WINAPI XTL::EMUPATCH(D3DPalette_Lock2)
|
||||
(
|
||||
X_D3DPalette *pThis,
|
||||
DWORD Flags
|
||||
)
|
||||
{
|
||||
LOG_FUNC_BEGIN
|
||||
LOG_FUNC_ARG(pThis)
|
||||
LOG_FUNC_ARG(Flags)
|
||||
LOG_FUNC_END;
|
||||
|
||||
XB_trampoline(D3DCOLOR*, WINAPI, D3DPalette_Lock2, (X_D3DPalette*, DWORD));
|
||||
D3DCOLOR* pData = XB_D3DPalette_Lock2(pThis, Flags);
|
||||
|
||||
// Check if this palette is in use by a texture stage, and force it to be re-converted if yes
|
||||
for (int i = 0; i < XTL::X_D3DTS_STAGECOUNT; i++) {
|
||||
if (EmuD3DActiveTexture[i] != nullptr && g_pXbox_Palette[i] == GetDataFromXboxResource(pThis)) {
|
||||
FreeHostResource(GetHostResourceKey(EmuD3DActiveTexture[i]));
|
||||
}
|
||||
}
|
||||
|
||||
RETURN(pData);
|
||||
}
|
||||
|
||||
// LTCG specific D3DDevice_SetFlickerFilter function...
|
||||
// This uses a custom calling convention where parameter is passed in ESI
|
||||
// Test-case: Metal Wolf Chaos
|
||||
|
|
|
@ -3867,3 +3867,57 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_GetLight)
|
|||
HRESULT hRet = g_pD3DDevice->GetLight(Index, pLight);
|
||||
DEBUG_D3DRESULT(hRet, "g_pD3DDevice->GetLight");
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
// * patch: IDirect3DPalette8_Lock
|
||||
// ******************************************************************
|
||||
VOID WINAPI XTL::EMUPATCH(D3DPalette_Lock)
|
||||
(
|
||||
X_D3DPalette *pThis,
|
||||
D3DCOLOR **ppColors,
|
||||
DWORD Flags
|
||||
)
|
||||
{
|
||||
LOG_FUNC_BEGIN
|
||||
LOG_FUNC_ARG(pThis)
|
||||
LOG_FUNC_ARG_OUT(ppColors)
|
||||
LOG_FUNC_ARG(Flags)
|
||||
LOG_FUNC_END;
|
||||
|
||||
XB_trampoline(VOID, WINAPI, D3DPalette_Lock, (X_D3DPalette*, D3DCOLOR**, DWORD));
|
||||
XB_D3DPalette_Lock(pThis, ppColors, Flags);
|
||||
|
||||
// Check if this palette is in use by a texture stage, and force it to be re-converted if yes
|
||||
for (int i = 0; i < XTL::X_D3DTS_STAGECOUNT; i++) {
|
||||
if (g_pXbox_Texture[i] != nullptr && g_pXbox_Palette[i] == GetDataFromXboxResource(pThis)) {
|
||||
FreeHostResource(GetHostResourceKey(g_pXbox_Texture[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
// * patch: IDirect3DPalette8_Lock2
|
||||
// ******************************************************************
|
||||
D3DCOLOR * WINAPI XTL::EMUPATCH(D3DPalette_Lock2)
|
||||
(
|
||||
X_D3DPalette *pThis,
|
||||
DWORD Flags
|
||||
)
|
||||
{
|
||||
LOG_FUNC_BEGIN
|
||||
LOG_FUNC_ARG(pThis)
|
||||
LOG_FUNC_ARG(Flags)
|
||||
LOG_FUNC_END;
|
||||
|
||||
XB_trampoline(D3DCOLOR*, WINAPI, D3DPalette_Lock2, (X_D3DPalette*, DWORD));
|
||||
D3DCOLOR* pData = XB_D3DPalette_Lock2(pThis, Flags);
|
||||
|
||||
// Check if this palette is in use by a texture stage, and force it to be re-converted if yes
|
||||
for (int i = 0; i < XTL::X_D3DTS_STAGECOUNT; i++) {
|
||||
if (g_pXbox_Texture[i] != nullptr && g_pXbox_Palette[i] == GetDataFromXboxResource(pThis)) {
|
||||
FreeHostResource(GetHostResourceKey(g_pXbox_Texture[i]));
|
||||
}
|
||||
}
|
||||
|
||||
RETURN(pData);
|
||||
}
|
||||
|
|
|
@ -175,8 +175,6 @@ std::map<const std::string, const xbox_patch_t> g_PatchTable = {
|
|||
PATCH_ENTRY("D3DDevice_Swap_0", XTL::EMUPATCH(D3DDevice_Swap_0), PATCH_HLE_D3D),
|
||||
PATCH_ENTRY("D3DDevice_SwitchTexture", XTL::EMUPATCH(D3DDevice_SwitchTexture), PATCH_HLE_D3D),
|
||||
PATCH_ENTRY("D3DDevice_UpdateOverlay", XTL::EMUPATCH(D3DDevice_UpdateOverlay), PATCH_HLE_D3D),
|
||||
PATCH_ENTRY("D3DPalette_Lock", XTL::EMUPATCH(D3DPalette_Lock), PATCH_HLE_D3D),
|
||||
PATCH_ENTRY("D3DPalette_Lock2", XTL::EMUPATCH(D3DPalette_Lock2), PATCH_HLE_D3D),
|
||||
PATCH_ENTRY("D3DResource_BlockUntilNotBusy", XTL::EMUPATCH(D3DResource_BlockUntilNotBusy), PATCH_HLE_D3D),
|
||||
PATCH_ENTRY("D3D_BlockOnTime", XTL::EMUPATCH(D3D_BlockOnTime), PATCH_HLE_D3D),
|
||||
PATCH_ENTRY("D3D_DestroyResource", XTL::EMUPATCH(D3D_DestroyResource), PATCH_HLE_D3D),
|
||||
|
|
Loading…
Reference in New Issue