Fixed false-positive image reuploads

This commit is contained in:
Vladislav Mikhalin 2024-11-20 21:56:08 +03:00
parent 3f1be5a4ce
commit 0f99682eb6
5 changed files with 16 additions and 10 deletions

View File

@ -158,7 +158,7 @@ struct PageManager::Impl {
const bool is_write = Common::IsWriteError(context);
if (is_write && owned_ranges.find(addr) != owned_ranges.end()) {
const VAddr addr_aligned = Common::AlignDown(addr, PAGESIZE);
rasterizer->InvalidateMemory(addr_aligned, PAGESIZE);
rasterizer->InvalidateMemory(addr, addr_aligned, PAGESIZE);
return true;
}
return false;

View File

@ -792,9 +792,9 @@ u32 Rasterizer::ReadDataFromGds(u32 gds_offset) {
return value;
}
void Rasterizer::InvalidateMemory(VAddr addr, u64 size) {
buffer_cache.InvalidateMemory(addr, size);
texture_cache.InvalidateMemory(addr, size);
void Rasterizer::InvalidateMemory(VAddr addr, VAddr addr_aligned, u64 size) {
buffer_cache.InvalidateMemory(addr_aligned, size);
texture_cache.InvalidateMemory(addr, addr_aligned, size);
}
void Rasterizer::MapMemory(VAddr addr, u64 size) {

View File

@ -46,7 +46,7 @@ public:
void InlineData(VAddr address, const void* value, u32 num_bytes, bool is_gds);
u32 ReadDataFromGds(u32 gsd_offset);
void InvalidateMemory(VAddr addr, u64 size);
void InvalidateMemory(VAddr addr, VAddr addr_aligned, u64 size);
void MapMemory(VAddr addr, u64 size);
void UnmapMemory(VAddr addr, u64 size);

View File

@ -43,11 +43,17 @@ TextureCache::TextureCache(const Vulkan::Instance& instance_, Vulkan::Scheduler&
TextureCache::~TextureCache() = default;
void TextureCache::InvalidateMemory(VAddr address, size_t size) {
void TextureCache::InvalidateMemory(VAddr addr, VAddr addr_aligned, size_t size) {
std::scoped_lock lock{mutex};
ForEachImageInRegion(address, size, [&](ImageId image_id, Image& image) {
// Ensure image is reuploaded when accessed again.
image.flags |= ImageFlagBits::CpuDirty;
ForEachImageInRegion(addr_aligned, size, [&](ImageId image_id, Image& image) {
const auto addr_begin = addr;
const auto addr_end = addr + size;
const auto image_begin = image.info.guest_address;
const auto image_end = image.info.guest_address + image.info.guest_size_bytes;
if (addr_begin < image_end && image_begin < addr_end) {
// Ensure image is reuploaded when accessed again.
image.flags |= ImageFlagBits::CpuDirty;
}
// Untrack image, so the range is unprotected and the guest can write freely.
UntrackImage(image_id);
});

View File

@ -95,7 +95,7 @@ public:
~TextureCache();
/// Invalidates any image in the logical page range.
void InvalidateMemory(VAddr address, size_t size);
void InvalidateMemory(VAddr addr, VAddr addr_aligned, size_t size);
/// Marks an image as dirty if it exists at the provided address.
void InvalidateMemoryFromGPU(VAddr address, size_t max_size);