From bb2b24a6ddb304e11d3324c66143a601d200ead4 Mon Sep 17 00:00:00 2001 From: Dario Date: Mon, 10 Feb 2025 20:21:32 -0300 Subject: [PATCH] Add Auto Graphics API option, add AMD driver workaround. --- UnleashedRecomp/gpu/rhi/plume_d3d12.cpp | 7 +++++++ .../gpu/rhi/plume_render_interface_types.h | 10 +++++++++- UnleashedRecomp/gpu/rhi/plume_vulkan.cpp | 1 + UnleashedRecomp/gpu/video.cpp | 20 +++++++++++++++++++ UnleashedRecomp/user/config.cpp | 1 + UnleashedRecomp/user/config.h | 1 + UnleashedRecomp/user/config_def.h | 8 +------- 7 files changed, 40 insertions(+), 8 deletions(-) diff --git a/UnleashedRecomp/gpu/rhi/plume_d3d12.cpp b/UnleashedRecomp/gpu/rhi/plume_d3d12.cpp index 85974e16..81d57b6b 100644 --- a/UnleashedRecomp/gpu/rhi/plume_d3d12.cpp +++ b/UnleashedRecomp/gpu/rhi/plume_d3d12.cpp @@ -3374,6 +3374,13 @@ namespace plume { capabilities.uma = uma; description.name = deviceName; description.dedicatedVideoMemory = adapterDesc.DedicatedVideoMemory; + description.vendor = RenderDeviceVendor(adapterDesc.VendorId); + + LARGE_INTEGER adapterVersion = {}; + res = adapter->CheckInterfaceSupport(__uuidof(IDXGIDevice), &adapterVersion); + if (SUCCEEDED(res)) { + description.driverVersion = adapterVersion.QuadPart; + } if (preferUserChoice) { break; diff --git a/UnleashedRecomp/gpu/rhi/plume_render_interface_types.h b/UnleashedRecomp/gpu/rhi/plume_render_interface_types.h index b7551832..f7c9683a 100644 --- a/UnleashedRecomp/gpu/rhi/plume_render_interface_types.h +++ b/UnleashedRecomp/gpu/rhi/plume_render_interface_types.h @@ -72,6 +72,13 @@ namespace plume { // Enums. + enum class RenderDeviceVendor { + UNKNOWN = 0x0, + AMD = 0x1002, + NVIDIA = 0x10DE, + INTEL = 0x8086 + }; + enum class RenderFormat { UNKNOWN, R32G32B32A32_TYPELESS, @@ -1769,7 +1776,8 @@ namespace plume { struct RenderDeviceDescription { std::string name = "Unknown"; RenderDeviceType type = RenderDeviceType::UNKNOWN; - uint32_t driverVersion = 0; + RenderDeviceVendor vendor = RenderDeviceVendor::UNKNOWN; + uint64_t driverVersion = 0; uint64_t dedicatedVideoMemory = 0; }; diff --git a/UnleashedRecomp/gpu/rhi/plume_vulkan.cpp b/UnleashedRecomp/gpu/rhi/plume_vulkan.cpp index 9e497c88..d84982e3 100644 --- a/UnleashedRecomp/gpu/rhi/plume_vulkan.cpp +++ b/UnleashedRecomp/gpu/rhi/plume_vulkan.cpp @@ -3516,6 +3516,7 @@ namespace plume { description.name = deviceName; description.type = toDeviceType(deviceProperties.deviceType); description.driverVersion = deviceProperties.driverVersion; + description.vendor = RenderDeviceVendor(deviceProperties.vendorID); currentDeviceTypeScore = deviceTypeScore; if (preferUserChoice) { diff --git a/UnleashedRecomp/gpu/video.cpp b/UnleashedRecomp/gpu/video.cpp index 7073c865..c5a19a2c 100644 --- a/UnleashedRecomp/gpu/video.cpp +++ b/UnleashedRecomp/gpu/video.cpp @@ -1610,6 +1610,7 @@ bool Video::CreateHostDevice(const char *sdlVideoDriver) interfaceFunctions.push_back(CreateVulkanInterfaceWrapper); #endif + bool driverWorkaroundsEnabled = Config::GraphicsAPI == EGraphicsAPI::Auto; for (RenderInterfaceFunction *interfaceFunction : interfaceFunctions) { g_interface = interfaceFunction(); @@ -1618,7 +1619,26 @@ bool Video::CreateHostDevice(const char *sdlVideoDriver) g_device = g_interface->createDevice(Config::GraphicsDevice); if (g_device != nullptr) { + const RenderDeviceDescription &deviceDescription = g_device->getDescription(); + #ifdef UNLEASHED_RECOMP_D3D12 + if (interfaceFunction == CreateD3D12Interface) + { + if (deviceDescription.vendor == RenderDeviceVendor::AMD) + { + // AMD Drivers before this version have a known issue where MSAA resolve targets will fail to work correctly. + // If no specific graphics API was selected, we silently destroy this one and move to the next option as it'll + // just work incorrectly otherwise and result in visual glitches and 3D rendering not working in general. + constexpr uint64_t MinimumAMDDriverVersion = 0x1F00005DC2005CULL; // 31.0.24002.92 + if ((Config::GraphicsAPI == EGraphicsAPI::Auto) && (deviceDescription.driverVersion < MinimumAMDDriverVersion)) + { + g_device.reset(); + g_interface.reset(); + continue; + } + } + } + g_vulkan = (interfaceFunction == CreateVulkanInterfaceWrapper); #endif break; diff --git a/UnleashedRecomp/user/config.cpp b/UnleashedRecomp/user/config.cpp index 918c7b6d..c506564f 100644 --- a/UnleashedRecomp/user/config.cpp +++ b/UnleashedRecomp/user/config.cpp @@ -302,6 +302,7 @@ CONFIG_DEFINE_ENUM_TEMPLATE(EVoiceLanguage) CONFIG_DEFINE_ENUM_TEMPLATE(EGraphicsAPI) { + { "Auto", EGraphicsAPI::Auto }, #ifdef UNLEASHED_RECOMP_D3D12 { "D3D12", EGraphicsAPI::D3D12 }, #endif diff --git a/UnleashedRecomp/user/config.h b/UnleashedRecomp/user/config.h index b944f691..05fe7229 100644 --- a/UnleashedRecomp/user/config.h +++ b/UnleashedRecomp/user/config.h @@ -62,6 +62,7 @@ enum class EChannelConfiguration : uint32_t enum class EGraphicsAPI : uint32_t { + Auto, #ifdef UNLEASHED_RECOMP_D3D12 D3D12, #endif diff --git a/UnleashedRecomp/user/config_def.h b/UnleashedRecomp/user/config_def.h index a9720297..3326c959 100644 --- a/UnleashedRecomp/user/config_def.h +++ b/UnleashedRecomp/user/config_def.h @@ -47,13 +47,7 @@ CONFIG_DEFINE_LOCALISED("Audio", bool, MusicAttenuation, false); CONFIG_DEFINE_LOCALISED("Audio", bool, BattleTheme, true); CONFIG_DEFINE("Video", std::string, GraphicsDevice, ""); - -#ifdef UNLEASHED_RECOMP_D3D12 -CONFIG_DEFINE_ENUM("Video", EGraphicsAPI, GraphicsAPI, EGraphicsAPI::D3D12); -#else -CONFIG_DEFINE_ENUM("Video", EGraphicsAPI, GraphicsAPI, EGraphicsAPI::Vulkan); -#endif - +CONFIG_DEFINE_ENUM("Video", EGraphicsAPI, GraphicsAPI, EGraphicsAPI::Auto); CONFIG_DEFINE("Video", int32_t, WindowX, WINDOWPOS_CENTRED); CONFIG_DEFINE("Video", int32_t, WindowY, WINDOWPOS_CENTRED); CONFIG_DEFINE_LOCALISED("Video", int32_t, WindowSize, -1);