From 6715698a0c801d74fb5ce6a2da5b2deacde7d68d Mon Sep 17 00:00:00 2001 From: Nikita Fediuchin Date: Fri, 17 Jan 2025 21:10:51 +0200 Subject: [PATCH] Improve bloom downsample performance https://www.shadertoy.com/view/cslczj --- include/garden/system/render/bloom.hpp | 10 +++++-- resources/shaders/bloom/downsample.frag | 38 +++++++++++++++++++++++-- source/system/render/bloom.cpp | 22 +++++++------- 3 files changed, 53 insertions(+), 17 deletions(-) diff --git a/include/garden/system/render/bloom.hpp b/include/garden/system/render/bloom.hpp index ff69c1e..315bb43 100644 --- a/include/garden/system/render/bloom.hpp +++ b/include/garden/system/render/bloom.hpp @@ -42,11 +42,15 @@ class BloomRenderSystem final : public System, public Singleton downsamplePipeline = {}; ID upsamplePipeline = {}; @@ -103,7 +107,7 @@ class BloomRenderSystem final : public System, public Singleton getDownsamplePipeline(); /** - * @brief Returns bloom upwnsample graphics pipeline. + * @brief Returns bloom upsample graphics pipeline. */ ID getUpsamplePipeline(); /** diff --git a/resources/shaders/bloom/downsample.frag b/resources/shaders/bloom/downsample.frag index 6a53b8f..470581a 100644 --- a/resources/shaders/bloom/downsample.frag +++ b/resources/shaders/bloom/downsample.frag @@ -16,8 +16,9 @@ #include "common/gbuffer.gsl" #include "common/tone-mapping.gsl" -#variantCount 2 -#define DOWNSAMPLE_0_VARIANT 0 +#variantCount 3 +#define DOWNSAMPLE_FIRST_VARIANT 0 +#define DOWNSAMPLE_6X6_VARIANT 1 spec const bool USE_THRESHOLD = false; spec const bool USE_ANTI_FLICKERING = true; @@ -100,16 +101,47 @@ float3 downsample(sampler2D srcTexture, float2 texCoords, float threshold, bool return color; } +//********************************************************************************************************************** +float3 downsample6x6(sampler2D srcTexture, float2 texCoords) +{ + const float o = 1.5f + 0.261629f; + const float wa = 7.46602f / 32.0f; + const float wb = 1.0f - wa * 2.0f; + const float wab = wa * wb; + const float waa = wa * wa; + const float wbb = wb * wb; + + float2 size = textureSize(srcTexture, 0); + size = (1.0f / size) * o; + + float3 c = texture(srcTexture, texCoords + float2(0.0f )).rgb; + float3 l = texture(srcTexture, texCoords + float2(-size.x, 0.0f)).rgb; + float3 r = texture(srcTexture, texCoords + float2( size.x, 0.0f)).rgb; + float3 b = texture(srcTexture, texCoords + float2( 0.0f, -size.y)).rgb; + float3 t = texture(srcTexture, texCoords + float2( 0.0f, size.y)).rgb; + float3 lb = texture(srcTexture, texCoords + float2(-size.x, -size.y)).rgb; + float3 rb = texture(srcTexture, texCoords + float2( size.x, -size.y)).rgb; + float3 lt = texture(srcTexture, texCoords + float2(-size.x, size.y)).rgb; + float3 rt = texture(srcTexture, texCoords + float2( size.x, size.y)).rgb; + + return (c * wbb + (l * wab + (r * wab + (b * wab + (t * wab + + (lb * waa + (rb * waa + (lt * waa + (rt * waa))))))))); +} + void main() { float3 color; - if (gsl.variant == DOWNSAMPLE_0_VARIANT) + if (gsl.variant == DOWNSAMPLE_FIRST_VARIANT) { color = downsample(srcTexture, fs.texCoords, pc.threshold, USE_THRESHOLD, USE_ANTI_FLICKERING); color = max(color, 0.0001f); } + else if (gsl.variant == DOWNSAMPLE_6X6_VARIANT) + { + color = downsample6x6(srcTexture, fs.texCoords); + } else { color = downsample(srcTexture, fs.texCoords, 0.0f, false, false); diff --git a/source/system/render/bloom.cpp b/source/system/render/bloom.cpp index adc7628..ec45228 100644 --- a/source/system/render/bloom.cpp +++ b/source/system/render/bloom.cpp @@ -48,12 +48,10 @@ static ID createBloomBuffer(vector>& imageViews) return image; } -//********************************************************************************************************************** static void createBloomFramebuffers(const vector>& imageViews, vector>& framebuffers) { auto graphicsSystem = GraphicsSystem::Instance::get(); - auto framebufferSize = graphicsSystem->getScaledFramebufferSize(); - framebufferSize = max(framebufferSize / 2u, uint2(1)); + auto framebufferSize = max(graphicsSystem->getScaledFramebufferSize() / 2u, uint2(1)); auto mipCount = (uint8)imageViews.size(); framebuffers.resize(mipCount); @@ -104,7 +102,6 @@ static void createBloomDescriptorSets(ID bloomBuffer, } } -//********************************************************************************************************************** static ID createDownsamplePipeline( ID framebuffer, bool useThreshold, bool useAntiFlickering) { @@ -224,17 +221,21 @@ void BloomRenderSystem::preLdrRender() SET_GPU_DEBUG_LABEL("Downsample", Color::transparent); framebufferView->beginRenderPass(float4(0.0f)); - downsamplePipelineView->bind(downsample0Variant); + downsamplePipelineView->bind(downsampleFirstVariant); downsamplePipelineView->setViewportScissor(); downsamplePipelineView->bindDescriptorSet(descriptorSets[0]); downsamplePipelineView->pushConstants(); downsamplePipelineView->drawFullscreen(); framebufferView->endRenderPass(); - downsamplePipelineView->bind(downsampleVariant); for (uint8 i = 1; i < mipCount; i++) { + framebufferView = graphicsSystem->get(framebuffers[i - 1]); + auto framebufferSize = framebufferView->getSize(); + framebufferView = graphicsSystem->get(framebuffers[i]); + downsamplePipelineView->bind(framebufferSize.x & 1 || framebufferSize.y & 1 ? + downsampleBaseVariant : downsample6x6Variant); framebufferView->beginRenderPass(float4(0.0f)); downsamplePipelineView->setViewportScissor(); downsamplePipelineView->bindDescriptorSet(descriptorSets[i]); @@ -285,7 +286,6 @@ void BloomRenderSystem::gBufferRecreate() } } -//********************************************************************************************************************** void BloomRenderSystem::setConsts(bool useThreshold, bool useAntiFlickering) { if (this->useThreshold == useThreshold && this->useAntiFlickering == useAntiFlickering) @@ -294,13 +294,13 @@ void BloomRenderSystem::setConsts(bool useThreshold, bool useAntiFlickering) this->useThreshold = useThreshold; this->useAntiFlickering = useAntiFlickering; + auto graphicsSystem = GraphicsSystem::Instance::get(); + graphicsSystem->destroy(descriptorSets); + descriptorSets.clear(); + if (downsamplePipeline) { - auto graphicsSystem = GraphicsSystem::Instance::get(); - graphicsSystem->destroy(descriptorSets); - descriptorSets.clear(); graphicsSystem->destroy(downsamplePipeline); - downsamplePipeline = createDownsamplePipeline(getFramebuffers()[0], useThreshold, useAntiFlickering); } }