From d3f9a2a1b9fe17517d4a7140c3055cb2e174a0f3 Mon Sep 17 00:00:00 2001 From: Turanszki Janos Date: Fri, 25 Sep 2020 00:24:05 +0200 Subject: [PATCH] rtao denoiser improvements --- Editor/Editor_UWP.vcxproj | 6 + Editor/PostprocessWindow.cpp | 4 +- Editor/RendererWindow.cpp | 8 +- Template_UWP/Template_UWP.vcxproj | 6 + WickedEngine/RenderPath3D.cpp | 2 +- WickedEngine/RenderPath3D_Forward.cpp | 2 +- WickedEngine/RenderPath3D_TiledDeferred.cpp | 4 +- WickedEngine/RenderPath3D_TiledForward.cpp | 2 +- WickedEngine/Shaders_SOURCE.vcxitems | 22 ++- WickedEngine/Shaders_SOURCE.vcxitems.filters | 8 +- WickedEngine/normalsfromdepthCS.hlsl | 79 ++++++++ WickedEngine/rtaoLIB.hlsl | 17 +- WickedEngine/rtao_denoise_blurCS.hlsl | 146 +++++++++++++++ ...alCS.hlsl => rtao_denoise_temporalCS.hlsl} | 0 WickedEngine/wiEmittedParticle.cpp | 10 +- WickedEngine/wiEnums.h | 4 +- WickedEngine/wiGraphics.h | 16 ++ WickedEngine/wiGraphicsDevice.cpp | 24 +-- WickedEngine/wiGraphicsDevice.h | 16 -- WickedEngine/wiRenderer.cpp | 168 ++++++++++++++++-- WickedEngine/wiRenderer.h | 5 + WickedEngine/wiScene.cpp | 6 +- WickedEngine/wiVersion.cpp | 2 +- 23 files changed, 475 insertions(+), 82 deletions(-) create mode 100644 WickedEngine/normalsfromdepthCS.hlsl create mode 100644 WickedEngine/rtao_denoise_blurCS.hlsl rename WickedEngine/{rtao_temporalCS.hlsl => rtao_denoise_temporalCS.hlsl} (100%) diff --git a/Editor/Editor_UWP.vcxproj b/Editor/Editor_UWP.vcxproj index 33a545371..e8aa7b2b8 100644 --- a/Editor/Editor_UWP.vcxproj +++ b/Editor/Editor_UWP.vcxproj @@ -448,6 +448,12 @@ Document + + Document + + + Document + Document diff --git a/Editor/PostprocessWindow.cpp b/Editor/PostprocessWindow.cpp index 3986bb4cc..e283688f1 100644 --- a/Editor/PostprocessWindow.cpp +++ b/Editor/PostprocessWindow.cpp @@ -68,7 +68,7 @@ PostprocessWindow::PostprocessWindow(EditorComponent* editor) : GUI(&editor->Get aoComboBox->AddItem("SSAO"); aoComboBox->AddItem("HBAO"); aoComboBox->AddItem("MSAO"); - if (wiRenderer::GetDevice()->CheckCapability(GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) + if (wiRenderer::GetDevice()->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) { aoComboBox->AddItem("RTAO"); } @@ -150,7 +150,7 @@ PostprocessWindow::PostprocessWindow(EditorComponent* editor) : GUI(&editor->Get editor->renderPath->setRaytracedReflectionsEnabled(args.bValue); }); ppWindow->AddWidget(ssrCheckBox); - ssrCheckBox->SetEnabled(wiRenderer::GetDevice()->CheckCapability(GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_RAYTRACING)); + ssrCheckBox->SetEnabled(wiRenderer::GetDevice()->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING)); sssCheckBox = new wiCheckBox("SSS: "); sssCheckBox->SetTooltip("Enable Subsurface Scattering. (Deferred only for now)"); diff --git a/Editor/RendererWindow.cpp b/Editor/RendererWindow.cpp index 3b9002c0f..e5b0c99db 100644 --- a/Editor/RendererWindow.cpp +++ b/Editor/RendererWindow.cpp @@ -159,7 +159,7 @@ RendererWindow::RendererWindow(EditorComponent* editor) : GUI(&editor->GetGUI()) }); variableRateShadingClassificationCheckBox->SetCheck(wiRenderer::GetVariableRateShadingClassification()); rendererWindow->AddWidget(variableRateShadingClassificationCheckBox); - variableRateShadingClassificationCheckBox->SetEnabled(wiRenderer::GetDevice()->CheckCapability(wiGraphics::GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_VARIABLE_RATE_SHADING_TIER2)); + variableRateShadingClassificationCheckBox->SetEnabled(wiRenderer::GetDevice()->CheckCapability(wiGraphics::GRAPHICSDEVICE_CAPABILITY_VARIABLE_RATE_SHADING_TIER2)); variableRateShadingClassificationDebugCheckBox = new wiCheckBox("DEBUG: "); variableRateShadingClassificationDebugCheckBox->SetTooltip("Toggle visualization of variable rate shading classification feature"); @@ -170,7 +170,7 @@ RendererWindow::RendererWindow(EditorComponent* editor) : GUI(&editor->GetGUI()) }); variableRateShadingClassificationDebugCheckBox->SetCheck(wiRenderer::GetVariableRateShadingClassificationDebug()); rendererWindow->AddWidget(variableRateShadingClassificationDebugCheckBox); - variableRateShadingClassificationDebugCheckBox->SetEnabled(wiRenderer::GetDevice()->CheckCapability(wiGraphics::GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_VARIABLE_RATE_SHADING_TIER2)); + variableRateShadingClassificationDebugCheckBox->SetEnabled(wiRenderer::GetDevice()->CheckCapability(wiGraphics::GRAPHICSDEVICE_CAPABILITY_VARIABLE_RATE_SHADING_TIER2)); advancedLightCullingCheckBox = new wiCheckBox("2.5D Light Culling: "); advancedLightCullingCheckBox->SetTooltip("Enable a more aggressive light culling approach which can result in slower culling but faster rendering (Tiled renderer only)"); @@ -201,7 +201,7 @@ RendererWindow::RendererWindow(EditorComponent* editor) : GUI(&editor->GetGUI()) }); tessellationCheckBox->SetCheck(wiRenderer::GetTessellationEnabled()); rendererWindow->AddWidget(tessellationCheckBox); - tessellationCheckBox->SetEnabled(wiRenderer::GetDevice()->CheckCapability(wiGraphics::GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_TESSELLATION)); + tessellationCheckBox->SetEnabled(wiRenderer::GetDevice()->CheckCapability(wiGraphics::GRAPHICSDEVICE_CAPABILITY_TESSELLATION)); alphaCompositionCheckBox = new wiCheckBox("Alpha Composition: "); alphaCompositionCheckBox->SetTooltip("Enable Alpha Composition. Enables softer alpha blending on partly solid geometry (eg. vegetation) but rendering performance will be slower."); @@ -237,7 +237,7 @@ RendererWindow::RendererWindow(EditorComponent* editor) : GUI(&editor->GetGUI()) shadowTypeComboBox->SetSize(XMFLOAT2(100, itemheight)); shadowTypeComboBox->SetPos(XMFLOAT2(x, y += step)); shadowTypeComboBox->AddItem("Shadowmaps"); - if (wiRenderer::GetDevice()->CheckCapability(wiGraphics::GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE)) + if (wiRenderer::GetDevice()->CheckCapability(wiGraphics::GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE)) { shadowTypeComboBox->AddItem("Ray traced"); } diff --git a/Template_UWP/Template_UWP.vcxproj b/Template_UWP/Template_UWP.vcxproj index b9122d16f..67f90cef3 100644 --- a/Template_UWP/Template_UWP.vcxproj +++ b/Template_UWP/Template_UWP.vcxproj @@ -478,6 +478,12 @@ Document + + Document + + + Document + Document diff --git a/WickedEngine/RenderPath3D.cpp b/WickedEngine/RenderPath3D.cpp index 30019cfdd..b6550cd69 100644 --- a/WickedEngine/RenderPath3D.cpp +++ b/WickedEngine/RenderPath3D.cpp @@ -201,7 +201,7 @@ void RenderPath3D::ResizeBuffers() device->SetName(&rtGUIBlurredBackground[2], "rtGUIBlurredBackground[2]"); } - if(device->CheckCapability(GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_VARIABLE_RATE_SHADING_TIER2)) + if(device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_VARIABLE_RATE_SHADING_TIER2)) { uint32_t tileSize = device->GetVariableRateShadingTileSize(); diff --git a/WickedEngine/RenderPath3D_Forward.cpp b/WickedEngine/RenderPath3D_Forward.cpp index 9aa18c9e3..5b6c54637 100644 --- a/WickedEngine/RenderPath3D_Forward.cpp +++ b/WickedEngine/RenderPath3D_Forward.cpp @@ -212,7 +212,7 @@ void RenderPath3D_Forward::Render() const GraphicsDevice* device = wiRenderer::GetDevice(); wiRenderer::UpdateCameraCB(wiRenderer::GetCamera(), cmd); - if (wiRenderer::GetVariableRateShadingClassification() && device->CheckCapability(GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_VARIABLE_RATE_SHADING_TIER2)) + if (wiRenderer::GetVariableRateShadingClassification() && device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_VARIABLE_RATE_SHADING_TIER2)) { wiRenderer::ComputeShadingRateClassification(*GetSceneRT_Read(1), rtLinearDepth, rtShadingRate, cmd); device->BindShadingRate(SHADING_RATE_1X1, cmd); diff --git a/WickedEngine/RenderPath3D_TiledDeferred.cpp b/WickedEngine/RenderPath3D_TiledDeferred.cpp index 435dfef09..6c066ae4e 100644 --- a/WickedEngine/RenderPath3D_TiledDeferred.cpp +++ b/WickedEngine/RenderPath3D_TiledDeferred.cpp @@ -17,7 +17,7 @@ void RenderPath3D_TiledDeferred::ResizeBuffers() GraphicsDevice* device = wiRenderer::GetDevice(); // Workaround textures if R11G11B10 UAV loads are not supported by the GPU: - if(!device->CheckCapability(GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_UAV_LOAD_FORMAT_R11G11B10_FLOAT)) + if(!device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_UAV_LOAD_FORMAT_R11G11B10_FLOAT)) { wiBackLog::post("\nWARNING: GRAPHICSDEVICE_CAPABILITY_UAV_LOAD_FORMAT_R11G11B10_FLOAT not supported, Tiled deferred will be using workaround slow path!\n"); @@ -115,7 +115,7 @@ void RenderPath3D_TiledDeferred::Render() const device->BindResource(CS, getSSREnabled() || getRaytracedReflectionEnabled() ? &rtSSR : wiTextureHelper::getTransparent(), TEXSLOT_RENDERPATH_SSR, cmd); - if (device->CheckCapability(GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_UAV_LOAD_FORMAT_R11G11B10_FLOAT)) + if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_UAV_LOAD_FORMAT_R11G11B10_FLOAT)) { wiRenderer::ComputeTiledLightCulling( depthBuffer_Copy, diff --git a/WickedEngine/RenderPath3D_TiledForward.cpp b/WickedEngine/RenderPath3D_TiledForward.cpp index 44ac3e0a7..fdfd4f75b 100644 --- a/WickedEngine/RenderPath3D_TiledForward.cpp +++ b/WickedEngine/RenderPath3D_TiledForward.cpp @@ -110,7 +110,7 @@ void RenderPath3D_TiledForward::Render() const cmd ); - if (wiRenderer::GetVariableRateShadingClassification() && device->CheckCapability(GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_VARIABLE_RATE_SHADING_TIER2)) + if (wiRenderer::GetVariableRateShadingClassification() && device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_VARIABLE_RATE_SHADING_TIER2)) { wiRenderer::ComputeShadingRateClassification(*GetSceneRT_Read(1), rtLinearDepth, rtShadingRate, cmd); device->BindShadingRate(SHADING_RATE_1X1, cmd); diff --git a/WickedEngine/Shaders_SOURCE.vcxitems b/WickedEngine/Shaders_SOURCE.vcxitems index fc5bb6154..ec3cd982f 100644 --- a/WickedEngine/Shaders_SOURCE.vcxitems +++ b/WickedEngine/Shaders_SOURCE.vcxitems @@ -616,7 +616,7 @@ Pixel Pixel - + Compute 5.0 Compute @@ -627,6 +627,26 @@ Compute Compute + + Compute + Compute + Compute + Compute + Compute + Compute + Compute + Compute + + + Compute + Compute + Compute + Compute + Compute + Compute + Compute + Compute + Compute 4.0 diff --git a/WickedEngine/Shaders_SOURCE.vcxitems.filters b/WickedEngine/Shaders_SOURCE.vcxitems.filters index bdde5d889..c781f04dd 100644 --- a/WickedEngine/Shaders_SOURCE.vcxitems.filters +++ b/WickedEngine/Shaders_SOURCE.vcxitems.filters @@ -1022,7 +1022,13 @@ CS - + + CS + + + CS + + CS diff --git a/WickedEngine/normalsfromdepthCS.hlsl b/WickedEngine/normalsfromdepthCS.hlsl new file mode 100644 index 000000000..710918d9b --- /dev/null +++ b/WickedEngine/normalsfromdepthCS.hlsl @@ -0,0 +1,79 @@ +#include "globals.hlsli" +#include "ShaderInterop_Postprocess.h" + +// This shader takes depth buffer and converts it to a flat normals buffer (world space) +// Output is unsigned float3 in [0, 1] range + +RWTEXTURE2D(output, float3, 0); + +static const uint TILE_BORDER = 1; +static const uint TILE_SIZE = POSTPROCESS_BLOCKSIZE + TILE_BORDER * 2; +groupshared float2 tile_XY[TILE_SIZE * TILE_SIZE]; +groupshared float tile_Z[TILE_SIZE * TILE_SIZE]; + +[numthreads(POSTPROCESS_BLOCKSIZE, POSTPROCESS_BLOCKSIZE, 1)] +void main(uint3 DTid : SV_DispatchThreadID, uint3 Gid : SV_GroupID, uint3 GTid : SV_GroupThreadID, uint groupIndex : SV_GroupIndex) +{ + const int2 tile_upperleft = Gid.xy * POSTPROCESS_BLOCKSIZE - TILE_BORDER; + for (uint t = groupIndex; t < TILE_SIZE * TILE_SIZE; t += POSTPROCESS_BLOCKSIZE * POSTPROCESS_BLOCKSIZE) + { + const uint2 pixel = tile_upperleft + unflatten2D(t, TILE_SIZE); + const float2 uv = (pixel + 0.5f) * xPPResolution_rcp; + const float depth = texture_depth.SampleLevel(sampler_point_clamp, uv, 0); + const float3 position = reconstructPosition(uv, depth); + tile_XY[t] = position.xy; + tile_Z[t] = position.z; + } + GroupMemoryBarrierWithGroupSync(); + + // reconstruct flat normals from depth buffer: + // Explanation: There are two main ways to reconstruct flat normals from depth buffer: + // 1: use ddx() and ddy() on the reconstructed positions to compute triangle, this has artifacts on depth discontinuities and doesn't work in compute shader + // 2: Take 3 taps from the depth buffer, reconstruct positions and compute triangle. This can still produce artifacts + // on discontinuities, but a little less. To fix the remaining artifacts, we can take 4 taps around the center, and find the "best triangle" + // by only computing the positions from those depths that have the least amount of discontinuity + + const uint cross_idx[5] = { + flatten2D(TILE_BORDER + GTid.xy, TILE_SIZE), // 0: center + flatten2D(TILE_BORDER + GTid.xy + int2(1, 0), TILE_SIZE), // 1: right + flatten2D(TILE_BORDER + GTid.xy + int2(-1, 0), TILE_SIZE), // 2: left + flatten2D(TILE_BORDER + GTid.xy + int2(0, 1), TILE_SIZE), // 3: down + flatten2D(TILE_BORDER + GTid.xy + int2(0, -1), TILE_SIZE), // 4: up + }; + + const float center_Z = tile_Z[cross_idx[0]]; + + [branch] + if (center_Z >= g_xCamera_ZFarP) + return; + + const uint best_Z_horizontal = abs(tile_Z[cross_idx[1]] - center_Z) < abs(tile_Z[cross_idx[2]] - center_Z) ? 1 : 2; + const uint best_Z_vertical = abs(tile_Z[cross_idx[3]] - center_Z) < abs(tile_Z[cross_idx[4]] - center_Z) ? 3 : 4; + + float3 p1 = 0, p2 = 0; + if (best_Z_horizontal == 1 && best_Z_vertical == 4) + { + p1 = float3(tile_XY[cross_idx[1]], tile_Z[cross_idx[1]]); + p2 = float3(tile_XY[cross_idx[4]], tile_Z[cross_idx[4]]); + } + else if (best_Z_horizontal == 1 && best_Z_vertical == 3) + { + p1 = float3(tile_XY[cross_idx[3]], tile_Z[cross_idx[3]]); + p2 = float3(tile_XY[cross_idx[1]], tile_Z[cross_idx[1]]); + } + else if (best_Z_horizontal == 2 && best_Z_vertical == 4) + { + p1 = float3(tile_XY[cross_idx[4]], tile_Z[cross_idx[4]]); + p2 = float3(tile_XY[cross_idx[2]], tile_Z[cross_idx[2]]); + } + else if (best_Z_horizontal == 2 && best_Z_vertical == 3) + { + p1 = float3(tile_XY[cross_idx[2]], tile_Z[cross_idx[2]]); + p2 = float3(tile_XY[cross_idx[3]], tile_Z[cross_idx[3]]); + } + + const float3 P = float3(tile_XY[cross_idx[0]], tile_Z[cross_idx[0]]); + const float3 normal = normalize(cross(p2 - P, p1 - P)); + + output[DTid.xy] = saturate(normal * 0.5f + 0.5f); +} diff --git a/WickedEngine/rtaoLIB.hlsl b/WickedEngine/rtaoLIB.hlsl index c31f17478..1481dad27 100644 --- a/WickedEngine/rtaoLIB.hlsl +++ b/WickedEngine/rtaoLIB.hlsl @@ -2,6 +2,8 @@ #include "ShaderInterop_Postprocess.h" #include "raytracingHF.hlsli" +TEXTURE2D(texture_normals, float3, TEXSLOT_ONDEMAND0); + RWTEXTURE2D(output, unorm float, 0); ConstantBuffer subsets_material[MAX_DESCRIPTOR_INDEXING] : register(b0, space1); @@ -25,20 +27,7 @@ void RTAO_Raygen() return; const float3 P = reconstructPosition(uv, depth); - - float2 uv0 = uv; // center - float2 uv1 = uv + float2(1, 0) / (float2)DispatchRaysDimensions(); // right - float2 uv2 = uv + float2(0, 1) / (float2)DispatchRaysDimensions(); // top - - float depth0 = texture_depth.SampleLevel(sampler_point_clamp, uv0, 0).r; - float depth1 = texture_depth.SampleLevel(sampler_point_clamp, uv1, 0).r; - float depth2 = texture_depth.SampleLevel(sampler_point_clamp, uv2, 0).r; - - float3 P0 = reconstructPosition(uv0, depth0); - float3 P1 = reconstructPosition(uv1, depth1); - float3 P2 = reconstructPosition(uv2, depth2); - - float3 N = normalize(cross(P1 - P0, P2 - P0)); + float3 N = normalize(texture_normals.SampleLevel(sampler_point_clamp, uv, 0) * 2 - 1); float seed = rtao_seed; diff --git a/WickedEngine/rtao_denoise_blurCS.hlsl b/WickedEngine/rtao_denoise_blurCS.hlsl new file mode 100644 index 000000000..6bad7fc99 --- /dev/null +++ b/WickedEngine/rtao_denoise_blurCS.hlsl @@ -0,0 +1,146 @@ +#include "globals.hlsli" +#include "ShaderInterop_Postprocess.h" + +// This is a bilateral blur, that also operates on normal buffer, not just depth + +#define BLUR_FORMAT unorm float + +TEXTURE2D(input, BLUR_FORMAT, TEXSLOT_ONDEMAND0); +TEXTURE2D(texture_normals, float3, TEXSLOT_ONDEMAND1); + +RWTEXTURE2D(output, BLUR_FORMAT, 0); + +// Calculate gaussian weights online: http://dev.theomader.com/gaussian-kernel-calculator/ +static const int GAUSS_KERNEL = 33; +static const float gaussianWeightsNormalized[GAUSS_KERNEL] = { + 0.004013, + 0.005554, + 0.007527, + 0.00999, + 0.012984, + 0.016524, + 0.020594, + 0.025133, + 0.030036, + 0.035151, + 0.040283, + 0.045207, + 0.049681, + 0.053463, + 0.056341, + 0.058141, + 0.058754, + 0.058141, + 0.056341, + 0.053463, + 0.049681, + 0.045207, + 0.040283, + 0.035151, + 0.030036, + 0.025133, + 0.020594, + 0.016524, + 0.012984, + 0.00999, + 0.007527, + 0.005554, + 0.004013 +}; +static const int gaussianOffsets[GAUSS_KERNEL] = { + -16, + -15, + -14, + -13, + -12, + -11, + -10, + -9, + -8, + -7, + -6, + -5, + -4, + -3, + -2, + -1, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, +}; + +static const int TILE_BORDER = GAUSS_KERNEL / 2; +static const int CACHE_SIZE = TILE_BORDER + POSTPROCESS_BLUR_GAUSSIAN_THREADCOUNT + TILE_BORDER; +groupshared BLUR_FORMAT color_cache[CACHE_SIZE]; + +groupshared float depth_cache[CACHE_SIZE]; +groupshared float3 normal_cache[CACHE_SIZE]; + +[numthreads(POSTPROCESS_BLUR_GAUSSIAN_THREADCOUNT, 1, 1)] +void main(uint3 Gid : SV_GroupID, uint groupIndex : SV_GroupIndex) +{ + float2 direction = xPPParams0.xy; + const bool horizontal = direction.y == 0; + + uint2 tile_start = Gid.xy; + [flatten] + if (horizontal) + { + tile_start.x *= POSTPROCESS_BLUR_GAUSSIAN_THREADCOUNT; + } + else + { + tile_start.y *= POSTPROCESS_BLUR_GAUSSIAN_THREADCOUNT; + } + + int i; + for (i = groupIndex; i < CACHE_SIZE; i += POSTPROCESS_BLUR_GAUSSIAN_THREADCOUNT) + { + const float2 uv = (tile_start + 0.5f + direction * (i - TILE_BORDER)) * xPPResolution_rcp; + color_cache[i] = input.SampleLevel(sampler_linear_clamp, uv, 0); + depth_cache[i] = texture_lineardepth.SampleLevel(sampler_point_clamp, uv, 0); + normal_cache[i] = texture_normals.SampleLevel(sampler_point_clamp, uv, 0) * 2 - 1; + } + GroupMemoryBarrierWithGroupSync(); + + const uint2 pixel = tile_start + groupIndex * direction; + if (pixel.x >= xPPResolution.x || pixel.y >= xPPResolution.y) + { + return; + } + + const uint center = TILE_BORDER + groupIndex; + + const float depth_threshold = xPPParams0.w; + const float center_depth = depth_cache[center]; + const float3 center_normal = normal_cache[center]; + const BLUR_FORMAT center_color = color_cache[center]; + + BLUR_FORMAT color = 0; + for (i = 0; i < GAUSS_KERNEL; ++i) + { + const uint sam = center + gaussianOffsets[i]; + const BLUR_FORMAT color2 = color_cache[sam]; + const float depth = depth_cache[sam]; + const float3 normal = normal_cache[sam]; + const float weight1 = saturate(abs(depth - center_depth) * g_xCamera_ZFarP * depth_threshold); + const float weight2 = 1 - saturate(dot(normal, center_normal)); + color += lerp(color2, center_color, max(weight1, weight2)) * gaussianWeightsNormalized[i]; + } + + output[pixel] = color; +} diff --git a/WickedEngine/rtao_temporalCS.hlsl b/WickedEngine/rtao_denoise_temporalCS.hlsl similarity index 100% rename from WickedEngine/rtao_temporalCS.hlsl rename to WickedEngine/rtao_denoise_temporalCS.hlsl diff --git a/WickedEngine/wiEmittedParticle.cpp b/WickedEngine/wiEmittedParticle.cpp index d2e27c43b..82c2f4398 100644 --- a/WickedEngine/wiEmittedParticle.cpp +++ b/WickedEngine/wiEmittedParticle.cpp @@ -280,7 +280,7 @@ void wiEmittedParticle::UpdateGPU(const TransformComponent& transform, const Mat { cb.xEmitterOptions |= EMITTER_OPTION_BIT_FRAME_BLENDING_ENABLED; } - if (device->CheckCapability(GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_MESH_SHADER)) + if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_MESH_SHADER)) { cb.xEmitterOptions |= EMITTER_OPTION_BIT_MESH_SHADER_ENABLED; } @@ -546,7 +546,7 @@ void wiEmittedParticle::Draw(const CameraComponent& camera, const MaterialCompon device->BindConstantBuffer(VS, &constantBuffer, CB_GETBINDSLOT(EmittedParticleCB), cmd); device->BindConstantBuffer(PS, &constantBuffer, CB_GETBINDSLOT(EmittedParticleCB), cmd); - if (device->CheckCapability(GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_MESH_SHADER)) + if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_MESH_SHADER)) { const GPUResource* res[] = { &counterBuffer, @@ -578,7 +578,7 @@ namespace wiEmittedParticle_Internal wiRenderer::LoadShader(VS, vertexShader, "emittedparticleVS.cso"); - if (wiRenderer::GetDevice()->CheckCapability(GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_MESH_SHADER)) + if (wiRenderer::GetDevice()->CheckCapability(GRAPHICSDEVICE_CAPABILITY_MESH_SHADER)) { wiRenderer::LoadShader(MS, meshShader, "emittedparticleMS.cso"); } @@ -609,7 +609,7 @@ namespace wiEmittedParticle_Internal for (int i = 0; i < BLENDMODE_COUNT; ++i) { PipelineStateDesc desc; - if (wiRenderer::GetDevice()->CheckCapability(GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_MESH_SHADER)) + if (wiRenderer::GetDevice()->CheckCapability(GRAPHICSDEVICE_CAPABILITY_MESH_SHADER)) { desc.ms = &meshShader; } @@ -630,7 +630,7 @@ namespace wiEmittedParticle_Internal { PipelineStateDesc desc; - if (wiRenderer::GetDevice()->CheckCapability(GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_MESH_SHADER)) + if (wiRenderer::GetDevice()->CheckCapability(GRAPHICSDEVICE_CAPABILITY_MESH_SHADER)) { desc.ms = &meshShader; } diff --git a/WickedEngine/wiEnums.h b/WickedEngine/wiEnums.h index 4308b3eb9..79e38cf34 100644 --- a/WickedEngine/wiEnums.h +++ b/WickedEngine/wiEnums.h @@ -333,7 +333,8 @@ enum CSTYPES CSTYPE_POSTPROCESS_SSR_RESOLVE, CSTYPE_POSTPROCESS_SSR_TEMPORAL, CSTYPE_POSTPROCESS_SSR_MEDIAN, - CSTYPE_POSTPROCESS_RTAO_TEMPORAL, + CSTYPE_POSTPROCESS_RTAO_DENOISE_TEMPORAL, + CSTYPE_POSTPROCESS_RTAO_DENOISE_BLUR, CSTYPE_POSTPROCESS_LIGHTSHAFTS, CSTYPE_POSTPROCESS_DEPTHOFFIELD_TILEMAXCOC_HORIZONTAL, CSTYPE_POSTPROCESS_DEPTHOFFIELD_TILEMAXCOC_VERTICAL, @@ -373,6 +374,7 @@ enum CSTYPES CSTYPE_POSTPROCESS_UPSAMPLE_BILATERAL_FLOAT4, CSTYPE_POSTPROCESS_UPSAMPLE_BILATERAL_UNORM4, CSTYPE_POSTPROCESS_DOWNSAMPLE4X, + CSTYPE_POSTPROCESS_NORMALSFROMDEPTH, CSTYPE_COUNT }; // raytracing shaders diff --git a/WickedEngine/wiGraphics.h b/WickedEngine/wiGraphics.h index ba4d38801..74394195d 100644 --- a/WickedEngine/wiGraphics.h +++ b/WickedEngine/wiGraphics.h @@ -308,6 +308,22 @@ namespace wiGraphics SHADING_RATE_4X2, SHADING_RATE_4X4 }; + enum GRAPHICSDEVICE_CAPABILITY + { + GRAPHICSDEVICE_CAPABILITY_TESSELLATION, + GRAPHICSDEVICE_CAPABILITY_CONSERVATIVE_RASTERIZATION, + GRAPHICSDEVICE_CAPABILITY_RASTERIZER_ORDERED_VIEWS, + GRAPHICSDEVICE_CAPABILITY_UAV_LOAD_FORMAT_COMMON, // eg: R16G16B16A16_FLOAT, R8G8B8A8_UNORM and more common ones + GRAPHICSDEVICE_CAPABILITY_UAV_LOAD_FORMAT_R11G11B10_FLOAT, + GRAPHICSDEVICE_CAPABILITY_RENDERTARGET_AND_VIEWPORT_ARRAYINDEX_WITHOUT_GS, + GRAPHICSDEVICE_CAPABILITY_RAYTRACING, + GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE, + GRAPHICSDEVICE_CAPABILITY_DESCRIPTOR_MANAGEMENT, + GRAPHICSDEVICE_CAPABILITY_VARIABLE_RATE_SHADING, + GRAPHICSDEVICE_CAPABILITY_VARIABLE_RATE_SHADING_TIER2, + GRAPHICSDEVICE_CAPABILITY_MESH_SHADER, + GRAPHICSDEVICE_CAPABILITY_COUNT, + }; // Flags //////////////////////////////////////////// enum BIND_FLAG diff --git a/WickedEngine/wiGraphicsDevice.cpp b/WickedEngine/wiGraphicsDevice.cpp index d44562ece..89dc78408 100644 --- a/WickedEngine/wiGraphicsDevice.cpp +++ b/WickedEngine/wiGraphicsDevice.cpp @@ -15,29 +15,29 @@ bool GraphicsDevice::CheckCapability(GRAPHICSDEVICE_CAPABILITY capability) const { switch (capability) { - case wiGraphics::GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_TESSELLATION: + case GRAPHICSDEVICE_CAPABILITY_TESSELLATION: return TESSELLATION; - case wiGraphics::GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_CONSERVATIVE_RASTERIZATION: + case GRAPHICSDEVICE_CAPABILITY_CONSERVATIVE_RASTERIZATION: return CONSERVATIVE_RASTERIZATION; - case wiGraphics::GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_RASTERIZER_ORDERED_VIEWS: + case GRAPHICSDEVICE_CAPABILITY_RASTERIZER_ORDERED_VIEWS: return RASTERIZER_ORDERED_VIEWS; - case wiGraphics::GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_UAV_LOAD_FORMAT_COMMON: + case GRAPHICSDEVICE_CAPABILITY_UAV_LOAD_FORMAT_COMMON: return UAV_LOAD_FORMAT_COMMON; - case wiGraphics::GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_UAV_LOAD_FORMAT_R11G11B10_FLOAT: + case GRAPHICSDEVICE_CAPABILITY_UAV_LOAD_FORMAT_R11G11B10_FLOAT: return UAV_LOAD_FORMAT_R11G11B10_FLOAT; - case wiGraphics::GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_RENDERTARGET_AND_VIEWPORT_ARRAYINDEX_WITHOUT_GS: + case GRAPHICSDEVICE_CAPABILITY_RENDERTARGET_AND_VIEWPORT_ARRAYINDEX_WITHOUT_GS: return RENDERTARGET_AND_VIEWPORT_ARRAYINDEX_WITHOUT_GS; - case wiGraphics::GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_RAYTRACING: + case GRAPHICSDEVICE_CAPABILITY_RAYTRACING: return RAYTRACING; - case wiGraphics::GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE: + case GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE: return RAYTRACING_INLINE; - case wiGraphics::GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_DESCRIPTOR_MANAGEMENT: + case GRAPHICSDEVICE_CAPABILITY_DESCRIPTOR_MANAGEMENT: return DESCRIPTOR_MANAGEMENT; - case wiGraphics::GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_VARIABLE_RATE_SHADING: + case GRAPHICSDEVICE_CAPABILITY_VARIABLE_RATE_SHADING: return VARIABLE_RATE_SHADING; - case wiGraphics::GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_VARIABLE_RATE_SHADING_TIER2: + case GRAPHICSDEVICE_CAPABILITY_VARIABLE_RATE_SHADING_TIER2: return VARIABLE_RATE_SHADING_TIER2; - case wiGraphics::GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_MESH_SHADER: + case GRAPHICSDEVICE_CAPABILITY_MESH_SHADER: return MESH_SHADER; } return false; diff --git a/WickedEngine/wiGraphicsDevice.h b/WickedEngine/wiGraphicsDevice.h index 13fde25d7..6f92ea129 100644 --- a/WickedEngine/wiGraphicsDevice.h +++ b/WickedEngine/wiGraphicsDevice.h @@ -95,22 +95,6 @@ namespace wiGraphics virtual Texture GetBackBuffer() = 0; - enum GRAPHICSDEVICE_CAPABILITY - { - GRAPHICSDEVICE_CAPABILITY_TESSELLATION, - GRAPHICSDEVICE_CAPABILITY_CONSERVATIVE_RASTERIZATION, - GRAPHICSDEVICE_CAPABILITY_RASTERIZER_ORDERED_VIEWS, - GRAPHICSDEVICE_CAPABILITY_UAV_LOAD_FORMAT_COMMON, // eg: R16G16B16A16_FLOAT, R8G8B8A8_UNORM and more common ones - GRAPHICSDEVICE_CAPABILITY_UAV_LOAD_FORMAT_R11G11B10_FLOAT, - GRAPHICSDEVICE_CAPABILITY_RENDERTARGET_AND_VIEWPORT_ARRAYINDEX_WITHOUT_GS, - GRAPHICSDEVICE_CAPABILITY_RAYTRACING, - GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE, - GRAPHICSDEVICE_CAPABILITY_DESCRIPTOR_MANAGEMENT, - GRAPHICSDEVICE_CAPABILITY_VARIABLE_RATE_SHADING, - GRAPHICSDEVICE_CAPABILITY_VARIABLE_RATE_SHADING_TIER2, - GRAPHICSDEVICE_CAPABILITY_MESH_SHADER, - GRAPHICSDEVICE_CAPABILITY_COUNT, - }; bool CheckCapability(GRAPHICSDEVICE_CAPABILITY capability) const; uint32_t GetFormatStride(FORMAT value) const; diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index 0d4529da6..ca073c5ff 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -1441,6 +1441,7 @@ void LoadShaders() wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(CS, computeShaders[CSTYPE_POSTPROCESS_UPSAMPLE_BILATERAL_FLOAT4], "upsample_bilateral_float4CS.cso"); }); wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(CS, computeShaders[CSTYPE_POSTPROCESS_UPSAMPLE_BILATERAL_UNORM4], "upsample_bilateral_unorm4CS.cso"); }); wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(CS, computeShaders[CSTYPE_POSTPROCESS_DOWNSAMPLE4X], "downsample4xCS.cso"); }); + wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(CS, computeShaders[CSTYPE_POSTPROCESS_NORMALSFROMDEPTH], "normalsfromdepthCS.cso"); }); wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(HS, hullShaders[HSTYPE_OBJECT], "objectHS.cso"); }); @@ -3123,7 +3124,7 @@ void RenderMeshes( device->EventBegin("RenderMeshes", cmd); - tessellation = tessellation && device->CheckCapability(GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_TESSELLATION); + tessellation = tessellation && device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_TESSELLATION); if (tessellation) { BindConstantBuffers(DS, cmd); @@ -3753,7 +3754,7 @@ void UpdatePerFrameData(float dt, uint32_t layerMask) // Need to swap prev and current vertex buffers for any dynamic meshes BEFORE render threads are kicked // and also create skinning bone buffers: wiJobSystem::Execute(ctx, [&](wiJobArgs args) { - const bool raytracing_api = device->CheckCapability(GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_RAYTRACING); + const bool raytracing_api = device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING); for (size_t i = 0; i < scene.softbodies.GetCount(); ++i) { @@ -4640,7 +4641,7 @@ void UpdateRaytracingAccelerationStructures(CommandList cmd) { GraphicsDevice* device = GetDevice(); const Scene& scene = GetScene(); - if (!device->CheckCapability(GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_RAYTRACING) || !scene.TLAS.IsValid()) + if (!device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING) || !scene.TLAS.IsValid()) { return; } @@ -5674,7 +5675,7 @@ void DrawShadowmaps(const CameraComponent& camera, CommandList cmd, uint32_t lay case LightComponent::RECTANGLE: case LightComponent::TUBE: { - assert(device->CheckCapability(GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_RENDERTARGET_AND_VIEWPORT_ARRAYINDEX_WITHOUT_GS)); + assert(device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RENDERTARGET_AND_VIEWPORT_ARRAYINDEX_WITHOUT_GS)); SPHERE boundingsphere = SPHERE(light.position, light.GetRange()); @@ -7195,7 +7196,7 @@ void RefreshEnvProbes(CommandList cmd) GraphicsDevice* device = GetDevice(); device->EventBegin("EnvironmentProbe Refresh", cmd); - assert(device->CheckCapability(GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_RENDERTARGET_AND_VIEWPORT_ARRAYINDEX_WITHOUT_GS)); + assert(device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RENDERTARGET_AND_VIEWPORT_ARRAYINDEX_WITHOUT_GS)); Viewport vp; vp.Height = envmapRes; @@ -9112,7 +9113,7 @@ void BindCommonResources(CommandList cmd) device->BindResources(PS, resources, SBSLOT_ENTITYARRAY, arraysize(resources), cmd); device->BindResources(CS, resources, SBSLOT_ENTITYARRAY, arraysize(resources), cmd); - if (device->CheckCapability(GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) + if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) { const Scene& scene = GetScene(); device->BindResource(PS, &scene.TLAS, TEXSLOT_ACCELERATION_STRUCTURE, cmd); @@ -9257,7 +9258,7 @@ void UpdateFrameCB(CommandList cmd) { cb.g_xFrame_Options |= OPTION_BIT_SIMPLE_SKY; } - if (GetDevice()->CheckCapability(GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_RAYTRACING) && GetRaytracedShadowsEnabled()) + if (GetDevice()->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING) && GetRaytracedShadowsEnabled()) { cb.g_xFrame_Options |= OPTION_BIT_RAYTRACED_SHADOWS; } @@ -10381,9 +10382,9 @@ void Postprocess_RTAO( float power ) { - if (!wiRenderer::GetDevice()->CheckCapability(GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) + if (!wiRenderer::GetDevice()->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) return; - if (!wiRenderer::GetDevice()->CheckCapability(GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_DESCRIPTOR_MANAGEMENT)) + if (!wiRenderer::GetDevice()->CheckCapability(GRAPHICSDEVICE_CAPABILITY_DESCRIPTOR_MANAGEMENT)) return; const Scene& scene = wiScene::GetScene(); @@ -10407,6 +10408,7 @@ void Postprocess_RTAO( descriptorTable = DescriptorTable(); descriptorTable.resources.push_back({ TEXTURE2D, TEXSLOT_DEPTH }); + descriptorTable.resources.push_back({ TEXTURE2D, TEXSLOT_ONDEMAND0 }); descriptorTable.resources.push_back({ ACCELERATIONSTRUCTURE, TEXSLOT_ACCELERATION_STRUCTURE }); descriptorTable.resources.push_back({ RWTEXTURE2D, 0 }); descriptorTable.resources.push_back({ ROOT_CONSTANTBUFFER, CB_GETBINDSLOT(FrameCB) }); @@ -10472,7 +10474,9 @@ void Postprocess_RTAO( success = device->CreateRaytracingPipelineState(&rtdesc, &RTPSO); assert(success); - success = LoadShader(CS, computeShaders[CSTYPE_POSTPROCESS_RTAO_TEMPORAL], "rtao_temporalCS.cso"); + success = LoadShader(CS, computeShaders[CSTYPE_POSTPROCESS_RTAO_DENOISE_TEMPORAL], "rtao_denoise_temporalCS.cso"); + assert(success); + success = LoadShader(CS, computeShaders[CSTYPE_POSTPROCESS_RTAO_DENOISE_BLUR], "rtao_denoise_blurCS.cso"); assert(success); }; @@ -10485,6 +10489,7 @@ void Postprocess_RTAO( static TextureDesc saved_desc; static Texture temp; static Texture temporal[2]; + static Texture normals; const TextureDesc& lineardepth_desc = lineardepth.GetDesc(); if (saved_desc.Width != lineardepth_desc.Width || saved_desc.Height != lineardepth_desc.Height) @@ -10503,8 +10508,16 @@ void Postprocess_RTAO( device->SetName(&temporal[0], "rtao_temporal[0]"); device->CreateTexture(&desc, nullptr, &temporal[1]); device->SetName(&temporal[1], "rtao_temporal[1]"); + + desc.Format = FORMAT_R11G11B10_FLOAT; + device->CreateTexture(&desc, nullptr, &normals); + device->SetName(&normals, "rtao_normals"); } + Postprocess_NormalsFromDepth(depthbuffer, normals, cmd); + + device->EventBegin("Raytrace", cmd); + const TextureDesc& desc = temp.GetDesc(); PostProcessCB cb; @@ -10521,8 +10534,9 @@ void Postprocess_RTAO( device->BindRaytracingPipelineState(&RTPSO, cmd); device->WriteDescriptor(&descriptorTable, 0, 0, &depthbuffer); - device->WriteDescriptor(&descriptorTable, 1, 0, &scene.TLAS); - device->WriteDescriptor(&descriptorTable, 2, 0, &temp); + device->WriteDescriptor(&descriptorTable, 1, 0, &normals); + device->WriteDescriptor(&descriptorTable, 2, 0, &scene.TLAS); + device->WriteDescriptor(&descriptorTable, 3, 0, &temp); device->BindDescriptorTable(RAYTRACING, 0, &descriptorTable, cmd); device->BindDescriptorTable(RAYTRACING, 1, &scene.descriptorTable, cmd); device->BindRootDescriptor(RAYTRACING, 0, &constantBuffers[CBTYPE_FRAME], 0, cmd); @@ -10563,13 +10577,15 @@ void Postprocess_RTAO( }; device->Barrier(barriers, arraysize(barriers), cmd); + device->EventEnd(cmd); + int temporal_output = device->GetFrameCount() % 2; int temporal_history = 1 - temporal_output; // Temporal pass: { - device->EventBegin("Temporal pass", cmd); - device->BindComputeShader(&computeShaders[CSTYPE_POSTPROCESS_RTAO_TEMPORAL], cmd); + device->EventBegin("Temporal Denoise", cmd); + device->BindComputeShader(&computeShaders[CSTYPE_POSTPROCESS_RTAO_DENOISE_TEMPORAL], cmd); device->BindResource(CS, &depthbuffer, TEXSLOT_DEPTH, cmd); device->BindResource(CS, &temp, TEXSLOT_ONDEMAND0, cmd); @@ -10596,7 +10612,81 @@ void Postprocess_RTAO( device->EventEnd(cmd); } - Postprocess_Blur_Bilateral(temporal[temporal_output], lineardepth, temp, temporal[temporal_output], cmd, 1.2f, -1, -1, true); + { + + device->EventBegin("Blur Denoise", cmd); + + device->BindComputeShader(&computeShaders[CSTYPE_POSTPROCESS_RTAO_DENOISE_BLUR], cmd); + device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); + + device->BindResource(CS, &lineardepth, TEXSLOT_LINEARDEPTH, cmd); + device->BindResource(CS, &normals, TEXSLOT_ONDEMAND1, cmd); + + static float depth_threshold = 1.2f; + + // Horizontal: + { + PostProcessCB cb; + cb.xPPResolution.x = desc.Width; + cb.xPPResolution.y = desc.Height; + cb.xPPResolution_rcp.x = 1.0f / cb.xPPResolution.x; + cb.xPPResolution_rcp.y = 1.0f / cb.xPPResolution.y; + cb.xPPParams0.x = 1; + cb.xPPParams0.y = 0; + cb.xPPParams0.w = depth_threshold; + device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); + + device->BindResource(CS, &temporal[temporal_output], TEXSLOT_ONDEMAND0, cmd); + device->BindUAV(CS, &temp, 0, cmd); + + device->Dispatch( + (cb.xPPResolution.x + POSTPROCESS_BLUR_GAUSSIAN_THREADCOUNT - 1) / POSTPROCESS_BLUR_GAUSSIAN_THREADCOUNT, + cb.xPPResolution.y, + 1, + cmd + ); + + GPUBarrier barriers[] = { + GPUBarrier::Memory(), + }; + device->Barrier(barriers, arraysize(barriers), cmd); + + device->UnbindUAVs(0, 1, cmd); + } + + // Vertical: + { + PostProcessCB cb; + cb.xPPResolution.x = desc.Width; + cb.xPPResolution.y = desc.Height; + cb.xPPResolution_rcp.x = 1.0f / cb.xPPResolution.x; + cb.xPPResolution_rcp.y = 1.0f / cb.xPPResolution.y; + cb.xPPParams0.x = 0; + cb.xPPParams0.y = 1; + cb.xPPParams0.w = depth_threshold; + device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); + + device->BindResource(CS, &temp, TEXSLOT_ONDEMAND0, cmd); + device->BindUAV(CS, &temporal[temporal_output], 0, cmd); + + device->Dispatch( + cb.xPPResolution.x, + (cb.xPPResolution.y + POSTPROCESS_BLUR_GAUSSIAN_THREADCOUNT - 1) / POSTPROCESS_BLUR_GAUSSIAN_THREADCOUNT, + 1, + cmd + ); + + GPUBarrier barriers[] = { + GPUBarrier::Memory(), + }; + device->Barrier(barriers, arraysize(barriers), cmd); + + device->UnbindUAVs(0, 1, cmd); + } + + device->EventEnd(cmd); + } + Postprocess_Upsample_Bilateral(temporal[temporal_output], lineardepth, output, cmd); wiProfiler::EndRange(prof_range); @@ -10611,9 +10701,9 @@ void Postprocess_RTReflection( float range ) { - if (!wiRenderer::GetDevice()->CheckCapability(GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) + if (!wiRenderer::GetDevice()->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) return; - if (!wiRenderer::GetDevice()->CheckCapability(GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_DESCRIPTOR_MANAGEMENT)) + if (!wiRenderer::GetDevice()->CheckCapability(GRAPHICSDEVICE_CAPABILITY_DESCRIPTOR_MANAGEMENT)) return; const Scene& scene = wiScene::GetScene(); @@ -12723,6 +12813,50 @@ void Postprocess_Downsample4x( device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } +void Postprocess_NormalsFromDepth( + const Texture& depthbuffer, + const Texture& output, + CommandList cmd +) +{ + GraphicsDevice* device = GetDevice(); + + device->EventBegin("Postprocess_NormalsFromDepth", cmd); + + const TextureDesc& desc = output.GetDesc(); + + PostProcessCB cb; + cb.xPPResolution.x = desc.Width; + cb.xPPResolution.y = desc.Height; + cb.xPPResolution_rcp.x = 1.0f / cb.xPPResolution.x; + cb.xPPResolution_rcp.y = 1.0f / cb.xPPResolution.y; + device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); + device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); + + device->BindComputeShader(&computeShaders[CSTYPE_POSTPROCESS_NORMALSFROMDEPTH], cmd); + + device->BindResource(CS, &depthbuffer, TEXSLOT_DEPTH, cmd); + + const GPUResource* uavs[] = { + &output, + }; + device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + + device->Dispatch( + (desc.Width + POSTPROCESS_BLOCKSIZE - 1) / POSTPROCESS_BLOCKSIZE, + (desc.Height + POSTPROCESS_BLOCKSIZE - 1) / POSTPROCESS_BLOCKSIZE, + 1, + cmd + ); + + GPUBarrier barriers[] = { + GPUBarrier::Memory(), + }; + device->Barrier(barriers, arraysize(barriers), cmd); + + device->UnbindUAVs(0, arraysize(uavs), cmd); + device->EventEnd(cmd); +} const XMFLOAT4& GetWaterPlane() { diff --git a/WickedEngine/wiRenderer.h b/WickedEngine/wiRenderer.h index 86b06a928..820d865de 100644 --- a/WickedEngine/wiRenderer.h +++ b/WickedEngine/wiRenderer.h @@ -368,6 +368,11 @@ namespace wiRenderer const wiGraphics::Texture& output, wiGraphics::CommandList cmd ); + void Postprocess_NormalsFromDepth( + const wiGraphics::Texture& depthbuffer, + const wiGraphics::Texture& output, + wiGraphics::CommandList cmd + ); // Build the scene BVH on GPU that can be used by ray traced rendering void BuildSceneBVH(wiGraphics::CommandList cmd); diff --git a/WickedEngine/wiScene.cpp b/WickedEngine/wiScene.cpp index 19e294340..b72646769 100644 --- a/WickedEngine/wiScene.cpp +++ b/WickedEngine/wiScene.cpp @@ -562,7 +562,7 @@ namespace wiScene vertexBuffer_PRE = GPUBuffer(); - if (wiRenderer::GetDevice()->CheckCapability(GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) + if (wiRenderer::GetDevice()->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) { BLAS_build_pending = true; @@ -1152,7 +1152,7 @@ namespace wiScene void Scene::Update(float dt) { GraphicsDevice* device = wiRenderer::GetDevice(); - if (device->CheckCapability(GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_DESCRIPTOR_MANAGEMENT) && !descriptorTable.IsValid()) + if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_DESCRIPTOR_MANAGEMENT) && !descriptorTable.IsValid()) { descriptorTable.resources.resize(DESCRIPTORTABLE_ENTRY_COUNT); descriptorTable.resources[DESCRIPTORTABLE_ENTRY_SUBSETS_MATERIAL] = { CONSTANTBUFFER, 0, MAX_DESCRIPTOR_INDEXING }; @@ -1219,7 +1219,7 @@ namespace wiScene bounds = AABB::Merge(bounds, group_bound); } - if (device->CheckCapability(GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) + if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) { // Recreate top level acceleration structure if the object count changed: if (dt > 0 && objects.GetCount() > 0 && objects.GetCount() != TLAS.desc.toplevel.count) diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 2a480e399..93b6e246c 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wiVersion // minor features, major updates, breaking API changes const int minor = 47; // minor bug fixes, alterations, refactors, updates - const int revision = 40; + const int revision = 41; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);