From f2b714f6bb352485006e3fb59ab9acf80239521b Mon Sep 17 00:00:00 2001 From: IndecisiveTurtle <47210458+raphaelthegreat@users.noreply.github.com> Date: Tue, 3 Sep 2024 14:58:07 +0300 Subject: [PATCH] texture_cache: Use invalidate threshhold * It's possible for shaders to bind huge buffers and only write to lower portion of it. This is a problem if upper parts of the buffer overlap with render targets. If the image is very far away from buffer base it's unlikely the shader will want to write it, so skip invalidation for it --- src/core/libraries/kernel/thread_management.cpp | 9 +++++++++ src/video_core/texture_cache/texture_cache.cpp | 14 ++++++++++---- src/video_core/texture_cache/texture_cache.h | 10 +++++----- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/core/libraries/kernel/thread_management.cpp b/src/core/libraries/kernel/thread_management.cpp index 11d472a49..88d33d5ff 100644 --- a/src/core/libraries/kernel/thread_management.cpp +++ b/src/core/libraries/kernel/thread_management.cpp @@ -1071,7 +1071,16 @@ ScePthread PThreadPool::Create() { } } +#ifdef _WIN64 auto* ret = new PthreadInternal{}; +#else + // TODO: Linux specific hack + static u8* hint_address = reinterpret_cast(0x7FFFFC000ULL); + auto* ret = reinterpret_cast( + mmap(hint_address, sizeof(PthreadInternal), PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0)); + hint_address += Common::AlignUp(sizeof(PthreadInternal), 4_KB); +#endif ret->is_free = false; ret->is_detached = false; ret->is_almost_done = false; diff --git a/src/video_core/texture_cache/texture_cache.cpp b/src/video_core/texture_cache/texture_cache.cpp index 90dc71409..d49b4e337 100644 --- a/src/video_core/texture_cache/texture_cache.cpp +++ b/src/video_core/texture_cache/texture_cache.cpp @@ -38,13 +38,15 @@ TextureCache::TextureCache(const Vulkan::Instance& instance_, Vulkan::Scheduler& TextureCache::~TextureCache() = default; void TextureCache::InvalidateMemory(VAddr address, size_t size) { + static constexpr size_t MaxInvalidateDist = 512_MB; std::unique_lock lock{mutex}; ForEachImageInRegion(address, size, [&](ImageId image_id, Image& image) { - if (!image.Overlaps(address, size)) { - return; + const size_t image_dist = + image.cpu_addr > address ? image.cpu_addr - address : address - image.cpu_addr; + if (image_dist < MaxInvalidateDist) { + // Ensure image is reuploaded when accessed again. + image.flags |= ImageFlagBits::CpuModified; } - // Ensure image is reuploaded when accessed again. - image.flags |= ImageFlagBits::CpuModified; // Untrack image, so the range is unprotected and the guest can write freely. UntrackImage(image_id); }); @@ -354,6 +356,10 @@ ImageView& TextureCache::FindDepthTarget(const ImageInfo& image_info, } void TextureCache::RefreshImage(Image& image, Vulkan::Scheduler* custom_scheduler /*= nullptr*/) { + if (False(image.flags & ImageFlagBits::CpuModified)) { + return; + } + // Mark image as validated. image.flags &= ~ImageFlagBits::CpuModified; diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 142093967..6ed1d7b94 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -61,11 +61,8 @@ public: /// Updates image contents if it was modified by CPU. void UpdateImage(ImageId image_id, Vulkan::Scheduler* custom_scheduler = nullptr) { Image& image = slot_images[image_id]; - if (False(image.flags & ImageFlagBits::CpuModified)) { - return; - } + TrackImage(image, image_id); RefreshImage(image, custom_scheduler); - TrackImage(image_id); } [[nodiscard]] ImageId ResolveOverlap(const ImageInfo& info, ImageId cache_img_id, @@ -133,7 +130,7 @@ private: using FuncReturn = typename std::invoke_result::type; static constexpr bool BOOL_BREAK = std::is_same_v; boost::container::small_vector images; - ForEachPage(cpu_addr, size, [this, &images, func](u64 page) { + ForEachPage(cpu_addr, size, [this, &images, cpu_addr, size, func](u64 page) { const auto it = page_table.find(page); if (it == nullptr) { if constexpr (BOOL_BREAK) { @@ -147,6 +144,9 @@ private: if (image.flags & ImageFlagBits::Picked) { continue; } + if (!image.Overlaps(cpu_addr, size)) { + continue; + } image.flags |= ImageFlagBits::Picked; images.push_back(image_id); if constexpr (BOOL_BREAK) {