mirror of
https://github.com/optiscaler/OptiScaler.git
synced 2026-08-25 15:46:45 +00:00
Add Nvngx FG Combo, FFX + Enabler combo mode
Mainly for use with FSR 4 FG as otherwise it doesn't make sense. FFX for the middle fake frame, Enabler for the rest: 2x - FFX 3x - Enabler 4x - FFX + Enabler 5x - Enabler 6x - FFX + Enabler Due to pacing, only odd number of fake frames are able to use FFX
This commit is contained in:
+2
-1
@@ -47,7 +47,8 @@ FGOutput=auto
|
||||
; Nukems - requires dlssg_to_fsr3_amd_is_better.dll, FSR 3 FG
|
||||
; Arturs - requires dlss-enabler-headless.dll, FSR 3 MFG
|
||||
; FFX - requires amd_fidelityfx_dx12.dll OR amd_fidelityfx_loader_dx12.dll + amd_fidelityfx_framegeneration_dx12.dll, FSRFG 3 or 4
|
||||
; None, Nukems, Arturs, FFX - Default (auto) is None
|
||||
; Combo - requires
|
||||
; None, Nukems, Arturs, FFX, Combo - Default (auto) is None
|
||||
FGNvngxReplacement=auto
|
||||
|
||||
; Frametime source, would affect frame pacing
|
||||
|
||||
@@ -115,6 +115,8 @@ bool Config::Reload(std::filesystem::path iniPath)
|
||||
FGNvngxReplacement.set_from_config(FGNvngxReplacement::Arturs);
|
||||
else if (lstrcmpiA(FGNvngxReplacementString.value().c_str(), "ffx") == 0)
|
||||
FGNvngxReplacement.set_from_config(FGNvngxReplacement::FFX);
|
||||
else if (lstrcmpiA(FGNvngxReplacementString.value().c_str(), "combo") == 0)
|
||||
FGNvngxReplacement.set_from_config(FGNvngxReplacement::Combo);
|
||||
}
|
||||
|
||||
if (auto forceXell = readBool("fakenvapi", "ForceXeLL"); forceXell.has_value() && forceXell.value())
|
||||
@@ -908,6 +910,8 @@ bool Config::SaveIni()
|
||||
FGNvngxReplacementString = "Arturs";
|
||||
else if (FGNvngxReplacementHeld.value() == FGNvngxReplacement::FFX)
|
||||
FGNvngxReplacementString = "FFX";
|
||||
else if (FGNvngxReplacementHeld.value() == FGNvngxReplacement::Combo)
|
||||
FGNvngxReplacementString = "Combo";
|
||||
}
|
||||
ini.SetValue("FrameGen", "FGNvngxReplacement", FGNvngxReplacementString.c_str());
|
||||
|
||||
|
||||
@@ -303,6 +303,7 @@ copy NUL "$(SolutionDir)x64\Release\a\!! EXTRACT ALL FILES TO GAME FOLDER !!" /Y
|
||||
</PreBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="framegen\nvngx\Nvngx_Combo.h" />
|
||||
<ClInclude Include="fsr4\FSR4Upgrade.h" />
|
||||
<ClInclude Include="hooks\Amdxc64_Hooks.h" />
|
||||
<ClInclude Include="DllNames.h" />
|
||||
@@ -593,6 +594,7 @@ copy NUL "$(SolutionDir)x64\Release\a\!! EXTRACT ALL FILES TO GAME FOLDER !!" /Y
|
||||
<ClInclude Include="NVNGX_Parameter.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="framegen\nvngx\Nvngx_Combo.cpp" />
|
||||
<ClCompile Include="fsr4\FSR4Upgrade.cpp" />
|
||||
<ClCompile Include="hooks\Amdxc64_Hooks.cpp" />
|
||||
<ClCompile Include="framegen\dlssg\DLSSG_Dx12.cpp" />
|
||||
|
||||
@@ -932,6 +932,9 @@
|
||||
<ClInclude Include="framegen\nvngx\Nvngx_Arturs.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="framegen\nvngx\Nvngx_Combo.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Config.cpp">
|
||||
@@ -1496,6 +1499,9 @@
|
||||
<ClCompile Include="framegen\nvngx\Nvngx_Arturs.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="framegen\nvngx\Nvngx_Combo.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="OptiScaler.rc" />
|
||||
|
||||
@@ -54,6 +54,7 @@ enum class FGNvngxReplacement : uint32_t
|
||||
Nukems,
|
||||
Arturs,
|
||||
FFX,
|
||||
Combo,
|
||||
};
|
||||
|
||||
enum class WorkingMode : uint32_t
|
||||
|
||||
@@ -0,0 +1,288 @@
|
||||
#include "pch.h"
|
||||
#include "Nvngx_Combo.h"
|
||||
|
||||
#include <NVNGX_Parameter.h>
|
||||
|
||||
#include "proxies/NVNGX_Proxy.h"
|
||||
#include "proxies/Ntdll_Proxy.h"
|
||||
#include <proxies/FfxApi_Proxy.h>
|
||||
#include <numbers>
|
||||
#include <misc/IdentifyGpu.h>
|
||||
|
||||
using Microsoft::WRL::ComPtr;
|
||||
|
||||
NVSDK_NGX_Result Nvngx_Combo::D3D12_Init(unsigned long long InApplicationId, const wchar_t* InApplicationDataPath,
|
||||
ID3D12Device* InDevice, const NVSDK_NGX_FeatureCommonInfo* InFeatureInfo,
|
||||
NVSDK_NGX_Version InSDKVersion)
|
||||
{
|
||||
return D3D12_Init_Ext(InApplicationId, InApplicationDataPath, InDevice, InSDKVersion, InFeatureInfo);
|
||||
}
|
||||
|
||||
NVSDK_NGX_Result Nvngx_Combo::D3D12_Init_Ext(unsigned long long InApplicationId, const wchar_t* InApplicationDataPath,
|
||||
ID3D12Device* InDevice, NVSDK_NGX_Version InSDKVersion,
|
||||
const NVSDK_NGX_FeatureCommonInfo* InFeatureInfo)
|
||||
{
|
||||
auto resultArturs =
|
||||
artursProvider->D3D12_Init_Ext(InApplicationId, InApplicationDataPath, InDevice, InSDKVersion, InFeatureInfo);
|
||||
auto resultFfx =
|
||||
ffxProvider->D3D12_Init_Ext(InApplicationId, InApplicationDataPath, InDevice, InSDKVersion, InFeatureInfo);
|
||||
|
||||
if (resultArturs != NVSDK_NGX_Result_Success || resultFfx != NVSDK_NGX_Result_Success)
|
||||
{
|
||||
return NVSDK_NGX_Result_Fail;
|
||||
}
|
||||
|
||||
return NVSDK_NGX_Result_Success;
|
||||
}
|
||||
|
||||
NVSDK_NGX_Result Nvngx_Combo::D3D12_Shutdown()
|
||||
{
|
||||
auto resultArturs = artursProvider->D3D12_Shutdown();
|
||||
auto resultFfx = ffxProvider->D3D12_Shutdown();
|
||||
|
||||
if (resultArturs != NVSDK_NGX_Result_Success || resultFfx != NVSDK_NGX_Result_Success)
|
||||
{
|
||||
return NVSDK_NGX_Result_Fail;
|
||||
}
|
||||
|
||||
return NVSDK_NGX_Result_Success;
|
||||
}
|
||||
|
||||
NVSDK_NGX_Result Nvngx_Combo::D3D12_Shutdown1(ID3D12Device* InDevice)
|
||||
{
|
||||
auto resultArturs = artursProvider->D3D12_Shutdown1(InDevice);
|
||||
auto resultFfx = ffxProvider->D3D12_Shutdown1(InDevice);
|
||||
|
||||
if (resultArturs != NVSDK_NGX_Result_Success || resultFfx != NVSDK_NGX_Result_Success)
|
||||
{
|
||||
return NVSDK_NGX_Result_Fail;
|
||||
}
|
||||
|
||||
return NVSDK_NGX_Result_Success;
|
||||
}
|
||||
|
||||
NVSDK_NGX_Result Nvngx_Combo::D3D12_GetScratchBufferSize(NVSDK_NGX_Feature InFeatureId,
|
||||
const NVSDK_NGX_Parameter* InParameters,
|
||||
size_t* OutSizeInBytes)
|
||||
{
|
||||
if (!OutSizeInBytes)
|
||||
return NVSDK_NGX_Result_FAIL_InvalidParameter;
|
||||
|
||||
*OutSizeInBytes = 0;
|
||||
|
||||
return NVSDK_NGX_Result_Success;
|
||||
}
|
||||
|
||||
NVSDK_NGX_Result Nvngx_Combo::D3D12_CreateFeature(ID3D12GraphicsCommandList* InCmdList, NVSDK_NGX_Feature InFeatureID,
|
||||
NVSDK_NGX_Parameter* InParameters, NVSDK_NGX_Handle** OutHandle)
|
||||
{
|
||||
Nvngx_Combo_Handle** OutOurHandle = (Nvngx_Combo_Handle**) OutHandle;
|
||||
|
||||
if (!OutOurHandle || !InParameters)
|
||||
return NVSDK_NGX_Result_FAIL_InvalidParameter;
|
||||
|
||||
if (InFeatureID != NVSDK_NGX_Feature_FrameGeneration)
|
||||
return NVSDK_NGX_Result_FAIL_FeatureNotSupported;
|
||||
|
||||
*OutOurHandle = new Nvngx_Combo_Handle(lastIdCreated++ + NVNGX_PROVIDER_ID_OFFSET, nullptr);
|
||||
|
||||
auto resultArturs =
|
||||
artursProvider->D3D12_CreateFeature(InCmdList, InFeatureID, InParameters, &(*OutOurHandle)->artursHandle);
|
||||
auto resultFfx =
|
||||
ffxProvider->D3D12_CreateFeature(InCmdList, InFeatureID, InParameters, &(*OutOurHandle)->ffxHandle);
|
||||
|
||||
if (resultArturs != NVSDK_NGX_Result_Success || resultFfx != NVSDK_NGX_Result_Success)
|
||||
{
|
||||
if (resultArturs == NVSDK_NGX_Result_Success)
|
||||
artursProvider->D3D12_ReleaseFeature((*OutOurHandle)->artursHandle);
|
||||
|
||||
if (resultFfx == NVSDK_NGX_Result_Success)
|
||||
ffxProvider->D3D12_ReleaseFeature((*OutOurHandle)->ffxHandle);
|
||||
|
||||
delete *OutOurHandle;
|
||||
*OutOurHandle = nullptr;
|
||||
|
||||
return NVSDK_NGX_Result_Fail;
|
||||
}
|
||||
|
||||
return NVSDK_NGX_Result_Success;
|
||||
}
|
||||
|
||||
NVSDK_NGX_Result Nvngx_Combo::D3D12_ReleaseFeature(NVSDK_NGX_Handle* InHandle)
|
||||
{
|
||||
Nvngx_Combo_Handle* InOurHandle = (Nvngx_Combo_Handle*) InHandle;
|
||||
|
||||
if (!InOurHandle || InOurHandle->Id < NVNGX_PROVIDER_ID_OFFSET)
|
||||
return NVSDK_NGX_Result_FAIL_InvalidParameter;
|
||||
|
||||
auto resultArturs = artursProvider->D3D12_ReleaseFeature(InOurHandle->artursHandle);
|
||||
auto resultFfx = ffxProvider->D3D12_ReleaseFeature(InOurHandle->ffxHandle);
|
||||
|
||||
delete InOurHandle;
|
||||
|
||||
if (resultArturs != NVSDK_NGX_Result_Success || resultFfx != NVSDK_NGX_Result_Success)
|
||||
{
|
||||
return NVSDK_NGX_Result_Fail;
|
||||
}
|
||||
|
||||
return NVSDK_NGX_Result_Success;
|
||||
}
|
||||
|
||||
NVSDK_NGX_Result Nvngx_Combo::D3D12_GetFeatureRequirements(IDXGIAdapter* Adapter,
|
||||
const NVSDK_NGX_FeatureDiscoveryInfo* FeatureDiscoveryInfo,
|
||||
NVSDK_NGX_FeatureRequirement* OutSupported)
|
||||
{
|
||||
if (!OutSupported)
|
||||
return NVSDK_NGX_Result_Fail;
|
||||
|
||||
OutSupported->FeatureSupported = NVSDK_NGX_FeatureSupportResult_Supported;
|
||||
OutSupported->MinHWArchitecture = 0x0;
|
||||
strcpy_s(OutSupported->MinOSVersion, "10.0.0");
|
||||
|
||||
return NVSDK_NGX_Result_Success;
|
||||
}
|
||||
|
||||
static D3D12_RESOURCE_STATES GetD3D12State(FfxApiResourceState state)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case FFX_API_RESOURCE_STATE_COMMON:
|
||||
return D3D12_RESOURCE_STATE_COMMON;
|
||||
case FFX_API_RESOURCE_STATE_UNORDERED_ACCESS:
|
||||
return D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
|
||||
case FFX_API_RESOURCE_STATE_COMPUTE_READ:
|
||||
return D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
|
||||
case FFX_API_RESOURCE_STATE_PIXEL_READ:
|
||||
return D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
|
||||
case FFX_API_RESOURCE_STATE_PIXEL_COMPUTE_READ:
|
||||
return (D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
|
||||
case FFX_API_RESOURCE_STATE_COPY_SRC:
|
||||
return D3D12_RESOURCE_STATE_COPY_SOURCE;
|
||||
case FFX_API_RESOURCE_STATE_COPY_DEST:
|
||||
return D3D12_RESOURCE_STATE_COPY_DEST;
|
||||
case FFX_API_RESOURCE_STATE_GENERIC_READ:
|
||||
return D3D12_RESOURCE_STATE_GENERIC_READ;
|
||||
case FFX_API_RESOURCE_STATE_INDIRECT_ARGUMENT:
|
||||
return D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT;
|
||||
case FFX_API_RESOURCE_STATE_RENDER_TARGET:
|
||||
return D3D12_RESOURCE_STATE_RENDER_TARGET;
|
||||
default:
|
||||
return D3D12_RESOURCE_STATE_COMMON;
|
||||
}
|
||||
}
|
||||
|
||||
static void CopyTexture(ID3D12GraphicsCommandList* CommandList, const FfxApiResource* Destination,
|
||||
const FfxApiResource* Source)
|
||||
{
|
||||
const auto cmdList12 = reinterpret_cast<ID3D12GraphicsCommandList*>(CommandList);
|
||||
|
||||
D3D12_RESOURCE_BARRIER barriers[2] = {};
|
||||
barriers[0].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
barriers[0].Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
barriers[0].Transition.pResource = static_cast<ID3D12Resource*>(Destination->resource); // Destination
|
||||
barriers[0].Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||
barriers[0].Transition.StateBefore = GetD3D12State((FfxApiResourceState) Destination->state);
|
||||
barriers[0].Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_DEST;
|
||||
|
||||
barriers[1] = barriers[0];
|
||||
barriers[1].Transition.pResource = static_cast<ID3D12Resource*>(Source->resource); // Source
|
||||
barriers[1].Transition.StateBefore = GetD3D12State((FfxApiResourceState) Source->state);
|
||||
barriers[1].Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_SOURCE;
|
||||
|
||||
cmdList12->ResourceBarrier(2, barriers);
|
||||
cmdList12->CopyResource(barriers[0].Transition.pResource, barriers[1].Transition.pResource);
|
||||
std::swap(barriers[0].Transition.StateBefore, barriers[0].Transition.StateAfter);
|
||||
std::swap(barriers[1].Transition.StateBefore, barriers[1].Transition.StateAfter);
|
||||
cmdList12->ResourceBarrier(2, barriers);
|
||||
}
|
||||
|
||||
NVSDK_NGX_Result Nvngx_Combo::D3D12_EvaluateFeature(ID3D12GraphicsCommandList* InCmdList,
|
||||
const NVSDK_NGX_Handle* InFeatureHandle,
|
||||
NVSDK_NGX_Parameter* InParameters,
|
||||
PFN_NVSDK_NGX_ProgressCallback InCallback)
|
||||
{
|
||||
// This is our handle so can cast away const
|
||||
Nvngx_Combo_Handle* InOurHandle = (Nvngx_Combo_Handle*) InFeatureHandle;
|
||||
|
||||
if (!InParameters || !InOurHandle || InOurHandle->Id < NVNGX_PROVIDER_ID_OFFSET)
|
||||
return NVSDK_NGX_Result_FAIL_InvalidParameter;
|
||||
|
||||
// Assuming ffx can only do one fake frame
|
||||
uint32_t frameIndex = 1;
|
||||
InParameters->Get("DLSSG.MultiFrameIndex", &frameIndex);
|
||||
|
||||
uint32_t frameCount = 0;
|
||||
InParameters->Get("DLSSG.MultiFrameCount", &frameCount);
|
||||
|
||||
NVSDK_NGX_Result result {};
|
||||
|
||||
if ((frameCount == 1 && frameIndex == 1) || (frameCount == 3 && frameIndex == 2) ||
|
||||
(frameCount == 5 && frameIndex == 3))
|
||||
{
|
||||
// Make the provider think we only want 2x to it generates the middle frame
|
||||
InParameters->Set("DLSSG.MultiFrameIndex", 1);
|
||||
InParameters->Set("DLSSG.MultiFrameCount", 1);
|
||||
|
||||
result = ffxProvider->D3D12_EvaluateFeature(InCmdList, InOurHandle->ffxHandle, InParameters, InCallback);
|
||||
|
||||
// Restore
|
||||
InParameters->Set("DLSSG.MultiFrameIndex", frameIndex);
|
||||
InParameters->Set("DLSSG.MultiFrameCount", frameCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = artursProvider->D3D12_EvaluateFeature(InCmdList, InOurHandle->artursHandle, InParameters, InCallback);
|
||||
}
|
||||
|
||||
ID3D12Resource* outputReal = nullptr;
|
||||
InParameters->Get("DLSSG.OutputReal", &outputReal);
|
||||
auto outputRealFfx = ffxApiGetResourceDX12(outputReal, FFX_API_RESOURCE_STATE_UNORDERED_ACCESS);
|
||||
|
||||
// Copy backbuffer to output real
|
||||
if (outputReal)
|
||||
{
|
||||
ID3D12Resource* backbuffer = nullptr;
|
||||
InParameters->Get("DLSSG.Backbuffer", &backbuffer);
|
||||
auto backbufferFfx = ffxApiGetResourceDX12(backbuffer, FFX_API_RESOURCE_STATE_COMPUTE_READ);
|
||||
|
||||
if (backbuffer)
|
||||
CopyTexture(InCmdList, &outputRealFfx, &backbufferFfx);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static NVSDK_NGX_Result GetCurrentSettingsCallback(Nvngx_Combo_Handle* InHandle, NVSDK_NGX_Parameter* InParameters)
|
||||
{
|
||||
if (!InHandle || !InParameters)
|
||||
return NVSDK_NGX_Result_FAIL_InvalidParameter;
|
||||
|
||||
InParameters->Set("DLSSG.MustCallEval", 1);
|
||||
InParameters->Set("DLSSG.BurstCaptureRunning", 0);
|
||||
|
||||
return NVSDK_NGX_Result_Success;
|
||||
}
|
||||
|
||||
static NVSDK_NGX_Result EstimateVRAMCallback(uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t,
|
||||
uint32_t, uint32_t, size_t* EstimatedSize)
|
||||
{
|
||||
// Assume 300MB
|
||||
if (EstimatedSize)
|
||||
*EstimatedSize = 300 * 1024 * 1024;
|
||||
|
||||
return NVSDK_NGX_Result_Success;
|
||||
}
|
||||
|
||||
NVSDK_NGX_Result Nvngx_Combo::D3D12_PopulateParameters_Impl(NVSDK_NGX_Parameter* InParameters)
|
||||
{
|
||||
if (!InParameters)
|
||||
return NVSDK_NGX_Result_FAIL_InvalidParameter;
|
||||
|
||||
InParameters->Set("DLSSG.GetCurrentSettingsCallback", &GetCurrentSettingsCallback);
|
||||
InParameters->Set("DLSSG.EstimateVRAMCallback", &EstimateVRAMCallback);
|
||||
|
||||
// if (inited) // Query FFX
|
||||
InParameters->Set("DLSSG.MultiFrameCountMax", 1);
|
||||
|
||||
return NVSDK_NGX_Result_Success;
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
#pragma once
|
||||
#include "IFGNvngx.h"
|
||||
#include "Nvngx_FFX.h"
|
||||
#include "Nvngx_Arturs.h"
|
||||
#include <d3d12.h>
|
||||
|
||||
struct Nvngx_Combo_Handle
|
||||
{
|
||||
unsigned int Id;
|
||||
|
||||
NVSDK_NGX_Handle* ffxHandle = nullptr;
|
||||
NVSDK_NGX_Handle* artursHandle = nullptr;
|
||||
};
|
||||
|
||||
class Nvngx_Combo : public IFGNvngx
|
||||
{
|
||||
private:
|
||||
std::atomic_uint32_t lastIdCreated = 0;
|
||||
|
||||
std::unique_ptr<Nvngx_Arturs> artursProvider = nullptr;
|
||||
std::unique_ptr<Nvngx_FFX> ffxProvider = nullptr;
|
||||
|
||||
public:
|
||||
Nvngx_Combo()
|
||||
{
|
||||
artursProvider = std::make_unique<Nvngx_Arturs>();
|
||||
ffxProvider = std::make_unique<Nvngx_FFX>();
|
||||
}
|
||||
|
||||
bool isDx12Available() override final
|
||||
{
|
||||
return artursProvider->isDx12Available() && ffxProvider->isDx12Available();
|
||||
};
|
||||
bool isVulkanAvailable() override final { return false; };
|
||||
|
||||
// DX12
|
||||
NVSDK_NGX_Result D3D12_Init(unsigned long long InApplicationId, const wchar_t* InApplicationDataPath,
|
||||
ID3D12Device* InDevice, const NVSDK_NGX_FeatureCommonInfo* InFeatureInfo,
|
||||
NVSDK_NGX_Version InSDKVersion) override;
|
||||
|
||||
NVSDK_NGX_Result D3D12_Init_Ext(unsigned long long InApplicationId, const wchar_t* InApplicationDataPath,
|
||||
ID3D12Device* InDevice, NVSDK_NGX_Version InSDKVersion,
|
||||
const NVSDK_NGX_FeatureCommonInfo* InFeatureInfo) override;
|
||||
|
||||
NVSDK_NGX_Result D3D12_Shutdown() override;
|
||||
|
||||
NVSDK_NGX_Result D3D12_Shutdown1(ID3D12Device* InDevice) override;
|
||||
|
||||
NVSDK_NGX_Result D3D12_GetScratchBufferSize(NVSDK_NGX_Feature InFeatureId, const NVSDK_NGX_Parameter* InParameters,
|
||||
size_t* OutSizeInBytes) override;
|
||||
|
||||
NVSDK_NGX_Result D3D12_CreateFeature(ID3D12GraphicsCommandList* InCmdList, NVSDK_NGX_Feature InFeatureID,
|
||||
NVSDK_NGX_Parameter* InParameters, NVSDK_NGX_Handle** OutHandle) override;
|
||||
|
||||
NVSDK_NGX_Result D3D12_ReleaseFeature(NVSDK_NGX_Handle* InHandle) override;
|
||||
|
||||
NVSDK_NGX_Result D3D12_GetFeatureRequirements(IDXGIAdapter* Adapter,
|
||||
const NVSDK_NGX_FeatureDiscoveryInfo* FeatureDiscoveryInfo,
|
||||
NVSDK_NGX_FeatureRequirement* OutSupported) override;
|
||||
|
||||
NVSDK_NGX_Result D3D12_EvaluateFeature(ID3D12GraphicsCommandList* InCmdList,
|
||||
const NVSDK_NGX_Handle* InFeatureHandle, NVSDK_NGX_Parameter* InParameters,
|
||||
PFN_NVSDK_NGX_ProgressCallback InCallback) override;
|
||||
|
||||
NVSDK_NGX_Result D3D12_PopulateParameters_Impl(NVSDK_NGX_Parameter* InParameters) override;
|
||||
|
||||
int getMaxFakeFramesCount() override { return 5; }
|
||||
FGNvngxReplacement getType() override { return FGNvngxReplacement::Combo; }
|
||||
};
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "Nvngx_Nukems.h"
|
||||
#include "Nvngx_Arturs.h"
|
||||
#include "Nvngx_FFX.h"
|
||||
#include "Nvngx_Combo.h"
|
||||
#include <imgui/ImGuiNotify.hpp>
|
||||
|
||||
IFGNvngx* Nvngx_FG::getProvider()
|
||||
@@ -33,6 +34,10 @@ IFGNvngx* Nvngx_FG::getProvider()
|
||||
_provider = std::make_unique<Nvngx_Arturs>();
|
||||
break;
|
||||
|
||||
case FGNvngxReplacement::Combo:
|
||||
_provider = std::make_unique<Nvngx_Combo>();
|
||||
break;
|
||||
|
||||
case FGNvngxReplacement::None:
|
||||
default:
|
||||
return nullptr;
|
||||
@@ -41,6 +46,7 @@ IFGNvngx* Nvngx_FG::getProvider()
|
||||
if (!_provider->isDx12Available() && !_provider->isVulkanAvailable())
|
||||
{
|
||||
// The selected provider cannot be used, try the remaining providers as fallback, try in order
|
||||
// FGNvngxReplacement::Combo doesn't make sense to try as it's Arturs + FFX
|
||||
const FGNvngxReplacement fallbacks[] = {
|
||||
FGNvngxReplacement::Arturs,
|
||||
FGNvngxReplacement::FFX,
|
||||
@@ -57,6 +63,8 @@ IFGNvngx* Nvngx_FG::getProvider()
|
||||
return "Nvngx FFX";
|
||||
case FGNvngxReplacement::Nukems:
|
||||
return "Nukems";
|
||||
case FGNvngxReplacement::Combo:
|
||||
return "Combo";
|
||||
case FGNvngxReplacement::None:
|
||||
default:
|
||||
return "???";
|
||||
|
||||
@@ -1783,6 +1783,10 @@ void MenuCommon::RenderPerformanceOverlay(RenderMenuContext& ctx)
|
||||
{
|
||||
fgText = formatFg("FFX", Nvngx_FG::getMaxFakeFramesCount());
|
||||
}
|
||||
else if (activeNvngxFg == FGNvngxReplacement::Combo)
|
||||
{
|
||||
fgText = formatFg("Combo", Nvngx_FG::getMaxFakeFramesCount());
|
||||
}
|
||||
|
||||
const auto overlayType = config->FpsOverlayType.value_or_default();
|
||||
const bool hasFeature = currentFeature && !currentFeature->IsFrozen();
|
||||
@@ -3107,6 +3111,8 @@ void MenuCommon::RenderFrameGenerationSelection(RenderMenuContext& ctx)
|
||||
{ FGNvngxReplacement::Nukems, "Nukem's", "FSR 3 FG" },
|
||||
{ FGNvngxReplacement::Arturs, "Enabler", "FSR 3 MFG" },
|
||||
{ FGNvngxReplacement::FFX, "FSR 3/4 FG", "FSR 3/4 FG using the FFX" },
|
||||
{ FGNvngxReplacement::Combo, "FFX + Enabler", "FFX for the middle fake frame, Enabler for the rest\n\n"
|
||||
"2x - FFX\n3x - Enabler\n4x - FFX + Enabler\n5x - Enabler\n6x - FFX + Enabler" },
|
||||
};
|
||||
|
||||
// clang-format on
|
||||
@@ -3144,6 +3150,11 @@ void MenuCommon::RenderFrameGenerationSelection(RenderMenuContext& ctx)
|
||||
nvngxOptions[fgNvngxFfxIndex].set_disabled(!FfxApiProxy::IsFGReady(false),
|
||||
"Missing amd_fidelityfx_framegeneration_dx12.dll");
|
||||
|
||||
auto constexpr fgNvngxComboIndex = (uint32_t) FGNvngxReplacement::Combo;
|
||||
nvngxOptions[fgNvngxComboIndex].set_disabled(
|
||||
!FfxApiProxy::IsFGReady(false) || !state.artursFgFileAvailable,
|
||||
"Missing amd_fidelityfx_framegeneration_dx12.dll\nor missing dlss-enabler-headless.dll");
|
||||
|
||||
// TODO: Automatically switch to any other option
|
||||
|
||||
if (!config->FGNvngxReplacement.has_value())
|
||||
@@ -4383,6 +4394,12 @@ void MenuCommon::RenderFrameGenerationRuntimeSettings(RenderMenuContext& ctx)
|
||||
{
|
||||
SeparatorWithHelpMarker("Frame Generation (FSRFG via FFX)", "FFX using the DLSSG swapchain");
|
||||
}
|
||||
else if (activeNvngxFg == FGNvngxReplacement::Combo)
|
||||
{
|
||||
SeparatorWithHelpMarker("Frame Generation (Enabler + FFX)",
|
||||
"FFX for middle fake frames, and Enabler for the rest\n\n2x - FFX\n"
|
||||
"3x - Enabler\n4x - FFX + Enabler\n5x - Enabler\n6x - FFX + Enabler");
|
||||
}
|
||||
|
||||
if (state.activeFgInput == FGInput::NvngxFG)
|
||||
{
|
||||
@@ -4448,7 +4465,7 @@ void MenuCommon::RenderFrameGenerationRuntimeSettings(RenderMenuContext& ctx)
|
||||
|
||||
if (isLoaded)
|
||||
{
|
||||
if (activeNvngxFg == FGNvngxReplacement::Arturs)
|
||||
if (activeNvngxFg == FGNvngxReplacement::Arturs || activeNvngxFg == FGNvngxReplacement::Combo)
|
||||
{
|
||||
if (bool showDebug = config->NvngxFGShowDebug.value_or_default();
|
||||
ImGui::Checkbox("Show Debug", &showDebug))
|
||||
@@ -4503,7 +4520,8 @@ void MenuCommon::RenderFrameGenerationRuntimeSettings(RenderMenuContext& ctx)
|
||||
config->NvngxFGDispatchFlags = temp_flags;
|
||||
}
|
||||
}
|
||||
else if (activeNvngxFg == FGNvngxReplacement::Nukems)
|
||||
|
||||
if (activeNvngxFg == FGNvngxReplacement::Nukems)
|
||||
{
|
||||
if (ImGui::Checkbox("Enable Debug View", &state.dlssgDebugView))
|
||||
{
|
||||
@@ -4514,7 +4532,8 @@ void MenuCommon::RenderFrameGenerationRuntimeSettings(RenderMenuContext& ctx)
|
||||
Nvngx_FG::setInterpolatedOnly(state.dlssgInterpolatedOnly);
|
||||
}
|
||||
}
|
||||
else if (activeNvngxFg == FGNvngxReplacement::FFX)
|
||||
|
||||
if (activeNvngxFg == FGNvngxReplacement::FFX || activeNvngxFg == FGNvngxReplacement::Combo)
|
||||
{
|
||||
if (_ffxFGIndex < 0)
|
||||
_ffxFGIndex = config->FfxFGIndex.value_or_default();
|
||||
|
||||
Reference in New Issue
Block a user