Graphics API Selection

Originally: To change between DirectX 12 and Vulkan API: you'd need to go to `config.toml` 's GraphicsAPI to either D3D12 or Vulkan. Now, you can choose Graphics APIs directly through the In-Game Video Settings!
This commit is contained in:
Al. Lopez 2025-09-17 18:36:43 -04:00 committed by GitHub
parent 3c1badf183
commit 78bcb27abf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 197 additions and 2 deletions

View file

@ -299,6 +299,10 @@ static std::unique_ptr<RenderDevice> g_device;
static RenderDeviceCapabilities g_capabilities; static RenderDeviceCapabilities g_capabilities;
// Track the currently active graphics API for display purposes
static EGraphicsAPI g_currentGraphicsAPI = EGraphicsAPI::Auto;
static bool g_currentAPIChosenByAuto = false;
static constexpr size_t NUM_FRAMES = 2; static constexpr size_t NUM_FRAMES = 2;
static constexpr size_t NUM_QUERIES = 2; static constexpr size_t NUM_QUERIES = 2;
@ -1673,6 +1677,12 @@ bool Video::CreateHostDevice(const char *sdlVideoDriver, bool graphicsApiRetry)
#ifdef UNLEASHED_RECOMP_D3D12 #ifdef UNLEASHED_RECOMP_D3D12
g_vulkan = DetectWine() || Config::GraphicsAPI == EGraphicsAPI::Vulkan; g_vulkan = DetectWine() || Config::GraphicsAPI == EGraphicsAPI::Vulkan;
// Track if the Graphics API was chosen by Auto or manually selected
g_currentAPIChosenByAuto = (Config::GraphicsAPI == EGraphicsAPI::Auto);
#else
// For Vulkan-only builds, check if Auto was selected
g_currentAPIChosenByAuto = (Config::GraphicsAPI == EGraphicsAPI::Auto);
#endif #endif
// Attempt to create the possible backends using a vector of function pointers. Whichever succeeds first will be the chosen API. // Attempt to create the possible backends using a vector of function pointers. Whichever succeeds first will be the chosen API.
@ -1765,6 +1775,12 @@ bool Video::CreateHostDevice(const char *sdlVideoDriver, bool graphicsApiRetry)
} }
g_vulkan = (interfaceFunction == CreateVulkanInterfaceWrapper); g_vulkan = (interfaceFunction == CreateVulkanInterfaceWrapper);
// Track which graphics API is actually being used for display purposes
g_currentGraphicsAPI = g_vulkan ? EGraphicsAPI::Vulkan : EGraphicsAPI::D3D12;
#else
// For Vulkan-only builds
g_currentGraphicsAPI = EGraphicsAPI::Vulkan;
#endif #endif
// Enable triangle strip workaround if we are on AMD, as there is a bug where // Enable triangle strip workaround if we are on AMD, as there is a bug where
// restart indices cause triangles to be culled incorrectly. Converting them to degenerate triangles fixes it. // restart indices cause triangles to be culled incorrectly. Converting them to degenerate triangles fixes it.
@ -3062,6 +3078,16 @@ void Video::ComputeViewportDimensions()
AspectRatioPatches::ComputeOffsets(); AspectRatioPatches::ComputeOffsets();
} }
EGraphicsAPI Video::GetCurrentGraphicsAPI()
{
return g_currentGraphicsAPI;
}
bool Video::IsCurrentAPIChosenByAuto()
{
return g_currentAPIChosenByAuto;
}
static RenderFormat ConvertFormat(uint32_t format) static RenderFormat ConvertFormat(uint32_t format)
{ {
switch (format) switch (format)

View file

@ -5,6 +5,7 @@
//#define PSO_CACHING_CLEANUP //#define PSO_CACHING_CLEANUP
#include <plume_render_interface.h> #include <plume_render_interface.h>
#include <user/config.h>
#define D3DCLEAR_TARGET 0x1 #define D3DCLEAR_TARGET 0x1
#define D3DCLEAR_ZBUFFER 0x10 #define D3DCLEAR_ZBUFFER 0x10
@ -24,6 +25,8 @@ struct Video
static void StartPipelinePrecompilation(); static void StartPipelinePrecompilation();
static void WaitForGPU(); static void WaitForGPU();
static void ComputeViewportDimensions(); static void ComputeViewportDimensions();
static EGraphicsAPI GetCurrentGraphicsAPI();
static bool IsCurrentAPIChosenByAuto();
}; };
struct GuestSamplerState struct GuestSamplerState

View file

