mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-15 05:47:56 -07:00
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
|
||||
// to update the point in the state state. We'll just throw it away if it's invalid.
|
||||
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->DoState(p);
|
||||
if (entry->texture && commit_state)
|
||||
@ -809,6 +810,13 @@ RcTcacheEntry TextureCacheBase::DoPartialTextureUpdates(RcTcacheEntry& entry_to_
|
||||
if (entry_to_update->IsCopy())
|
||||
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_height = TexDecoder_GetBlockHeightInTexels(entry_to_update->format.texfmt);
|
||||
u32 block_size = block_width * block_height *
|
||||
@ -1474,8 +1482,11 @@ RcTcacheEntry TextureCacheBase::GetTexture(const int textureCacheSafetyColorSamp
|
||||
{
|
||||
entry = DoPartialTextureUpdates(iter->second, texture_info.GetTlutAddress(),
|
||||
texture_info.GetTlutFormat());
|
||||
entry->texture->FinishedRendering();
|
||||
return entry;
|
||||
if (entry)
|
||||
{
|
||||
entry->texture->FinishedRendering();
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1511,9 +1522,8 @@ RcTcacheEntry TextureCacheBase::GetTexture(const int textureCacheSafetyColorSamp
|
||||
|
||||
if (unconverted_copy != textures_by_address.end())
|
||||
{
|
||||
auto decoded_entry =
|
||||
ApplyPaletteToEntry(unconverted_copy->second, texture_info.GetTlutAddress(),
|
||||
texture_info.GetTlutFormat());
|
||||
auto decoded_entry = ApplyPaletteToEntry(
|
||||
unconverted_copy->second, texture_info.GetTlutAddress(), texture_info.GetTlutFormat());
|
||||
|
||||
if (decoded_entry)
|
||||
{
|
||||
@ -1543,8 +1553,11 @@ RcTcacheEntry TextureCacheBase::GetTexture(const int textureCacheSafetyColorSamp
|
||||
{
|
||||
entry = DoPartialTextureUpdates(hash_iter->second, texture_info.GetTlutAddress(),
|
||||
texture_info.GetTlutFormat());
|
||||
entry->texture->FinishedRendering();
|
||||
return entry;
|
||||
if (entry)
|
||||
{
|
||||
entry->texture->FinishedRendering();
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
++hash_iter;
|
||||
}
|
||||
@ -1771,9 +1784,9 @@ RcTcacheEntry TextureCacheBase::GetXFBTexture(u32 address, u32 width, u32 height
|
||||
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);
|
||||
if (entry)
|
||||
if (entry && !entry->IsLocked())
|
||||
{
|
||||
if (entry->is_xfb_container)
|
||||
{
|
||||
@ -2265,8 +2278,8 @@ void TextureCacheBase::CopyRenderTargetToTexture(
|
||||
entry->may_have_overlapping_textures = false;
|
||||
entry->is_custom_tex = false;
|
||||
|
||||
CopyEFBToCacheEntry(entry, is_depth_copy, srcRect, scaleByHalf, linear_filter,
|
||||
dstFormat, isIntensity, gamma, clamp_top, clamp_bottom,
|
||||
CopyEFBToCacheEntry(entry, is_depth_copy, srcRect, scaleByHalf, linear_filter, dstFormat,
|
||||
isIntensity, gamma, clamp_top, clamp_bottom,
|
||||
GetVRAMCopyFilterCoefficients(filter_coefficients));
|
||||
|
||||
if (is_xfb_copy && (g_ActiveConfig.bDumpXFBTarget || g_ActiveConfig.bGraphicMods))
|
||||
@ -2584,7 +2597,7 @@ RcTcacheEntry TextureCacheBase::AllocateCacheEntry(const TextureConfig& config)
|
||||
return {};
|
||||
|
||||
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->id = last_entry_id++;
|
||||
return cacheEntry;
|
||||
@ -2710,7 +2723,8 @@ TextureCacheBase::InvalidateTexture(TexAddrCache::iterator iter, bool discard_pe
|
||||
{
|
||||
// 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.
|
||||
ReleaseToPool(entry.get());
|
||||
if (!entry->IsLocked())
|
||||
ReleaseToPool(entry.get());
|
||||
}
|
||||
}
|
||||
entry->invalidated = true;
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include "Common/BitSet.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/MathUtil.h"
|
||||
#include "Common/RcPtr.h"
|
||||
#include "VideoCommon/AbstractTexture.h"
|
||||
#include "VideoCommon/BPMemory.h"
|
||||
#include "VideoCommon/TextureConfig.h"
|
||||
@ -127,6 +126,7 @@ struct TCacheEntry
|
||||
bool is_xfb_copy = false;
|
||||
bool is_xfb_container = false;
|
||||
u64 id = 0;
|
||||
u32 content_semaphore = 0; // Counts up
|
||||
|
||||
// Indicates that this TCacheEntry has been invalided from textures_by_address
|
||||
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
|
||||
// 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:
|
||||
// * efb copies used by this partially updated texture
|
||||
@ -194,6 +194,14 @@ struct TCacheEntry
|
||||
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 SetEfbCopy(u32 stride);
|
||||
void SetNotCopy();
|
||||
@ -217,7 +225,7 @@ struct TCacheEntry
|
||||
void DoState(PointerWrap& p);
|
||||
};
|
||||
|
||||
using RcTcacheEntry = Common::rc_ptr<TCacheEntry>;
|
||||
using RcTcacheEntry = std::shared_ptr<TCacheEntry>;
|
||||
|
||||
class TextureCacheBase
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user