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(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<RenderDevice> D3D12Interface::createDevice() {
std::unique_ptr<D3D12Device> createdDevice = std::make_unique<D3D12Device>(this);
std::unique_ptr<RenderDevice> D3D12Interface::createDevice(const std::string &preferredDeviceName) {
std::unique_ptr<D3D12Device> createdDevice = std::make_unique<D3D12Device>(this, preferredDeviceName);
return createdDevice->isValid() ? std::move(createdDevice) : nullptr;
}
@ -3784,6 +3800,10 @@ namespace plume {
return capabilities;
}
const std::vector<std::string> &D3D12Interface::getDeviceNames() const {
return deviceNames;
}
bool D3D12Interface::isValid() const {
return dxgiFactory != nullptr;
}

View file

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

View file

@ -237,7 +237,8 @@ namespace plume {
struct 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;
};

View file

@ -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<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() {
@ -4241,8 +4264,8 @@ namespace plume {
}
}
std::unique_ptr<RenderDevice> VulkanInterface::createDevice() {
std::unique_ptr<VulkanDevice> createdDevice = std::make_unique<VulkanDevice>(this);
std::unique_ptr<RenderDevice> VulkanInterface::createDevice(const std::string &preferredDeviceName) {
std::unique_ptr<VulkanDevice> createdDevice = std::make_unique<VulkanDevice>(this, preferredDeviceName);
return createdDevice->isValid() ? std::move(createdDevice) : nullptr;
}
@ -4250,6 +4273,10 @@ namespace plume {
return capabilities;
}
const std::vector<std::string> &VulkanInterface::getDeviceNames() const {
return deviceNames;
}
bool VulkanInterface::isValid() const {
return instance != nullptr;
}

View file

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

View file

@ -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();

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)
{
Value = section[Name].value_or<std::string>(DefaultValue);
Value = section[Name].value_or(DefaultValue);
}
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, BattleTheme, true);
CONFIG_DEFINE("Video", std::string, GraphicsDevice, "");
#ifdef UNLEASHED_RECOMP_D3D12
CONFIG_DEFINE_ENUM("Video", EGraphicsAPI, GraphicsAPI, EGraphicsAPI::D3D12);
#else