Add fallback for creating other video backends. (#254)

* Add fallback for creating other video backends.

* Update video.cpp
This commit is contained in:
Darío 2025-01-31 09:45:48 -03:00 committed by GitHub
parent ddd8ce77db
commit 54d5588d79
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 65 additions and 15 deletions

View file

@ -95,6 +95,14 @@ namespace plume
#else
extern std::unique_ptr<RenderInterface> CreateVulkanInterface();
#endif
static std::unique_ptr<RenderInterface> CreateVulkanInterfaceWrapper() {
#ifdef SDL_VULKAN_ENABLED
return CreateVulkanInterface(GameWindow::s_renderWindow);
#else
return CreateVulkanInterface();
#endif
}
}
#pragma pack(push, 1)
@ -1472,7 +1480,7 @@ static void BeginCommandList()
commandList->setGraphicsDescriptorSet(g_samplerDescriptorSet.get(), 3);
}
void Video::CreateHostDevice(const char *sdlVideoDriver)
bool Video::CreateHostDevice(const char *sdlVideoDriver)
{
for (uint32_t i = 0; i < 16; i++)
g_inputSlots[i].index = i;
@ -1487,20 +1495,39 @@ void Video::CreateHostDevice(const char *sdlVideoDriver)
g_vulkan = DetectWine() || Config::GraphicsAPI == EGraphicsAPI::Vulkan;
#endif
LoadEmbeddedResources();
// Attempt to create the possible backends using a vector of function pointers. Whichever succeeds first will be the chosen API.
using RenderInterfaceFunction = std::unique_ptr<RenderInterface>(void);
std::vector<RenderInterfaceFunction *> interfaceFunctions;
if (g_vulkan)
#ifdef SDL_VULKAN_ENABLED
g_interface = CreateVulkanInterface(GameWindow::s_renderWindow);
#else
g_interface = CreateVulkanInterface();
#endif
#ifdef UNLEASHED_RECOMP_D3D12
else
g_interface = CreateD3D12Interface();
interfaceFunctions.push_back(g_vulkan ? CreateVulkanInterfaceWrapper : CreateD3D12Interface);
interfaceFunctions.push_back(g_vulkan ? CreateD3D12Interface : CreateVulkanInterfaceWrapper);
#else
interfaceFunctions.push_back(CreateVulkanInterfaceWrapper);
#endif
for (RenderInterfaceFunction *interfaceFunction : interfaceFunctions)
{
g_interface = interfaceFunction();
if (g_interface != nullptr)
{
g_device = g_interface->createDevice();
if (g_device != nullptr)
{
#ifdef UNLEASHED_RECOMP_D3D12
g_vulkan = (interfaceFunction == CreateVulkanInterfaceWrapper);
#endif
break;
}
}
}
if (g_device == nullptr)
{
return false;
}
LoadEmbeddedResources();
g_capabilities = g_device->getCapabilities();
@ -1712,6 +1739,8 @@ void Video::CreateHostDevice(const char *sdlVideoDriver)
blankTextureBarriers[i] = RenderTextureBarrier(g_blankTextures[i].get(), RenderTextureLayout::SHADER_READ);
g_commandLists[g_frame]->barriers(RenderBarrierStage::NONE, blankTextureBarriers, std::size(blankTextureBarriers));
return true;
}
void Video::WaitForGPU()
@ -2068,6 +2097,10 @@ static void DrawProfiler()
ImGui::Text("Triangle Fan: %s", g_capabilities.triangleFan ? "Supported" : "Unsupported");
ImGui::NewLine();
ImGui::Text("API: %s", g_vulkan ? "Vulkan" : "D3D12");
ImGui::Text("Device: %s", g_device->getDescription().name.c_str());
ImGui::Text("VRAM: %.2f MiB", (double)(g_device->getDescription().dedicatedVideoMemory) / (1024.0 * 1024.0));
const char* sdlVideoDriver = SDL_GetCurrentVideoDriver();
if (sdlVideoDriver != nullptr)
ImGui::Text("SDL Video Driver: %s", sdlVideoDriver);

View file

@ -18,7 +18,7 @@ struct Video
static inline uint32_t s_viewportWidth;
static inline uint32_t s_viewportHeight;
static void CreateHostDevice(const char *sdlVideoDriver);
static bool CreateHostDevice(const char *sdlVideoDriver);
static void WaitOnSwapChain();
static void Present();
static void StartPipelinePrecompilation();

View file

@ -377,6 +377,12 @@ std::unordered_map<std::string, std::unordered_map<ELanguage, std::string>> g_lo
{ ELanguage::English, "The achievement data could not be loaded.\nYour achievements will not be saved." }
}
},
{
"Video_BackendError",
{
{ ELanguage::English, "Unable to create a D3D12 (Windows) or Vulkan backend.\n\nPlease make sure that:\n\n- Your system meets the minimum requirements.\n- Your GPU drivers are up to date.\n- Your operating system is on the latest version available." },
}
},
{
"Common_On",
{

View file

@ -18,6 +18,7 @@
#include <os/logger.h>
#include <os/process.h>
#include <os/registry.h>
#include <ui/game_window.h>
#include <ui/installer_wizard.h>
#include <mod/mod_loader.h>
@ -182,7 +183,11 @@ int main(int argc, char *argv[])
bool runInstallerWizard = forceInstaller || forceDLCInstaller || !isGameInstalled;
if (runInstallerWizard)
{
Video::CreateHostDevice(sdlVideoDriver);
if (!Video::CreateHostDevice(sdlVideoDriver))
{
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, GameWindow::GetTitle(), Localise("Video_BackendError").c_str(), GameWindow::s_pWindow);
return 1;
}
if (!InstallerWizard::Run(GAME_INSTALL_DIRECTORY, isGameInstalled && forceDLCInstaller))
{
@ -197,7 +202,13 @@ int main(int argc, char *argv[])
uint32_t entry = LdrLoadModule(modulePath);
if (!runInstallerWizard)
Video::CreateHostDevice(sdlVideoDriver);
{
if (!Video::CreateHostDevice(sdlVideoDriver))
{
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, GameWindow::GetTitle(), Localise("Video_BackendError").c_str(), GameWindow::s_pWindow);
return 1;
}
}
Video::StartPipelinePrecompilation();

View file

@ -12,7 +12,7 @@
class GameWindow
{
public:
static inline SDL_Window* s_pWindow;
static inline SDL_Window* s_pWindow = nullptr;
static inline plume::RenderWindow s_renderWindow;
static inline int s_x;