Refactor texture cache image download handling (#4593)

* Add rasterizer image processing in event handling

* Implement ProcessDownloadImages method

Added a new method to process downloaded images in the rasterizer.

* Add ProcessDownloadImages method to vk_rasterizer.h

* Modify DownloadImageMemory to include sync parameter

Added optional sync parameter to DownloadImageMemory.

* Refactor texture cache image download handling

Updated DownloadImageMemory to support synchronous downloads and adjusted image extent calculations.

* Refactor image download condition and format code

Fix conditional logic for downloading images and add newline at end of file.

* Removed redundant check for volume in FindTexture function.

* Add readback_linear_images check in FindTexture
This commit is contained in:
Hog 2026-07-07 14:23:09 +01:00 committed by GitHub
parent 64d198190f
commit 16d5f9c54c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 30 additions and 10 deletions

View File

@ -691,6 +691,9 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
}
case PM4ItOpcode::EventWriteEos: {
const auto* event_eos = reinterpret_cast<const PM4CmdEventWriteEos*>(header);
if (rasterizer) {
rasterizer->ProcessDownloadImages();
}
event_eos->SignalFence([](void* address, u64 data, u32 num_bytes) {
auto* memory = Core::Memory::Instance();
if (!memory->TryWriteBacking(address, &data, num_bytes)) {
@ -709,6 +712,9 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
}
case PM4ItOpcode::EventWriteEop: {
const auto* event_eop = reinterpret_cast<const PM4CmdEventWriteEop*>(header);
if (rasterizer) {
rasterizer->ProcessDownloadImages();
}
event_eop->SignalFence(
[](void* address, u64 data, u32 num_bytes) {
auto* memory = Core::Memory::Instance();
@ -1137,6 +1143,9 @@ Liverpool::Task Liverpool::ProcessCompute(std::span<const u32> acb, u32 vqid) {
}
case PM4ItOpcode::ReleaseMem: {
const auto* release_mem = reinterpret_cast<const PM4CmdReleaseMem*>(header);
if (rasterizer) {
rasterizer->ProcessDownloadImages();
}
release_mem->SignalFence(
[pipe_id = queue.pipe_id] {
Platform::IrqC::Instance()->Signal(static_cast<Platform::InterruptId>(pipe_id));

View File

@ -1068,6 +1068,10 @@ bool Rasterizer::ReadMemory(VAddr addr, u64 size) {
return true;
}
void Rasterizer::ProcessDownloadImages() {
texture_cache.ProcessDownloadImages();
}
bool Rasterizer::IsMapped(VAddr addr, u64 size) {
if (size == 0) {
// There is no memory, so not mapped.

View File

@ -60,6 +60,7 @@ public:
u32 ReadDataFromGds(u32 gsd_offset);
bool InvalidateMemory(VAddr addr, u64 size);
bool ReadMemory(VAddr addr, u64 size);
void ProcessDownloadImages();
bool IsMapped(VAddr addr, u64 size);
void MapMemory(VAddr addr, u64 size);
void UnmapMemory(VAddr addr, u64 size);

View File

@ -87,18 +87,18 @@ ImageId TextureCache::GetNullImage(const vk::Format format) {
void TextureCache::ProcessDownloadImages() {
for (const ImageId image_id : download_images) {
DownloadImageMemory(image_id);
DownloadImageMemory(image_id, true);
}
download_images.clear();
}
void TextureCache::DownloadImageMemory(ImageId image_id) {
void TextureCache::DownloadImageMemory(ImageId image_id, bool sync) {
Image& image = slot_images[image_id];
if (False(image.flags & ImageFlagBits::GpuModified)) {
return;
}
auto& download_buffer = buffer_cache.GetUtilityBuffer(MemoryUsage::Download);
const u32 download_size = image.info.pitch * image.info.size.height *
const u32 download_size = image.info.pitch * image.info.size.height * image.info.size.depth *
image.info.resources.layers * (image.info.num_bits / 8);
ASSERT(download_size <= image.info.guest_size);
const auto [download, offset] = download_buffer.Map(download_size);
@ -116,7 +116,7 @@ void TextureCache::DownloadImageMemory(ImageId image_id) {
.layerCount = image.info.resources.layers,
},
.imageOffset = {0, 0, 0},
.imageExtent = {image.info.size.width, image.info.size.height, 1},
.imageExtent = {image.info.size.width, image.info.size.height, image.info.size.depth},
};
scheduler.EndRendering();
const auto cmdbuf = scheduler.CommandBuffer();
@ -124,11 +124,17 @@ void TextureCache::DownloadImageMemory(ImageId image_id) {
cmdbuf.copyImageToBuffer(image.GetImage(), vk::ImageLayout::eTransferSrcOptimal,
download_buffer.Handle(), image_download);
scheduler.DeferPriorityOperation(
[this, device_addr = image.info.guest_address, download, download_size] {
Core::Memory::Instance()->TryWriteBacking(std::bit_cast<u8*>(device_addr), download,
download_size);
});
const auto write_data = [this, device_addr = image.info.guest_address, download,
download_size] {
Core::Memory::Instance()->TryWriteBacking(std::bit_cast<u8*>(device_addr), download,
download_size);
};
if (sync) {
scheduler.Finish();
write_data();
} else {
scheduler.DeferPriorityOperation(write_data);
}
}
void TextureCache::MarkAsMaybeDirty(ImageId image_id, Image& image) {

View File

@ -272,7 +272,7 @@ private:
ImageId GetNullImage(vk::Format format);
/// Copies image memory back to CPU.
void DownloadImageMemory(ImageId image_id);
void DownloadImageMemory(ImageId image_id, bool sync = false);
/// Thread function for copying downloaded images out to CPU memory.
void DownloadedImagesThread(const std::stop_token& token);