mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-07-22 18:15:14 +00:00
config: Add readbacks config option
This commit is contained in:
parent
0b410a16ad
commit
53519aa8ca
@ -51,6 +51,7 @@ static bool isShowSplash = false;
|
|||||||
static std::string isSideTrophy = "right";
|
static std::string isSideTrophy = "right";
|
||||||
static bool isNullGpu = false;
|
static bool isNullGpu = false;
|
||||||
static bool shouldCopyGPUBuffers = false;
|
static bool shouldCopyGPUBuffers = false;
|
||||||
|
static bool readbacksEnabled = false;
|
||||||
static bool shouldDumpShaders = false;
|
static bool shouldDumpShaders = false;
|
||||||
static bool shouldPatchShaders = true;
|
static bool shouldPatchShaders = true;
|
||||||
static u32 vblankDivider = 1;
|
static u32 vblankDivider = 1;
|
||||||
@ -240,6 +241,10 @@ bool copyGPUCmdBuffers() {
|
|||||||
return shouldCopyGPUBuffers;
|
return shouldCopyGPUBuffers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool readbacks() {
|
||||||
|
return readbacksEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
bool dumpShaders() {
|
bool dumpShaders() {
|
||||||
return shouldDumpShaders;
|
return shouldDumpShaders;
|
||||||
}
|
}
|
||||||
@ -344,6 +349,10 @@ void setCopyGPUCmdBuffers(bool enable) {
|
|||||||
shouldCopyGPUBuffers = enable;
|
shouldCopyGPUBuffers = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setReadbacks(bool enable) {
|
||||||
|
readbacksEnabled = enable;
|
||||||
|
}
|
||||||
|
|
||||||
void setDumpShaders(bool enable) {
|
void setDumpShaders(bool enable) {
|
||||||
shouldDumpShaders = enable;
|
shouldDumpShaders = enable;
|
||||||
}
|
}
|
||||||
@ -586,6 +595,7 @@ void load(const std::filesystem::path& path) {
|
|||||||
screenHeight = toml::find_or<int>(gpu, "screenHeight", screenHeight);
|
screenHeight = toml::find_or<int>(gpu, "screenHeight", screenHeight);
|
||||||
isNullGpu = toml::find_or<bool>(gpu, "nullGpu", false);
|
isNullGpu = toml::find_or<bool>(gpu, "nullGpu", false);
|
||||||
shouldCopyGPUBuffers = toml::find_or<bool>(gpu, "copyGPUBuffers", false);
|
shouldCopyGPUBuffers = toml::find_or<bool>(gpu, "copyGPUBuffers", false);
|
||||||
|
readbacksEnabled = toml::find_or<bool>(gpu, "readbacks", false);
|
||||||
shouldDumpShaders = toml::find_or<bool>(gpu, "dumpShaders", false);
|
shouldDumpShaders = toml::find_or<bool>(gpu, "dumpShaders", false);
|
||||||
shouldPatchShaders = toml::find_or<bool>(gpu, "patchShaders", true);
|
shouldPatchShaders = toml::find_or<bool>(gpu, "patchShaders", true);
|
||||||
vblankDivider = toml::find_or<int>(gpu, "vblankDivider", 1);
|
vblankDivider = toml::find_or<int>(gpu, "vblankDivider", 1);
|
||||||
@ -735,6 +745,7 @@ void save(const std::filesystem::path& path) {
|
|||||||
data["GPU"]["screenHeight"] = screenHeight;
|
data["GPU"]["screenHeight"] = screenHeight;
|
||||||
data["GPU"]["nullGpu"] = isNullGpu;
|
data["GPU"]["nullGpu"] = isNullGpu;
|
||||||
data["GPU"]["copyGPUBuffers"] = shouldCopyGPUBuffers;
|
data["GPU"]["copyGPUBuffers"] = shouldCopyGPUBuffers;
|
||||||
|
data["GPU"]["readbacks"] = readbacksEnabled;
|
||||||
data["GPU"]["dumpShaders"] = shouldDumpShaders;
|
data["GPU"]["dumpShaders"] = shouldDumpShaders;
|
||||||
data["GPU"]["patchShaders"] = shouldPatchShaders;
|
data["GPU"]["patchShaders"] = shouldPatchShaders;
|
||||||
data["GPU"]["vblankDivider"] = vblankDivider;
|
data["GPU"]["vblankDivider"] = vblankDivider;
|
||||||
|
@ -45,6 +45,8 @@ bool nullGpu();
|
|||||||
void setNullGpu(bool enable);
|
void setNullGpu(bool enable);
|
||||||
bool copyGPUCmdBuffers();
|
bool copyGPUCmdBuffers();
|
||||||
void setCopyGPUCmdBuffers(bool enable);
|
void setCopyGPUCmdBuffers(bool enable);
|
||||||
|
bool readbacks();
|
||||||
|
void setReadbacks(bool enable);
|
||||||
bool dumpShaders();
|
bool dumpShaders();
|
||||||
void setDumpShaders(bool enable);
|
void setDumpShaders(bool enable);
|
||||||
u32 vblankDiv();
|
u32 vblankDiv();
|
||||||
|
@ -77,7 +77,7 @@ void Liverpool::ProcessCommands() {
|
|||||||
while (num_commands) {
|
while (num_commands) {
|
||||||
Common::UniqueFunction<void> callback{};
|
Common::UniqueFunction<void> callback{};
|
||||||
{
|
{
|
||||||
std::unique_lock lk{submit_mutex};
|
std::scoped_lock lk{submit_mutex};
|
||||||
callback = std::move(command_queue.front());
|
callback = std::move(command_queue.front());
|
||||||
command_queue.pop();
|
command_queue.pop();
|
||||||
--num_commands;
|
--num_commands;
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <coroutine>
|
#include <coroutine>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <semaphore>
|
||||||
#include <span>
|
#include <span>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -1512,11 +1513,29 @@ public:
|
|||||||
rasterizer = rasterizer_;
|
rasterizer = rasterizer_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendCommand(Common::UniqueFunction<void>&& func) {
|
template <bool wait_done = false>
|
||||||
std::scoped_lock lk{submit_mutex};
|
void SendCommand(auto&& func) {
|
||||||
command_queue.emplace(std::move(func));
|
if (std::this_thread::get_id() == gpu_id) {
|
||||||
++num_commands;
|
return func();
|
||||||
submit_cv.notify_one();
|
}
|
||||||
|
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() {
|
void ReserveCopyBufferSpace() {
|
||||||
@ -1542,7 +1561,6 @@ public:
|
|||||||
u32 tmp_dwords;
|
u32 tmp_dwords;
|
||||||
};
|
};
|
||||||
Common::SlotVector<AscQueueInfo> asc_queues{};
|
Common::SlotVector<AscQueueInfo> asc_queues{};
|
||||||
std::thread::id gpu_id;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Task {
|
struct Task {
|
||||||
@ -1628,6 +1646,7 @@ private:
|
|||||||
std::mutex submit_mutex;
|
std::mutex submit_mutex;
|
||||||
std::condition_variable_any submit_cv;
|
std::condition_variable_any submit_cv;
|
||||||
std::queue<Common::UniqueFunction<void>> command_queue{};
|
std::queue<Common::UniqueFunction<void>> command_queue{};
|
||||||
|
std::thread::id gpu_id;
|
||||||
int curr_qid{-1};
|
int curr_qid{-1};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <semaphore>
|
|
||||||
#include "common/alignment.h"
|
#include "common/alignment.h"
|
||||||
|
#include "common/config.h"
|
||||||
#include "common/debug.h"
|
#include "common/debug.h"
|
||||||
#include "common/scope_exit.h"
|
#include "common/scope_exit.h"
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
@ -136,25 +136,17 @@ void BufferCache::InvalidateMemory(VAddr device_addr, u64 size) {
|
|||||||
if (!IsRegionRegistered(device_addr, size)) {
|
if (!IsRegionRegistered(device_addr, size)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (memory_tracker->IsRegionGpuModified(device_addr, size)) {
|
if (Config::readbacks() && memory_tracker->IsRegionGpuModified(device_addr, size)) {
|
||||||
ReadMemory(device_addr, size);
|
ReadMemory(device_addr, size);
|
||||||
}
|
}
|
||||||
memory_tracker->MarkRegionAsCpuModified(device_addr, size);
|
memory_tracker->MarkRegionAsCpuModified(device_addr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BufferCache::ReadMemory(VAddr device_addr, u64 size) {
|
void BufferCache::ReadMemory(VAddr device_addr, u64 size) {
|
||||||
if (std::this_thread::get_id() != liverpool->gpu_id) {
|
liverpool->SendCommand<true>([this, device_addr, size] {
|
||||||
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 {
|
|
||||||
Buffer& buffer = slot_buffers[FindBuffer(device_addr, size)];
|
Buffer& buffer = slot_buffers[FindBuffer(device_addr, size)];
|
||||||
DownloadBufferMemory(buffer, device_addr, size);
|
DownloadBufferMemory(buffer, device_addr, size);
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void BufferCache::DownloadBufferMemory(Buffer& buffer, VAddr device_addr, u64 size) {
|
void BufferCache::DownloadBufferMemory(Buffer& buffer, VAddr device_addr, u64 size) {
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array>
|
|
||||||
#include "common/bit_array.h"
|
#include "common/bit_array.h"
|
||||||
#include "common/types.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 {
|
enum class Type {
|
||||||
CPU,
|
CPU,
|
||||||
GPU,
|
GPU,
|
||||||
Writeable,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
using RegionBits = Common::BitArray<NUM_PAGES_PER_REGION>;
|
using RegionBits = Common::BitArray<NUM_PAGES_PER_REGION>;
|
||||||
|
|
||||||
} // namespace VideoCore
|
} // namespace VideoCore
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include "common/config.h"
|
||||||
#include "common/div_ceil.h"
|
#include "common/div_ceil.h"
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
@ -47,29 +48,19 @@ public:
|
|||||||
|
|
||||||
template <Type type>
|
template <Type type>
|
||||||
RegionBits& GetRegionBits() noexcept {
|
RegionBits& GetRegionBits() noexcept {
|
||||||
static_assert(type != Type::Writeable);
|
|
||||||
if constexpr (type == Type::CPU) {
|
if constexpr (type == Type::CPU) {
|
||||||
return cpu;
|
return cpu;
|
||||||
} else if constexpr (type == Type::GPU) {
|
} else if constexpr (type == Type::GPU) {
|
||||||
return gpu;
|
return gpu;
|
||||||
} else if constexpr (type == Type::Writeable) {
|
|
||||||
return writeable;
|
|
||||||
} else {
|
|
||||||
static_assert(false, "Invalid type");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <Type type>
|
template <Type type>
|
||||||
const RegionBits& GetRegionBits() const noexcept {
|
const RegionBits& GetRegionBits() const noexcept {
|
||||||
static_assert(type != Type::Writeable);
|
|
||||||
if constexpr (type == Type::CPU) {
|
if constexpr (type == Type::CPU) {
|
||||||
return cpu;
|
return cpu;
|
||||||
} else if constexpr (type == Type::GPU) {
|
} else if constexpr (type == Type::GPU) {
|
||||||
return gpu;
|
return gpu;
|
||||||
} else if constexpr (type == Type::Writeable) {
|
|
||||||
return writeable;
|
|
||||||
} else {
|
|
||||||
static_assert(false, "Invalid type");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,7 +81,6 @@ public:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::scoped_lock lk{lock};
|
std::scoped_lock lk{lock};
|
||||||
static_assert(type != Type::Writeable);
|
|
||||||
|
|
||||||
RegionBits& bits = GetRegionBits<type>();
|
RegionBits& bits = GetRegionBits<type>();
|
||||||
if constexpr (enable) {
|
if constexpr (enable) {
|
||||||
@ -100,7 +90,7 @@ public:
|
|||||||
}
|
}
|
||||||
if constexpr (type == Type::CPU) {
|
if constexpr (type == Type::CPU) {
|
||||||
UpdateProtection<!enable, false>();
|
UpdateProtection<!enable, false>();
|
||||||
} else {
|
} else if (Config::readbacks()) {
|
||||||
UpdateProtection<enable, true>();
|
UpdateProtection<enable, true>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -124,7 +114,6 @@ public:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::scoped_lock lk{lock};
|
std::scoped_lock lk{lock};
|
||||||
static_assert(type != Type::Writeable);
|
|
||||||
|
|
||||||
RegionBits& bits = GetRegionBits<type>();
|
RegionBits& bits = GetRegionBits<type>();
|
||||||
RegionBits mask(bits, start_page, end_page);
|
RegionBits mask(bits, start_page, end_page);
|
||||||
@ -137,7 +126,7 @@ public:
|
|||||||
bits.UnsetRange(start_page, end_page);
|
bits.UnsetRange(start_page, end_page);
|
||||||
if constexpr (type == Type::CPU) {
|
if constexpr (type == Type::CPU) {
|
||||||
UpdateProtection<true, false>();
|
UpdateProtection<true, false>();
|
||||||
} else {
|
} else if (Config::readbacks()) {
|
||||||
UpdateProtection<false, true>();
|
UpdateProtection<false, true>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -159,7 +148,6 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::scoped_lock lk{lock};
|
std::scoped_lock lk{lock};
|
||||||
static_assert(type != Type::Writeable);
|
|
||||||
|
|
||||||
const RegionBits& bits = GetRegionBits<type>();
|
const RegionBits& bits = GetRegionBits<type>();
|
||||||
RegionBits test(bits, start_page, end_page);
|
RegionBits test(bits, start_page, end_page);
|
||||||
|
Loading…
Reference in New Issue
Block a user