@ -71,14 +71,16 @@ class TextureCache {
static constexpr bool FRAMEBUFFER_BLITS = P : : FRAMEBUFFER_BLITS ;
/// True when some copies have to be emulated
static constexpr bool HAS_EMULATED_COPIES = P : : HAS_EMULATED_COPIES ;
/// True when the API can provide info about the memory of the device.
static constexpr bool HAS_DEVICE_MEMORY_INFO = P : : HAS_DEVICE_MEMORY_INFO ;
/// Image view ID for null descriptors
static constexpr ImageViewId NULL_IMAGE_VIEW_ID { 0 } ;
/// Sampler ID for bugged sampler ids
static constexpr SamplerId NULL_SAMPLER_ID { 0 } ;
static constexpr u64 EXPECTED_MEMORY = Common : : Size_1_GB ;
static constexpr u64 CRITICAL_MEMORY = Common : : Size_2_GB ;
static constexpr u64 DEFAULT_ EXPECTED_MEMORY = Common : : Size_1_GB ;
static constexpr u64 DEFAULT_ CRITICAL_MEMORY = Common : : Size_2_GB ;
using Runtime = typename P : : Runtime ;
using Image = typename P : : Image ;
@ -108,6 +110,9 @@ public:
/// Notify the cache that a new frame has been queued
void TickFrame ( ) ;
/// Runs the Garbage Collector.
void RunGarbageCollector ( ) ;
/// Return a constant reference to the given image view id
[[nodiscard]] const ImageView & GetImageView ( ImageViewId id ) const noexcept ;
@ -339,6 +344,8 @@ private:
bool has_deleted_images = false ;
u64 total_used_memory = 0 ;
u64 expected_memory ;
u64 critical_memory ;
SlotVector < Image > slot_images ;
SlotVector < ImageView > slot_image_views ;
@ -382,21 +389,23 @@ TextureCache<P>::TextureCache(Runtime& runtime_, VideoCore::RasterizerInterface&
void ( slot_samplers . insert ( runtime , sampler_descriptor ) ) ;
deletion_iterator = slot_images . begin ( ) ;
if constexpr ( HAS_DEVICE_MEMORY_INFO ) {
const auto device_memory = runtime . GetDeviceLocalMemory ( ) ;
const u64 possible_expected_memory = ( device_memory * 3 ) / 10 ;
const u64 possible_critical_memory = ( device_memory * 6 ) / 10 ;
expected_memory = std : : max ( possible_expected_memory , DEFAULT_EXPECTED_MEMORY ) ;
critical_memory = std : : max ( possible_critical_memory , DEFAULT_CRITICAL_MEMORY ) ;
} else {
expected_memory = DEFAULT_EXPECTED_MEMORY ;
critical_memory = DEFAULT_CRITICAL_MEMORY ;
}
}
template < class P >
void TextureCache < P > : : TickFrame ( ) {
const bool enabled_gc = Settings : : values . use_caches_gc . GetValue ( ) ;
if ( ! enabled_gc ) {
// @Note(Blinkhawk): compile error with SCOPE_EXIT on msvc.
sentenced_images . Tick ( ) ;
sentenced_framebuffers . Tick ( ) ;
sentenced_image_view . Tick ( ) ;
+ + frame_tick ;
return ;
}
const bool high_priority_mode = total_used_memory > = EXPECTED_MEMORY ;
const bool aggressive_mode = total_used_memory > = CRITICAL_MEMORY ;
void TextureCache < P > : : RunGarbageCollector ( ) {
const bool high_priority_mode = total_used_memory > = expected_memory ;
const bool aggressive_mode = total_used_memory > = critical_memory ;
const u64 ticks_to_destroy = high_priority_mode ? 60 : 100 ;
int num_iterations = aggressive_mode ? 256 : ( high_priority_mode ? 128 : 64 ) ;
for ( ; num_iterations > 0 ; - - num_iterations ) {
@ -451,11 +460,18 @@ void TextureCache<P>::TickFrame() {
UnregisterImage ( image_id ) ;
DeleteImage ( image_id ) ;
if ( is_bad_overlap ) {
num_iterations + + ;
+ + num_iterations ;
}
}
+ + deletion_iterator ;
}
}
template < class P >
void TextureCache < P > : : TickFrame ( ) {
if ( Settings : : values . use_caches_gc . GetValue ( ) ) {
RunGarbageCollector ( ) ;
}
sentenced_images . Tick ( ) ;
sentenced_framebuffers . Tick ( ) ;
sentenced_image_view . Tick ( ) ;