From 2bc6ca089fec0de626130decd3ed7d9b8f1ffe39 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 8 Jun 2021 16:11:27 +0200 Subject: [PATCH] Add `HasTypedUAVLoad` to GPULimits (use for GPU lightmaps support baking detection) #526 --- .../Handlers/BakeLightmapsProgress.cs | 16 +++++--------- Source/Engine/Graphics/GPULimits.h | 5 +++++ .../DirectX/DX11/GPUDeviceDX11.cpp | 22 ++++++------------- .../DirectX/DX12/GPUDeviceDX12.cpp | 1 + .../GraphicsDevice/Null/GPUDeviceNull.cpp | 1 + .../GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp | 1 + Source/Engine/Renderer/DepthOfFieldPass.cpp | 2 -- Source/Engine/Renderer/ShadowsPass.cpp | 12 +++++++--- 8 files changed, 29 insertions(+), 31 deletions(-) diff --git a/Source/Editor/Progress/Handlers/BakeLightmapsProgress.cs b/Source/Editor/Progress/Handlers/BakeLightmapsProgress.cs index 39e46d19e..c2f23285f 100644 --- a/Source/Editor/Progress/Handlers/BakeLightmapsProgress.cs +++ b/Source/Editor/Progress/Handlers/BakeLightmapsProgress.cs @@ -10,8 +10,6 @@ namespace FlaxEditor.Progress.Handlers /// public sealed class BakeLightmapsProgress : ProgressHandler { - private static int _canBake; - /// /// Gets a value indicating whether GPU lightmaps baking is supported on this device. /// @@ -19,15 +17,11 @@ namespace FlaxEditor.Progress.Handlers { get { - if (_canBake == 0) - { - var instance = GPUDevice.Instance; - if (instance == null) - return false; - var limits = instance.Limits; - _canBake = limits.HasCompute && limits.MaximumTexture2DSize >= 8 * 1024 && instance.TotalGraphicsMemory >= 2 * 1024 ? 1 : 2; - } - return _canBake == 1; + var instance = GPUDevice.Instance; + if (instance == null) + return false; + var limits = instance.Limits; + return limits.HasCompute && limits.HasTypedUAVLoad && limits.MaximumTexture2DSize >= 8 * 1024 && instance.TotalGraphicsMemory >= 2 * 1024; } } diff --git a/Source/Engine/Graphics/GPULimits.h b/Source/Engine/Graphics/GPULimits.h index b50714fcd..401ce5178 100644 --- a/Source/Engine/Graphics/GPULimits.h +++ b/Source/Engine/Graphics/GPULimits.h @@ -275,6 +275,11 @@ DECLARE_SCRIPTING_TYPE_MINIMAL(GPULimits); /// API_FIELD() bool HasMultisampleDepthAsSRV; + /// + /// True if device supports reading from typed UAV in shader (common types such as R32G32B32A32, R16G16B16A16, R16, R8). This doesn't apply to single-component 32-bit formats. + /// + API_FIELD() bool HasTypedUAVLoad; + /// /// The maximum amount of texture mip levels. /// diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp index 938570e9f..2f7560141 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp @@ -296,26 +296,16 @@ bool GPUDeviceDX11::Init() ASSERT(createdFeatureLevel == targetFeatureLevel); _state = DeviceState::Created; - // Verify compute shader is supported on DirectX 11 - if (createdFeatureLevel >= D3D_FEATURE_LEVEL_11_0) - { - D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS options = { 0 }; - _device->CheckFeatureSupport(D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &options, sizeof(options)); - if (!options.ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x) - { - _device->Release(); - _device = nullptr; - LOG(Fatal, "DirectCompute is not supported by this device (DirectX 11 level)."); - return true; - } - } - // Init device limits { auto& limits = Limits; if (createdFeatureLevel >= D3D_FEATURE_LEVEL_11_0) { - limits.HasCompute = true; + D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS d3D10XHardwareOptions = {}; + _device->CheckFeatureSupport(D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &d3D10XHardwareOptions, sizeof(d3D10XHardwareOptions)); + D3D11_FEATURE_DATA_D3D11_OPTIONS2 featureDataD3D11Options2 = {}; + _device->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS2, &featureDataD3D11Options2, sizeof(featureDataD3D11Options2)); + limits.HasCompute = d3D10XHardwareOptions.ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x != 0; limits.HasTessellation = true; limits.HasGeometryShaders = true; limits.HasInstancing = true; @@ -326,6 +316,7 @@ bool GPUDeviceDX11::Init() limits.HasDepthAsSRV = true; limits.HasReadOnlyDepth = true; limits.HasMultisampleDepthAsSRV = true; + limits.HasTypedUAVLoad = featureDataD3D11Options2.TypedUAVLoadAdditionalFormats != 0; limits.MaximumMipLevelsCount = D3D11_REQ_MIP_LEVELS; limits.MaximumTexture1DSize = D3D11_REQ_TEXTURE1D_U_DIMENSION; limits.MaximumTexture1DArraySize = D3D11_REQ_TEXTURE1D_ARRAY_AXIS_DIMENSION; @@ -347,6 +338,7 @@ bool GPUDeviceDX11::Init() limits.HasDepthAsSRV = false; limits.HasReadOnlyDepth = createdFeatureLevel == D3D_FEATURE_LEVEL_10_1; limits.HasMultisampleDepthAsSRV = false; + limits.HasTypedUAVLoad = false; limits.MaximumMipLevelsCount = D3D10_REQ_MIP_LEVELS; limits.MaximumTexture1DSize = D3D10_REQ_TEXTURE1D_U_DIMENSION; limits.MaximumTexture1DArraySize = D3D10_REQ_TEXTURE1D_ARRAY_AXIS_DIMENSION; diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp index 40f860a87..caab244de 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp @@ -339,6 +339,7 @@ bool GPUDeviceDX12::Init() limits.HasDepthAsSRV = true; limits.HasReadOnlyDepth = true; limits.HasMultisampleDepthAsSRV = true; + limits.HasTypedUAVLoad = options.TypedUAVLoadAdditionalFormats != 0; limits.MaximumMipLevelsCount = D3D12_REQ_MIP_LEVELS; limits.MaximumTexture1DSize = D3D12_REQ_TEXTURE1D_U_DIMENSION; limits.MaximumTexture1DArraySize = D3D12_REQ_TEXTURE1D_ARRAY_AXIS_DIMENSION; diff --git a/Source/Engine/GraphicsDevice/Null/GPUDeviceNull.cpp b/Source/Engine/GraphicsDevice/Null/GPUDeviceNull.cpp index e20fe0ac0..fa266a34a 100644 --- a/Source/Engine/GraphicsDevice/Null/GPUDeviceNull.cpp +++ b/Source/Engine/GraphicsDevice/Null/GPUDeviceNull.cpp @@ -58,6 +58,7 @@ bool GPUDeviceNull::Init() limits.HasDepthAsSRV = false; limits.HasReadOnlyDepth = false; limits.HasMultisampleDepthAsSRV = false; + limits.HasTypedUAVLoad = false; limits.MaximumMipLevelsCount = 14; limits.MaximumTexture1DSize = 8192; limits.MaximumTexture1DArraySize = 512; diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp index 9ca399dad..5c9a7032a 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp @@ -1684,6 +1684,7 @@ bool GPUDeviceVulkan::Init() limits.HasDepthAsSRV = true; limits.HasReadOnlyDepth = true; limits.HasMultisampleDepthAsSRV = !!PhysicalDeviceFeatures.sampleRateShading; + limits.HasTypedUAVLoad = true; limits.MaximumMipLevelsCount = Math::Min(static_cast(log2(PhysicalDeviceLimits.maxImageDimension2D)), GPU_MAX_TEXTURE_MIP_LEVELS); limits.MaximumTexture1DSize = PhysicalDeviceLimits.maxImageDimension1D; limits.MaximumTexture1DArraySize = PhysicalDeviceLimits.maxImageArrayLayers; diff --git a/Source/Engine/Renderer/DepthOfFieldPass.cpp b/Source/Engine/Renderer/DepthOfFieldPass.cpp index 8ebcbb53f..3affcdfda 100644 --- a/Source/Engine/Renderer/DepthOfFieldPass.cpp +++ b/Source/Engine/Renderer/DepthOfFieldPass.cpp @@ -38,8 +38,6 @@ bool DepthOfFieldPass::Init() _platformSupportsDoF = limits.HasCompute; _platformSupportsBokeh = _platformSupportsDoF && limits.HasGeometryShaders && limits.HasDrawIndirect && limits.HasAppendConsumeBuffers; - _platformSupportsBokeh &= GPUDevice::Instance->GetRendererType() != RendererType::Vulkan; // TODO: add bokeh on Vulkan (draw indirect with UA output from PS) - // Create pipeline states if (_platformSupportsDoF) { diff --git a/Source/Engine/Renderer/ShadowsPass.cpp b/Source/Engine/Renderer/ShadowsPass.cpp index 3f724dfaa..707aa461d 100644 --- a/Source/Engine/Renderer/ShadowsPass.cpp +++ b/Source/Engine/Renderer/ShadowsPass.cpp @@ -314,11 +314,13 @@ void ShadowsPass::RenderShadow(RenderContext& renderContext, RendererPointLightD context->ResetSR(); context->ResetRenderTarget(); const Viewport viewport = renderContext.Task->GetViewport(); + GPUTexture* depthBuffer = renderContext.Buffers->DepthBuffer; + GPUTextureView* depthBufferHandle = depthBuffer->GetDescription().Flags & GPUTextureFlags::ReadOnlyDepthView ? depthBuffer->ViewReadOnlyDepth() : depthBuffer->View(); context->SetViewportAndScissors(viewport); context->BindSR(0, renderContext.Buffers->GBuffer0); context->BindSR(1, renderContext.Buffers->GBuffer1); context->BindSR(2, renderContext.Buffers->GBuffer2); - context->BindSR(3, renderContext.Buffers->DepthBuffer); + context->BindSR(3, depthBufferHandle); context->BindSR(4, renderContext.Buffers->GBuffer3); // Setup shader data @@ -414,11 +416,13 @@ void ShadowsPass::RenderShadow(RenderContext& renderContext, RendererSpotLightDa context->ResetSR(); context->ResetRenderTarget(); const Viewport viewport = renderContext.Task->GetViewport(); + GPUTexture* depthBuffer = renderContext.Buffers->DepthBuffer; + GPUTextureView* depthBufferHandle = depthBuffer->GetDescription().Flags & GPUTextureFlags::ReadOnlyDepthView ? depthBuffer->ViewReadOnlyDepth() : depthBuffer->View(); context->SetViewportAndScissors(viewport); context->BindSR(0, renderContext.Buffers->GBuffer0); context->BindSR(1, renderContext.Buffers->GBuffer1); context->BindSR(2, renderContext.Buffers->GBuffer2); - context->BindSR(3, renderContext.Buffers->DepthBuffer); + context->BindSR(3, depthBufferHandle); context->BindSR(4, renderContext.Buffers->GBuffer3); // Setup shader data @@ -688,11 +692,13 @@ void ShadowsPass::RenderShadow(RenderContext& renderContext, RendererDirectional context->ResetSR(); context->ResetRenderTarget(); const Viewport viewport = renderContext.Task->GetViewport(); + GPUTexture* depthBuffer = renderContext.Buffers->DepthBuffer; + GPUTextureView* depthBufferHandle = depthBuffer->GetDescription().Flags & GPUTextureFlags::ReadOnlyDepthView ? depthBuffer->ViewReadOnlyDepth() : depthBuffer->View(); context->SetViewportAndScissors(viewport); context->BindSR(0, renderContext.Buffers->GBuffer0); context->BindSR(1, renderContext.Buffers->GBuffer1); context->BindSR(2, renderContext.Buffers->GBuffer2); - context->BindSR(3, renderContext.Buffers->DepthBuffer); + context->BindSR(3, depthBufferHandle); context->BindSR(4, renderContext.Buffers->GBuffer3); // Setup shader data