Compare commits

..

1 Commits

Author SHA1 Message Date
The-Little-Wolf 56515d796b
Merge 85b2e956a7 into 55bbb28a80 2025-01-17 10:36:01 +01:00
6 changed files with 50 additions and 65 deletions

View File

@ -31,6 +31,7 @@
#include "xenia/cpu/processor.h" #include "xenia/cpu/processor.h"
#include "xenia/emulator.h" #include "xenia/emulator.h"
#include "xenia/gpu/command_processor.h" #include "xenia/gpu/command_processor.h"
#include "xenia/gpu/d3d12/d3d12_command_processor.h"
#include "xenia/gpu/graphics_system.h" #include "xenia/gpu/graphics_system.h"
#include "xenia/hid/input_system.h" #include "xenia/hid/input_system.h"
#include "xenia/kernel/xam/profile_manager.h" #include "xenia/kernel/xam/profile_manager.h"
@ -57,9 +58,7 @@ DECLARE_bool(guide_button);
DECLARE_bool(clear_memory_page_state); DECLARE_bool(clear_memory_page_state);
DECLARE_bool(readback_resolve); DECLARE_bool(d3d12_readback_resolve);
DECLARE_bool(readback_memexport);
DEFINE_bool(fullscreen, false, "Whether to launch the emulator in fullscreen.", DEFINE_bool(fullscreen, false, "Whether to launch the emulator in fullscreen.",
"Display"); "Display");
@ -1675,7 +1674,7 @@ EmulatorWindow::ControllerHotKey EmulatorWindow::ProcessControllerHotkey(
} }
} break; } break;
case ButtonFunctions::ClearMemoryPageState: case ButtonFunctions::ClearMemoryPageState:
ToggleGPUSetting(GPUSetting::ClearMemoryPageState); ToggleGPUSetting(gpu_cvar::ClearMemoryPageState);
// Assume the user wants ClearCaches as well // Assume the user wants ClearCaches as well
if (cvars::clear_memory_page_state) { if (cvars::clear_memory_page_state) {
@ -1690,10 +1689,10 @@ EmulatorWindow::ControllerHotKey EmulatorWindow::ProcessControllerHotkey(
xe::threading::Sleep(delay); xe::threading::Sleep(delay);
break; break;
case ButtonFunctions::ReadbackResolve: case ButtonFunctions::ReadbackResolve:
ToggleGPUSetting(GPUSetting::ReadbackResolve); ToggleGPUSetting(gpu_cvar::ReadbackResolve);
notificationTitle = "Toggle Readback Resolve"; notificationTitle = "Toggle Readback Resolve";
notificationDesc = cvars::readback_resolve ? "Enabled" : "Disabled"; notificationDesc = cvars::d3d12_readback_resolve ? "Enabled" : "Disabled";
// Extra Sleep // Extra Sleep
xe::threading::Sleep(delay); xe::threading::Sleep(delay);
@ -1863,17 +1862,15 @@ void EmulatorWindow::GamepadHotKeys() {
} }
} }
void EmulatorWindow::ToggleGPUSetting(gpu::GPUSetting setting) { void EmulatorWindow::ToggleGPUSetting(gpu_cvar value) {
switch (setting) { switch (value) {
case GPUSetting::ClearMemoryPageState: case gpu_cvar::ClearMemoryPageState:
SaveGPUSetting(GPUSetting::ClearMemoryPageState, CommonSaveGPUSetting(CommonGPUSetting::ClearMemoryPageState,
!cvars::clear_memory_page_state); !cvars::clear_memory_page_state);
break; break;
case GPUSetting::ReadbackResolve: case gpu_cvar::ReadbackResolve:
SaveGPUSetting(GPUSetting::ReadbackResolve, !cvars::readback_resolve); D3D12SaveGPUSetting(D3D12GPUSetting::ReadbackResolve,
break; !cvars::d3d12_readback_resolve);
case GPUSetting::ReadbackMemexport:
SaveGPUSetting(GPUSetting::ReadbackMemexport, !cvars::readback_memexport);
break; break;
} }
} }
@ -1918,7 +1915,7 @@ void EmulatorWindow::DisplayHotKeysConfig() {
msg += "\n"; msg += "\n";
msg += "Readback Resolve: " + msg += "Readback Resolve: " +
xe::string_util::BoolToString(cvars::readback_resolve); xe::string_util::BoolToString(cvars::d3d12_readback_resolve);
msg += "\n"; msg += "\n";
msg += "Clear Memory Page State: " + msg += "Clear Memory Page State: " +

View File

@ -112,6 +112,11 @@ class EmulatorWindow {
Unknown Unknown
}; };
enum class gpu_cvar {
ClearMemoryPageState,
ReadbackResolve,
};
class ControllerHotKey { class ControllerHotKey {
public: public:
// If true the hotkey can be activated while a title is running, otherwise // If true the hotkey can be activated while a title is running, otherwise
@ -230,7 +235,7 @@ class EmulatorWindow {
void VibrateController(xe::hid::InputSystem* input_sys, uint32_t user_index, void VibrateController(xe::hid::InputSystem* input_sys, uint32_t user_index,
bool vibrate = true); bool vibrate = true);
void GamepadHotKeys(); void GamepadHotKeys();
void ToggleGPUSetting(gpu::GPUSetting setting); void ToggleGPUSetting(gpu_cvar index);
void DisplayHotKeysConfig(); void DisplayHotKeysConfig();
static std::string CanonicalizeFileExtension( static std::string CanonicalizeFileExtension(

View File

@ -402,7 +402,7 @@ class Timer : public WaitHandle {
virtual bool Cancel() = 0; virtual bool Cancel() = 0;
}; };
#if XE_PLATFORM_WIN32 #if XE_PLATFORM_WINDOWS
struct ThreadPriority { struct ThreadPriority {
static const int32_t kLowest = -2; static const int32_t kLowest = -2;
static const int32_t kBelowNormal = -1; static const int32_t kBelowNormal = -1;

View File

@ -50,52 +50,17 @@ DEFINE_bool(clear_memory_page_state, false,
"for 'Team Ninja' Games to fix missing character models)", "for 'Team Ninja' Games to fix missing character models)",
"GPU"); "GPU");
DEFINE_bool(
readback_resolve, false,
"[D3D12 Only] Read render-to-texture results on the CPU. This may be "
"needed in some games, for instance, for screenshots in saved games, but "
"causes mid-frame synchronization, so it has a huge performance impact.",
"GPU");
DEFINE_bool(
readback_memexport, false,
"[D3D12 Only] Read data written by memory export in shaders on the CPU. "
"This may be needed in some games (but many only access exported data on "
"the GPU, and this flag isn't needed to handle such behavior), but causes "
"mid-frame synchronization, so it has a huge performance impact.",
"GPU");
namespace xe { namespace xe {
namespace gpu { namespace gpu {
// This should be written completely differently with support for different void CommonSaveGPUSetting(CommonGPUSetting setting, uint64_t value) {
// types.
void SaveGPUSetting(GPUSetting setting, uint64_t value) {
switch (setting) { switch (setting) {
case GPUSetting::ClearMemoryPageState: case CommonGPUSetting::ClearMemoryPageState:
OVERRIDE_bool(clear_memory_page_state, static_cast<bool>(value)); OVERRIDE_bool(clear_memory_page_state, (bool)value);
break;
case GPUSetting::ReadbackResolve:
OVERRIDE_bool(readback_resolve, static_cast<bool>(value));
break;
case GPUSetting::ReadbackMemexport:
OVERRIDE_bool(readback_memexport, static_cast<bool>(value));
break; break;
} }
} }
bool GetGPUSetting(GPUSetting setting) {
switch (setting) {
case GPUSetting::ClearMemoryPageState:
return cvars::clear_memory_page_state;
case GPUSetting::ReadbackResolve:
return cvars::readback_resolve;
case GPUSetting::ReadbackMemexport:
return cvars::readback_memexport;
}
return false;
}
using namespace xe::gpu::xenos; using namespace xe::gpu::xenos;
CommandProcessor::CommandProcessor(GraphicsSystem* graphics_system, CommandProcessor::CommandProcessor(GraphicsSystem* graphics_system,

View File

@ -33,14 +33,11 @@ class ByteStream;
namespace gpu { namespace gpu {
enum class GPUSetting { enum class CommonGPUSetting {
ClearMemoryPageState, ClearMemoryPageState,
ReadbackResolve,
ReadbackMemexport
}; };
void SaveGPUSetting(GPUSetting setting, uint64_t value); void CommonSaveGPUSetting(CommonGPUSetting setting, uint64_t value);
bool GetGPUSetting(GPUSetting setting);
class GraphicsSystem; class GraphicsSystem;
class Shader; class Shader;

View File

@ -32,7 +32,19 @@ DEFINE_bool(d3d12_bindless, true,
"Use bindless resources where available - may improve performance, " "Use bindless resources where available - may improve performance, "
"but may make debugging more complicated.", "but may make debugging more complicated.",
"D3D12"); "D3D12");
DEFINE_bool(d3d12_readback_memexport, false,
"Read data written by memory export in shaders on the CPU. This "
"may be needed in some games (but many only access exported data "
"on the GPU, and this flag isn't needed to handle such behavior), "
"but causes mid-frame synchronization, so it has a huge "
"performance impact.",
"D3D12");
DEFINE_bool(d3d12_readback_resolve, false,
"Read render-to-texture results on the CPU. This may be needed in "
"some games, for instance, for screenshots in saved games, but "
"causes mid-frame synchronization, so it has a huge performance "
"impact.",
"D3D12");
DEFINE_bool(d3d12_submit_on_primary_buffer_end, true, DEFINE_bool(d3d12_submit_on_primary_buffer_end, true,
"Submit the command list when a PM4 primary buffer ends if it's " "Submit the command list when a PM4 primary buffer ends if it's "
"possible to submit immediately to try to reduce frame latency.", "possible to submit immediately to try to reduce frame latency.",
@ -42,6 +54,15 @@ DECLARE_bool(clear_memory_page_state);
namespace xe { namespace xe {
namespace gpu { namespace gpu {
void D3D12SaveGPUSetting(D3D12GPUSetting setting, uint64_t value) {
switch (setting) {
case D3D12GPUSetting::ReadbackResolve:
OVERRIDE_bool(d3d12_readback_resolve, (bool)value);
break;
}
}
namespace d3d12 { namespace d3d12 {
// Generated with `xb buildshaders`. // Generated with `xb buildshaders`.
@ -2990,7 +3011,7 @@ bool D3D12CommandProcessor::IssueDraw(xenos::PrimitiveType primitive_type,
memexport_range.base_address_dwords << 2, memexport_range.size_bytes, memexport_range.base_address_dwords << 2, memexport_range.size_bytes,
false); false);
} }
if (GetGPUSetting(GPUSetting::ReadbackResolve)) { if (cvars::d3d12_readback_memexport) {
// Read the exported data on the CPU. // Read the exported data on the CPU.
uint32_t memexport_total_size = 0; uint32_t memexport_total_size = 0;
for (const draw_util::MemExportRange& memexport_range : for (const draw_util::MemExportRange& memexport_range :
@ -3070,7 +3091,7 @@ bool D3D12CommandProcessor::IssueCopy() {
if (!BeginSubmission(true)) { if (!BeginSubmission(true)) {
return false; return false;
} }
if (!GetGPUSetting(GPUSetting::ReadbackResolve)) { if (!cvars::d3d12_readback_resolve) {
uint32_t written_address, written_length; uint32_t written_address, written_length;
return render_target_cache_->Resolve(*memory_, *shared_memory_, return render_target_cache_->Resolve(*memory_, *shared_memory_,
*texture_cache_, written_address, *texture_cache_, written_address,