From ca2106ff5d5dfca65e9f71824a02ec668104efa9 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sat, 4 Nov 2023 21:27:57 +0100 Subject: [PATCH] Remove `SHADOW_MAPS_FORMAT` and support fallback formats for shadow maps --- Source/Engine/Renderer/Config.h | 3 -- Source/Engine/Renderer/ShadowsPass.cpp | 43 ++++++++++++++------------ Source/Engine/Renderer/ShadowsPass.h | 2 +- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Source/Engine/Renderer/Config.h b/Source/Engine/Renderer/Config.h index 659369a71..876da3100 100644 --- a/Source/Engine/Renderer/Config.h +++ b/Source/Engine/Renderer/Config.h @@ -114,6 +114,3 @@ PACK_STRUCT(struct ProbeData { // Maximum amount of directional light cascades (using CSM technique) #define MAX_CSM_CASCADES 4 - -// Default format for the shadow map textures -#define SHADOW_MAPS_FORMAT PixelFormat::D16_UNorm diff --git a/Source/Engine/Renderer/ShadowsPass.cpp b/Source/Engine/Renderer/ShadowsPass.cpp index 7e0cd1053..06381d826 100644 --- a/Source/Engine/Renderer/ShadowsPass.cpp +++ b/Source/Engine/Renderer/ShadowsPass.cpp @@ -4,11 +4,11 @@ #include "GBufferPass.h" #include "VolumetricFogPass.h" #include "Engine/Graphics/Graphics.h" +#include "Engine/Graphics/GPUContext.h" #include "Engine/Graphics/RenderTask.h" #include "Engine/Graphics/RenderBuffers.h" #include "Engine/Graphics/PixelFormatExtensions.h" #include "Engine/Content/Content.h" -#include "Engine/Graphics/GPUContext.h" #include "Engine/Scripting/Enums.h" #if USE_EDITOR #include "Engine/Renderer/Lightmaps.h" @@ -81,19 +81,22 @@ bool ShadowsPass::Init() _shader.Get()->OnReloading.Bind(this); #endif - // If GPU doesn't support linear sampling for the shadow map then fallback to the single sample on lowest quality - const auto formatTexture = PixelFormatExtensions::FindShaderResourceFormat(SHADOW_MAPS_FORMAT, false); - const auto formatFeaturesDepth = GPUDevice::Instance->GetFormatFeatures(SHADOW_MAPS_FORMAT); - const auto formatFeaturesTexture = GPUDevice::Instance->GetFormatFeatures(formatTexture); - _supportsShadows = EnumHasAllFlags(formatFeaturesDepth.Support, FormatSupport::DepthStencil | FormatSupport::Texture2D) - && EnumHasAllFlags(formatFeaturesTexture.Support, FormatSupport::ShaderSample | FormatSupport::ShaderSampleComparison); - // TODO: fallback to 32-bit shadow map format if 16-bit is not supported - if (!_supportsShadows) + // Select format for shadow maps + _shadowMapFormat = PixelFormat::Unknown; + for (const PixelFormat format : { PixelFormat::D16_UNorm, PixelFormat::D24_UNorm_S8_UInt, PixelFormat::D32_Float }) { - LOG(Warning, "GPU doesn't support shadows rendering"); - LOG(Warning, "Format: {0}, features support: {1}", ScriptingEnum::ToString(SHADOW_MAPS_FORMAT), (uint32)formatFeaturesDepth.Support); - LOG(Warning, "Format: {0}, features support: {1}", ScriptingEnum::ToString(formatTexture), (uint32)formatFeaturesTexture.Support); + const auto formatTexture = PixelFormatExtensions::FindShaderResourceFormat(format, false); + const auto formatFeaturesDepth = GPUDevice::Instance->GetFormatFeatures(format); + const auto formatFeaturesTexture = GPUDevice::Instance->GetFormatFeatures(formatTexture); + if (EnumHasAllFlags(formatFeaturesDepth.Support, FormatSupport::DepthStencil | FormatSupport::Texture2D) && + EnumHasAllFlags(formatFeaturesTexture.Support, FormatSupport::ShaderSample | FormatSupport::ShaderSampleComparison)) + { + _shadowMapFormat = format; + break; + } } + if (_shadowMapFormat == PixelFormat::Unknown) + LOG(Warning, "GPU doesn't support shadows rendering"); return false; } @@ -148,7 +151,7 @@ void ShadowsPass::updateShadowMapSize() // Select new size _currentShadowMapsQuality = Graphics::ShadowMapsQuality; - if (_supportsShadows) + if (_shadowMapFormat != PixelFormat::Unknown) { switch (_currentShadowMapsQuality) { @@ -174,18 +177,18 @@ void ShadowsPass::updateShadowMapSize() // Check if size will change if (newSizeCSM > 0 && newSizeCSM != _shadowMapsSizeCSM) { - if (_shadowMapCSM->Init(GPUTextureDescription::New2D(newSizeCSM, newSizeCSM, SHADOW_MAPS_FORMAT, GPUTextureFlags::ShaderResource | GPUTextureFlags::DepthStencil, 1, MAX_CSM_CASCADES))) + if (_shadowMapCSM->Init(GPUTextureDescription::New2D(newSizeCSM, newSizeCSM, _shadowMapFormat, GPUTextureFlags::ShaderResource | GPUTextureFlags::DepthStencil, 1, MAX_CSM_CASCADES))) { - LOG(Fatal, "Cannot setup shadow map '{0}' Size: {1}, format: {2}.", TEXT("CSM"), newSizeCSM, (int32)SHADOW_MAPS_FORMAT); + LOG(Fatal, "Cannot setup shadow map '{0}' Size: {1}, format: {2}.", TEXT("CSM"), newSizeCSM, ScriptingEnum::ToString(_shadowMapFormat)); return; } _shadowMapsSizeCSM = newSizeCSM; } if (newSizeCube > 0 && newSizeCube != _shadowMapsSizeCube) { - if (_shadowMapCube->Init(GPUTextureDescription::NewCube(newSizeCube, SHADOW_MAPS_FORMAT, GPUTextureFlags::ShaderResource | GPUTextureFlags::DepthStencil))) + if (_shadowMapCube->Init(GPUTextureDescription::NewCube(newSizeCube, _shadowMapFormat, GPUTextureFlags::ShaderResource | GPUTextureFlags::DepthStencil))) { - LOG(Fatal, "Cannot setup shadow map '{0}' Size: {1}, format: {2}.", TEXT("Cube"), newSizeCube, (int32)SHADOW_MAPS_FORMAT); + LOG(Fatal, "Cannot setup shadow map '{0}' Size: {1}, format: {2}.", TEXT("Cube"), newSizeCube, ScriptingEnum::ToString(_shadowMapFormat)); return; } _shadowMapsSizeCube = newSizeCube; @@ -586,7 +589,7 @@ bool ShadowsPass::CanRenderShadow(const RenderContext& renderContext, const Rend const float fadeDistance = Math::Max(light.ShadowsFadeDistance, 0.1f); const float fade = 1 - Math::Saturate((dstLightToView - light.Radius - light.ShadowsDistance + fadeDistance) / fadeDistance); - return fade > ZeroTolerance && _supportsShadows; + return fade > ZeroTolerance && _shadowMapFormat != PixelFormat::Unknown; } bool ShadowsPass::CanRenderShadow(const RenderContext& renderContext, const RendererSpotLightData& light) @@ -598,12 +601,12 @@ bool ShadowsPass::CanRenderShadow(const RenderContext& renderContext, const Rend const float fadeDistance = Math::Max(light.ShadowsFadeDistance, 0.1f); const float fade = 1 - Math::Saturate((dstLightToView - light.Radius - light.ShadowsDistance + fadeDistance) / fadeDistance); - return fade > ZeroTolerance && _supportsShadows; + return fade > ZeroTolerance && _shadowMapFormat != PixelFormat::Unknown; } bool ShadowsPass::CanRenderShadow(const RenderContext& renderContext, const RendererDirectionalLightData& light) { - return _supportsShadows; + return _shadowMapFormat != PixelFormat::Unknown; } void ShadowsPass::RenderShadow(RenderContextBatch& renderContextBatch, RendererPointLightData& light, GPUTextureView* shadowMask) diff --git a/Source/Engine/Renderer/ShadowsPass.h b/Source/Engine/Renderer/ShadowsPass.h index 176fbd9a0..e58d68d62 100644 --- a/Source/Engine/Renderer/ShadowsPass.h +++ b/Source/Engine/Renderer/ShadowsPass.h @@ -55,7 +55,7 @@ private: GPUPipelineStatePermutationsPs(Quality::MAX) * 2 * 2> _psShadowDir; GPUPipelineStatePermutationsPs(Quality::MAX) * 2> _psShadowPoint; GPUPipelineStatePermutationsPs(Quality::MAX) * 2> _psShadowSpot; - bool _supportsShadows; + PixelFormat _shadowMapFormat; // Shadow maps stuff int32 _shadowMapsSizeCSM;