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