Fixes for SL inputs, incorrect resource size, invalid cmdlist, doubled slSetConstants, remove unnecessary hooks, fix sl dll override hooking

This commit is contained in:
FakeMichau
2025-08-12 17:20:48 +02:00
parent b8061e0e10
commit 889ceee24b
9 changed files with 117 additions and 52 deletions
+77 -29
View File
@@ -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)
{
+1 -1
View File
@@ -12,6 +12,7 @@ class Sl_Inputs_Dx12
std::optional<sl::Constants> 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] {};
+7 -1
View File
@@ -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;
}
+7 -14
View File
@@ -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)
+1 -1
View File
@@ -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);
+21 -4
View File
@@ -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);
+1
View File
@@ -38,6 +38,7 @@ class StreamlineHooks
private:
static sl::RenderAPI renderApi;
static std::mutex setConstantsMutex;
// Interposer
static decltype(&slInit) o_slInit;
@@ -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());
@@ -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;