Settings: Add option for enabling GPU-based validation

This commit is contained in:
Stenzek 2025-03-30 23:20:39 +10:00
parent 049ec4af90
commit b798d8f1aa
No known key found for this signature in database
9 changed files with 80 additions and 43 deletions

View File

@ -6434,6 +6434,11 @@ void FullscreenUI::DrawAdvancedSettingsPage()
FSUI_CSTR("Enable debugging when supported by the host's renderer API. Only for developer use."), FSUI_CSTR("Enable debugging when supported by the host's renderer API. Only for developer use."),
"GPU", "UseDebugDevice", false); "GPU", "UseDebugDevice", false);
DrawToggleSetting(
bsi, FSUI_CSTR("Enable GPU-Based Validation"),
FSUI_CSTR("Enable GPU-based validation when supported by the host's renderer API. Only for developer use."), "GPU",
"UseGPUBasedValidation", false);
DrawToggleSetting( DrawToggleSetting(
bsi, FSUI_CSTR("Load Devices From Save States"), bsi, FSUI_CSTR("Load Devices From Save States"),
FSUI_CSTR("When enabled, memory cards and controllers will be overwritten when save states are loaded."), "Main", FSUI_CSTR("When enabled, memory cards and controllers will be overwritten when save states are loaded."), "Main",
@ -9202,6 +9207,8 @@ TRANSLATE_NOOP("FullscreenUI", "Enable Achievements");
TRANSLATE_NOOP("FullscreenUI", "Enable Cheats"); TRANSLATE_NOOP("FullscreenUI", "Enable Cheats");
TRANSLATE_NOOP("FullscreenUI", "Enable Discord Presence"); TRANSLATE_NOOP("FullscreenUI", "Enable Discord Presence");
TRANSLATE_NOOP("FullscreenUI", "Enable Fast Boot"); TRANSLATE_NOOP("FullscreenUI", "Enable Fast Boot");
TRANSLATE_NOOP("FullscreenUI", "Enable GPU-Based Validation");
TRANSLATE_NOOP("FullscreenUI", "Enable GPU-based validation when supported by the host's renderer API. Only for developer use.");
TRANSLATE_NOOP("FullscreenUI", "Enable In-Game Overlays"); TRANSLATE_NOOP("FullscreenUI", "Enable In-Game Overlays");
TRANSLATE_NOOP("FullscreenUI", "Enable Overclocking"); TRANSLATE_NOOP("FullscreenUI", "Enable Overclocking");
TRANSLATE_NOOP("FullscreenUI", "Enable Post Processing"); TRANSLATE_NOOP("FullscreenUI", "Enable Post Processing");

View File

@ -621,7 +621,7 @@ bool GPUThread::CreateDeviceOnThread(RenderAPI api, bool fullscreen, bool clear_
if (g_gpu_settings.gpu_disable_compressed_textures) if (g_gpu_settings.gpu_disable_compressed_textures)
disabled_features |= GPUDevice::FEATURE_MASK_COMPRESSED_TEXTURES; disabled_features |= GPUDevice::FEATURE_MASK_COMPRESSED_TEXTURES;
// Don't dump shaders on debug builds for Android, users will complain about storage... // Don't dump shaders on debug builds for Android, users will complain about storage...
#if !defined(__ANDROID__) || defined(_DEBUG) #if !defined(__ANDROID__) || defined(_DEBUG)
const std::string_view shader_dump_directory(EmuFolders::DataRoot); const std::string_view shader_dump_directory(EmuFolders::DataRoot);
#else #else
@ -636,9 +636,9 @@ bool GPUThread::CreateDeviceOnThread(RenderAPI api, bool fullscreen, bool clear_
Host::GetStringSettingValue("GPU", "Adapter"), static_cast<GPUDevice::FeatureMask>(disabled_features), Host::GetStringSettingValue("GPU", "Adapter"), static_cast<GPUDevice::FeatureMask>(disabled_features),
shader_dump_directory, shader_dump_directory,
g_gpu_settings.gpu_disable_shader_cache ? std::string_view() : std::string_view(EmuFolders::Cache), g_gpu_settings.gpu_disable_shader_cache ? std::string_view() : std::string_view(EmuFolders::Cache),
SHADER_CACHE_VERSION, g_gpu_settings.gpu_use_debug_device, wi.value(), s_state.requested_vsync, SHADER_CACHE_VERSION, g_gpu_settings.gpu_use_debug_device, g_gpu_settings.gpu_use_debug_device_gpu_validation,
s_state.requested_allow_present_throttle, fullscreen_mode.has_value() ? &fullscreen_mode.value() : nullptr, wi.value(), s_state.requested_vsync, s_state.requested_allow_present_throttle,
exclusive_fullscreen_control, &create_error)) fullscreen_mode.has_value() ? &fullscreen_mode.value() : nullptr, exclusive_fullscreen_control, &create_error))
{ {
ERROR_LOG("Failed to create GPU device: {}", create_error.GetDescription()); ERROR_LOG("Failed to create GPU device: {}", create_error.GetDescription());
if (g_gpu_device) if (g_gpu_device)

View File

@ -216,6 +216,7 @@ void Settings::Load(const SettingsInterface& si, const SettingsInterface& contro
gpu_automatic_resolution_scale = (gpu_resolution_scale == 0); gpu_automatic_resolution_scale = (gpu_resolution_scale == 0);
gpu_multisamples = static_cast<u8>(si.GetUIntValue("GPU", "Multisamples", 1u)); gpu_multisamples = static_cast<u8>(si.GetUIntValue("GPU", "Multisamples", 1u));
gpu_use_debug_device = si.GetBoolValue("GPU", "UseDebugDevice", false); gpu_use_debug_device = si.GetBoolValue("GPU", "UseDebugDevice", false);
gpu_use_debug_device_gpu_validation = si.GetBoolValue("GPU", "UseGPUBasedValidation", false);
gpu_disable_shader_cache = si.GetBoolValue("GPU", "DisableShaderCache", false); gpu_disable_shader_cache = si.GetBoolValue("GPU", "DisableShaderCache", false);
gpu_disable_dual_source_blend = si.GetBoolValue("GPU", "DisableDualSourceBlend", false); gpu_disable_dual_source_blend = si.GetBoolValue("GPU", "DisableDualSourceBlend", false);
gpu_disable_framebuffer_fetch = si.GetBoolValue("GPU", "DisableFramebufferFetch", false); gpu_disable_framebuffer_fetch = si.GetBoolValue("GPU", "DisableFramebufferFetch", false);
@ -576,6 +577,7 @@ void Settings::Save(SettingsInterface& si, bool ignore_base) const
if (!ignore_base) if (!ignore_base)
{ {
si.SetBoolValue("GPU", "UseDebugDevice", gpu_use_debug_device); si.SetBoolValue("GPU", "UseDebugDevice", gpu_use_debug_device);
si.SetBoolValue("GPU", "UseGPUBasedValidation", gpu_use_debug_device_gpu_validation);
si.SetBoolValue("GPU", "DisableShaderCache", gpu_disable_shader_cache); si.SetBoolValue("GPU", "DisableShaderCache", gpu_disable_shader_cache);
si.SetBoolValue("GPU", "DisableDualSourceBlend", gpu_disable_dual_source_blend); si.SetBoolValue("GPU", "DisableDualSourceBlend", gpu_disable_dual_source_blend);
si.SetBoolValue("GPU", "DisableFramebufferFetch", gpu_disable_framebuffer_fetch); si.SetBoolValue("GPU", "DisableFramebufferFetch", gpu_disable_framebuffer_fetch);
@ -1127,6 +1129,7 @@ bool Settings::AreGPUDeviceSettingsChanged(const Settings& old_settings) const
{ {
return (gpu_adapter != old_settings.gpu_adapter || gpu_use_thread != old_settings.gpu_use_thread || return (gpu_adapter != old_settings.gpu_adapter || gpu_use_thread != old_settings.gpu_use_thread ||
gpu_use_debug_device != old_settings.gpu_use_debug_device || gpu_use_debug_device != old_settings.gpu_use_debug_device ||
gpu_use_debug_device_gpu_validation != old_settings.gpu_use_debug_device_gpu_validation ||
gpu_disable_shader_cache != old_settings.gpu_disable_shader_cache || gpu_disable_shader_cache != old_settings.gpu_disable_shader_cache ||
gpu_disable_dual_source_blend != old_settings.gpu_disable_dual_source_blend || gpu_disable_dual_source_blend != old_settings.gpu_disable_dual_source_blend ||
gpu_disable_framebuffer_fetch != old_settings.gpu_disable_framebuffer_fetch || gpu_disable_framebuffer_fetch != old_settings.gpu_disable_framebuffer_fetch ||

View File

@ -94,6 +94,7 @@ struct GPUSettings
bool gpu_use_thread : 1 = true; bool gpu_use_thread : 1 = true;
bool gpu_use_software_renderer_for_readbacks : 1 = false; bool gpu_use_software_renderer_for_readbacks : 1 = false;
bool gpu_use_debug_device : 1 = false; bool gpu_use_debug_device : 1 = false;
bool gpu_use_debug_device_gpu_validation : 1 = false;
bool gpu_disable_shader_cache : 1 = false; bool gpu_disable_shader_cache : 1 = false;
bool gpu_disable_dual_source_blend : 1 = false; bool gpu_disable_dual_source_blend : 1 = false;
bool gpu_disable_framebuffer_fetch : 1 = false; bool gpu_disable_framebuffer_fetch : 1 = false;

View File

@ -310,6 +310,7 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.gpuDumpFastReplayMode, "GPU", "DumpFastReplayMode", false); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.gpuDumpFastReplayMode, "GPU", "DumpFastReplayMode", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.useDebugDevice, "GPU", "UseDebugDevice", false); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.useDebugDevice, "GPU", "UseDebugDevice", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.useGPUBasedValidation, "GPU", "UseGPUBasedValidation", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.disableShaderCache, "GPU", "DisableShaderCache", false); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.disableShaderCache, "GPU", "DisableShaderCache", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.disableDualSource, "GPU", "DisableDualSourceBlend", false); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.disableDualSource, "GPU", "DisableDualSourceBlend", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.disableFramebufferFetch, "GPU", "DisableFramebufferFetch", SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.disableFramebufferFetch, "GPU", "DisableFramebufferFetch",
@ -631,6 +632,9 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
dialog->registerWidgetHelp( dialog->registerWidgetHelp(
m_ui.useDebugDevice, tr("Use Debug Device"), tr("Unchecked"), m_ui.useDebugDevice, tr("Use Debug Device"), tr("Unchecked"),
tr("Enable debugging when supported by the host's renderer API. <strong>Only for developer use.</strong>")); tr("Enable debugging when supported by the host's renderer API. <strong>Only for developer use.</strong>"));
dialog->registerWidgetHelp(
m_ui.useGPUBasedValidation, tr("Use GPU-Based Validation"), tr("Unchecked"),
tr("Enable GPU-based validation when supported by the renderer API. <strong>Only for developer use.</strong>"));
dialog->registerWidgetHelp( dialog->registerWidgetHelp(
m_ui.disableShaderCache, tr("Disable Shader Cache"), tr("Unchecked"), m_ui.disableShaderCache, tr("Disable Shader Cache"), tr("Unchecked"),
tr("Forces shaders to be compiled for every run of the program. <strong>Only for developer use.</strong>")); tr("Forces shaders to be compiled for every run of the program. <strong>Only for developer use.</strong>"));

View File

@ -1350,6 +1350,20 @@
<layout class="QFormLayout" name="formLayout_10"> <layout class="QFormLayout" name="formLayout_10">
<item row="0" column="0" colspan="2"> <item row="0" column="0" colspan="2">
<layout class="QGridLayout" name="gridLayout_8"> <layout class="QGridLayout" name="gridLayout_8">
<item row="5" column="0">
<widget class="QCheckBox" name="disableComputeShaders">
<property name="text">
<string>Disable Compute Shaders</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="disableDualSource">
<property name="text">
<string>Disable Dual-Source Blending</string>
</property>
</widget>
</item>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QCheckBox" name="useDebugDevice"> <widget class="QCheckBox" name="useDebugDevice">
<property name="text"> <property name="text">
@ -1357,35 +1371,21 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0"> <item row="4" column="0">
<widget class="QCheckBox" name="disableTextureBuffers"> <widget class="QCheckBox" name="disableMemoryImport">
<property name="text"> <property name="text">
<string>Disable Texture Buffers</string> <string>Disable Memory Import</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="0"> <item row="4" column="1">
<widget class="QCheckBox" name="disableDualSource"> <widget class="QCheckBox" name="disableRasterOrderViews">
<property name="text"> <property name="text">
<string>Disable Dual-Source Blending</string> <string>Disable Rasterizer Order Views</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="1"> <item row="3" column="1">
<widget class="QCheckBox" name="disableShaderCache">
<property name="text">
<string>Disable Shader Cache</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="disableFramebufferFetch">
<property name="text">
<string>Disable Framebuffer Fetch</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="disableTextureCopyToSelf"> <widget class="QCheckBox" name="disableTextureCopyToSelf">
<property name="text"> <property name="text">
<string>Disable Texture Copy To Self</string> <string>Disable Texture Copy To Self</string>
@ -1393,33 +1393,40 @@
</widget> </widget>
</item> </item>
<item row="3" column="0"> <item row="3" column="0">
<widget class="QCheckBox" name="disableMemoryImport"> <widget class="QCheckBox" name="disableTextureBuffers">
<property name="text"> <property name="text">
<string>Disable Memory Import</string> <string>Disable Texture Buffers</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="1"> <item row="2" column="1">
<widget class="QCheckBox" name="disableRasterOrderViews"> <widget class="QCheckBox" name="disableFramebufferFetch">
<property name="text"> <property name="text">
<string>Disable Rasterizer Order Views</string> <string>Disable Framebuffer Fetch</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="0"> <item row="1" column="1">
<widget class="QCheckBox" name="disableComputeShaders">
<property name="text">
<string>Disable Compute Shaders</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QCheckBox" name="disableCompressedTextures"> <widget class="QCheckBox" name="disableCompressedTextures">
<property name="text"> <property name="text">
<string>Disable Compressed Textures</string> <string>Disable Compressed Textures</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="0">
<widget class="QCheckBox" name="disableShaderCache">
<property name="text">
<string>Disable Shader Cache</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="useGPUBasedValidation">
<property name="text">
<string>Use GPU-Based Validation</string>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
</layout> </layout>

View File

@ -186,10 +186,22 @@ bool D3D12Device::CreateDeviceAndMainSwapChain(std::string_view adapter, Feature
if (m_debug_device) if (m_debug_device)
{ {
ComPtr<ID3D12Debug> debug12; ComPtr<ID3D12Debug> debug12;
hr = D3D12GetDebugInterface(IID_PPV_ARGS(debug12.GetAddressOf())); if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(debug12.GetAddressOf()))))
if (SUCCEEDED(hr))
{ {
INFO_LOG("Enabling debug layer.");
debug12->EnableDebugLayer(); debug12->EnableDebugLayer();
ComPtr<ID3D12Debug1> debug12_1;
if (SUCCEEDED(debug12.As(&debug12_1)))
{
INFO_LOG("Enabling GPU-based validation.");
debug12_1->SetEnableGPUBasedValidation(true);
}
else
{
ERROR_LOG("GPU-based validation requested but not available.");
m_debug_device_gpu_validation = false;
}
} }
else else
{ {

View File

@ -449,11 +449,12 @@ GPUDevice::AdapterInfoList GPUDevice::GetAdapterListForAPI(RenderAPI api)
bool GPUDevice::Create(std::string_view adapter, FeatureMask disabled_features, std::string_view shader_dump_path, bool GPUDevice::Create(std::string_view adapter, FeatureMask disabled_features, std::string_view shader_dump_path,
std::string_view shader_cache_path, u32 shader_cache_version, bool debug_device, std::string_view shader_cache_path, u32 shader_cache_version, bool debug_device,
const WindowInfo& wi, GPUVSyncMode vsync, bool allow_present_throttle, bool gpu_validation, const WindowInfo& wi, GPUVSyncMode vsync, bool allow_present_throttle,
const ExclusiveFullscreenMode* exclusive_fullscreen_mode, const ExclusiveFullscreenMode* exclusive_fullscreen_mode,
std::optional<bool> exclusive_fullscreen_control, Error* error) std::optional<bool> exclusive_fullscreen_control, Error* error)
{ {
m_debug_device = debug_device; m_debug_device = debug_device;
m_debug_device_gpu_validation = debug_device && gpu_validation;
s_shader_dump_path = shader_dump_path; s_shader_dump_path = shader_dump_path;
INFO_LOG("Main render window is {}x{}.", wi.surface_width, wi.surface_height); INFO_LOG("Main render window is {}x{}.", wi.surface_width, wi.surface_height);

View File

@ -727,8 +727,9 @@ public:
ALWAYS_INLINE bool IsGPUTimingEnabled() const { return m_gpu_timing_enabled; } ALWAYS_INLINE bool IsGPUTimingEnabled() const { return m_gpu_timing_enabled; }
bool Create(std::string_view adapter, FeatureMask disabled_features, std::string_view shader_dump_path, bool Create(std::string_view adapter, FeatureMask disabled_features, std::string_view shader_dump_path,
std::string_view shader_cache_path, u32 shader_cache_version, bool debug_device, const WindowInfo& wi, std::string_view shader_cache_path, u32 shader_cache_version, bool debug_device, bool gpu_validation,
GPUVSyncMode vsync, bool allow_present_throttle, const ExclusiveFullscreenMode* exclusive_fullscreen_mode, const WindowInfo& wi, GPUVSyncMode vsync, bool allow_present_throttle,
const ExclusiveFullscreenMode* exclusive_fullscreen_mode,
std::optional<bool> exclusive_fullscreen_control, Error* error); std::optional<bool> exclusive_fullscreen_control, Error* error);
void Destroy(); void Destroy();
@ -995,6 +996,7 @@ protected:
bool m_gpu_timing_enabled = false; bool m_gpu_timing_enabled = false;
bool m_debug_device = false; bool m_debug_device = false;
bool m_debug_device_gpu_validation = false;
}; };
extern std::unique_ptr<GPUDevice> g_gpu_device; extern std::unique_ptr<GPUDevice> g_gpu_device;