Implement depthClamp
The depthClamp feature allows users to force the depth to fit between
two values. Enabling depth clamping disables primitive depth clipping
unless a user explicitly enables both.
Bug: b/181655689
Tests: dEQP-VK.glsl.builtin_var.fragdepth.*
Tests: dEQP-VK.clipping.clip_volume.depth_clamp.*
Tests: dEQP-VK.draw.inverted_depth_ranges.*
Tests: dEQP-VK.draw.depth_clamp.*
Change-Id: Ib184b1972a11db2a806b7985754075fff55b4461
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/53929
Reviewed-by: Alexis Hétu <sugoi@google.com>
Tested-by: Sean Risser <srisser@google.com>
Commit-Queue: Sean Risser <srisser@google.com>
diff --git a/src/Device/Context.cpp b/src/Device/Context.cpp
index ad04d5b..96e0b8d 100644
--- a/src/Device/Context.cpp
+++ b/src/Device/Context.cpp
@@ -311,11 +311,6 @@
UNSUPPORTED("pCreateInfo->pRasterizationState->flags %d", int(pCreateInfo->pRasterizationState->flags));
}
- if(rasterizationState->depthClampEnable != VK_FALSE)
- {
- UNSUPPORTED("VkPhysicalDeviceFeatures::depthClamp");
- }
-
rasterizerDiscard = (rasterizationState->rasterizerDiscardEnable != VK_FALSE);
cullMode = rasterizationState->cullMode;
frontFace = rasterizationState->frontFace;
diff --git a/src/Device/PixelProcessor.cpp b/src/Device/PixelProcessor.cpp
index fa85953..1990fff 100644
--- a/src/Device/PixelProcessor.cpp
+++ b/src/Device/PixelProcessor.cpp
@@ -118,9 +118,22 @@
state.depthBias = (pipelineState.getConstantDepthBias() != 0.0f) || (pipelineState.getSlopeDepthBias() != 0.0f);
+ bool pipelineDepthClamp = pipelineState.getDepthClampEnable();
// "For fixed-point depth buffers, fragment depth values are always limited to the range [0,1] by clamping after depth bias addition is performed.
// Unless the VK_EXT_depth_range_unrestricted extension is enabled, fragment depth values are clamped even when the depth buffer uses a floating-point representation."
- state.depthClamp = !state.depthFormat.isFloatFormat() || !pipelineState.hasDepthRangeUnrestricted();
+ state.depthClamp = pipelineDepthClamp || !state.depthFormat.isFloatFormat() || !pipelineState.hasDepthRangeUnrestricted();
+
+ if(pipelineDepthClamp)
+ {
+ const VkViewport viewport = pipelineState.getViewport();
+ state.minDepthClamp = min(viewport.minDepth, viewport.maxDepth);
+ state.maxDepthClamp = max(viewport.minDepth, viewport.maxDepth);
+ }
+ else if(state.depthClamp)
+ {
+ state.minDepthClamp = 0.0f;
+ state.maxDepthClamp = 1.0f;
+ }
}
state.depthBoundsTestActive = pipelineState.depthBoundsTestActive();
diff --git a/src/Device/PixelProcessor.hpp b/src/Device/PixelProcessor.hpp
index b7187d4..c07366b 100644
--- a/src/Device/PixelProcessor.hpp
+++ b/src/Device/PixelProcessor.hpp
@@ -98,6 +98,9 @@
vk::Format depthFormat;
bool depthBias;
bool depthClamp;
+
+ float minDepthClamp;
+ float maxDepthClamp;
};
struct State : States
diff --git a/src/Pipeline/PixelRoutine.cpp b/src/Pipeline/PixelRoutine.cpp
index f1c55be..91d7fe5 100644
--- a/src/Pipeline/PixelRoutine.cpp
+++ b/src/Pipeline/PixelRoutine.cpp
@@ -129,7 +129,7 @@
if(state.depthClamp)
{
- z[q] = Min(Max(z[q], Float4(0.0f)), Float4(1.0f));
+ z[q] = Min(Max(z[q], Float4(state.minDepthClamp)), Float4(state.maxDepthClamp));
}
}
}
diff --git a/src/Vulkan/VkPhysicalDevice.cpp b/src/Vulkan/VkPhysicalDevice.cpp
index 7e14d4b..1a14680 100644
--- a/src/Vulkan/VkPhysicalDevice.cpp
+++ b/src/Vulkan/VkPhysicalDevice.cpp
@@ -46,7 +46,7 @@
VK_FALSE, // logicOp
VK_TRUE, // multiDrawIndirect
VK_TRUE, // drawIndirectFirstInstance
- VK_FALSE, // depthClamp
+ VK_TRUE, // depthClamp
VK_TRUE, // depthBiasClamp
VK_TRUE, // fillModeNonSolid
VK_TRUE, // depthBounds