This commit is contained in:
cdozdil
2025-08-10 12:50:22 +03:00
7 changed files with 151 additions and 48 deletions
+23 -18
View File
@@ -127,7 +127,7 @@ bool Sl_Inputs_Dx12::evaluateState(ID3D12Device* device)
bool Sl_Inputs_Dx12::reportResource(const sl::ResourceTag& tag, ID3D12GraphicsCommandList* cmdBuffer, uint32_t frameId)
{
if (!cmdBuffer)
LOG_ERROR("cmdBuffer is null");
LOG_TRACE("cmdBuffer is null");
auto fgOutput = reinterpret_cast<IFGFeature_Dx12*>(State::Instance().currentFG);
@@ -166,15 +166,18 @@ bool Sl_Inputs_Dx12::reportResource(const sl::ResourceTag& tag, ID3D12GraphicsCo
auto hudlessResource = (ID3D12Resource*) tag.resource->native;
const auto validity =
(tag.lifecycle == sl::eOnlyValidNow) ? FG_ResourceValidity::ValidNow : FG_ResourceValidity::UntilPresent;
fgOutput->SetResource(FG_ResourceType::HudlessColor, cmdBuffer, hudlessResource, tag.resource->width,
tag.resource->height, (D3D12_RESOURCE_STATES) tag.resource->state, validity);
(tag.lifecycle != sl::eOnlyValidNow) ? FG_ResourceValidity::UntilPresent : FG_ResourceValidity::ValidNow;
fgOutput->SetResource(FG_ResourceType::HudlessColor, cmdBuffer, hudlessResource, tag.extent.width,
tag.extent.height, (D3D12_RESOURCE_STATES) tag.resource->state, validity);
// Assume hudless is the size used for interpolation
interpolationWidth = tag.extent.width;
interpolationHeight = tag.extent.height;
auto static lastFormat = DXGI_FORMAT_UNKNOWN;
auto format = hudlessResource->GetDesc().Format;
// This might be specific to FSR FG
// Hopefully we don't need to use ffxCreateContextDescFrameGenerationHudless
if (lastFormat != DXGI_FORMAT_UNKNOWN && lastFormat != format)
{
State::Instance().FGchanged = true;
@@ -193,9 +196,9 @@ bool Sl_Inputs_Dx12::reportResource(const sl::ResourceTag& tag, ID3D12GraphicsCo
auto depthResource = (ID3D12Resource*) tag.resource->native;
const auto validity =
(tag.lifecycle == sl::eOnlyValidNow) ? FG_ResourceValidity::ValidNow : FG_ResourceValidity::UntilPresent;
fgOutput->SetResource(FG_ResourceType::Depth, cmdBuffer, depthResource, tag.resource->width,
tag.resource->height, (D3D12_RESOURCE_STATES) tag.resource->state, validity);
(tag.lifecycle != sl::eOnlyValidNow) ? FG_ResourceValidity::UntilPresent : FG_ResourceValidity::ValidNow;
fgOutput->SetResource(FG_ResourceType::Depth, cmdBuffer, depthResource, tag.extent.width, tag.extent.height,
(D3D12_RESOURCE_STATES) tag.resource->state, validity);
}
else if (tag.type == sl::kBufferTypeMotionVectors)
{
@@ -208,9 +211,9 @@ bool Sl_Inputs_Dx12::reportResource(const sl::ResourceTag& tag, ID3D12GraphicsCo
auto mvResource = (ID3D12Resource*) tag.resource->native;
const auto validity =
(tag.lifecycle == sl::eOnlyValidNow) ? FG_ResourceValidity::ValidNow : FG_ResourceValidity::UntilPresent;
fgOutput->SetResource(FG_ResourceType::Velocity, cmdBuffer, mvResource, tag.resource->width,
tag.resource->height, (D3D12_RESOURCE_STATES) tag.resource->state, validity);
(tag.lifecycle != sl::eOnlyValidNow) ? FG_ResourceValidity::UntilPresent : FG_ResourceValidity::ValidNow;
fgOutput->SetResource(FG_ResourceType::Velocity, cmdBuffer, mvResource, tag.extent.width, tag.extent.height,
(D3D12_RESOURCE_STATES) tag.resource->state, validity);
}
else if (tag.type == sl::kBufferTypeUIColorAndAlpha)
{
@@ -224,10 +227,10 @@ bool Sl_Inputs_Dx12::reportResource(const sl::ResourceTag& tag, ID3D12GraphicsCo
auto uiResource = (ID3D12Resource*) tag.resource->native;
const auto validity = (tag.lifecycle == sl::eOnlyValidNow) ? FG_ResourceValidity::ValidNow
: FG_ResourceValidity::UntilPresent;
fgOutput->SetResource(FG_ResourceType::UIColor, cmdBuffer, uiResource, tag.resource->width,
tag.resource->height, (D3D12_RESOURCE_STATES) tag.resource->state, validity);
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,
(D3D12_RESOURCE_STATES) tag.resource->state, validity);
}
}
else if (tag.type == sl::kBufferTypeBidirectionalDistortionField)
@@ -241,9 +244,9 @@ bool Sl_Inputs_Dx12::reportResource(const sl::ResourceTag& tag, ID3D12GraphicsCo
auto distortionFieldResource = (ID3D12Resource*) tag.resource->native;
const auto validity =
(tag.lifecycle == sl::eOnlyValidNow) ? FG_ResourceValidity::ValidNow : FG_ResourceValidity::UntilPresent;
fgOutput->SetResource(FG_ResourceType::Distortion, cmdBuffer, distortionFieldResource, tag.resource->width,
tag.resource->height, (D3D12_RESOURCE_STATES) tag.resource->state, 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);
}
if (readyForDispatch())
@@ -363,6 +366,8 @@ bool Sl_Inputs_Dx12::dispatchFG(ID3D12GraphicsCommandList* cmdBuffer)
fgOutput->SetReset(slConstsRef.reset == sl::Boolean::eTrue);
fgOutput->SetInterpolationRect(interpolationWidth, interpolationHeight);
return true;
}
@@ -25,6 +25,9 @@ class Sl_Inputs_Dx12
bool frameBasedTracking = false;
uint32_t indexToFrameIdMapping[BUFFER_COUNT] {};
uint32_t interpolationWidth = 0;
uint32_t interpolationHeight = 0;
std::optional<sl::Constants>* getFrameData(IFGFeature_Dx12* fgOutput);
public:
+1 -2
View File
@@ -268,8 +268,7 @@ static HRESULT hkFGPresent(void* This, UINT SyncInterval, UINT Flags)
LOG_TRACE("Accuired FG->Mutex: {}", fg->Mutex.getOwner());
}
if (willPresent && State::Instance().currentCommandQueue != nullptr &&
State::Instance().activeFgInput == FGInput::Upscaler && fg != nullptr && fg->IsActive())
if (willPresent && State::Instance().currentCommandQueue != nullptr && fg != nullptr && fg->IsActive())
{
fg->Present();
}
+33 -13
View File
@@ -108,6 +108,12 @@ sl::Result StreamlineHooks::hkslInit(sl::Preferences* pref, uint64_t sdkVersion)
renderApi = pref->renderAPI;
State::Instance().slFGInputs.reportEngineType(pref->engine);
// bool hookSetTag =
// (State::Instance().activeFgInput == FGInput::Nukems || State::Instance().activeFgInput == FGInput::DLSSG);
// if (hookSetTag)
// pref->flags &= ~(sl::PreferenceFlags::eAllowOTA | sl::PreferenceFlags::eLoadDownloadedPlugins);
return o_slInit(*pref, sdkVersion);
}
@@ -122,6 +128,12 @@ sl::Result StreamlineHooks::hkslSetTag(sl::ViewportHandle& viewport, sl::Resourc
for (uint32_t i = 0; i < numTags; i++)
{
if (tags[i].resource == nullptr)
{
LOG_TRACE("Resource of type: {} is null, continuing", tags[i].type);
continue;
}
// Cyberpunk hudless state fix for RDNA 2
if (State::Instance().gameQuirks & GameQuirk::CyberpunkHudlessStateOverride &&
tags[i].resource->state ==
@@ -158,6 +170,12 @@ sl::Result StreamlineHooks::hkslSetTagForFrame(const sl::FrameToken& frame, cons
for (uint32_t i = 0; i < numResources; i++)
{
if (resources[i].resource == nullptr)
{
LOG_TRACE("Resource of type: {} is null, continuing", resources[i].type);
continue;
}
if (State::Instance().activeFgInput == FGInput::DLSSG &&
(resources[i].type == sl::kBufferTypeHUDLessColor || resources[i].type == sl::kBufferTypeDepth ||
resources[i].type == sl::kBufferTypeHiResDepth || resources[i].type == sl::kBufferTypeLinearDepth ||
@@ -692,6 +710,8 @@ void StreamlineHooks::hookInterposer(HMODULE slInterposer)
char dllPath[MAX_PATH];
GetModuleFileNameA(slInterposer, dllPath, MAX_PATH);
LOG_TRACE("slInterposer path: {}", dllPath);
Util::version_t sl_version;
Util::GetDLLVersion(string_to_wstring(dllPath), &sl_version);
@@ -727,8 +747,8 @@ void StreamlineHooks::hookInterposer(HMODULE slInterposer)
DetourAttach(&(PVOID&) o_slInit, hkslInit);
bool hookSetTag = (Config::Instance()->FGInput.value_or_default() == FGInput::Nukems ||
Config::Instance()->FGInput.value_or_default() == FGInput::DLSSG);
bool hookSetTag = (State::Instance().activeFgInput == FGInput::Nukems ||
State::Instance().activeFgInput == FGInput::DLSSG);
if (o_slSetTag != nullptr && hookSetTag)
DetourAttach(&(PVOID&) o_slSetTag, hkslSetTag);
@@ -736,20 +756,20 @@ void StreamlineHooks::hookInterposer(HMODULE slInterposer)
if (o_slSetTagForFrame != nullptr && hookSetTag)
DetourAttach(&(PVOID&) o_slSetTagForFrame, hkslSetTagForFrame);
if (o_slEvaluateFeature != nullptr)
DetourAttach(&(PVOID&) o_slEvaluateFeature, hkslEvaluateFeature);
if (o_slAllocateResources != nullptr)
DetourAttach(&(PVOID&) o_slAllocateResources, hkslAllocateResources);
if (o_slSetConstants != nullptr)
if (o_slSetConstants != nullptr && hookSetTag)
DetourAttach(&(PVOID&) o_slSetConstants, hkslSetConstants);
if (o_slGetNativeInterface != nullptr)
DetourAttach(&(PVOID&) o_slGetNativeInterface, hkslGetNativeInterface);
// if (o_slEvaluateFeature != nullptr)
// DetourAttach(&(PVOID&) o_slEvaluateFeature, hkslEvaluateFeature);
if (o_slSetD3DDevice != nullptr)
DetourAttach(&(PVOID&) o_slSetD3DDevice, hkslSetD3DDevice);
// if (o_slAllocateResources != nullptr)
// DetourAttach(&(PVOID&) o_slAllocateResources, hkslAllocateResources);
// if (o_slGetNativeInterface != nullptr)
// DetourAttach(&(PVOID&) o_slGetNativeInterface, hkslGetNativeInterface);
// if (o_slSetD3DDevice != nullptr)
// DetourAttach(&(PVOID&) o_slSetD3DDevice, hkslSetD3DDevice);
DetourTransactionCommit();
}
+23 -7
View File
@@ -18,7 +18,10 @@ NvAPI_Status ReflexHooks::hkNvAPI_D3D_SetSleepMode(IUnknown* pDev, NV_SET_SLEEP_
if (_minimumIntervalUs != 0)
pSetSleepModeParams->minimumIntervalUs = _minimumIntervalUs;
return o_NvAPI_D3D_SetSleepMode(pDev, pSetSleepModeParams);
if (State::Instance().activeFgOutput == FGOutput::XeFG && fakenvapi::ForNvidia_SetSleepMode)
return fakenvapi::ForNvidia_SetSleepMode(pDev, pSetSleepModeParams);
else
return o_NvAPI_D3D_SetSleepMode(pDev, pSetSleepModeParams);
}
NvAPI_Status ReflexHooks::hkNvAPI_D3D_Sleep(IUnknown* pDev)
@@ -27,7 +30,10 @@ NvAPI_Status ReflexHooks::hkNvAPI_D3D_Sleep(IUnknown* pDev)
LOG_FUNC();
#endif
return o_NvAPI_D3D_Sleep(pDev);
if (State::Instance().activeFgOutput == FGOutput::XeFG && fakenvapi::ForNvidia_Sleep)
return fakenvapi::ForNvidia_Sleep(pDev);
else
return o_NvAPI_D3D_Sleep(pDev);
}
NvAPI_Status ReflexHooks::hkNvAPI_D3D_GetLatency(IUnknown* pDev, NV_LATENCY_RESULT_PARAMS* pGetLatencyParams)
@@ -36,7 +42,10 @@ NvAPI_Status ReflexHooks::hkNvAPI_D3D_GetLatency(IUnknown* pDev, NV_LATENCY_RESU
LOG_FUNC();
#endif
return o_NvAPI_D3D_GetLatency(pDev, pGetLatencyParams);
if (State::Instance().activeFgOutput == FGOutput::XeFG && fakenvapi::ForNvidia_GetLatency)
return fakenvapi::ForNvidia_GetLatency(pDev, pGetLatencyParams);
else
return o_NvAPI_D3D_GetLatency(pDev, pGetLatencyParams);
}
NvAPI_Status ReflexHooks::hkNvAPI_D3D_SetLatencyMarker(IUnknown* pDev,
@@ -75,7 +84,10 @@ NvAPI_Status ReflexHooks::hkNvAPI_D3D_SetLatencyMarker(IUnknown* pDev,
State::Instance().slFGInputs.evaluateState(device12);
}
return o_NvAPI_D3D_SetLatencyMarker(pDev, pSetLatencyMarkerParams);
if (State::Instance().activeFgOutput == FGOutput::XeFG && fakenvapi::ForNvidia_SetLatencyMarker)
return fakenvapi::ForNvidia_SetLatencyMarker(pDev, pSetLatencyMarkerParams);
else
return o_NvAPI_D3D_SetLatencyMarker(pDev, pSetLatencyMarkerParams);
}
NvAPI_Status ReflexHooks::hkNvAPI_D3D12_SetAsyncFrameMarker(ID3D12CommandQueue* pCommandQueue,
@@ -119,7 +131,10 @@ NvAPI_Status ReflexHooks::hkNvAPI_D3D12_SetAsyncFrameMarker(ID3D12CommandQueue*
}
}
return o_NvAPI_D3D12_SetAsyncFrameMarker(pCommandQueue, pSetAsyncFrameMarkerParams);
if (State::Instance().activeFgOutput == FGOutput::XeFG && fakenvapi::ForNvidia_SetAsyncFrameMarker)
return fakenvapi::ForNvidia_SetAsyncFrameMarker(pCommandQueue, pSetAsyncFrameMarkerParams);
else
return o_NvAPI_D3D12_SetAsyncFrameMarker(pCommandQueue, pSetAsyncFrameMarkerParams);
}
NvAPI_Status ReflexHooks::hkNvAPI_Vulkan_SetLatencyMarker(HANDLE vkDevice,
@@ -240,8 +255,9 @@ void ReflexHooks::update(bool optiFg_FgState, bool isVulkan)
// Don't use when: Real Reflex markers + OptiFG + Reflex disabled, causes huge input latency
State::Instance().reflexLimitsFps =
fakenvapi::isUsingFakenvapi() || !optiFg_FgState || _lastSleepParams.bLowLatencyMode;
State::Instance().reflexShowWarning =
!fakenvapi::isUsingFakenvapi() && optiFg_FgState && _lastSleepParams.bLowLatencyMode;
State::Instance().reflexShowWarning = State::Instance().activeFgOutput != FGOutput::XeFG &&
!fakenvapi::isUsingFakenvapi() && optiFg_FgState &&
_lastSleepParams.bLowLatencyMode;
}
static float lastFps = 0;
+55 -6
View File
@@ -1,9 +1,6 @@
#include "fakenvapi.h"
#include "proxies/FfxApi_Proxy.h"
void* fakenvapi::_lowLatencyContext = nullptr;
Mode fakenvapi::_lowLatencyMode = Mode::LatencyFlex;
void fakenvapi::Init(PFN_NvApi_QueryInterface& queryInterface)
{
if (_inited)
@@ -84,7 +81,10 @@ void fakenvapi::reportFGPresent(IDXGISwapChain* pSwapChain, bool fg_state, bool
bool fakenvapi::updateModeAndContext()
{
if (!isUsingFakenvapi())
if (!isUsingFakenvapi() && State::Instance().activeFgOutput == FGOutput::XeFG)
auto loaded = fakenvapi::loadForNvidia();
if (!isUsingFakenvapi() && !isUsingFakenvapiOnNvidia())
return false;
LOG_FUNC();
@@ -120,7 +120,10 @@ bool fakenvapi::updateModeAndContext()
bool fakenvapi::setModeAndContext(void* context, Mode mode)
{
if (!isUsingFakenvapi())
if (!isUsingFakenvapi() && State::Instance().activeFgOutput == FGOutput::XeFG)
auto loaded = fakenvapi::loadForNvidia();
if (!isUsingFakenvapi() && !isUsingFakenvapiOnNvidia())
return false;
LOG_FUNC();
@@ -138,8 +141,54 @@ bool fakenvapi::setModeAndContext(void* context, Mode mode)
return false;
}
bool fakenvapi::loadForNvidia()
{
if (!State::Instance().isRunningOnNvidia)
return false;
if (_dllForNvidia != nullptr)
return true;
_dllForNvidia = KernelBaseProxy::LoadLibraryExW_()(L"fakenvapi.dll", NULL, 0);
if (!_dllForNvidia)
return false;
auto queryInterface =
(PFN_NvApi_QueryInterface) KernelBaseProxy::GetProcAddress_()(_dllForNvidia, "nvapi_QueryInterface");
if (queryInterface == nullptr)
{
_dllForNvidia = nullptr;
return false;
}
ForNvidia_SetSleepMode = GET_INTERFACE(NvAPI_D3D_SetSleepMode, queryInterface);
ForNvidia_Sleep = GET_INTERFACE(NvAPI_D3D_Sleep, queryInterface);
ForNvidia_GetLatency = GET_INTERFACE(NvAPI_D3D_GetLatency, queryInterface);
ForNvidia_SetLatencyMarker = GET_INTERFACE(NvAPI_D3D_SetLatencyMarker, queryInterface);
ForNvidia_SetAsyncFrameMarker = GET_INTERFACE(NvAPI_D3D12_SetAsyncFrameMarker, queryInterface);
Fake_InformFGState = static_cast<decltype(Fake_InformFGState)>(queryInterface(GET_ID(Fake_InformFGState)));
Fake_InformPresentFG = static_cast<decltype(Fake_InformPresentFG)>(queryInterface(GET_ID(Fake_InformPresentFG)));
Fake_GetAntiLagCtx = static_cast<decltype(Fake_GetAntiLagCtx)>(queryInterface(GET_ID(Fake_GetAntiLagCtx)));
Fake_GetLowLatencyCtx = static_cast<decltype(Fake_GetLowLatencyCtx)>(queryInterface(GET_ID(Fake_GetLowLatencyCtx)));
Fake_SetLowLatencyCtx = static_cast<decltype(Fake_SetLowLatencyCtx)>(queryInterface(GET_ID(Fake_SetLowLatencyCtx)));
if (Fake_SetLowLatencyCtx)
{
_initedForNvidia = true;
LOG_INFO("fakenvapi initialized for Nvidia");
return true;
}
LOG_INFO("Failed to initialize fakenvapi for Nvidia");
return false;
}
// updateModeAndContext needs to be called before that
Mode fakenvapi::getCurrentMode() { return _lowLatencyMode; }
// won't work with older fakenvapi builds
bool fakenvapi::isUsingFakenvapi() { return _inited; }
bool fakenvapi::isUsingFakenvapiOnNvidia() { return _initedForNvidia; }
+13 -2
View File
@@ -1,6 +1,7 @@
#pragma once
#include <dxgi.h>
#include <d3d12.h>
#include <fakenvapi_inc.h>
#include "NvApiTypes.h"
@@ -19,18 +20,28 @@ class fakenvapi
inline static decltype(&Fake_SetLowLatencyCtx) Fake_SetLowLatencyCtx = nullptr;
inline static bool _inited = false;
static void* _lowLatencyContext;
static Mode _lowLatencyMode;
inline static bool _initedForNvidia = false;
inline static void* _lowLatencyContext = nullptr;
inline static Mode _lowLatencyMode = Mode::LatencyFlex;
inline static HMODULE _dllForNvidia = nullptr;
public:
inline static const GUID IID_IFfxAntiLag2Data = {
0x5083ae5b, 0x8070, 0x4fca, { 0x8e, 0xe5, 0x35, 0x82, 0xdd, 0x36, 0x7d, 0x13 }
};
inline static decltype(&NvAPI_D3D_SetSleepMode) ForNvidia_SetSleepMode = nullptr;
inline static decltype(&NvAPI_D3D_Sleep) ForNvidia_Sleep = nullptr;
inline static decltype(&NvAPI_D3D_GetLatency) ForNvidia_GetLatency = nullptr;
inline static decltype(&NvAPI_D3D_SetLatencyMarker) ForNvidia_SetLatencyMarker = nullptr;
inline static decltype(&NvAPI_D3D12_SetAsyncFrameMarker) ForNvidia_SetAsyncFrameMarker = nullptr;
static void Init(PFN_NvApi_QueryInterface& queryInterface);
static void reportFGPresent(IDXGISwapChain* pSwapChain, bool fg_state, bool frame_interpolated);
static bool updateModeAndContext();
static bool setModeAndContext(void* context, Mode mode);
static bool loadForNvidia();
static Mode getCurrentMode();
static bool isUsingFakenvapi();
static bool isUsingFakenvapiOnNvidia();
};