mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-12-08 20:58:41 +00:00
texture_cache: Make sure that readback images are downloaded in time (#3593)
This commit is contained in:
@@ -34,8 +34,9 @@ Rasterizer::Rasterizer(const Instance& instance_, Scheduler& scheduler_,
|
||||
AmdGpu::Liverpool* liverpool_)
|
||||
: instance{instance_}, scheduler{scheduler_}, page_manager{this},
|
||||
buffer_cache{instance, scheduler, liverpool_, texture_cache, page_manager},
|
||||
texture_cache{instance, scheduler, buffer_cache, page_manager}, liverpool{liverpool_},
|
||||
memory{Core::Memory::Instance()}, pipeline_cache{instance, scheduler, liverpool} {
|
||||
texture_cache{instance, scheduler, liverpool_, buffer_cache, page_manager},
|
||||
liverpool{liverpool_}, memory{Core::Memory::Instance()},
|
||||
pipeline_cache{instance, scheduler, liverpool} {
|
||||
if (!Config::nullGpu()) {
|
||||
liverpool->BindRasterizer(this);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/config.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/polyfill_thread.h"
|
||||
#include "common/scope_exit.h"
|
||||
#include "core/memory.h"
|
||||
#include "video_core/buffer_cache/buffer_cache.h"
|
||||
@@ -22,9 +23,10 @@ static constexpr u64 PageShift = 12;
|
||||
static constexpr u64 NumFramesBeforeRemoval = 32;
|
||||
|
||||
TextureCache::TextureCache(const Vulkan::Instance& instance_, Vulkan::Scheduler& scheduler_,
|
||||
BufferCache& buffer_cache_, PageManager& tracker_)
|
||||
: instance{instance_}, scheduler{scheduler_}, buffer_cache{buffer_cache_}, tracker{tracker_},
|
||||
blit_helper{instance, scheduler},
|
||||
AmdGpu::Liverpool* liverpool_, BufferCache& buffer_cache_,
|
||||
PageManager& tracker_)
|
||||
: instance{instance_}, scheduler{scheduler_}, liverpool{liverpool_},
|
||||
buffer_cache{buffer_cache_}, tracker{tracker_}, blit_helper{instance, scheduler},
|
||||
tile_manager{instance, scheduler, buffer_cache.GetUtilityBuffer(MemoryUsage::Stream)} {
|
||||
// Create basic null image at fixed image ID.
|
||||
const auto null_id = GetNullImage(vk::Format::eR8G8B8A8Unorm);
|
||||
@@ -51,6 +53,9 @@ TextureCache::TextureCache(const Vulkan::Instance& instance_, Vulkan::Scheduler&
|
||||
std::max<u64>(std::min(device_local_memory - min_vacancy_critical, min_spacing_critical),
|
||||
DEFAULT_CRITICAL_GC_MEMORY));
|
||||
trigger_gc_memory = static_cast<u64>((device_local_memory - mem_threshold) / 2);
|
||||
|
||||
downloaded_images_thread =
|
||||
std::jthread([&](const std::stop_token& token) { DownloadedImagesThread(token); });
|
||||
}
|
||||
|
||||
TextureCache::~TextureCache() = default;
|
||||
@@ -121,10 +126,34 @@ void TextureCache::DownloadImageMemory(ImageId image_id) {
|
||||
image.Transit(vk::ImageLayout::eTransferSrcOptimal, vk::AccessFlagBits2::eTransferRead, {});
|
||||
cmdbuf.copyImageToBuffer(image.image, vk::ImageLayout::eTransferSrcOptimal,
|
||||
download_buffer.Handle(), image_download);
|
||||
scheduler.DeferOperation([device_addr = image.info.guest_address, download, download_size] {
|
||||
auto* memory = Core::Memory::Instance();
|
||||
memory->TryWriteBacking(std::bit_cast<u8*>(device_addr), download, download_size);
|
||||
});
|
||||
|
||||
{
|
||||
std::unique_lock lock(downloaded_images_mutex);
|
||||
downloaded_images_queue.emplace(scheduler.CurrentTick(), image.info.guest_address, download,
|
||||
download_size);
|
||||
downloaded_images_cv.notify_one();
|
||||
}
|
||||
}
|
||||
|
||||
void TextureCache::DownloadedImagesThread(const std::stop_token& token) {
|
||||
auto* memory = Core::Memory::Instance();
|
||||
while (!token.stop_requested()) {
|
||||
DownloadedImage image;
|
||||
{
|
||||
std::unique_lock lock{downloaded_images_mutex};
|
||||
Common::CondvarWait(downloaded_images_cv, lock, token,
|
||||
[this] { return !downloaded_images_queue.empty(); });
|
||||
if (token.stop_requested()) {
|
||||
break;
|
||||
}
|
||||
image = downloaded_images_queue.front();
|
||||
downloaded_images_queue.pop();
|
||||
}
|
||||
|
||||
scheduler.GetMasterSemaphore()->Wait(image.tick);
|
||||
memory->TryWriteBacking(std::bit_cast<u8*>(image.device_addr), image.download,
|
||||
image.download_size);
|
||||
}
|
||||
}
|
||||
|
||||
void TextureCache::MarkAsMaybeDirty(ImageId image_id, Image& image) {
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
#include "video_core/texture_cache/sampler.h"
|
||||
#include "video_core/texture_cache/tile_manager.h"
|
||||
|
||||
namespace AmdGpu {
|
||||
struct Liverpool;
|
||||
}
|
||||
|
||||
namespace VideoCore {
|
||||
|
||||
class BufferCache;
|
||||
@@ -85,7 +89,7 @@ public:
|
||||
|
||||
public:
|
||||
TextureCache(const Vulkan::Instance& instance, Vulkan::Scheduler& scheduler,
|
||||
BufferCache& buffer_cache, PageManager& tracker);
|
||||
AmdGpu::Liverpool* liverpool, BufferCache& buffer_cache, PageManager& tracker);
|
||||
~TextureCache();
|
||||
|
||||
TileManager& GetTileManager() noexcept {
|
||||
@@ -272,6 +276,9 @@ private:
|
||||
/// Copies image memory back to CPU.
|
||||
void DownloadImageMemory(ImageId image_id);
|
||||
|
||||
/// Thread function for copying downloaded images out to CPU memory.
|
||||
void DownloadedImagesThread(const std::stop_token& token);
|
||||
|
||||
/// Create an image from the given parameters
|
||||
[[nodiscard]] ImageId InsertImage(const ImageInfo& info, VAddr cpu_addr);
|
||||
|
||||
@@ -308,6 +315,7 @@ private:
|
||||
private:
|
||||
const Vulkan::Instance& instance;
|
||||
Vulkan::Scheduler& scheduler;
|
||||
AmdGpu::Liverpool* liverpool;
|
||||
BufferCache& buffer_cache;
|
||||
PageManager& tracker;
|
||||
BlitHelper blit_helper;
|
||||
@@ -326,6 +334,17 @@ private:
|
||||
PageTable page_table;
|
||||
std::mutex mutex;
|
||||
|
||||
struct DownloadedImage {
|
||||
u64 tick;
|
||||
VAddr device_addr;
|
||||
void* download;
|
||||
size_t download_size;
|
||||
};
|
||||
std::queue<DownloadedImage> downloaded_images_queue;
|
||||
std::mutex downloaded_images_mutex;
|
||||
std::condition_variable_any downloaded_images_cv;
|
||||
std::jthread downloaded_images_thread;
|
||||
|
||||
struct MetaDataInfo {
|
||||
enum class Type {
|
||||
CMask,
|
||||
|
||||
Reference in New Issue
Block a user