mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-26 12:56:54 +01:00
graphics: unwatch image heap pages on writes next to a table
This commit is contained in:
@@ -254,10 +254,12 @@ void ImageHeap::Unwatch(const Memory& memory) {
|
||||
void ImageHeap::InvalidateMemory(uint64_t address, uint64_t size) {
|
||||
std::scoped_lock lock {m_mutex};
|
||||
for (auto& memory: m_memories) {
|
||||
const auto begin = std::max(address, memory->base);
|
||||
const auto end = std::min(address + size, memory->base + memory->size);
|
||||
if (begin >= end) continue;
|
||||
// Watches cover whole pages, so a write next to the table must unwatch its page too.
|
||||
const auto origin = Common::AlignDown(memory->base, TRACKER_PAGE_SIZE);
|
||||
const auto begin = std::max(address, origin);
|
||||
const auto end = std::min(address + size,
|
||||
origin + memory->dirty_pages.size() * TRACKER_PAGE_SIZE);
|
||||
if (begin >= end) continue;
|
||||
MarkDirty(*memory, (begin - origin) / TRACKER_PAGE_SIZE,
|
||||
(end - 1u - origin) / TRACKER_PAGE_SIZE + 1u);
|
||||
}
|
||||
|
||||
@@ -242,6 +242,10 @@ struct ImageHeapTestAccess {
|
||||
static ImageId ImageOf(const ImageHeap &heap, uint32_t entry) {
|
||||
return Element(heap, entry).binding.image_id;
|
||||
}
|
||||
// Whether the newest table no longer watches its last page.
|
||||
static bool TailPageDirty(const ImageHeap &heap) {
|
||||
return heap.m_memories.back()->dirty_pages.back() != 0u;
|
||||
}
|
||||
};
|
||||
|
||||
struct TextureCacheTestAccess {
|
||||
@@ -5518,6 +5522,13 @@ public:
|
||||
acquire(sampled, idle_table) && view.kinds.empty() &&
|
||||
ImageHeapTestAccess::MemoryCount(heap) == 1u,
|
||||
"an all-null table was not kept resident");
|
||||
// A write past a table's end, in its watched tail page, must unwatch the page.
|
||||
constexpr uint64_t unaligned_table = base + 0x1a0800;
|
||||
Require(name, "tail page fault",
|
||||
acquire(sampled, unaligned_table) &&
|
||||
context.HandleFault(PageFaultAccess::Write, unaligned_table + table_size) &&
|
||||
ImageHeapTestAccess::TailPageDirty(heap),
|
||||
"a write fault next to a table left its page watched");
|
||||
draw();
|
||||
context.UnmapMemory(base, idle_table - base);
|
||||
scheduler.Finish();
|
||||
|
||||
Reference in New Issue
Block a user