Fix crash on Android if GPU doesn't support linear sampling of the shadow map

This commit is contained in:
Wojtek Figat
2021-01-14 22:23:22 +01:00
parent b76d5d34ea
commit f80f7cdd33
4 changed files with 43 additions and 25 deletions

View File

@@ -174,10 +174,10 @@ API_ENUM(Attributes="Flags") enum class FormatSupport : int32
DECLARE_ENUM_OPERATORS(FormatSupport);
// Helper macro to check if given format does not support a given set of feature flags
#define FORMAT_FEATURES_ARE_NOT_SUPPORTED(formatSupport, formatSupportFlags) ((formatSupport & formatSupportFlags) != static_cast<int>(formatSupportFlags))
#define FORMAT_FEATURES_ARE_NOT_SUPPORTED(formatSupport, formatSupportFlags) ((formatSupport & (formatSupportFlags)) != static_cast<int>(formatSupportFlags))
// Helper macro to check if given format does support a given set of feature flags
#define FORMAT_FEATURES_ARE_SUPPORTED(formatSupport, formatSupportFlags) ((formatSupport & formatSupportFlags) == static_cast<int>(formatSupportFlags))
#define FORMAT_FEATURES_ARE_SUPPORTED(formatSupport, formatSupportFlags) ((formatSupport & (formatSupportFlags)) == static_cast<int>(formatSupportFlags))
/// <summary>
/// The features exposed for a particular format.

View File

@@ -57,11 +57,11 @@ bool MotionBlurPass::Init()
// Prepare formats for the buffers
auto format = MOTION_VECTORS_PIXEL_FORMAT;
if (FORMAT_FEATURES_ARE_NOT_SUPPORTED(GPUDevice::Instance->GetFormatFeatures(format).Support, (FormatSupport::RenderTarget | FormatSupport::ShaderSample | FormatSupport::Texture2D)))
if (FORMAT_FEATURES_ARE_NOT_SUPPORTED(GPUDevice::Instance->GetFormatFeatures(format).Support, FormatSupport::RenderTarget | FormatSupport::ShaderSample | FormatSupport::Texture2D))
{
if (FORMAT_FEATURES_ARE_NOT_SUPPORTED(GPUDevice::Instance->GetFormatFeatures(PixelFormat::R32G32_Float).Support, (FormatSupport::RenderTarget | FormatSupport::ShaderSample | FormatSupport::Texture2D)))
if (FORMAT_FEATURES_ARE_NOT_SUPPORTED(GPUDevice::Instance->GetFormatFeatures(PixelFormat::R32G32_Float).Support, FormatSupport::RenderTarget | FormatSupport::ShaderSample | FormatSupport::Texture2D))
format = PixelFormat::R32G32_Float;
else if (FORMAT_FEATURES_ARE_NOT_SUPPORTED(GPUDevice::Instance->GetFormatFeatures(PixelFormat::R16G16B16A16_Float).Support, (FormatSupport::RenderTarget | FormatSupport::ShaderSample | FormatSupport::Texture2D)))
else if (FORMAT_FEATURES_ARE_NOT_SUPPORTED(GPUDevice::Instance->GetFormatFeatures(PixelFormat::R16G16B16A16_Float).Support, FormatSupport::RenderTarget | FormatSupport::ShaderSample | FormatSupport::Texture2D))
format = PixelFormat::R16G16B16A16_Float;
else
format = PixelFormat::R32G32B32A32_Float;

View File

@@ -6,6 +6,7 @@
#include "Engine/Graphics/Graphics.h"
#include "Engine/Graphics/RenderBuffers.h"
#include "Engine/Content/Content.h"
#include "Engine/Graphics/PixelFormatExtensions.h"
#if USE_EDITOR
#include "Engine/Renderer/Lightmaps.h"
#endif
@@ -77,6 +78,19 @@ bool ShadowsPass::Init()
_shader.Get()->OnReloading.Bind<ShadowsPass, &ShadowsPass::OnShaderReloading>(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 = FORMAT_FEATURES_ARE_SUPPORTED(formatFeaturesDepth.Support, FormatSupport::DepthStencil | FormatSupport::Texture2D)
&& FORMAT_FEATURES_ARE_SUPPORTED(formatFeaturesTexture.Support, FormatSupport::ShaderSample | FormatSupport::ShaderSampleComparison);
if (!_supportsShadows)
{
LOG(Warning, "GPU doesn't support shadows rendering");
LOG(Warning, "Format: {0} features support: {1}", (int32)SHADOW_MAPS_FORMAT, (uint32)formatFeaturesDepth.Support);
LOG(Warning, "Format: {0} features support: {1}", (int32)formatTexture, (uint32)formatFeaturesTexture.Support);
}
return false;
}
@@ -130,24 +144,27 @@ void ShadowsPass::updateShadowMapSize()
// Select new size
_currentShadowMapsQuality = Graphics::ShadowMapsQuality;
switch (_currentShadowMapsQuality)
if (_supportsShadows)
{
case Quality::Ultra:
newSizeCSM = 2048;
newSizeCube = 1024;
break;
case Quality::High:
newSizeCSM = 1024;
newSizeCube = 1024;
break;
case Quality::Medium:
newSizeCSM = 1024;
newSizeCube = 512;
break;
case Quality::Low:
newSizeCSM = 512;
newSizeCube = 256;
break;
switch (_currentShadowMapsQuality)
{
case Quality::Ultra:
newSizeCSM = 2048;
newSizeCube = 1024;
break;
case Quality::High:
newSizeCSM = 1024;
newSizeCube = 1024;
break;
case Quality::Medium:
newSizeCSM = 1024;
newSizeCube = 512;
break;
case Quality::Low:
newSizeCSM = 512;
newSizeCube = 256;
break;
}
}
// Check if size will change
@@ -194,7 +211,7 @@ bool ShadowsPass::CanRenderShadow(RenderContext& renderContext, const RendererPo
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;
return fade > ZeroTolerance && _supportsShadows;
}
bool ShadowsPass::CanRenderShadow(RenderContext& renderContext, const RendererSpotLightData& light)
@@ -206,12 +223,12 @@ bool ShadowsPass::CanRenderShadow(RenderContext& renderContext, const RendererSp
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;
return fade > ZeroTolerance && _supportsShadows;
}
bool ShadowsPass::CanRenderShadow(RenderContext& renderContext, const RendererDirectionalLightData& light)
{
return true;
return _supportsShadows;
}
void ShadowsPass::Prepare(RenderContext& renderContext, GPUContext* context)

View File

@@ -25,6 +25,7 @@ private:
GPUPipelineStatePermutationsPs<static_cast<int32>(Quality::MAX) * 2 * 2> _psShadowDir;
GPUPipelineStatePermutationsPs<static_cast<int32>(Quality::MAX) * 2> _psShadowPoint;
GPUPipelineStatePermutationsPs<static_cast<int32>(Quality::MAX) * 2> _psShadowSpot;
bool _supportsShadows;
// Shadow maps stuff
int32 _shadowMapsSizeCSM;