mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-08-04 08:22:32 +00:00
untrack only first page of the image in case of head access
This commit is contained in:
parent
7936dd7386
commit
da28623315
@ -114,7 +114,7 @@ struct PageManager::Impl {
|
||||
|
||||
// Notify rasterizer about the fault.
|
||||
const VAddr addr = msg.arg.pagefault.address;
|
||||
const VAddr addr_page = Common::AlignDown(addr, PAGESIZE);
|
||||
const VAddr addr_page = GetPageAddr(addr);
|
||||
rasterizer->InvalidateMemory(addr, addr_page, PAGESIZE);
|
||||
}
|
||||
}
|
||||
@ -157,7 +157,7 @@ struct PageManager::Impl {
|
||||
const auto addr = reinterpret_cast<VAddr>(fault_address);
|
||||
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);
|
||||
const VAddr addr_aligned = GetPageAddr(addr);
|
||||
rasterizer->InvalidateMemory(addr, addr_aligned, PAGESIZE);
|
||||
return true;
|
||||
}
|
||||
@ -174,6 +174,14 @@ PageManager::PageManager(Vulkan::Rasterizer* rasterizer_)
|
||||
|
||||
PageManager::~PageManager() = default;
|
||||
|
||||
VAddr PageManager::GetPageAddr(VAddr addr) {
|
||||
return Common::AlignDown(addr, PAGESIZE);
|
||||
}
|
||||
|
||||
VAddr PageManager::GetNextPageAddr(VAddr addr) {
|
||||
return Common::AlignUp(addr + 1, PAGESIZE);
|
||||
}
|
||||
|
||||
void PageManager::OnGpuMap(VAddr address, size_t size) {
|
||||
impl->OnMap(address, size);
|
||||
}
|
||||
|
@ -28,6 +28,9 @@ public:
|
||||
/// Increase/decrease the number of surface in pages touching the specified region
|
||||
void UpdatePagesCachedCount(VAddr addr, u64 size, s32 delta);
|
||||
|
||||
static VAddr GetPageAddr(VAddr addr);
|
||||
static VAddr GetNextPageAddr(VAddr addr);
|
||||
|
||||
private:
|
||||
struct Impl;
|
||||
std::unique_ptr<Impl> impl;
|
||||
|
@ -25,9 +25,10 @@ enum ImageFlagBits : u32 {
|
||||
MaybeCpuDirty = 1 << 0, ///< The page this image is in was touched before the image address
|
||||
CpuDirty = 1 << 1, ///< Contents have been modified from the CPU
|
||||
GpuDirty = 1 << 2, ///< Contents have been modified from the GPU (valid data in buffer cache)
|
||||
Dirty = CpuDirty | GpuDirty | MaybeCpuDirty,
|
||||
Dirty = MaybeCpuDirty | CpuDirty | GpuDirty,
|
||||
GpuModified = 1 << 3, ///< Contents have been modified from the GPU
|
||||
Tracked = 1 << 4, ///< Writes and reads are being hooked from the CPU
|
||||
TailTracked = 1 << 5, ///< Writes and reads to the image tail are being hooked from the CPU
|
||||
Registered = 1 << 6, ///< True when the image is registered
|
||||
Picked = 1 << 7, ///< Temporary flag to mark the image as picked
|
||||
MetaRegistered = 1 << 8, ///< True when metadata for this surface is known and registered
|
||||
|
@ -56,8 +56,15 @@ void TextureCache::InvalidateMemory(VAddr addr, VAddr addr_aligned, size_t size)
|
||||
// Image ends on this page so it can not receive any more invalidations.
|
||||
// We will check it's hash later to see if it really was modified.
|
||||
image.flags |= ImageFlagBits::MaybeCpuDirty;
|
||||
UntrackImage(image_id);
|
||||
} else {
|
||||
// Remove tracking from this page only.
|
||||
UntrackImageHead(image_id);
|
||||
}
|
||||
} else if (addr < image_end) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (addr < image_end) {
|
||||
// Ensure image is reuploaded when accessed again.
|
||||
image.flags |= ImageFlagBits::CpuDirty;
|
||||
}
|
||||
@ -436,6 +443,7 @@ void TextureCache::RefreshImage(Image& image, Vulkan::Scheduler* custom_schedule
|
||||
const u8* addr = std::bit_cast<u8*>(image.info.guest_address);
|
||||
const u64 hash = XXH3_64bits(addr, image.info.guest_size_bytes);
|
||||
if (image.hash == hash) {
|
||||
image.flags &= ~ImageFlagBits::MaybeCpuDirty;
|
||||
return;
|
||||
}
|
||||
image.hash = hash;
|
||||
@ -481,6 +489,7 @@ void TextureCache::RefreshImage(Image& image, Vulkan::Scheduler* custom_schedule
|
||||
}
|
||||
|
||||
if (image_copy.empty()) {
|
||||
image.flags &= ~ImageFlagBits::Dirty;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -556,22 +565,59 @@ void TextureCache::TrackImage(ImageId image_id) {
|
||||
if (True(image.flags & ImageFlagBits::Tracked)) {
|
||||
return;
|
||||
}
|
||||
if (True(image.flags & ImageFlagBits::TailTracked)) {
|
||||
// Re-track only image head
|
||||
TrackImageHead(image_id);
|
||||
} else {
|
||||
// Re-track the whole image
|
||||
image.flags |= ImageFlagBits::Tracked;
|
||||
tracker.UpdatePagesCachedCount(image.cpu_addr, image.info.guest_size_bytes, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void TextureCache::TrackImageHead(ImageId image_id) {
|
||||
auto& image = slot_images[image_id];
|
||||
if (True(image.flags & ImageFlagBits::Tracked)) {
|
||||
return;
|
||||
}
|
||||
ASSERT(True(image.flags & ImageFlagBits::TailTracked));
|
||||
image.flags |= ImageFlagBits::Tracked;
|
||||
tracker.UpdatePagesCachedCount(image.cpu_addr, image.info.guest_size_bytes, 1);
|
||||
image.flags &= ~ImageFlagBits::TailTracked;
|
||||
const auto size = tracker.GetNextPageAddr(image.cpu_addr) - image.cpu_addr;
|
||||
tracker.UpdatePagesCachedCount(image.cpu_addr, size, 1);
|
||||
}
|
||||
|
||||
void TextureCache::UntrackImage(ImageId image_id) {
|
||||
auto& image = slot_images[image_id];
|
||||
ASSERT(!True(image.flags & ImageFlagBits::Tracked) ||
|
||||
!True(image.flags & ImageFlagBits::TailTracked));
|
||||
if (True(image.flags & ImageFlagBits::Tracked)) {
|
||||
image.flags &= ~ImageFlagBits::Tracked;
|
||||
tracker.UpdatePagesCachedCount(image.cpu_addr, image.info.guest_size_bytes, -1);
|
||||
}
|
||||
if (True(image.flags & ImageFlagBits::TailTracked)) {
|
||||
image.flags &= ~ImageFlagBits::TailTracked;
|
||||
const auto addr = tracker.GetNextPageAddr(image.cpu_addr);
|
||||
const auto size = image.info.guest_size_bytes - (addr - image.cpu_addr);
|
||||
tracker.UpdatePagesCachedCount(addr, size, -1);
|
||||
}
|
||||
}
|
||||
|
||||
void TextureCache::UntrackImageHead(ImageId image_id) {
|
||||
auto& image = slot_images[image_id];
|
||||
if (False(image.flags & ImageFlagBits::Tracked)) {
|
||||
return;
|
||||
}
|
||||
image.flags |= ImageFlagBits::TailTracked;
|
||||
image.flags &= ~ImageFlagBits::Tracked;
|
||||
tracker.UpdatePagesCachedCount(image.cpu_addr, image.info.guest_size_bytes, -1);
|
||||
const auto size = tracker.GetNextPageAddr(image.cpu_addr) - image.cpu_addr;
|
||||
tracker.UpdatePagesCachedCount(image.cpu_addr, size, -1);
|
||||
}
|
||||
|
||||
void TextureCache::DeleteImage(ImageId image_id) {
|
||||
Image& image = slot_images[image_id];
|
||||
ASSERT_MSG(False(image.flags & ImageFlagBits::Tracked), "Image was not untracked");
|
||||
ASSERT_MSG(False(image.flags & ImageFlagBits::TailTracked), "Image was not untracked");
|
||||
ASSERT_MSG(False(image.flags & ImageFlagBits::Registered), "Image was not unregistered");
|
||||
|
||||
// Remove any registered meta areas.
|
||||
|
@ -243,9 +243,15 @@ private:
|
||||
/// Track CPU reads and writes for image
|
||||
void TrackImage(ImageId image_id);
|
||||
|
||||
/// Track CPU reads and writes for image
|
||||
void TrackImageHead(ImageId image_id);
|
||||
|
||||
/// Stop tracking CPU reads and writes for image
|
||||
void UntrackImage(ImageId image_id);
|
||||
|
||||
/// Stop tracking CPU reads and writes for the first page of the image
|
||||
void UntrackImageHead(ImageId image_id);
|
||||
|
||||
/// Removes the image and any views/surface metas that reference it.
|
||||
void DeleteImage(ImageId image_id);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user