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
This commit is contained in:
IndecisiveTurtle 2024-09-03 14:58:07 +03:00
parent 28feb77982
commit f2b714f6bb
3 changed files with 24 additions and 9 deletions

View file

@ -1071,7 +1071,16 @@ ScePthread PThreadPool::Create() {
}
}
#ifdef _WIN64
auto* ret = new PthreadInternal{};
#else
// TODO: Linux specific hack
static u8* hint_address = reinterpret_cast<u8*>(0x7FFFFC000ULL);
auto* ret = reinterpret_cast<PthreadInternal*>(
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;

View file

@ -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;

View file

@ -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<Func, ImageId, Image&>::type;
static constexpr bool BOOL_BREAK = std::is_same_v<FuncReturn, bool>;
boost::container::small_vector<ImageId, 32> 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) {