Add support for depthBiasClamp

Enabled depthBiasClamp in SwiftShader's PhysicalDeviceFeatures, which
will also enable any dEQP tests that rely on it.

Bug: b/160463658
Tests: dEQP-VK.dynamic_state.rs_state.depth_bias_clamp
Change-Id: Ida3ae12d30fb70a3bd7e508e276fb9a1bfc96231
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/46848
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Tested-by: Sean Risser <srisser@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Device/Context.hpp b/src/Device/Context.hpp
index 1c31201..3ca8216 100644
--- a/src/Device/Context.hpp
+++ b/src/Device/Context.hpp
@@ -103,6 +103,7 @@
 
 	float depthBias;
 	float slopeDepthBias;
+	float depthBiasClamp;
 
 	VkFormat renderTargetInternalFormat(int index) const;
 	int colorWriteActive(int index) const;
diff --git a/src/Device/Renderer.cpp b/src/Device/Renderer.cpp
index 825c09f..206f5d8 100644
--- a/src/Device/Renderer.cpp
+++ b/src/Device/Renderer.cpp
@@ -338,6 +338,7 @@
 		data->halfPixelY = float4(0.5f / H);
 		data->viewportHeight = abs(viewport.height);
 		data->slopeDepthBias = context->slopeDepthBias;
+		data->depthBiasClamp = context->depthBiasClamp;
 		data->depthRange = Z;
 		data->depthNear = N;
 	}
diff --git a/src/Device/Renderer.hpp b/src/Device/Renderer.hpp
index 367959f..da9d8fe 100644
--- a/src/Device/Renderer.hpp
+++ b/src/Device/Renderer.hpp
@@ -90,6 +90,7 @@
 	float slopeDepthBias;
 	float depthRange;
 	float depthNear;
+	float depthBiasClamp;
 
 	unsigned int *colorBuffer[RENDERTARGETS];
 	int colorPitchB[RENDERTARGETS];
diff --git a/src/Device/SetupProcessor.cpp b/src/Device/SetupProcessor.cpp
index b0d85f5..ad588b7 100644
--- a/src/Device/SetupProcessor.cpp
+++ b/src/Device/SetupProcessor.cpp
@@ -65,6 +65,7 @@
 	state.isDrawLine = context->isDrawLine(true);
 	state.isDrawTriangle = context->isDrawTriangle(true);
 	state.applySlopeDepthBias = context->isDrawTriangle(false) && (context->slopeDepthBias != 0.0f);
+	state.applyDepthBiasClamp = context->isDrawTriangle(false) && (context->depthBiasClamp != 0.0f);
 	state.interpolateZ = context->depthBufferActive() || vPosZW;
 	state.interpolateW = context->pixelShader != nullptr;
 	state.frontFace = context->frontFace;
diff --git a/src/Device/SetupProcessor.hpp b/src/Device/SetupProcessor.hpp
index 8d6a43c..50290b6 100644
--- a/src/Device/SetupProcessor.hpp
+++ b/src/Device/SetupProcessor.hpp
@@ -49,6 +49,7 @@
 		bool isDrawLine : 1;
 		bool isDrawTriangle : 1;
 		bool applySlopeDepthBias : 1;
+		bool applyDepthBiasClamp : 1;
 		bool interpolateZ : 1;
 		bool interpolateW : 1;
 		VkFrontFace frontFace : BITS(VK_FRONT_FACE_MAX_ENUM);
diff --git a/src/Pipeline/SetupRoutine.cpp b/src/Pipeline/SetupRoutine.cpp
index a34c489..ddfdef3 100644
--- a/src/Pipeline/SetupRoutine.cpp
+++ b/src/Pipeline/SetupRoutine.cpp
@@ -443,6 +443,13 @@
 
 			C = Float4(c * *Pointer<Float>(data + OFFSET(DrawData, depthRange)) + *Pointer<Float>(data + OFFSET(DrawData, depthNear)));
 
