diff --git a/OptiScaler/framegen/Streamline_Inputs_Dx12.cpp b/OptiScaler/framegen/Streamline_Inputs_Dx12.cpp index 4d8173af..d05b4992 100644 --- a/OptiScaler/framegen/Streamline_Inputs_Dx12.cpp +++ b/OptiScaler/framegen/Streamline_Inputs_Dx12.cpp @@ -21,10 +21,13 @@ bool Sl_Inputs_Dx12::setConstants(const sl::Constants& values, uint32_t frameId) LOG_DEBUG("Setting consts for streamline index: {}", index); - // Streamline logs already log this + // Streamline already log this error, keep using the previous data static uint32_t lastFrameId = UINT32_MAX; - setConstantsSameFrameId = lastFrameId == frameId; - lastFrameId = frameId; + if (lastFrameId == frameId) + { + lastFrameId = frameId; + return false; + } data = sl::Constants {}; @@ -147,8 +150,7 @@ bool Sl_Inputs_Dx12::reportResource(const sl::ResourceTag& tag, ID3D12GraphicsCo return true; } - // TODO: detect if there are multiple calls to hkslSetConstants with the same ID, DRG crashing, sl sees an error - if (dispatched && !setConstantsSameFrameId) + if (dispatched) { fgOutput->StartNewFrame(); @@ -167,23 +169,32 @@ bool Sl_Inputs_Dx12::reportResource(const sl::ResourceTag& tag, ID3D12GraphicsCo hudlessSent = true; - // ResTrack_Dx12::SetHudlessCmdList(cmdBuffer); - auto hudlessResource = (ID3D12Resource*) tag.resource->native; auto validity = (tag.lifecycle != sl::eOnlyValidNow) ? FG_ResourceValidity::UntilPresent : FG_ResourceValidity::ValidNow; // We need to make sure we have a copy of hudless that WE can use - if (cmdBuffer != nullptr && validity == FG_ResourceValidity::ValidNow) - validity = FG_ResourceValidity::ValidButMakeCopy; + // TODO: bugged and copy crashes + // if (cmdBuffer != nullptr && validity == FG_ResourceValidity::ValidNow) + // validity = FG_ResourceValidity::ValidButMakeCopy; - fgOutput->SetResource(FG_ResourceType::HudlessColor, cmdBuffer, hudlessResource, tag.extent.width, - tag.extent.height, (D3D12_RESOURCE_STATES) tag.resource->state, validity); + auto width = tag.extent.width; + auto height = tag.extent.height; + + if (!tag.extent) + { + const auto desc = hudlessResource->GetDesc(); + width = desc.Width; + height = desc.Height; + } + + fgOutput->SetResource(FG_ResourceType::HudlessColor, cmdBuffer, hudlessResource, width, height, + (D3D12_RESOURCE_STATES) tag.resource->state, validity); // Assume hudless is the size used for interpolation - interpolationWidth = tag.extent.width; - interpolationHeight = tag.extent.height; + interpolationWidth = width; + interpolationHeight = height; auto static lastFormat = DXGI_FORMAT_UNKNOWN; auto format = hudlessResource->GetDesc().Format; @@ -206,9 +217,20 @@ bool Sl_Inputs_Dx12::reportResource(const sl::ResourceTag& tag, ID3D12GraphicsCo auto depthResource = (ID3D12Resource*) tag.resource->native; + auto width = tag.extent.width; + auto height = tag.extent.height; + + if (!tag.extent) + { + const auto desc = depthResource->GetDesc(); + width = desc.Width; + height = desc.Height; + } + const auto validity = (tag.lifecycle != sl::eOnlyValidNow) ? FG_ResourceValidity::UntilPresent : FG_ResourceValidity::ValidNow; - fgOutput->SetResource(FG_ResourceType::Depth, cmdBuffer, depthResource, tag.extent.width, tag.extent.height, + + fgOutput->SetResource(FG_ResourceType::Depth, cmdBuffer, depthResource, width, height, (D3D12_RESOURCE_STATES) tag.resource->state, validity); } else if (tag.type == sl::kBufferTypeMotionVectors) @@ -217,16 +239,25 @@ bool Sl_Inputs_Dx12::reportResource(const sl::ResourceTag& tag, ID3D12GraphicsCo mvsSent = true; - mvsWidth = tag.extent.width; - mvsHeight = tag.extent.height; - - // ResTrack_Dx12::SetMVsCmdList(cmdBuffer); - auto mvResource = (ID3D12Resource*) tag.resource->native; + auto width = tag.extent.width; + auto height = tag.extent.height; + + if (!tag.extent) + { + const auto desc = mvResource->GetDesc(); + width = desc.Width; + height = desc.Height; + } + + mvsWidth = width; + mvsHeight = height; + const auto validity = (tag.lifecycle != sl::eOnlyValidNow) ? FG_ResourceValidity::UntilPresent : FG_ResourceValidity::ValidNow; - fgOutput->SetResource(FG_ResourceType::Velocity, cmdBuffer, mvResource, tag.extent.width, tag.extent.height, + + fgOutput->SetResource(FG_ResourceType::Velocity, cmdBuffer, mvResource, width, height, (D3D12_RESOURCE_STATES) tag.resource->state, validity); } else if (tag.type == sl::kBufferTypeUIColorAndAlpha) @@ -237,13 +268,22 @@ bool Sl_Inputs_Dx12::reportResource(const sl::ResourceTag& tag, ID3D12GraphicsCo if (uiRequired) { - // ResTrack_Dx12::SetUICmdList(cmdBuffer); - auto uiResource = (ID3D12Resource*) tag.resource->native; + auto width = tag.extent.width; + auto height = tag.extent.height; + + if (!tag.extent) + { + const auto desc = uiResource->GetDesc(); + width = desc.Width; + height = desc.Height; + } + const auto validity = (tag.lifecycle != sl::eOnlyValidNow) ? FG_ResourceValidity::UntilPresent : FG_ResourceValidity::ValidNow; - fgOutput->SetResource(FG_ResourceType::UIColor, cmdBuffer, uiResource, tag.extent.width, tag.extent.height, + + fgOutput->SetResource(FG_ResourceType::UIColor, cmdBuffer, uiResource, width, height, (D3D12_RESOURCE_STATES) tag.resource->state, validity); } } @@ -253,14 +293,23 @@ bool Sl_Inputs_Dx12::reportResource(const sl::ResourceTag& tag, ID3D12GraphicsCo distortionFieldSent = true; - // ResTrack_Dx12::SetDistortionFieldCmdList(cmdBuffer); - auto distortionFieldResource = (ID3D12Resource*) tag.resource->native; + auto width = tag.extent.width; + auto height = tag.extent.height; + + if (!tag.extent) + { + const auto desc = distortionFieldResource->GetDesc(); + width = desc.Width; + height = desc.Height; + } + const auto validity = (tag.lifecycle != sl::eOnlyValidNow) ? FG_ResourceValidity::UntilPresent : FG_ResourceValidity::ValidNow; - fgOutput->SetResource(FG_ResourceType::Distortion, cmdBuffer, distortionFieldResource, tag.extent.width, - tag.extent.height, (D3D12_RESOURCE_STATES) tag.resource->state, validity); + + fgOutput->SetResource(FG_ResourceType::Distortion, cmdBuffer, distortionFieldResource, width, height, + (D3D12_RESOURCE_STATES) tag.resource->state, validity); } return true; @@ -366,8 +415,7 @@ bool Sl_Inputs_Dx12::dispatchFG() // Streamline is not 100% clear on if we should multiply by resolution or not. // But UE games and Dead Rising expect that multiplication to be done, even if the scale is 1.0. - // bool multiplyByResolution = dataCopy.mvecScale.x != 1.f || dataCopy.mvecScale.y - // != 1.f; + // bool multiplyByResolution = dataCopy.mvecScale.x != 1.f || dataCopy.mvecScale.y != 1.f; bool multiplyByResolution = true; if (multiplyByResolution) { diff --git a/OptiScaler/framegen/Streamline_Inputs_Dx12.h b/OptiScaler/framegen/Streamline_Inputs_Dx12.h index 197ff89b..b1d24e24 100644 --- a/OptiScaler/framegen/Streamline_Inputs_Dx12.h +++ b/OptiScaler/framegen/Streamline_Inputs_Dx12.h @@ -12,6 +12,7 @@ class Sl_Inputs_Dx12 std::optional slConstants[BUFFER_COUNT] {}; sl::EngineType engineType = sl::EngineType::eCount; + // TODO: make "sent" map/array bool depthSent = false; bool hudlessSent = false; bool mvsSent = false; @@ -21,7 +22,6 @@ class Sl_Inputs_Dx12 bool distortionFieldRequired = false; bool dispatched = false; - bool setConstantsSameFrameId = false; bool frameBasedTracking = false; uint32_t indexToFrameIdMapping[BUFFER_COUNT] {}; diff --git a/OptiScaler/framegen/xefg/XeFG_Dx12.cpp b/OptiScaler/framegen/xefg/XeFG_Dx12.cpp index c24ef142..311b5c21 100644 --- a/OptiScaler/framegen/xefg/XeFG_Dx12.cpp +++ b/OptiScaler/framegen/xefg/XeFG_Dx12.cpp @@ -658,10 +658,16 @@ void XeFG_Dx12::SetResource(FG_ResourceType type, ID3D12GraphicsCommandList* cmd xefg_swapchain_d3d12_resource_data_t resourceParam = GetResourceData(type); + // HACK: XeFG docs lie and cmd list is technically required as it checks for it + // But it doesn't seem to use it when the validity is UNTIL_NEXT_PRESENT + if (cmdList == nullptr && resourceParam.validity == XEFG_SWAPCHAIN_RV_UNTIL_NEXT_PRESENT) + cmdList = (ID3D12GraphicsCommandList*) 1; + auto result = XeFGProxy::D3D12TagFrameResource()(_swapChainContext, cmdList, _frameCount, &resourceParam); if (result != XEFG_SWAPCHAIN_RESULT_SUCCESS) { - LOG_ERROR("D3D12TagFrameResource Depth error: {} ({})", magic_enum::enum_name(result), (UINT) result); + LOG_ERROR("D3D12TagFrameResource {} error: {} ({})", magic_enum::enum_name(type), magic_enum::enum_name(result), + (UINT) result); return; } diff --git a/OptiScaler/hooks/HooksDx.cpp b/OptiScaler/hooks/HooksDx.cpp index 88490d13..ba9adfce 100644 --- a/OptiScaler/hooks/HooksDx.cpp +++ b/OptiScaler/hooks/HooksDx.cpp @@ -217,8 +217,6 @@ static HRESULT hkFGPresent(void* This, UINT SyncInterval, UINT Flags) LOG_DEBUG("_frameCounter: {}, flags: {:X}, Frametime: {}", _frameCounter, Flags, ftDelta); } - IFGFeature_Dx12* fg = State::Instance().currentFG; - if (willPresent) { if (State::Instance().activeFgInput == FGInput::Upscaler && HooksDx::dx12UpscaleTrig && @@ -257,11 +255,14 @@ static HRESULT hkFGPresent(void* This, UINT SyncInterval, UINT Flags) HooksDx::readbackBuffer->Unmap(0, nullptr); HooksDx::dx12UpscaleTrig = false; } + + if (State::Instance().slFGInputs.readyForDispatch() && !State::Instance().slFGInputs.dispatchFG()) + LOG_DEBUG("Streamline FG was not dispatched"); + + State::Instance().slFGInputs.markLastSendAsRequired(); } - if (State::Instance().slFGInputs.readyForDispatch()) - State::Instance().slFGInputs.dispatchFG(); - + IFGFeature_Dx12* fg = State::Instance().currentFG; bool mutexUsed = false; if (willPresent && fg != nullptr && fg->IsActive() && Config::Instance()->FGUseMutexForSwapchain.value_or_default() && fg->Mutex.getOwner() != 2) @@ -277,14 +278,6 @@ static HRESULT hkFGPresent(void* This, UINT SyncInterval, UINT Flags) fg->Present(); } - State::Instance().slFGInputs.markLastSendAsRequired(); - - // if (willPresent && State::Instance().activeFgInput == FGInput::DLSSG && - // State::Instance().slFGInputs.readyForDispatch() && fg != nullptr) - //{ - // State::Instance().slFGInputs.dispatchFG(nullptr); - // } - if (willPresent) { ResTrack_Dx12::ClearPossibleHudless(); @@ -310,7 +303,7 @@ static HRESULT hkFGPresent(void* This, UINT SyncInterval, UINT Flags) Hudfix_Dx12::PresentEnd(); - if (!State::Instance().reflexLimitsFps && State::Instance().activeFgOutput != FGOutput::NoFG) + if (willPresent && !State::Instance().reflexLimitsFps && State::Instance().activeFgOutput != FGOutput::NoFG) FrameLimit::sleep(fg != nullptr ? fg->IsActive() : false); if (mutexUsed && fg != nullptr) diff --git a/OptiScaler/hooks/Kernel_Hooks.h b/OptiScaler/hooks/Kernel_Hooks.h index ede41123..cd7e6489 100644 --- a/OptiScaler/hooks/Kernel_Hooks.h +++ b/OptiScaler/hooks/Kernel_Hooks.h @@ -621,7 +621,7 @@ class KernelHooks // Try to catch something like this: // C:\ProgramData/NVIDIA/NGX/models/sl_dlss_0/versions/133120/files/190_E658703.dll if (CheckDllNameW(&lcaseLibName, &slDlssNamesW) || - (lcaseLibName.contains(L"/versions/") && lcaseLibName.contains(L"/sl_dlss_"))) + (lcaseLibName.contains(L"/versions/") && lcaseLibName.contains(L"/sl_dlss_0"))) { auto dlssModule = KernelBaseProxy::LoadLibraryExW_()(lpLibFullPath, NULL, 0); diff --git a/OptiScaler/hooks/Streamline_Hooks.cpp b/OptiScaler/hooks/Streamline_Hooks.cpp index 6d1248cf..332f28ee 100644 --- a/OptiScaler/hooks/Streamline_Hooks.cpp +++ b/OptiScaler/hooks/Streamline_Hooks.cpp @@ -13,6 +13,7 @@ #include "include/sl.param/parameters.h" sl::RenderAPI StreamlineHooks::renderApi = sl::RenderAPI::eCount; +std::mutex StreamlineHooks::setConstantsMutex {}; // interposer decltype(&slInit) StreamlineHooks::o_slInit = nullptr; @@ -128,7 +129,7 @@ sl::Result StreamlineHooks::hkslSetTag(sl::ViewportHandle& viewport, sl::Resourc for (uint32_t i = 0; i < numTags; i++) { - if (tags[i].resource == nullptr) + if (tags[i].resource == nullptr || tags[i].resource->native == nullptr) { LOG_TRACE("Resource of type: {} is null, continuing", tags[i].type); continue; @@ -414,9 +415,8 @@ bool StreamlineHooks::hkdlssg_slOnPluginLoad(void* params, const char* loaderJSO sl::Result StreamlineHooks::hkslSetConstants(const sl::Constants& values, const sl::FrameToken& frame, const sl::ViewportHandle& viewport) { - unsigned int frameIndex = frame; - - LOG_TRACE("called with frameIndex: {}", frameIndex); + std::scoped_lock lock(setConstantsMutex); + LOG_TRACE("called with frameIndex: {}, viewport: {}", (unsigned int) frame, (unsigned int) viewport); State::Instance().slFGInputs.setConstants(values, (uint32_t) frame); @@ -426,8 +426,25 @@ sl::Result StreamlineHooks::hkslSetConstants(const sl::Constants& values, const bool StreamlineHooks::hkcommon_slOnPluginLoad(void* params, const char* loaderJSON, const char** pluginJSON) { LOG_FUNC(); + + // TODO: do it better than "static" and hoping for the best + static std::string config; + auto result = o_common_slOnPluginLoad(params, loaderJSON, pluginJSON); + // Completely disables Streamline hooks + // if (true) + //{ + // nlohmann::json configJson = nlohmann::json::parse(*pluginJSON); + + // configJson["hooks"].clear(); + // configJson["exclusive_hooks"].clear(); + + // config = configJson.dump(); + + // *pluginJSON = config.c_str(); + //} + if (Config::Instance()->StreamlineSpoofing.value_or_default()) setSystemCapsArch((sl::param::IParameters*) params, UINT_MAX); diff --git a/OptiScaler/hooks/Streamline_Hooks.h b/OptiScaler/hooks/Streamline_Hooks.h index 2729247c..0c86bf27 100644 --- a/OptiScaler/hooks/Streamline_Hooks.h +++ b/OptiScaler/hooks/Streamline_Hooks.h @@ -38,6 +38,7 @@ class StreamlineHooks private: static sl::RenderAPI renderApi; + static std::mutex setConstantsMutex; // Interposer static decltype(&slInit) o_slInit; diff --git a/OptiScaler/resource_tracking/ResTrack_dx12.cpp b/OptiScaler/resource_tracking/ResTrack_dx12.cpp index 150ce60e..29f6dc1c 100644 --- a/OptiScaler/resource_tracking/ResTrack_dx12.cpp +++ b/OptiScaler/resource_tracking/ResTrack_dx12.cpp @@ -1820,7 +1820,7 @@ void ResTrack_Dx12::HookDevice(ID3D12Device* device) o_CopyDescriptorsSimple = (PFN_CopyDescriptorsSimple) pVTable[24]; // Apply the detour - if (o_CreateDescriptorHeap != nullptr) + if (o_CreateDescriptorHeap != nullptr && State::Instance().activeFgInput == FGInput::Upscaler) { DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); diff --git a/OptiScaler/shaders/hudless_compare/HC_Dx12.cpp b/OptiScaler/shaders/hudless_compare/HC_Dx12.cpp index 77763de9..e842a15e 100644 --- a/OptiScaler/shaders/hudless_compare/HC_Dx12.cpp +++ b/OptiScaler/shaders/hudless_compare/HC_Dx12.cpp @@ -318,7 +318,7 @@ bool HC_Dx12::Dispatch(IDXGISwapChain3* sc, ID3D12CommandQueue* queue, ID3D12Res // Check Hudless Buffer D3D12_RESOURCE_DESC hudlessDesc = hudless->GetDesc(); - if (hudlessDesc.Format != scDesc.BufferDesc.Format || hudlessDesc.Width != scDesc.BufferDesc.Width || + if (/*hudlessDesc.Format != scDesc.BufferDesc.Format ||*/ hudlessDesc.Width != scDesc.BufferDesc.Width || hudlessDesc.Height != scDesc.BufferDesc.Height) { return false;