mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-27 16:02:37 +00:00
graphics: unwatch image heap pages on writes next to a table
This commit is contained in:
1 parent
597137e8b1
commit
463a096249
2 files changed
+16
-3
No files matched your search
@@ -254,10 +254,12 @@ void ImageHeap::Unwatch(const Memory& memory) {
|
|||||||
void ImageHeap::InvalidateMemory(uint64_t address, uint64_t size) {
|
void ImageHeap::InvalidateMemory(uint64_t address, uint64_t size) {
|
||||||
std::scoped_lock lock {m_mutex};
|
std::scoped_lock lock {m_mutex};
|
||||||
for (auto& memory: m_memories) {
|
for (auto& memory: m_memories) {
|
||||||
const auto begin = std::max(address, memory->base);
|
// Watches cover whole pages, so a write next to the table must unwatch its page too.
|
||||||
const auto end = std::min(address + size, memory->base + memory->size);
|
|
||||||
if (begin >= end) continue;
|
|
||||||
const auto origin = Common::AlignDown(memory->base, TRACKER_PAGE_SIZE);
|
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,
|
MarkDirty(*memory, (begin - origin) / TRACKER_PAGE_SIZE,
|
||||||
(end - 1u - origin) / TRACKER_PAGE_SIZE + 1u);
|
(end - 1u - origin) / TRACKER_PAGE_SIZE + 1u);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -242,6 +242,10 @@ struct ImageHeapTestAccess {
|
|||||||
static ImageId ImageOf(const ImageHeap &heap, uint32_t entry) {
|
static ImageId ImageOf(const ImageHeap &heap, uint32_t entry) {
|
||||||
return Element(heap, entry).binding.image_id;
|
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 {
|
struct TextureCacheTestAccess {
|
||||||
@@ -5518,6 +5522,13 @@ public:
|
|||||||
acquire(sampled, idle_table) && view.kinds.empty() &&
|
acquire(sampled, idle_table) && view.kinds.empty() &&
|
||||||
ImageHeapTestAccess::MemoryCount(heap) == 1u,
|
ImageHeapTestAccess::MemoryCount(heap) == 1u,
|
||||||
"an all-null table was not kept resident");
|
"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();
|
draw();
|
||||||
context.UnmapMemory(base, idle_table - base);
|
context.UnmapMemory(base, idle_table - base);
|
||||||
scheduler.Finish();
|
scheduler.Finish();
|
||||||
|
|||||||
Reference in new issue
Block a user