diff --git a/UnleashedRecomp/gpu/rhi/plume_d3d12.cpp b/UnleashedRecomp/gpu/rhi/plume_d3d12.cpp index a543b74..85974e1 100644 --- a/UnleashedRecomp/gpu/rhi/plume_d3d12.cpp +++ b/UnleashedRecomp/gpu/rhi/plume_d3d12.cpp @@ -3259,7 +3259,7 @@ namespace plume { // D3D12Device - D3D12Device::D3D12Device(D3D12Interface *renderInterface) { + D3D12Device::D3D12Device(D3D12Interface *renderInterface, const std::string &preferredDeviceName) { assert(renderInterface != nullptr); this->renderInterface = renderInterface; @@ -3349,9 +3349,10 @@ namespace plume { } // Pick this adapter and device if it has better feature support than the current one. + std::string deviceName = Utf16ToUtf8(adapterDesc.Description); bool preferOverNothing = (adapter == nullptr) || (d3d == nullptr); bool preferVideoMemory = adapterDesc.DedicatedVideoMemory > description.dedicatedVideoMemory; - bool preferUserChoice = false;//wcsstr(adapterDesc.Description, L"AMD") != nullptr; + bool preferUserChoice = preferredDeviceName == deviceName; bool preferOption = preferOverNothing || preferVideoMemory || preferUserChoice; if (preferOption) { if (d3d != nullptr) { @@ -3371,7 +3372,7 @@ namespace plume { capabilities.triangleFan = triangleFanSupportOption; capabilities.dynamicDepthBias = dynamicDepthBiasOption; capabilities.uma = uma; - description.name = Utf16ToUtf8(adapterDesc.Description); + description.name = deviceName; description.dedicatedVideoMemory = adapterDesc.DedicatedVideoMemory; if (preferUserChoice) { @@ -3767,6 +3768,21 @@ namespace plume { // Fill capabilities. capabilities.shaderFormat = RenderShaderFormat::DXIL; + + // Fill device names. + UINT adapterIndex = 0; + IDXGIAdapter1 *adapterOption = nullptr; + while (dxgiFactory->EnumAdapters1(adapterIndex++, &adapterOption) != DXGI_ERROR_NOT_FOUND) { + DXGI_ADAPTER_DESC1 adapterDesc; + adapterOption->GetDesc1(&adapterDesc); + + // Ignore remote or software adapters. + if ((adapterDesc.Flags & (DXGI_ADAPTER_FLAG_REMOTE | DXGI_ADAPTER_FLAG_SOFTWARE)) == 0) { + deviceNames.emplace_back(Utf16ToUtf8(adapterDesc.Description)); + } + + adapterOption->Release(); + } } D3D12Interface::~D3D12Interface() { @@ -3775,8 +3791,8 @@ namespace plume { } } - std::unique_ptr D3D12Interface::createDevice() { - std::unique_ptr createdDevice = std::make_unique(this); + std::unique_ptr D3D12Interface::createDevice(const std::string &preferredDeviceName) { + std::unique_ptr createdDevice = std::make_unique(this, preferredDeviceName); return createdDevice->isValid() ? std::move(createdDevice) : nullptr; } @@ -3784,6 +3800,10 @@ namespace plume { return capabilities; } + const std::vector &D3D12Interface::getDeviceNames() const { + return deviceNames; + } + bool D3D12Interface::isValid() const { return dxgiFactory != nullptr; } diff --git a/UnleashedRecomp/gpu/rhi/plume_d3d12.h b/UnleashedRecomp/gpu/rhi/plume_d3d12.h index 291a7d4..6b00ed7 100644 --- a/UnleashedRecomp/gpu/rhi/plume_d3d12.h +++ b/UnleashedRecomp/gpu/rhi/plume_d3d12.h @@ -418,7 +418,7 @@ namespace plume { RenderDeviceCapabilities capabilities; RenderDeviceDescription description; - D3D12Device(D3D12Interface *renderInterface); + D3D12Device(D3D12Interface *renderInterface, const std::string &preferredDeviceName); ~D3D12Device() override; std::unique_ptr createCommandList(RenderCommandListType type) override; std::unique_ptr createDescriptorSet(const RenderDescriptorSetDesc &desc) override; @@ -450,11 +450,13 @@ namespace plume { struct D3D12Interface : RenderInterface { IDXGIFactory4 *dxgiFactory = nullptr; RenderInterfaceCapabilities capabilities; + std::vector deviceNames; D3D12Interface(); ~D3D12Interface() override; - std::unique_ptr createDevice() override; + std::unique_ptr createDevice(const std::string &preferredDeviceName) override; const RenderInterfaceCapabilities &getCapabilities() const override; + const std::vector &getDeviceNames() const override; bool isValid() const; }; }; diff --git a/UnleashedRecomp/gpu/rhi/plume_render_interface.h b/UnleashedRecomp/gpu/rhi/plume_render_interface.h index 4b9e533..995bc25 100644 --- a/UnleashedRecomp/gpu/rhi/plume_render_interface.h +++ b/UnleashedRecomp/gpu/rhi/plume_render_interface.h @@ -237,7 +237,8 @@ namespace plume { struct RenderInterface { virtual ~RenderInterface() { } - virtual std::unique_ptr createDevice() = 0; + virtual std::unique_ptr createDevice(const std::string &preferredDeviceName = "") = 0; + virtual const std::vector &getDeviceNames() const = 0; virtual const RenderInterfaceCapabilities &getCapabilities() const = 0; }; diff --git a/UnleashedRecomp/gpu/rhi/plume_vulkan.cpp b/UnleashedRecomp/gpu/rhi/plume_vulkan.cpp index 1ff395a..9e497c8 100644 --- a/UnleashedRecomp/gpu/rhi/plume_vulkan.cpp +++ b/UnleashedRecomp/gpu/rhi/plume_vulkan.cpp @@ -3473,7 +3473,7 @@ namespace plume { // VulkanDevice - VulkanDevice::VulkanDevice(VulkanInterface *renderInterface) { + VulkanDevice::VulkanDevice(VulkanInterface *renderInterface, const std::string &preferredDeviceName) { assert(renderInterface != nullptr); this->renderInterface = renderInterface; @@ -3506,15 +3506,21 @@ namespace plume { continue; } + std::string deviceName(deviceProperties.deviceName); uint32_t deviceTypeScore = deviceTypeScoreTable[deviceTypeIndex]; bool preferDeviceTypeScore = (deviceTypeScore > currentDeviceTypeScore); - bool preferOption = preferDeviceTypeScore; + bool preferUserChoice = preferredDeviceName == deviceName; + bool preferOption = preferDeviceTypeScore || preferUserChoice; if (preferOption) { physicalDevice = physicalDevices[i]; - description.name = std::string(deviceProperties.deviceName); + description.name = deviceName; description.type = toDeviceType(deviceProperties.deviceType); description.driverVersion = deviceProperties.driverVersion; currentDeviceTypeScore = deviceTypeScore; + + if (preferUserChoice) { + break; + } } } @@ -4233,6 +4239,23 @@ namespace plume { // Fill capabilities. capabilities.shaderFormat = RenderShaderFormat::SPIRV; + + // Fill device names. + uint32_t deviceCount = 0; + vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr); + if (deviceCount > 0) { + std::vector physicalDevices(deviceCount); + vkEnumeratePhysicalDevices(instance, &deviceCount, physicalDevices.data()); + + for (uint32_t i = 0; i < deviceCount; i++) { + VkPhysicalDeviceProperties deviceProperties; + vkGetPhysicalDeviceProperties(physicalDevices[i], &deviceProperties); + uint32_t deviceTypeIndex = deviceProperties.deviceType; + if (deviceTypeIndex <= 4) { + deviceNames.emplace_back(deviceProperties.deviceName); + } + } + } } VulkanInterface::~VulkanInterface() { @@ -4241,8 +4264,8 @@ namespace plume { } } - std::unique_ptr VulkanInterface::createDevice() { - std::unique_ptr createdDevice = std::make_unique(this); + std::unique_ptr VulkanInterface::createDevice(const std::string &preferredDeviceName) { + std::unique_ptr createdDevice = std::make_unique(this, preferredDeviceName); return createdDevice->isValid() ? std::move(createdDevice) : nullptr; } @@ -4250,6 +4273,10 @@ namespace plume { return capabilities; } + const std::vector &VulkanInterface::getDeviceNames() const { + return deviceNames; + } + bool VulkanInterface::isValid() const { return instance != nullptr; } diff --git a/UnleashedRecomp/gpu/rhi/plume_vulkan.h b/UnleashedRecomp/gpu/rhi/plume_vulkan.h index 469f056..59f2aaf 100644 --- a/UnleashedRecomp/gpu/rhi/plume_vulkan.h +++ b/UnleashedRecomp/gpu/rhi/plume_vulkan.h @@ -391,7 +391,7 @@ namespace plume { VkPhysicalDeviceSampleLocationsPropertiesEXT sampleLocationProperties = {}; bool loadStoreOpNoneSupported = false; - VulkanDevice(VulkanInterface *renderInterface); + VulkanDevice(VulkanInterface *renderInterface, const std::string &preferredDeviceName); ~VulkanDevice() override; std::unique_ptr createCommandList(RenderCommandListType type) override; std::unique_ptr createDescriptorSet(const RenderDescriptorSetDesc &desc) override; @@ -424,6 +424,7 @@ namespace plume { VkInstance instance = VK_NULL_HANDLE; VkApplicationInfo appInfo = {}; RenderInterfaceCapabilities capabilities; + std::vector deviceNames; # if SDL_VULKAN_ENABLED VulkanInterface(RenderWindow sdlWindow); @@ -432,8 +433,9 @@ namespace plume { # endif ~VulkanInterface() override; - std::unique_ptr createDevice() override; + std::unique_ptr createDevice(const std::string &preferredDeviceName) override; const RenderInterfaceCapabilities &getCapabilities() const override; + const std::vector &getDeviceNames() const override; bool isValid() const; }; }; diff --git a/UnleashedRecomp/gpu/video.cpp b/UnleashedRecomp/gpu/video.cpp index 62a5b30..7073c86 100644 --- a/UnleashedRecomp/gpu/video.cpp +++ b/UnleashedRecomp/gpu/video.cpp @@ -1615,7 +1615,7 @@ bool Video::CreateHostDevice(const char *sdlVideoDriver) g_interface = interfaceFunction(); if (g_interface != nullptr) { - g_device = g_interface->createDevice(); + g_device = g_interface->createDevice(Config::GraphicsDevice); if (g_device != nullptr) { #ifdef UNLEASHED_RECOMP_D3D12 @@ -2256,6 +2256,21 @@ static void DrawProfiler() const char* sdlVideoDriver = SDL_GetCurrentVideoDriver(); if (sdlVideoDriver != nullptr) ImGui::Text("SDL Video Driver: %s", sdlVideoDriver); + + ImGui::NewLine(); + if (ImGui::TreeNode("Device Names")) + { + ImGui::Indent(); + + uint32_t deviceIndex = 0; + for (const std::string &deviceName : g_interface->getDeviceNames()) + { + ImGui::Text("Option #%d: %s", deviceIndex++, deviceName.c_str()); + } + + ImGui::Unindent(); + ImGui::TreePop(); + } } ImGui::End(); diff --git a/UnleashedRecomp/user/config.cpp b/UnleashedRecomp/user/config.cpp index 4aeafb9..918c7b6 100644 --- a/UnleashedRecomp/user/config.cpp +++ b/UnleashedRecomp/user/config.cpp @@ -472,7 +472,7 @@ void ConfigDef::ReadValue(toml::v3::ex::parse_result& toml) if constexpr (std::is_same::value) { - Value = section[Name].value_or(DefaultValue); + Value = section[Name].value_or(DefaultValue); } else if constexpr (std::is_enum_v) { diff --git a/UnleashedRecomp/user/config_def.h b/UnleashedRecomp/user/config_def.h index 611aff3..a972029 100644 --- a/UnleashedRecomp/user/config_def.h +++ b/UnleashedRecomp/user/config_def.h @@ -46,6 +46,8 @@ CONFIG_DEFINE_ENUM_LOCALISED("Audio", EChannelConfiguration, ChannelConfiguratio 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