diff --git a/CMakeLists.txt b/CMakeLists.txt index 593d73bc..2cd269cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,6 +98,7 @@ set(Sources "Source/VulkanDevice_Dev.cpp" "Source/JsonParser.cpp" "Source/SceneMeta.cpp" + "Source/Streamline.cpp" ) diff --git a/Source/Streamline.cpp b/Source/Streamline.cpp new file mode 100644 index 00000000..e957ac84 --- /dev/null +++ b/Source/Streamline.cpp @@ -0,0 +1,320 @@ +// Copyright (c) 2023 Sultim Tsyrendashiev +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#include "Streamline.h" +#include "Streamline.h" +#include "Streamline.h" + +#include "RgException.h" + +namespace +{ + +static_assert( uint32_t( sl::FunctionHookID::eMaxNum ) == 20, + "Recheck functions that need to be hooked" ); + +void ResetStreamlineVkFunctionsToDefault() +{ + RTGL1::svkCreateInstance = vkCreateInstance; + RTGL1::svkCreateWin32SurfaceKHR = vkCreateWin32SurfaceKHR; + RTGL1::svkDestroySurfaceKHR = vkDestroySurfaceKHR; + + RTGL1::svkCreateDevice = vkCreateDevice; + RTGL1::svkQueuePresentKHR = vkQueuePresentKHR; + RTGL1::svkCreateSwapchainKHR = vkCreateSwapchainKHR; + RTGL1::svkDestroySwapchainKHR = vkDestroySwapchainKHR; + RTGL1::svkGetSwapchainImagesKHR = vkGetSwapchainImagesKHR; + RTGL1::svkAcquireNextImageKHR = vkAcquireNextImageKHR; + RTGL1::svkDeviceWaitIdle = vkDeviceWaitIdle; +} + +auto FindInterposerDll( const std::filesystem::path& binFolder ) -> HMODULE +{ + assert( binFolder.is_absolute() ); + + auto dllPath = binFolder / "sl.interposer.dll"; + + if( !sl::security::verifyEmbeddedSignature( dllPath.c_str() ) ) + { + RTGL1::debug::Error( "Failed to verify signature for NVIDIA Streamline: {}", + dllPath.string() ); + return nullptr; + } + + return LoadLibrary( dllPath.string().c_str() ); +} + +auto FetchFunctions( HMODULE interposerDll ) -> std::optional< RTGL1::Streamline::Pfn > +{ + if( !interposerDll ) + { + return {}; + } + + auto fetchInto = [ interposerDll ]< typename T >( T* dst, const char* name ) { + if( auto f = reinterpret_cast< T >( GetProcAddress( interposerDll, name ) ) ) + { + *dst = f; + return true; + } + RTGL1::debug::Warning( "(NVIDIA Streamline) Failed to fetch function: {}", name ); + return false; + }; + + // clang-format off + auto pfn = RTGL1::Streamline::Pfn{}; + if( !fetchInto( &pfn.slInit , "slInit" ) ) { return {}; } + if( !fetchInto( &pfn.slShutdown , "slShutdown" ) ) { return {}; } + if( !fetchInto( &pfn.slIsFeatureSupported , "slIsFeatureSupported" ) ) { return {}; } + if( !fetchInto( &pfn.slIsFeatureLoaded , "slIsFeatureLoaded" ) ) { return {}; } + if( !fetchInto( &pfn.slSetFeatureLoaded , "slSetFeatureLoaded" ) ) { return {}; } + if( !fetchInto( &pfn.slEvaluateFeature , "slEvaluateFeature" ) ) { return {}; } + if( !fetchInto( &pfn.slAllocateResources , "slAllocateResources" ) ) { return {}; } + if( !fetchInto( &pfn.slFreeResources , "slFreeResources" ) ) { return {}; } + if( !fetchInto( &pfn.slSetTag , "slSetTag" ) ) { return {}; } + if( !fetchInto( &pfn.slGetFeatureRequirements , "slGetFeatureRequirements" ) ) { return {}; } + if( !fetchInto( &pfn.slGetFeatureVersion , "slGetFeatureVersion" ) ) { return {}; } + if( !fetchInto( &pfn.slUpgradeInterface , "slUpgradeInterface" ) ) { return {}; } + if( !fetchInto( &pfn.slSetConstants , "slSetConstants" ) ) { return {}; } + if( !fetchInto( &pfn.slGetNativeInterface , "slGetNativeInterface" ) ) { return {}; } + if( !fetchInto( &pfn.slGetFeatureFunction , "slGetFeatureFunction" ) ) { return {}; } + if( !fetchInto( &pfn.slGetNewFrameToken , "slGetNewFrameToken" ) ) { return {}; } + if( !fetchInto( &pfn.slSetVulkanInfo , "slSetVulkanInfo" ) ) { return {}; } + // clang-format on + + return pfn; +} + +auto FetchVkInstanceFunctions( RTGL1::Streamline::Proxies& proxies, VkInstance instance ) + -> std::optional< RTGL1::Streamline::ProxiesVkInstance > +{ + auto fetchVkInto = [ &proxies, instance ]< typename T >( T* dst, const char* name ) { + if( auto f = reinterpret_cast< T >( proxies.vkGetInstanceProcAddr( instance, name ) ) ) + { + *dst = f; + return true; + } + RTGL1::debug::Warning( "(NVIDIA Streamline) Failed to fetch function: {}", name ); + return false; + }; + + // clang-format off + auto instPfn = RTGL1::Streamline::ProxiesVkInstance{}; + if( !fetchVkInto( &instPfn.vkCreateWin32SurfaceKHR , "vkCreateWin32SurfaceKHR" ) ) { return {}; } + if( !fetchVkInto( &instPfn.vkDestroySurfaceKHR , "vkDestroySurfaceKHR" ) ) { return {}; } + // clang-format on + + return instPfn; +} + +auto FetchVkDeviceFunctions( RTGL1::Streamline::Proxies& proxies, VkDevice device ) + -> std::optional< RTGL1::Streamline::ProxiesVkDevice > +{ + auto fetchVkInto = [ &proxies, device ]< typename T >( T* dst, const char* name ) { + if( auto f = reinterpret_cast< T >( proxies.vkGetDeviceProcAddr( device, name ) ) ) + { + *dst = f; + return true; + } + RTGL1::debug::Warning( "(NVIDIA Streamline) Failed to fetch function: {}", name ); + return false; + }; + + // clang-format off + auto dvcPfn = RTGL1::Streamline::ProxiesVkDevice{}; + if( !fetchVkInto( &dvcPfn.vkCreateDevice , "vkCreateDevice" ) ) { return {}; } + if( !fetchVkInto( &dvcPfn.vkQueuePresentKHR , "vkQueuePresentKHR" ) ) { return {}; } + if( !fetchVkInto( &dvcPfn.vkCreateSwapchainKHR , "vkCreateSwapchainKHR" ) ) { return {}; } + if( !fetchVkInto( &dvcPfn.vkDestroySwapchainKHR , "vkDestroySwapchainKHR" ) ) { return {}; } + if( !fetchVkInto( &dvcPfn.vkGetSwapchainImagesKHR , "vkGetSwapchainImagesKHR" ) ) { return {}; } + if( !fetchVkInto( &dvcPfn.vkAcquireNextImageKHR , "vkAcquireNextImageKHR" ) ) { return {}; } + if( !fetchVkInto( &dvcPfn.vkDeviceWaitIdle , "vkDeviceWaitIdle" ) ) { return {}; } + // clang-format on + + return dvcPfn; +} + +auto InitStreamline( HMODULE interposerDll, + RTGL1::Streamline::Pfn& pfn, + const char* pAppGUID, + const std::filesystem::path& binFolder, + bool isDebugBuild ) -> std::optional< RTGL1::Streamline::Proxies > +{ + assert( binFolder.is_absolute() ); + + using namespace RTGL1; + + { + const auto guidRegex = + std::regex{ "^[{]?[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}[}]?$" }; + + if( pAppGUID == nullptr ) + { + throw RgException( + RG_RESULT_WRONG_FUNCTION_ARGUMENT, + "Application GUID wasn't provided. Generate and specify it to use DLSS." ); + } + + if( !std::regex_match( pAppGUID, guidRegex ) ) + { + throw RgException( + RG_RESULT_WRONG_FUNCTION_ARGUMENT, + "Provided application GUID is not GUID. Generate and specify correct " + "GUID to use DLSS." ); + } + } + + + if( !interposerDll ) + { + return {}; + } + + auto fetchInto = [ interposerDll ]< typename T >( T* dst, const char* name ) { + if( auto f = reinterpret_cast< T >( GetProcAddress( interposerDll, name ) ) ) + { + *dst = f; + return true; + } + RTGL1::debug::Warning( "(NVIDIA Streamline) Failed to fetch function: {}", name ); + return false; + }; + + // clang-format off + auto proxies = Streamline::Proxies{}; + if( !fetchInto( &proxies.vkGetDeviceProcAddr , "vkGetDeviceProcAddr" ) ) { return {}; } + if( !fetchInto( &proxies.vkGetInstanceProcAddr , "vkGetInstanceProcAddr" ) ) { return {}; } + if( !fetchInto( &proxies.vkCreateInstance , "vkCreateInstance" ) ) { return {}; } + // clang-format on + + + const wchar_t* pluginFolder = binFolder.c_str(); + + auto pref = sl::Preferences{}; + { + pref.showConsole = isDebugBuild; + pref.logLevel = isDebugBuild ? sl::LogLevel::eVerbose : sl::LogLevel::eOff; + pref.logMessageCallback = []( sl::LogType type, const char* msg ) { + RgMessageSeverityFlags rgSeverity = + ( type == sl::LogType::eError ) ? RG_MESSAGE_SEVERITY_ERROR + : ( type == sl::LogType::eWarn ) ? RG_MESSAGE_SEVERITY_WARNING + : ( type == sl::LogType::eInfo ) ? RG_MESSAGE_SEVERITY_INFO + : RG_MESSAGE_SEVERITY_VERBOSE; + debug::detail::Print( rgSeverity, msg ); + }; + pref.numPathsToPlugins = 1; + pref.pathsToPlugins = &pluginFolder; + pref.flags = sl::PreferenceFlags::eUseManualHooking; + pref.engineVersion = RG_RTGL_VERSION_API; + pref.projectId = pAppGUID; + pref.renderAPI = sl::RenderAPI::eVulkan; + } + + if( SL_FAILED( slr, pfn.slInit( pref, sl::kSDKVersion ) ) ) + { + switch( slr ) + { + case sl::Result::eErrorDriverOutOfDate: + debug::Error( "(NVIDIA Streamline) Please, update to the latest drivers" ); + case sl::Result::eErrorOSOutOfDate: + debug::Error( "(NVIDIA Streamline) Please, update the Windows OS" ); + default: + debug::Error( "(NVIDIA Streamline) Failed to initialize Streamline. Error code: {}", + uint32_t( slr ) ); + } + + return {}; + } + + return proxies; +} + +} + +RTGL1::Streamline::Streamline( const char* pAppGUID, + const std::filesystem::path& binFolder, + bool isDebugBuild ) + : interposerDll{ FindInterposerDll( binFolder ) } + , pfn{ FetchFunctions( interposerDll ) } + , proxies{ pfn ? InitStreamline( interposerDll, *pfn, pAppGUID, binFolder, isDebugBuild ) + : std::nullopt } +{ +} + +RTGL1::Streamline::~Streamline() +{ + ResetStreamlineVkFunctionsToDefault(); +} + +bool RTGL1::Streamline::HookVkCreateInstanceFunction() +{ + if( proxies ) + { + RTGL1::svkCreateInstance = proxies->vkCreateInstance; + + assert( RTGL1::svkCreateInstance ); + return true; + } + return false; +} + +bool RTGL1::Streamline::HookVkInstanceFunctions( VkInstance instance ) +{ + if( proxies ) + { + if( auto f = FetchVkInstanceFunctions( *proxies, instance ) ) + { + RTGL1::svkCreateWin32SurfaceKHR = f->vkCreateWin32SurfaceKHR; + RTGL1::svkDestroySurfaceKHR = f->vkDestroySurfaceKHR; + + assert( RTGL1::svkCreateWin32SurfaceKHR ); + assert( RTGL1::svkDestroySurfaceKHR ); + return true; + } + } + return false; +} + +bool RTGL1::Streamline::HookVkDeviceFunctions( VkDevice device ) +{ + if( proxies ) + { + if( auto f = FetchVkDeviceFunctions( *proxies, device ) ) + { + RTGL1::svkCreateDevice = f->vkCreateDevice; + RTGL1::svkQueuePresentKHR = f->vkQueuePresentKHR; + RTGL1::svkCreateSwapchainKHR = f->vkCreateSwapchainKHR; + RTGL1::svkDestroySwapchainKHR = f->vkDestroySwapchainKHR; + RTGL1::svkGetSwapchainImagesKHR = f->vkGetSwapchainImagesKHR; + RTGL1::svkAcquireNextImageKHR = f->vkAcquireNextImageKHR; + RTGL1::svkDeviceWaitIdle = f->vkDeviceWaitIdle; + + assert( RTGL1::svkCreateDevice ); + assert( RTGL1::svkQueuePresentKHR ); + assert( RTGL1::svkCreateSwapchainKHR ); + assert( RTGL1::svkDestroySwapchainKHR ); + assert( RTGL1::svkGetSwapchainImagesKHR ); + assert( RTGL1::svkAcquireNextImageKHR ); + assert( RTGL1::svkDeviceWaitIdle ); + return true; + } + } + return false; +} diff --git a/Source/Streamline.h b/Source/Streamline.h new file mode 100644 index 00000000..a63530f5 --- /dev/null +++ b/Source/Streamline.h @@ -0,0 +1,107 @@ +// Copyright (c) 2023 Sultim Tsyrendashiev +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#pragma once + +#include "Common.h" + +#ifdef RG_USE_STREAMLINE + + #include + #include + #include + #include + #include + #include + + #include + #include + +namespace RTGL1 +{ + + +struct Streamline +{ + Streamline( const char* pAppGUID, const std::filesystem::path& binFolder, bool isDebugBuild ); + ~Streamline(); + + Streamline( const Streamline& other ) = delete; + Streamline( Streamline&& other ) noexcept = delete; + Streamline& operator=( const Streamline& other ) = delete; + Streamline& operator=( Streamline&& other ) noexcept = delete; + + [[nodiscard]] bool HookVkCreateInstanceFunction(); + [[nodiscard]] bool HookVkInstanceFunctions( VkInstance instance ); + [[nodiscard]] bool HookVkDeviceFunctions( VkDevice device ); + + struct ProxiesVkInstance + { + PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR; + PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR; + }; + + struct ProxiesVkDevice + { + PFN_vkCreateDevice vkCreateDevice; + PFN_vkQueuePresentKHR vkQueuePresentKHR; + PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR; + PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR; + PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR; + PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR; + PFN_vkDeviceWaitIdle vkDeviceWaitIdle; + }; + + struct Proxies + { + PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr; + PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr; + PFN_vkCreateInstance vkCreateInstance; + }; + + struct Pfn + { + PFun_slInit* slInit; + PFun_slShutdown* slShutdown; + PFun_slIsFeatureSupported* slIsFeatureSupported; + PFun_slIsFeatureLoaded* slIsFeatureLoaded; + PFun_slSetFeatureLoaded* slSetFeatureLoaded; + PFun_slEvaluateFeature* slEvaluateFeature; + PFun_slAllocateResources* slAllocateResources; + PFun_slFreeResources* slFreeResources; + PFun_slSetTag* slSetTag; + PFun_slGetFeatureRequirements* slGetFeatureRequirements; + PFun_slGetFeatureVersion* slGetFeatureVersion; + PFun_slUpgradeInterface* slUpgradeInterface; + PFun_slSetConstants* slSetConstants; + PFun_slGetNativeInterface* slGetNativeInterface; + PFun_slGetFeatureFunction* slGetFeatureFunction; + PFun_slGetNewFrameToken* slGetNewFrameToken; + PFun_slSetVulkanInfo* slSetVulkanInfo; + }; + + HMODULE interposerDll; + std::optional< Pfn > pfn; + std::optional< Proxies > proxies; +}; + +} + +#endif \ No newline at end of file diff --git a/Source/VulkanDevice.h b/Source/VulkanDevice.h index 0582c915..9b0256b3 100644 --- a/Source/VulkanDevice.h +++ b/Source/VulkanDevice.h @@ -64,6 +64,7 @@ #include "SceneMeta.h" #include "DrawFrameInfo.h" #include "VulkanDevice_Dev.h" +#include "Streamline.h" // clang-format on namespace RTGL1 @@ -72,14 +73,6 @@ namespace RTGL1 struct Devmode; -struct StreamlineProxies -{ - PFN_vkGetDeviceProcAddr sl_vkGetDeviceProcAddr; - PFN_vkGetInstanceProcAddr sl_vkGetInstanceProcAddr; - PFN_vkCreateInstance sl_vkCreateInstance; -}; - - class VulkanDevice { public: @@ -237,7 +230,9 @@ class VulkanDevice ScratchImmediate scratchImmediate; std::unique_ptr< FolderObserver > observer; - std::optional< StreamlineProxies > slProxies; +#ifdef RG_USE_STREAMLINE + std::shared_ptr< Streamline > streamline; +#endif struct CameraInfo { diff --git a/Source/VulkanDevice_Init.cpp b/Source/VulkanDevice_Init.cpp index 2ca7139a..d315101e 100644 --- a/Source/VulkanDevice_Init.cpp +++ b/Source/VulkanDevice_Init.cpp @@ -28,136 +28,13 @@ #include "JsonParser.h" #include "RenderResolutionHelper.h" #include "RgException.h" +#include "Streamline.h" #include "Generated/ShaderCommonC.h" -#ifdef RG_USE_STREAMLINE - #include - #include - #include - #include - #include - #include -#endif - -#include - namespace { -void ResetStreamlineVkFunctionsToDefault() -{ - RTGL1::svkCreateInstance = vkCreateInstance; - RTGL1::svkCreateWin32SurfaceKHR = vkCreateWin32SurfaceKHR; - RTGL1::svkDestroySurfaceKHR = vkDestroySurfaceKHR; - - RTGL1::svkCreateDevice = vkCreateDevice; - RTGL1::svkQueuePresentKHR = vkQueuePresentKHR; - RTGL1::svkCreateSwapchainKHR = vkCreateSwapchainKHR; - RTGL1::svkDestroySwapchainKHR = vkDestroySwapchainKHR; - RTGL1::svkGetSwapchainImagesKHR = vkGetSwapchainImagesKHR; - RTGL1::svkAcquireNextImageKHR = vkAcquireNextImageKHR; - RTGL1::svkDeviceWaitIdle = vkDeviceWaitIdle; -} - -#if RG_USE_STREAMLINE -auto InitStreamline( const char* pAppGUID, - const std::filesystem::path& binFolder, - bool isDebugBuild ) -> std::optional< RTGL1::StreamlineProxies > -{ - assert( binFolder.is_absolute() ); - - using namespace RTGL1; - - { - const auto guidRegex = - std::regex{ "^[{]?[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}[}]?$" }; - - if( pAppGUID == nullptr ) - { - throw RgException( - RG_RESULT_WRONG_FUNCTION_ARGUMENT, - "Application GUID wasn't provided. Generate and specify it to use DLSS." ); - } - - if( !std::regex_match( pAppGUID, guidRegex ) ) - { - throw RgException( - RG_RESULT_WRONG_FUNCTION_ARGUMENT, - "Provided application GUID is not GUID. Generate and specify correct " - "GUID to use DLSS." ); - } - } - - - - // TODO: !!! dynamically link to sl.interposer.dll !!! - - - - auto pathToSlInterposer = binFolder / "sl.interposer.dll"; - - if( !sl::security::verifyEmbeddedSignature( pathToSlInterposer.c_str() ) ) - { - debug::Error( "Failed to verify signature for NVIDIA Streamline: {}", - pathToSlInterposer.string() ); - return {}; - } - - HMODULE slModule = LoadLibrary( pathToSlInterposer.string().c_str() ); - - // clang-format off - auto proxies = StreamlineProxies{ - .sl_vkGetDeviceProcAddr = reinterpret_cast< PFN_vkGetDeviceProcAddr >( GetProcAddress( slModule, "vkGetDeviceProcAddr" ) ), - .sl_vkGetInstanceProcAddr = reinterpret_cast< PFN_vkGetInstanceProcAddr >( GetProcAddress( slModule, "vkGetInstanceProcAddr" ) ), - .sl_vkCreateInstance = reinterpret_cast< PFN_vkCreateInstance >( GetProcAddress( slModule, "vkCreateInstance" ) ), - }; - // clang-format on - static_assert( uint32_t( sl::FunctionHookID::eMaxNum ) == 20, - "Recheck functions that need to be hooked" ); - - const wchar_t* pluginFolder = binFolder.c_str(); - - auto pref = sl::Preferences{}; - { - pref.showConsole = isDebugBuild; - pref.logLevel = isDebugBuild ? sl::LogLevel::eVerbose : sl::LogLevel::eOff; - pref.logMessageCallback = []( sl::LogType type, const char* msg ) { - RgMessageSeverityFlags rgSeverity = - ( type == sl::LogType::eError ) ? RG_MESSAGE_SEVERITY_ERROR - : ( type == sl::LogType::eWarn ) ? RG_MESSAGE_SEVERITY_WARNING - : ( type == sl::LogType::eInfo ) ? RG_MESSAGE_SEVERITY_INFO - : RG_MESSAGE_SEVERITY_VERBOSE; - debug::detail::Print( rgSeverity, msg ); - }; - pref.numPathsToPlugins = 1; - pref.pathsToPlugins = &pluginFolder; - pref.flags = sl::PreferenceFlags::eUseManualHooking; - pref.engineVersion = RG_RTGL_VERSION_API; - pref.projectId = pAppGUID; - pref.renderAPI = sl::RenderAPI::eVulkan; - } - - if( SL_FAILED( slr, slInit( pref ) ) ) - { - switch( slr ) - { - case sl::Result::eErrorDriverOutOfDate: - debug::Error( "(NVIDIA Streamline) Please, update to the latest drivers" ); - case sl::Result::eErrorOSOutOfDate: - debug::Error( "(NVIDIA Streamline) Please, update the Windows OS" ); - default: - debug::Error( "(NVIDIA Streamline) Failed to initialize Streamline. Error code: {}", - uint32_t( slr ) ); - } - - return {}; - } - - return proxies; -} -#endif - VkSurfaceKHR GetSurfaceFromUser( VkInstance instance, const RgInstanceCreateInfo& info ) { using namespace RTGL1; @@ -746,17 +623,15 @@ VKAPI_ATTR VkBool32 VKAPI_CALL void RTGL1::VulkanDevice::CreateInstance( const RgInstanceCreateInfo& info ) { { - ResetStreamlineVkFunctionsToDefault(); - #ifdef RG_USE_STREAMLINE - slProxies = InitStreamline( + streamline = std::make_shared< Streamline >( info.pAppGUID, absolute( ovrdFolder / BIN_FOLDER ), libconfig.dlssValidation ); -#endif - if( slProxies ) + if( !streamline->HookVkCreateInstanceFunction() ) { - svkCreateInstance = slProxies->sl_vkCreateInstance; + streamline.reset(); } +#endif } std::vector< const char* > layerNames;