From 176f56da8d55a414ca19d83c06ca6103282b25c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 27 Oct 2026 10:12:32 +0100 Subject: [PATCH] Implement support for setting two common driver flags for Turnip (custom Adreno driver) enable_tp_ubwc_flag_hint and storage_8bit are now available as check boxes on the driver setup screen. Fixes #22808 --- Common/CMakeLists.txt | 1 + Common/Common.vcxproj | 1 + Common/Common.vcxproj.filters | 3 +++ Common/GPU/Vulkan/VulkanDriverVars.h | 17 ++++++++++++++ Common/GPU/Vulkan/VulkanLoader.cpp | 35 ++++++++++++++++++++++++++++ Common/GPU/Vulkan/VulkanLoader.h | 3 +++ Core/Config.cpp | 9 +++++++ Core/Config.h | 1 + UI/DeveloperSettingsPages.cpp | 2 +- UI/DriverManagerScreen.cpp | 12 +++++++++- 10 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 Common/GPU/Vulkan/VulkanDriverVars.h diff --git a/Common/CMakeLists.txt b/Common/CMakeLists.txt index f86cffe35a..29b2a2ed3d 100644 --- a/Common/CMakeLists.txt +++ b/Common/CMakeLists.txt @@ -200,6 +200,7 @@ add_library(Common STATIC GPU/Vulkan/VulkanBarrier.h GPU/Vulkan/VulkanDebug.cpp GPU/Vulkan/VulkanDebug.h + GPU/Vulkan/VulkanDriverVars.h GPU/Vulkan/VulkanContext.cpp GPU/Vulkan/VulkanContext.h GPU/Vulkan/FixedSPIRVCache.h diff --git a/Common/Common.vcxproj b/Common/Common.vcxproj index f618df14f5..f922675333 100644 --- a/Common/Common.vcxproj +++ b/Common/Common.vcxproj @@ -452,6 +452,7 @@ + diff --git a/Common/Common.vcxproj.filters b/Common/Common.vcxproj.filters index ee58c22799..26c4ae712e 100644 --- a/Common/Common.vcxproj.filters +++ b/Common/Common.vcxproj.filters @@ -821,6 +821,9 @@ Render + + GPU\Vulkan + diff --git a/Common/GPU/Vulkan/VulkanDriverVars.h b/Common/GPU/Vulkan/VulkanDriverVars.h new file mode 100644 index 0000000000..34ec7c299c --- /dev/null +++ b/Common/GPU/Vulkan/VulkanDriverVars.h @@ -0,0 +1,17 @@ +#pragma once + +#include +#include "Common/Common.h" + +enum class AdrenoEnvVar : int { + enable_tp_ubwc_flag_hint = (1 << 0), + storage_8bit = (1 << 1), +}; +ENUM_CLASS_BITOPS(AdrenoEnvVar); + +struct AdrenoEnvVarDef { + std::string_view name; + AdrenoEnvVar var; +}; + +const AdrenoEnvVarDef *GetAdrenoEnvVarDefs(int *count); diff --git a/Common/GPU/Vulkan/VulkanLoader.cpp b/Common/GPU/Vulkan/VulkanLoader.cpp index a574926328..6906331f4c 100644 --- a/Common/GPU/Vulkan/VulkanLoader.cpp +++ b/Common/GPU/Vulkan/VulkanLoader.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include "Core/Config.h" #include "Common/Data/Format/JSONReader.h" @@ -385,6 +386,8 @@ static VulkanLibraryHandle VulkanLoadLibrary(std::string *errorString) { File::CreateDir(tempDir); File::CreateDir(fileRedirectDir); + // Driver workaround through environment variables must have been applied before this (AdrenoEnvVar). + lib = adrenotools_open_libvulkan( RTLD_NOW | RTLD_LOCAL, ADRENOTOOLS_DRIVER_FILE_REDIRECT | ADRENOTOOLS_DRIVER_CUSTOM, (std::string(tempDir.c_str()) + "/").c_str(), g_nativeLibDir.c_str(), @@ -1007,3 +1010,35 @@ const char *VulkanResultToString(VkResult res) { return temp; } } + +static const AdrenoEnvVarDef adrenoEnvVarDefs[] = { + {"enable_tp_ubwc_flag_hint", AdrenoEnvVar::enable_tp_ubwc_flag_hint}, + {"storage_8bit", AdrenoEnvVar::storage_8bit}, +}; + +const AdrenoEnvVarDef *GetAdrenoEnvVarDefs(int *count) { + *count = ARRAY_SIZE(adrenoEnvVarDefs); + return adrenoEnvVarDefs; +} + +void VulkanApplyCustomDriverEnvVars(AdrenoEnvVar envVars) { + std::string FD_DEV_FEATURES; + for (int i = 0; i < ARRAY_SIZE(adrenoEnvVarDefs); i++) { + const char *value = (envVars & adrenoEnvVarDefs[i].var) ? "1" : "0"; + if (!FD_DEV_FEATURES.empty()) { + FD_DEV_FEATURES += ","; + } + FD_DEV_FEATURES += adrenoEnvVarDefs[i].name; + FD_DEV_FEATURES += "="; + FD_DEV_FEATURES += value; + } + + // Simply set the environment variable, AdrenoTools will pick it up. +#if PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(LINUX) + setenv("FD_DEV_FEATURES", FD_DEV_FEATURES.c_str(), 1); // 1 = overwrite existing value +#else + WARN_LOG(Log::G3D, "VulkanApplyCustomDriverEnvVars: Not supported on this platform. (%s)", FD_DEV_FEATURES.c_str()); +#endif +} + +const AdrenoEnvVarDef *GetAdrenoEnvVarDefs(int *count); diff --git a/Common/GPU/Vulkan/VulkanLoader.h b/Common/GPU/Vulkan/VulkanLoader.h index 879b372043..fed9b7ba1f 100644 --- a/Common/GPU/Vulkan/VulkanLoader.h +++ b/Common/GPU/Vulkan/VulkanLoader.h @@ -18,6 +18,7 @@ #pragma once #include "ppsspp_config.h" +#include "Common/GPU/Vulkan/VulkanDriverVars.h" #if PPSSPP_PLATFORM(ANDROID) #define VK_USE_PLATFORM_ANDROID_KHR @@ -286,6 +287,8 @@ struct VulkanExtensions { // bool EXT_depth_range_unrestricted; // Allows depth outside [0.0, 1.0] in 32-bit float depth buffers. }; +void VulkanApplyCustomDriverEnvVars(AdrenoEnvVar envVars); + // Way to do a quick check before even attempting to load. void VulkanSetNativeLibDir(std::string_view nativeLibDir); bool VulkanMayBeAvailable(); diff --git a/Core/Config.cpp b/Core/Config.cpp index 9c24f73ee7..c38b8debe3 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -754,6 +754,8 @@ bool Config::IsBackendEnabled(GPUBackend backend) { if (backend == GPUBackend::OPENGL) return false; #endif + // On normal boots, this is where the Vulkan driver gets loaded the first time, in this check. + // That's a bit weird actually. But at least the config is loaded. if (backend == GPUBackend::VULKAN && !VulkanMayBeAvailable()) return false; return true; @@ -920,6 +922,7 @@ static constexpr ConfigSetting graphicsSettings[] = { .Label(I18NCat::GRAPHICS, "External display").Choices(externalDisplayNames), #if PPSSPP_PLATFORM(ANDROID) && PPSSPP_ARCH(ARM64) ConfigSetting("CustomDriver", SETTING(g_Config, sCustomDriver), "", CfgFlag::DEFAULT), + ConfigSetting("AdrenoDriverVars", SETTING(g_Config, iAdrenoEnvVars), 0, CfgFlag::DEFAULT), #endif ConfigSetting("DisabledGraphicsBackends", SETTING(g_Config, sDisabledGPUBackends), "", CfgFlag::DEFAULT), ConfigSetting("VulkanDevice", SETTING(g_Config, sVulkanDevice), "", CfgFlag::DEFAULT) @@ -2050,6 +2053,12 @@ void Config::PostLoadCleanup() { iGPUBackend = (int)GPUBackend::DIRECT3D11; #endif + // IsBackendEnabled below triggers a Vulkan driver load. So we must first apply the environment vars for custom drivers, + // so the environment variables are set on load. Not super pretty. + if (!g_Config.sCustomDriver.empty()) { + VulkanApplyCustomDriverEnvVars((AdrenoEnvVar)g_Config.iAdrenoEnvVars); + } + if (!IsBackendEnabled((GPUBackend)iGPUBackend)) { ERROR_LOG(Log::G3D, "Backend %d not enabled - switching to platform default", iGPUBackend); iGPUBackend = (int)DefaultGPUBackend(); diff --git a/Core/Config.h b/Core/Config.h index e0ea676739..3a981eafd4 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -301,6 +301,7 @@ public: int iGPUBackend; int iExternalDisplay; // ExternalDisplayMode std::string sCustomDriver; + int iAdrenoEnvVars; // AdrenoEnvVars std::string sFailedGPUBackends; // NOT stored in ppsspp.ini anymore! std::string sDisabledGPUBackends; // We have separate device parameters for each backend so it doesn't get erased if you switch backends. diff --git a/UI/DeveloperSettingsPages.cpp b/UI/DeveloperSettingsPages.cpp index 1646226516..9e9b995dc6 100644 --- a/UI/DeveloperSettingsPages.cpp +++ b/UI/DeveloperSettingsPages.cpp @@ -67,7 +67,7 @@ static bool SupportsCustomDriver() { static bool SupportsCustomDriver() { #ifdef _DEBUG - return false; // change to true to debug driver installation on other platforms + return false; // change to true to debug driver installation on other platforms. DO NOT commit as true. #else return false; #endif diff --git a/UI/DriverManagerScreen.cpp b/UI/DriverManagerScreen.cpp index 51ae7a6950..91007188c0 100644 --- a/UI/DriverManagerScreen.cpp +++ b/UI/DriverManagerScreen.cpp @@ -3,6 +3,7 @@ #include "Common/Data/Text/I18n.h" #include "Common/System/Request.h" #include "Common/System/OSD.h" +#include "Common/GPU/Vulkan/VulkanDriverVars.h" #include "Common/Log.h" #include "Common/StringUtils.h" #include "Common/UI/PopupScreens.h" @@ -165,12 +166,21 @@ void DriverManagerScreen::CreateDriverTab(UI::ViewGroup *drivers) { auto di = GetI18NCategory(I18NCat::DIALOG); auto gr = GetI18NCategory(I18NCat::GRAPHICS); - ChoiceGroup *driverManagerGroup = drivers->Add(new ChoiceGroupList())->Add(new ChoiceGroup(gr->T("AdrenoTools driver manager"))); + ChoiceGroupList *groups = drivers->Add(new ChoiceGroupList()); + + ChoiceGroup *driverManagerGroup = groups->Add(new ChoiceGroup(gr->T("AdrenoTools driver manager"))); auto customDriverInstallChoice = driverManagerGroup->Add(new Choice(gr->T("Install custom driver..."))); driverManagerGroup->Add(new Choice(di->T("More info")))->OnClick.Add([=](UI::EventParams &e) { System_LaunchUrl(LaunchUrlType::BROWSER_URL, "https://www.ppsspp.org/docs/reference/custom-drivers/"); }); + ChoiceGroup *adrenoEnvVarGroup = groups->Add(new ChoiceGroup(gr->T("Turnip driver flags"))); + int count = 0; + const AdrenoEnvVarDef *adrenoEnvVarDefs = GetAdrenoEnvVarDefs(&count); + for (int i = 0; i < count; i++) { + adrenoEnvVarGroup->Add(new BitCheckBox(&g_Config.iAdrenoEnvVars, (int)adrenoEnvVarDefs[i].var, adrenoEnvVarDefs[i].name)); + } + customDriverInstallChoice->OnClick.Handle(this, &DriverManagerScreen::OnCustomDriverInstall); drivers->Add(new ItemHeader(gr->T("Drivers")));