mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 06:09:50 -06:00
TextureCache: Refactor with smart pointers
The whole ownership model was getting a bit of a mess, with a some of special cases to deal with. And I'm planning to make it even more complex in the future. So here is some upfront work to convert it over to reference counted pointers.
This commit is contained in:
@ -19,6 +19,7 @@
|
||||
#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"
|
||||
@ -88,6 +89,7 @@ struct EFBCopyParams
|
||||
template <>
|
||||
struct fmt::formatter<EFBCopyParams>
|
||||
{
|
||||
std::shared_ptr<int> state;
|
||||
constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
|
||||
template <typename FormatContext>
|
||||
auto format(const EFBCopyParams& uid, FormatContext& ctx) const
|
||||
@ -119,14 +121,16 @@ struct TCacheEntry
|
||||
bool is_efb_copy = false;
|
||||
bool is_custom_tex = false;
|
||||
bool may_have_overlapping_textures = true;
|
||||
bool tmem_only = false; // indicates that this texture only exists in the tmem cache
|
||||
bool has_arbitrary_mips = false; // indicates that the mips in this texture are arbitrary
|
||||
// content, aren't just downscaled
|
||||
bool has_arbitrary_mips = false; // indicates that the mips in this texture are arbitrary
|
||||
// content, aren't just downscaled
|
||||
bool should_force_safe_hashing = false; // for XFB
|
||||
bool is_xfb_copy = false;
|
||||
bool is_xfb_container = false;
|
||||
u64 id = 0;
|
||||
|
||||
// Indicates that this TCacheEntry has been invalided from textures_by_address
|
||||
bool invalidated = false;
|
||||
|
||||
bool reference_changed = false; // used by xfb to determine when a reference xfb changed
|
||||
|
||||
// Texture dimensions from the GameCube's point of view
|
||||
@ -139,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, TCacheEntry*>::iterator textures_by_hash_iter;
|
||||
std::multimap<u64, Common::rc_ptr<TCacheEntry>>::iterator textures_by_hash_iter;
|
||||
|
||||
// This is used to keep track of both:
|
||||
// * efb copies used by this partially updated texture
|
||||
@ -150,12 +154,11 @@ struct TCacheEntry
|
||||
std::unique_ptr<AbstractStagingTexture> pending_efb_copy;
|
||||
u32 pending_efb_copy_width = 0;
|
||||
u32 pending_efb_copy_height = 0;
|
||||
bool pending_efb_copy_invalidated = false;
|
||||
|
||||
std::string texture_info_name = "";
|
||||
|
||||
explicit TCacheEntry(std::unique_ptr<AbstractTexture> tex,
|
||||
std::unique_ptr<AbstractFramebuffer> fb);
|
||||
std::unique_ptr<AbstractFramebuffer> fb);
|
||||
|
||||
~TCacheEntry();
|
||||
|
||||
@ -169,7 +172,7 @@ struct TCacheEntry
|
||||
}
|
||||
|
||||
void SetDimensions(unsigned int _native_width, unsigned int _native_height,
|
||||
unsigned int _native_levels)
|
||||
unsigned int _native_levels)
|
||||
{
|
||||
native_width = _native_width;
|
||||
native_height = _native_height;
|
||||
@ -214,6 +217,8 @@ struct TCacheEntry
|
||||
void DoState(PointerWrap& p);
|
||||
};
|
||||
|
||||
using RcTcacheEntry = Common::rc_ptr<TCacheEntry>;
|
||||
|
||||
class TextureCacheBase
|
||||
{
|
||||
public:
|
||||
@ -231,6 +236,7 @@ public:
|
||||
virtual ~TextureCacheBase();
|
||||
|
||||
bool Initialize();
|
||||
void Shutdown();
|
||||
|
||||
void OnConfigChanged(const VideoConfig& config);
|
||||
void ForceReload();
|
||||
@ -240,12 +246,13 @@ public:
|
||||
void Cleanup(int _frameCount);
|
||||
|
||||
void Invalidate();
|
||||
void ReleaseToPool(TCacheEntry* entry);
|
||||
|
||||
TCacheEntry* Load(const TextureInfo& texture_info);
|
||||
TCacheEntry* GetTexture(const int textureCacheSafetyColorSampleSize,
|
||||
const TextureInfo& texture_info);
|
||||
TCacheEntry* GetXFBTexture(u32 address, u32 width, u32 height, u32 stride,
|
||||
MathUtil::Rectangle<int>* display_rect);
|
||||
RcTcacheEntry GetTexture(const int textureCacheSafetyColorSampleSize,
|
||||
const TextureInfo& texture_info);
|
||||
RcTcacheEntry GetXFBTexture(u32 address, u32 width, u32 height, u32 stride,
|
||||
MathUtil::Rectangle<int>* display_rect);
|
||||
|
||||
virtual void BindTextures(BitSet32 used_textures);
|
||||
void CopyRenderTargetToTexture(u32 dstAddr, EFBCopyFormat dstFormat, u32 width, u32 height,
|
||||
@ -255,11 +262,14 @@ public:
|
||||
bool clamp_bottom,
|
||||
const CopyFilterCoefficients::Values& filter_coefficients);
|
||||
|
||||
void ScaleTextureCacheEntryTo(TCacheEntry* entry, u32 new_width, u32 new_height);
|
||||
void ScaleTextureCacheEntryTo(RcTcacheEntry& entry, u32 new_width, u32 new_height);
|
||||
|
||||
// Flushes all pending EFB copies to emulated RAM.
|
||||
void FlushEFBCopies();
|
||||
|
||||
// Flush any Bound textures that can't be reused
|
||||
void FlushStaleBinds();
|
||||
|
||||
// Texture Serialization
|
||||
void SerializeTexture(AbstractTexture* tex, const TextureConfig& config, PointerWrap& p);
|
||||
std::optional<TexPoolEntry> DeserializeTexture(PointerWrap& p);
|
||||
@ -276,7 +286,7 @@ protected:
|
||||
// width, height are the size of the image in pixels.
|
||||
// aligned_width, aligned_height are the size of the image in pixels, aligned to the block size.
|
||||
// row_stride is the number of bytes for a row of blocks, not pixels.
|
||||
bool DecodeTextureOnGPU(TCacheEntry* entry, u32 dst_level, const u8* data, u32 data_size,
|
||||
bool DecodeTextureOnGPU(RcTcacheEntry& entry, u32 dst_level, const u8* data, u32 data_size,
|
||||
TextureFormat format, u32 width, u32 height, u32 aligned_width,
|
||||
u32 aligned_height, u32 row_stride, const u8* palette,
|
||||
TLUTFormat palette_format);
|
||||
@ -286,7 +296,7 @@ protected:
|
||||
const MathUtil::Rectangle<int>& src_rect, bool scale_by_half,
|
||||
bool linear_filter, float y_scale, float gamma, bool clamp_top,
|
||||
bool clamp_bottom, const std::array<u32, 3>& filter_coefficients);
|
||||
virtual void CopyEFBToCacheEntry(TCacheEntry* entry, bool is_depth_copy,
|
||||
virtual void CopyEFBToCacheEntry(RcTcacheEntry& entry, bool is_depth_copy,
|
||||
const MathUtil::Rectangle<int>& src_rect, bool scale_by_half,
|
||||
bool linear_filter, EFBCopyFormat dst_format, bool is_intensity,
|
||||
float gamma, bool clamp_top, bool clamp_bottom,
|
||||
@ -295,32 +305,31 @@ protected:
|
||||
alignas(16) u8* temp = nullptr;
|
||||
size_t temp_size = 0;
|
||||
|
||||
std::array<TCacheEntry*, 8> bound_textures{};
|
||||
static std::bitset<8> valid_bind_points;
|
||||
|
||||
private:
|
||||
using TexAddrCache = std::multimap<u32, TCacheEntry*>;
|
||||
using TexHashCache = std::multimap<u64, TCacheEntry*>;
|
||||
using TexAddrCache = std::multimap<u32, RcTcacheEntry>;
|
||||
using TexHashCache = std::multimap<u64, RcTcacheEntry>;
|
||||
|
||||
using TexPool = std::unordered_multimap<TextureConfig, TexPoolEntry>;
|
||||
|
||||
bool CreateUtilityTextures();
|
||||
|
||||
void SetBackupConfig(const VideoConfig& config);
|
||||
|
||||
TCacheEntry* GetXFBFromCache(u32 address, u32 width, u32 height, u32 stride);
|
||||
RcTcacheEntry GetXFBFromCache(u32 address, u32 width, u32 height, u32 stride);
|
||||
|
||||
TCacheEntry* ApplyPaletteToEntry(TCacheEntry* entry, const u8* palette, TLUTFormat tlutfmt);
|
||||
RcTcacheEntry ApplyPaletteToEntry(RcTcacheEntry& entry, const u8* palette, TLUTFormat tlutfmt);
|
||||
|
||||
TCacheEntry* ReinterpretEntry(const TCacheEntry* existing_entry, TextureFormat new_format);
|
||||
RcTcacheEntry ReinterpretEntry(const RcTcacheEntry& existing_entry, TextureFormat new_format);
|
||||
|
||||
TCacheEntry* DoPartialTextureUpdates(TCacheEntry* entry_to_update, const u8* palette,
|
||||
TLUTFormat tlutfmt);
|
||||
void StitchXFBCopy(TCacheEntry* entry_to_update);
|
||||
RcTcacheEntry DoPartialTextureUpdates(RcTcacheEntry& entry_to_update, const u8* palette,
|
||||
TLUTFormat tlutfmt);
|
||||
void StitchXFBCopy(RcTcacheEntry& entry_to_update);
|
||||
|
||||
void DumpTexture(TCacheEntry* entry, std::string basename, unsigned int level, bool is_arbitrary);
|
||||
void DumpTexture(RcTcacheEntry& entry, std::string basename, unsigned int level,
|
||||
bool is_arbitrary);
|
||||
void CheckTempSize(size_t required_size);
|
||||
|
||||
TCacheEntry* AllocateCacheEntry(const TextureConfig& config);
|
||||
RcTcacheEntry AllocateCacheEntry(const TextureConfig& config);
|
||||
std::optional<TexPoolEntry> AllocateTexture(const TextureConfig& config);
|
||||
TexPool::iterator FindMatchingTextureFromPool(const TextureConfig& config);
|
||||
TexAddrCache::iterator GetTexCacheIter(TCacheEntry* entry);
|
||||
@ -358,8 +367,18 @@ private:
|
||||
void DoSaveState(PointerWrap& p);
|
||||
void DoLoadState(PointerWrap& p);
|
||||
|
||||
// textures_by_address is the authoritive version of what's actually "in" the texture cache
|
||||
// but it's possible for invalidated TCache entries to live on elsewhere
|
||||
TexAddrCache textures_by_address;
|
||||
|
||||
// textures_by_hash is an alternative view of the texture cache
|
||||
// All textures in here will also be in textures_by_address
|
||||
TexHashCache textures_by_hash;
|
||||
|
||||
// bound_textures are actually active in the current draw
|
||||
// It's valid for textures to be in here after they've been invalidated
|
||||
std::array<RcTcacheEntry, 8> bound_textures{};
|
||||
|
||||
TexPool texture_pool;
|
||||
u64 last_entry_id = 0;
|
||||
|
||||
@ -394,7 +413,8 @@ private:
|
||||
|
||||
// List of pending EFB copies. It is important that the order is preserved for these,
|
||||
// so that overlapping textures are written to guest RAM in the order they are issued.
|
||||
std::vector<TCacheEntry*> m_pending_efb_copies;
|
||||
// It's valid for textures to live be in here after they've been invalidated
|
||||
std::vector<RcTcacheEntry> m_pending_efb_copies;
|
||||
|
||||
// Staging texture used for readbacks.
|
||||
// We store this in the class so that the same staging texture can be used for multiple
|
||||
|
Reference in New Issue
Block a user