/* * Copyright (c) 2022 - 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. * * NVIDIA CORPORATION, its affiliates and licensors retain all intellectual * property and proprietary rights in and to this material, related * documentation and any modifications thereto. Any use, reproduction, * disclosure or distribution of this material and related documentation * without an express license agreement from NVIDIA CORPORATION or * its affiliates is strictly prohibited. */ #include "StreamlineAPI.h" #include "StreamlineRHI.h" #include "StreamlineRHIPrivate.h" #include "HAL/IConsoleManager.h" #include "HAL/PlatformProcess.h" #include "HAL/ThreadManager.h" #include "Runtime/Launch/Resources/Version.h" #include "sl.h" #include "sl_helpers.h" #define LOCTEXT_NAMESPACE "FStreamlineRHIModule" #ifndef LOG_SL_FUNCTIONS #define LOG_SL_FUNCTIONS (!(UE_BUILD_TEST || UE_BUILD_SHIPPING)) #endif static bool bLogStreamlineLogFunctions = 0; static FAutoConsoleVariableRef CVarStreamlineLogFunctions( TEXT("r.Streamline.LogFunctions"), bLogStreamlineLogFunctions, TEXT("Enable/disable whether streamline functions calls and thread are written to the log. Is also set to true with -slloglevel=3 \n"), ECVF_Default); static bool LogStreamlineFunctions() { #if LOG_SL_FUNCTIONS return bLogStreamlineLogFunctions; #else return false; #endif } void SetStreamlineAPILoggingEnabled(bool bEnabled) { bLogStreamlineLogFunctions = bEnabled; } namespace sl { inline const char* getFeatureRequirementsSingleBitFlagsAsStr(FeatureRequirementFlags f) { switch (f) { SL_CASE_STR(FeatureRequirementFlags::eD3D11Supported); SL_CASE_STR(FeatureRequirementFlags::eD3D12Supported); SL_CASE_STR(FeatureRequirementFlags::eVulkanSupported); SL_CASE_STR(FeatureRequirementFlags::eVSyncOffRequired); SL_CASE_STR(FeatureRequirementFlags::eHardwareSchedulingRequired); } return "Unknown"; } inline FString getFeatureRequirementsFlagsAsStr(FeatureRequirementFlags f) { FString Result; for (uint32 SingleBit = uint32(sl::FeatureRequirementFlags::eHardwareSchedulingRequired); SingleBit != 0; SingleBit >>= 1) { sl::FeatureRequirementFlags Flag = sl::FeatureRequirementFlags(SingleBit); if (Flag == SLBitwiseAnd(f, Flag)) { Result.Append(getFeatureRequirementsSingleBitFlagsAsStr(Flag)); if (SingleBit != 1) { Result.AppendChar(TCHAR('|')); } } } return Result; } } STREAMLINERHI_API void LogStreamlineFeatureSupport(sl::Feature Feature, const sl::AdapterInfo& Adapter) { sl::Result SupportedResult = SLisFeatureSupported(Feature,Adapter); UE_LOG(LogStreamlineRHI, Log, TEXT("SLisFeatureSupported(%s) -> (%d, %s)"), ANSI_TO_TCHAR(sl::getFeatureAsStr(Feature)), SupportedResult, ANSI_TO_TCHAR(sl::getResultAsStr(SupportedResult))); // putting this here since the alternative of having FStreamlineRHI compute & store that was annoying since it would mean to have sl.h be a public include if (SupportedResult != sl::Result::eErrorFeatureMissing) { sl::FeatureVersion Version; sl::Result VersionResult = SLgetFeatureVersion(Feature, Version); UE_LOG(LogStreamlineRHI, Log, TEXT("SLgetFeatureVersion(%s) versionSL = %s, versionNGX = %s -> (%d, %s)"), ANSI_TO_TCHAR(sl::getFeatureAsStr(Feature)), ANSI_TO_TCHAR(Version.versionSL.toStr().c_str()), ANSI_TO_TCHAR(Version.versionNGX.toStr().c_str()), VersionResult, ANSI_TO_TCHAR(sl::getResultAsStr(VersionResult))); sl::FeatureRequirements Requirements; sl::Result RequirementsResult = SLgetFeatureRequirements(Feature, Requirements); UE_LOG(LogStreamlineRHI, Log, TEXT("SLgetFeatureRequirements(%s) -> (%d, %s)"), ANSI_TO_TCHAR(sl::getFeatureAsStr(Feature)), RequirementsResult, ANSI_TO_TCHAR(sl::getResultAsStr(RequirementsResult))); LogStreamlineFeatureRequirements(Feature, Requirements); } } void LogStreamlineFeatureRequirements(sl::Feature Feature, const sl::FeatureRequirements& Requirements) { UE_LOG(LogStreamlineRHI, Log, TEXT("FeatureRequirements %s: flags %s"), ANSI_TO_TCHAR(sl::getFeatureAsStr(Feature)), *sl::getFeatureRequirementsFlagsAsStr(Requirements.flags)); UE_LOG(LogStreamlineRHI, Log, TEXT("maxNumCPUThreads : %u"),Requirements.maxNumCPUThreads); UE_LOG(LogStreamlineRHI, Log, TEXT("maxNumViewports : %u"), Requirements.maxNumViewports); UE_LOG(LogStreamlineRHI, Log, TEXT("osVersion detected: %s, required: %s"), ANSI_TO_TCHAR(Requirements.osVersionDetected.toStr().c_str()), ANSI_TO_TCHAR(Requirements.osVersionRequired.toStr().c_str())); UE_LOG(LogStreamlineRHI, Log, TEXT("driverVersion detected: %s, required: %s"), ANSI_TO_TCHAR(Requirements.driverVersionDetected.toStr().c_str()), ANSI_TO_TCHAR(Requirements.driverVersionRequired.toStr().c_str())); UE_LOG(LogStreamlineRHI, Log, TEXT("requiredTags (%u): {%s}"), Requirements.numRequiredTags ,*FString::JoinBy(MakeArrayView( Requirements.requiredTags, Requirements.numRequiredTags), TEXT(", "), [](const sl::BufferType& Buffer) { return FString::Printf(TEXT("%s (%u)"), ANSI_TO_TCHAR(sl::getBufferTypeAsStr(Buffer)), Buffer); }) ); } namespace { void* SLInterPoserDLL = nullptr; PFun_slInit* Ptr_init = nullptr; PFun_slShutdown* Ptr_shutdown = nullptr; PFun_slIsFeatureSupported* Ptr_isFeatureSupported = nullptr; PFun_slIsFeatureLoaded* Ptr_isFeatureLoaded = nullptr; PFun_slSetFeatureLoaded* Ptr_setFeatureLoaded = nullptr; PFun_slEvaluateFeature* Ptr_evaluateFeature = nullptr; PFun_slAllocateResources* Ptr_allocateResources = nullptr; PFun_slFreeResources* Ptr_freeResources = nullptr; PFun_slSetTag* Ptr_setTag = nullptr; PFun_slGetFeatureRequirements* Ptr_getFeatureRequirements = nullptr; PFun_slGetFeatureVersion* Ptr_getFeatureVersion = nullptr; PFun_slUpgradeInterface* Ptr_upgradeInterface = nullptr; PFun_slSetConstants* Ptr_setConstants = nullptr; PFun_slGetNativeInterface* Ptr_getNativeInterface = nullptr; PFun_slGetFeatureFunction* Ptr_getFeatureFunction = nullptr; PFun_slGetNewFrameToken* Ptr_getNewFrameToken = nullptr; PFun_slSetD3DDevice* Ptr_setD3DDevice = nullptr; bool bIsStreamlineFunctionPointersLoaded = false; } FString CurrentThreadName() { const uint32 ThreadId = FPlatformTLS::GetCurrentThreadId(); const FString ThreadName = FThreadManager::GetThreadName(ThreadId); return FString::Printf(TEXT("%s (tid=%u)"),*ThreadName, ThreadId); } void LogStreamlineFunctionCall(const FString& Function, const FString& Arguments) { #if LOG_SL_FUNCTIONS if (LogStreamlineFunctions()) { UE_LOG(LogStreamlineRHI, Log, TEXT("%s %s %s"), *Function, *CurrentThreadName(), *Arguments); } #endif } STREAMLINERHI_API bool AreStreamlineFunctionsLoaded() { return bIsStreamlineFunctionPointersLoaded; } sl::Result SLinit(const sl::Preferences& pref, uint64_t sdkVersion) { // we cannot call IsStreamlineSupported since that checks whether bIsStreamlineInitialized is set to true, which it will with the result of this call check(AreStreamlineFunctionsLoaded()); check(SLInterPoserDLL); check(Ptr_init != nullptr); #if LOG_SL_FUNCTIONS if(LogStreamlineFunctions()) { UE_LOG(LogStreamlineRHI, Log, TEXT("%s %s sdkVersion=%llx"), ANSI_TO_TCHAR(__FUNCTION__), *CurrentThreadName(), sdkVersion); } #endif return Ptr_init(pref, sdkVersion); } sl::Result SLshutdown() { check(IsStreamlineSupported()); check(SLInterPoserDLL); check(Ptr_shutdown != nullptr); #if LOG_SL_FUNCTIONS if (LogStreamlineFunctions()) { UE_LOG(LogStreamlineRHI, Log, TEXT("%s %s"), ANSI_TO_TCHAR(__FUNCTION__), *CurrentThreadName()); } #endif return Ptr_shutdown(); } sl::Result SLisFeatureSupported(sl::Feature feature, const sl::AdapterInfo& adapterInfo) { check(IsStreamlineSupported()); check(SLInterPoserDLL); check(Ptr_isFeatureSupported != nullptr); #if LOG_SL_FUNCTIONS if (LogStreamlineFunctions()) { UE_LOG(LogStreamlineRHI, Log, TEXT("%s %s feature=%s (%u)"), ANSI_TO_TCHAR(__FUNCTION__), *CurrentThreadName(), ANSI_TO_TCHAR(sl::getFeatureAsStr(feature)), feature ); } #endif return Ptr_isFeatureSupported(feature, adapterInfo); } sl::Result SLisFeatureLoaded(sl::Feature feature, bool& loaded) { check(IsStreamlineSupported()); check(SLInterPoserDLL); check(Ptr_isFeatureLoaded != nullptr); #if LOG_SL_FUNCTIONS if (LogStreamlineFunctions()) { UE_LOG(LogStreamlineRHI, Log, TEXT("%s %s feature=%s (%u)"), ANSI_TO_TCHAR(__FUNCTION__), *CurrentThreadName(), ANSI_TO_TCHAR(sl::getFeatureAsStr(feature)), feature ); } #endif return Ptr_isFeatureLoaded(feature, loaded); } sl::Result SLsetFeatureLoaded(sl::Feature feature, bool loaded) { check(IsStreamlineSupported()); check(SLInterPoserDLL); check(Ptr_setFeatureLoaded != nullptr); #if LOG_SL_FUNCTIONS if (LogStreamlineFunctions()) { UE_LOG(LogStreamlineRHI, Log, TEXT("%s %s feature=%s (%u), loaded=%u"), ANSI_TO_TCHAR(__FUNCTION__), *CurrentThreadName(), ANSI_TO_TCHAR(sl::getFeatureAsStr(feature)), feature, loaded); } #endif return Ptr_setFeatureLoaded(feature, loaded); } namespace sl { template T* findStruct(const void* ptr) { auto base = static_cast(ptr); while (base && base->structType != T::s_structType) { base = base->next; } return (T*)base; } template T* findStruct(void* ptr) { auto base = static_cast(ptr); while (base && base->structType != T::s_structType) { base = base->next; } return (T*)base; } //! Find a struct of type T, but stop the search if we find a struct of type S template T* findStruct(void* ptr) { auto base = static_cast(ptr); while (base && base->structType != T::s_structType) { base = base->next; // If we find a struct of type S, we know should stop the search if (base->structType == S::s_structType) { return nullptr; } } return (T*)base; } template T* findStruct(const void** ptr, uint32_t count) { const BaseStructure* base{}; for (uint32_t i = 0; base == nullptr && i < count; i++) { base = static_cast(ptr[i]); while (base && base->structType != T::s_structType) { base = base->next; } } return (T*)base; } template bool findStructs(const void** ptr, uint32_t count, std::vector& structs) { for (uint32_t i = 0; i < count; i++) { auto base = static_cast(ptr[i]); while (base) { if (base->structType == T::s_structType) { structs.push_back((T*)base); } base = base->next; } } return structs.size() > 0; } } sl::Result SLevaluateFeature(sl::Feature feature, const sl::FrameToken& frame, const sl::BaseStructure** inputs, uint32_t numInputs, sl::CommandBuffer* cmdBuffer) { check(IsStreamlineSupported()); check(SLInterPoserDLL); check(Ptr_evaluateFeature != nullptr); #if LOG_SL_FUNCTIONS if (LogStreamlineFunctions()) { FString ViewportHandle; auto viewport = sl::findStruct(inputs); if (viewport) { ViewportHandle = FString::FromInt(viewport->operator unsigned int()); } UE_LOG(LogStreamlineRHI, Log, TEXT("%s %s feature=%s (%u) frame=%u, numInputs=%u, {viewport=%s} "), ANSI_TO_TCHAR(__FUNCTION__), *CurrentThreadName(), ANSI_TO_TCHAR(sl::getFeatureAsStr(feature)), feature, static_cast(frame), numInputs, *ViewportHandle); } #endif return Ptr_evaluateFeature(feature, frame, inputs, numInputs, cmdBuffer); } sl::Result SLAllocateResources(sl::CommandBuffer* cmdBuffer, sl::Feature feature, const sl::ViewportHandle& viewport) { check(IsStreamlineSupported()); check(SLInterPoserDLL); check(Ptr_allocateResources != nullptr); #if LOG_SL_FUNCTIONS if (LogStreamlineFunctions()) { UE_LOG(LogStreamlineRHI, Log, TEXT("%s %s feature=%s (%u), viewport=%u"), ANSI_TO_TCHAR(__FUNCTION__), *CurrentThreadName(), ANSI_TO_TCHAR(sl::getFeatureAsStr(feature)), feature, static_cast(viewport)); } #endif return Ptr_allocateResources(cmdBuffer, feature, viewport); } sl::Result SLFreeResources(sl::Feature feature, const sl::ViewportHandle& viewport) { check(IsStreamlineSupported()); check(SLInterPoserDLL); check(Ptr_freeResources != nullptr); #if LOG_SL_FUNCTIONS if (LogStreamlineFunctions()) { UE_LOG(LogStreamlineRHI, Log, TEXT("%s %s feature=%s (%u), viewport=%u"), ANSI_TO_TCHAR(__FUNCTION__), *CurrentThreadName(), ANSI_TO_TCHAR(sl::getFeatureAsStr(feature)), feature, static_cast(viewport)); } #endif return Ptr_freeResources(feature, viewport); } sl::Result SLsetTag(const sl::ViewportHandle& viewport, const sl::ResourceTag* tags, uint32_t numTags, sl::CommandBuffer* cmdBuffer) { check(IsStreamlineSupported()); check(SLInterPoserDLL); check(Ptr_setTag != nullptr); #if LOG_SL_FUNCTIONS if (LogStreamlineFunctions()) { if (numTags > 0) { const FString Tags = FString::JoinBy(MakeArrayView(tags, numTags), TEXT(", "), [](const sl::ResourceTag Tag) { return FString::Printf(TEXT("%s(%u) [left=%u, top=%u, width=%u, height=%u] "), ANSI_TO_TCHAR(sl::getBufferTypeAsStr(Tag.type)), Tag.type, Tag.extent.left, Tag.extent.top, Tag.extent.width, Tag.extent.height ); } ); UE_LOG(LogStreamlineRHI, Log, TEXT("%s %s tags=%s (%u), viewport=%u"), ANSI_TO_TCHAR(__FUNCTION__), *CurrentThreadName(), *Tags, numTags, static_cast(viewport)); } } #endif return Ptr_setTag(viewport, tags, numTags, cmdBuffer); } sl::Result SLgetFeatureRequirements(sl::Feature feature, sl::FeatureRequirements& requirements) { check(IsStreamlineSupported()); check(SLInterPoserDLL); check(Ptr_getFeatureRequirements != nullptr); #if LOG_SL_FUNCTIONS if (LogStreamlineFunctions()) { UE_LOG(LogStreamlineRHI, Log, TEXT("%s %s feature=%s (%u)"), ANSI_TO_TCHAR(__FUNCTION__), *CurrentThreadName(), ANSI_TO_TCHAR(sl::getFeatureAsStr(feature)), feature); } #endif return Ptr_getFeatureRequirements(feature, requirements); } sl::Result SLgetFeatureVersion(sl::Feature feature, sl::FeatureVersion& version) { check(IsStreamlineSupported()); check(SLInterPoserDLL); check(Ptr_getFeatureVersion != nullptr); #if LOG_SL_FUNCTIONS if (LogStreamlineFunctions()) { UE_LOG(LogStreamlineRHI, Log, TEXT("%s %s feature=%s (%u)"), ANSI_TO_TCHAR(__FUNCTION__), *CurrentThreadName(), ANSI_TO_TCHAR(sl::getFeatureAsStr(feature)), feature); } #endif return Ptr_getFeatureVersion(feature, version); } sl::Result SLUpgradeInterface(void** baseInterface) { check(IsStreamlineSupported()); check(SLInterPoserDLL); check(Ptr_upgradeInterface != nullptr); #if LOG_SL_FUNCTIONS if (LogStreamlineFunctions()) { UE_LOG(LogStreamlineRHI, Log, TEXT("%s %s"), ANSI_TO_TCHAR(__FUNCTION__), *CurrentThreadName()); } #endif return Ptr_upgradeInterface(baseInterface); } sl::Result SLsetConstants(const sl::Constants& values, const sl::FrameToken& frame, const sl::ViewportHandle& viewport) { check(IsStreamlineSupported()); check(SLInterPoserDLL); check(Ptr_setConstants != nullptr); #if LOG_SL_FUNCTIONS if (LogStreamlineFunctions()) { // cameraAspectRatio and mvecScale (derived from 1/ ViewRect size) are typically different for each view thus useful to debug "same view different constants per frame errors" UE_LOG(LogStreamlineRHI, Log, TEXT("%s %s frame=%u, values.cameraAspectRatio=%0.2f 1/mvecScale=%0.0f x %0.0f viewport=%u"), ANSI_TO_TCHAR(__FUNCTION__), *CurrentThreadName(), static_cast(frame), values.cameraAspectRatio, 1.0f/values.mvecScale.x, 1.0f / values.mvecScale.y, static_cast(viewport)); } #endif return Ptr_setConstants(values, frame, viewport); } sl::Result SLgetNativeInterface(void* proxyInterface, void** baseInterface) { check(IsStreamlineSupported()); check(SLInterPoserDLL); check(Ptr_getNativeInterface != nullptr); #if LOG_SL_FUNCTIONS if (LogStreamlineFunctions()) { UE_LOG(LogStreamlineRHI, Log, TEXT("%s %s"), ANSI_TO_TCHAR(__FUNCTION__), *CurrentThreadName()); } #endif return Ptr_getNativeInterface(proxyInterface, baseInterface); } sl::Result SLgetFeatureFunction(sl::Feature feature, const char* functionName, void*& function) { check(IsStreamlineSupported()); check(SLInterPoserDLL); check(Ptr_getFeatureFunction != nullptr); #if LOG_SL_FUNCTIONS if (LogStreamlineFunctions()) { UE_LOG(LogStreamlineRHI, Log, TEXT("%s %s feature=%s (%u), functionName=%s"), ANSI_TO_TCHAR(__FUNCTION__), *CurrentThreadName(), ANSI_TO_TCHAR(sl::getFeatureAsStr(feature)), feature, ANSI_TO_TCHAR(functionName)); } #endif return Ptr_getFeatureFunction(feature, functionName, function); } sl::Result SLgetNewFrameToken(sl::FrameToken*& token, uint32_t* frameIndex) { check(IsStreamlineSupported()); check(SLInterPoserDLL); check(Ptr_getNewFrameToken != nullptr); #if LOG_SL_FUNCTIONS if (LogStreamlineFunctions()) { if (frameIndex != nullptr) { UE_LOG(LogStreamlineRHI, Log, TEXT("%s %s frameIndex=%u"), ANSI_TO_TCHAR(__FUNCTION__), *CurrentThreadName(), *frameIndex); } else { UE_LOG(LogStreamlineRHI, Log, TEXT("%s %s frameIndex=nullptr"), ANSI_TO_TCHAR(__FUNCTION__), *CurrentThreadName()); } } #endif return Ptr_getNewFrameToken(token, frameIndex); } sl::Result SLsetD3DDevice(void* d3dDevice) { check(IsStreamlineSupported()); check(SLInterPoserDLL); check(Ptr_setD3DDevice != nullptr); #if LOG_SL_FUNCTIONS if (LogStreamlineFunctions()) { UE_LOG(LogStreamlineRHI, Log, TEXT("%s %s"), ANSI_TO_TCHAR(__FUNCTION__), *CurrentThreadName()); } #endif return Ptr_setD3DDevice(d3dDevice); } bool LoadStreamlineFunctionPointers(const FString& InterposerBinaryPath) { if (!bIsStreamlineFunctionPointersLoaded) { UE_LOG(LogStreamlineRHI, Log, TEXT("loading core Streamline functions from Streamline interposer at %s"), *InterposerBinaryPath); const bool bInterposerBinarySigned = slVerifyEmbeddedSignature(InterposerBinaryPath); #if UE_BUILD_SHIPPING if (bInterposerBinarySigned) #endif { SLInterPoserDLL = FPlatformProcess::GetDllHandle(*InterposerBinaryPath); if (SLInterPoserDLL != nullptr) { UE_LOG(LogStreamlineRHI, Log, TEXT("SLInterPoserLibrary = %p"), SLInterPoserDLL); } else { UE_LOG(LogStreamlineRHI, Log, TEXT("Unable to load SLInterPoserLibrary from %s"), *InterposerBinaryPath); return false; } Ptr_init = (PFun_slInit*)(FWindowsPlatformProcess::GetDllExport(SLInterPoserDLL, TEXT("slInit"))); UE_LOG(LogStreamlineRHI, Log, TEXT("slInit = %p"), Ptr_init); check(Ptr_init); Ptr_shutdown = (PFun_slShutdown*)(FWindowsPlatformProcess::GetDllExport(SLInterPoserDLL, TEXT("slShutdown"))); UE_LOG(LogStreamlineRHI, Log, TEXT("slShutdown = %p"), Ptr_shutdown); check(Ptr_shutdown); Ptr_isFeatureSupported = (PFun_slIsFeatureSupported*)(FWindowsPlatformProcess::GetDllExport(SLInterPoserDLL, TEXT("slIsFeatureSupported"))); UE_LOG(LogStreamlineRHI, Log, TEXT("slIsFeatureSupported = %p"), Ptr_isFeatureSupported); check(Ptr_isFeatureSupported); Ptr_isFeatureLoaded = (PFun_slIsFeatureLoaded*)(FWindowsPlatformProcess::GetDllExport(SLInterPoserDLL, TEXT("slIsFeatureLoaded"))); UE_LOG(LogStreamlineRHI, Log, TEXT("slIsFeatureLoaded = %p"), Ptr_isFeatureLoaded); check(Ptr_isFeatureLoaded); Ptr_setFeatureLoaded = (PFun_slSetFeatureLoaded*)(FWindowsPlatformProcess::GetDllExport(SLInterPoserDLL, TEXT("slSetFeatureLoaded"))); UE_LOG(LogStreamlineRHI, Log, TEXT("slSetFeatureLoaded = %p"), Ptr_setFeatureLoaded); check(Ptr_setFeatureLoaded); Ptr_evaluateFeature = (PFun_slEvaluateFeature*)(FWindowsPlatformProcess::GetDllExport(SLInterPoserDLL, TEXT("slEvaluateFeature"))); UE_LOG(LogStreamlineRHI, Log, TEXT("slEvaluateFeature = %p"), Ptr_evaluateFeature); check(Ptr_evaluateFeature); Ptr_allocateResources = (PFun_slAllocateResources*)(FWindowsPlatformProcess::GetDllExport(SLInterPoserDLL, TEXT("slAllocateResources"))); UE_LOG(LogStreamlineRHI, Log, TEXT("slAllocateResources = %p"), Ptr_allocateResources); check(Ptr_allocateResources); Ptr_freeResources = (PFun_slFreeResources*)(FWindowsPlatformProcess::GetDllExport(SLInterPoserDLL, TEXT("slFreeResources"))); UE_LOG(LogStreamlineRHI, Log, TEXT("slFreeResources = %p"), Ptr_freeResources); check(Ptr_freeResources); Ptr_setTag = (PFun_slSetTag*)(FWindowsPlatformProcess::GetDllExport(SLInterPoserDLL, TEXT("slSetTag"))); UE_LOG(LogStreamlineRHI, Log, TEXT("slSetTag = %p"), Ptr_setTag); check(Ptr_setTag); Ptr_getFeatureRequirements = (PFun_slGetFeatureRequirements*)(FWindowsPlatformProcess::GetDllExport(SLInterPoserDLL, TEXT("slGetFeatureRequirements"))); UE_LOG(LogStreamlineRHI, Log, TEXT("slGetFeatureRequirements = %p"), Ptr_getFeatureRequirements); check(Ptr_getFeatureRequirements); Ptr_getFeatureVersion = (PFun_slGetFeatureVersion*)(FWindowsPlatformProcess::GetDllExport(SLInterPoserDLL, TEXT("slGetFeatureVersion"))); UE_LOG(LogStreamlineRHI, Log, TEXT("slGetFeatureVersion = %p"), Ptr_getFeatureVersion); check(Ptr_getFeatureVersion); Ptr_upgradeInterface = (PFun_slUpgradeInterface*)(FWindowsPlatformProcess::GetDllExport(SLInterPoserDLL, TEXT("slUpgradeInterface"))); UE_LOG(LogStreamlineRHI, Log, TEXT("slUpgradeInterface = %p"), Ptr_upgradeInterface); check(Ptr_upgradeInterface); Ptr_setConstants = (PFun_slSetConstants*)(FWindowsPlatformProcess::GetDllExport(SLInterPoserDLL, TEXT("slSetConstants"))); UE_LOG(LogStreamlineRHI, Log, TEXT("slSetConstants = %p"), Ptr_setConstants); check(Ptr_setConstants); Ptr_getNativeInterface = (PFun_slGetNativeInterface*)(FWindowsPlatformProcess::GetDllExport(SLInterPoserDLL, TEXT("slGetNativeInterface"))); UE_LOG(LogStreamlineRHI, Log, TEXT("slGetNativeInterface = %p"), Ptr_getNativeInterface); check(Ptr_getNativeInterface); Ptr_getFeatureFunction = (PFun_slGetFeatureFunction*)(FWindowsPlatformProcess::GetDllExport(SLInterPoserDLL, TEXT("slGetFeatureFunction"))); UE_LOG(LogStreamlineRHI, Log, TEXT("slGetFeatureFunction = %p"), Ptr_getFeatureFunction); check(Ptr_getFeatureFunction); Ptr_getNewFrameToken = (PFun_slGetNewFrameToken*)(FWindowsPlatformProcess::GetDllExport(SLInterPoserDLL, TEXT("slGetNewFrameToken"))); UE_LOG(LogStreamlineRHI, Log, TEXT("slGetNewFrameToken = %p"), Ptr_getNewFrameToken); check(Ptr_getNewFrameToken); Ptr_setD3DDevice = (PFun_slSetD3DDevice*)(FWindowsPlatformProcess::GetDllExport(SLInterPoserDLL, TEXT("slSetD3DDevice"))); UE_LOG(LogStreamlineRHI, Log, TEXT("slSetD3DDevice = %p"), Ptr_setD3DDevice); check(Ptr_setD3DDevice); bIsStreamlineFunctionPointersLoaded = true; } } return bIsStreamlineFunctionPointersLoaded; } #undef LOCTEXT_NAMESPACE