mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-12-09 05:08:43 +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_)
|
AmdGpu::Liverpool* liverpool_)
|
||||||
: instance{instance_}, scheduler{scheduler_}, page_manager{this},
|
: instance{instance_}, scheduler{scheduler_}, page_manager{this},
|
||||||
buffer_cache{instance, scheduler, liverpool_, texture_cache, page_manager},
|
buffer_cache{instance, scheduler, liverpool_, texture_cache, page_manager},
|
||||||
texture_cache{instance, scheduler, buffer_cache, page_manager}, liverpool{liverpool_},
|
texture_cache{instance, scheduler, liverpool_, buffer_cache, page_manager},
|
||||||
memory{Core::Memory::Instance()}, pipeline_cache{instance, scheduler, liverpool} {
|
liverpool{liverpool_}, memory{Core::Memory::Instance()},
|
||||||
|
pipeline_cache{instance, scheduler, liverpool} {
|
||||||
if (!Config::nullGpu()) {
|
if (!Config::nullGpu()) {
|
||||||
liverpool->BindRasterizer(this);
|
liverpool->BindRasterizer(this);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/config.h"
|
#include "common/config.h"
|
||||||
#include "common/debug.h"
|
#include "common/debug.h"
|
||||||
|
#include "common/polyfill_thread.h"
|
||||||
#include "common/scope_exit.h"
|
#include "common/scope_exit.h"
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
#include "video_core/buffer_cache/buffer_cache.h"
|
#include "video_core/buffer_cache/buffer_cache.h"
|
||||||
@@ -22,9 +23,10 @@ static constexpr u64 PageShift = 12;
|
|||||||
static constexpr u64 NumFramesBeforeRemoval = 32;
|
static constexpr u64 NumFramesBeforeRemoval = 32;
|
||||||
|
|
||||||
TextureCache::TextureCache(const Vulkan::Instance& instance_, Vulkan::Scheduler& scheduler_,
|
TextureCache::TextureCache(const Vulkan::Instance& instance_, Vulkan::Scheduler& scheduler_,
|
||||||
BufferCache& buffer_cache_, PageManager& tracker_)
|
AmdGpu::Liverpool* liverpool_, BufferCache& buffer_cache_,
|
||||||
: instance{instance_}, scheduler{scheduler_}, buffer_cache{buffer_cache_}, tracker{tracker_},
|
PageManager& tracker_)
|
||||||
blit_helper{instance, scheduler},
|
: 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)} {
|
tile_manager{instance, scheduler, buffer_cache.GetUtilityBuffer(MemoryUsage::Stream)} {
|
||||||
// Create basic null image at fixed image ID.
|
// Create basic null image at fixed image ID.
|
||||||
const auto null_id = GetNullImage(vk::Format::eR8G8B8A8Unorm);
|
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),
|
std::max<u64>(std::min(device_local_memory - min_vacancy_critical, min_spacing_critical),
|
||||||
DEFAULT_CRITICAL_GC_MEMORY));
|
DEFAULT_CRITICAL_GC_MEMORY));
|
||||||
trigger_gc_memory = static_cast<u64>((device_local_memory - mem_threshold) / 2);
|
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;
|
TextureCache::~TextureCache() = default;
|
||||||
@@ -121,10 +126,34 @@ void TextureCache::DownloadImageMemory(ImageId image_id) {
|
|||||||
image.Transit(vk::ImageLayout::eTransferSrcOptimal, vk::AccessFlagBits2::eTransferRead, {});
|
image.Transit(vk::ImageLayout::eTransferSrcOptimal, vk::AccessFlagBits2::eTransferRead, {});
|
||||||
cmdbuf.copyImageToBuffer(image.image, vk::ImageLayout::eTransferSrcOptimal,
|
cmdbuf.copyImageToBuffer(image.image, vk::ImageLayout::eTransferSrcOptimal,
|
||||||
download_buffer.Handle(), image_download);
|
download_buffer.Handle(), image_download);
|
||||||
scheduler.DeferOperation([device_addr = image.info.guest_address, 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();
|
auto* memory = Core::Memory::Instance();
|
||||||
memory->TryWriteBacking(std::bit_cast<u8*>(device_addr), download, download_size);
|
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) {
|
void TextureCache::MarkAsMaybeDirty(ImageId image_id, Image& image) {
|
||||||
|
|||||||
@@ -17,6 +17,10 @@
|
|||||||
#include "video_core/texture_cache/sampler.h"
|
#include "video_core/texture_cache/sampler.h"
|
||||||
#include "video_core/texture_cache/tile_manager.h"
|
#include "video_core/texture_cache/tile_manager.h"
|
||||||
|
|
||||||
|
namespace AmdGpu {
|
||||||
|
struct Liverpool;
|
||||||
|
}
|
||||||
|
|
||||||
namespace VideoCore {
|
namespace VideoCore {
|
||||||
|
|
||||||
class BufferCache;
|
class BufferCache;
|
||||||
@@ -85,7 +89,7 @@ public:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
TextureCache(const Vulkan::Instance& instance, Vulkan::Scheduler& scheduler,
|
TextureCache(const Vulkan::Instance& instance, Vulkan::Scheduler& scheduler,
|
||||||
BufferCache& buffer_cache, PageManager& tracker);
|
AmdGpu::Liverpool* liverpool, BufferCache& buffer_cache, PageManager& tracker);
|
||||||
~TextureCache();
|
~TextureCache();
|
||||||
|
|
||||||
TileManager& GetTileManager() noexcept {
|
TileManager& GetTileManager() noexcept {
|
||||||
@@ -272,6 +276,9 @@ private:
|
|||||||
/// Copies image memory back to CPU.
|
/// Copies image memory back to CPU.
|
||||||
void DownloadImageMemory(ImageId image_id);
|
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
|
/// Create an image from the given parameters
|
||||||
[[nodiscard]] ImageId InsertImage(const ImageInfo& info, VAddr cpu_addr);
|
[[nodiscard]] ImageId InsertImage(const ImageInfo& info, VAddr cpu_addr);
|
||||||
|
|
||||||
@@ -308,6 +315,7 @@ private:
|
|||||||
private:
|
private:
|
||||||
const Vulkan::Instance& instance;
|
const Vulkan::Instance& instance;
|
||||||
Vulkan::Scheduler& scheduler;
|
Vulkan::Scheduler& scheduler;
|
||||||
|
AmdGpu::Liverpool* liverpool;
|
||||||
BufferCache& buffer_cache;
|
BufferCache& buffer_cache;
|
||||||
PageManager& tracker;
|
PageManager& tracker;
|
||||||
BlitHelper blit_helper;
|
BlitHelper blit_helper;
|
||||||
@@ -326,6 +334,17 @@ private:
|
|||||||
PageTable page_table;
|
PageTable page_table;
|
||||||
std::mutex mutex;
|
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 {
|
struct MetaDataInfo {
|
||||||
enum class Type {
|
enum class Type {
|
||||||
CMask,
|
CMask,
|
||||||
|
|||||||
Reference in New Issue
Block a user