Add support for preferred device to configuration. (#355)

* Preferred device support.

* Add GraphicsDevice option and fix error in Config class to accept strings.

Co-authored-by: Hyper <34012267+hyperbx@users.noreply.github.com>

---------

Co-authored-by: Hyper <34012267+hyperbx@users.noreply.github.com>
This commit is contained in:
Darío 2025-02-10 18:01:12 -03:00 committed by GitHub
parent 3285ad045f
commit d2a3818700
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 86 additions and 17 deletions

View file

@ -3259,7 +3259,7 @@ namespace plume {
// D3D12Device // D3D12Device
D3D12Device::D3D12Device(D3D12Interface *renderInterface) { D3D12Device::D3D12Device(D3D12Interface *renderInterface, const std::string &preferredDeviceName) {
assert(renderInterface != nullptr); assert(renderInterface != nullptr);
this->renderInterface = renderInterface; this->renderInterface = renderInterface;
@ -3349,9 +3349,10 @@ namespace plume {
} }
// Pick this adapter and device if it has better feature support than the current one. // 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 preferOverNothing = (adapter == nullptr) || (d3d == nullptr);
bool preferVideoMemory = adapterDesc.DedicatedVideoMemory > description.dedicatedVideoMemory; bool preferVideoMemory = adapterDesc.DedicatedVideoMemory > description.dedicatedVideoMemory;
bool preferUserChoice = false;//wcsstr(adapterDesc.Description, L"AMD") != nullptr; bool preferUserChoice = preferredDeviceName == deviceName;
bool preferOption = preferOverNothing || preferVideoMemory || preferUserChoice; bool preferOption = preferOverNothing || preferVideoMemory || preferUserChoice;
if (preferOption) { if (preferOption) {
if (d3d != nullptr) { if (d3d != nullptr) {
@ -3371,7 +3372,7 @@ namespace plume {
capabilities.triangleFan = triangleFanSupportOption; capabilities.triangleFan = triangleFanSupportOption;
capabilities.dynamicDepthBias = dynamicDepthBiasOption; capabilities.dynamicDepthBias = dynamicDepthBiasOption;
capabilities.uma = uma; capabilities.uma = uma;
description.name = Utf16ToUtf8(adapterDesc.Description); description.name = deviceName;
description.dedicatedVideoMemory = adapterDesc.DedicatedVideoMemory; description.dedicatedVideoMemory = adapterDesc.DedicatedVideoMemory;
if (preferUserChoice) { if (preferUserChoice) {
@ -3767,6 +3768,21 @@ namespace plume {
// Fill capabilities. // Fill capabilities.
capabilities.shaderFormat = RenderShaderFormat::DXIL; 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() { D3D12Interface::~D3D12Interface() {
@ -3775,8 +3791,8 @@ namespace plume {
} }
} }
std::unique_ptr<RenderDevice> D3D12Interface::createDevice() { std::unique_ptr<RenderDevice> D3D12Interface::createDevice(const std::string &preferredDeviceName) {
std::unique_ptr<D3D12Device> createdDevice = std::make_unique<D3D12Device>(this); std::unique_ptr<D3D12Device> createdDevice = std::make_unique<D3D12Device>(this, preferredDeviceName);
return createdDevice->isValid() ? std::move(createdDevice) : nullptr; return createdDevice->isValid() ? std::move(createdDevice) : nullptr;
} }
@ -3784,6 +3800,10 @@ namespace plume {
return capabilities; return capabilities;
} }
const std::vector<std::string> &D3D12Interface::getDeviceNames() const {
return deviceNames;
}
bool D3D12Interface::isValid() const { bool D3D12Interface::isValid() const {
return dxgiFactory != nullptr; return dxgiFactory != nullptr;
} }

View file

@ -418,7 +418,7 @@ namespace plume {
RenderDeviceCapabilities capabilities; RenderDeviceCapabilities capabilities;
RenderDeviceDescription description; RenderDeviceDescription description;
D3D12Device(D3D12Interface *renderInterface); D3D12Device(D3D12Interface *renderInterface, const std::string &preferredDeviceName);
~D3D12Device() override; ~D3D12Device() override;
std::unique_ptr<RenderCommandList> createCommandList(RenderCommandListType type) override; std::unique_ptr<RenderCommandList> createCommandList(RenderCommandListType type) override;
std::unique_ptr<RenderDescriptorSet> createDescriptorSet(const RenderDescriptorSetDesc &desc) override; std::unique_ptr<RenderDescriptorSet> createDescriptorSet(const RenderDescriptorSetDesc &desc) override;
@ -450,11 +450,13 @@ namespace plume {
struct D3D12Interface : RenderInterface { struct D3D12Interface : RenderInterface {
IDXGIFactory4 *dxgiFactory = nullptr; IDXGIFactory4 *dxgiFactory = nullptr;
RenderInterfaceCapabilities capabilities; RenderInterfaceCapabilities capabilities;
std::vector<std::string> deviceNames;
D3D12Interface(); D3D12Interface();
~D3D12Interface() override; ~D3D12Interface() override;
std::unique_ptr<RenderDevice> createDevice() override; std::unique_ptr<RenderDevice> createDevice(const std::string &preferredDeviceName) override;
const RenderInterfaceCapabilities &getCapabilities() const override; const RenderInterfaceCapabilities &getCapabilities() const override;
const std::vector<std::string> &getDeviceNames() const override;
bool isValid() const; bool isValid() const;
}; };
}; };

View file

@ -237,7 +237,8 @@ namespace plume {
struct RenderInterface { struct RenderInterface {
virtual ~RenderInterface() { } virtual ~RenderInterface() { }
virtual std::unique_ptr<RenderDevice> createDevice() = 0; virtual std::unique_ptr<RenderDevice> createDevice(const std::string &preferredDeviceName = "") = 0;
virtual const std::vector<std::string> &getDeviceNames() const = 0;
virtual const RenderInterfaceCapabilities &getCapabilities() const = 0; virtual const RenderInterfaceCapabilities &getCapabilities() const = 0;
}; };

View file

@ -3473,7 +3473,7 @@ namespace plume {
// VulkanDevice // VulkanDevice
VulkanDevice::VulkanDevice(VulkanInterface *renderInterface) { VulkanDevice::VulkanDevice(VulkanInterface *renderInterface, const std::string &preferredDeviceName) {
assert(renderInterface != nullptr); assert(renderInterface != nullptr);
this->renderInterface = renderInterface; this->renderInterface = renderInterface;
@ -3506,15 +3506,21 @@ namespace plume {
continue; continue;
} }
std::string deviceName(deviceProperties.deviceName);
uint32_t deviceTypeScore = deviceTypeScoreTable[deviceTypeIndex]; uint32_t deviceTypeScore = deviceTypeScoreTable[deviceTypeIndex];
bool preferDeviceTypeScore = (deviceTypeScore > currentDeviceTypeScore); bool preferDeviceTypeScore = (deviceTypeScore > currentDeviceTypeScore);
bool preferOption = preferDeviceTypeScore; bool preferUserChoice = preferredDeviceName == deviceName;
bool preferOption = preferDeviceTypeScore || preferUserChoice;
if (preferOption) { if (preferOption) {
physicalDevice = physicalDevices[i]; physicalDevice = physicalDevices[i];
description.name = std::string(deviceProperties.deviceName); description.name = deviceName;
description.type = toDeviceType(deviceProperties.deviceType); description.type = toDeviceType(deviceProperties.deviceType);
description.driverVersion = deviceProperties.driverVersion; description.driverVersion = deviceProperties.driverVersion;
currentDeviceTypeScore = deviceTypeScore; currentDeviceTypeScore = deviceTypeScore;
if (preferUserChoice) {
break;
}
} }
} }
@ -4233,6 +4239,23 @@ namespace plume {
// Fill capabilities. // Fill capabilities.
capabilities.shaderFormat = RenderShaderFormat::SPIRV; capabilities.shaderFormat = RenderShaderFormat::SPIRV;
// Fill device names.
uint32_t deviceCount = 0;
vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);
if (deviceCount > 0) {
std::vector<VkPhysicalDevice> 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() { VulkanInterface::~VulkanInterface() {
@ -4241,8 +4264,8 @@ namespace plume {
} }
} }
std::unique_ptr<RenderDevice> VulkanInterface::createDevice() { std::unique_ptr<RenderDevice> VulkanInterface::createDevice(const std::string &preferredDeviceName) {
std::unique_ptr<VulkanDevice> createdDevice = std::make_unique<VulkanDevice>(this); std::unique_ptr<VulkanDevice> createdDevice = std::make_unique<VulkanDevice>(this, preferredDeviceName);
return createdDevice->isValid() ? std::move(createdDevice) : nullptr; return createdDevice->isValid() ? std::move(createdDevice) : nullptr;
} }
@ -4250,6 +4273,10 @@ namespace plume {
return capabilities; return capabilities;
} }
const std::vector<std::string> &VulkanInterface::getDeviceNames() const {
return deviceNames;
}
bool VulkanInterface::isValid() const { bool VulkanInterface::isValid() const {
return instance != nullptr; return instance != nullptr;
} }

View file

@ -391,7 +391,7 @@ namespace plume {
VkPhysicalDeviceSampleLocationsPropertiesEXT sampleLocationProperties = {}; VkPhysicalDeviceSampleLocationsPropertiesEXT sampleLocationProperties = {};
bool loadStoreOpNoneSupported = false; bool loadStoreOpNoneSupported = false;
VulkanDevice(VulkanInterface *renderInterface); VulkanDevice(VulkanInterface *renderInterface, const std::string &preferredDeviceName);
~VulkanDevice() override; ~VulkanDevice() override;
std::unique_ptr<RenderCommandList> createCommandList(RenderCommandListType type) override; std::unique_ptr<RenderCommandList> createCommandList(RenderCommandListType type) override;
std::unique_ptr<RenderDescriptorSet> createDescriptorSet(const RenderDescriptorSetDesc &desc) override; std::unique_ptr<RenderDescriptorSet> createDescriptorSet(const RenderDescriptorSetDesc &desc) override;
@ -424,6 +424,7 @@ namespace plume {
VkInstance instance = VK_NULL_HANDLE; VkInstance instance = VK_NULL_HANDLE;
VkApplicationInfo appInfo = {}; VkApplicationInfo appInfo = {};
RenderInterfaceCapabilities capabilities; RenderInterfaceCapabilities capabilities;
std::vector<std::string> deviceNames;
# if SDL_VULKAN_ENABLED # if SDL_VULKAN_ENABLED
VulkanInterface(RenderWindow sdlWindow); VulkanInterface(RenderWindow sdlWindow);
@ -432,8 +433,9 @@ namespace plume {
# endif # endif
~VulkanInterface() override; ~VulkanInterface() override;
std::unique_ptr<RenderDevice> createDevice() override; std::unique_ptr<RenderDevice> createDevice(const std::string &preferredDeviceName) override;
const RenderInterfaceCapabilities &getCapabilities() const override; const RenderInterfaceCapabilities &getCapabilities() const override;
const std::vector<std::string> &getDeviceNames() const override;
bool isValid() const; bool isValid() const;
}; };
}; };

View file

@ -1615,7 +1615,7 @@ bool Video::CreateHostDevice(const char *sdlVideoDriver)
g_interface = interfaceFunction(); g_interface = interfaceFunction();
if (g_interface != nullptr) if (g_interface != nullptr)
{ {
g_device = g_interface->createDevice(); g_device = g_interface->createDevice(Config::GraphicsDevice);
if (g_device != nullptr) if (g_device != nullptr)
{ {
#ifdef UNLEASHED_RECOMP_D3D12 #ifdef UNLEASHED_RECOMP_D3D12
@ -2256,6 +2256,21 @@ static void DrawProfiler()
const char* sdlVideoDriver = SDL_GetCurrentVideoDriver(); const char* sdlVideoDriver = SDL_GetCurrentVideoDriver();
if (sdlVideoDriver != nullptr) if (sdlVideoDriver != nullptr)
ImGui::Text("SDL Video Driver: %s", sdlVideoDriver); 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(); ImGui::End();

View file

@ -472,7 +472,7 @@ void ConfigDef<T, isHidden>::ReadValue(toml::v3::ex::parse_result& toml)
if constexpr (std::is_same<T, std::string>::value) if constexpr (std::is_same<T, std::string>::value)
{ {
Value = section[Name].value_or<std::string>(DefaultValue); Value = section[Name].value_or(DefaultValue);
} }
else if constexpr (std::is_enum_v<T>) else if constexpr (std::is_enum_v<T>)
{ {

View file

@ -46,6 +46,8 @@ CONFIG_DEFINE_ENUM_LOCALISED("Audio", EChannelConfiguration, ChannelConfiguratio
CONFIG_DEFINE_LOCALISED("Audio", bool, MusicAttenuation, false); CONFIG_DEFINE_LOCALISED("Audio", bool, MusicAttenuation, false);
CONFIG_DEFINE_LOCALISED("Audio", bool, BattleTheme, true); CONFIG_DEFINE_LOCALISED("Audio", bool, BattleTheme, true);
CONFIG_DEFINE("Video", std::string, GraphicsDevice, "");
#ifdef UNLEASHED_RECOMP_D3D12 #ifdef UNLEASHED_RECOMP_D3D12
CONFIG_DEFINE_ENUM("Video", EGraphicsAPI, GraphicsAPI, EGraphicsAPI::D3D12); CONFIG_DEFINE_ENUM("Video", EGraphicsAPI, GraphicsAPI, EGraphicsAPI::D3D12);
#else #else