Fixed dlss issues.

This commit is contained in:
Justin Marshall
2026-05-21 08:19:03 -07:00
parent ce78a355f5
commit 2e4265f5a1
17 changed files with 97617 additions and 92471 deletions
+557 -11
View File
@@ -73,6 +73,8 @@ using Microsoft::WRL::ComPtr;
#include <sl_consts.h>
#include <sl_dlss.h>
#include <sl_dlss_d.h>
#include <sl_dlss_g.h>
#include <sl_reflex.h>
#endif
#if defined(QD3D12_ENABLE_FFX)
@@ -197,6 +199,9 @@ using Microsoft::WRL::ComPtr;
#ifndef GL_QD3D12_NEURAL_POM_BINDING
#define GL_QD3D12_NEURAL_POM_BINDING 0x600D
#endif
#ifndef GL_QD3D12_FRAME_GENERATION
#define GL_QD3D12_FRAME_GENERATION 0x600E
#endif
#ifndef GL_QD3D12_TAA
#define GL_QD3D12_TAA GL_QD3D12_TAA_ENABLED
#endif
@@ -327,6 +332,8 @@ void QD3D12_SetUpscalerQuality(int quality);
void QD3D12_SetUpscalerSharpness(float sharpness);
void QD3D12_SetToneMapBrightness(float brightness);
float QD3D12_GetToneMapBrightness(void);
void QD3D12_SetFrameGenerationMultiplier(int multiplier);
int QD3D12_GetFrameGenerationMultiplier(void);
void APIENTRY glToneMapBrightnessQD3D12(GLfloat brightness);
void APIENTRY glToneMapBrightnessfQD3D12(GLfloat brightness);
void APIENTRY glTonemapBrightnessQD3D12(GLfloat brightness);
@@ -1295,14 +1302,20 @@ struct GLState
std::unordered_map<GLuint, Mat4> prevObjectMVPs;
std::unordered_map<GLuint, Mat4> currObjectMVPs;
uint64_t frameSerial = 0;
#if defined(QD3D12_ENABLE_STREAMLINE)
sl::FrameToken* streamlineFrameToken = nullptr;
uint64_t streamlineFrameTokenSerial = UINT64_MAX;
uint64_t streamlineConstantsSerial = UINT64_MAX;
#endif
bool motionHistoryReset = true;
QD3D12UpscalerBackend upscalerBackend = QD3D12_UPSCALER_DLSS;
QD3D12UpscalerQuality upscalerQuality = QD3D12_QUALITY_DLAA;
QD3D12UpscalerQuality upscalerQuality = QD3D12_QUALITY_PERFORMANCE;
bool enableInternalTAA = true;
bool enableRayAIDenoise = false;
bool enableDLSSRayReconstruction = true;
bool enableFSRRayRegeneration = false;
uint32_t frameGenerationMultiplier = 2;
uint32_t pathTracingSamplesPerPixel = 1;
uint32_t pathTracingFallbackSamplesPerPixel = 2;
uint32_t pathTracingMaxBounces = 2;
@@ -6095,6 +6108,14 @@ struct QD3D12StreamlineState
bool deviceBound = false;
bool dlssSupported = false;
bool dlssRrSupported = false;
bool dlssGSupported = false;
bool dlssGFeatureLoaded = false;
bool reflexSupported = false;
bool dlssGActive = false;
uint32_t lastDlssGStatusLogged = 0;
uint32_t lastDlssGEligibilityMaskLogged = 0xffffffffu;
uint32_t lastDlssGFramesToGenerateLogged = 0xffffffffu;
uint32_t lastDlssGPresentedFramesLogged = 0xffffffffu;
sl::ViewportHandle viewport = { 1 };
};
static QD3D12StreamlineState g_qd3d12Sl;
@@ -6110,6 +6131,106 @@ struct QD3D12StreamlineInterposerState
};
static QD3D12StreamlineInterposerState g_qd3d12SlInterposer;
static bool QD3D12_GetExecutableDirectoryA(char* outPath, size_t outPathSize)
{
if (!outPath || outPathSize == 0)
return false;
DWORD len = GetModuleFileNameA(nullptr, outPath, (DWORD)outPathSize);
if (len == 0 || len >= outPathSize)
return false;
for (char* p = outPath + len; p > outPath; --p)
{
if (p[-1] == '\\' || p[-1] == '/')
{
p[-1] = '\0';
return true;
}
}
return false;
}
static bool QD3D12_GetExecutableDirectoryW(wchar_t* outPath, size_t outPathSize)
{
if (!outPath || outPathSize == 0)
return false;
DWORD len = GetModuleFileNameW(nullptr, outPath, (DWORD)outPathSize);
if (len == 0 || len >= outPathSize)
return false;
for (wchar_t* p = outPath + len; p > outPath; --p)
{
if (p[-1] == L'\\' || p[-1] == L'/')
{
p[-1] = L'\0';
return true;
}
}
return false;
}
static bool QD3D12_ExecutableDirectoryHasFile(const char* dir, const char* name)
{
if (!dir || !name)
return false;
char path[MAX_PATH];
snprintf(path, sizeof(path), "%s\\%s", dir, name);
return GetFileAttributesA(path) != INVALID_FILE_ATTRIBUTES;
}
static bool QD3D12_CheckStreamlineFrameGenerationRuntimeFiles()
{
char exeDir[MAX_PATH] = {};
if (!QD3D12_GetExecutableDirectoryA(exeDir, sizeof(exeDir)))
{
QD3D12_Log("DLSS_G runtime check failed: could not resolve executable directory.");
return false;
}
struct RequiredFile
{
const char* name;
bool requiredForFrameGeneration;
};
const RequiredFile files[] =
{
{ "sl.interposer.dll", true },
{ "sl.common.dll", true },
{ "sl.dlss.dll", true },
{ "sl.dlss_d.dll", true },
{ "sl.dlss_g.dll", true },
{ "sl.reflex.dll", true },
{ "sl.pcl.dll", false },
{ "nvngx_dlss.dll", true },
{ "nvngx_dlssd.dll", true },
{ "nvngx_dlssg.dll", true }
};
bool ok = true;
for (const RequiredFile& file : files)
{
const bool present = QD3D12_ExecutableDirectoryHasFile(exeDir, file.name);
if (!present && file.requiredForFrameGeneration)
{
QD3D12_Log("DLSS_G runtime missing %s beside the executable in %s.", file.name, exeDir);
ok = false;
}
}
if (!ok)
{
QD3D12_Log("DLSS_G cannot generate frames until the Streamline DLSS-G runtime DLLs are copied beside the game executable.");
}
return ok;
}
static void QD3D12_LoadStreamlineInterposer()
{
if (g_qd3d12SlInterposer.module)
@@ -6188,11 +6309,27 @@ static void QD3D12_InitStreamlineEarly()
pref.engine = sl::EngineType::eCustom;
pref.engineVersion = "IceBridge 1.0";
pref.flags |= sl::PreferenceFlags::eUseFrameBasedResourceTagging;
pref.flags |= sl::PreferenceFlags::eUseDXGIFactoryProxy;
pref.flags &= ~sl::PreferenceFlags::eAllowOTA;
pref.flags &= ~sl::PreferenceFlags::eLoadDownloadedPlugins;
static wchar_t pluginPath[MAX_PATH] = {};
static const wchar_t* pluginPaths[] = { pluginPath };
if (QD3D12_GetExecutableDirectoryW(pluginPath, _countof(pluginPath)))
{
pref.pathsToPlugins = pluginPaths;
pref.numPathsToPlugins = _countof(pluginPaths);
pref.pathToLogsAndData = pluginPath;
}
QD3D12_CheckStreamlineFrameGenerationRuntimeFiles();
sl::Feature features[] =
{
sl::kFeatureDLSS,
sl::kFeatureDLSS_RR
sl::kFeatureDLSS_RR,
sl::kFeatureDLSS_G,
sl::kFeatureReflex
};
pref.featuresToLoad = features;
@@ -6206,12 +6343,16 @@ static void QD3D12_InitStreamlineEarly()
}
g_qd3d12Sl.initialized = true;
g_qd3d12Sl.dlssGFeatureLoaded = true;
}
static void QD3D12_CheckStreamlineFeatureSupport()
{
g_qd3d12Sl.dlssSupported = false;
g_qd3d12Sl.dlssRrSupported = false;
g_qd3d12Sl.dlssGSupported = false;
g_qd3d12Sl.dlssGFeatureLoaded = false;
g_qd3d12Sl.reflexSupported = false;
if (!g_qd3d12Sl.initialized || !g_gl.device)
return;
@@ -6233,6 +6374,28 @@ static void QD3D12_CheckStreamlineFeatureSupport()
QD3D12_Log("slIsFeatureSupported(DLSS_RR) failed (%d); disabling Ray Reconstruction.", int(rrSupport));
g_gl.enableDLSSRayReconstruction = false;
}
const sl::Result fgSupport = slIsFeatureSupported(sl::kFeatureDLSS_G, adapterInfo);
g_qd3d12Sl.dlssGSupported = (fgSupport == sl::Result::eOk);
if (!g_qd3d12Sl.dlssGSupported)
{
QD3D12_Log("slIsFeatureSupported(DLSS_G) failed (%d); frame generation will stay off.", int(fgSupport));
}
bool dlssGLoaded = false;
const sl::Result fgLoadedResult = slIsFeatureLoaded(sl::kFeatureDLSS_G, dlssGLoaded);
g_qd3d12Sl.dlssGFeatureLoaded = (fgLoadedResult == sl::Result::eOk && dlssGLoaded);
if (!g_qd3d12Sl.dlssGFeatureLoaded)
{
QD3D12_Log("slIsFeatureLoaded(DLSS_G) failed or returned unloaded (result=%d loaded=%d).", int(fgLoadedResult), dlssGLoaded ? 1 : 0);
}
const sl::Result reflexSupport = slIsFeatureSupported(sl::kFeatureReflex, adapterInfo);
g_qd3d12Sl.reflexSupported = (reflexSupport == sl::Result::eOk);
if (!g_qd3d12Sl.reflexSupported)
{
QD3D12_Log("slIsFeatureSupported(Reflex) failed (%d); frame generation will stay off.", int(reflexSupport));
}
}
static void QD3D12_StreamlineOnDeviceCreated()
@@ -6276,6 +6439,9 @@ static bool QD3D12_UseLightingTextureAsUpscaleInput(const QD3D12Window& w)
static sl::Result QD3D12_SetStreamlineCommonConstants(sl::FrameToken& frameToken)
{
if (g_gl.streamlineConstantsSerial == g_gl.frameSerial)
return sl::Result::eOk;
sl::Constants consts{};
memcpy(&consts.cameraViewToClip, g_gl.cameraState.viewToClip.m, sizeof(float) * 16);
memcpy(&consts.clipToCameraView, g_gl.cameraState.clipToView.m, sizeof(float) * 16);
@@ -6283,6 +6449,7 @@ static sl::Result QD3D12_SetStreamlineCommonConstants(sl::FrameToken& frameToken
memcpy(&consts.prevClipToClip, g_gl.cameraState.prevClipToClip.m, sizeof(float) * 16);
consts.jitterOffset = { g_gl.jitterX, g_gl.jitterY };
consts.mvecScale = { 1.0f, 1.0f }; // motion vectors are written in PreviousUV - CurrentUV
consts.cameraPinholeOffset = { 0.0f, 0.0f };
memcpy(&consts.cameraPos, g_gl.cameraState.cameraPos, sizeof(float) * 3);
memcpy(&consts.cameraRight, g_gl.cameraState.cameraRight, sizeof(float) * 3);
memcpy(&consts.cameraUp, g_gl.cameraState.cameraUp, sizeof(float) * 3);
@@ -6297,7 +6464,295 @@ static sl::Result QD3D12_SetStreamlineCommonConstants(sl::FrameToken& frameToken
consts.motionVectors3D = sl::Boolean::eFalse;
consts.motionVectorsDilated = sl::Boolean::eFalse;
consts.motionVectorsJittered = sl::Boolean::eFalse;
return slSetConstants(consts, frameToken, g_qd3d12Sl.viewport);
const sl::Result result = slSetConstants(consts, frameToken, g_qd3d12Sl.viewport);
if (result == sl::Result::eOk)
g_gl.streamlineConstantsSerial = g_gl.frameSerial;
return result;
}
static sl::Result QD3D12_GetStreamlineFrameToken(sl::FrameToken*& frameToken)
{
if (g_gl.streamlineFrameToken &&
g_gl.streamlineFrameTokenSerial == g_gl.frameSerial)
{
frameToken = g_gl.streamlineFrameToken;
return sl::Result::eOk;
}
frameToken = nullptr;
uint32_t frameIndex = (uint32_t)g_gl.frameSerial;
const sl::Result result = slGetNewFrameToken(frameToken, &frameIndex);
if (result == sl::Result::eOk && frameToken)
{
g_gl.streamlineFrameToken = frameToken;
g_gl.streamlineFrameTokenSerial = g_gl.frameSerial;
g_gl.streamlineConstantsSerial = UINT64_MAX;
}
return result;
}
static bool QD3D12_WantsDLSSFrameGeneration(const QD3D12Window& w)
{
return
!w.isPbuffer &&
g_gl.cameraState.valid &&
g_qd3d12Sl.deviceBound &&
g_qd3d12Sl.dlssGSupported &&
g_qd3d12Sl.dlssGFeatureLoaded &&
g_qd3d12Sl.reflexSupported &&
g_gl.frameGenerationMultiplier >= 2 &&
w.backBuffers[w.frameIndex] &&
w.depthBuffer &&
w.velocityBuffers[w.frameIndex];
}
static uint32_t QD3D12_GetDLSSFrameGenerationEligibilityMask(const QD3D12Window& w)
{
uint32_t mask = 0;
if (w.isPbuffer)
mask |= 1u << 0;
if (!g_gl.cameraState.valid)
mask |= 1u << 1;
if (!g_qd3d12Sl.deviceBound)
mask |= 1u << 2;
if (!g_qd3d12Sl.dlssGSupported)
mask |= 1u << 3;
if (!g_qd3d12Sl.dlssGFeatureLoaded)
mask |= 1u << 4;
if (!g_qd3d12Sl.reflexSupported)
mask |= 1u << 5;
if (g_gl.frameGenerationMultiplier < 2)
mask |= 1u << 6;
if (!w.backBuffers[w.frameIndex] || !w.depthBuffer || !w.velocityBuffers[w.frameIndex])
mask |= 1u << 7;
return mask;
}
static void QD3D12_LogDLSSFrameGenerationEligibility(const QD3D12Window& w, uint32_t mask)
{
if (g_qd3d12Sl.lastDlssGEligibilityMaskLogged == mask)
return;
g_qd3d12Sl.lastDlssGEligibilityMaskLogged = mask;
if (mask == 0)
{
QD3D12_Log("DLSS_G eligible: requested %ux frame generation.", g_gl.frameGenerationMultiplier);
return;
}
QD3D12_Log(
"DLSS_G inactive: r_frameGen=%u, pbuffer=%d, camera=%d, deviceBound=%d, dlssG=%d, reflex=%d, resources=%d.",
g_gl.frameGenerationMultiplier,
w.isPbuffer ? 1 : 0,
g_gl.cameraState.valid ? 1 : 0,
g_qd3d12Sl.deviceBound ? 1 : 0,
(g_qd3d12Sl.dlssGSupported && g_qd3d12Sl.dlssGFeatureLoaded) ? 1 : 0,
g_qd3d12Sl.reflexSupported ? 1 : 0,
(w.backBuffers[w.frameIndex] && w.depthBuffer && w.velocityBuffers[w.frameIndex]) ? 1 : 0);
}
static void QD3D12_SetDLSSFrameGenerationOff()
{
if (!g_qd3d12Sl.deviceBound || !g_qd3d12Sl.dlssGSupported || !g_qd3d12Sl.dlssGActive)
return;
sl::DLSSGOptions options{};
options.mode = sl::DLSSGMode::eOff;
options.flags = sl::DLSSGFlags::eRetainResourcesWhenOff;
const sl::Result result = slDLSSGSetOptions(g_qd3d12Sl.viewport, options);
if (result != sl::Result::eOk)
QD3D12_Log("slDLSSGSetOptions(off) failed (%d).", int(result));
if (g_qd3d12Sl.reflexSupported)
{
sl::ReflexOptions reflexOptions{};
reflexOptions.mode = sl::ReflexMode::eOff;
slReflexSetOptions(reflexOptions);
}
g_qd3d12Sl.dlssGActive = false;
}
static void QD3D12_SetDLSSGFeatureLoaded(bool loaded)
{
if (!g_qd3d12Sl.initialized || g_qd3d12Sl.dlssGFeatureLoaded == loaded)
return;
const sl::Result result = slSetFeatureLoaded(sl::kFeatureDLSS_G, loaded);
if (result != sl::Result::eOk)
{
QD3D12_Log("slSetFeatureLoaded(DLSS_G, %d) failed (%d).", loaded ? 1 : 0, int(result));
return;
}
g_qd3d12Sl.dlssGFeatureLoaded = loaded;
QD3D12_Log("DLSS_G feature %s for swap-chain recreation.", loaded ? "loaded" : "unloaded");
}
static void QD3D12_TagDLSSFrameGenerationInputs(
QD3D12Window& w,
sl::FrameToken& frameToken,
const sl::Extent& renderExtent,
const sl::Extent& outputExtent)
{
ID3D12GraphicsCommandList* cl = g_gl.cmdList.Get();
if (!cl)
return;
sl::Resource hudless = { sl::ResourceType::eTex2d, w.backBuffers[w.frameIndex].Get(), nullptr, nullptr, uint32_t(w.backBufferState[w.frameIndex]) };
sl::Resource depth = { sl::ResourceType::eTex2d, w.depthBuffer.Get(), nullptr, nullptr, uint32_t(D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE) };
sl::Resource mvec = { sl::ResourceType::eTex2d, w.velocityBuffers[w.frameIndex].Get(), nullptr, nullptr, uint32_t(D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE) };
sl::ResourceTag tags[] =
{
sl::ResourceTag{ &hudless, sl::kBufferTypeHUDLessColor, sl::ResourceLifecycle::eValidUntilPresent, &outputExtent },
sl::ResourceTag{ &depth, sl::kBufferTypeDepth, sl::ResourceLifecycle::eValidUntilPresent, &renderExtent },
sl::ResourceTag{ &mvec, sl::kBufferTypeMotionVectors, sl::ResourceLifecycle::eValidUntilPresent, &renderExtent }
};
slSetTagForFrame(frameToken, g_qd3d12Sl.viewport, tags, _countof(tags), cl);
}
static void QD3D12_ConfigureDLSSFrameGeneration(QD3D12Window& w, sl::FrameToken* existingFrameToken)
{
const uint32_t eligibilityMask = QD3D12_GetDLSSFrameGenerationEligibilityMask(w);
if (g_gl.frameGenerationMultiplier >= 2 && !w.isPbuffer)
QD3D12_LogDLSSFrameGenerationEligibility(w, eligibilityMask);
if (eligibilityMask != 0 || !QD3D12_WantsDLSSFrameGeneration(w))
{
QD3D12_SetDLSSFrameGenerationOff();
return;
}
sl::FrameToken* frameToken = existingFrameToken;
if (!frameToken)
{
const sl::Result frameResult = QD3D12_GetStreamlineFrameToken(frameToken);
if (frameResult != sl::Result::eOk || !frameToken)
{
QD3D12_Log("slGetNewFrameToken for DLSS_G failed (%d), disabling frame generation for this frame.", int(frameResult));
QD3D12_SetDLSSFrameGenerationOff();
return;
}
}
const sl::Result constResult = QD3D12_SetStreamlineCommonConstants(*frameToken);
if (constResult != sl::Result::eOk)
{
QD3D12_Log("slSetConstants for DLSS_G failed (%d), disabling frame generation for this frame.", int(constResult));
QD3D12_SetDLSSFrameGenerationOff();
return;
}
sl::ReflexOptions reflexOptions{};
reflexOptions.mode = sl::ReflexMode::eLowLatencyWithBoost;
const sl::Result reflexOptionsResult = slReflexSetOptions(reflexOptions);
if (reflexOptionsResult != sl::Result::eOk)
{
QD3D12_Log("slReflexSetOptions failed (%d), disabling frame generation for this frame.", int(reflexOptionsResult));
QD3D12_SetDLSSFrameGenerationOff();
return;
}
const sl::Result reflexSleepResult = slReflexSleep(*frameToken);
if (reflexSleepResult != sl::Result::eOk)
{
QD3D12_Log("slReflexSleep failed (%d), continuing with frame generation setup.", int(reflexSleepResult));
}
sl::Extent renderExtent{};
renderExtent.left = 0;
renderExtent.top = 0;
renderExtent.width = w.renderWidth;
renderExtent.height = w.renderHeight;
sl::Extent outputExtent{};
outputExtent.left = 0;
outputExtent.top = 0;
outputExtent.width = w.width;
outputExtent.height = w.height;
sl::DLSSGOptions options{};
options.mode = sl::DLSSGMode::eOn;
options.numFramesToGenerate = ClampValue<uint32_t>(g_gl.frameGenerationMultiplier - 1, 1, 3);
options.flags = sl::DLSSGFlags::eRetainResourcesWhenOff;
options.numBackBuffers = QD3D12_FrameCount;
options.mvecDepthWidth = w.renderWidth;
options.mvecDepthHeight = w.renderHeight;
options.colorWidth = w.width;
options.colorHeight = w.height;
options.colorBufferFormat = uint32_t(DXGI_FORMAT_R8G8B8A8_UNORM);
options.mvecBufferFormat = uint32_t(QD3D12_VelocityFormat);
options.depthBufferFormat = uint32_t(QD3D12_DepthSrvFormat);
options.hudLessBufferFormat = uint32_t(DXGI_FORMAT_R8G8B8A8_UNORM);
options.uiBufferFormat = uint32_t(DXGI_FORMAT_R8G8B8A8_UNORM);
sl::DLSSGState state{};
const sl::Result stateResult = slDLSSGGetState(g_qd3d12Sl.viewport, state, &options);
if (stateResult == sl::Result::eOk)
{
if (state.numFramesToGenerateMax > 0)
options.numFramesToGenerate = min(options.numFramesToGenerate, state.numFramesToGenerateMax);
if (state.status != sl::DLSSGStatus::eOk)
{
const uint32_t statusBits = uint32_t(state.status);
if (g_qd3d12Sl.lastDlssGStatusLogged != statusBits)
{
QD3D12_Log("DLSS_G reported status 0x%08x; leaving frame generation off for this frame.", statusBits);
g_qd3d12Sl.lastDlssGStatusLogged = statusBits;
}
QD3D12_SetDLSSFrameGenerationOff();
return;
}
g_qd3d12Sl.lastDlssGStatusLogged = 0;
}
else
{
QD3D12_Log("slDLSSGGetState failed (%d), trying DLSS_G set-options path anyway.", int(stateResult));
}
QD3D12_TagDLSSFrameGenerationInputs(w, *frameToken, renderExtent, outputExtent);
const sl::Result setResult = slDLSSGSetOptions(g_qd3d12Sl.viewport, options);
if (setResult != sl::Result::eOk)
{
QD3D12_Log("slDLSSGSetOptions(on) failed (%d).", int(setResult));
QD3D12_SetDLSSFrameGenerationOff();
return;
}
if (!g_qd3d12Sl.dlssGActive || g_qd3d12Sl.lastDlssGFramesToGenerateLogged != options.numFramesToGenerate)
{
QD3D12_Log(
"DLSS_G active: requested %ux, generating %u frame(s) between rendered frames.",
g_gl.frameGenerationMultiplier,
options.numFramesToGenerate);
g_qd3d12Sl.lastDlssGFramesToGenerateLogged = options.numFramesToGenerate;
}
g_qd3d12Sl.dlssGActive = true;
}
static void QD3D12_LogDLSSFrameGenerationPresentResult()
{
if (!g_qd3d12Sl.deviceBound || !g_qd3d12Sl.dlssGSupported || !g_qd3d12Sl.dlssGActive)
return;
sl::DLSSGState state{};
const sl::Result stateResult = slDLSSGGetState(g_qd3d12Sl.viewport, state, nullptr);
if (stateResult != sl::Result::eOk)
return;
if (state.numFramesActuallyPresented != g_qd3d12Sl.lastDlssGPresentedFramesLogged)
{
QD3D12_Log(
"DLSS_G present: Streamline presented %u frame(s) since last check.",
state.numFramesActuallyPresented);
g_qd3d12Sl.lastDlssGPresentedFramesLogged = state.numFramesActuallyPresented;
}
}
#else
static HRESULT QD3D12_CreateDXGIFactory1ForStreamline(REFIID riid, void** ppFactory)
@@ -6315,6 +6770,8 @@ static void QD3D12_StreamlineOnDeviceCreated() {}
static bool QD3D12_WantsDLSSRayReconstruction() { return false; }
static bool QD3D12_CanUseDLSSRayReconstructionForLighting(const QD3D12Window&) { return false; }
static bool QD3D12_UseLightingTextureAsUpscaleInput(const QD3D12Window&) { return false; }
static void QD3D12_ConfigureDLSSFrameGeneration(QD3D12Window&, void*) {}
static void QD3D12_LogDLSSFrameGenerationPresentResult() {}
#endif
#if defined(QD3D12_ENABLE_FFX)
@@ -6948,8 +7405,7 @@ static void QD3D12_RunUpscalerOrBlit(QD3D12Window& w)
if (haveTemporalCameraInputs && useLightingUpscaleInput && g_gl.upscalerBackend == QD3D12_UPSCALER_DLSS && g_qd3d12Sl.deviceBound && w.slOutputBuffers[w.frameIndex])
{
sl::FrameToken* frameToken = nullptr;
uint32_t frameIndex = (uint32_t)g_gl.frameSerial;
const sl::Result frameResult = slGetNewFrameToken(frameToken, &frameIndex);
const sl::Result frameResult = QD3D12_GetStreamlineFrameToken(frameToken);
if (frameResult == sl::Result::eOk && frameToken)
{
sl::Extent renderExtent{};
@@ -7060,8 +7516,7 @@ static void QD3D12_RunUpscalerOrBlit(QD3D12Window& w)
if (haveTemporalCameraInputs && g_gl.upscalerBackend == QD3D12_UPSCALER_DLSS && g_qd3d12Sl.deviceBound && w.slOutputBuffers[w.frameIndex])
{
sl::FrameToken* frameToken = nullptr;
uint32_t frameIndex = (uint32_t)g_gl.frameSerial;
const sl::Result frameResult = slGetNewFrameToken(frameToken, &frameIndex);
const sl::Result frameResult = QD3D12_GetStreamlineFrameToken(frameToken);
if (frameResult == sl::Result::eOk && frameToken)
{
sl::Extent renderExtent{};
@@ -7252,13 +7707,12 @@ static void QD3D12_CreateDevice()
QD3D12_CHECK(QD3D12_CreateDXGIFactory1ForStreamline(IID_PPV_ARGS(&g_gl.factory)));
QD3D12_CHECK(QD3D12_D3D12CreateDeviceForStreamline(nullptr, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&g_gl.device)));
QD3D12_StreamlineOnDeviceCreated();
QD3D12_SelectGBufferSampleCount();
D3D12_COMMAND_QUEUE_DESC qd{};
qd.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
QD3D12_CHECK(g_gl.device->CreateCommandQueue(&qd, IID_PPV_ARGS(&g_gl.queue)));
QD3D12_StreamlineOnDeviceCreated();
}
static void QD3D12_CreateSwapChainForWindow(QD3D12Window& w)
@@ -7273,15 +7727,17 @@ static void QD3D12_CreateSwapChainForWindow(QD3D12Window& w)
sd.SampleDesc.Count = 1;
sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
ComPtr<IDXGISwapChain1> sc1;
IDXGISwapChain1* rawSwapChain = nullptr;
QD3D12_CHECK(g_gl.factory->CreateSwapChainForHwnd(
g_gl.queue.Get(),
w.hwnd,
&sd,
nullptr,
nullptr,
&sc1));
&rawSwapChain));
ComPtr<IDXGISwapChain1> sc1;
sc1.Attach(rawSwapChain);
QD3D12_CHECK(sc1.As(&w.swapChain));
w.frameIndex = w.swapChain->GetCurrentBackBufferIndex();
}
@@ -8970,6 +9426,9 @@ void QD3D12_EndFrame()
QD3D12_ProcessCompletedTextureMipJobs(2);
QD3D12_TransitionResource(g_gl.cmdList.Get(), w.backBuffers[w.frameIndex].Get(), w.backBufferState[w.frameIndex], D3D12_RESOURCE_STATE_PRESENT);
#if defined(QD3D12_ENABLE_STREAMLINE)
QD3D12_ConfigureDLSSFrameGeneration(w, nullptr);
#endif
QD3D12_CHECK(g_gl.cmdList->Close());
ID3D12CommandList* lists[] = { g_gl.cmdList.Get() };
@@ -8993,7 +9452,12 @@ void QD3D12_Present()
QD3D12Window& w = *g_currentWindow;
if (w.swapChain)
{
QD3D12_CHECK(w.swapChain->Present(0, DXGI_PRESENT_ALLOW_TEARING));
#if defined(QD3D12_ENABLE_STREAMLINE)
QD3D12_LogDLSSFrameGenerationPresentResult();
#endif
}
FrameResources& fr = w.frames[w.frameIndex];
const UINT64 signalValue = g_gl.nextFenceValue++;
@@ -13298,6 +13762,66 @@ static void QD3D12_ReconfigureCurrentWindowForUpscalerChange()
QD3D12_UpdateViewportState();
}
static void QD3D12_RecreateCurrentWindowSwapChainForFrameGenerationChange(bool enableFrameGeneration)
{
if (!g_currentWindow || !g_currentWindow->swapChain || !g_gl.device)
return;
const UINT width = g_currentWindow->width;
const UINT height = g_currentWindow->height;
if (width == 0 || height == 0)
return;
if (g_gl.frameOpen || !g_gl.queuedBatches.empty())
QD3D12_SubmitOpenFrameNoPresentAndWait();
QD3D12_WaitForGPU();
g_gl.queuedBatches.clear();
#if defined(QD3D12_ENABLE_STREAMLINE)
if (!enableFrameGeneration)
QD3D12_SetDLSSFrameGenerationOff();
#endif
#if defined(QD3D12_ENABLE_FFX)
QD3D12_DestroyFfxUpscaleContext();
#endif
QD3D12_ReleaseWindowSizeResources(*g_currentWindow);
g_currentWindow->swapChain.Reset();
#if defined(QD3D12_ENABLE_STREAMLINE)
QD3D12_SetDLSSGFeatureLoaded(enableFrameGeneration);
#endif
QD3D12_CreateSwapChainForWindow(*g_currentWindow);
QD3D12_SelectRenderResolution(*g_currentWindow, width, height);
g_currentWindow->frameIndex = g_currentWindow->swapChain->GetCurrentBackBufferIndex();
g_gl.viewportW = (GLsizei)width;
g_gl.viewportH = (GLsizei)height;
g_gl.motionHistoryReset = true;
QD3D12_CreateRTVsForWindow(*g_currentWindow);
QD3D12_CreateDSVForWindow(*g_currentWindow);
g_psoCache.clear();
g_arbPsoCache.clear();
g_gl.framePhase = QD3D12_FRAME_LOW_RES;
g_gl.sceneResolvedThisFrame = false;
g_gl.gbufferResolvedThisFrame = false;
g_gl.raytracedLightingReadyThisFrame = false;
g_gl.sceneFogValidThisFrame = false;
#if defined(QD3D12_ENABLE_STREAMLINE)
g_gl.streamlineFrameToken = nullptr;
g_gl.streamlineFrameTokenSerial = UINT64_MAX;
g_gl.streamlineConstantsSerial = UINT64_MAX;
#endif
QD3D12_UpdateViewportState();
QD3D12_Log("DLSS_G swap-chain recreated with frame generation %s.", enableFrameGeneration ? "enabled" : "disabled");
}
GLenum APIENTRY glGetError(void) {
GLenum e = g_gl.lastError;
if (e != GL_NO_ERROR)
@@ -14745,6 +15269,8 @@ PROC WINAPI qd3d12_wglGetProcAddress(LPCSTR name) {
{ "QD3D12_SetUpscalerSharpness", (PROC)QD3D12_SetUpscalerSharpness },
{ "QD3D12_SetToneMapBrightness", (PROC)QD3D12_SetToneMapBrightness },
{ "QD3D12_GetToneMapBrightness", (PROC)QD3D12_GetToneMapBrightness },
{ "QD3D12_SetFrameGenerationMultiplier", (PROC)QD3D12_SetFrameGenerationMultiplier },
{ "QD3D12_GetFrameGenerationMultiplier", (PROC)QD3D12_GetFrameGenerationMultiplier },
{ "glToneMapBrightnessQD3D12", (PROC)glToneMapBrightnessQD3D12 },
{ "glToneMapBrightnessfQD3D12", (PROC)glToneMapBrightnessfQD3D12 },
{ "glTonemapBrightnessQD3D12", (PROC)glTonemapBrightnessQD3D12 },
@@ -15665,6 +16191,26 @@ void QD3D12_SetUpscalerQuality(int quality)
QD3D12_ReconfigureCurrentWindowForUpscalerChange();
}
void QD3D12_SetFrameGenerationMultiplier(int multiplier)
{
const uint32_t clamped = (uint32_t)ClampValue<int>(multiplier, 0, 4);
const bool wasEnabled = g_gl.frameGenerationMultiplier >= 2;
const bool willBeEnabled = clamped >= 2;
if (g_gl.frameGenerationMultiplier == clamped)
return;
g_gl.frameGenerationMultiplier = clamped;
g_gl.motionHistoryReset = true;
if (wasEnabled != willBeEnabled)
QD3D12_RecreateCurrentWindowSwapChainForFrameGenerationChange(willBeEnabled);
}
int QD3D12_GetFrameGenerationMultiplier(void)
{
return (int)g_gl.frameGenerationMultiplier;
}
void QD3D12_EnableDLAA(int enabled)
{
const QD3D12UpscalerBackend oldBackend = g_gl.upscalerBackend;
+3 -1
View File
@@ -2326,7 +2326,9 @@ void APIENTRY glShowAllTopLevelAccelStructures(
void QD3D12_SetUpscalerSharpness(float sharpness);
void QD3D12_SetToneMapBrightness(float brightness);
void QD3D12_SetFrameGenerationMultiplier(int multiplier);
int QD3D12_GetFrameGenerationMultiplier(void);
void QD3D12_EnableTAA(int enabled);
#include "opengl_nn.h"
#include "opengl_nn.h"