Implement Hashing of Textures and Surfaces to detect changes

Not the best way of doing things, but it will dof or now.
This commit is contained in:
Luke Usher 2018-01-31 11:19:54 +00:00
parent 79a5ae3d8b
commit c9f331837b
1 changed files with 106 additions and 68 deletions

View File

@ -690,9 +690,62 @@ inline bool IsXboxResourceD3DCreated(const XTL::X_D3DResource *pXboxResource)
return result; return result;
} }
// Map native resource data pointers to the host resource void *GetDataFromXboxResource(XTL::X_D3DResource *pXboxResource)
// TODO: Move all these HostResource functions into a ResourceManager class {
std::map <resource_key_t, XTL::IDirect3DResource8*> g_HostResources; // Don't pass in unassigned Xbox resources
if (pXboxResource == NULL)
return nullptr;
xbaddr pData = pXboxResource->Data;
if (pData == NULL)
return nullptr;
if (IsSpecialXboxResource(pXboxResource))
{
switch (pData) {
case X_D3DRESOURCE_DATA_BACK_BUFFER:
return nullptr;
case X_D3DRESOURCE_DATA_RENDER_TARGET:
return nullptr;
case X_D3DRESOURCE_DATA_DEPTH_STENCIL:
return nullptr;
case X_D3DRESOURCE_DATA_SURFACE_LEVEL:
return nullptr;
default:
CxbxKrnlCleanup("Unhandled special resource type");
}
}
DWORD Type = GetXboxCommonResourceType(pXboxResource);
switch (Type) {
case X_D3DCOMMON_TYPE_VERTEXBUFFER:
case X_D3DCOMMON_TYPE_INDEXBUFFER:
case X_D3DCOMMON_TYPE_PALETTE:
case X_D3DCOMMON_TYPE_TEXTURE:
case X_D3DCOMMON_TYPE_SURFACE:
pData |= MM_SYSTEM_PHYSICAL_MAP;
pData |= MM_SYSTEM_PHYSICAL_MAP;
break;
case X_D3DCOMMON_TYPE_PUSHBUFFER:
break;
case X_D3DCOMMON_TYPE_FIXUP:
break;
default:
CxbxKrnlCleanup("Unhandled resource type");
}
return (uint08*)pData;
}
typedef struct {
XTL::IDirect3DResource8* pHostResource = nullptr;
XTL::X_D3DResource* pXboxResource = nullptr;
void* pXboxData = nullptr;
size_t szXboxDataSize = 0;
uint32_t hash = 0;
} host_resource_info_t;
std::map <resource_key_t, host_resource_info_t> g_HostResources;
resource_key_t GetHostResourceKey(XTL::X_D3DResource* pXboxResource) resource_key_t GetHostResourceKey(XTL::X_D3DResource* pXboxResource)
{ {
@ -711,8 +764,8 @@ void FreeHostResource(resource_key_t key)
// Release the host resource and remove it from the list // Release the host resource and remove it from the list
auto hostResourceIterator = g_HostResources.find(key); auto hostResourceIterator = g_HostResources.find(key);
if (hostResourceIterator != g_HostResources.end()) { if (hostResourceIterator != g_HostResources.end()) {
if (hostResourceIterator->second) { if (hostResourceIterator->second.pHostResource) {
(hostResourceIterator->second)->Release(); (hostResourceIterator->second.pHostResource)->Release();
} }
g_HostResources.erase(hostResourceIterator); g_HostResources.erase(hostResourceIterator);
} }
@ -743,7 +796,37 @@ XTL::IDirect3DResource8 *GetHostResource(XTL::X_D3DResource *pXboxResource, bool
return nullptr; return nullptr;
} }
return it->second; return it->second.pHostResource;
}
size_t GetXboxResourceSize(XTL::X_D3DResource* pXboxResource)
{
// TODO: Smart size calculation based around format of resource
return xboxkrnl::MmQueryAllocationSize(GetDataFromXboxResource(pXboxResource));
}
bool HostResourceRequiresUpdate(resource_key_t key)
{
auto it = g_HostResources.find(key);
if (it == g_HostResources.end()) {
return false;
}
// Currently, we only dynamically update Textures and Surfaces, so if our resource
// isn't of these types, do nothing
DWORD type = GetXboxCommonResourceType(it->second.pXboxResource);
if (type != X_D3DCOMMON_TYPE_SURFACE && type != X_D3DCOMMON_TYPE_TEXTURE) {
return false;
}
uint32_t oldHash = it->second.hash;
it->second.hash = XXHash32::hash(it->second.pXboxData, it->second.szXboxDataSize, 0);
if (it->second.hash != oldHash) {
return true;
}
return false;
} }
void SetHostResource(XTL::X_D3DResource* pXboxResource, XTL::IDirect3DResource8* pHostResource) void SetHostResource(XTL::X_D3DResource* pXboxResource, XTL::IDirect3DResource8* pHostResource)
@ -754,7 +837,14 @@ void SetHostResource(XTL::X_D3DResource* pXboxResource, XTL::IDirect3DResource8*
EmuWarning("SetHostResource: Overwriting an existing host resource"); EmuWarning("SetHostResource: Overwriting an existing host resource");
} }
g_HostResources[key] = pHostResource; host_resource_info_t hostResourceInfo;
hostResourceInfo.pHostResource = pHostResource;
hostResourceInfo.pXboxResource = pXboxResource;
hostResourceInfo.pXboxData = GetDataFromXboxResource(pXboxResource);
hostResourceInfo.szXboxDataSize = GetXboxResourceSize(pXboxResource);
hostResourceInfo.hash = XXHash32::hash(hostResourceInfo.pXboxData, hostResourceInfo.szXboxDataSize, 0);
g_HostResources[key] = hostResourceInfo;
} }
@ -869,53 +959,6 @@ void SetHostVertexBuffer(XTL::X_D3DResource *pXboxResource, XTL::IDirect3DVertex
SetHostResource(pXboxResource, (XTL::IDirect3DResource8*)pHostVertexBuffer); SetHostResource(pXboxResource, (XTL::IDirect3DResource8*)pHostVertexBuffer);
} }
void *GetDataFromXboxResource(XTL::X_D3DResource *pXboxResource)
{
// Don't pass in unassigned Xbox resources
if(pXboxResource == NULL)
return nullptr;
xbaddr pData = pXboxResource->Data;
if (pData == NULL)
return nullptr;
if (IsSpecialXboxResource(pXboxResource))
{
switch (pData) {
case X_D3DRESOURCE_DATA_BACK_BUFFER:
return nullptr;
case X_D3DRESOURCE_DATA_RENDER_TARGET:
return nullptr;
case X_D3DRESOURCE_DATA_DEPTH_STENCIL:
return nullptr;
case X_D3DRESOURCE_DATA_SURFACE_LEVEL:
return nullptr;
default:
CxbxKrnlCleanup("Unhandled special resource type");
}
}
DWORD Type = GetXboxCommonResourceType(pXboxResource);
switch (Type) {
case X_D3DCOMMON_TYPE_VERTEXBUFFER:
case X_D3DCOMMON_TYPE_INDEXBUFFER:
case X_D3DCOMMON_TYPE_PALETTE:
case X_D3DCOMMON_TYPE_TEXTURE:
case X_D3DCOMMON_TYPE_SURFACE:
pData |= MM_SYSTEM_PHYSICAL_MAP;
pData |= MM_SYSTEM_PHYSICAL_MAP;
break;
case X_D3DCOMMON_TYPE_PUSHBUFFER:
break;
case X_D3DCOMMON_TYPE_FIXUP:
break;
default:
CxbxKrnlCleanup("Unhandled resource type");
}
return (uint08*)pData;
}
int XboxD3DPaletteSizeToBytes(const XTL::X_D3DPALETTESIZE Size) int XboxD3DPaletteSizeToBytes(const XTL::X_D3DPALETTESIZE Size)
{ {
static int lk[4] = static int lk[4] =
@ -1968,25 +2011,16 @@ static DWORD WINAPI EmuCreateDeviceProxy(LPVOID)
} }
// update render target cache // update render target cache
g_pCachedRenderTarget = EmuNewD3DSurface();
XTL::IDirect3DSurface8 *pNewHostSurface = nullptr; XTL::IDirect3DSurface8 *pNewHostSurface = nullptr;
g_pCachedRenderTarget->Data = X_D3DRESOURCE_DATA_RENDER_TARGET;
hRet = g_pD3DDevice8->GetRenderTarget(&pNewHostSurface); hRet = g_pD3DDevice8->GetRenderTarget(&pNewHostSurface);
DEBUG_D3DRESULT(hRet, "g_pD3DDevice8->GetRenderTarget"); DEBUG_D3DRESULT(hRet, "g_pD3DDevice8->GetRenderTarget");
SetHostSurface(g_pCachedRenderTarget, pNewHostSurface); // update z-stencil surface cache
// update z-stencil surface cache
g_pCachedDepthStencil = EmuNewD3DSurface();
pNewHostSurface = nullptr; pNewHostSurface = nullptr;
g_pCachedDepthStencil->Data = X_D3DRESOURCE_DATA_DEPTH_STENCIL;
hRet = g_pD3DDevice8->GetDepthStencilSurface(&pNewHostSurface); hRet = g_pD3DDevice8->GetDepthStencilSurface(&pNewHostSurface);
DEBUG_D3DRESULT(hRet, "g_pD3DDevice8->GetDepthStencilSurface"); DEBUG_D3DRESULT(hRet, "g_pD3DDevice8->GetDepthStencilSurface");
g_bHasDepthStencil = SUCCEEDED(hRet); g_bHasDepthStencil = SUCCEEDED(hRet);
if (g_bHasDepthStencil)
SetHostSurface(g_pCachedDepthStencil, pNewHostSurface);
hRet = g_pD3DDevice8->CreateVertexBuffer hRet = g_pD3DDevice8->CreateVertexBuffer
( (
@ -2091,7 +2125,11 @@ static void EmuVerifyResourceIsRegistered(XTL::X_D3DResource *pResource)
auto key = GetHostResourceKey(pResource); auto key = GetHostResourceKey(pResource);
if (std::find(g_RegisteredResources.begin(), g_RegisteredResources.end(), key) != g_RegisteredResources.end()) { if (std::find(g_RegisteredResources.begin(), g_RegisteredResources.end(), key) != g_RegisteredResources.end()) {
return; if (!HostResourceRequiresUpdate(key)) {
return;
}
FreeHostResource(key);
} }
XTL::EMUPATCH(D3DResource_Register)(pResource, /* Base = */NULL); XTL::EMUPATCH(D3DResource_Register)(pResource, /* Base = */NULL);
@ -3374,9 +3412,9 @@ HRESULT WINAPI XTL::EMUPATCH(D3DDevice_CreateVertexShader)
{ {
static const char dummy[] = static const char dummy[] =
"vs.1.1\n" "vs.1.1\n"
"dp4 oPos.x, v0, c96\n" "dp4 oPos.x, v0, c96\n"
"dp4 oPos.y, v0, c97\n" "dp4 oPos.y, v0, c97\n"
"dp4 oPos.z, v0, c98\n" "dp4 oPos.z, v0, c98\n"
"dp4 oPos.w, v0, c99\n"; "dp4 oPos.w, v0, c99\n";
EmuWarning("Trying fallback:\n%s", dummy); EmuWarning("Trying fallback:\n%s", dummy);