+			if(state.applyDepthBiasClamp)
+			{
+				Float clamp = *Pointer<Float>(data + OFFSET(DrawData, depthBiasClamp));
+				Float4 clamp4 = Float4(clamp);
+				C = IfThenElse(clamp > 0.0f, Min(clamp4, C), Max(clamp4, C));
+			}
+
 			*Pointer<Float4>(primitive + OFFSET(Primitive, z.C), 16) = C;
 		}
 
diff --git a/src/Vulkan/VkCommandBuffer.cpp b/src/Vulkan/VkCommandBuffer.cpp
index df555d0..ab9fb26 100644
--- a/src/Vulkan/VkCommandBuffer.cpp
+++ b/src/Vulkan/VkCommandBuffer.cpp
@@ -547,11 +547,9 @@
 
 		if(pipeline->hasDynamicState(VK_DYNAMIC_STATE_DEPTH_BIAS))
 		{
-			// If the depth bias clamping feature is not enabled, depthBiasClamp must be 0.0
-			ASSERT(executionState.dynamicState.depthBiasClamp == 0.0f);
-
 			context.depthBias = executionState.dynamicState.depthBiasConstantFactor;
 			context.slopeDepthBias = executionState.dynamicState.depthBiasSlopeFactor;
+			context.depthBiasClamp = executionState.dynamicState.depthBiasClamp;
 		}
 
 		if(pipeline->hasDynamicState(VK_DYNAMIC_STATE_DEPTH_BOUNDS) && context.depthBoundsTestEnable)
diff --git a/src/Vulkan/VkPhysicalDevice.cpp b/src/Vulkan/VkPhysicalDevice.cpp
index e42061c..9518a95 100644
--- a/src/Vulkan/VkPhysicalDevice.cpp
+++ b/src/Vulkan/VkPhysicalDevice.cpp
@@ -76,7 +76,7 @@
 		VK_TRUE,   // multiDrawIndirect
 		VK_TRUE,   // drawIndirectFirstInstance
 		VK_FALSE,  // depthClamp
-		VK_FALSE,  // depthBiasClamp
+		VK_TRUE,   // depthBiasClamp
 		VK_TRUE,   // fillModeNonSolid
 		VK_FALSE,  // depthBounds
 		VK_FALSE,  // wideLines
diff --git a/src/Vulkan/VkPipeline.cpp b/src/Vulkan/VkPipeline.cpp
index f8bb462..1bdbc16 100644
--- a/src/Vulkan/VkPipeline.cpp
+++ b/src/Vulkan/VkPipeline.cpp
@@ -260,6 +260,21 @@
 	context.polygonMode = rasterizationState->polygonMode;
 	context.depthBias = (rasterizationState->depthBiasEnable != VK_FALSE) ? rasterizationState->depthBiasConstantFactor : 0.0f;
 	context.slopeDepthBias = (rasterizationState->depthBiasEnable != VK_FALSE) ? rasterizationState->depthBiasSlopeFactor : 0.0f;
+	context.depthBiasClamp = (rasterizationState->depthBiasEnable != VK_FALSE) ? rasterizationState->depthBiasClamp : 0.0f;
+
+	// From the Vulkan spec for vkCmdSetDepthBias:
+	//    The bias value O for a polygon is:
+	//        O = dbclamp(...)
+	//    where dbclamp(x) =
+	//        * x                       depthBiasClamp = 0 or NaN
+	//        * min(x, depthBiasClamp)  depthBiasClamp > 0
+	//        * max(x, depthBiasClamp)  depthBiasClamp < 0
+	// So it should be safe to resolve NaNs to 0.0f.
+	if(std::isnan(context.depthBiasClamp))
+	{
+		context.depthBiasClamp = 0.0f;
+	}
+
 	context.lineWidth = rasterizationState->lineWidth;
 
 	const VkBaseInStructure *extensionCreateInfo = reinterpret_cast<const VkBaseInStructure *>(rasterizationState->pNext);