From 394451eeb698c44dd22da75c4838c5f142fae6cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Lewandowski?= <49685661+FakeMichau@users.noreply.github.com> Date: Mon, 24 Feb 2025 16:21:57 +0100 Subject: [PATCH] Support for Streamline v1 logging (#231) * Add streamline 1 logging * Add back log forwarding --- OptiScaler/proxies/Streamline_Proxy.h | 118 +++++-- external/streamline1/sl1.h | 426 ++++++++++++++++++++++++++ external/streamline1/sl1_consts.h | 217 +++++++++++++ 3 files changed, 729 insertions(+), 32 deletions(-) create mode 100644 external/streamline1/sl1.h create mode 100644 external/streamline1/sl1_consts.h diff --git a/OptiScaler/proxies/Streamline_Proxy.h b/OptiScaler/proxies/Streamline_Proxy.h index 737cb222..a7f77149 100644 --- a/OptiScaler/proxies/Streamline_Proxy.h +++ b/OptiScaler/proxies/Streamline_Proxy.h @@ -8,16 +8,14 @@ #include "detours/detours.h" #include +#include +static decltype(&slSetTag) o_slSetTag = nullptr; +static decltype(&slInit) o_slInit = nullptr; +static decltype(&sl1::slInit) o_slInit_sl1 = nullptr; -typedef int(*PFN_slSetTag)(uint64_t viewport, sl::ResourceTag* tags, uint32_t numTags, uint64_t cmdBuffer); -typedef int(*PFN_slInit)(sl::Preferences* pref, uint64_t sdkVersion); -typedef void(*PFN_LogCallback)(sl::LogType type, const char* msg); - -static PFN_slSetTag o_slSetTag = nullptr; -static PFN_slInit o_slInit = nullptr; - -static PFN_LogCallback o_logCallback = nullptr; +static sl::PFun_LogMessageCallback* o_logCallback = nullptr; +static sl1::pfunLogMessageCallback* o_logCallback_sl1 = nullptr; static char* trimStreamlineLog(const char* msg) { int bracket_count = 0; @@ -59,15 +57,16 @@ static void streamlineLogCallback(sl::LogType type, const char* msg) { o_logCallback(type, msg); } -static int hkslInit(sl::Preferences* pref, uint64_t sdkVersion) { +static sl::Result hkslInit(sl::Preferences* pref, uint64_t sdkVersion) { LOG_FUNC(); - // o_logCallback = pref->logMessageCallback; // causes a loop in cyberpunk on linux + if (pref->logMessageCallback != &streamlineLogCallback) + o_logCallback = pref->logMessageCallback; pref->logLevel = sl::LogLevel::eCount; pref->logMessageCallback = &streamlineLogCallback; - return o_slInit(pref, sdkVersion); + return o_slInit(*pref, sdkVersion); } -static int hkslSetTag(uint64_t viewport, sl::ResourceTag* tags, uint32_t numTags, uint64_t cmdBuffer) { +static sl::Result hkslSetTag(sl::ViewportHandle& viewport, sl::ResourceTag* tags, uint32_t numTags, sl::CommandBuffer* cmdBuffer) { for (uint32_t i = 0; i < numTags; i++) { if (State::Instance().gameQuirk == Cyberpunk && tags[i].type == 2 && tags[i].resource->state == (D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE)) { tags[i].resource->state = D3D12_RESOURCE_STATE_UNORDERED_ACCESS; @@ -78,20 +77,61 @@ static int hkslSetTag(uint64_t viewport, sl::ResourceTag* tags, uint32_t numTags return result; } +static void streamlineLogCallback_sl1(sl1::LogType type, const char* msg) { + char* trimmed_msg = trimStreamlineLog(msg); + + switch (type) { + case sl1::LogType::eLogTypeWarn: + LOG_WARN("{}", trimmed_msg); + break; + case sl1::LogType::eLogTypeInfo: + LOG_INFO("{}", trimmed_msg); + break; + case sl1::LogType::eLogTypeError: + LOG_ERROR("{}", trimmed_msg); + break; + case sl1::LogType::eLogTypeCount: + LOG_ERROR("{}", trimmed_msg); + break; + } + + free(trimmed_msg); + + if (o_logCallback_sl1) + o_logCallback_sl1(type, msg); +} + +static bool hkslInit_sl1(sl1::Preferences* pref, int applicationId) { + LOG_FUNC(); + if (pref->logMessageCallback != &streamlineLogCallback_sl1) + o_logCallback_sl1 = pref->logMessageCallback; + pref->logLevel = sl1::LogLevel::eLogLevelCount; + pref->logMessageCallback = &streamlineLogCallback_sl1; + return o_slInit_sl1(*pref, applicationId); +} + static void unhookStreamline() { DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); - if (o_slSetTag != nullptr) { + if (o_slSetTag) { DetourDetach(&(PVOID&)o_slSetTag, hkslSetTag); o_slSetTag = nullptr; } - if (o_slInit != nullptr) { + if (o_slInit) { DetourDetach(&(PVOID&)o_slInit, hkslInit); o_slInit = nullptr; } + if (o_slInit_sl1) { + DetourDetach(&(PVOID&)o_slInit_sl1, hkslInit_sl1); + o_slInit_sl1 = nullptr; + } + + o_logCallback_sl1 = nullptr; + o_logCallback = nullptr; + DetourTransactionCommit(); } @@ -99,34 +139,48 @@ static void unhookStreamline() { static void hookStreamline(HMODULE slInterposer) { LOG_FUNC(); - if (o_slSetTag != nullptr || o_slInit != nullptr) + if (!slInterposer) { + LOG_WARN("Streamline module in NULL"); + return; + } + + if (o_slSetTag || o_slInit || o_slInit_sl1) unhookStreamline(); if (Config::Instance()->FGType.value_or_default() == FGType::Nukems) { - o_slSetTag = reinterpret_cast(GetProcAddress(slInterposer, "slSetTag")); - o_slInit = reinterpret_cast(GetProcAddress(slInterposer, "slInit")); + char dllPath[MAX_PATH]; + GetModuleFileNameA(slInterposer, dllPath, MAX_PATH); + Util::version_t sl_version; + Util::GetDLLVersion(string_to_wstring(dllPath), &sl_version); + LOG_INFO("Streamline version: {}.{}.{}", sl_version.major, sl_version.minor, sl_version.patch); - if (o_slSetTag != nullptr && o_slInit != nullptr) { - DetourTransactionBegin(); - DetourUpdateThread(GetCurrentThread()); + if (sl_version.major >= 2) { + o_slSetTag = reinterpret_cast(GetProcAddress(slInterposer, "slSetTag")); + o_slInit = reinterpret_cast(GetProcAddress(slInterposer, "slInit")); - // Get a handle for sl.interposer and then the path - HMODULE hModule = nullptr; - char dllPath[MAX_PATH]; - GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, reinterpret_cast(o_slSetTag), &hModule); - GetModuleFileNameA(hModule, dllPath, MAX_PATH); + if (o_slSetTag != nullptr && o_slInit != nullptr) { + DetourTransactionBegin(); + DetourUpdateThread(GetCurrentThread()); - Util::version_t sl_version; - Util::GetDLLVersion(string_to_wstring(dllPath), &sl_version); - LOG_INFO("Streamline version: {}.{}.{}", sl_version.major, sl_version.minor, sl_version.patch); - - if (sl_version.major >= 2) { DetourAttach(&(PVOID&)o_slSetTag, hkslSetTag); DetourAttach(&(PVOID&)o_slInit, hkslInit); - } - DetourTransactionCommit(); + DetourTransactionCommit(); + } + } + else if (sl_version.major == 1) + { + o_slInit_sl1 = reinterpret_cast(GetProcAddress(slInterposer, "slInit")); + + if (o_slInit_sl1) { + DetourTransactionBegin(); + DetourUpdateThread(GetCurrentThread()); + + DetourAttach(&(PVOID&)o_slInit_sl1, hkslInit_sl1); + + DetourTransactionCommit(); + } } } } diff --git a/external/streamline1/sl1.h b/external/streamline1/sl1.h new file mode 100644 index 00000000..06023fd8 --- /dev/null +++ b/external/streamline1/sl1.h @@ -0,0 +1,426 @@ +/* +* Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved +* +* 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 "sl1_consts.h" + +//#define SL_API extern "C" +#define SL_API + +namespace sl1 { + + using CommandBuffer = void; + + //! Buffer types used for tagging + //! + //! IMPORTANT: Each tag must use the unique id + //! + enum BufferType : uint32_t + { + //! Depth buffer - IMPORTANT - Must be suitable to use with clipToPrevClip transformation (see Constants below) + eBufferTypeDepth, + //! Object and optional camera motion vectors (see Constants below) + eBufferTypeMVec, + //! Color buffer with all post-processing effects applied but without any UI/HUD elements + eBufferTypeHUDLessColor, + //! Color buffer containing jittered input data for the image scaling pass + eBufferTypeScalingInputColor, + //! Color buffer containing results from the image scaling pass + eBufferTypeScalingOutputColor, + //! Normals + eBufferTypeNormals, + //! Roughness + eBufferTypeRoughness, + //! Albedo + eBufferTypeAlbedo, + //! Specular Albedo + eBufferTypeSpecularAlbedo, + //! Indirect Albedo + eBufferTypeIndirectAlbedo, + //! Specular Mvec + eBufferTypeSpecularMVec, + //! Disocclusion Mask + eBufferTypeDisocclusionMask, + //! Emissive + eBufferTypeEmissive, + //! Exposure + eBufferTypeExposure, + //! Buffer with normal and roughness in alpha channel + eBufferTypeNormalRoughness, + //! Diffuse and camera ray length + eBufferTypeDiffuseHitNoisy, + //! Diffuse denoised + eBufferTypeDiffuseHitDenoised, + //! Specular and reflected ray length + eBufferTypeSpecularHitNoisy, + //! Specular denoised + eBufferTypeSpecularHitDenoised, + //! Shadow noisy + eBufferTypeShadowNoisy, + //! Shadow denoised + eBufferTypeShadowDenoised, + //! AO noisy + eBufferTypeAmbientOcclusionNoisy, + //! AO denoised + eBufferTypeAmbientOcclusionDenoised, + + //! Optional - UI/HUD pixels hint (set to 1 if a pixel belongs to the UI/HUD elements, 0 otherwise) + eBufferTypeUIHint, + //! Optional - Shadow pixels hint (set to 1 if a pixel belongs to the shadow area, 0 otherwise) + eBufferTypeShadowHint, + //! Optional - Reflection pixels hint (set to 1 if a pixel belongs to the reflection area, 0 otherwise) + eBufferTypeReflectionHint, + //! Optional - Particle pixels hint (set to 1 if a pixel represents a particle, 0 otherwise) + eBufferTypeParticleHint, + //! Optional - Transparency pixels hint (set to 1 if a pixel belongs to the transparent area, 0 otherwise) + eBufferTypeTransparencyHint, + //! Optional - Animated texture pixels hint (set to 1 if a pixel belongs to the animated texture area, 0 otherwise) + eBufferTypeAnimatedTextureHint, + //! Optional - Bias for current color vs history hint - lerp(history, current, bias) (set to 1 to completely reject history) + eBufferTypeBiasCurrentColorHint, + //! Optional - Ray-tracing distance (camera ray length) + eBufferTypeRaytracingDistance, + //! Optional - Motion vectors for reflections + eBufferTypeReflectionMotionVectors, + //! Optional - Position, in same space as eBufferTypeNormals + eBufferTypePosition, + //! Optional - Indicates (via non-zero value) which pixels have motion/depth values that do not match the final color content at that pixel (e.g. overlaid, opaque Picture-in-Picture) + eBufferTypeInvalidDepthMotionHint + }; + + //! Features supported with this SDK + //! + //! IMPORTANT: Each feature must use the unique id + //! + enum Feature : uint32_t + { + //! Deep Learning Super Sampling + eFeatureDLSS = 0, + //! Real-Time Denoiser + eFeatureNRD = 1, + //! NVIDIA Image Scaling + eFeatureNIS = 2, + //! Low-Latency + eFeatureReflex = 3, + //! Common feature, NOT intended to be used directly + eFeatureCommon = UINT_MAX + }; + + //! Different levels for logging + enum LogLevel + { + //! No logging + eLogLevelOff, + //! Default logging + eLogLevelDefault, + //! Verbose logging + eLogLevelVerbose, + //! Total count + eLogLevelCount + }; + + //! Resource types + enum ResourceType : char + { + eResourceTypeTex2d, + eResourceTypeBuffer + }; + + //! Resource description + struct ResourceDesc + { + //! Indicates the type of resource + ResourceType type = eResourceTypeTex2d; + //! D3D12_RESOURCE_DESC/VkImageCreateInfo/VkBufferCreateInfo + void* desc{}; + //! Initial state as D3D12_RESOURCE_STATES or VkMemoryPropertyFlags + uint32_t state = 0; + //! CD3DX12_HEAP_PROPERTIES or nullptr + void* heap{}; + //! Reserved for future expansion, must be set to null + void* ext{}; + }; + + //! Native resource + struct Resource + { + //! Indicates the type of resource + ResourceType type = eResourceTypeTex2d; + //! ID3D11Resource/ID3D12Resource/VkBuffer/VkImage + void* native{}; + //! vkDeviceMemory or nullptr + void* memory{}; + //! VkImageView/VkBufferView or nullptr + void* view{}; + //! State as D3D12_RESOURCE_STATES or VkImageLayout + //! + //! IMPORTANT: State needs to be correct when tagged resources are actually used. + //! + uint32_t state{}; + //! Reserved for future expansion, must be set to null + void* ext{}; + }; + + //! Resource allocation/deallocation callbacks + //! + //! Use these callbacks to gain full control over + //! resource life cycle and memory allocation tracking. + //! + //! @param device - Device to be used (vkDevice or ID3D11Device or ID3D12Device) + //! + //! IMPORTANT: Textures must have the pixel shader resource + //! and the unordered access view flags set + using pfunResourceAllocateCallback = Resource(const ResourceDesc* desc, void* device); + using pfunResourceReleaseCallback = void(Resource* resource, void* device); + + //! Log type + enum LogType + { + //! Controlled by LogLevel, SL can show more information in eLogLevelVerbose mode + eLogTypeInfo, + //! Always shown regardless of LogLevel + eLogTypeWarn, + eLogTypeError, + //! Total count + eLogTypeCount + }; + + //! Logging callback + //! + //! Use these callbacks to track messages posted in the log. + //! If any of the SL methods returns false use eLogTypeError + //! type to track down what went wrong and why. + using pfunLogMessageCallback = void(LogType type, const char* msg); + + //! Optional flags + enum PreferenceFlags : uint64_t + { + //! IMPORTANT: If this flag is set then the host application is responsible for restoring CL state correctly after each 'slEvaluateFeature' call + ePreferenceFlagDisableCLStateTracking = 1 << 0, + //! Disables debug text on screen in development builds + ePreferenceFlagDisableDebugText = 1 << 1, + }; + + SL_ENUM_OPERATORS_64(PreferenceFlags) + + //! Optional preferences + struct Preferences + { + //! Optional - In non-production builds it is useful to enable debugging console window + bool showConsole = false; + //! Optional - Various logging levels + LogLevel logLevel = eLogLevelDefault; + //! Optional - Absolute paths to locations where to look for plugins, first path in the list has the highest priority + const wchar_t** pathsToPlugins = {}; + //! Optional - Number of paths to search + uint32_t numPathsToPlugins = 0; + //! Optional - Absolute path to location where logs and other data should be stored + //! NOTE: Set this to nullptr in order to disable logging to a file + const wchar_t* pathToLogsAndData = {}; + //! Optional - Allows resource allocation tracking on the host side + pfunResourceAllocateCallback* allocateCallback = {}; + //! Optional - Allows resource deallocation tracking on the host side + pfunResourceReleaseCallback* releaseCallback = {}; + //! Optional - Allows log message tracking including critical errors if they occur + pfunLogMessageCallback* logMessageCallback = {}; + //! Optional - Flags used to enable or disable advanced options + PreferenceFlags flags{}; + //! Required - Features to load (assuming appropriate plugins are found), if not specified NO features will be loaded by default + const Feature* featuresToLoad = {}; + //! Required - Number of features to load, only used when list is not a null pointer + uint32_t numFeaturesToLoad = 0; + //! Reserved for future expansion, must be set to null + void* ext = {}; + }; + + //! Unique application ID + constexpr int kUniqueApplicationId = 0; + + //! Streamline API functions + //! + using PFunSlInit = bool(const sl1::Preferences& pref, int applicationId); + using PFunSlShutdown = bool(); + using PFunSlSetFeatureEnabled = bool(sl1::Feature feature, bool enabled); + using PFunSlIsFeatureEnabled = bool(sl1::Feature feature); + using PFunSlIsFeatureSupported = bool(sl1::Feature feature, uint32_t* adapterBitMask); + using PFunSlSetTag = bool(const sl1::Resource* resource, sl1::BufferType tag, uint32_t id, const sl1::Extent* extent); + using PFunSlSetConstants = bool(const sl1::Constants& values, uint32_t frameIndex, uint32_t id); + using PFunSlSetFeatureConstants = bool(sl1::Feature feature, const void* consts, uint32_t frameIndex, uint32_t id); + using PFunSlGetFeatureSettings = bool(sl1::Feature feature, const void* consts, void* settings); + using PFunSlEvaluateFeature = bool(sl1::CommandBuffer* cmdBuffer, sl1::Feature feature, uint32_t frameIndex, uint32_t id); + using PFunSlAllocateResources = bool(sl1::CommandBuffer* cmdBuffer, sl1::Feature feature, uint32_t id); + using PFunSlFreeResources = bool(sl1::Feature feature, uint32_t id); + + //! Initializes the SL module + //! + //! Call this method when the game is initializing. + //! + //! @param pref Specifies preferred behavior for the SL library (SL will keep a copy) + //! @param applicationId Unique id for your application. + //! @return false if SL is not supported on the system true otherwise. + //! + //! This method is NOT thread safe. + SL_API bool slInit(const sl1::Preferences& pref, int applicationId = sl1::kUniqueApplicationId); + + //! Shuts down the SL module + //! + //! Call this method when the game is shutting down. + //! + //! @return false if SL did not shutdown correctly true otherwise. + //! + //! This method is NOT thread safe. + SL_API bool slShutdown(); + + //! Checks if specific feature is supported or not. + //! + //! Call this method to check if certain eFeature* (see above) is available. + //! This method must be called after init otherwise it will always return false. + //! + //! @param feature Specifies which feature to check + //! @param adapterBitMask Optional bit-mask specifying which adapter supports the give feature + //! @return false if feature is not supported on the system true otherwise. + //! + //! NOTE: You can provide the adapter bit mask to ensure that feature is available on the adapter + //! for which you are planning to create a device. For the adapter at index N you can check the bit 1 << N. + //! + //! This method is NOT thread safe. + SL_API bool slIsFeatureSupported(sl1::Feature feature, uint32_t* adapterBitMask = nullptr); + + //! Checks if specified feature is enabled or not. + //! + //! Call this method to check if feature is enabled. + //! All supported features are enabled by default and have to be disabled explicitly if needed. + //! + //! @param feature Specifies which feature to check + //! @return false if feature is disabled, not supported on the system or if device has not been created yet, true otherwise. + //! + //! This method is NOT thread safe and requires DX/VK device to be created before calling it. + SL_API bool slIsFeatureEnabled(sl1::Feature feature); + + //! Sets the specified feature to either enabled or disabled state. + //! + //! Call this method to enable or disable certain eFeature*. + //! All supported features are enabled by default and have to be disabled explicitly if needed. + //! + //! @param feature Specifies which feature to check + //! @param enabled Value specifying if feature should be enabled or disabled. + //! @return false if feature is not supported on the system or if device has not been created yet, true otherwise. + //! + //! NOTE: When this method is called no other DXGI/D3D/Vulkan APIs should be invoked in parallel so + //! make sure to flush your pipeline before calling this method. + //! + //! This method is NOT thread safe and requires DX/VK device to be created before calling it. + SL_API bool slSetFeatureEnabled(sl1::Feature feature, bool enabled); + + //! Tags resource + //! + //! Call this method to tag the appropriate buffers. + //! + //! @param resource Pointer to resource to tag, set to null to remove the specified tag + //! @param tag Specific tag for the resource + //! @param id Unique id (can be viewport id | instance id etc.) + //! @param extent The area of the tagged resource to use (if using the entire resource leave as null) + //! @return false if resource cannot be tagged or if device has not been created yet, true otherwise. + //! + //! This method is thread safe and requires DX/VK device to be created before calling it. + SL_API bool slSetTag(const sl1::Resource* resource, sl1::BufferType tag, uint32_t id = 0, const sl1::Extent* extent = nullptr); + + //! Sets common constants. + //! + //! Call this method to provide the required data (SL will keep a copy). + //! + //! @param values Common constants required by SL plugins (SL will keep a copy) + //! @param frameIndex Index of the current frame + //! @param id Unique id (can be viewport id | instance id etc.) + //! @return false if constants cannot be set or if device has not been created yet, true otherwise. + //! + //! This method is thread safe and requires DX/VK device to be created before calling it. + SL_API bool slSetConstants(const sl1::Constants& values, uint32_t frameIndex, uint32_t id = 0); + + //! Sets feature specific constants. + //! + //! Call this method to provide the required data + //! for the specified feature (SL will keep a copy). + //! + //! @param feature Feature we are working with + //! @param consts Pointer to the feature specific constants (SL will keep a copy) + //! @param frameIndex Index of the current frame + //! @param id Unique id (can be viewport id | instance id etc.) + //! @return false if constants cannot be set or if device has not been created yet, true otherwise. + //! + //! This method is thread safe and requires DX/VK device to be created before calling it. + SL_API bool slSetFeatureConstants(sl1::Feature feature, const void* consts, uint32_t frameIndex, uint32_t id = 0); + + //! Gets feature specific settings. + //! + //! Call this method to obtain settings for the specified feature. + //! + //! @param feature Feature we are working with + //! @param consts Pointer to the feature specific constants + //! @param settings Pointer to the returned feature specific settings + //! @return false if feature does not have settings or if device has not been created yet, true otherwise. + //! + //! This method is NOT thread safe and requires DX/VK device to be created before calling it. + SL_API bool slGetFeatureSettings(sl1::Feature feature, const void* consts, void* settings); + + //! Allocates resources for the specified feature. + //! + //! Call this method to explicitly allocate resources + //! for an instance of the specified feature. + //! + //! @param cmdBuffer Command buffer to use (must be created on device where feature is supported but can be null if not needed) + //! @param feature Feature we are working with + //! @param id Unique id (instance handle) + //! @return false if resources cannot be allocated or if device has not been created yet, true otherwise. + //! + //! This method is NOT thread safe and requires DX/VK device to be created before calling it. + SL_API bool slAllocateResources(sl1::CommandBuffer* cmdBuffer, sl1::Feature feature, uint32_t id); + + //! Frees resources for the specified feature. + //! + //! Call this method to explicitly free resources + //! for an instance of the specified feature. + //! + //! @param feature Feature we are working with + //! @param id Unique id (instance handle) + //! @return false if resources cannot be freed or if device has not been created yet, true otherwise. + //! + //! This method is NOT thread safe and requires DX/VK device to be created before calling it. + SL_API bool slFreeResources(sl1::Feature feature, uint32_t id); + + //! Evaluates feature + //! + //! Use this method to mark the section in your rendering pipeline + //! where specific feature should be injected. + //! + //! @param cmdBuffer Command buffer to use (must be created on device where feature is supported but can be null if not needed) + //! @param feature Feature we are working with + //! @param frameIndex Current frame index (can be 0 if not needed) + //! @param id Unique id (can be viewport id | instance id etc.) + //! @return false if feature event cannot be injected in the command buffer or if device has not been created yet, true otherwise. + //! + //! IMPORTANT: frameIndex and id must match whatever is used to set common and or feature constants (if any) + //! + //! This method is NOT thread safe and requires DX/VK device to be created before calling it. + SL_API bool slEvaluateFeature(sl1::CommandBuffer* cmdBuffer, sl1::Feature feature, uint32_t frameIndex, uint32_t id = 0); +} \ No newline at end of file diff --git a/external/streamline1/sl1_consts.h b/external/streamline1/sl1_consts.h new file mode 100644 index 00000000..c20c3fc0 --- /dev/null +++ b/external/streamline1/sl1_consts.h @@ -0,0 +1,217 @@ +/* +* Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved +* +* 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 + +#define SL_ENUM_OPERATORS_64(T) \ +inline bool operator&(T a, T b) \ +{ \ + return ((uint64_t)a & (uint64_t)b) != 0; \ +} \ + \ +inline T& operator&=(T& a, T b) \ +{ \ + a = (T)((uint64_t)a & (uint64_t)b); \ + return a; \ +} \ + \ +inline T operator|(T a, T b) \ +{ \ + return (T)((uint64_t)a | (uint64_t)b); \ +} \ + \ +inline T& operator |= (T& lhs, T rhs) \ +{ \ + lhs = (T)((uint64_t)lhs | (uint64_t)rhs); \ + return lhs; \ +} \ + \ +inline T operator~(T a) \ +{ \ + return (T)~((uint64_t)a); \ +} + +#define SL_ENUM_OPERATORS_32(T) \ +inline bool operator&(T a, T b) \ +{ \ + return ((uint32_t)a & (uint32_t)b) != 0; \ +} \ + \ +inline T& operator&=(T& a, T b) \ +{ \ + a = (T)((uint32_t)a & (uint32_t)b); \ + return a; \ +} \ + \ +inline T operator|(T a, T b) \ +{ \ + return (T)((uint32_t)a | (uint32_t)b); \ +} \ + \ +inline T& operator |= (T& lhs, T rhs) \ +{ \ + lhs = (T)((uint32_t)lhs | (uint32_t)rhs); \ + return lhs; \ +} \ + \ +inline T operator~(T a) \ +{ \ + return (T)~((uint32_t)a); \ +} + +namespace sl1 +{ +//! For cases when value has to be provided and we don't have good default +constexpr float INVALID_FLOAT = 3.40282346638528859811704183484516925440e38f; +constexpr uint32_t INVALID_UINT = 0xffffffff; + +struct float2 +{ + float2() : x(INVALID_FLOAT), y(INVALID_FLOAT) {} + float2(float _x, float _y) : x(_x), y(_y) {} + float x, y; +}; + +struct float3 +{ + float3() : x(INVALID_FLOAT), y(INVALID_FLOAT), z(INVALID_FLOAT) {} + float3(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {} + float x, y, z; +}; + +struct float4 +{ + float4() : x(INVALID_FLOAT), y(INVALID_FLOAT), z(INVALID_FLOAT), w(INVALID_FLOAT) {} + float4(float _x, float _y, float _z, float _w) : x(_x), y(_y), z(_z), w(_w) {} + float x, y, z, w; +}; + +struct float4x4 +{ + //! All access points take row index as a parameter + inline float4& operator[](uint32_t i) { return row[i]; } + inline const float4& operator[](uint32_t i) const { return row[i]; } + inline void setRow(uint32_t i, const float4& v) { row[i] = v; } + inline const float4& getRow(uint32_t i) { return row[i]; } +private: + //! Row major matrix + float4 row[4]; +}; + +struct Extent +{ + uint32_t top{}; + uint32_t left{}; + uint32_t width{}; + uint32_t height{}; + + inline operator bool() const { return width != 0 && height != 0; } + inline bool operator==(const Extent& rhs) const + { + return top == rhs.top && left == rhs.left && + width == rhs.width && height == rhs.height; + } + inline bool operator!=(const Extent& rhs) const + { + return !operator==(rhs); + } +}; + +//! For cases when value has to be provided and we don't have good default +enum Boolean : char +{ + eFalse, + eTrue, + eInvalid +}; + +//! Common constants, all parameters must be provided unless they are marked as optional +struct Constants +{ + //! IMPORTANT: All matrices are row major (see float4x4 definition) and + //! must NOT contain temporal AA jitter offset (if any). Any jitter offset + //! should be provided as the additional parameter Constants::jitterOffset (see below) + + //! Specifies matrix transformation from the camera view to the clip space. + float4x4 cameraViewToClip; + //! Specifies matrix transformation from the clip space to the camera view space. + float4x4 clipToCameraView; + //! Optional - Specifies matrix transformation describing lens distortion in clip space. + float4x4 clipToLensClip; + //! Specifies matrix transformation from the current clip to the previous clip space. + //! clipToPrevClip = clipToView * viewToWorld * worldToViewPrev * viewToClipPrev + float4x4 clipToPrevClip; + //! Specifies matrix transformation from the previous clip to the current clip space. + //! prevClipToClip = clipToPrevClip.inverse() + float4x4 prevClipToClip; + + //! Specifies pixel space jitter offset + float2 jitterOffset; + //! Specifies scale factors used to normalize motion vectors (so the values are in [-1,1] range) + float2 mvecScale; + //! Optional - Specifies camera pinhole offset if used. + float2 cameraPinholeOffset; + //! Specifies camera position in world space. + float3 cameraPos; + //! Specifies camera up vector in world space. + float3 cameraUp; + //! Specifies camera right vector in world space. + float3 cameraRight; + //! Specifies camera forward vector in world space. + float3 cameraFwd; + + //! Specifies camera near view plane distance. + float cameraNear = INVALID_FLOAT; + //! Specifies camera far view plane distance. + float cameraFar = INVALID_FLOAT; + //! Specifies camera field of view in radians. + float cameraFOV = INVALID_FLOAT; + //! Specifies camera aspect ratio defined as view space width divided by height. + float cameraAspectRatio = INVALID_FLOAT; + //! Specifies which value represents an invalid (un-initialized) value in the motion vectors buffer + //! NOTE: This is only required if `cameraMotionIncluded` is set to false and SL needs to compute it. + float motionVectorsInvalidValue = INVALID_FLOAT; + + //! Specifies if depth values are inverted (value closer to the camera is higher) or not. + Boolean depthInverted = Boolean::eInvalid; + //! Specifies if camera motion is included in the MVec buffer. + Boolean cameraMotionIncluded = Boolean::eInvalid; + //! Specifies if motion vectors are 3D or not. + Boolean motionVectors3D = Boolean::eInvalid; + //! Specifies if previous frame has no connection to the current one (i.e. motion vectors are invalid) + Boolean reset = Boolean::eInvalid; + //! Specifies if application is not currently rendering game frames (paused in menu, playing video cut-scenes) + Boolean notRenderingGameFrames = Boolean::eInvalid; + //! Specifies if orthographic projection is used or not. + Boolean orthographicProjection = Boolean::eFalse; + //! Specifies if motion vectors are already dilated or not. + Boolean motionVectorsDilated = Boolean::eFalse; + //! Specifies if motion vectors are jittered or not. + Boolean motionVectorsJittered = Boolean::eFalse; + + //! Reserved for future expansion, must be set to null + void* ext = {}; +}; + +}