diff --git a/src/common/config.cpp b/src/common/config.cpp index 9c316949a..0b5f11200 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -51,6 +51,7 @@ static bool isShowSplash = false; static std::string isSideTrophy = "right"; static bool isNullGpu = false; static bool shouldCopyGPUBuffers = false; +static bool readbacksEnabled = false; static bool shouldDumpShaders = false; static bool shouldPatchShaders = true; static u32 vblankDivider = 1; @@ -240,6 +241,10 @@ bool copyGPUCmdBuffers() { return shouldCopyGPUBuffers; } +bool readbacks() { + return readbacksEnabled; +} + bool dumpShaders() { return shouldDumpShaders; } @@ -344,6 +349,10 @@ void setCopyGPUCmdBuffers(bool enable) { shouldCopyGPUBuffers = enable; } +void setReadbacks(bool enable) { + readbacksEnabled = enable; +} + void setDumpShaders(bool enable) { shouldDumpShaders = enable; } @@ -586,6 +595,7 @@ void load(const std::filesystem::path& path) { screenHeight = toml::find_or(gpu, "screenHeight", screenHeight); isNullGpu = toml::find_or(gpu, "nullGpu", false); shouldCopyGPUBuffers = toml::find_or(gpu, "copyGPUBuffers", false); + readbacksEnabled = toml::find_or(gpu, "readbacks", false); shouldDumpShaders = toml::find_or(gpu, "dumpShaders", false); shouldPatchShaders = toml::find_or(gpu, "patchShaders", true); vblankDivider = toml::find_or(gpu, "vblankDivider", 1); @@ -735,6 +745,7 @@ void save(const std::filesystem::path& path) { data["GPU"]["screenHeight"] = screenHeight; data["GPU"]["nullGpu"] = isNullGpu; data["GPU"]["copyGPUBuffers"] = shouldCopyGPUBuffers; + data["GPU"]["readbacks"] = readbacksEnabled; data["GPU"]["dumpShaders"] = shouldDumpShaders; data["GPU"]["patchShaders"] = shouldPatchShaders; data["GPU"]["vblankDivider"] = vblankDivider; diff --git a/src/common/config.h b/src/common/config.h index 38114983f..219461e7e 100644 --- a/src/common/config.h +++ b/src/common/config.h @@ -45,6 +45,8 @@ bool nullGpu(); void setNullGpu(bool enable); bool copyGPUCmdBuffers(); void setCopyGPUCmdBuffers(bool enable); +bool readbacks(); +void setReadbacks(bool enable); bool dumpShaders(); void setDumpShaders(bool enable); u32 vblankDiv(); diff --git a/src/video_core/amdgpu/liverpool.cpp b/src/video_core/amdgpu/liverpool.cpp index 0e1b1b39a..9b8c28b66 100644 --- a/src/video_core/amdgpu/liverpool.cpp +++ b/src/video_core/amdgpu/liverpool.cpp @@ -77,7 +77,7 @@ void Liverpool::ProcessCommands() { while (num_commands) { Common::UniqueFunction callback{}; { - std::unique_lock lk{submit_mutex}; + std::scoped_lock lk{submit_mutex}; callback = std::move(command_queue.front()); command_queue.pop(); --num_commands; diff --git a/src/video_core/amdgpu/liverpool.h b/src/video_core/amdgpu/liverpool.h index 809a48155..0613823ab 100644 --- a/src/video_core/amdgpu/liverpool.h +++ b/src/video_core/amdgpu/liverpool.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -1512,11 +1513,29 @@ public: rasterizer = rasterizer_; } - void SendCommand(Common::UniqueFunction&& func) { - std::scoped_lock lk{submit_mutex}; - command_queue.emplace(std::move(func)); - ++num_commands; - submit_cv.notify_one(); + template + void SendCommand(auto&& func) { + if (std::this_thread::get_id() == gpu_id) { + return func(); + } + if constexpr (wait_done) { + std::binary_semaphore sem{0}; + { + std::scoped_lock lk{submit_mutex}; + command_queue.emplace([&sem, &func] { + func(); + sem.release(); + }); + ++num_commands; + submit_cv.notify_one(); + } + sem.acquire(); + } else { + std::scoped_lock lk{submit_mutex}; + command_queue.emplace(std::move(func)); + ++num_commands; + submit_cv.notify_one(); + } } void ReserveCopyBufferSpace() { @@ -1542,7 +1561,6 @@ public: u32 tmp_dwords; }; Common::SlotVector asc_queues{}; - std::thread::id gpu_id; private: struct Task { @@ -1628,6 +1646,7 @@ private: std::mutex submit_mutex; std::condition_variable_any submit_cv; std::queue> command_queue{}; + std::thread::id gpu_id; int curr_qid{-1}; }; diff --git a/src/video_core/buffer_cache/buffer_cache.cpp b/src/video_core/buffer_cache/buffer_cache.cpp index ea683ad15..4a88c7ed4 100644 --- a/src/video_core/buffer_cache/buffer_cache.cpp +++ b/src/video_core/buffer_cache/buffer_cache.cpp @@ -2,8 +2,8 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include -#include #include "common/alignment.h" +#include "common/config.h" #include "common/debug.h" #include "common/scope_exit.h" #include "common/types.h" @@ -136,25 +136,17 @@ void BufferCache::InvalidateMemory(VAddr device_addr, u64 size) { if (!IsRegionRegistered(device_addr, size)) { return; } - if (memory_tracker->IsRegionGpuModified(device_addr, size)) { + if (Config::readbacks() && memory_tracker->IsRegionGpuModified(device_addr, size)) { ReadMemory(device_addr, size); } memory_tracker->MarkRegionAsCpuModified(device_addr, size); } void BufferCache::ReadMemory(VAddr device_addr, u64 size) { - if (std::this_thread::get_id() != liverpool->gpu_id) { - std::binary_semaphore command_wait{0}; - liverpool->SendCommand([this, &command_wait, device_addr, size] { - Buffer& buffer = slot_buffers[FindBuffer(device_addr, size)]; - DownloadBufferMemory(buffer, device_addr, size); - command_wait.release(); - }); - command_wait.acquire(); - } else { + liverpool->SendCommand([this, device_addr, size] { Buffer& buffer = slot_buffers[FindBuffer(device_addr, size)]; DownloadBufferMemory(buffer, device_addr, size); - } + }); } void BufferCache::DownloadBufferMemory(Buffer& buffer, VAddr device_addr, u64 size) { diff --git a/src/video_core/buffer_cache/region_definitions.h b/src/video_core/buffer_cache/region_definitions.h index f035704d9..76e7ee263 100644 --- a/src/video_core/buffer_cache/region_definitions.h +++ b/src/video_core/buffer_cache/region_definitions.h @@ -3,7 +3,6 @@ #pragma once -#include #include "common/bit_array.h" #include "common/types.h" @@ -20,9 +19,8 @@ constexpr u64 NUM_PAGES_PER_REGION = TRACKER_HIGHER_PAGE_SIZE / TRACKER_BYTES_PE enum class Type { CPU, GPU, - Writeable, }; using RegionBits = Common::BitArray; -} // namespace VideoCore \ No newline at end of file +} // namespace VideoCore diff --git a/src/video_core/buffer_cache/region_manager.h b/src/video_core/buffer_cache/region_manager.h index 802ca8139..894809cd5 100644 --- a/src/video_core/buffer_cache/region_manager.h +++ b/src/video_core/buffer_cache/region_manager.h @@ -4,6 +4,7 @@ #pragma once #include +#include "common/config.h" #include "common/div_ceil.h" #ifdef __linux__ @@ -47,29 +48,19 @@ public: template RegionBits& GetRegionBits() noexcept { - static_assert(type != Type::Writeable); if constexpr (type == Type::CPU) { return cpu; } else if constexpr (type == Type::GPU) { return gpu; - } else if constexpr (type == Type::Writeable) { - return writeable; - } else { - static_assert(false, "Invalid type"); } } template const RegionBits& GetRegionBits() const noexcept { - static_assert(type != Type::Writeable); if constexpr (type == Type::CPU) { return cpu; } else if constexpr (type == Type::GPU) { return gpu; - } else if constexpr (type == Type::Writeable) { - return writeable; - } else { - static_assert(false, "Invalid type"); } } @@ -90,7 +81,6 @@ public: return; } std::scoped_lock lk{lock}; - static_assert(type != Type::Writeable); RegionBits& bits = GetRegionBits(); if constexpr (enable) { @@ -100,7 +90,7 @@ public: } if constexpr (type == Type::CPU) { UpdateProtection(); - } else { + } else if (Config::readbacks()) { UpdateProtection(); } } @@ -124,7 +114,6 @@ public: return; } std::scoped_lock lk{lock}; - static_assert(type != Type::Writeable); RegionBits& bits = GetRegionBits(); RegionBits mask(bits, start_page, end_page); @@ -137,7 +126,7 @@ public: bits.UnsetRange(start_page, end_page); if constexpr (type == Type::CPU) { UpdateProtection(); - } else { + } else if (Config::readbacks()) { UpdateProtection(); } } @@ -159,7 +148,6 @@ public: return false; } std::scoped_lock lk{lock}; - static_assert(type != Type::Writeable); const RegionBits& bits = GetRegionBits(); RegionBits test(bits, start_page, end_page);