@ -526,6 +526,82 @@ CONFIG_DEFINE_LOCALE(Monitor)
{ ELanguage::Italian, { "Schermo", "Cambia lo schermo su cui visualizzare il gioco." } } { ELanguage::Italian, { "Schermo", "Cambia lo schermo su cui visualizzare il gioco." } }
}; };
// Japanese Notes: This localization should include furigana.
CONFIG_DEFINE_LOCALE(GraphicsAPI)
{
{ ELanguage::English, { "Graphics API", "Change the graphics API used for rendering. \n\nWARNING: Changing graphics api requires game restart" } },
{ ELanguage::Japanese, { "グラフィックAPI", "レンダリングに[使用:しよう]するグラフィックAPIを[変更:へんこう]します。\n\n[警告:けいこく]: グラフィックAPIの[変更:へんこう]にはゲームの[再起動:さいきどう]が[必要:ひつよう]です" } },
{ ELanguage::German, { "Grafik-API", "Ändere die Grafik-API für das Rendering. \n\nWARNUNG: Das Ändern der Grafik-API erfordert einen Neustart des Spiels" } },
{ ELanguage::French, { "API graphique", "Modifie l'API graphique utilisée pour le rendu. \n\nATTENTION : Changer l'API graphique nécessite un redémarrage du jeu" } },
{ ELanguage::Spanish, { "API de gráficos", "Cambia la API de gráficos utilizada para el renderizado. \n\nADVERTENCIA: Cambiar la API de gráficos requiere reiniciar el juego" } },
{ ELanguage::Italian, { "API grafica", "Modifica l'API grafica utilizzata per il rendering. \n\nATTENZIONE: Cambiare l'API grafica richiede il riavvio del gioco" } }
};
// Japanese Notes: This localization should include furigana in its description.
CONFIG_DEFINE_ENUM_LOCALE(EGraphicsAPI)
{
{
ELanguage::English,
{
{ EGraphicsAPI::Auto, { "AUTO", "Automatically selects the best available graphics API for your system." } },
#ifdef UNLEASHED_RECOMP_D3D12
{ EGraphicsAPI::D3D12, { "DX12", "use Microsoft's DirectX 12 API for graphics rendering." } },
#endif
{ EGraphicsAPI::Vulkan, { "VULKAN", "use Khronos Group's Vulkan API for graphics rendering." } }
}
},
{
ELanguage::Japanese,
{
{ EGraphicsAPI::Auto, { "自動", "[自動:じどう]: [最適:さいてき]なグラフィックAPIを\u200B[自動的:じどうてき]に\u200B[選択:せんたく]します" } },
#ifdef UNLEASHED_RECOMP_D3D12
{ EGraphicsAPI::D3D12, { "DX12", "Microsoft の DirectX 12 API を\u200B[使用:しよう]してレンダリングします" } },
#endif
{ EGraphicsAPI::Vulkan, { "VULKAN", "Khronos Group の Vulkan API を\u200B[使用:しよう]してレンダリングします" } }
}
},
{
ELanguage::German,
{
{ EGraphicsAPI::Auto, { "AUTO", "Wählt automatisch die beste verfügbare Grafik-API aus." } },
#ifdef UNLEASHED_RECOMP_D3D12
{ EGraphicsAPI::D3D12, { "DX12", "Verwendet Microsofts DirectX 12 API für das Rendering." } },
#endif
{ EGraphicsAPI::Vulkan, { "VULKAN", "Verwendet die Khronos Group's Vulkan API für das Rendering." } }
}
},
{
ELanguage::French,
{
{ EGraphicsAPI::Auto, { "AUTO", "sélectionne automatiquement la meilleure API graphique disponible." } },
#ifdef UNLEASHED_RECOMP_D3D12
{ EGraphicsAPI::D3D12, { "DX12", "utilise l'API DirectX 12 de Microsoft pour le rendu." } },
#endif
{ EGraphicsAPI::Vulkan, { "VULKAN", "utilise l'API Vulkan du Khronos Group pour le rendu." } }
}
},
{
ELanguage::Spanish,
{
{ EGraphicsAPI::Auto, { "AUTO", "selecciona automáticamente la mejor API de gráficos disponible." } },
#ifdef UNLEASHED_RECOMP_D3D12
{ EGraphicsAPI::D3D12, { "DX12", "utiliza la API DirectX 12 de Microsoft para el renderizado." } },
#endif
{ EGraphicsAPI::Vulkan, { "VULKAN", "utiliza la API Vulkan del Khronos Group para el renderizado." } }
}
},
{
ELanguage::Italian,
{
{ EGraphicsAPI::Auto, { "AUTO", "seleziona automaticamente la migliore API grafica disponibile." } },
#ifdef UNLEASHED_RECOMP_D3D12
{ EGraphicsAPI::D3D12, { "DX12", "utilizza l'API DirectX 12 di Microsoft per il rendering." } },
#endif
{ EGraphicsAPI::Vulkan, { "VULKAN", "utilizza l'API Vulkan del Khronos Group per il rendering." } }
}
}
};
// Japanese Notes: This localization should include furigana. // Japanese Notes: This localization should include furigana.
CONFIG_DEFINE_LOCALE(AspectRatio) CONFIG_DEFINE_LOCALE(AspectRatio)
{ {

View file

@ -1271,6 +1271,7 @@ static void DrawConfigOptions()
DrawConfigOption(rowCount++, yOffset, &Config::AspectRatio, true); DrawConfigOption(rowCount++, yOffset, &Config::AspectRatio, true);
DrawConfigOption(rowCount++, yOffset, &Config::ResolutionScale, true, nullptr, 0.25f, 1.0f, 2.0f); DrawConfigOption(rowCount++, yOffset, &Config::ResolutionScale, true, nullptr, 0.25f, 1.0f, 2.0f);
DrawConfigOption(rowCount++, yOffset, &Config::Fullscreen, true); DrawConfigOption(rowCount++, yOffset, &Config::Fullscreen, true);
DrawConfigOption(rowCount++, yOffset, &Config::GraphicsAPI, true);
DrawConfigOption(rowCount++, yOffset, &Config::VSync, true); DrawConfigOption(rowCount++, yOffset, &Config::VSync, true);
DrawConfigOption(rowCount++, yOffset, &Config::FPS, true, nullptr, FPS_MIN, 120, FPS_MAX); DrawConfigOption(rowCount++, yOffset, &Config::FPS, true, nullptr, FPS_MIN, 120, FPS_MAX);
DrawConfigOption(rowCount++, yOffset, &Config::Brightness, true); DrawConfigOption(rowCount++, yOffset, &Config::Brightness, true);

View file

@ -2,6 +2,7 @@
#include <os/logger.h> #include <os/logger.h>
#include <ui/game_window.h> #include <ui/game_window.h>
#include <user/paths.h> #include <user/paths.h>
#include <gpu/video.h>
std::vector<IConfigDef*> g_configDefinitions; std::vector<IConfigDef*> g_configDefinitions;
@ -407,6 +408,12 @@ CONFIG_DEFINE_ENUM_TEMPLATE(EUIAlignmentMode)
extern CONFIG_ENUM_LOCALE(type) g_##type##_locale; \ extern CONFIG_ENUM_LOCALE(type) g_##type##_locale; \
ConfigDef<type> Config::name{section, #name, &g_##name##_locale, defaultValue, &g_##type##_template, &g_##type##_locale}; ConfigDef<type> Config::name{section, #name, &g_##name##_locale, defaultValue, &g_##type##_template, &g_##type##_locale};
#undef CONFIG_DEFINE_ENUM_LOCALISED_HIDDEN
#define CONFIG_DEFINE_ENUM_LOCALISED_HIDDEN(section, type, name, defaultValue) \
extern CONFIG_LOCALE g_##name##_locale; \
extern CONFIG_ENUM_LOCALE(type) g_##type##_locale; \
ConfigDef<type, true> Config::name{section, #name, &g_##name##_locale, defaultValue, &g_##type##_template, &g_##type##_locale};
#include "config_def.h" #include "config_def.h"
// CONFIG_DEFINE // CONFIG_DEFINE
@ -594,6 +601,58 @@ std::string ConfigDef<T, isHidden>::GetValueLocalised(ELanguage language) const
return ToString(false); return ToString(false);
} }
template<typename T, bool isHidden>
bool ConfigDef<T, isHidden>::ShouldShowCurrentAPI() const
{
if constexpr (std::is_same_v<T, EGraphicsAPI>)
{
return Value == EGraphicsAPI::Auto &&
Config::GraphicsAPI.Value == EGraphicsAPI::Auto &&
Video::IsCurrentAPIChosenByAuto();
}
return false;
}
template<typename T, bool isHidden>
std::string ConfigDef<T, isHidden>::GetCurrentAPIName(const ELanguage* languages, CONFIG_ENUM_LOCALE(T)* locale) const
{
if constexpr (std::is_same_v<T, EGraphicsAPI>)
{
EGraphicsAPI currentAPI = Video::GetCurrentGraphicsAPI();
if (currentAPI == EGraphicsAPI::Auto) return "";
for (auto langToFind : {languages[0], languages[1]})
{
auto langFindResult = locale->find(langToFind);
if (langFindResult != locale->end())
{
auto apiFindResult = langFindResult->second.find(currentAPI);
if (apiFindResult != langFindResult->second.end())
{
return std::get<0>(apiFindResult->second);
}
}
if (langToFind == ELanguage::English) break;
}
}
return "";
}
template<typename T, bool isHidden>
std::string ConfigDef<T, isHidden>::GetCurrentAPIText(ELanguage language, const std::string& apiName) const
{
switch (language)
{
case ELanguage::English: return " Currently using: " + apiName;
case ELanguage::Japanese: return " [現在:げんざい][使用中:しようちゅう]: " + apiName;
case ELanguage::German: return " Derzeit verwendet: " + apiName;
case ELanguage::French: return " Actuellement utilisé : " + apiName;
case ELanguage::Spanish: return " Actualmente usando: " + apiName;
case ELanguage::Italian: return " Attualmente in uso: " + apiName;
default: return " Currently using: " + apiName;
}
}
template<typename T, bool isHidden> template<typename T, bool isHidden>
std::string ConfigDef<T, isHidden>::GetValueDescription(ELanguage language) const std::string ConfigDef<T, isHidden>::GetValueDescription(ELanguage language) const
{ {
@ -620,7 +679,24 @@ std::string ConfigDef<T, isHidden>::GetValueDescription(ELanguage language) cons
{ {
auto valueFindResult = languageFindResult->second.find(Value); auto valueFindResult = languageFindResult->second.find(Value);
if (valueFindResult != languageFindResult->second.end()) if (valueFindResult != languageFindResult->second.end())
return std::get<1>(valueFindResult->second); {
std::string description = std::get<1>(valueFindResult->second);
// Special case for EGraphicsAPI::Auto - append current API info
if constexpr (std::is_same_v<T, EGraphicsAPI>)
{
if (ShouldShowCurrentAPI())
{
std::string currentAPIText = GetCurrentAPIName(languages, locale);
if (!currentAPIText.empty())
{
description += GetCurrentAPIText(language, currentAPIText);
}
}
}
return description;
}
} }
if (languageToFind == ELanguage::English) if (languageToFind == ELanguage::English)

View file

@ -200,6 +200,13 @@ public:
void GetLocaleStrings(std::vector<std::string_view>& localeStrings) const override; void GetLocaleStrings(std::vector<std::string_view>& localeStrings) const override;
void SnapToNearestAccessibleValue(bool searchUp) override; void SnapToNearestAccessibleValue(bool searchUp) override;
private:
// Graphics API dynamic text
bool ShouldShowCurrentAPI() const;
std::string GetCurrentAPIName(const ELanguage* languages, CONFIG_ENUM_LOCALE(T)* locale) const;
std::string GetCurrentAPIText(ELanguage language, const std::string& apiName) const;
public:
operator T() const operator T() const
{ {
return Value; return Value;
@ -219,6 +226,7 @@ public:
#define CONFIG_DEFINE_LOCALISED(section, type, name, defaultValue) CONFIG_DECLARE(type, name) #define CONFIG_DEFINE_LOCALISED(section, type, name, defaultValue) CONFIG_DECLARE(type, name)
#define CONFIG_DEFINE_ENUM(section, type, name, defaultValue) CONFIG_DECLARE(type, name) #define CONFIG_DEFINE_ENUM(section, type, name, defaultValue) CONFIG_DECLARE(type, name)
#define CONFIG_DEFINE_ENUM_LOCALISED(section, type, name, defaultValue) CONFIG_DECLARE(type, name) #define CONFIG_DEFINE_ENUM_LOCALISED(section, type, name, defaultValue) CONFIG_DECLARE(type, name)
#define CONFIG_DEFINE_ENUM_LOCALISED_HIDDEN(section, type, name, defaultValue) CONFIG_DECLARE_HIDDEN(type, name)
class Config class Config
{ {

View file

@ -47,7 +47,12 @@ 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, ""); CONFIG_DEFINE("Video", std::string, GraphicsDevice, "");
CONFIG_DEFINE_ENUM("Video", EGraphicsAPI, GraphicsAPI, EGraphicsAPI::Auto); #ifdef UNLEASHED_RECOMP_D3D12
CONFIG_DEFINE_ENUM_LOCALISED("Video", EGraphicsAPI, GraphicsAPI, EGraphicsAPI::Auto);
#else
// Hide Graphics API setting for Vulkan-only builds
CONFIG_DEFINE_ENUM_LOCALISED_HIDDEN("Video", EGraphicsAPI, GraphicsAPI, EGraphicsAPI::Vulkan);
#endif
CONFIG_DEFINE("Video", int32_t, WindowX, WINDOWPOS_CENTRED); CONFIG_DEFINE("Video", int32_t, WindowX, WINDOWPOS_CENTRED);
CONFIG_DEFINE("Video", int32_t, WindowY, WINDOWPOS_CENTRED); CONFIG_DEFINE("Video", int32_t, WindowY, WINDOWPOS_CENTRED);
CONFIG_DEFINE_LOCALISED("Video", int32_t, WindowSize, -1); CONFIG_DEFINE_LOCALISED("Video", int32_t, WindowSize, -1);