TextureCache: Add content locking
Texture cache occasionally mutates textures for efficiency. Which is awkward if we want to borrow those textures from texture cache to do something else, such as a graphics debugger, or async presentation on another thread. Content locking provides a way to signal that the contents of a texture cache entry should not change. Texture cache will be forced to use alternative strategies.
This commit is contained in:
parent
606c18210d
commit
a01d5283ec
|
@ -700,7 +700,8 @@ void TextureCacheBase::DoLoadState(PointerWrap& p)
|
||||||
// Even if the texture isn't valid, we still need to create the cache entry object
|
// Even if the texture isn't valid, we still need to create the cache entry object
|
||||||
// to update the point in the state state. We'll just throw it away if it's invalid.
|
// to update the point in the state state. We'll just throw it away if it's invalid.
|
||||||
auto tex = DeserializeTexture(p);
|
auto tex = DeserializeTexture(p);
|
||||||
auto entry = Common::make_rc<TCacheEntry>(std::move(tex->texture), std::move(tex->framebuffer));
|
auto entry =
|
||||||
|
std::make_shared<TCacheEntry>(std::move(tex->texture), std::move(tex->framebuffer));
|
||||||
entry->textures_by_hash_iter = textures_by_hash.end();
|
entry->textures_by_hash_iter = textures_by_hash.end();
|
||||||
entry->DoState(p);
|
entry->DoState(p);
|
||||||
if (entry->texture && commit_state)
|
if (entry->texture && commit_state)
|
||||||
|
@ -809,6 +810,13 @@ RcTcacheEntry TextureCacheBase::DoPartialTextureUpdates(RcTcacheEntry& entry_to_
|
||||||
if (entry_to_update->IsCopy())
|
if (entry_to_update->IsCopy())
|
||||||
return entry_to_update;
|
return entry_to_update;
|
||||||
|
|
||||||
|
if (entry_to_update->IsLocked())
|
||||||
|
{
|
||||||
|
// TODO: Shouldn't be too hard, just need to clone the texture entry + texture contents.
|
||||||
|
PanicAlertFmt("TextureCache: PartialTextureUpdates of locked textures is not implemented");
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
u32 block_width = TexDecoder_GetBlockWidthInTexels(entry_to_update->format.texfmt);
|
u32 block_width = TexDecoder_GetBlockWidthInTexels(entry_to_update->format.texfmt);
|
||||||
u32 block_height = TexDecoder_GetBlockHeightInTexels(entry_to_update->format.texfmt);
|
u32 block_height = TexDecoder_GetBlockHeightInTexels(entry_to_update->format.texfmt);
|
||||||
u32 block_size = block_width * block_height *
|
u32 block_size = block_width * block_height *
|
||||||
|
@ -1474,10 +1482,13 @@ RcTcacheEntry TextureCacheBase::GetTexture(const int textureCacheSafetyColorSamp
|
||||||
{
|
{
|
||||||
entry = DoPartialTextureUpdates(iter->second, texture_info.GetTlutAddress(),
|
entry = DoPartialTextureUpdates(iter->second, texture_info.GetTlutAddress(),
|
||||||
texture_info.GetTlutFormat());
|
texture_info.GetTlutFormat());
|
||||||
|
if (entry)
|
||||||
|
{
|
||||||
entry->texture->FinishedRendering();
|
entry->texture->FinishedRendering();
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Find the texture which hasn't been used for the longest time. Count paletted
|
// Find the texture which hasn't been used for the longest time. Count paletted
|
||||||
// textures as the same texture here, when the texture itself is the same. This
|
// textures as the same texture here, when the texture itself is the same. This
|
||||||
|
@ -1511,9 +1522,8 @@ RcTcacheEntry TextureCacheBase::GetTexture(const int textureCacheSafetyColorSamp
|
||||||
|
|
||||||
if (unconverted_copy != textures_by_address.end())
|
if (unconverted_copy != textures_by_address.end())
|
||||||
{
|
{
|
||||||
auto decoded_entry =
|
auto decoded_entry = ApplyPaletteToEntry(
|
||||||
ApplyPaletteToEntry(unconverted_copy->second, texture_info.GetTlutAddress(),
|
unconverted_copy->second, texture_info.GetTlutAddress(), texture_info.GetTlutFormat());
|
||||||
texture_info.GetTlutFormat());
|
|
||||||
|
|
||||||
if (decoded_entry)
|
if (decoded_entry)
|
||||||
{
|
{
|
||||||
|
@ -1543,9 +1553,12 @@ RcTcacheEntry TextureCacheBase::GetTexture(const int textureCacheSafetyColorSamp
|
||||||
{
|
{
|
||||||
entry = DoPartialTextureUpdates(hash_iter->second, texture_info.GetTlutAddress(),
|
entry = DoPartialTextureUpdates(hash_iter->second, texture_info.GetTlutAddress(),
|
||||||
texture_info.GetTlutFormat());
|
texture_info.GetTlutFormat());
|
||||||
|
if (entry)
|
||||||
|
{
|
||||||
entry->texture->FinishedRendering();
|
entry->texture->FinishedRendering();
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
++hash_iter;
|
++hash_iter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1771,9 +1784,9 @@ RcTcacheEntry TextureCacheBase::GetXFBTexture(u32 address, u32 width, u32 height
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do we currently have a version of this XFB copy in VRAM?
|
// Do we currently have a mutable version of this XFB copy in VRAM?
|
||||||
RcTcacheEntry entry = GetXFBFromCache(address, width, height, stride);
|
RcTcacheEntry entry = GetXFBFromCache(address, width, height, stride);
|
||||||
if (entry)
|
if (entry && !entry->IsLocked())
|
||||||
{
|
{
|
||||||
if (entry->is_xfb_container)
|
if (entry->is_xfb_container)
|
||||||
{
|
{
|
||||||
|
@ -2265,8 +2278,8 @@ void TextureCacheBase::CopyRenderTargetToTexture(
|
||||||
entry->may_have_overlapping_textures = false;
|
entry->may_have_overlapping_textures = false;
|
||||||
entry->is_custom_tex = false;
|
entry->is_custom_tex = false;
|
||||||
|
|
||||||
CopyEFBToCacheEntry(entry, is_depth_copy, srcRect, scaleByHalf, linear_filter,
|
CopyEFBToCacheEntry(entry, is_depth_copy, srcRect, scaleByHalf, linear_filter, dstFormat,
|
||||||
dstFormat, isIntensity, gamma, clamp_top, clamp_bottom,
|
isIntensity, gamma, clamp_top, clamp_bottom,
|
||||||
GetVRAMCopyFilterCoefficients(filter_coefficients));
|
GetVRAMCopyFilterCoefficients(filter_coefficients));
|
||||||
|
|
||||||
if (is_xfb_copy && (g_ActiveConfig.bDumpXFBTarget || g_ActiveConfig.bGraphicMods))
|
if (is_xfb_copy && (g_ActiveConfig.bDumpXFBTarget || g_ActiveConfig.bGraphicMods))
|
||||||
|
@ -2584,7 +2597,7 @@ RcTcacheEntry TextureCacheBase::AllocateCacheEntry(const TextureConfig& config)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
auto cacheEntry =
|
auto cacheEntry =
|
||||||
Common::make_rc<TCacheEntry>(std::move(alloc->texture), std::move(alloc->framebuffer));
|
std::make_shared<TCacheEntry>(std::move(alloc->texture), std::move(alloc->framebuffer));
|
||||||
cacheEntry->textures_by_hash_iter = textures_by_hash.end();
|
cacheEntry->textures_by_hash_iter = textures_by_hash.end();
|
||||||
cacheEntry->id = last_entry_id++;
|
cacheEntry->id = last_entry_id++;
|
||||||
return cacheEntry;
|
return cacheEntry;
|
||||||
|
@ -2710,6 +2723,7 @@ TextureCacheBase::InvalidateTexture(TexAddrCache::iterator iter, bool discard_pe
|
||||||
{
|
{
|
||||||
// The texture data has already been copied into the staging texture, so it's valid to
|
// The texture data has already been copied into the staging texture, so it's valid to
|
||||||
// optimistically release the texture data. Will slightly lower VRAM usage.
|
// optimistically release the texture data. Will slightly lower VRAM usage.
|
||||||
|
if (!entry->IsLocked())
|
||||||
ReleaseToPool(entry.get());
|
ReleaseToPool(entry.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
#include "Common/BitSet.h"
|
#include "Common/BitSet.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/MathUtil.h"
|
#include "Common/MathUtil.h"
|
||||||
#include "Common/RcPtr.h"
|
|
||||||
#include "VideoCommon/AbstractTexture.h"
|
#include "VideoCommon/AbstractTexture.h"
|
||||||
#include "VideoCommon/BPMemory.h"
|
#include "VideoCommon/BPMemory.h"
|
||||||
#include "VideoCommon/TextureConfig.h"
|
#include "VideoCommon/TextureConfig.h"
|
||||||
|
@ -127,6 +126,7 @@ struct TCacheEntry
|
||||||
bool is_xfb_copy = false;
|
bool is_xfb_copy = false;
|
||||||
bool is_xfb_container = false;
|
bool is_xfb_container = false;
|
||||||
u64 id = 0;
|
u64 id = 0;
|
||||||
|
u32 content_semaphore = 0; // Counts up
|
||||||
|
|
||||||
// Indicates that this TCacheEntry has been invalided from textures_by_address
|
// Indicates that this TCacheEntry has been invalided from textures_by_address
|
||||||
bool invalidated = false;
|
bool invalidated = false;
|
||||||
|
@ -143,7 +143,7 @@ struct TCacheEntry
|
||||||
|
|
||||||
// Keep an iterator to the entry in textures_by_hash, so it does not need to be searched when
|
// Keep an iterator to the entry in textures_by_hash, so it does not need to be searched when
|
||||||
// removing the cache entry
|
// removing the cache entry
|
||||||
std::multimap<u64, Common::rc_ptr<TCacheEntry>>::iterator textures_by_hash_iter;
|
std::multimap<u64, std::shared_ptr<TCacheEntry>>::iterator textures_by_hash_iter;
|
||||||
|
|
||||||
// This is used to keep track of both:
|
// This is used to keep track of both:
|
||||||
// * efb copies used by this partially updated texture
|
// * efb copies used by this partially updated texture
|
||||||
|
@ -194,6 +194,14 @@ struct TCacheEntry
|
||||||
other_entry->references.emplace(this);
|
other_entry->references.emplace(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Acquiring a content lock will lock the current contents and prevent texture cache from
|
||||||
|
// reusing the same entry for a newer version of the texture.
|
||||||
|
void AcquireContentLock() { content_semaphore++; }
|
||||||
|
void ReleaseContentLock() { content_semaphore--; }
|
||||||
|
|
||||||
|
// Can this be mutated?
|
||||||
|
bool IsLocked() const { return content_semaphore > 0; }
|
||||||
|
|
||||||
void SetXfbCopy(u32 stride);
|
void SetXfbCopy(u32 stride);
|
||||||
void SetEfbCopy(u32 stride);
|
void SetEfbCopy(u32 stride);
|
||||||
void SetNotCopy();
|
void SetNotCopy();
|
||||||
|
@ -217,7 +225,7 @@ struct TCacheEntry
|
||||||
void DoState(PointerWrap& p);
|
void DoState(PointerWrap& p);
|
||||||
};
|
};
|
||||||
|
|
||||||
using RcTcacheEntry = Common::rc_ptr<TCacheEntry>;
|
using RcTcacheEntry = std::shared_ptr<TCacheEntry>;
|
||||||
|
|
||||||
class TextureCacheBase
|
class TextureCacheBase
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue