From 19316cf3e505d6561d1df011e94b41d8c1dc608e Mon Sep 17 00:00:00 2001 From: nbenty Date: Mon, 21 May 2018 10:20:43 -0700 Subject: [PATCH 01/18] dev-3.0.3 branch --- Framework/Source/Falcor.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Framework/Source/Falcor.h b/Framework/Source/Falcor.h index 52f836e76..039677f22 100644 --- a/Framework/Source/Falcor.h +++ b/Framework/Source/Falcor.h @@ -159,5 +159,5 @@ #define FALCOR_MAJOR_VERSION 3 #define FALCOR_MINOR_VERSION 0 #define FALCOR_DEV_STAGE "" -#define FALCOR_DEV_REVISION 2 -#define FALCOR_VERSION_STRING "3.0.2" \ No newline at end of file +#define FALCOR_DEV_REVISION 3 +#define FALCOR_VERSION_STRING "3.0.3" \ No newline at end of file From 248874c99cfae47bc5bec9c912671b9fa712d6cd Mon Sep 17 00:00:00 2001 From: nbenty Date: Mon, 21 May 2018 10:30:46 -0700 Subject: [PATCH 02/18] FXAA files (currently just bliting) --- Framework/Source/Data/Effects/FXAA.slang | 10 ++++ Framework/Source/Effects/FXAA/FXAA.cpp | 48 ++++++++++++++++ Framework/Source/Effects/FXAA/FXAA.h | 70 ++++++++++++++++++++++++ Framework/Source/Falcor.props | 2 +- Framework/Source/Falcor.vcxproj | 3 + Framework/Source/Falcor.vcxproj.filters | 12 ++++ 6 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 Framework/Source/Data/Effects/FXAA.slang create mode 100644 Framework/Source/Effects/FXAA/FXAA.cpp create mode 100644 Framework/Source/Effects/FXAA/FXAA.h diff --git a/Framework/Source/Data/Effects/FXAA.slang b/Framework/Source/Data/Effects/FXAA.slang new file mode 100644 index 000000000..47b0dca80 --- /dev/null +++ b/Framework/Source/Data/Effects/FXAA.slang @@ -0,0 +1,10 @@ +/*************************************************************************** +Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. +***************************************************************************/ +Texture2D gSrc; +SSamplerState gSampler; + +float4 ps(float2 texC : TEXCOORD) : SV_TARGET +{ + return gSrc.Sample(gSampler, texC); +} \ No newline at end of file diff --git a/Framework/Source/Effects/FXAA/FXAA.cpp b/Framework/Source/Effects/FXAA/FXAA.cpp new file mode 100644 index 000000000..a4ce82d38 --- /dev/null +++ b/Framework/Source/Effects/FXAA/FXAA.cpp @@ -0,0 +1,48 @@ +/*************************************************************************** +* Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. +***************************************************************************/ +#include "FXAA.h" + +namespace Falcor +{ + static const char* kShaderFilename = "Effects/FXAA.slang"; + + FXAA::~FXAA() = default; + + FXAA::FXAA() + { + mpPass = FullScreenPass::create(kShaderFilename); + mpGraphicsVars = GraphicsVars::create(mpPass->getProgram()->getReflector()); + mpPointSampler = Sampler::create({}); + mpGraphicsVars->setSampler("gSampler", mpPointSampler); + } + + FXAA::UniquePtr FXAA::create() + { + try + { + FXAA* pTaa = new FXAA(); + return FXAA::UniquePtr(pTaa); + } + catch (const std::exception&) + { + return nullptr; + } + } + + void FXAA::renderUI(Gui* pGui) + { + } + + void FXAA::execute(RenderContext* pRenderContext, const Texture::SharedPtr& pSrcTex, const Fbo::SharedPtr& pDstFbo) + { + mpGraphicsVars->setTexture("gSrc", pSrcTex); + pRenderContext->pushGraphicsVars(mpGraphicsVars); + pRenderContext->getGraphicsState()->pushFbo(pDstFbo); + + mpPass->execute(pRenderContext); + + pRenderContext->getGraphicsState()->popFbo(); + pRenderContext->popGraphicsVars(); + } +} \ No newline at end of file diff --git a/Framework/Source/Effects/FXAA/FXAA.h b/Framework/Source/Effects/FXAA/FXAA.h new file mode 100644 index 000000000..064c1ed95 --- /dev/null +++ b/Framework/Source/Effects/FXAA/FXAA.h @@ -0,0 +1,70 @@ +/*************************************************************************** +# Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of NVIDIA CORPORATION nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +***************************************************************************/ +#pragma once +#include "Falcor.h" + +namespace Falcor +{ + class Gui; + + /** Temporal AA class + */ + class FXAA + { + public: + using UniquePtr = std::unique_ptr; + + /** Destructor + */ + ~FXAA(); + + /** Create a new instance + */ + static UniquePtr create(); + + /** Render UI controls for this effect. + \param[in] pGui GUI object to render UI elements with + */ + void renderUI(Gui* pGui); + + /** Run the effect + \param[in] pRenderContext Render context with the destination FBO already set + \param[in] pCurColor Current frame color buffer + \param[in] pPrevColor Previous frame color buffer + \param[in] pMotionVec Motion vector buffer + */ + void execute(RenderContext* pRenderContext, const Texture::SharedPtr& pSrcTex, const Fbo::SharedPtr& pDstFbo); + + private: + FXAA(); + + FullScreenPass::UniquePtr mpPass; + GraphicsVars::SharedPtr mpGraphicsVars; + Sampler::SharedPtr mpPointSampler; + }; +} \ No newline at end of file diff --git a/Framework/Source/Falcor.props b/Framework/Source/Falcor.props index 8fc182e0c..71033cef6 100644 --- a/Framework/Source/Falcor.props +++ b/Framework/Source/Falcor.props @@ -3,7 +3,7 @@ $(SolutionDir)\.\Framework\Source\\..\ - FALCOR_VK + FALCOR_D3D12 $(SolutionDir)Bin\$(PlatformShortName)\$(Configuration)\ diff --git a/Framework/Source/Falcor.vcxproj b/Framework/Source/Falcor.vcxproj index 788f1e900..f5c584ac1 100644 --- a/Framework/Source/Falcor.vcxproj +++ b/Framework/Source/Falcor.vcxproj @@ -380,6 +380,7 @@ + @@ -931,6 +932,7 @@ + @@ -1287,6 +1289,7 @@ + diff --git a/Framework/Source/Falcor.vcxproj.filters b/Framework/Source/Falcor.vcxproj.filters index dce28c5f4..9f2b8ec60 100644 --- a/Framework/Source/Falcor.vcxproj.filters +++ b/Framework/Source/Falcor.vcxproj.filters @@ -532,6 +532,9 @@ API\Vulkan + + Effects\FXAA + @@ -1687,6 +1690,9 @@ Data\Effects + + Effects\FXAA + @@ -1872,6 +1878,9 @@ {e3b76813-257a-4b19-8517-03302aa9fe98} + + {51b693f1-34da-4d5e-a6d5-925944c92c79} + @@ -2315,5 +2324,8 @@ Data\Effects + + Data\Effects + \ No newline at end of file From b9028d5c8438c29c2af9c2f9dd10ddea2b163f93 Mon Sep 17 00:00:00 2001 From: nbenty Date: Mon, 21 May 2018 12:29:30 -0700 Subject: [PATCH 03/18] Implemented the FXAA shader. I couldn't use the shader from the NV D3Dsamples directly because Slang complains about an error. Will fix it once I figure it out --- Framework/Source/Data/Effects/FXAA.slang | 672 +++++++++++++++++- Framework/Source/Data/Effects/TAA.ps.slang | 26 +- Framework/Source/Effects/FXAA/FXAA.cpp | 12 +- Framework/Source/Effects/FXAA/FXAA.h | 2 +- Framework/Source/Falcor.h | 1 + Samples/ForwardRenderer/ForwardRenderer.cpp | 18 +- Samples/ForwardRenderer/ForwardRenderer.h | 11 +- .../ForwardRendererControls.cpp | 28 +- 8 files changed, 746 insertions(+), 24 deletions(-) diff --git a/Framework/Source/Data/Effects/FXAA.slang b/Framework/Source/Data/Effects/FXAA.slang index 47b0dca80..8d155809d 100644 --- a/Framework/Source/Data/Effects/FXAA.slang +++ b/Framework/Source/Data/Effects/FXAA.slang @@ -1,10 +1,672 @@ /*************************************************************************** -Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of NVIDIA CORPORATION nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ +import HostDeviceData; + +// #define FXAA_PC 1 +// #define FXAA_HLSL_5 1 +// #define FXAA_EARLY_EXIT 1 +// #define FXAA_FAST_PIXEL_OFFSET 0 +// #define FXAA_GATHER4_ALPHA 0 +#define FXAA_QUALITY__PRESET 39 + +/*============================================================================ + + FXAA QUALITY - PRESETS + +============================================================================*/ + +/*============================================================================ + FXAA QUALITY - MEDIUM DITHER PRESETS +============================================================================*/ +#if (FXAA_QUALITY__PRESET == 10) +#define FXAA_QUALITY__PS 3 +#define FXAA_QUALITY__P0 1.5 +#define FXAA_QUALITY__P1 3.0 +#define FXAA_QUALITY__P2 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 11) +#define FXAA_QUALITY__PS 4 +#define FXAA_QUALITY__P0 1.0 +#define FXAA_QUALITY__P1 1.5 +#define FXAA_QUALITY__P2 3.0 +#define FXAA_QUALITY__P3 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 12) +#define FXAA_QUALITY__PS 5 +#define FXAA_QUALITY__P0 1.0 +#define FXAA_QUALITY__P1 1.5 +#define FXAA_QUALITY__P2 2.0 +#define FXAA_QUALITY__P3 4.0 +#define FXAA_QUALITY__P4 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 13) +#define FXAA_QUALITY__PS 6 +#define FXAA_QUALITY__P0 1.0 +#define FXAA_QUALITY__P1 1.5 +#define FXAA_QUALITY__P2 2.0 +#define FXAA_QUALITY__P3 2.0 +#define FXAA_QUALITY__P4 4.0 +#define FXAA_QUALITY__P5 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 14) +#define FXAA_QUALITY__PS 7 +#define FXAA_QUALITY__P0 1.0 +#define FXAA_QUALITY__P1 1.5 +#define FXAA_QUALITY__P2 2.0 +#define FXAA_QUALITY__P3 2.0 +#define FXAA_QUALITY__P4 2.0 +#define FXAA_QUALITY__P5 4.0 +#define FXAA_QUALITY__P6 12.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 15) +#define FXAA_QUALITY__PS 8 +#define FXAA_QUALITY__P0 1.0 +#define FXAA_QUALITY__P1 1.5 +#define FXAA_QUALITY__P2 2.0 +#define FXAA_QUALITY__P3 2.0 +#define FXAA_QUALITY__P4 2.0 +#define FXAA_QUALITY__P5 2.0 +#define FXAA_QUALITY__P6 4.0 +#define FXAA_QUALITY__P7 12.0 +#endif + +/*============================================================================ + FXAA QUALITY - LOW DITHER PRESETS +============================================================================*/ +#if (FXAA_QUALITY__PRESET == 20) +#define FXAA_QUALITY__PS 3 +#define FXAA_QUALITY__P0 1.5 +#define FXAA_QUALITY__P1 2.0 +#define FXAA_QUALITY__P2 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 21) +#define FXAA_QUALITY__PS 4 +#define FXAA_QUALITY__P0 1.0 +#define FXAA_QUALITY__P1 1.5 +#define FXAA_QUALITY__P2 2.0 +#define FXAA_QUALITY__P3 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 22) +#define FXAA_QUALITY__PS 5 +#define FXAA_QUALITY__P0 1.0 +#define FXAA_QUALITY__P1 1.5 +#define FXAA_QUALITY__P2 2.0 +#define FXAA_QUALITY__P3 2.0 +#define FXAA_QUALITY__P4 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 23) +#define FXAA_QUALITY__PS 6 +#define FXAA_QUALITY__P0 1.0 +#define FXAA_QUALITY__P1 1.5 +#define FXAA_QUALITY__P2 2.0 +#define FXAA_QUALITY__P3 2.0 +#define FXAA_QUALITY__P4 2.0 +#define FXAA_QUALITY__P5 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 24) +#define FXAA_QUALITY__PS 7 +#define FXAA_QUALITY__P0 1.0 +#define FXAA_QUALITY__P1 1.5 +#define FXAA_QUALITY__P2 2.0 +#define FXAA_QUALITY__P3 2.0 +#define FXAA_QUALITY__P4 2.0 +#define FXAA_QUALITY__P5 3.0 +#define FXAA_QUALITY__P6 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 25) +#define FXAA_QUALITY__PS 8 +#define FXAA_QUALITY__P0 1.0 +#define FXAA_QUALITY__P1 1.5 +#define FXAA_QUALITY__P2 2.0 +#define FXAA_QUALITY__P3 2.0 +#define FXAA_QUALITY__P4 2.0 +#define FXAA_QUALITY__P5 2.0 +#define FXAA_QUALITY__P6 4.0 +#define FXAA_QUALITY__P7 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 26) +#define FXAA_QUALITY__PS 9 +#define FXAA_QUALITY__P0 1.0 +#define FXAA_QUALITY__P1 1.5 +#define FXAA_QUALITY__P2 2.0 +#define FXAA_QUALITY__P3 2.0 +#define FXAA_QUALITY__P4 2.0 +#define FXAA_QUALITY__P5 2.0 +#define FXAA_QUALITY__P6 2.0 +#define FXAA_QUALITY__P7 4.0 +#define FXAA_QUALITY__P8 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 27) +#define FXAA_QUALITY__PS 10 +#define FXAA_QUALITY__P0 1.0 +#define FXAA_QUALITY__P1 1.5 +#define FXAA_QUALITY__P2 2.0 +#define FXAA_QUALITY__P3 2.0 +#define FXAA_QUALITY__P4 2.0 +#define FXAA_QUALITY__P5 2.0 +#define FXAA_QUALITY__P6 2.0 +#define FXAA_QUALITY__P7 2.0 +#define FXAA_QUALITY__P8 4.0 +#define FXAA_QUALITY__P9 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 28) +#define FXAA_QUALITY__PS 11 +#define FXAA_QUALITY__P0 1.0 +#define FXAA_QUALITY__P1 1.5 +#define FXAA_QUALITY__P2 2.0 +#define FXAA_QUALITY__P3 2.0 +#define FXAA_QUALITY__P4 2.0 +#define FXAA_QUALITY__P5 2.0 +#define FXAA_QUALITY__P6 2.0 +#define FXAA_QUALITY__P7 2.0 +#define FXAA_QUALITY__P8 2.0 +#define FXAA_QUALITY__P9 4.0 +#define FXAA_QUALITY__P10 8.0 +#endif +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PRESET == 29) +#define FXAA_QUALITY__PS 12 +#define FXAA_QUALITY__P0 1.0 +#define FXAA_QUALITY__P1 1.5 +#define FXAA_QUALITY__P2 2.0 +#define FXAA_QUALITY__P3 2.0 +#define FXAA_QUALITY__P4 2.0 +#define FXAA_QUALITY__P5 2.0 +#define FXAA_QUALITY__P6 2.0 +#define FXAA_QUALITY__P7 2.0 +#define FXAA_QUALITY__P8 2.0 +#define FXAA_QUALITY__P9 2.0 +#define FXAA_QUALITY__P10 4.0 +#define FXAA_QUALITY__P11 8.0 +#endif + +/*============================================================================ + FXAA QUALITY - EXTREME QUALITY +============================================================================*/ +#if (FXAA_QUALITY__PRESET == 39) +#define FXAA_QUALITY__PS 12 +#define FXAA_QUALITY__P0 1.0 +#define FXAA_QUALITY__P1 1.0 +#define FXAA_QUALITY__P2 1.0 +#define FXAA_QUALITY__P3 1.0 +#define FXAA_QUALITY__P4 1.0 +#define FXAA_QUALITY__P5 1.5 +#define FXAA_QUALITY__P6 2.0 +#define FXAA_QUALITY__P7 2.0 +#define FXAA_QUALITY__P8 2.0 +#define FXAA_QUALITY__P9 2.0 +#define FXAA_QUALITY__P10 4.0 +#define FXAA_QUALITY__P11 8.0 +#endif + +cbuffer PerFrameCB +{ + float2 rcpTexDim; + float qualitySubPix; + float qualityEdgeThreshold; + float qualityEdgeThresholdMin; +}; + +SamplerState gSampler; Texture2D gSrc; -SSamplerState gSampler; -float4 ps(float2 texC : TEXCOORD) : SV_TARGET +/*--------------------------------------------------------------------------*/ +float4 main(float2 texC : TEXCOORD) : SV_TARGET { - return gSrc.Sample(gSampler, texC); -} \ No newline at end of file + float2 posM = texC; + float4 color = gSrc.SampleLevel(gSampler, texC, 0); + float lumaM = luminance(color.rgb); + float lumaS = luminance(gSrc.SampleLevel(gSampler, posM, 0, int2(0, 1)).rgb); + float lumaE = luminance(gSrc.SampleLevel(gSampler, posM, 0, int2(1, 0)).rgb); + float lumaN = luminance(gSrc.SampleLevel(gSampler, posM, 0, int2(0, -1)).rgb); + float lumaW = luminance(gSrc.SampleLevel(gSampler, posM, 0, int2(-1, 0)).rgb); + + float maxSM = max(lumaS, lumaM); + float minSM = min(lumaS, lumaM); + float maxESM = max(lumaE, maxSM); + float minESM = min(lumaE, minSM); + float maxWN = max(lumaN, lumaW); + float minWN = min(lumaN, lumaW); + float rangeMax = max(maxWN, maxESM); + float rangeMin = min(minWN, minESM); + float rangeMaxScaled = rangeMax * qualityEdgeThreshold; + float range = rangeMax - rangeMin; + float rangeMaxClamped = max(qualityEdgeThresholdMin, rangeMaxScaled); + bool earlyExit = range < rangeMaxClamped; + + if (earlyExit) + return color; + + float lumaNW = luminance(gSrc.SampleLevel(gSampler, posM, 0, int2(-1, -1)).rgb); + float lumaSE = luminance(gSrc.SampleLevel(gSampler, posM, 0, int2(1, 1)).rgb); + float lumaNE = luminance(gSrc.SampleLevel(gSampler, posM, 0, int2(1, -1)).rgb); + float lumaSW = luminance(gSrc.SampleLevel(gSampler, posM, 0, int2(-1, 1)).rgb); + + float lumaNS = lumaN + lumaS; + float lumaWE = lumaW + lumaE; + float subpixRcpRange = 1.0 / range; + float subpixNSWE = lumaNS + lumaWE; + float edgeHorz1 = (-2.0 * lumaM) + lumaNS; + float edgeVert1 = (-2.0 * lumaM) + lumaWE; + + float lumaNESE = lumaNE + lumaSE; + float lumaNWNE = lumaNW + lumaNE; + float edgeHorz2 = (-2.0 * lumaE) + lumaNESE; + float edgeVert2 = (-2.0 * lumaN) + lumaNWNE; + + float lumaNWSW = lumaNW + lumaSW; + float lumaSWSE = lumaSW + lumaSE; + float edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2); + float edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2); + float edgeHorz3 = (-2.0 * lumaW) + lumaNWSW; + float edgeVert3 = (-2.0 * lumaS) + lumaSWSE; + float edgeHorz = abs(edgeHorz3) + edgeHorz4; + float edgeVert = abs(edgeVert3) + edgeVert4; + + float subpixNWSWNESE = lumaNWSW + lumaNESE; + float lengthSign = rcpTexDim.x; + bool horzSpan = edgeHorz >= edgeVert; + float subpixA = subpixNSWE * 2.0 + subpixNWSWNESE; + + if (!horzSpan) + lumaN = lumaW; + if (!horzSpan) + lumaS = lumaE; + if (horzSpan) + lengthSign = rcpTexDim.y; + float subpixB = (subpixA * (1.0 / 12.0)) - lumaM; + + float gradientN = lumaN - lumaM; + float gradientS = lumaS - lumaM; + float lumaNN = lumaN + lumaM; + float lumaSS = lumaS + lumaM; + bool pairN = abs(gradientN) >= abs(gradientS); + float gradient = max(abs(gradientN), abs(gradientS)); + if (pairN) + lengthSign = -lengthSign; + float subpixC = saturate(abs(subpixB) * subpixRcpRange); + + float2 posB; + posB.x = posM.x; + posB.y = posM.y; + float2 offNP; + offNP.x = (!horzSpan) ? 0.0 : rcpTexDim.x; + offNP.y = (horzSpan) ? 0.0 : rcpTexDim.y; + if (!horzSpan) + posB.x += lengthSign * 0.5; + if (horzSpan) + posB.y += lengthSign * 0.5; + + float2 posN; + posN.x = posB.x - offNP.x * FXAA_QUALITY__P0; + posN.y = posB.y - offNP.y * FXAA_QUALITY__P0; + float2 posP; + posP.x = posB.x + offNP.x * FXAA_QUALITY__P0; + posP.y = posB.y + offNP.y * FXAA_QUALITY__P0; + float subpixD = ((-2.0) * subpixC) + 3.0; + float lumaEndN = luminance(gSrc.SampleLevel(gSampler, posN, 0).rgb); + float subpixE = subpixC * subpixC; + float lumaEndP = luminance(gSrc.SampleLevel(gSampler, posP, 0).rgb); + + if (!pairN) + lumaNN = lumaSS; + float gradientScaled = gradient * 1.0 / 4.0; + float lumaMM = lumaM - lumaNN * 0.5; + float subpixF = subpixD * subpixE; + bool lumaMLTZero = lumaMM < 0.0; + + lumaEndN -= lumaNN * 0.5; + lumaEndP -= lumaNN * 0.5; + bool doneN = abs(lumaEndN) >= gradientScaled; + bool doneP = abs(lumaEndP) >= gradientScaled; + if (!doneN) + posN.x -= offNP.x * FXAA_QUALITY__P1; + if (!doneN) + posN.y -= offNP.y * FXAA_QUALITY__P1; + bool doneNP = (!doneN) || (!doneP); + if (!doneP) + posP.x += offNP.x * FXAA_QUALITY__P1; + if (!doneP) + posP.y += offNP.y * FXAA_QUALITY__P1; + + if (doneNP) + { + if (!doneN) + lumaEndN = luminance(gSrc.SampleLevel(gSampler, posN.xy, 0).rgb); + if (!doneP) + lumaEndP = luminance(gSrc.SampleLevel(gSampler, posP.xy, 0).rgb); + if (!doneN) + lumaEndN = lumaEndN - lumaNN * 0.5; + if (!doneP) + lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if (!doneN) + posN.x -= offNP.x * FXAA_QUALITY__P2; + if (!doneN) + posN.y -= offNP.y * FXAA_QUALITY__P2; + doneNP = (!doneN) || (!doneP); + if (!doneP) + posP.x += offNP.x * FXAA_QUALITY__P2; + if (!doneP) + posP.y += offNP.y * FXAA_QUALITY__P2; +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PS > 3) + if (doneNP) + { + if (!doneN) + lumaEndN = luminance(gSrc.SampleLevel(gSampler, posN.xy, 0).rgb); + if (!doneP) + lumaEndP = luminance(gSrc.SampleLevel(gSampler, posP.xy, 0).rgb); + if (!doneN) + lumaEndN = lumaEndN - lumaNN * 0.5; + if (!doneP) + lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if (!doneN) + posN.x -= offNP.x * FXAA_QUALITY__P3; + if (!doneN) + posN.y -= offNP.y * FXAA_QUALITY__P3; + doneNP = (!doneN) || (!doneP); + if (!doneP) + posP.x += offNP.x * FXAA_QUALITY__P3; + if (!doneP) + posP.y += offNP.y * FXAA_QUALITY__P3; +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PS > 4) + if (doneNP) + { + if (!doneN) + lumaEndN = luminance(gSrc.SampleLevel(gSampler, posN.xy, 0).rgb); + if (!doneP) + lumaEndP = luminance(gSrc.SampleLevel(gSampler, posP.xy, 0).rgb); + if (!doneN) + lumaEndN = lumaEndN - lumaNN * 0.5; + if (!doneP) + lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if (!doneN) + posN.x -= offNP.x * FXAA_QUALITY__P4; + if (!doneN) + posN.y -= offNP.y * FXAA_QUALITY__P4; + doneNP = (!doneN) || (!doneP); + if (!doneP) + posP.x += offNP.x * FXAA_QUALITY__P4; + if (!doneP) + posP.y += offNP.y * FXAA_QUALITY__P4; +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PS > 5) + if (doneNP) + { + if (!doneN) + lumaEndN = luminance(gSrc.SampleLevel(gSampler, posN.xy, 0).rgb); + if (!doneP) + lumaEndP = luminance(gSrc.SampleLevel(gSampler, posP.xy, 0).rgb); + if (!doneN) + lumaEndN = lumaEndN - lumaNN * 0.5; + if (!doneP) + lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if (!doneN) + posN.x -= offNP.x * FXAA_QUALITY__P5; + if (!doneN) + posN.y -= offNP.y * FXAA_QUALITY__P5; + doneNP = (!doneN) || (!doneP); + if (!doneP) + posP.x += offNP.x * FXAA_QUALITY__P5; + if (!doneP) + posP.y += offNP.y * FXAA_QUALITY__P5; +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PS > 6) + if (doneNP) + { + if (!doneN) + lumaEndN = luminance(gSrc.SampleLevel(gSampler, posN.xy, 0).rgb); + if (!doneP) + lumaEndP = luminance(gSrc.SampleLevel(gSampler, posP.xy, 0).rgb); + if (!doneN) + lumaEndN = lumaEndN - lumaNN * 0.5; + if (!doneP) + lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if (!doneN) + posN.x -= offNP.x * FXAA_QUALITY__P6; + if (!doneN) + posN.y -= offNP.y * FXAA_QUALITY__P6; + doneNP = (!doneN) || (!doneP); + if (!doneP) + posP.x += offNP.x * FXAA_QUALITY__P6; + if (!doneP) + posP.y += offNP.y * FXAA_QUALITY__P6; +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PS > 7) + if (doneNP) + { + if (!doneN) + lumaEndN = luminance(gSrc.SampleLevel(gSampler, posN.xy, 0).rgb); + if (!doneP) + lumaEndP = luminance(gSrc.SampleLevel(gSampler, posP.xy, 0).rgb); + if (!doneN) + lumaEndN = lumaEndN - lumaNN * 0.5; + if (!doneP) + lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if (!doneN) + posN.x -= offNP.x * FXAA_QUALITY__P7; + if (!doneN) + posN.y -= offNP.y * FXAA_QUALITY__P7; + doneNP = (!doneN) || (!doneP); + if (!doneP) + posP.x += offNP.x * FXAA_QUALITY__P7; + if (!doneP) + posP.y += offNP.y * FXAA_QUALITY__P7; +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PS > 8) + if (doneNP) + { + if (!doneN) + lumaEndN = luminance(gSrc.SampleLevel(gSampler, posN.xy, 0).rgb); + if (!doneP) + lumaEndP = luminance(gSrc.SampleLevel(gSampler, posP.xy, 0).rgb); + if (!doneN) + lumaEndN = lumaEndN - lumaNN * 0.5; + if (!doneP) + lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if (!doneN) + posN.x -= offNP.x * FXAA_QUALITY__P8; + if (!doneN) + posN.y -= offNP.y * FXAA_QUALITY__P8; + doneNP = (!doneN) || (!doneP); + if (!doneP) + posP.x += offNP.x * FXAA_QUALITY__P8; + if (!doneP) + posP.y += offNP.y * FXAA_QUALITY__P8; +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PS > 9) + if (doneNP) + { + if (!doneN) + lumaEndN = luminance(gSrc.SampleLevel(gSampler, posN.xy, 0).rgb); + if (!doneP) + lumaEndP = luminance(gSrc.SampleLevel(gSampler, posP.xy, 0).rgb); + if (!doneN) + lumaEndN = lumaEndN - lumaNN * 0.5; + if (!doneP) + lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if (!doneN) + posN.x -= offNP.x * FXAA_QUALITY__P9; + if (!doneN) + posN.y -= offNP.y * FXAA_QUALITY__P9; + doneNP = (!doneN) || (!doneP); + if (!doneP) + posP.x += offNP.x * FXAA_QUALITY__P9; + if (!doneP) + posP.y += offNP.y * FXAA_QUALITY__P9; +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PS > 10) + if (doneNP) + { + if (!doneN) + lumaEndN = luminance(gSrc.SampleLevel(gSampler, posN.xy, 0).rgb); + if (!doneP) + lumaEndP = luminance(gSrc.SampleLevel(gSampler, posP.xy, 0).rgb); + if (!doneN) + lumaEndN = lumaEndN - lumaNN * 0.5; + if (!doneP) + lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if (!doneN) + posN.x -= offNP.x * FXAA_QUALITY__P10; + if (!doneN) + posN.y -= offNP.y * FXAA_QUALITY__P10; + doneNP = (!doneN) || (!doneP); + if (!doneP) + posP.x += offNP.x * FXAA_QUALITY__P10; + if (!doneP) + posP.y += offNP.y * FXAA_QUALITY__P10; +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PS > 11) + if (doneNP) + { + if (!doneN) + lumaEndN = luminance(gSrc.SampleLevel(gSampler, posN.xy, 0).rgb); + if (!doneP) + lumaEndP = luminance(gSrc.SampleLevel(gSampler, posP.xy, 0).rgb); + if (!doneN) + lumaEndN = lumaEndN - lumaNN * 0.5; + if (!doneP) + lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if (!doneN) + posN.x -= offNP.x * FXAA_QUALITY__P11; + if (!doneN) + posN.y -= offNP.y * FXAA_QUALITY__P11; + doneNP = (!doneN) || (!doneP); + if (!doneP) + posP.x += offNP.x * FXAA_QUALITY__P11; + if (!doneP) + posP.y += offNP.y * FXAA_QUALITY__P11; +/*--------------------------------------------------------------------------*/ +#if (FXAA_QUALITY__PS > 12) + if(doneNP) { + if(!doneN) lumaEndN = luminance(gSrc.SampleLevel(gSampler, posN.xy, 0).rgb); + if(!doneP) lumaEndP = luminance(gSrc.SampleLevel(gSampler, posP.xy, 0).rgb); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P12; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P12; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P12; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P12; +/*--------------------------------------------------------------------------*/ + } +#endif +/*--------------------------------------------------------------------------*/ + } +#endif +/*--------------------------------------------------------------------------*/ + } +#endif +/*--------------------------------------------------------------------------*/ + } +#endif +/*--------------------------------------------------------------------------*/ + } +#endif +/*--------------------------------------------------------------------------*/ + } +#endif +/*--------------------------------------------------------------------------*/ + } +#endif +/*--------------------------------------------------------------------------*/ + } +#endif +/*--------------------------------------------------------------------------*/ + } +#endif +/*--------------------------------------------------------------------------*/ + } +#endif +/*--------------------------------------------------------------------------*/ + } +/*--------------------------------------------------------------------------*/ + float dstN = posM.x - posN.x; + float dstP = posP.x - posM.x; + if (!horzSpan) + dstN = posM.y - posN.y; + if (!horzSpan) + dstP = posP.y - posM.y; +/*--------------------------------------------------------------------------*/ + bool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero; + float spanLength = (dstP + dstN); + bool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero; + float spanLengthRcp = 1.0 / spanLength; +/*--------------------------------------------------------------------------*/ + bool directionN = dstN < dstP; + float dst = min(dstN, dstP); + bool goodSpan = directionN ? goodSpanN : goodSpanP; + float subpixG = subpixF * subpixF; + float pixelOffset = (dst * (-spanLengthRcp)) + 0.5; + float subpixH = subpixG * qualitySubPix; +/*--------------------------------------------------------------------------*/ + float pixelOffsetGood = goodSpan ? pixelOffset : 0.0; + float pixelOffsetSubpix = max(pixelOffsetGood, subpixH); + if (!horzSpan) + posM.x += pixelOffsetSubpix * lengthSign; + if (horzSpan) + posM.y += pixelOffsetSubpix * lengthSign; + return float4(gSrc.SampleLevel(gSampler, posM, 0).xyz, lumaM); +} +/*==========================================================================*/ diff --git a/Framework/Source/Data/Effects/TAA.ps.slang b/Framework/Source/Data/Effects/TAA.ps.slang index 75dd46852..8be2e7984 100644 --- a/Framework/Source/Data/Effects/TAA.ps.slang +++ b/Framework/Source/Data/Effects/TAA.ps.slang @@ -1,5 +1,29 @@ /*************************************************************************** -Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of NVIDIA CORPORATION nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ #include "HostDeviceData.h" diff --git a/Framework/Source/Effects/FXAA/FXAA.cpp b/Framework/Source/Effects/FXAA/FXAA.cpp index a4ce82d38..5fc21af72 100644 --- a/Framework/Source/Effects/FXAA/FXAA.cpp +++ b/Framework/Source/Effects/FXAA/FXAA.cpp @@ -13,8 +13,10 @@ namespace Falcor { mpPass = FullScreenPass::create(kShaderFilename); mpGraphicsVars = GraphicsVars::create(mpPass->getProgram()->getReflector()); - mpPointSampler = Sampler::create({}); - mpGraphicsVars->setSampler("gSampler", mpPointSampler); + Sampler::Desc samplerDesc; + samplerDesc.setFilterMode(Sampler::Filter::Linear, Sampler::Filter::Linear, Sampler::Filter::Point); + mpLinearSampler = Sampler::create(samplerDesc); + mpGraphicsVars->setSampler("gSampler", mpLinearSampler); } FXAA::UniquePtr FXAA::create() @@ -37,6 +39,12 @@ namespace Falcor void FXAA::execute(RenderContext* pRenderContext, const Texture::SharedPtr& pSrcTex, const Fbo::SharedPtr& pDstFbo) { mpGraphicsVars->setTexture("gSrc", pSrcTex); + float2 rcpFrame = 1.0f / float2(pSrcTex->getWidth(), pSrcTex->getHeight()); + mpGraphicsVars->getDefaultBlock()["PerFrameCB"]["rcpTexDim"] = rcpFrame; + mpGraphicsVars->getDefaultBlock()["PerFrameCB"]["qualitySubPix"] = 0.75f; + mpGraphicsVars->getDefaultBlock()["PerFrameCB"]["qualityEdgeThreshold"] = 0.166f; + mpGraphicsVars->getDefaultBlock()["PerFrameCB"]["qualityEdgeThresholdMin"] = 0.0833f; + pRenderContext->pushGraphicsVars(mpGraphicsVars); pRenderContext->getGraphicsState()->pushFbo(pDstFbo); diff --git a/Framework/Source/Effects/FXAA/FXAA.h b/Framework/Source/Effects/FXAA/FXAA.h index 064c1ed95..566ccf279 100644 --- a/Framework/Source/Effects/FXAA/FXAA.h +++ b/Framework/Source/Effects/FXAA/FXAA.h @@ -65,6 +65,6 @@ namespace Falcor FullScreenPass::UniquePtr mpPass; GraphicsVars::SharedPtr mpGraphicsVars; - Sampler::SharedPtr mpPointSampler; + Sampler::SharedPtr mpLinearSampler; }; } \ No newline at end of file diff --git a/Framework/Source/Falcor.h b/Framework/Source/Falcor.h index 039677f22..b2e67de81 100644 --- a/Framework/Source/Falcor.h +++ b/Framework/Source/Falcor.h @@ -140,6 +140,7 @@ #include "Effects/AmbientOcclusion/SSAO.h" #include "Effects/ParticleSystem/ParticleSystem.h" #include "Effects/TAA/TAA.h" +#include "Effects/FXAA/FXAA.h" #ifdef FALCOR_DXR #include "Raytracing/RtModel.h" diff --git a/Samples/ForwardRenderer/ForwardRenderer.cpp b/Samples/ForwardRenderer/ForwardRenderer.cpp index 667676cf0..b41eeaf73 100644 --- a/Samples/ForwardRenderer/ForwardRenderer.cpp +++ b/Samples/ForwardRenderer/ForwardRenderer.cpp @@ -163,7 +163,7 @@ void ForwardRenderer::initScene(SampleCallbacks* pSample, Scene::SharedPtr pScen auto pTargetFbo = pSample->getCurrentFbo(); initShadowPass(pTargetFbo->getWidth(), pTargetFbo->getHeight()); initSSAO(); - initTAA(pSample); + initAA(pSample); mControls[EnableReflections].enabled = pScene->getLightProbeCount() > 0; applyLightingProgramControl(ControlID::EnableReflections); @@ -247,9 +247,10 @@ void ForwardRenderer::updateLightProbe(const LightProbe::SharedPtr& pLight) applyLightingProgramControl(ControlID::EnableReflections); } -void ForwardRenderer::initTAA(SampleCallbacks* pSample) +void ForwardRenderer::initAA(SampleCallbacks* pSample) { mTAA.pTAA = TemporalAA::create(); + mpFXAA = FXAA::create(); applyAaMode(pSample); } @@ -442,7 +443,7 @@ void ForwardRenderer::ambientOcclusion(RenderContext* pContext, Fbo::SharedPtr p PROFILE(ssao); if (mControls[EnableSSAO].enabled) { - Texture::SharedPtr pDepth = (mAAMode == AAMode::TAA) ? mpResolveFbo->getDepthStencilTexture() : mpResolveFbo->getColorTexture(2); + Texture::SharedPtr pDepth = (mAAMode == AAMode::MSAA) ? mpResolveFbo->getColorTexture(2) : mpResolveFbo->getDepthStencilTexture(); Texture::SharedPtr pAOMap = mSSAO.pSSAO->generateAOMap(pContext, mpSceneRenderer->getScene()->getActiveCamera().get(), pDepth, mpResolveFbo->getColorTexture(1)); mSSAO.pVars->setTexture("gColor", mpPostProcessFbo->getColorTexture(0)); mSSAO.pVars->setTexture("gAOMap", pAOMap); @@ -454,6 +455,16 @@ void ForwardRenderer::ambientOcclusion(RenderContext* pContext, Fbo::SharedPtr p } } +void ForwardRenderer::executeFXAA(RenderContext* pContext, Fbo::SharedPtr pTargetFbo) +{ + PROFILE(fxaa); + if(mAAMode == AAMode::FXAA) + { + pContext->blit(pTargetFbo->getColorTexture(0)->getSRV(), mpResolveFbo->getRenderTargetView(0)); + mpFXAA->execute(pContext, mpResolveFbo->getColorTexture(0), pTargetFbo); + } +} + void ForwardRenderer::onBeginTestFrame(SampleTest* pSampleTest) { // Already existing. Is this a problem? @@ -487,6 +498,7 @@ void ForwardRenderer::onFrameRender(SampleCallbacks* pSample, RenderContext::Sha postProcess(pRenderContext.get(), pPostProcessDst); runTAA(pRenderContext.get(), pPostProcessDst); // This will only run if we are in TAA mode ambientOcclusion(pRenderContext.get(), pTargetFbo); + executeFXAA(pRenderContext.get(), pTargetFbo); endFrame(pRenderContext.get()); } diff --git a/Samples/ForwardRenderer/ForwardRenderer.h b/Samples/ForwardRenderer/ForwardRenderer.h index 2119315e9..ca17883f6 100644 --- a/Samples/ForwardRenderer/ForwardRenderer.h +++ b/Samples/ForwardRenderer/ForwardRenderer.h @@ -125,6 +125,8 @@ class ForwardRenderer : public Renderer GraphicsVars::SharedPtr pVars; } mSSAO; + FXAA::UniquePtr mpFXAA; + void beginFrame(RenderContext* pContext, Fbo* pTargetFbo, uint64_t frameId); void endFrame(RenderContext* pContext); void depthPass(RenderContext* pContext); @@ -134,6 +136,7 @@ class ForwardRenderer : public Renderer //Need to resolve depth first to pass resolved depth to shadow pass void resolveDepthMSAA(RenderContext* pContext); void resolveMSAA(RenderContext* pContext); + void executeFXAA(RenderContext* pContext, Fbo::SharedPtr pTargetFbo); void runTAA(RenderContext* pContext, Fbo::SharedPtr pColorFbo); void postProcess(RenderContext* pContext, Fbo::SharedPtr pTargetFbo); void ambientOcclusion(RenderContext* pContext, Fbo::SharedPtr pTargetFbo); @@ -142,15 +145,14 @@ class ForwardRenderer : public Renderer void renderOpaqueObjects(RenderContext* pContext); void renderTransparentObjects(RenderContext* pContext); - - void initSkyBox(const std::string& name); + void initSkyBox(const std::string& name); void initPostProcess(); void initLightingPass(); void initDepthPass(); void initShadowPass(uint32_t windowWidth, uint32_t windowHeight); void initSSAO(); void updateLightProbe(const LightProbe::SharedPtr& pLight); - void initTAA(SampleCallbacks* pSample); + void initAA(SampleCallbacks* pSample); void initControls(); @@ -196,7 +198,8 @@ class ForwardRenderer : public Renderer enum class AAMode { MSAA, - TAA + TAA, + FXAA }; float mOpacityScale = 0.5f; diff --git a/Samples/ForwardRenderer/ForwardRendererControls.cpp b/Samples/ForwardRenderer/ForwardRendererControls.cpp index 823f1f98b..d60ff6f7c 100644 --- a/Samples/ForwardRenderer/ForwardRendererControls.cpp +++ b/Samples/ForwardRenderer/ForwardRendererControls.cpp @@ -38,7 +38,8 @@ Gui::DropdownList kSampleCountList = const Gui::DropdownList aaModeList = { { 0, "MSAA" }, - { 1, "TAA" } + { 1, "TAA" }, + { 2, "FXAA" } }; @@ -92,15 +93,26 @@ void ForwardRenderer::applyAaMode(SampleCallbacks* pSample) // Release the TAA FBOs mTAA.resetFbos(); - if (mAAMode == AAMode::MSAA) + if (mAAMode == AAMode::MSAA || mAAMode == AAMode::FXAA) { mLightingPass.pProgram->removeDefine("_OUTPUT_MOTION_VECTORS"); applyLightingProgramControl(SuperSampling); - fboDesc.setSampleCount(mMSAASampleCount); + fboDesc.setSampleCount(mAAMode == AAMode::MSAA ? mMSAASampleCount : 1); - Fbo::Desc resolveDesc; - resolveDesc.setColorTarget(0, ResourceFormat::RGBA32Float).setColorTarget(1, ResourceFormat::RGBA8Unorm).setColorTarget(2, ResourceFormat::R32Float); - mpResolveFbo = FboHelper::create2D(w, h, resolveDesc); + if(mAAMode == AAMode::MSAA) + { + Fbo::Desc resolveDesc; + resolveDesc.setColorTarget(0, ResourceFormat::RGBA32Float); + resolveDesc.setColorTarget(1, ResourceFormat::RGBA8Unorm).setColorTarget(2, ResourceFormat::R32Float); + mpResolveFbo = FboHelper::create2D(w, h, resolveDesc); + } + + if (mAAMode == AAMode::FXAA) + { + Fbo::Desc resolveDesc; + resolveDesc.setColorTarget(0, pSample->getCurrentFbo()->getColorTexture(0)->getFormat()); + mpResolveFbo = FboHelper::create2D(w, h, resolveDesc); + } } else if (mAAMode == AAMode::TAA) { @@ -117,7 +129,7 @@ void ForwardRenderer::applyAaMode(SampleCallbacks* pSample) mpDepthPassFbo = Fbo::create(); mpDepthPassFbo->attachDepthStencilTarget(mpMainFbo->getDepthStencilTexture()); - if (mAAMode == AAMode::TAA) + if (mAAMode != AAMode::MSAA) { mpResolveFbo = mpMainFbo; } @@ -230,7 +242,7 @@ void ForwardRenderer::onGuiRender(SampleCallbacks* pSample, Gui* pGui) applyLightingProgramControl(ControlID::SuperSampling); } } - + // Temporal Anti-Aliasing. if (mAAMode == AAMode::TAA) { From f65df73a05788921f89d1ca0d9c6634cad2fbf81 Mon Sep 17 00:00:00 2001 From: nbenty Date: Mon, 21 May 2018 12:59:29 -0700 Subject: [PATCH 04/18] Added FXAA GUI --- Framework/Source/Data/Effects/FXAA.slang | 3 ++- Framework/Source/Effects/FXAA/FXAA.cpp | 21 ++++++++++++++----- Framework/Source/Effects/FXAA/FXAA.h | 7 ++++++- .../ForwardRendererControls.cpp | 5 +++++ 4 files changed, 29 insertions(+), 7 deletions(-) diff --git a/Framework/Source/Data/Effects/FXAA.slang b/Framework/Source/Data/Effects/FXAA.slang index 8d155809d..6e7e19541 100644 --- a/Framework/Source/Data/Effects/FXAA.slang +++ b/Framework/Source/Data/Effects/FXAA.slang @@ -243,6 +243,7 @@ cbuffer PerFrameCB float qualitySubPix; float qualityEdgeThreshold; float qualityEdgeThresholdMin; + bool earlyOut; }; SamplerState gSampler; @@ -272,7 +273,7 @@ float4 main(float2 texC : TEXCOORD) : SV_TARGET float rangeMaxClamped = max(qualityEdgeThresholdMin, rangeMaxScaled); bool earlyExit = range < rangeMaxClamped; - if (earlyExit) + if (earlyOut && earlyExit) return color; float lumaNW = luminance(gSrc.SampleLevel(gSampler, posM, 0, int2(-1, -1)).rgb); diff --git a/Framework/Source/Effects/FXAA/FXAA.cpp b/Framework/Source/Effects/FXAA/FXAA.cpp index d2ab5bf0d..6838ca283 100644 --- a/Framework/Source/Effects/FXAA/FXAA.cpp +++ b/Framework/Source/Effects/FXAA/FXAA.cpp @@ -32,18 +32,29 @@ namespace Falcor } } - void FXAA::renderUI(Gui* pGui) + void FXAA::renderUI(Gui* pGui, const char* uiGroup) { + if (!uiGroup || pGui->beginGroup(uiGroup)) + { + pGui->addFloatVar("Sub-Pixel Quality", mQualitySubPix, 0, 1); + pGui->addFloatVar("Edge Threshold", mQualityEdgeThreshold, 0, 1); + pGui->addFloatVar("Edge Threhold Min", mQualityEdgeThresholdMin, 0, 1); + pGui->addCheckBox("Early out", mEarlyOut); + if (uiGroup) pGui->endGroup(); + } } void FXAA::execute(RenderContext* pRenderContext, const Texture::SharedPtr& pSrcTex, const Fbo::SharedPtr& pDstFbo) { mpGraphicsVars->setTexture("gSrc", pSrcTex); float2 rcpFrame = 1.0f / float2(pSrcTex->getWidth(), pSrcTex->getHeight()); - mpGraphicsVars->getDefaultBlock()["PerFrameCB"]["rcpTexDim"] = rcpFrame; - mpGraphicsVars->getDefaultBlock()["PerFrameCB"]["qualitySubPix"] = 0.75f; - mpGraphicsVars->getDefaultBlock()["PerFrameCB"]["qualityEdgeThreshold"] = 0.166f; - mpGraphicsVars->getDefaultBlock()["PerFrameCB"]["qualityEdgeThresholdMin"] = 0.0833f; + auto& pCB = mpGraphicsVars->getDefaultBlock()["PerFrameCB"]; + pCB["rcpTexDim"] = rcpFrame; + pCB["qualitySubPix"] = mQualitySubPix; + pCB["qualityEdgeThreshold"] = mQualityEdgeThreshold; + pCB["qualityEdgeThresholdMin"] = mQualityEdgeThresholdMin; + pCB["earlyOut"] = mEarlyOut; + mpGraphicsVars->setSampler("gSampler", mpLinearSampler); pRenderContext->pushGraphicsVars(mpGraphicsVars); diff --git a/Framework/Source/Effects/FXAA/FXAA.h b/Framework/Source/Effects/FXAA/FXAA.h index 566ccf279..c145ec959 100644 --- a/Framework/Source/Effects/FXAA/FXAA.h +++ b/Framework/Source/Effects/FXAA/FXAA.h @@ -50,7 +50,7 @@ namespace Falcor /** Render UI controls for this effect. \param[in] pGui GUI object to render UI elements with */ - void renderUI(Gui* pGui); + void renderUI(Gui* pGui, const char* uiGroup); /** Run the effect \param[in] pRenderContext Render context with the destination FBO already set @@ -66,5 +66,10 @@ namespace Falcor FullScreenPass::UniquePtr mpPass; GraphicsVars::SharedPtr mpGraphicsVars; Sampler::SharedPtr mpLinearSampler; + + float mQualitySubPix = 0.75f; + float mQualityEdgeThreshold = 0.166f; + float mQualityEdgeThresholdMin = 0.0833f; + bool mEarlyOut = true; }; } \ No newline at end of file diff --git a/Samples/ForwardRenderer/ForwardRendererControls.cpp b/Samples/ForwardRenderer/ForwardRendererControls.cpp index d60ff6f7c..2ad4e3785 100644 --- a/Samples/ForwardRenderer/ForwardRendererControls.cpp +++ b/Samples/ForwardRenderer/ForwardRendererControls.cpp @@ -262,6 +262,11 @@ void ForwardRenderer::onGuiRender(SampleCallbacks* pSample, Gui* pGui) } } + if (mAAMode == AAMode::FXAA) + { + mpFXAA->renderUI(pGui, "FXAA"); + } + if (reapply) applyAaMode(pSample); pGui->endGroup(); From 1d332d9c465575ec49ae33bcebfcc5f153b77edc Mon Sep 17 00:00:00 2001 From: Kai-Hwa Yao Date: Mon, 21 May 2018 16:00:22 -0700 Subject: [PATCH 05/18] Reset Vulkan query pool before using it for timestamps. Fixes negative profiler timings in release builds --- Framework/Source/API/Vulkan/VKGpuTimer.cpp | 3 +- Framework/Source/Utils/Profiler.cpp | 124 ++++++++++----------- 2 files changed, 64 insertions(+), 63 deletions(-) diff --git a/Framework/Source/API/Vulkan/VKGpuTimer.cpp b/Framework/Source/API/Vulkan/VKGpuTimer.cpp index a574d3597..146eaf379 100644 --- a/Framework/Source/API/Vulkan/VKGpuTimer.cpp +++ b/Framework/Source/API/Vulkan/VKGpuTimer.cpp @@ -33,6 +33,7 @@ namespace Falcor { void GpuTimer::apiBegin() { + vkCmdResetQueryPool(mpLowLevelData->getCommandList(), mpHeap, mStart, 2); vkCmdWriteTimestamp(mpLowLevelData->getCommandList(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, mpHeap, mStart); } @@ -43,6 +44,6 @@ namespace Falcor void GpuTimer::apiResolve(uint64_t result[2]) { - vk_call(vkGetQueryPoolResults(gpDevice->getApiHandle(), mpHeap, mStart, 2, sizeof(uint64_t)*2, result, sizeof(result[0]), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT)); + vk_call(vkGetQueryPoolResults(gpDevice->getApiHandle(), mpHeap, mStart, 2, sizeof(uint64_t) * 2, result, sizeof(result[0]), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT)); } } diff --git a/Framework/Source/Utils/Profiler.cpp b/Framework/Source/Utils/Profiler.cpp index dae02e13b..0f96d8dff 100644 --- a/Framework/Source/Utils/Profiler.cpp +++ b/Framework/Source/Utils/Profiler.cpp @@ -43,45 +43,45 @@ namespace Falcor uint32_t Profiler::sCurrentLevel = 0; uint32_t Profiler::sGpuTimerIndex = 0; std::vector Profiler::sProfilerVector; - + std::hash HashedString::hashFunc; - void Profiler::initNewEvent(EventData *pEvent, const HashedString& name) + void Profiler::initNewEvent(EventData *pEvent, const HashedString& name) { - pEvent->name = name.str; + pEvent->name = name.str; pEvent->level = sCurrentLevel; - sProfilerEvents[name.hash] = pEvent; + sProfilerEvents[name.hash] = pEvent; sProfilerVector.push_back(pEvent); - } + } Profiler::EventData* Profiler::createNewEvent(const HashedString& name) { EventData *pData = new EventData; - initNewEvent(pData, name); + initNewEvent(pData, name); return pData; } Profiler::EventData* Profiler::isEventRegistered(const HashedString& name) - { + { auto event = sProfilerEvents.find(name.hash); - if(event == sProfilerEvents.end()) - { - return nullptr; - } - else - { - return event->second; - } - } + if (event == sProfilerEvents.end()) + { + return nullptr; + } + else + { + return event->second; + } + } Profiler::EventData* Profiler::getEvent(const HashedString& name) { auto event = isEventRegistered(name); - if(event) - { - return event; - } - else + if (event) + { + return event; + } + else { return createNewEvent(name); } @@ -101,7 +101,7 @@ namespace Falcor sCurrentLevel++; } - void Profiler::endEvent(const HashedString& name, EventData* pData) + void Profiler::endEvent(const HashedString& name, EventData* pData) { pData->cpuEnd = CpuTimer::getCurrentTimePoint(); pData->cpuTotal += CpuTimer::calcDuration(pData->cpuStart, pData->cpuEnd); @@ -116,10 +116,10 @@ namespace Falcor { profileResults = "Name\t\t\tCPU time(ms)\t\t\tGPU time(ms)\n"; - for (EventData* pData : sProfilerVector) - { + for (EventData* pData : sProfilerVector) + { double gpuTime = 0; - for(size_t i = 0 ; i < pData->frameData[1 - sGpuTimerIndex].currentTimer ; i++) + for (size_t i = 0; i < pData->frameData[1 - sGpuTimerIndex].currentTimer; i++) { gpuTime += pData->frameData[1 - sGpuTimerIndex].pTimers[i]->getElapsedTime(); } @@ -127,30 +127,30 @@ namespace Falcor pData->frameData[1 - sGpuTimerIndex].currentTimer = 0; assert(pData->callStack.empty()); - char event[1000]; - uint32_t nameIndent = pData->level * 2 + 1; - uint32_t cpuIndent = 32 - (nameIndent + (uint32_t)pData->name.size()); - std::snprintf(event, 1000, "%*s%s %*.3f %36.3f\n", nameIndent, " ", pData->name.c_str(), cpuIndent, pData->cpuTotal, gpuTime); + char event[1000]; + uint32_t nameIndent = pData->level * 2 + 1; + uint32_t cpuIndent = 32 - (nameIndent + (uint32_t)pData->name.size()); + std::snprintf(event, 1000, "%*s%s %*.3f %36.3f\n", nameIndent, " ", pData->name.c_str(), cpuIndent, pData->cpuTotal, gpuTime); #if _PROFILING_LOG == 1 - pData->cpuMs[pData->stepNr] = pData->cpuTotal; - pData->gpuMs[pData->stepNr] = (float)gpuTime; - pData->stepNr++; - if (pData->stepNr == _PROFILING_LOG_BATCH_SIZE) - { - std::ostringstream logOss, fileOss; - logOss << "dumping " << "profile_" << pData->name << "_" << pData->filesWritten; - logInfo(logOss.str()); - fileOss << "profile_" << pData->name << "_" << pData->filesWritten++; - std::ofstream out(fileOss.str().c_str()); - for (int i = 0; i < _PROFILING_LOG_BATCH_SIZE; ++i) - { - out << pData->cpuMs[i] << " " << pData->gpuMs[i] << "\n"; - } - pData->stepNr = 0; - } + pData->cpuMs[pData->stepNr] = pData->cpuTotal; + pData->gpuMs[pData->stepNr] = (float)gpuTime; + pData->stepNr++; + if (pData->stepNr == _PROFILING_LOG_BATCH_SIZE) + { + std::ostringstream logOss, fileOss; + logOss << "dumping " << "profile_" << pData->name << "_" << pData->filesWritten; + logInfo(logOss.str()); + fileOss << "profile_" << pData->name << "_" << pData->filesWritten++; + std::ofstream out(fileOss.str().c_str()); + for (int i = 0; i < _PROFILING_LOG_BATCH_SIZE; ++i) + { + out << pData->cpuMs[i] << " " << pData->gpuMs[i] << "\n"; + } + pData->stepNr = 0; + } #endif pData->cpuTotal = 0; - pData->gpuTotal = 0; + pData->gpuTotal = 0; profileResults += event; } @@ -158,21 +158,21 @@ namespace Falcor } #if _PROFILING_LOG == 1 - void Profiler::flushLog() { - for (EventData* pData : sProfilerVector) - { - std::ostringstream logOss, fileOss; - logOss << "dumping " << "profile_" << pData->name << "_" << pData->filesWritten; - logInfo(logOss.str()); - fileOss << "profile_" << pData->name << "_" << pData->filesWritten++; - std::ofstream out(fileOss.str().c_str()); - for (int i = 0; i < pData->stepNr; ++i) - { - out << pData->cpuMs[i] << " " << pData->gpuMs[i] << "\n"; - } - pData->stepNr = 0; - } - } + void Profiler::flushLog() { + for (EventData* pData : sProfilerVector) + { + std::ostringstream logOss, fileOss; + logOss << "dumping " << "profile_" << pData->name << "_" << pData->filesWritten; + logInfo(logOss.str()); + fileOss << "profile_" << pData->name << "_" << pData->filesWritten++; + std::ofstream out(fileOss.str().c_str()); + for (int i = 0; i < pData->stepNr; ++i) + { + out << pData->cpuMs[i] << " " << pData->gpuMs[i] << "\n"; + } + pData->stepNr = 0; + } + } #endif void Profiler::clearEvents() @@ -186,4 +186,4 @@ namespace Falcor sCurrentLevel = 0; sGpuTimerIndex = 0; } -} \ No newline at end of file +} From 8dd9dc8da3418ebeb52dd29e5196e01eab3f1556 Mon Sep 17 00:00:00 2001 From: Kai-Hwa Yao Date: Mon, 21 May 2018 17:38:20 -0700 Subject: [PATCH 06/18] Added FXAA to Makefile --- Framework/Source/Effects/FXAA/FXAA.cpp | 2 +- Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Framework/Source/Effects/FXAA/FXAA.cpp b/Framework/Source/Effects/FXAA/FXAA.cpp index 6838ca283..18dd6d628 100644 --- a/Framework/Source/Effects/FXAA/FXAA.cpp +++ b/Framework/Source/Effects/FXAA/FXAA.cpp @@ -48,7 +48,7 @@ namespace Falcor { mpGraphicsVars->setTexture("gSrc", pSrcTex); float2 rcpFrame = 1.0f / float2(pSrcTex->getWidth(), pSrcTex->getHeight()); - auto& pCB = mpGraphicsVars->getDefaultBlock()["PerFrameCB"]; + auto pCB = mpGraphicsVars->getDefaultBlock()["PerFrameCB"]; pCB["rcpTexDim"] = rcpFrame; pCB["qualitySubPix"] = mQualitySubPix; pCB["qualityEdgeThreshold"] = mQualityEdgeThreshold; diff --git a/Makefile b/Makefile index 4c9d28f9a..cbb6ceeca 100644 --- a/Makefile +++ b/Makefile @@ -101,7 +101,7 @@ SOURCE_DIR:=Framework/Source/ # All directories containing source code relative from the base Source folder. The "/" in the first line is to include the base Source directory RELATIVE_DIRS:=/ \ API/ API/LowLevel/ API/Vulkan/ API/Vulkan/LowLevel/ \ -Effects/AmbientOcclusion/ Effects/NormalMap/ Effects/ParticleSystem/ Effects/Shadows/ Effects/SkyBox/ Effects/TAA/ Effects/ToneMapping/ Effects/Utils/ \ +Effects/AmbientOcclusion/ Effects/FXAA/ Effects/NormalMap/ Effects/ParticleSystem/ Effects/Shadows/ Effects/SkyBox/ Effects/TAA/ Effects/ToneMapping/ Effects/Utils/ \ Graphics/ Graphics/Camera/ Graphics/Material/ Graphics/Model/ Graphics/Model/Loaders/ Graphics/Paths/ Graphics/Program/ Graphics/Scene/ Graphics/Scene/Editor/ \ Utils/ Utils/Math/ Utils/Picking/ Utils/Psychophysics/ Utils/Platform/ Utils/Platform/Linux/ Utils/Video/ \ VR/ VR/OpenVR/ \ From a6c5184d82f6c20e17afa07b38ecafa663daee56 Mon Sep 17 00:00:00 2001 From: nbenty Date: Tue, 22 May 2018 09:07:08 -0700 Subject: [PATCH 07/18] First version is working. The sample positions are part of the FBO, but I'm not sure about the interface yet --- .../Source/API/D3D12/D3D12RenderContext.cpp | 20 +++++++++++++++- .../LowLevel/D3D12LowLevelContextData.cpp | 16 +++++++++++-- Framework/Source/API/FBO.cpp | 17 +++++++++++++ Framework/Source/API/FBO.h | 24 +++++++++++++++++++ Framework/Source/API/RenderContext.h | 1 + 5 files changed, 75 insertions(+), 3 deletions(-) diff --git a/Framework/Source/API/D3D12/D3D12RenderContext.cpp b/Framework/Source/API/D3D12/D3D12RenderContext.cpp index 5eab6aa19..097e20107 100644 --- a/Framework/Source/API/D3D12/D3D12RenderContext.cpp +++ b/Framework/Source/API/D3D12/D3D12RenderContext.cpp @@ -188,8 +188,26 @@ namespace Falcor } } } + ID3D12GraphicsCommandList* pCmdList = pCtx->getLowLevelData()->getCommandList().GetInterfacePtr(); + pCmdList->OMSetRenderTargets(colorTargets, pRTV.data(), FALSE, &pDSV); - pCtx->getLowLevelData()->getCommandList()->OMSetRenderTargets(colorTargets, pRTV.data(), FALSE, &pDSV); + ID3D12GraphicsCommandList1* pList1; + pCmdList->QueryInterface(IID_PPV_ARGS(&pList1)); + const auto& samplePos = pFbo->getSamplePositions(); + if (!pList1) + { + if(samplePos.size()) + { + logError("The FBO specifies programmable sample positions, but the hardware doesn't support it"); + } + } + else + { + static_assert(offsetof(Fbo::SamplePosition, xOffset) == offsetof(D3D12_SAMPLE_POSITION, X), "SamplePosition.X"); + static_assert(offsetof(Fbo::SamplePosition, yOffset) == offsetof(D3D12_SAMPLE_POSITION, Y), "SamplePosition.Y"); + uint32_t sampleCount = samplePos.size() ? pFbo->getSampleCount() : 0; + pList1->SetSamplePositions(sampleCount, pFbo->getSamplePositionsPixelCount(), (D3D12_SAMPLE_POSITION*)samplePos.data()); + } } static void D3D12SetViewports(ID3D12GraphicsCommandList* pList, const GraphicsState::Viewport* vp) diff --git a/Framework/Source/API/D3D12/LowLevel/D3D12LowLevelContextData.cpp b/Framework/Source/API/D3D12/LowLevel/D3D12LowLevelContextData.cpp index e3ab901fd..224de3b26 100644 --- a/Framework/Source/API/D3D12/LowLevel/D3D12LowLevelContextData.cpp +++ b/Framework/Source/API/D3D12/LowLevel/D3D12LowLevelContextData.cpp @@ -44,6 +44,14 @@ namespace Falcor return pAllocator; } + template + ApiType createCommandList(ID3D12Device* pDevice, D3D12_COMMAND_LIST_TYPE type, CommandAllocatorHandle allocator) + { + ApiType pList; + HRESULT hr = pDevice->CreateCommandList(0, type, allocator, nullptr, IID_PPV_ARGS(&pList)); + return (FAILED(hr)) ? nullptr : pList; + } + LowLevelContextData::SharedPtr LowLevelContextData::create(CommandQueueType type, CommandQueueHandle queue) { SharedPtr pThis = SharedPtr(new LowLevelContextData); @@ -69,9 +77,13 @@ namespace Falcor } pThis->mpAllocator = pThis->mpApiData->pAllocatorPool->newObject(); - // Create a command list + // Create a command list. Try to create the latest version the device supports ID3D12Device* pDevice = gpDevice->getApiHandle().GetInterfacePtr(); - if (FAILED(pDevice->CreateCommandList(0, cmdListType, pThis->mpAllocator, nullptr, IID_PPV_ARGS(&pThis->mpList)))) + pThis->mpList = createCommandList(pDevice, cmdListType, pThis->mpAllocator); + if(!pThis->mpList) createCommandList(pDevice, cmdListType, pThis->mpAllocator); + if (!pThis->mpList) createCommandList(pDevice, cmdListType, pThis->mpAllocator); + + if (pThis->mpList == nullptr) { logError("Failed to create command list for LowLevelContextData"); return nullptr; diff --git a/Framework/Source/API/FBO.cpp b/Framework/Source/API/FBO.cpp index 95d35c42b..b0de08480 100644 --- a/Framework/Source/API/FBO.cpp +++ b/Framework/Source/API/FBO.cpp @@ -272,6 +272,17 @@ namespace Falcor // Check depth if (verifyAttachment(mDepthStencil) == false) return false; + // In case there are sample positions, make sure they are valid + if (mSamplePositions.size()) + { + uint32_t expectedCount = mSamplePositionsPixelCount * mTempDesc.getSampleCount(); + if (expectedCount != mSamplePositions.size()) + { + logError("Error when validating FBO. The sample-positions array-size has the wrong size.\n"); + return false; + } + } + // Insert the attachment into the static array and initialize the address mpDesc = &(*(sDescs.insert(mTempDesc).first)); @@ -303,4 +314,10 @@ namespace Falcor } return true; } + + void Fbo::setSamplePositions(uint32_t numPixels, const SamplePosition positions[], uint32_t count) + { + mSamplePositions = std::vector(positions, positions + count); + mSamplePositionsPixelCount = numPixels; + } } \ No newline at end of file diff --git a/Framework/Source/API/FBO.h b/Framework/Source/API/FBO.h index dc2af8ec9..a6c17fbc7 100644 --- a/Framework/Source/API/FBO.h +++ b/Framework/Source/API/FBO.h @@ -190,6 +190,27 @@ namespace Falcor */ RenderTargetView::SharedPtr getRenderTargetView(uint32_t rtIndex) const; + + struct SamplePosition + { + int8 xOffset = 0; + int8 yOffset = 0; + }; + + /** Configure the sample positions used by multi-sampled buffers. + The size of the positions array should be samplesPerPixel*numPixels + To reset the positions to their original location pass nullptr for positions + */ + void setSamplePositions(uint32_t numPixels, const SamplePosition positions[], uint32_t count); + + /** Get the sample positions + */ + const std::vector getSamplePositions() const { return mSamplePositions; } + + /** Get the number of pixels the sample positions are configured for + */ + uint32_t getSamplePositionsPixelCount() const { return mSamplePositionsPixelCount; } + struct Attachment { Texture::SharedPtr pTexture = nullptr; @@ -215,6 +236,9 @@ namespace Falcor Fbo(); std::vector mColorAttachments; + std::vector mSamplePositions; + uint32_t mSamplePositionsPixelCount = 0; + Attachment mDepthStencil; mutable Desc mTempDesc; diff --git a/Framework/Source/API/RenderContext.h b/Framework/Source/API/RenderContext.h index 5a3dfa81e..8b022d5c7 100644 --- a/Framework/Source/API/RenderContext.h +++ b/Framework/Source/API/RenderContext.h @@ -193,6 +193,7 @@ namespace Falcor */ void raytrace(std::shared_ptr pVars, std::shared_ptr pState, uint32_t width, uint32_t height); #endif + private: RenderContext(); GraphicsVars::SharedPtr mpGraphicsVars; From 43f6e48f5970fb09a8da50973a32022494b0eb3e Mon Sep 17 00:00:00 2001 From: nbenty Date: Tue, 22 May 2018 10:21:36 -0700 Subject: [PATCH 08/18] Cleaned the API --- .../Source/API/D3D12/D3D12RenderContext.cpp | 24 +++++++++++++++---- Framework/Source/API/FBO.cpp | 14 ++++++++--- Framework/Source/API/FBO.h | 8 ++++--- Framework/Source/API/RenderContext.h | 1 + 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/Framework/Source/API/D3D12/D3D12RenderContext.cpp b/Framework/Source/API/D3D12/D3D12RenderContext.cpp index 097e20107..3caaac495 100644 --- a/Framework/Source/API/D3D12/D3D12RenderContext.cpp +++ b/Framework/Source/API/D3D12/D3D12RenderContext.cpp @@ -190,13 +190,18 @@ namespace Falcor } ID3D12GraphicsCommandList* pCmdList = pCtx->getLowLevelData()->getCommandList().GetInterfacePtr(); pCmdList->OMSetRenderTargets(colorTargets, pRTV.data(), FALSE, &pDSV); + } + static void D3D12SetSamplePositions(ID3D12GraphicsCommandList* pList, const Fbo* pFbo) + { + if (!pFbo) return; ID3D12GraphicsCommandList1* pList1; - pCmdList->QueryInterface(IID_PPV_ARGS(&pList1)); + pList->QueryInterface(IID_PPV_ARGS(&pList1)); const auto& samplePos = pFbo->getSamplePositions(); + if (!pList1) { - if(samplePos.size()) + if (samplePos.size()) { logError("The FBO specifies programmable sample positions, but the hardware doesn't support it"); } @@ -205,8 +210,15 @@ namespace Falcor { static_assert(offsetof(Fbo::SamplePosition, xOffset) == offsetof(D3D12_SAMPLE_POSITION, X), "SamplePosition.X"); static_assert(offsetof(Fbo::SamplePosition, yOffset) == offsetof(D3D12_SAMPLE_POSITION, Y), "SamplePosition.Y"); - uint32_t sampleCount = samplePos.size() ? pFbo->getSampleCount() : 0; - pList1->SetSamplePositions(sampleCount, pFbo->getSamplePositionsPixelCount(), (D3D12_SAMPLE_POSITION*)samplePos.data()); + + if (samplePos.size()) + { + pList1->SetSamplePositions(pFbo->getSampleCount(), pFbo->getSamplePositionsPixelCount(), (D3D12_SAMPLE_POSITION*)samplePos.data()); + } + else + { + pList1->SetSamplePositions(0, 0, nullptr); + } } } @@ -276,6 +288,10 @@ namespace Falcor { D3D12SetFbo(this, mpGraphicsState->getFbo().get()); } + if (is_set(StateBindFlags::SamplePositions, mBindFlags)) + { + D3D12SetSamplePositions(pList, mpGraphicsState->getFbo().get()); + } if (is_set(StateBindFlags::Viewports, mBindFlags)) { D3D12SetViewports(pList, &mpGraphicsState->getViewport(0)); diff --git a/Framework/Source/API/FBO.cpp b/Framework/Source/API/FBO.cpp index b0de08480..2af6c7868 100644 --- a/Framework/Source/API/FBO.cpp +++ b/Framework/Source/API/FBO.cpp @@ -315,9 +315,17 @@ namespace Falcor return true; } - void Fbo::setSamplePositions(uint32_t numPixels, const SamplePosition positions[], uint32_t count) + void Fbo::setSamplePositions(uint32_t samplesPerPixel, uint32_t pixelCount, const SamplePosition positions[]) { - mSamplePositions = std::vector(positions, positions + count); - mSamplePositionsPixelCount = numPixels; + if (positions) + { + mSamplePositions = std::vector(positions, positions + (samplesPerPixel * pixelCount)); + mSamplePositionsPixelCount = pixelCount; + } + else + { + mSamplePositionsPixelCount = 0; + mSamplePositions.clear(); + } } } \ No newline at end of file diff --git a/Framework/Source/API/FBO.h b/Framework/Source/API/FBO.h index a6c17fbc7..b67f73b69 100644 --- a/Framework/Source/API/FBO.h +++ b/Framework/Source/API/FBO.h @@ -198,10 +198,12 @@ namespace Falcor }; /** Configure the sample positions used by multi-sampled buffers. - The size of the positions array should be samplesPerPixel*numPixels - To reset the positions to their original location pass nullptr for positions + \param[in] samplesPerPixel The number of samples-per-pixel. This value has to match the FBO's sample count + \param[in] pixelCount the number if pixels the sample pattern is specified for + \param[in] positions The sample positions. (0,0) is a pixel's center. The size of this array should be samplesPerPixel*pixelCount + To reset the positions to their original location pass `nullptr` for positions */ - void setSamplePositions(uint32_t numPixels, const SamplePosition positions[], uint32_t count); + void setSamplePositions(uint32_t samplesPerPixel, uint32_t pixelCount, const SamplePosition positions[]); /** Get the sample positions */ diff --git a/Framework/Source/API/RenderContext.h b/Framework/Source/API/RenderContext.h index 8b022d5c7..5092fd68f 100644 --- a/Framework/Source/API/RenderContext.h +++ b/Framework/Source/API/RenderContext.h @@ -66,6 +66,7 @@ namespace Falcor Viewports = 0x10, /// Date: Tue, 22 May 2018 10:30:41 -0700 Subject: [PATCH 09/18] Added a warning message to the VK backend in case programmable sample positions are used --- Framework/Source/API/D3D12/D3D12RenderContext.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Framework/Source/API/D3D12/D3D12RenderContext.cpp b/Framework/Source/API/D3D12/D3D12RenderContext.cpp index 3caaac495..8c1ea5c86 100644 --- a/Framework/Source/API/D3D12/D3D12RenderContext.cpp +++ b/Framework/Source/API/D3D12/D3D12RenderContext.cpp @@ -304,6 +304,13 @@ namespace Falcor { pList->SetPipelineState(mpGraphicsState->getGSO(mpGraphicsVars.get())->getApiHandle()); } + if (is_set(StateBindFlags::SamplePositions, mBindFlags)) + { + if (mpGraphicsState->getFbo() && mpGraphicsState->getFbo()->getSamplePositions().size()) + { + logWarning("The Vulkan backend doesn't support programmable sample positions"); + } + } BlendState::SharedPtr blendState = mpGraphicsState->getBlendState(); if (blendState != nullptr) From 15c44584949fc83459195d73f1ffa97ad3f186a4 Mon Sep 17 00:00:00 2001 From: nbenty Date: Tue, 22 May 2018 10:33:24 -0700 Subject: [PATCH 10/18] CHANGELOG --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 984308484..54a93f154 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +v3.0.3 +------ +- Added FXAA as an effect +- Support programmable sample position - `Fbo::setSamplePositions()` (DX only) + +v3.0.2 +------ +- Various bug fixes +- Fixed Vulkan error spam seen when running Falcor's included samples +- Updated API abstraction interfaces to return const-ref where applicable +- Fixed crash when handling mouse/keyboard messages after the renderer has shut down + v3.0.1 ------ - Added RenderContext::StateBindFlags, which allows the user to control which part of the `GraphicsState` will be bound to the pipeline From 43ac65a137b4ff872861d41e3e80ec44a67d4429 Mon Sep 17 00:00:00 2001 From: nbenty Date: Tue, 22 May 2018 11:49:49 -0700 Subject: [PATCH 11/18] Added RenderContext::resolveResource() function and RenderContext::resolveSubresource() functions --- .../Source/API/D3D12/D3D12RenderContext.cpp | 27 +++++++++++++++++++ .../LowLevel/D3D12LowLevelContextData.cpp | 2 ++ Framework/Source/API/RenderContext.cpp | 1 + Framework/Source/API/RenderContext.h | 9 +++++++ Framework/Source/API/Vulkan/VKCopyContext.cpp | 12 ++++----- .../Source/API/Vulkan/VKRenderContext.cpp | 23 +++++++++++++++- Samples/ForwardRenderer/ForwardRenderer.cpp | 6 ++--- 7 files changed, 69 insertions(+), 11 deletions(-) diff --git a/Framework/Source/API/D3D12/D3D12RenderContext.cpp b/Framework/Source/API/D3D12/D3D12RenderContext.cpp index 8c1ea5c86..88f3ecb1a 100644 --- a/Framework/Source/API/D3D12/D3D12RenderContext.cpp +++ b/Framework/Source/API/D3D12/D3D12RenderContext.cpp @@ -460,4 +460,31 @@ namespace Falcor popGraphicsState(); popGraphicsVars(); } + + void RenderContext::resolveSubresource(const Texture* pSrc, uint32_t srcSubresource, const Texture* pDst, uint32_t dstSubresource) + { + DXGI_FORMAT format = getDxgiFormat(pDst->getFormat()); + mpLowLevelData->getCommandList()->ResolveSubresource(pDst->getApiHandle(), dstSubresource, pSrc->getApiHandle(), srcSubresource, format); + mCommandsPending = true; + } + + void RenderContext::resolveResource(const Texture* pSrc, const Texture* pDst) + { + bool match = true; + match = match && (pSrc->getMipCount() == pDst->getMipCount()); + match = match && (pSrc->getArraySize() == pDst->getArraySize()); + if (!match) + { + logWarning("Can't resolve a resource. The src and dst textures have a different array-size or mip-count"); + } + + resourceBarrier(pSrc, Resource::State::ResolveSource); + resourceBarrier(pDst, Resource::State::ResolveDest); + + uint32_t subresourceCount = pSrc->getMipCount() * pSrc->getArraySize(); + for (uint32_t s = 0; s < subresourceCount; s++) + { + resolveSubresource(pSrc, s, pDst, s); + } + } } diff --git a/Framework/Source/API/D3D12/LowLevel/D3D12LowLevelContextData.cpp b/Framework/Source/API/D3D12/LowLevel/D3D12LowLevelContextData.cpp index 224de3b26..ef18437af 100644 --- a/Framework/Source/API/D3D12/LowLevel/D3D12LowLevelContextData.cpp +++ b/Framework/Source/API/D3D12/LowLevel/D3D12LowLevelContextData.cpp @@ -79,7 +79,9 @@ namespace Falcor // Create a command list. Try to create the latest version the device supports ID3D12Device* pDevice = gpDevice->getApiHandle().GetInterfacePtr(); +#ifdef FALCOR_DXR pThis->mpList = createCommandList(pDevice, cmdListType, pThis->mpAllocator); +#endif if(!pThis->mpList) createCommandList(pDevice, cmdListType, pThis->mpAllocator); if (!pThis->mpList) createCommandList(pDevice, cmdListType, pThis->mpAllocator); diff --git a/Framework/Source/API/RenderContext.cpp b/Framework/Source/API/RenderContext.cpp index 4adb822bc..6d88873f6 100644 --- a/Framework/Source/API/RenderContext.cpp +++ b/Framework/Source/API/RenderContext.cpp @@ -125,3 +125,4 @@ namespace Falcor mBindGraphicsRootSig = true; } } + diff --git a/Framework/Source/API/RenderContext.h b/Framework/Source/API/RenderContext.h index 5092fd68f..f03ad3190 100644 --- a/Framework/Source/API/RenderContext.h +++ b/Framework/Source/API/RenderContext.h @@ -189,6 +189,15 @@ namespace Falcor */ void setBindFlags(StateBindFlags flags) { mBindFlags = flags; } + /** Resolve an entire multi-sampled resource. The dst and src resources must have the same dimensions, array-size, mip-count and format. + If any of these properties don't match, you'll have to use `resolveSubresource` + */ + void resolveResource(const Texture* pSrc, const Texture* pDst); + + /** Resolve a multi-sampled sub-resource + */ + void resolveSubresource(const Texture* pSrc, uint32_t srcSubresource, const Texture* pDst, uint32_t dstSubresource); + #ifdef FALCOR_DXR /** Submit a raytrace command. This function doesn't change the state of the render-context. Graphics/compute vars and state will stay the same */ diff --git a/Framework/Source/API/Vulkan/VKCopyContext.cpp b/Framework/Source/API/Vulkan/VKCopyContext.cpp index 691501cd9..7690cf09b 100644 --- a/Framework/Source/API/Vulkan/VKCopyContext.cpp +++ b/Framework/Source/API/Vulkan/VKCopyContext.cpp @@ -64,7 +64,7 @@ namespace Falcor return size; } - static VkImageLayout getImageLayout(Resource::State state) + VkImageLayout getImageLayout(Resource::State state) { switch (state) { @@ -76,15 +76,15 @@ namespace Falcor case Resource::State::UnorderedAccess: return VK_IMAGE_LAYOUT_GENERAL; case Resource::State::RenderTarget: - case Resource::State::ResolveDest: return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; case Resource::State::DepthStencil: return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; case Resource::State::ShaderResource: - case Resource::State::ResolveSource: return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + case Resource::State::ResolveDest: case Resource::State::CopyDest: return VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + case Resource::State::ResolveSource: case Resource::State::CopySource: return VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; break; @@ -121,14 +121,12 @@ namespace Falcor return VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; case Resource::State::IndirectArg: return VK_ACCESS_INDIRECT_COMMAND_READ_BIT; + case Resource::State::ResolveDest: case Resource::State::CopyDest: return VK_ACCESS_TRANSFER_WRITE_BIT; + case Resource::State::ResolveSource: case Resource::State::CopySource: return VK_ACCESS_TRANSFER_READ_BIT; - case Resource::State::ResolveDest: - return VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - case Resource::State::ResolveSource: - return VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; default: should_not_get_here(); return VkAccessFlagBits(-1); diff --git a/Framework/Source/API/Vulkan/VKRenderContext.cpp b/Framework/Source/API/Vulkan/VKRenderContext.cpp index 18b49f085..62dff7b34 100644 --- a/Framework/Source/API/Vulkan/VKRenderContext.cpp +++ b/Framework/Source/API/Vulkan/VKRenderContext.cpp @@ -35,7 +35,8 @@ namespace Falcor { VkImageAspectFlags getAspectFlagsFromFormat(ResourceFormat format); - + VkImageLayout getImageLayout(Resource::State state); + RenderContext::SharedPtr RenderContext::create(CommandQueueHandle queue) { SharedPtr pCtx = SharedPtr(new RenderContext()); @@ -319,5 +320,25 @@ namespace Falcor VkFilter vkFilter = isDepthStencilFormat(pTexture->getFormat()) ? VK_FILTER_NEAREST : getVkFilter(filter); vkCmdBlitImage(mpLowLevelData->getCommandList(), pSrc->getResource()->getApiHandle(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, pDst->getResource()->getApiHandle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blt, vkFilter); } + mCommandsPending = true; + } + + void RenderContext::resolveResource(const Texture* pSrc, const Texture* pDst) + { + // Just blit. It will work + blit(pSrc->getSRV(), pDst->getRTV()); + } + + void RenderContext::resolveSubresource(const Texture* pSrc, uint32_t srcSubresource, const Texture* pDst, uint32_t dstSubresource) + { + uint32_t srcArray = pSrc->getSubresourceArraySlice(srcSubresource); + uint32_t srcMip = pSrc->getSubresourceMipLevel(srcSubresource); + const auto& pSrcSrv = pSrc->getSRV(srcMip, 1, srcArray, 1); + + uint32_t dstArray = pDst->getSubresourceArraySlice(dstSubresource); + uint32_t dstMip = pDst->getSubresourceMipLevel(dstSubresource); + const auto& pDstRtv = pDst->getRTV(dstMip, dstArray, 1); + + blit(pSrcSrv, pDstRtv); } } diff --git a/Samples/ForwardRenderer/ForwardRenderer.cpp b/Samples/ForwardRenderer/ForwardRenderer.cpp index b41eeaf73..a9d27f187 100644 --- a/Samples/ForwardRenderer/ForwardRenderer.cpp +++ b/Samples/ForwardRenderer/ForwardRenderer.cpp @@ -379,7 +379,7 @@ void ForwardRenderer::resolveDepthMSAA(RenderContext* pContext) { if (mAAMode == AAMode::MSAA) { - pContext->blit(mpMainFbo->getDepthStencilTexture()->getSRV(), mpResolveFbo->getRenderTargetView(2)); + pContext->resolveResource(mpMainFbo->getDepthStencilTexture().get(), mpResolveFbo->getColorTexture(2).get()); } } @@ -388,8 +388,8 @@ void ForwardRenderer::resolveMSAA(RenderContext* pContext) if(mAAMode == AAMode::MSAA) { PROFILE(resolveMSAA); - pContext->blit(mpMainFbo->getColorTexture(0)->getSRV(), mpResolveFbo->getRenderTargetView(0)); - pContext->blit(mpMainFbo->getColorTexture(1)->getSRV(), mpResolveFbo->getRenderTargetView(1)); + pContext->resolveResource(mpMainFbo->getColorTexture(0).get(), mpResolveFbo->getColorTexture(0).get()); + pContext->resolveResource(mpMainFbo->getColorTexture(1).get(), mpResolveFbo->getColorTexture(1).get()); } } From 40b85a2c2ad85477e945dc5e22be14e4aa6ce394 Mon Sep 17 00:00:00 2001 From: nbenty Date: Tue, 22 May 2018 11:50:47 -0700 Subject: [PATCH 12/18] CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 54a93f154..f18f4c7a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ v3.0.3 ------ - Added FXAA as an effect - Support programmable sample position - `Fbo::setSamplePositions()` (DX only) +- Added RenderContext::resolveResource() and RenderContext::resolveSubresource() MSAA resolve functions v3.0.2 ------ From 1ee201f32570b6cf1555087a0ce23be7724c7f52 Mon Sep 17 00:00:00 2001 From: nbenty Date: Tue, 22 May 2018 14:36:03 -0700 Subject: [PATCH 13/18] Initialize the command-list pointer correctly --- .../Source/API/D3D12/LowLevel/D3D12LowLevelContextData.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Framework/Source/API/D3D12/LowLevel/D3D12LowLevelContextData.cpp b/Framework/Source/API/D3D12/LowLevel/D3D12LowLevelContextData.cpp index ef18437af..589c0a940 100644 --- a/Framework/Source/API/D3D12/LowLevel/D3D12LowLevelContextData.cpp +++ b/Framework/Source/API/D3D12/LowLevel/D3D12LowLevelContextData.cpp @@ -82,8 +82,8 @@ namespace Falcor #ifdef FALCOR_DXR pThis->mpList = createCommandList(pDevice, cmdListType, pThis->mpAllocator); #endif - if(!pThis->mpList) createCommandList(pDevice, cmdListType, pThis->mpAllocator); - if (!pThis->mpList) createCommandList(pDevice, cmdListType, pThis->mpAllocator); + if (!pThis->mpList) pThis->mpList = createCommandList(pDevice, cmdListType, pThis->mpAllocator); + if (!pThis->mpList) pThis->mpList = createCommandList(pDevice, cmdListType, pThis->mpAllocator); if (pThis->mpList == nullptr) { From 01c63fb11f9511cef6dc81a475a75fce3e7fa0af Mon Sep 17 00:00:00 2001 From: nbenty Date: Tue, 22 May 2018 14:51:08 -0700 Subject: [PATCH 14/18] Added ParameterBlock::getDefaultConstantBuffer() --- Framework/Source/Graphics/Material/Material.cpp | 2 +- Framework/Source/Graphics/Program/ParameterBlock.cpp | 5 +++++ Framework/Source/Graphics/Program/ParameterBlock.h | 5 +++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Framework/Source/Graphics/Material/Material.cpp b/Framework/Source/Graphics/Material/Material.cpp index 22114a675..396910355 100644 --- a/Framework/Source/Graphics/Material/Material.cpp +++ b/Framework/Source/Graphics/Material/Material.cpp @@ -308,7 +308,7 @@ namespace Falcor void Material::setIntoParameterBlock(ParameterBlock* pBlock) const { - ConstantBuffer* pCB = pBlock->getConstantBuffer(pBlock->getReflection()->getName()).get(); + ConstantBuffer* pCB = pBlock->getDefaultConstantBuffer().get(); setMaterialIntoBlockCommon(pBlock, pCB, 0, "", mData); } diff --git a/Framework/Source/Graphics/Program/ParameterBlock.cpp b/Framework/Source/Graphics/Program/ParameterBlock.cpp index 62cc4f5b6..a460af314 100644 --- a/Framework/Source/Graphics/Program/ParameterBlock.cpp +++ b/Framework/Source/Graphics/Program/ParameterBlock.cpp @@ -228,6 +228,11 @@ namespace Falcor return pReflector->getResourceBinding(name); } + ConstantBuffer::SharedPtr ParameterBlock::getDefaultConstantBuffer() const + { + return getConstantBuffer(mpReflector->getName()); + } + ConstantBuffer::SharedPtr ParameterBlock::getConstantBuffer(const std::string& name) const { uint32_t arrayIndex; diff --git a/Framework/Source/Graphics/Program/ParameterBlock.h b/Framework/Source/Graphics/Program/ParameterBlock.h index 80f681010..ebdff8287 100644 --- a/Framework/Source/Graphics/Program/ParameterBlock.h +++ b/Framework/Source/Graphics/Program/ParameterBlock.h @@ -94,6 +94,11 @@ namespace Falcor */ ConstantBuffer::SharedPtr getConstantBuffer(const BindLocation& bindLocation, uint32_t arrayIndex) const; + /** Get the default constant-buffer + The default constant-buffer has the same name as the parameter-block, so this call is equivalent to `getConstantBuffer(getReflection()->getName())` + */ + ConstantBuffer::SharedPtr getDefaultConstantBuffer() const; + /** Set a raw-buffer. Based on the shader reflection, it will be bound as either an SRV or a UAV \param[in] name The name of the buffer \param[in] pBuf The buffer object From 4180764136b05b946726c2ffa65fb9eba72525e9 Mon Sep 17 00:00:00 2001 From: Kai-Hwa Yao Date: Wed, 23 May 2018 19:08:04 -0700 Subject: [PATCH 15/18] Added shading model setting to model load flags and fscene --- CHANGELOG.md | 1 + .../Model/Loaders/AssimpModelImporter.cpp | 5 +++ Framework/Source/Graphics/Model/Model.h | 1 + .../Graphics/Scene/Editor/SceneEditor.cpp | 38 +++++++++++++++---- .../Graphics/Scene/Editor/SceneEditor.h | 3 ++ .../Graphics/Scene/SceneExportImportCommon.h | 5 +++ .../Source/Graphics/Scene/SceneExporter.cpp | 16 ++++++++ .../Source/Graphics/Scene/SceneImporter.cpp | 36 ++++++++++++++++-- 8 files changed, 95 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f18f4c7a6..1cb677245 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ v3.0.3 - Added FXAA as an effect - Support programmable sample position - `Fbo::setSamplePositions()` (DX only) - Added RenderContext::resolveResource() and RenderContext::resolveSubresource() MSAA resolve functions +- Added support for setting shading model through fscene files and load flags. Also editable in Scene Editor v3.0.2 ------ diff --git a/Framework/Source/Graphics/Model/Loaders/AssimpModelImporter.cpp b/Framework/Source/Graphics/Model/Loaders/AssimpModelImporter.cpp index 50c6b9cc7..cf65ed375 100644 --- a/Framework/Source/Graphics/Model/Loaders/AssimpModelImporter.cpp +++ b/Framework/Source/Graphics/Model/Loaders/AssimpModelImporter.cpp @@ -333,6 +333,11 @@ namespace Falcor Material::SharedPtr pMaterial = Material::create(nameStr); loadTextures(pAiMaterial, folder, pMaterial.get(), isObjFile, useSrgb); + if(is_set(mFlags, Model::LoadFlags::UseSpecGlossMaterials)) + { + pMaterial->setShadingModel(ShadingModelSpecGloss); + } + // Opacity float opacity; if (pAiMaterial->Get(AI_MATKEY_OPACITY, opacity) == AI_SUCCESS) diff --git a/Framework/Source/Graphics/Model/Model.h b/Framework/Source/Graphics/Model/Model.h index 79a355f46..e62cc7e17 100644 --- a/Framework/Source/Graphics/Model/Model.h +++ b/Framework/Source/Graphics/Model/Model.h @@ -66,6 +66,7 @@ namespace Falcor DontMergeMeshes = 0x8, ///< Preserve the original list of meshes in the scene, don't merge meshes with the same material BuffersAsShaderResource = 0x10, ///< Generate the VBs and IB with the shader-resource-view bind flag RemoveInstancing = 0x20, ///< Flatten mesh instances + UseSpecGlossMaterials = 0x40, ///< Set materials to use Spec-Gloss shading model. Otherwise default is Metal-Rough. }; /** Create a new model from file diff --git a/Framework/Source/Graphics/Scene/Editor/SceneEditor.cpp b/Framework/Source/Graphics/Scene/Editor/SceneEditor.cpp index 142c3c785..55a421aaf 100644 --- a/Framework/Source/Graphics/Scene/Editor/SceneEditor.cpp +++ b/Framework/Source/Graphics/Scene/Editor/SceneEditor.cpp @@ -49,6 +49,7 @@ namespace Falcor const char* kSelectedInstanceStr = "Selected Instance"; const char* kActiveAnimationStr = "Active Animation"; const char* kModelNameStr = "Model Name"; + const char* kShadingModelStr = "Shading Model"; const char* kInstanceStr = "Instance"; const char* kCamerasStr = "Cameras"; const char* kActiveCameraStr = "Active Camera"; @@ -60,6 +61,12 @@ namespace Falcor const float SceneEditor::kLightModelScale = 0.3f; const float SceneEditor::kKeyframeModelScale = 0.2f; + const Gui::DropdownList SceneEditor::kShadingModelList = + { + { ShadingModelMetalRough, "Metal-Rough" }, + { ShadingModelSpecGloss, "Spec-Gloss" } + }; + const Gui::RadioButtonGroup SceneEditor::kGizmoSelectionButtons { { (int32_t)Gizmo::Type::Translate, "Translation", false }, @@ -120,6 +127,23 @@ namespace Falcor } } + void SceneEditor::setShadingModel(Gui* pGui) + { + auto& pModel = mpScene->getModel(mSelectedModel); + assert(pModel->getMeshCount() > 0); + assert(pModel->getMesh(0)->getMaterial() != nullptr); + + uint32_t shadingModel = pModel->getMesh(0)->getMaterial()->getShadingModel(); + if (pGui->addDropdown(kShadingModelStr, kShadingModelList, shadingModel)) + { + for (uint32_t i = 0; i < pModel->getMeshCount(); i++) + { + pModel->getMesh(i)->getMaterial()->setShadingModel(shadingModel); + } + mSceneDirty = true; + } + } + void SceneEditor::setModelVisible(Gui* pGui) { const Scene::ModelInstance::SharedPtr& instance = mpScene->getModelInstance(mSelectedModel, mSelectedModelInstance); @@ -423,7 +447,7 @@ namespace Falcor // Copy camera transform from master scene const auto& pSceneCamera = mpScene->getActiveCamera(); - if(pSceneCamera) + if (pSceneCamera) { const auto& pEditorCamera = mpEditorScene->getActiveCamera(); @@ -493,7 +517,7 @@ namespace Falcor mpEditorScene = Scene::create(); mpEditorScene->addCamera(Camera::create()); - mpEditorScene->getActiveCamera()->setAspectRatio((float)backBufferWidth/(float)backBufferHeight); + mpEditorScene->getActiveCamera()->setAspectRatio((float)backBufferWidth / (float)backBufferHeight); mpEditorSceneRenderer = SceneEditorRenderer::create(mpEditorScene); mpEditorPicker = Picking::create(mpEditorScene, backBufferWidth, backBufferHeight); @@ -711,7 +735,7 @@ namespace Falcor mpDebugDrawer->addPath(mpScene->getPath(i)); } } - else if(mpPathEditor != nullptr) + else if (mpPathEditor != nullptr) { mpDebugDrawer->addPath(mpPathEditor->getPath()); } @@ -791,7 +815,7 @@ namespace Falcor const uint32_t activeFrame = mpPathEditor->getActiveFrame(); auto& pInstance = mpEditorScene->getModelInstance(mEditorKeyframeModelID, activeFrame); activeGizmo->applyDelta(pInstance); - + auto& pPath = mpScene->getPath(mSelectedPath); pPath->setFramePosition(activeFrame, pInstance->getTranslation()); pPath->setFrameTarget(activeFrame, pInstance->getTarget()); @@ -945,6 +969,7 @@ namespace Falcor pGui->addSeparator(); selectActiveModel(pGui); setModelName(pGui); + setShadingModel(pGui); if (pGui->beginGroup(kInstanceStr)) { @@ -1001,7 +1026,7 @@ namespace Falcor if (pGui->beginGroup(kCamerasStr)) { addCamera(pGui); - if(mpScene->getCameraCount()) + if (mpScene->getCameraCount()) { setActiveCamera(pGui); setCameraName(pGui); @@ -1399,7 +1424,7 @@ namespace Falcor { auto pCamera = Camera::create(); auto pActiveCamera = mpScene->getActiveCamera(); - if(pActiveCamera) + if (pActiveCamera) { *pCamera = *pActiveCamera; } @@ -1632,7 +1657,6 @@ namespace Falcor pNewPath->attachObject(pMovable); mObjToPathMap[pMovable.get()] = pNewPath; } - } } } diff --git a/Framework/Source/Graphics/Scene/Editor/SceneEditor.h b/Framework/Source/Graphics/Scene/Editor/SceneEditor.h index 1f15d465f..a8434ff2c 100644 --- a/Framework/Source/Graphics/Scene/Editor/SceneEditor.h +++ b/Framework/Source/Graphics/Scene/Editor/SceneEditor.h @@ -107,6 +107,7 @@ namespace Falcor void deleteModel(Gui* pGui); void deleteModel(); void setModelName(Gui* pGui); + void setShadingModel(Gui* pGui); void setModelVisible(Gui* pGui); void selectActiveModel(Gui* pGui); @@ -277,6 +278,8 @@ namespace Falcor std::string mSelectedMeshString; Mesh::SharedPtr mpSelectedMesh; + const static Gui::DropdownList kShadingModelList; + // // Paths // diff --git a/Framework/Source/Graphics/Scene/SceneExportImportCommon.h b/Framework/Source/Graphics/Scene/SceneExportImportCommon.h index 404c83856..7524ffa84 100644 --- a/Framework/Source/Graphics/Scene/SceneExportImportCommon.h +++ b/Framework/Source/Graphics/Scene/SceneExportImportCommon.h @@ -90,6 +90,11 @@ namespace Falcor static const char* kLight = "light"; static const char* kCamera = "camera"; + static const char* kMaterial = "material"; + static const char* kShadingModel = "shading_model"; + static const char* kShadingMetalRough = "metal_rough"; + static const char* kShadingSpecGloss = "spec_gloss"; + static const char* kUserDefined = "user_defined"; }; } \ No newline at end of file diff --git a/Framework/Source/Graphics/Scene/SceneExporter.cpp b/Framework/Source/Graphics/Scene/SceneExporter.cpp index c46b76263..d09a22601 100644 --- a/Framework/Source/Graphics/Scene/SceneExporter.cpp +++ b/Framework/Source/Graphics/Scene/SceneExporter.cpp @@ -166,6 +166,22 @@ namespace Falcor addLiteral(jmodel, allocator, SceneKeys::kActiveAnimation, pModel->getActiveAnimation()); } + // Export model material properties + rapidjson::Value materialValue; + materialValue.SetObject(); + switch(pModel->getMesh(0)->getMaterial()->getShadingModel()) + { + case ShadingModelMetalRough: + addString(materialValue, allocator, SceneKeys::kShadingModel, SceneKeys::kShadingMetalRough); + break; + case ShadingModelSpecGloss: + addString(materialValue, allocator, SceneKeys::kShadingModel, SceneKeys::kShadingSpecGloss); + break; + default: + logWarning("SceneExporter: Unknown shading model found on model " + pModel->getName() + ", ignoring value"); + } + addJsonValue(jmodel, allocator, SceneKeys::kMaterial, materialValue); + // Export model instances rapidjson::Value jsonInstanceArray; jsonInstanceArray.SetArray(); diff --git a/Framework/Source/Graphics/Scene/SceneImporter.cpp b/Framework/Source/Graphics/Scene/SceneImporter.cpp index 852048bed..a33f6ba69 100644 --- a/Framework/Source/Graphics/Scene/SceneImporter.cpp +++ b/Framework/Source/Graphics/Scene/SceneImporter.cpp @@ -38,6 +38,7 @@ #include #include "Graphics/TextureHelper.h" #include "API/Device.h" +#include "Data/HostDeviceSharedMacros.h" #define SCENE_IMPORTER #include "SceneExportImportCommon.h" @@ -184,19 +185,44 @@ namespace Falcor { return error("Model must have a filename"); } + + // Get Model name const auto& modelFile = jsonModel[SceneKeys::kFilename]; if(modelFile.IsString() == false) { return error("Model filename must be a string"); } - // Load the model - std::string file = mDirectory + '/' + modelFile.GetString(); + std::string file = mDirectory + '/' + modelFile.GetString(); if (doesFileExist(file) == false) { file = modelFile.GetString(); } - auto pModel = Model::createFromFile(file.c_str(), mModelLoadFlags); + + // Parse additional properties that affect loading + Model::LoadFlags modelFlags = mModelLoadFlags; + if (jsonModel.HasMember(SceneKeys::kMaterial)) + { + const auto& materialSettings = jsonModel[SceneKeys::kMaterial]; + if (materialSettings.IsObject() == false) + { + return error("Material properties for \"" + file + "\" must be a JSON object"); + } + + for (auto m = materialSettings.MemberBegin(); m != materialSettings.MemberEnd(); m++) + { + if (m->name == SceneKeys::kShadingModel) + { + if (m->value == SceneKeys::kShadingSpecGloss) + { + modelFlags |= Model::LoadFlags::UseSpecGlossMaterials; + } + } + } + } + + // Load the model + auto pModel = Model::createFromFile(file.c_str(), modelFlags); if(pModel == nullptr) { return error("Could not load model: " + file); @@ -247,6 +273,10 @@ namespace Falcor pModel->setActiveAnimation(activeAnimation); } } + else if (keyName == SceneKeys::kMaterial) + { + // Existing parameters already handled + } else { return error("Invalid key found in models array. Key == " + keyName + "."); From 809c3bef7ce528c995cb7d138a39f2bddf6034b3 Mon Sep 17 00:00:00 2001 From: Kai-Hwa Yao Date: Thu, 24 May 2018 14:29:36 -0700 Subject: [PATCH 16/18] Updated Slang to 0.10.17 --- dependencies.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dependencies.xml b/dependencies.xml index 23210209f..75dfb91bc 100644 --- a/dependencies.xml +++ b/dependencies.xml @@ -29,8 +29,8 @@ - - + + From df343aac5b13c35eb780b7f1a7c9f8b9b7b4382f Mon Sep 17 00:00:00 2001 From: Kai-Hwa Yao Date: Thu, 24 May 2018 18:43:39 -0700 Subject: [PATCH 17/18] Moved a SceneKey unused in the importer into an ifdef for exporter-only variables --- Framework/Source/Graphics/Scene/SceneExportImportCommon.h | 7 ++++++- Framework/Source/Graphics/Scene/SceneExporter.cpp | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Framework/Source/Graphics/Scene/SceneExportImportCommon.h b/Framework/Source/Graphics/Scene/SceneExportImportCommon.h index 7524ffa84..d3fca98c5 100644 --- a/Framework/Source/Graphics/Scene/SceneExportImportCommon.h +++ b/Framework/Source/Graphics/Scene/SceneExportImportCommon.h @@ -48,6 +48,12 @@ namespace Falcor static const char* kAmbientIntensity = "ambient_intensity"; #endif + // Values currently only used in the exporter +#ifdef SCENE_EXPORTER + // Default values ignored by importer + static const char* kShadingMetalRough = "metal_rough"; +#endif + static const char* kVersion = "version"; static const char* kCameraSpeed = "camera_speed"; static const char* kActiveCamera = "active_camera"; @@ -92,7 +98,6 @@ namespace Falcor static const char* kMaterial = "material"; static const char* kShadingModel = "shading_model"; - static const char* kShadingMetalRough = "metal_rough"; static const char* kShadingSpecGloss = "spec_gloss"; static const char* kUserDefined = "user_defined"; diff --git a/Framework/Source/Graphics/Scene/SceneExporter.cpp b/Framework/Source/Graphics/Scene/SceneExporter.cpp index d09a22601..90a1df640 100644 --- a/Framework/Source/Graphics/Scene/SceneExporter.cpp +++ b/Framework/Source/Graphics/Scene/SceneExporter.cpp @@ -35,6 +35,7 @@ #include "Utils/Platform/OS.h" #include "Graphics/Scene/Editor/SceneEditor.h" +#define SCENE_EXPORTER #include "SceneExportImportCommon.h" From 5ab1324bd65ad8605af983df084a61cb40b5f3e7 Mon Sep 17 00:00:00 2001 From: Kai-Hwa Yao Date: Fri, 25 May 2018 11:09:34 -0700 Subject: [PATCH 18/18] Updated Slang to 0.10.18 --- dependencies.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dependencies.xml b/dependencies.xml index 75dfb91bc..abc147a75 100644 --- a/dependencies.xml +++ b/dependencies.xml @@ -29,8 +29,8 @@ - - + +