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