Split up resource cache in two, one for paletized textures (which gets pruned when it overflows),
one for all other resources (which cache doesn't prune, like it did not do before, too). This way, only paletized textures get pruned from their specialized cache, while other resources, including render-targets (which can't be paletized) will stay resident in the general cache (which won't overflow). Doing it this way, probably fixes the reported black texture regressions, but it might also lead to less of a performance increase than before.
This commit is contained in:
parent
b03551535c
commit
de1b815542
|
@ -217,7 +217,7 @@ typedef struct resource_key_hash {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// These operator overloads are required to use resource_key_t in std::unordered_map<> g_Xbox_Direct3DResources :
|
// These operator overloads are required to use resource_key_t in resource_cache_t :
|
||||||
bool operator==(const struct resource_key_hash& other) const
|
bool operator==(const struct resource_key_hash& other) const
|
||||||
{
|
{
|
||||||
return (Common == other.Common)
|
return (Common == other.Common)
|
||||||
|
@ -623,21 +623,32 @@ void DrawUEM(HWND hWnd)
|
||||||
EndPaint(hWnd, &ps);
|
EndPaint(hWnd, &ps);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DWORD GetXboxCommonResourceType(const XTL::X_D3DResource *pXboxResource)
|
inline DWORD GetXboxCommonResourceType(const XTL::DWORD XboxResource_Common)
|
||||||
|
{
|
||||||
|
DWORD dwCommonType = XboxResource_Common & X_D3DCOMMON_TYPE_MASK;
|
||||||
|
return dwCommonType;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline DWORD GetXboxCommonResourceType(const XTL::X_D3DResource* pXboxResource)
|
||||||
{
|
{
|
||||||
// Don't pass in unassigned Xbox resources
|
// Don't pass in unassigned Xbox resources
|
||||||
assert(pXboxResource != xbnullptr);
|
assert(pXboxResource != xbnullptr);
|
||||||
|
|
||||||
DWORD dwCommonType = pXboxResource->Common & X_D3DCOMMON_TYPE_MASK;
|
return GetXboxCommonResourceType(pXboxResource->Common);
|
||||||
return dwCommonType;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
XTL::X_D3DFORMAT GetXboxPixelContainerFormat(const XTL::X_D3DPixelContainer *pXboxPixelContainer)
|
XTL::X_D3DFORMAT GetXboxPixelContainerFormat(const XTL::DWORD XboxPixelContainer_Format)
|
||||||
|
{
|
||||||
|
XTL::X_D3DFORMAT d3d_format = (XTL::X_D3DFORMAT)((XboxPixelContainer_Format & X_D3DFORMAT_FORMAT_MASK) >> X_D3DFORMAT_FORMAT_SHIFT);
|
||||||
|
return d3d_format;
|
||||||
|
}
|
||||||
|
|
||||||
|
XTL::X_D3DFORMAT GetXboxPixelContainerFormat(const XTL::X_D3DPixelContainer* pXboxPixelContainer)
|
||||||
{
|
{
|
||||||
// Don't pass in unassigned Xbox pixel container
|
// Don't pass in unassigned Xbox pixel container
|
||||||
assert(pXboxPixelContainer != xbnullptr);
|
assert(pXboxPixelContainer != xbnullptr);
|
||||||
|
|
||||||
return (XTL::X_D3DFORMAT)((pXboxPixelContainer->Format & X_D3DFORMAT_FORMAT_MASK) >> X_D3DFORMAT_FORMAT_SHIFT);
|
return GetXboxPixelContainerFormat(pXboxPixelContainer->Format);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int GetXboxPixelContainerDimensionCount(const XTL::X_D3DPixelContainer *pXboxPixelContainer)
|
inline int GetXboxPixelContainerDimensionCount(const XTL::X_D3DPixelContainer *pXboxPixelContainer)
|
||||||
|
@ -714,25 +725,36 @@ inline bool IsResourceTypeGPUReadable(const DWORD ResourceType)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool IsYuvSurfaceOrTexture(const XTL::X_D3DResource *pXboxResource)
|
inline bool IsPaletizedTexture(const XTL::DWORD XboxPixelContainer_Format)
|
||||||
{
|
{
|
||||||
if (GetXboxPixelContainerFormat((XTL::X_D3DPixelContainer *)pXboxResource) == XTL::X_D3DFMT_YUY2)
|
return GetXboxPixelContainerFormat(XboxPixelContainer_Format) == XTL::X_D3DFMT_P8;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0 // unused
|
||||||
|
inline bool IsYuvSurfaceOrTexture(const XTL::X_D3DResource* pXboxResource)
|
||||||
|
{
|
||||||
|
if (GetXboxPixelContainerFormat((XTL::X_D3DPixelContainer*)pXboxResource) == XTL::X_D3DFMT_YUY2)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0 // unused
|
||||||
inline bool IsXboxResourceLocked(const XTL::X_D3DResource *pXboxResource)
|
inline bool IsXboxResourceLocked(const XTL::X_D3DResource *pXboxResource)
|
||||||
{
|
{
|
||||||
bool result = !!(pXboxResource->Common & X_D3DCOMMON_ISLOCKED);
|
bool result = !!(pXboxResource->Common & X_D3DCOMMON_ISLOCKED);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0 // unused
|
||||||
inline bool IsXboxResourceD3DCreated(const XTL::X_D3DResource *pXboxResource)
|
inline bool IsXboxResourceD3DCreated(const XTL::X_D3DResource *pXboxResource)
|
||||||
{
|
{
|
||||||
bool result = !!(pXboxResource->Common & X_D3DCOMMON_D3DCREATED);
|
bool result = !!(pXboxResource->Common & X_D3DCOMMON_D3DCREATED);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void *GetDataFromXboxResource(XTL::X_D3DResource *pXboxResource)
|
void *GetDataFromXboxResource(XTL::X_D3DResource *pXboxResource)
|
||||||
{
|
{
|
||||||
|
@ -764,12 +786,13 @@ typedef struct {
|
||||||
std::chrono::time_point<std::chrono::high_resolution_clock> lastUpdate;
|
std::chrono::time_point<std::chrono::high_resolution_clock> lastUpdate;
|
||||||
} resource_info_t;
|
} resource_info_t;
|
||||||
|
|
||||||
std::unordered_map<resource_key_t, resource_info_t, resource_key_hash> g_Xbox_Direct3DResources;
|
typedef std::unordered_map<resource_key_t, resource_info_t, resource_key_hash> resource_cache_t;
|
||||||
|
resource_cache_t g_Cxbx_Cached_Direct3DResources;
|
||||||
|
resource_cache_t g_Cxbx_Cached_PaletizedTextures;
|
||||||
|
|
||||||
bool IsResourceAPixelContainer(XTL::X_D3DResource* pXboxResource)
|
bool IsResourceAPixelContainer(XTL::DWORD XboxResource_Common)
|
||||||
{
|
{
|
||||||
// assert(pXboxResource);
|
DWORD Type = GetXboxCommonResourceType(XboxResource_Common);
|
||||||
DWORD Type = GetXboxCommonResourceType(pXboxResource);
|
|
||||||
switch (Type)
|
switch (Type)
|
||||||
{
|
{
|
||||||
case X_D3DCOMMON_TYPE_TEXTURE:
|
case X_D3DCOMMON_TYPE_TEXTURE:
|
||||||
|
@ -780,7 +803,21 @@ bool IsResourceAPixelContainer(XTL::X_D3DResource* pXboxResource)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
resource_key_t GetHostResourceKey(XTL::X_D3DResource* pXboxResource, int iTextureStage = 0)
|
bool IsResourceAPixelContainer(XTL::X_D3DResource* pXboxResource)
|
||||||
|
{
|
||||||
|
// Don't pass in unassigned Xbox resources
|
||||||
|
assert(pXboxResource != xbnullptr);
|
||||||
|
|
||||||
|
return IsResourceAPixelContainer(pXboxResource->Common);
|
||||||
|
}
|
||||||
|
|
||||||
|
resource_cache_t& GetResourceCache(resource_key_t& key)
|
||||||
|
{
|
||||||
|
return IsResourceAPixelContainer(key.Common) && IsPaletizedTexture(key.Format)
|
||||||
|
? g_Cxbx_Cached_PaletizedTextures : g_Cxbx_Cached_Direct3DResources;
|
||||||
|
}
|
||||||
|
|
||||||
|
resource_key_t GetHostResourceKey(XTL::X_D3DResource* pXboxResource, int iTextureStage = -1)
|
||||||
{
|
{
|
||||||
resource_key_t key = {};
|
resource_key_t key = {};
|
||||||
if (pXboxResource != xbnullptr) {
|
if (pXboxResource != xbnullptr) {
|
||||||
|
@ -792,18 +829,23 @@ resource_key_t GetHostResourceKey(XTL::X_D3DResource* pXboxResource, int iTextur
|
||||||
auto pPixelContainer = (XTL::X_D3DPixelContainer*)pXboxResource;
|
auto pPixelContainer = (XTL::X_D3DPixelContainer*)pXboxResource;
|
||||||
key.Format = pPixelContainer->Format;
|
key.Format = pPixelContainer->Format;
|
||||||
key.Size = pPixelContainer->Size;
|
key.Size = pPixelContainer->Size;
|
||||||
// Protect for when this gets hit before an actual palette is set
|
// For paletized textures, include the current palette hash as well
|
||||||
if (g_Xbox_Palette_Size[iTextureStage] >= /*256 >> XTL::X_D3DPALETTESIZE.D3DPALETTE_32=*/32) {
|
if (IsPaletizedTexture(pPixelContainer->Format)) {
|
||||||
// For paletized textures, include the current palette hash as well
|
if (iTextureStage < 0) {
|
||||||
if (GetXboxPixelContainerFormat(pPixelContainer) == XTL::X_D3DFMT_P8) {
|
// ForceResourceRehash (called by Lock[23]DSurface) could hit this (not knowing the texture-stage)
|
||||||
// This caters for palette changes (only the active one will be used,
|
LOG_TEST_CASE("Unknown texture stage!");
|
||||||
// any intermediate changes have no effect). Obsolete palette texture
|
} else {
|
||||||
// conversions will be pruned together with g_Xbox_Direct3DResources
|
assert(iTextureStage < XTL::X_D3DTS_STAGECOUNT);
|
||||||
key.PaletteHash = ComputeHash(g_pXbox_Palette_Data[iTextureStage], g_Xbox_Palette_Size[iTextureStage]);
|
// Protect for when this gets hit before an actual palette is set
|
||||||
|
if (g_Xbox_Palette_Size[iTextureStage] > 0) {
|
||||||
|
// 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 from g_Cxbx_Cached_PaletizedTextures
|
||||||
|
key.PaletteHash = ComputeHash(g_pXbox_Palette_Data[iTextureStage], g_Xbox_Palette_Size[iTextureStage]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// For other resource types, do include their Xbox resource address (TODO : come up with something better)
|
// For other resource types, do include their Xbox resource address (TODO : come up with something better)
|
||||||
key.ResourceAddr = (xbaddr)pXboxResource;
|
key.ResourceAddr = (xbaddr)pXboxResource;
|
||||||
}
|
}
|
||||||
|
@ -815,41 +857,43 @@ resource_key_t GetHostResourceKey(XTL::X_D3DResource* pXboxResource, int iTextur
|
||||||
void FreeHostResource(resource_key_t key)
|
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_Xbox_Direct3DResources.find(key);
|
auto& ResourceCache = GetResourceCache(key);
|
||||||
if (hostResourceIterator != g_Xbox_Direct3DResources.end()) {
|
auto hostResourceIterator = ResourceCache.find(key);
|
||||||
|
if (hostResourceIterator != ResourceCache.end()) {
|
||||||
if (hostResourceIterator->second.pHostResource) {
|
if (hostResourceIterator->second.pHostResource) {
|
||||||
(hostResourceIterator->second.pHostResource)->Release();
|
(hostResourceIterator->second.pHostResource)->Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
g_Xbox_Direct3DResources.erase(hostResourceIterator);
|
ResourceCache.erase(hostResourceIterator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClearResourceCache()
|
void ClearResourceCache(resource_cache_t& ResourceCache)
|
||||||
{
|
{
|
||||||
for (auto& hostResourceIterator : g_Xbox_Direct3DResources) {
|
for (auto& hostResourceIterator : ResourceCache) {
|
||||||
if (hostResourceIterator.second.pHostResource) {
|
if (hostResourceIterator.second.pHostResource) {
|
||||||
(hostResourceIterator.second.pHostResource)->Release();
|
(hostResourceIterator.second.pHostResource)->Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g_Xbox_Direct3DResources.clear();
|
ResourceCache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PruneResourceCache()
|
void PrunePaletizedTexturesCache()
|
||||||
{
|
{
|
||||||
// TODO : Implement a better cache eviction algorithm (like least-recently used)
|
// TODO : Implement a better cache eviction algorithm (like least-recently used, or just at-random)
|
||||||
// Poor mans cache eviction policy: just clear it once it overflows (5000 entries should be good enough)
|
// Poor mans cache eviction policy: just clear it once it overflows
|
||||||
if (g_Xbox_Direct3DResources.size() >= 5000) {
|
if (g_Cxbx_Cached_PaletizedTextures.size() >= 1500) {
|
||||||
ClearResourceCache();
|
ClearResourceCache(g_Cxbx_Cached_PaletizedTextures);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ForceResourceRehash(XTL::X_D3DResource* pXboxResource)
|
void ForceResourceRehash(XTL::X_D3DResource* pXboxResource)
|
||||||
{
|
{
|
||||||
auto key = GetHostResourceKey(pXboxResource);
|
auto key = GetHostResourceKey(pXboxResource); // Note : iTextureStage is unknown here!
|
||||||
auto it = g_Xbox_Direct3DResources.find(key);
|
auto& ResourceCache = GetResourceCache(key);
|
||||||
if (it != g_Xbox_Direct3DResources.end() && it->second.pHostResource) {
|
auto it = ResourceCache.find(key);
|
||||||
|
if (it != ResourceCache.end() && it->second.pHostResource) {
|
||||||
it->second.forceRehash = true;
|
it->second.forceRehash = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -862,8 +906,9 @@ IDirect3DResource *GetHostResource(XTL::X_D3DResource *pXboxResource, DWORD D3DU
|
||||||
EmuVerifyResourceIsRegistered(pXboxResource, D3DUsage, iTextureStage, /*dwSize=*/0);
|
EmuVerifyResourceIsRegistered(pXboxResource, D3DUsage, iTextureStage, /*dwSize=*/0);
|
||||||
|
|
||||||
auto key = GetHostResourceKey(pXboxResource, iTextureStage);
|
auto key = GetHostResourceKey(pXboxResource, iTextureStage);
|
||||||
auto it = g_Xbox_Direct3DResources.find(key);
|
auto& ResourceCache = GetResourceCache(key);
|
||||||
if (it == g_Xbox_Direct3DResources.end() || !it->second.pHostResource) {
|
auto it = ResourceCache.find(key);
|
||||||
|
if (it == ResourceCache.end() || !it->second.pHostResource) {
|
||||||
EmuLog(LOG_LEVEL::WARNING, "GetHostResource: Resource not registered or does not have a host counterpart!");
|
EmuLog(LOG_LEVEL::WARNING, "GetHostResource: Resource not registered or does not have a host counterpart!");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -910,8 +955,9 @@ size_t GetXboxResourceSize(XTL::X_D3DResource* pXboxResource)
|
||||||
|
|
||||||
bool HostResourceRequiresUpdate(resource_key_t key, DWORD dwSize)
|
bool HostResourceRequiresUpdate(resource_key_t key, DWORD dwSize)
|
||||||
{
|
{
|
||||||
auto it = g_Xbox_Direct3DResources.find(key);
|
auto& ResourceCache = GetResourceCache(key);
|
||||||
if (it == g_Xbox_Direct3DResources.end() || !it->second.pXboxResource) {
|
auto it = ResourceCache.find(key);
|
||||||
|
if (it == ResourceCache.end() || !it->second.pXboxResource) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -961,10 +1007,11 @@ bool HostResourceRequiresUpdate(resource_key_t key, DWORD dwSize)
|
||||||
return modified;
|
return modified;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetHostResource(XTL::X_D3DResource* pXboxResource, IDirect3DResource* pHostResource, DWORD dwSize = 0)
|
void SetHostResource(XTL::X_D3DResource* pXboxResource, IDirect3DResource* pHostResource, int iTextureStage = -1, DWORD dwSize = 0)
|
||||||
{
|
{
|
||||||
auto key = GetHostResourceKey(pXboxResource);
|
auto key = GetHostResourceKey(pXboxResource, iTextureStage);
|
||||||
auto& resourceInfo = g_Xbox_Direct3DResources[key]; // Implicitely inserts a new entry if not already existing
|
auto& ResourceCache = GetResourceCache(key);
|
||||||
|
auto& resourceInfo = ResourceCache[key]; // Implicitely inserts a new entry if not already existing
|
||||||
|
|
||||||
if (resourceInfo.pHostResource) {
|
if (resourceInfo.pHostResource) {
|
||||||
EmuLog(LOG_LEVEL::WARNING, "SetHostResource: Overwriting an existing host resource");
|
EmuLog(LOG_LEVEL::WARNING, "SetHostResource: Overwriting an existing host resource");
|
||||||
|
@ -1004,7 +1051,7 @@ IDirect3DBaseTexture *GetHostBaseTexture(XTL::X_D3DResource *pXboxResource, DWOR
|
||||||
return (IDirect3DBaseTexture*)GetHostResource(pXboxResource, D3DUsage, iTextureStage);
|
return (IDirect3DBaseTexture*)GetHostResource(pXboxResource, D3DUsage, iTextureStage);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0 // unused
|
||||||
IDirect3DTexture *GetHostTexture(XTL::X_D3DResource *pXboxResource, int iTextureStage = 0)
|
IDirect3DTexture *GetHostTexture(XTL::X_D3DResource *pXboxResource, int iTextureStage = 0)
|
||||||
{
|
{
|
||||||
if (pXboxResource == xbnullptr)
|
if (pXboxResource == xbnullptr)
|
||||||
|
@ -1023,7 +1070,7 @@ IDirect3DVolumeTexture *GetHostVolumeTexture(XTL::X_D3DResource *pXboxResource,
|
||||||
// TODO : Check for 1 face (and 2 dimensions)?
|
// TODO : Check for 1 face (and 2 dimensions)?
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0 // unused
|
||||||
IDirect3DIndexBuffer *GetHostIndexBuffer(XTL::X_D3DResource *pXboxResource)
|
IDirect3DIndexBuffer *GetHostIndexBuffer(XTL::X_D3DResource *pXboxResource)
|
||||||
{
|
{
|
||||||
if (pXboxResource == xbnullptr)
|
if (pXboxResource == xbnullptr)
|
||||||
|
@ -1035,44 +1082,44 @@ IDirect3DIndexBuffer *GetHostIndexBuffer(XTL::X_D3DResource *pXboxResource)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void SetHostSurface(XTL::X_D3DResource *pXboxResource, IDirect3DSurface *pHostSurface)
|
void SetHostSurface(XTL::X_D3DResource *pXboxResource, IDirect3DSurface *pHostSurface, int iTextureStage)
|
||||||
{
|
{
|
||||||
assert(pXboxResource != xbnullptr);
|
assert(pXboxResource != xbnullptr);
|
||||||
assert(GetXboxCommonResourceType(pXboxResource) == X_D3DCOMMON_TYPE_SURFACE);
|
assert(GetXboxCommonResourceType(pXboxResource) == X_D3DCOMMON_TYPE_SURFACE);
|
||||||
|
|
||||||
SetHostResource(pXboxResource, (IDirect3DResource*)pHostSurface);
|
SetHostResource(pXboxResource, (IDirect3DResource*)pHostSurface, iTextureStage);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetHostTexture(XTL::X_D3DResource *pXboxResource, IDirect3DTexture *pHostTexture)
|
void SetHostTexture(XTL::X_D3DResource *pXboxResource, IDirect3DTexture *pHostTexture, int iTextureStage)
|
||||||
{
|
{
|
||||||
assert(pXboxResource != xbnullptr);
|
assert(pXboxResource != xbnullptr);
|
||||||
assert(GetXboxCommonResourceType(pXboxResource) == X_D3DCOMMON_TYPE_TEXTURE);
|
assert(GetXboxCommonResourceType(pXboxResource) == X_D3DCOMMON_TYPE_TEXTURE);
|
||||||
|
|
||||||
SetHostResource(pXboxResource, (IDirect3DResource*)pHostTexture);
|
SetHostResource(pXboxResource, (IDirect3DResource*)pHostTexture, iTextureStage);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetHostCubeTexture(XTL::X_D3DResource *pXboxResource, IDirect3DCubeTexture *pHostCubeTexture)
|
void SetHostCubeTexture(XTL::X_D3DResource *pXboxResource, IDirect3DCubeTexture *pHostCubeTexture, int iTextureStage)
|
||||||
{
|
{
|
||||||
assert(pXboxResource != xbnullptr);
|
assert(pXboxResource != xbnullptr);
|
||||||
assert(GetXboxCommonResourceType(pXboxResource) == X_D3DCOMMON_TYPE_TEXTURE);
|
assert(GetXboxCommonResourceType(pXboxResource) == X_D3DCOMMON_TYPE_TEXTURE);
|
||||||
|
|
||||||
SetHostResource(pXboxResource, (IDirect3DResource*)pHostCubeTexture);
|
SetHostResource(pXboxResource, (IDirect3DResource*)pHostCubeTexture, iTextureStage);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetHostVolumeTexture(XTL::X_D3DResource *pXboxResource, IDirect3DVolumeTexture *pHostVolumeTexture)
|
void SetHostVolumeTexture(XTL::X_D3DResource *pXboxResource, IDirect3DVolumeTexture *pHostVolumeTexture, int iTextureStage)
|
||||||
{
|
{
|
||||||
assert(pXboxResource != xbnullptr);
|
assert(pXboxResource != xbnullptr);
|
||||||
assert(GetXboxCommonResourceType(pXboxResource) == X_D3DCOMMON_TYPE_TEXTURE);
|
assert(GetXboxCommonResourceType(pXboxResource) == X_D3DCOMMON_TYPE_TEXTURE);
|
||||||
|
|
||||||
SetHostResource(pXboxResource, (IDirect3DResource*)pHostVolumeTexture);
|
SetHostResource(pXboxResource, (IDirect3DResource*)pHostVolumeTexture, iTextureStage);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetHostVolume(XTL::X_D3DResource *pXboxResource, IDirect3DVolume *pHostVolume)
|
void SetHostVolume(XTL::X_D3DResource *pXboxResource, IDirect3DVolume *pHostVolume, int iTextureStage)
|
||||||
{
|
{
|
||||||
assert(pXboxResource != xbnullptr);
|
assert(pXboxResource != xbnullptr);
|
||||||
assert(GetXboxCommonResourceType(pXboxResource) == X_D3DCOMMON_TYPE_TEXTURE);
|
assert(GetXboxCommonResourceType(pXboxResource) == X_D3DCOMMON_TYPE_TEXTURE);
|
||||||
|
|
||||||
SetHostResource(pXboxResource, (IDirect3DResource*)pHostVolume);
|
SetHostResource(pXboxResource, (IDirect3DResource*)pHostVolume, iTextureStage);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetHostIndexBuffer(XTL::X_D3DResource *pXboxResource, IDirect3DIndexBuffer *pHostIndexBuffer)
|
void SetHostIndexBuffer(XTL::X_D3DResource *pXboxResource, IDirect3DIndexBuffer *pHostIndexBuffer)
|
||||||
|
@ -1096,7 +1143,7 @@ int XboxD3DPaletteSizeToBytes(const XTL::X_D3DPALETTESIZE Size)
|
||||||
|
|
||||||
return lk[Size];
|
return lk[Size];
|
||||||
*/
|
*/
|
||||||
return 256 >> (unsigned)Size;
|
return (256 * sizeof(D3DCOLOR)) >> (unsigned)Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline XTL::X_D3DPALETTESIZE GetXboxPaletteSize(const XTL::X_D3DPalette *pPalette)
|
inline XTL::X_D3DPALETTESIZE GetXboxPaletteSize(const XTL::X_D3DPalette *pPalette)
|
||||||
|
@ -2021,7 +2068,8 @@ static DWORD WINAPI EmuCreateDeviceProxy(LPVOID)
|
||||||
|
|
||||||
g_pD3DDevice->EndScene();
|
g_pD3DDevice->EndScene();
|
||||||
|
|
||||||
ClearResourceCache();
|
ClearResourceCache(g_Cxbx_Cached_PaletizedTextures);
|
||||||
|
ClearResourceCache(g_Cxbx_Cached_Direct3DResources);
|
||||||
|
|
||||||
// TODO: ensure all other resources are cleaned up too
|
// TODO: ensure all other resources are cleaned up too
|
||||||
|
|
||||||
|
@ -2445,9 +2493,10 @@ static void EmuVerifyResourceIsRegistered(XTL::X_D3DResource *pResource, DWORD D
|
||||||
if (pResource->Data == xbnull)
|
if (pResource->Data == xbnull)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto key = GetHostResourceKey(pResource);
|
auto key = GetHostResourceKey(pResource, iTextureStage);
|
||||||
auto it = g_Xbox_Direct3DResources.find(key);
|
auto& ResourceCache = GetResourceCache(key);
|
||||||
if (it != g_Xbox_Direct3DResources.end()) {
|
auto it = ResourceCache.find(key);
|
||||||
|
if (it != ResourceCache.end()) {
|
||||||
if (D3DUsage == D3DUSAGE_RENDERTARGET && IsResourceAPixelContainer(pResource) && EmuXBFormatIsRenderTarget(GetXboxPixelContainerFormat((XTL::X_D3DPixelContainer*)pResource))) {
|
if (D3DUsage == D3DUSAGE_RENDERTARGET && IsResourceAPixelContainer(pResource) && EmuXBFormatIsRenderTarget(GetXboxPixelContainerFormat((XTL::X_D3DPixelContainer*)pResource))) {
|
||||||
// Render targets have special behavior: We can't trash them on guest modification
|
// Render targets have special behavior: We can't trash them on guest modification
|
||||||
// this fixes an issue where CubeMaps were broken because the surface Set in GetCubeMapSurface
|
// this fixes an issue where CubeMaps were broken because the surface Set in GetCubeMapSurface
|
||||||
|
@ -2487,7 +2536,7 @@ static void EmuVerifyResourceIsRegistered(XTL::X_D3DResource *pResource, DWORD D
|
||||||
|
|
||||||
if (pParentXboxTexture) {
|
if (pParentXboxTexture) {
|
||||||
// Re-create the texture with D3DUSAGE_RENDERTARGET, this will automatically create any child-surfaces
|
// Re-create the texture with D3DUSAGE_RENDERTARGET, this will automatically create any child-surfaces
|
||||||
FreeHostResource(GetHostResourceKey(pParentXboxTexture));
|
FreeHostResource(GetHostResourceKey(pParentXboxTexture, iTextureStage));
|
||||||
CreateHostResource(pParentXboxTexture, D3DUsage, iTextureStage, dwSize);
|
CreateHostResource(pParentXboxTexture, D3DUsage, iTextureStage, dwSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2523,9 +2572,6 @@ static void EmuVerifyResourceIsRegistered(XTL::X_D3DResource *pResource, DWORD D
|
||||||
}
|
}
|
||||||
|
|
||||||
FreeHostResource(key);
|
FreeHostResource(key);
|
||||||
} else {
|
|
||||||
resource_info_t newResource;
|
|
||||||
g_Xbox_Direct3DResources[key] = newResource;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateHostResource(pResource, D3DUsage, iTextureStage, dwSize);
|
CreateHostResource(pResource, D3DUsage, iTextureStage, dwSize);
|
||||||
|
@ -3501,14 +3547,14 @@ XTL::X_D3DSurface* WINAPI XTL::EMUPATCH(D3DDevice_GetBackBuffer2)
|
||||||
DEBUG_D3DRESULT(hRet, "g_pD3DDevice->CreateOffscreenPlainSurface");
|
DEBUG_D3DRESULT(hRet, "g_pD3DDevice->CreateOffscreenPlainSurface");
|
||||||
}
|
}
|
||||||
|
|
||||||
SetHostSurface(pXboxBackBuffer, pCachedPrimarySurface);
|
SetHostSurface(pXboxBackBuffer, pCachedPrimarySurface); // No iTextureStage!
|
||||||
|
|
||||||
hRet = g_pD3DDevice->GetFrontBuffer(pCachedPrimarySurface);
|
hRet = g_pD3DDevice->GetFrontBuffer(pCachedPrimarySurface);
|
||||||
DEBUG_D3DRESULT(hRet, "g_pD3DDevice->GetFrontBuffer");
|
DEBUG_D3DRESULT(hRet, "g_pD3DDevice->GetFrontBuffer");
|
||||||
|
|
||||||
if (FAILED(hRet)) {
|
if (FAILED(hRet)) {
|
||||||
EmuLog(LOG_LEVEL::WARNING, "Could not retrieve primary surface, using backbuffer");
|
EmuLog(LOG_LEVEL::WARNING, "Could not retrieve primary surface, using backbuffer");
|
||||||
SetHostSurface(pXboxBackBuffer, nullptr);
|
SetHostSurface(pXboxBackBuffer, nullptr); // No iTextureStage!
|
||||||
pCachedPrimarySurface->Release();
|
pCachedPrimarySurface->Release();
|
||||||
pCachedPrimarySurface = nullptr;
|
pCachedPrimarySurface = nullptr;
|
||||||
BackBuffer = 0;
|
BackBuffer = 0;
|
||||||
|
@ -3543,7 +3589,7 @@ XTL::X_D3DSurface* WINAPI XTL::EMUPATCH(D3DDevice_GetBackBuffer2)
|
||||||
if (FAILED(hRet))
|
if (FAILED(hRet))
|
||||||
CxbxKrnlCleanup("Unable to retrieve back buffer");
|
CxbxKrnlCleanup("Unable to retrieve back buffer");
|
||||||
|
|
||||||
SetHostSurface(pXboxBackBuffer, pCurrentHostBackBuffer);
|
SetHostSurface(pXboxBackBuffer, pCurrentHostBackBuffer); // No iTextureStage!
|
||||||
|
|
||||||
// Increment reference count
|
// Increment reference count
|
||||||
pXboxBackBuffer->Common++; // EMUPATCH(D3DResource_AddRef)(pXboxBackBuffer);
|
pXboxBackBuffer->Common++; // EMUPATCH(D3DResource_AddRef)(pXboxBackBuffer);
|
||||||
|
@ -5474,7 +5520,7 @@ void CreateHostResource(XTL::X_D3DResource *pResource, DWORD D3DUsage, int iText
|
||||||
|
|
||||||
DEBUG_D3DRESULT(hRet, "pHostParentTexture->GetCubeMapSurface");
|
DEBUG_D3DRESULT(hRet, "pHostParentTexture->GetCubeMapSurface");
|
||||||
if (hRet == D3D_OK) {
|
if (hRet == D3D_OK) {
|
||||||
SetHostSurface(pXboxSurface, pNewHostSurface);
|
SetHostSurface(pXboxSurface, pNewHostSurface, iTextureStage);
|
||||||
EmuLog(LOG_LEVEL::DEBUG, "CreateHostResource : Successfully created CubeTexture surface level (Face: %u, Level: %u, pResource: 0x%.08X, pNewHostSurface: 0x%.08X)",
|
EmuLog(LOG_LEVEL::DEBUG, "CreateHostResource : Successfully created CubeTexture surface level (Face: %u, Level: %u, pResource: 0x%.08X, pNewHostSurface: 0x%.08X)",
|
||||||
CubeMapFace, SurfaceLevel, pResource, pNewHostSurface);
|
CubeMapFace, SurfaceLevel, pResource, pNewHostSurface);
|
||||||
return;
|
return;
|
||||||
|
@ -5491,7 +5537,7 @@ void CreateHostResource(XTL::X_D3DResource *pResource, DWORD D3DUsage, int iText
|
||||||
|
|
||||||
DEBUG_D3DRESULT(hRet, "pHostParentTexture->GetSurfaceLevel");
|
DEBUG_D3DRESULT(hRet, "pHostParentTexture->GetSurfaceLevel");
|
||||||
if (hRet == D3D_OK) {
|
if (hRet == D3D_OK) {
|
||||||
SetHostSurface(pXboxSurface, pNewHostSurface);
|
SetHostSurface(pXboxSurface, pNewHostSurface, iTextureStage);
|
||||||
EmuLog(LOG_LEVEL::DEBUG, "CreateHostResource : Successfully created Texture surface level (Level: %u, pResource: 0x%.08X, pNewHostSurface: 0x%.08X)",
|
EmuLog(LOG_LEVEL::DEBUG, "CreateHostResource : Successfully created Texture surface level (Level: %u, pResource: 0x%.08X, pNewHostSurface: 0x%.08X)",
|
||||||
SurfaceLevel, pResource, pNewHostSurface);
|
SurfaceLevel, pResource, pNewHostSurface);
|
||||||
return;
|
return;
|
||||||
|
@ -5516,7 +5562,7 @@ void CreateHostResource(XTL::X_D3DResource *pResource, DWORD D3DUsage, int iText
|
||||||
HRESULT hRet = pParentHostVolumeTexture->GetVolumeLevel(VolumeLevel, &pNewHostVolume);
|
HRESULT hRet = pParentHostVolumeTexture->GetVolumeLevel(VolumeLevel, &pNewHostVolume);
|
||||||
DEBUG_D3DRESULT(hRet, "pParentHostVolumeTexture->GetVolumeLevel");
|
DEBUG_D3DRESULT(hRet, "pParentHostVolumeTexture->GetVolumeLevel");
|
||||||
if (hRet == D3D_OK) {
|
if (hRet == D3D_OK) {
|
||||||
SetHostVolume(pXboxVolume, pNewHostVolume);
|
SetHostVolume(pXboxVolume, pNewHostVolume, iTextureStage);
|
||||||
EmuLog(LOG_LEVEL::DEBUG, "CreateHostResource : Successfully created volume level (%u, 0x%.08X, 0x%.08X)",
|
EmuLog(LOG_LEVEL::DEBUG, "CreateHostResource : Successfully created volume level (%u, 0x%.08X, 0x%.08X)",
|
||||||
VolumeLevel, pResource, pNewHostVolume);
|
VolumeLevel, pResource, pNewHostVolume);
|
||||||
return;
|
return;
|
||||||
|
@ -5713,7 +5759,7 @@ void CreateHostResource(XTL::X_D3DResource *pResource, DWORD D3DUsage, int iText
|
||||||
DXGetErrorString(hRet), DXGetErrorDescription(hRet));
|
DXGetErrorString(hRet), DXGetErrorDescription(hRet));
|
||||||
}
|
}
|
||||||
|
|
||||||
SetHostSurface(pResource, pNewHostSurface);
|
SetHostSurface(pResource, pNewHostSurface, iTextureStage);
|
||||||
EmuLog(LOG_LEVEL::DEBUG, "CreateHostResource : Successfully created %s (0x%.08X, 0x%.08X)",
|
EmuLog(LOG_LEVEL::DEBUG, "CreateHostResource : Successfully created %s (0x%.08X, 0x%.08X)",
|
||||||
ResourceTypeName, pResource, pNewHostSurface);
|
ResourceTypeName, pResource, pNewHostSurface);
|
||||||
EmuLog(LOG_LEVEL::DEBUG, "CreateHostResource : Width : %d, Height : %d, Format : %d",
|
EmuLog(LOG_LEVEL::DEBUG, "CreateHostResource : Width : %d, Height : %d, Format : %d",
|
||||||
|
@ -5728,7 +5774,7 @@ void CreateHostResource(XTL::X_D3DResource *pResource, DWORD D3DUsage, int iText
|
||||||
// So, we need to do this differently - we need to step up to the containing VolumeTexture,
|
// So, we need to do this differently - we need to step up to the containing VolumeTexture,
|
||||||
// and retrieve and convert all of it's GetVolumeLevel() slices.
|
// and retrieve and convert all of it's GetVolumeLevel() slices.
|
||||||
pNewHostVolume = nullptr;
|
pNewHostVolume = nullptr;
|
||||||
// SetHostVolume(pResource, pNewHostVolume);
|
// SetHostVolume(pResource, pNewHostVolume, iTextureStage);
|
||||||
// EmuLog(LOG_LEVEL::DEBUG, "CreateHostResource : Successfully created %s (0x%.08X, 0x%.08X)",
|
// EmuLog(LOG_LEVEL::DEBUG, "CreateHostResource : Successfully created %s (0x%.08X, 0x%.08X)",
|
||||||
// ResourceTypeName, pResource, pNewHostVolume);
|
// ResourceTypeName, pResource, pNewHostVolume);
|
||||||
break;
|
break;
|
||||||
|
@ -5781,7 +5827,7 @@ void CreateHostResource(XTL::X_D3DResource *pResource, DWORD D3DUsage, int iText
|
||||||
"Error: 0x%X\nFormat: %d\nDimensions: %dx%d", hRet, PCFormat, dwWidth, dwHeight);
|
"Error: 0x%X\nFormat: %d\nDimensions: %dx%d", hRet, PCFormat, dwWidth, dwHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
SetHostTexture(pResource, pNewHostTexture);
|
SetHostTexture(pResource, pNewHostTexture, iTextureStage);
|
||||||
EmuLog(LOG_LEVEL::DEBUG, "CreateHostResource : Successfully created %s (0x%.08X, 0x%.08X)",
|
EmuLog(LOG_LEVEL::DEBUG, "CreateHostResource : Successfully created %s (0x%.08X, 0x%.08X)",
|
||||||
ResourceTypeName, pResource, pNewHostTexture);
|
ResourceTypeName, pResource, pNewHostTexture);
|
||||||
break;
|
break;
|
||||||
|
@ -5807,7 +5853,7 @@ void CreateHostResource(XTL::X_D3DResource *pResource, DWORD D3DUsage, int iText
|
||||||
DXGetErrorString(hRet), DXGetErrorDescription(hRet));
|
DXGetErrorString(hRet), DXGetErrorDescription(hRet));
|
||||||
}
|
}
|
||||||
|
|
||||||
SetHostVolumeTexture(pResource, pNewHostVolumeTexture);
|
SetHostVolumeTexture(pResource, pNewHostVolumeTexture, iTextureStage);
|
||||||
EmuLog(LOG_LEVEL::DEBUG, "CreateHostResource : Successfully created %s (0x%.08X, 0x%.08X)",
|
EmuLog(LOG_LEVEL::DEBUG, "CreateHostResource : Successfully created %s (0x%.08X, 0x%.08X)",
|
||||||
ResourceTypeName, pResource, pNewHostVolumeTexture);
|
ResourceTypeName, pResource, pNewHostVolumeTexture);
|
||||||
break;
|
break;
|
||||||
|
@ -5836,7 +5882,7 @@ void CreateHostResource(XTL::X_D3DResource *pResource, DWORD D3DUsage, int iText
|
||||||
DXGetErrorString(hRet), DXGetErrorDescription(hRet)*/);
|
DXGetErrorString(hRet), DXGetErrorDescription(hRet)*/);
|
||||||
}
|
}
|
||||||
|
|
||||||
SetHostCubeTexture(pResource, pNewHostCubeTexture);
|
SetHostCubeTexture(pResource, pNewHostCubeTexture, iTextureStage);
|
||||||
// TODO : Cube face surfaces can be used as a render-target,
|
// TODO : Cube face surfaces can be used as a render-target,
|
||||||
// so we need to associate host surfaces to each surface of this cube texture
|
// so we need to associate host surfaces to each surface of this cube texture
|
||||||
// However, we can't do it here: On Xbox, a new Surface is created on every call to
|
// However, we can't do it here: On Xbox, a new Surface is created on every call to
|
||||||
|
@ -6958,7 +7004,7 @@ void EmuUpdateActiveTextureStages()
|
||||||
void CxbxUpdateNativeD3DResources()
|
void CxbxUpdateNativeD3DResources()
|
||||||
{
|
{
|
||||||
// Before we start, make sure our resource cache stays limited in size
|
// Before we start, make sure our resource cache stays limited in size
|
||||||
PruneResourceCache(); // TODO : Could we move this to Swap instead?
|
PrunePaletizedTexturesCache(); // TODO : Could we move this to Swap instead?
|
||||||
|
|
||||||
EmuUpdateActiveTextureStages();
|
EmuUpdateActiveTextureStages();
|
||||||
|
|
||||||
|
@ -8751,6 +8797,8 @@ bool DestroyResource_Common(XTL::X_D3DResource* pResource)
|
||||||
|
|
||||||
for (int i = 0; i < XTL::X_D3DTS_STAGECOUNT; i++) {
|
for (int i = 0; i < XTL::X_D3DTS_STAGECOUNT; i++) {
|
||||||
if (pResource == g_pXbox_SetTexture[i]) {
|
if (pResource == g_pXbox_SetTexture[i]) {
|
||||||
|
// This shouldn't happen, since texture resources that get destroyed,
|
||||||
|
// shouldn't be set to any stage anymore.
|
||||||
LOG_TEST_CASE("Skipping Release of active Xbox Texture");
|
LOG_TEST_CASE("Skipping Release of active Xbox Texture");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue