From 1f5f0733fe1538cf249789168197570491b48f59 Mon Sep 17 00:00:00 2001 From: Justin Marshall Date: Thu, 21 May 2026 17:43:28 -0700 Subject: [PATCH] Framegen now works and increase light bounce to 3. --- e3/maps/e3/e3_1.map | 1 + neo/engine/doomdll.vcxproj.user | 4 +- neo/engine/framework/Console.cpp | 26 +- neo/engine/opengl/gl_d3d12raylight.cpp | 58 +++-- neo/engine/opengl/gl_d3d12shim.cpp | 314 +++++++++++++++++-------- 5 files changed, 277 insertions(+), 126 deletions(-) diff --git a/e3/maps/e3/e3_1.map b/e3/maps/e3/e3_1.map index 6239f657..2bdb88fc 100644 --- a/e3/maps/e3/e3_1.map +++ b/e3/maps/e3/e3_1.map @@ -17771,6 +17771,7 @@ Version 2 "light_target" "0 0 -434" "light_up" "8 -348 0" "light_right" "-272 6 0" +"vls" "1" } // entity 89 { diff --git a/neo/engine/doomdll.vcxproj.user b/neo/engine/doomdll.vcxproj.user index e4f905db..b9fcfa12 100644 --- a/neo/engine/doomdll.vcxproj.user +++ b/neo/engine/doomdll.vcxproj.user @@ -15,9 +15,9 @@ D:\projects\Doom3\Doom3.exe WindowsLocalDebugger - +set r_fullscreen 0 +set r_mode 9 +set sv_pure 0 +set fs_game e3 + +set r_fullscreen 0 +set r_mode 9 +set sv_pure 0 D:\projects\Doom3 - +set r_fullscreen 0 +set r_mode 9|+set r_fullscreen 1 +set r_mode 9 +set sv_pure 0 +set fs_game e3|+set r_fullscreen 0 +set r_mode 9 +set sv_pure 0 |+set r_fullscreen 0 +set r_mode 9 +set sv_pure 0|+set r_fullscreen 0 +set r_mode 9 +set sv_pure 0 +set fs_game e3| + +set r_fullscreen 0 +set r_mode 9|+set r_fullscreen 1 +set r_mode 9 +set sv_pure 0 +set fs_game e3|+set r_fullscreen 0 +set r_mode 9 +set sv_pure 0|+set r_fullscreen 0 +set r_mode 9 +set sv_pure 0 +set fs_game e3|+set r_fullscreen 0 +set r_mode 9 +set sv_pure 0 | D:\projects\Doom3\Quake4.exe diff --git a/neo/engine/framework/Console.cpp b/neo/engine/framework/Console.cpp index c20805a7..2e698299 100644 --- a/neo/engine/framework/Console.cpp +++ b/neo/engine/framework/Console.cpp @@ -178,6 +178,16 @@ SCR_DrawFPS ================== */ #define FPS_FRAMES 4 +static const idVec4 &SCR_FrameTimeColor( int msec ) { + if ( msec < 16 ) { + return colorGreen; + } + if ( msec < 30 ) { + return colorYellow; + } + return colorRed; +} + float SCR_DrawFPS( float y ) { char *s; int w; @@ -208,15 +218,25 @@ float SCR_DrawFPS( float y ) { fps = 10000 * FPS_FRAMES / total; fps = (fps + 5)/10; - s = va( "%ifps", fps ); + const int averageFrameTime = ( total + ( FPS_FRAMES / 2 ) ) / FPS_FRAMES; + const int frameGenMultiplier = idMath::ClampInt( 1, 4, cvarSystem->GetCVarInteger( "r_frameGen" ) ); + const int displayFps = fps * frameGenMultiplier; + const int displayFrameTime = ( averageFrameTime + ( frameGenMultiplier / 2 ) ) / frameGenMultiplier; + const idVec4 &frameColor = SCR_FrameTimeColor( displayFrameTime ); + + if ( frameGenMultiplier >= 2 ) { + s = va( "%ifps %dms est (%ir %dms)", displayFps, displayFrameTime, fps, averageFrameTime ); + } else { + s = va( "%ifps %dms", fps, averageFrameTime ); + } w = strlen( s ) * BIGCHAR_WIDTH; - renderSystem->DrawBigStringExt( (SCREEN_WIDTH - 5.0f) - w, idMath::FtoiFast(y) + 2, s, colorWhite, true, localConsole.charSetShader); + renderSystem->DrawBigStringExt( (SCREEN_WIDTH - 5.0f) - w, idMath::FtoiFast(y) + 2, s, frameColor, true, localConsole.charSetShader); y += BIGCHAR_HEIGHT + 4; s = va( "game cpu:%4.1fms render cpu:%4.1fms pt gpu:%4.1fms", com_lastGameFrameMsec, com_lastRenderFrameMsec, com_pathTracingGpuMsec ); w = strlen( s ) * SMALLCHAR_WIDTH; - renderSystem->DrawSmallStringExt( (SCREEN_WIDTH - 5.0f) - w, idMath::FtoiFast(y) + 2, s, colorWhite, true, localConsole.charSetShader); + renderSystem->DrawSmallStringExt( (SCREEN_WIDTH - 5.0f) - w, idMath::FtoiFast(y) + 2, s, frameColor, true, localConsole.charSetShader); return y + SMALLCHAR_HEIGHT + 4; } diff --git a/neo/engine/opengl/gl_d3d12raylight.cpp b/neo/engine/opengl/gl_d3d12raylight.cpp index 5b629e1e..703ac935 100644 --- a/neo/engine/opengl/gl_d3d12raylight.cpp +++ b/neo/engine/opengl/gl_d3d12raylight.cpp @@ -2434,11 +2434,12 @@ struct glRaytracingLightingState_t ComPtr denoisePSO; ComPtr temporalPSO; - glRaytracingTexture_t pathTraceTexture; + glRaytracingTexture_t pathTraceTexture[2]; glRaytracingTexture_t temporalTexture; glRaytracingTexture_t historyTexture[2]; glRaytracingTexture_t denoiseTemp[2]; uint32_t currentHistoryIndex; + uint32_t currentPathTraceIndex; glRaytracingBuffer_t denoiseConstantBuffer[3]; glRaytracingBuffer_t denoiseConstantBufferRing[GL_RAYTRACING_CMD_RING_SIZE][3]; void* denoiseConstantBufferMapped[3]; @@ -2474,6 +2475,7 @@ struct glRaytracingLightingState_t denoiseHeight = 0; denoiseFormat = DXGI_FORMAT_UNKNOWN; currentHistoryIndex = 0; + currentPathTraceIndex = 0; frameCounter = 0; externalDenoiser = false; emissiveTexture = nullptr; @@ -4707,7 +4709,7 @@ float3 PathTraceDeterministicLighting( float3 skyColorRGB = float3(0.98, 0.55, 0.35); float3 skyColor = skyColorRGB * (0.35 + 0.65 * upness); - float3 lightingAccum = gAmbientColor.rgb * (gAmbientColor.a * 0.04); + float3 lightingAccum = float3(0, 0, 0); // gAmbientColor.rgb * (gAmbientColor.a * 0.04); lightingAccum += skyColor * (0.42 * skyVis); lightingAccum += ambientSkyVis * (skyColorRGB * 0.12); @@ -6243,7 +6245,8 @@ static int glRaytracingLightingEnsureDenoiseResources(UINT width, UINT height) if (width == 0 || height == 0) return 0; - if (g_glRaytracingLighting.pathTraceTexture.resource && + if (g_glRaytracingLighting.pathTraceTexture[0].resource && + g_glRaytracingLighting.pathTraceTexture[1].resource && g_glRaytracingLighting.temporalTexture.resource && g_glRaytracingLighting.historyTexture[0].resource && g_glRaytracingLighting.historyTexture[1].resource && @@ -6256,7 +6259,8 @@ static int glRaytracingLightingEnsureDenoiseResources(UINT width, UINT height) return 1; } - if (g_glRaytracingLighting.pathTraceTexture.resource || + if (g_glRaytracingLighting.pathTraceTexture[0].resource || + g_glRaytracingLighting.pathTraceTexture[1].resource || g_glRaytracingLighting.temporalTexture.resource || g_glRaytracingLighting.historyTexture[0].resource || g_glRaytracingLighting.historyTexture[1].resource || @@ -6266,20 +6270,24 @@ static int glRaytracingLightingEnsureDenoiseResources(UINT width, UINT height) glRaytracingWaitIdle(); } - g_glRaytracingLighting.pathTraceTexture = glRaytracingTexture_t(); + g_glRaytracingLighting.pathTraceTexture[0] = glRaytracingTexture_t(); + g_glRaytracingLighting.pathTraceTexture[1] = glRaytracingTexture_t(); g_glRaytracingLighting.temporalTexture = glRaytracingTexture_t(); g_glRaytracingLighting.historyTexture[0] = glRaytracingTexture_t(); g_glRaytracingLighting.historyTexture[1] = glRaytracingTexture_t(); g_glRaytracingLighting.denoiseTemp[0] = glRaytracingTexture_t(); g_glRaytracingLighting.denoiseTemp[1] = glRaytracingTexture_t(); - g_glRaytracingLighting.pathTraceTexture = glRaytracingCreateTexture2D( - g_glRaytracingCmd.device.Get(), - width, - height, - GL_RAYTRACING_DENOISE_FORMAT, - D3D12_RESOURCE_STATE_UNORDERED_ACCESS, - D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS); + for (int i = 0; i < 2; ++i) + { + g_glRaytracingLighting.pathTraceTexture[i] = glRaytracingCreateTexture2D( + g_glRaytracingCmd.device.Get(), + width, + height, + GL_RAYTRACING_DENOISE_FORMAT, + D3D12_RESOURCE_STATE_UNORDERED_ACCESS, + D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS); + } g_glRaytracingLighting.temporalTexture = glRaytracingCreateTexture2D( g_glRaytracingCmd.device.Get(), @@ -6311,7 +6319,8 @@ static int glRaytracingLightingEnsureDenoiseResources(UINT width, UINT height) D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS); } - if (!g_glRaytracingLighting.pathTraceTexture.resource || + if (!g_glRaytracingLighting.pathTraceTexture[0].resource || + !g_glRaytracingLighting.pathTraceTexture[1].resource || !g_glRaytracingLighting.temporalTexture.resource || !g_glRaytracingLighting.historyTexture[0].resource || !g_glRaytracingLighting.historyTexture[1].resource || @@ -6322,6 +6331,7 @@ static int glRaytracingLightingEnsureDenoiseResources(UINT width, UINT height) } g_glRaytracingLighting.currentHistoryIndex = 0; + g_glRaytracingLighting.currentPathTraceIndex = 0; g_glRaytracingLighting.denoiseWidth = width; g_glRaytracingLighting.denoiseHeight = height; g_glRaytracingLighting.denoiseFormat = GL_RAYTRACING_DENOISE_FORMAT; @@ -6486,7 +6496,7 @@ static bool glRaytracingLightingExecuteInternal( !g_glRaytracingLighting.externalDenoiser; ID3D12Resource* rayOutputTexture = useInternalDenoiser - ? g_glRaytracingLighting.pathTraceTexture.resource.Get() + ? g_glRaytracingLighting.pathTraceTexture[g_glRaytracingLighting.currentPathTraceIndex & 1u].resource.Get() : pass->outputTexture; if (!glRaytracingBeginCmd()) @@ -6517,12 +6527,14 @@ static bool glRaytracingLightingExecuteInternal( const uint32_t historyReadIndex = g_glRaytracingLighting.currentHistoryIndex & 1u; const uint32_t historyWriteIndex = (g_glRaytracingLighting.currentHistoryIndex ^ 1u) & 1u; + const uint32_t pathTraceIndex = g_glRaytracingLighting.currentPathTraceIndex & 1u; + glRaytracingTexture_t& pathTraceTexture = g_glRaytracingLighting.pathTraceTexture[pathTraceIndex]; glRaytracingLightingCreatePerPassDescriptors( pass, topLevelAS, rayOutputTexture, - g_glRaytracingLighting.pathTraceTexture.resource.Get(), + pathTraceTexture.resource.Get(), g_glRaytracingLighting.denoiseTemp[0].resource.Get(), g_glRaytracingLighting.denoiseTemp[1].resource.Get(), g_glRaytracingLighting.historyTexture[historyReadIndex].resource.Get(), @@ -6532,10 +6544,10 @@ static bool glRaytracingLightingExecuteInternal( if (useInternalDenoiser) { glRaytracingTransition(g_glRaytracingCmd.cmdList.Get(), - g_glRaytracingLighting.pathTraceTexture.resource.Get(), - g_glRaytracingLighting.pathTraceTexture.state, + pathTraceTexture.resource.Get(), + pathTraceTexture.state, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); - g_glRaytracingLighting.pathTraceTexture.state = D3D12_RESOURCE_STATE_UNORDERED_ACCESS; + pathTraceTexture.state = D3D12_RESOURCE_STATE_UNORDERED_ACCESS; } else { @@ -6598,10 +6610,10 @@ static bool glRaytracingLightingExecuteInternal( const UINT groupsY = (pass->height + 7u) / 8u; glRaytracingTransition(g_glRaytracingCmd.cmdList.Get(), - g_glRaytracingLighting.pathTraceTexture.resource.Get(), - g_glRaytracingLighting.pathTraceTexture.state, + pathTraceTexture.resource.Get(), + pathTraceTexture.state, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); - g_glRaytracingLighting.pathTraceTexture.state = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; + pathTraceTexture.state = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; glRaytracingTransition(g_glRaytracingCmd.cmdList.Get(), g_glRaytracingLighting.temporalTexture.resource.Get(), @@ -6737,7 +6749,10 @@ static bool glRaytracingLightingExecuteInternal( g_glRaytracingCmd.pathTracingTimestampFenceRing[g_glRaytracingCmd.cmdCurrentSlot] = g_glRaytracingCmd.cmdLastFenceValue; if (useInternalDenoiser) + { g_glRaytracingLighting.currentHistoryIndex = historyWriteIndex; + g_glRaytracingLighting.currentPathTraceIndex = (pathTraceIndex ^ 1u); + } ++g_glRaytracingLighting.frameCounter; return true; @@ -6795,6 +6810,7 @@ bool glRaytracingLightingInit(void) return false; memset(&g_glRaytracingLighting.constants, 0, sizeof(g_glRaytracingLighting.constants)); + g_glRaytracingLighting.cpuLights.reserve(GL_RAYTRACING_MAX_LIGHTS); glRaytracingSetIdentity4x4(g_glRaytracingLighting.constants.invViewProj); glRaytracingSetIdentity4x4(g_glRaytracingLighting.constants.invViewMatrix); glRaytracingSetIdentity4x4(g_glRaytracingLighting.constants.viewProj); diff --git a/neo/engine/opengl/gl_d3d12shim.cpp b/neo/engine/opengl/gl_d3d12shim.cpp index b3669ece..a3fd56f9 100644 --- a/neo/engine/opengl/gl_d3d12shim.cpp +++ b/neo/engine/opengl/gl_d3d12shim.cpp @@ -373,6 +373,7 @@ static void QD3D12_SubmitOpenFrameNoPresentAndWait(); static void QD3D12_EnsureFrameOpen(); static void QD3D12_RunUpscalerOrBlit(QD3D12Window& w); static void QD3D12_ExecuteMainCommandListAndWait(QD3D12Window& w); +static void QD3D12_ExecuteMainCommandListForRaytracingHandoff(QD3D12Window& w); static bool QD3D12_RunInternalTAA(QD3D12Window& w, D3D12_GPU_DESCRIPTOR_HANDLE inputSrv, D3D12_GPU_DESCRIPTOR_HANDLE& outputSrv); static bool QD3D12_FinalBlitToBackBuffer(QD3D12Window& w, D3D12_GPU_DESCRIPTOR_HANDLE inputSrv, const D3D12_VIEWPORT& outputViewport, const D3D12_RECT& outputScissor, bool toneMapInput = false); static void QD3D12_RunRayAIDenoiseIfEnabled(ID3D12GraphicsCommandList* cl, QD3D12Window& w, ID3D12Resource* lightingResource); @@ -1483,6 +1484,10 @@ struct GLState GLenum depthFunc = GL_LEQUAL; UINT64 nextFenceValue = 1; + ComPtr raytraceContinuationAlloc[QD3D12_FrameCount]; + UINT64 raytraceContinuationFence[QD3D12_FrameCount] = {}; + UINT raytraceContinuationIndex = 0; + int activeRaytraceContinuationSlot = -1; GLuint currentMotionObjectId = 0; float currentSurfaceRoughness = 0.5f; @@ -1500,14 +1505,14 @@ struct GLState QD3D12UpscalerBackend upscalerBackend = QD3D12_UPSCALER_DLSS; QD3D12UpscalerQuality upscalerQuality = QD3D12_QUALITY_DLAA; - bool enableInternalTAA = true; + bool enableInternalTAA = false; bool enableRayAIDenoise = false; - bool enableDLSSRayReconstruction = true; + bool enableDLSSRayReconstruction = false; bool enableFSRRayRegeneration = false; uint32_t frameGenerationMultiplier = 2; uint32_t pathTracingSamplesPerPixel = 1; uint32_t pathTracingFallbackSamplesPerPixel = 2; - uint32_t pathTracingMaxBounces = 2; + uint32_t pathTracingMaxBounces = 3; float jitterX = 0.0f; float jitterY = 0.0f; @@ -2250,9 +2255,17 @@ void QD3D12_SetCurrentWindow(struct QD3D12Window* window) { g_qd3d12CurrentDC = window->hdc; } -static GLuint g_lightingTextureId = 0; -static TextureResource* g_lightingTexture = nullptr; -static D3D12_RESOURCE_STATES g_lightingTextureState = D3D12_RESOURCE_STATE_COMMON; +static constexpr UINT QD3D12_LightingTextureCount = 2; +static GLuint g_lightingTextureId[QD3D12_LightingTextureCount] = {}; +static TextureResource* g_lightingTexture[QD3D12_LightingTextureCount] = {}; +static D3D12_RESOURCE_STATES g_lightingTextureState[QD3D12_LightingTextureCount] = +{ + D3D12_RESOURCE_STATE_COMMON, + D3D12_RESOURCE_STATE_COMMON +}; +static bool g_lightingTextureValid[QD3D12_LightingTextureCount] = {}; +static UINT g_lightingReadIndex = 0; +static UINT g_lightingWriteIndex = 0; static ComPtr g_qd3d12NeuralPOMZeroBuffer; static UINT g_qd3d12NeuralPOMZeroSrvIndex = UINT_MAX; @@ -6751,7 +6764,12 @@ struct QD3D12StreamlineState uint32_t lastDlssGEligibilityMaskLogged = 0xffffffffu; uint32_t lastDlssGFramesToGenerateLogged = 0xffffffffu; uint32_t lastDlssGPresentedFramesLogged = 0xffffffffu; - sl::ViewportHandle viewport = { 1 }; + uint32_t dlssGConfiguredFramesToGenerate = 0xffffffffu; + uint32_t dlssGConfiguredRenderWidth = 0xffffffffu; + uint32_t dlssGConfiguredRenderHeight = 0xffffffffu; + uint32_t dlssGConfiguredColorWidth = 0xffffffffu; + uint32_t dlssGConfiguredColorHeight = 0xffffffffu; + sl::ViewportHandle viewport = { 0 }; }; static QD3D12StreamlineState g_qd3d12Sl; @@ -7051,10 +7069,7 @@ static void QD3D12_StreamlineOnDeviceCreated() static bool QD3D12_WantsDLSSRayReconstruction() { - return g_gl.enableDLSSRayReconstruction && - g_gl.upscalerBackend == QD3D12_UPSCALER_DLSS && - g_gl.upscalerQuality != QD3D12_QUALITY_NATIVE && - g_qd3d12Sl.deviceBound; + return false; } static bool QD3D12_CanUseDLSSRayReconstructionForLighting(const QD3D12Window& w) @@ -7068,8 +7083,8 @@ static bool QD3D12_UseLightingTextureAsUpscaleInput(const QD3D12Window& w) { return QD3D12_CanUseDLSSRayReconstructionForLighting(w) && g_gl.raytracedLightingReadyThisFrame && - g_lightingTexture && - g_lightingTexture->texture; + g_lightingTexture[g_lightingReadIndex] && + g_lightingTexture[g_lightingReadIndex]->texture; } static sl::Result QD3D12_SetStreamlineCommonConstants(sl::FrameToken& frameToken) @@ -7127,6 +7142,21 @@ static sl::Result QD3D12_GetStreamlineFrameToken(sl::FrameToken*& frameToken) return result; } +static sl::Result QD3D12_EnableReflexForFrame(sl::FrameToken& frameToken) +{ + sl::ReflexOptions reflexOptions{}; + reflexOptions.mode = sl::ReflexMode::eLowLatencyWithBoost; + sl::Result result = slReflexSetOptions(reflexOptions); + if (result != sl::Result::eOk) + return result; + + result = slReflexSleep(frameToken); + if (result != sl::Result::eOk) + QD3D12_Log("slReflexSleep failed (%d), continuing with frame generation setup.", int(result)); + + return sl::Result::eOk; +} + static bool QD3D12_WantsDLSSFrameGeneration(const QD3D12Window& w) { return @@ -7207,6 +7237,11 @@ static void QD3D12_SetDLSSFrameGenerationOff() } g_qd3d12Sl.dlssGActive = false; + g_qd3d12Sl.dlssGConfiguredFramesToGenerate = 0xffffffffu; + g_qd3d12Sl.dlssGConfiguredRenderWidth = 0xffffffffu; + g_qd3d12Sl.dlssGConfiguredRenderHeight = 0xffffffffu; + g_qd3d12Sl.dlssGConfiguredColorWidth = 0xffffffffu; + g_qd3d12Sl.dlssGConfiguredColorHeight = 0xffffffffu; } static void QD3D12_SetDLSSGFeatureLoaded(bool loaded) @@ -7273,6 +7308,14 @@ static void QD3D12_ConfigureDLSSFrameGeneration(QD3D12Window& w, sl::FrameToken* } } + const sl::Result reflexResult = QD3D12_EnableReflexForFrame(*frameToken); + if (reflexResult != sl::Result::eOk) + { + QD3D12_Log("slReflexSetOptions failed (%d), disabling frame generation for this frame.", int(reflexResult)); + QD3D12_SetDLSSFrameGenerationOff(); + return; + } + const sl::Result constResult = QD3D12_SetStreamlineCommonConstants(*frameToken); if (constResult != sl::Result::eOk) { @@ -7281,22 +7324,6 @@ static void QD3D12_ConfigureDLSSFrameGeneration(QD3D12Window& w, sl::FrameToken* 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; @@ -7324,8 +7351,16 @@ static void QD3D12_ConfigureDLSSFrameGeneration(QD3D12Window& w, sl::FrameToken* options.hudLessBufferFormat = uint32_t(DXGI_FORMAT_R8G8B8A8_UNORM); options.uiBufferFormat = uint32_t(DXGI_FORMAT_R8G8B8A8_UNORM); + const bool configMayNeedUpdate = + !g_qd3d12Sl.dlssGActive || + g_qd3d12Sl.dlssGConfiguredFramesToGenerate != options.numFramesToGenerate || + g_qd3d12Sl.dlssGConfiguredRenderWidth != w.renderWidth || + g_qd3d12Sl.dlssGConfiguredRenderHeight != w.renderHeight || + g_qd3d12Sl.dlssGConfiguredColorWidth != w.width || + g_qd3d12Sl.dlssGConfiguredColorHeight != w.height; + sl::DLSSGState state{}; - const sl::Result stateResult = slDLSSGGetState(g_qd3d12Sl.viewport, state, &options); + const sl::Result stateResult = slDLSSGGetState(g_qd3d12Sl.viewport, state, configMayNeedUpdate ? &options : nullptr); if (stateResult == sl::Result::eOk) { if (state.numFramesToGenerateMax > 0) @@ -7351,12 +7386,29 @@ static void QD3D12_ConfigureDLSSFrameGeneration(QD3D12Window& w, sl::FrameToken* QD3D12_TagDLSSFrameGenerationInputs(w, *frameToken, renderExtent, outputExtent); - const sl::Result setResult = slDLSSGSetOptions(g_qd3d12Sl.viewport, options); - if (setResult != sl::Result::eOk) + const bool needsSetOptions = + !g_qd3d12Sl.dlssGActive || + g_qd3d12Sl.dlssGConfiguredFramesToGenerate != options.numFramesToGenerate || + g_qd3d12Sl.dlssGConfiguredRenderWidth != w.renderWidth || + g_qd3d12Sl.dlssGConfiguredRenderHeight != w.renderHeight || + g_qd3d12Sl.dlssGConfiguredColorWidth != w.width || + g_qd3d12Sl.dlssGConfiguredColorHeight != w.height; + + if (needsSetOptions) { - QD3D12_Log("slDLSSGSetOptions(on) failed (%d).", int(setResult)); - QD3D12_SetDLSSFrameGenerationOff(); - return; + 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; + } + + g_qd3d12Sl.dlssGConfiguredFramesToGenerate = options.numFramesToGenerate; + g_qd3d12Sl.dlssGConfiguredRenderWidth = w.renderWidth; + g_qd3d12Sl.dlssGConfiguredRenderHeight = w.renderHeight; + g_qd3d12Sl.dlssGConfiguredColorWidth = w.width; + g_qd3d12Sl.dlssGConfiguredColorHeight = w.height; } if (!g_qd3d12Sl.dlssGActive || g_qd3d12Sl.lastDlssGFramesToGenerateLogged != options.numFramesToGenerate) @@ -7847,11 +7899,8 @@ static bool QD3D12_ExternalTemporalUpscalerActive(const QD3D12Window& w) static bool QD3D12_ShouldRunInternalTAA(const QD3D12Window& w) { - // DLSS/DLSS-RR/FSR are already temporal. The internal TAA pass replaces MSAA - // for the native/no-upscaler path and runs after lighting but before 2D. - return g_gl.enableInternalTAA && - !w.isPbuffer && - !QD3D12_ExternalTemporalUpscalerActive(w); + (void)w; + return false; } static bool QD3D12_FinalBlitToBackBuffer( @@ -7985,6 +8034,40 @@ static void QD3D12_ExecuteMainCommandListAndWait(QD3D12Window& w) g_gl.frameOwner = &w; } +static void QD3D12_ExecuteMainCommandListForRaytracingHandoff(QD3D12Window& w) +{ + QD3D12_CHECK(g_gl.cmdList->Close()); + + ID3D12CommandList* lists[] = { g_gl.cmdList.Get() }; + g_gl.queue->ExecuteCommandLists(1, lists); + + const UINT64 signalValue = g_gl.nextFenceValue++; + QD3D12_CHECK(g_gl.queue->Signal(g_gl.fence.Get(), signalValue)); + w.frames[w.frameIndex].fenceValue = signalValue; + + const UINT slot = g_gl.raytraceContinuationIndex++ % QD3D12_FrameCount; + const UINT64 continuationFence = g_gl.raytraceContinuationFence[slot]; + if (continuationFence != 0 && g_gl.fence->GetCompletedValue() < continuationFence) + { + QD3D12_CHECK(g_gl.fence->SetEventOnCompletion(continuationFence, g_gl.fenceEvent)); + WaitForSingleObject(g_gl.fenceEvent, INFINITE); + } + + if (!g_gl.raytraceContinuationAlloc[slot]) + { + QD3D12_CHECK(g_gl.device->CreateCommandAllocator( + D3D12_COMMAND_LIST_TYPE_DIRECT, + IID_PPV_ARGS(&g_gl.raytraceContinuationAlloc[slot]))); + } + + QD3D12_CHECK(g_gl.raytraceContinuationAlloc[slot]->Reset()); + QD3D12_CHECK(g_gl.cmdList->Reset(g_gl.raytraceContinuationAlloc[slot].Get(), nullptr)); + + g_gl.activeRaytraceContinuationSlot = (int)slot; + g_gl.frameOpen = true; + g_gl.frameOwner = &w; +} + static void QD3D12_RunRayAIDenoiseIfEnabled(ID3D12GraphicsCommandList* cl, QD3D12Window& w, ID3D12Resource* lightingResource) { (void)cl; @@ -8016,10 +8099,11 @@ static void QD3D12_RunUpscalerOrBlit(QD3D12Window& w) ID3D12Resource* upscaleInputResource = w.sceneColorBuffers[w.frameIndex].Get(); D3D12_GPU_DESCRIPTOR_HANDLE upscaleInputSrv = w.sceneColorSrvGpu[w.frameIndex]; - if (useLightingUpscaleInput && g_lightingTexture && g_lightingTexture->texture) + TextureResource* readLightingTex = g_lightingTexture[g_lightingReadIndex]; + if (useLightingUpscaleInput && readLightingTex && readLightingTex->texture) { - upscaleInputResource = g_lightingTexture->texture.Get(); - upscaleInputSrv = g_lightingTexture->srvGpu; + upscaleInputResource = readLightingTex->texture.Get(); + upscaleInputSrv = readLightingTex->srvGpu; } D3D12_VIEWPORT outputViewport{}; @@ -10069,6 +10153,15 @@ void QD3D12_EndFrame() ID3D12CommandList* lists[] = { g_gl.cmdList.Get() }; g_gl.queue->ExecuteCommandLists(1, lists); + if (g_gl.activeRaytraceContinuationSlot >= 0) + { + const UINT slot = (UINT)g_gl.activeRaytraceContinuationSlot; + const UINT64 signalValue = g_gl.nextFenceValue++; + QD3D12_CHECK(g_gl.queue->Signal(g_gl.fence.Get(), signalValue)); + g_gl.raytraceContinuationFence[slot] = signalValue; + g_gl.activeRaytraceContinuationSlot = -1; + } + g_gl.frameOpen = false; g_gl.frameOwner = nullptr; if (!w.isPbuffer) @@ -10300,16 +10393,17 @@ static void EnsureTextureResource(TextureResource& tex) tex.gpuValid = false; } -static TextureResource* QD3D12_EnsureLightingTexture(int width, int height) +static TextureResource* QD3D12_EnsureLightingTexture(int width, int height, UINT slot) { const DXGI_FORMAT desiredFormat = DXGI_FORMAT_R16G16B16A16_FLOAT; + slot %= QD3D12_LightingTextureCount; - if (g_lightingTextureId == 0) + if (g_lightingTextureId[slot] == 0) { - g_lightingTextureId = g_gl.nextTextureId++; + g_lightingTextureId[slot] = g_gl.nextTextureId++; TextureResource tex{}; - tex.glId = g_lightingTextureId; + tex.glId = g_lightingTextureId[slot]; tex.width = (int)width; tex.height = (int)height; tex.format = GL_RGBA; @@ -10329,44 +10423,45 @@ static TextureResource* QD3D12_EnsureLightingTexture(int width, int height) tex.srvCpu = QD3D12_SrvCpu(tex.srvIndex); tex.srvGpu = QD3D12_SrvGpu(tex.srvIndex); - auto it = g_gl.textures.emplace(g_lightingTextureId, std::move(tex)).first; - g_lightingTexture = &it->second; + auto it = g_gl.textures.emplace(g_lightingTextureId[slot], std::move(tex)).first; + g_lightingTexture[slot] = &it->second; } - if (!g_lightingTexture) + if (!g_lightingTexture[slot]) { - auto it = g_gl.textures.find(g_lightingTextureId); + auto it = g_gl.textures.find(g_lightingTextureId[slot]); if (it == g_gl.textures.end()) return nullptr; - g_lightingTexture = &it->second; + g_lightingTexture[slot] = &it->second; } - g_lightingTexture->dxgiFormat = desiredFormat; - g_lightingTexture->mipLevels = 1; + TextureResource* lightingTex = g_lightingTexture[slot]; + lightingTex->dxgiFormat = desiredFormat; + lightingTex->mipLevels = 1; const bool needsCreate = - !g_lightingTexture->texture || - g_lightingTexture->width != (int)width || - g_lightingTexture->height != (int)height || - g_lightingTexture->texture->GetDesc().Format != desiredFormat || - ((g_lightingTexture->texture->GetDesc().Flags & D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS) == 0); + !lightingTex->texture || + lightingTex->width != (int)width || + lightingTex->height != (int)height || + lightingTex->texture->GetDesc().Format != desiredFormat || + ((lightingTex->texture->GetDesc().Flags & D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS) == 0); if (!needsCreate) - return g_lightingTexture; + return lightingTex; - if (g_lightingTexture->texture) + if (lightingTex->texture) { - QD3D12_RetireResource(g_lightingTexture->texture); + QD3D12_RetireResource(lightingTex->texture); } - g_lightingTexture->width = (int)width; - g_lightingTexture->height = (int)height; - g_lightingTexture->compressed = false; - g_lightingTexture->compressedInternalFormat = 0; - g_lightingTexture->compressedBlockBytes = 0; - g_lightingTexture->compressedImageSize = 0; - g_lightingTexture->forceOpaqueAlpha = false; - g_lightingTexture->sysmem.clear(); + lightingTex->width = (int)width; + lightingTex->height = (int)height; + lightingTex->compressed = false; + lightingTex->compressedInternalFormat = 0; + lightingTex->compressedBlockBytes = 0; + lightingTex->compressedImageSize = 0; + lightingTex->forceOpaqueAlpha = false; + lightingTex->sysmem.clear(); D3D12_RESOURCE_DESC rd{}; rd.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; @@ -10390,7 +10485,7 @@ static TextureResource* QD3D12_EnsureLightingTexture(int width, int height) &rd, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, nullptr, - IID_PPV_ARGS(&g_lightingTexture->texture))); + IID_PPV_ARGS(&lightingTex->texture))); D3D12_SHADER_RESOURCE_VIEW_DESC srv{}; srv.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; @@ -10399,15 +10494,16 @@ static TextureResource* QD3D12_EnsureLightingTexture(int width, int height) srv.Texture2D.MipLevels = 1; g_gl.device->CreateShaderResourceView( - g_lightingTexture->texture.Get(), + lightingTex->texture.Get(), &srv, - g_lightingTexture->srvCpu); + lightingTex->srvCpu); - g_lightingTexture->gpuValid = true; - g_lightingTexture->state = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; - g_lightingTextureState = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; + lightingTex->gpuValid = true; + lightingTex->state = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; + g_lightingTextureState[slot] = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; + g_lightingTextureValid[slot] = false; - return g_lightingTexture; + return lightingTex; } static void ConvertToRGBA8(const TextureResource& tex, std::vector& outRGBA) @@ -16733,9 +16829,15 @@ static void QD3D12_ResolveSceneToOutputAndEnterNativePhase(QD3D12Window& w) { QD3D12_TransitionResource(cl, w.normalBuffers[w.frameIndex].Get(), w.normalBufferState[w.frameIndex], D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); - if (g_lightingTexture && g_lightingTexture->texture) + TextureResource* readLightingTex = g_lightingTexture[g_lightingReadIndex]; + if (readLightingTex && readLightingTex->texture) { - QD3D12_TransitionResource(cl, g_lightingTexture->texture.Get(), g_lightingTextureState, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); + QD3D12_TransitionResource( + cl, + readLightingTex->texture.Get(), + g_lightingTextureState[g_lightingReadIndex], + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); + g_lightingTextureState[g_lightingReadIndex] = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; } } @@ -16771,8 +16873,14 @@ void glLightScene(glRaytracingSceneHandle_t sceneHandle) QD3D12_EnsureFrameOpen(); - TextureResource* lightingTex = QD3D12_EnsureLightingTexture(width, height); - if (!lightingTex || !lightingTex->texture) + const UINT writeLightingIndex = g_lightingWriteIndex % QD3D12_LightingTextureCount; + const UINT previousLightingIndex = writeLightingIndex ^ 1u; + + TextureResource* writeLightingTex = QD3D12_EnsureLightingTexture(width, height, writeLightingIndex); + (void)QD3D12_EnsureLightingTexture(width, height, previousLightingIndex); + const UINT readLightingIndex = writeLightingIndex; + TextureResource* readLightingTex = g_lightingTexture[readLightingIndex]; + if (!writeLightingTex || !writeLightingTex->texture || !readLightingTex || !readLightingTex->texture) return; // Scene/TLAS ownership is now per render world. Querying the scene TLAS here @@ -16835,18 +16943,18 @@ void glLightScene(glRaytracingSceneHandle_t sceneHandle) // The external DXR module records and executes its own command list. Because // of that, the scene input transitions must be submitted on the main command // list before we call into glRaytracingLightingExecuteForScene. - if (g_lightingTextureState != D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE) + if (g_lightingTextureState[writeLightingIndex] != D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE) { QD3D12_TransitionResource( cl, - lightingTex->texture.Get(), - g_lightingTextureState, + writeLightingTex->texture.Get(), + g_lightingTextureState[writeLightingIndex], D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); - g_lightingTextureState = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; + g_lightingTextureState[writeLightingIndex] = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; } - QD3D12_ExecuteMainCommandListAndWait(*window); + QD3D12_ExecuteMainCommandListForRaytracingHandoff(*window); cl = g_gl.cmdList.Get(); QD3D12_UpdateCameraInfoFromCurrentMatrices(); @@ -16883,8 +16991,8 @@ void glLightScene(glRaytracingSceneHandle_t sceneHandle) pass.depthTexture = sceneDepth; pass.depthFormat = QD3D12_DepthSrvFormat; - pass.outputTexture = lightingTex->texture.Get(); - pass.outputFormat = lightingTex->dxgiFormat; + pass.outputTexture = writeLightingTex->texture.Get(); + pass.outputFormat = writeLightingTex->dxgiFormat; pass.width = (uint32_t)width; pass.height = (uint32_t)height; @@ -16945,21 +17053,25 @@ void glLightScene(glRaytracingSceneHandle_t sceneHandle) } // The scene-handle DXR path leaves outputTexture in PIXEL_SHADER_RESOURCE. - g_lightingTextureState = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; + g_lightingTextureState[writeLightingIndex] = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; + g_lightingTextureValid[writeLightingIndex] = true; + g_lightingReadIndex = readLightingIndex; + g_lightingWriteIndex = previousLightingIndex; - QD3D12_RunRayAIDenoiseIfEnabled(cl, *window, lightingTex->texture.Get()); + QD3D12_RunRayAIDenoiseIfEnabled(cl, *window, writeLightingTex->texture.Get()); - // If the denoiser changes the texture state and updates g_lightingTextureState, + // If the denoiser changes the written texture state, restore it to a + // shader-readable state before this slot becomes the next read target. // restore the texture to a shader-readable state for the post/upscale pass. - if (g_lightingTextureState != D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE) + if (g_lightingTextureState[writeLightingIndex] != D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE) { QD3D12_TransitionResource( cl, - lightingTex->texture.Get(), - g_lightingTextureState, + writeLightingTex->texture.Get(), + g_lightingTextureState[writeLightingIndex], D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); - g_lightingTextureState = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; + g_lightingTextureState[writeLightingIndex] = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; } g_gl.raytracedLightingReadyThisFrame = true; @@ -16992,7 +17104,7 @@ void glLightScene(glRaytracingSceneHandle_t sceneHandle) // in QD3D12_FinalBlitToBackBuffer(). if (!QD3D12_ToneMapFullscreenPass( *window, - lightingTex->srvGpu, + readLightingTex->srvGpu, CurrentResolvedSceneColorRTV(), viewport, scissor, @@ -17002,7 +17114,7 @@ void glLightScene(glRaytracingSceneHandle_t sceneHandle) QD3D12_PostFullscreenPass( cl, g_gl.postCopyPSO.Get(), - lightingTex->srvGpu, + readLightingTex->srvGpu, CurrentResolvedSceneColorRTV(), viewport, scissor, @@ -17177,7 +17289,8 @@ static void QD3D12_ResetInternalTAAHistoryForWindow(QD3D12Window* window) void QD3D12_EnableTAA(int enabled) { - const bool newValue = enabled ? true : false; + (void)enabled; + const bool newValue = false; if (g_gl.enableInternalTAA == newValue) return; @@ -17193,7 +17306,7 @@ void QD3D12_EnableTAA(int enabled) int QD3D12_IsTAAEnabled(void) { - return g_gl.enableInternalTAA ? 1 : 0; + return 0; } void APIENTRY glTAAQD3D12(GLboolean enable) @@ -17270,7 +17383,8 @@ void QD3D12_EnableRayAIDenoise(int enabled) void QD3D12_EnableDLSSRayReconstruction(int enabled) { - const bool newValue = enabled ? true : false; + (void)enabled; + const bool newValue = false; if (g_gl.enableDLSSRayReconstruction == newValue) return;