Clamp float values to correct range before conversion to normalized

Per Vulkan spec 2.9.2, when converting from a floating point value to
unsigned normalized, we must first clamp to [0,1]. When converting from
a floating point value to signed normalized, we must first clamp to
[-1,1]. This wasn't done to clear values.

Test: dEQP-VK.rasterization.provoking_vertex.*
Bug: b/140203285
Change-Id: I3f8c421b187b6a7e8bcb22d45142dc1664221605
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/35668
Tested-by: Chris Forbes <chrisforbes@google.com>
Presubmit-Ready: Chris Forbes <chrisforbes@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
diff --git a/src/Device/Blitter.cpp b/src/Device/Blitter.cpp
index c8298ed..b366b72 100644
--- a/src/Device/Blitter.cpp
+++ b/src/Device/Blitter.cpp
@@ -47,6 +47,22 @@
 			return;
 		}
 
+		float *pPixel = static_cast<float *>(pixel);
+		if (viewFormat.isUnsignedNormalized())
+		{
+			pPixel[0] = sw::clamp(pPixel[0], 0.0f, 1.0f);
+			pPixel[1] = sw::clamp(pPixel[1], 0.0f, 1.0f);
+			pPixel[2] = sw::clamp(pPixel[2], 0.0f, 1.0f);
+			pPixel[3] = sw::clamp(pPixel[3], 0.0f, 1.0f);
+		}
+		else if (viewFormat.isSignedNormalized())
+		{
+			pPixel[0] = sw::clamp(pPixel[0], -1.0f, 1.0f);
+			pPixel[1] = sw::clamp(pPixel[1], -1.0f, 1.0f);
+			pPixel[2] = sw::clamp(pPixel[2], -1.0f, 1.0f);
+			pPixel[3] = sw::clamp(pPixel[3], -1.0f, 1.0f);
+		}
+
 		if(fastClear(pixel, format, dest, dstFormat, subresourceRange, renderArea))
 		{
 			return;
diff --git a/src/Vulkan/VkFormat.cpp b/src/Vulkan/VkFormat.cpp
index e980ea3..7e7cce7 100644
--- a/src/Vulkan/VkFormat.cpp
+++ b/src/Vulkan/VkFormat.cpp
@@ -19,6 +19,58 @@
 namespace vk
 {
 
+bool Format::isUnsignedNormalized() const
+{
+	switch(format)
+	{
+	case VK_FORMAT_R4G4_UNORM_PACK8:
+	case VK_FORMAT_R4G4B4A4_UNORM_PACK16:
+	case VK_FORMAT_B4G4R4A4_UNORM_PACK16:
+	case VK_FORMAT_A1R5G5B5_UNORM_PACK16:
+	case VK_FORMAT_R5G5B5A1_UNORM_PACK16:
+	case VK_FORMAT_B5G5R5A1_UNORM_PACK16:
+	case VK_FORMAT_R5G6B5_UNORM_PACK16:
+	case VK_FORMAT_B5G6R5_UNORM_PACK16:
+	case VK_FORMAT_R8_UNORM:
+	case VK_FORMAT_R8G8_UNORM:
+	case VK_FORMAT_R8G8B8_UNORM:
+	case VK_FORMAT_R8G8B8A8_UNORM:
+	case VK_FORMAT_A8B8G8R8_UNORM_PACK32:
+	case VK_FORMAT_B8G8R8A8_UNORM:
+	case VK_FORMAT_A2R10G10B10_UNORM_PACK32:
+	case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
+	case VK_FORMAT_R16_UNORM:
+	case VK_FORMAT_R16G16_UNORM:
+	case VK_FORMAT_R16G16B16_UNORM:
+	case VK_FORMAT_R16G16B16A16_UNORM:
+		return true;
+	default:
+		return false;
+	}
+}
+
+bool Format::isSignedNormalized() const
+{
+	switch(format)
+	{
+	case VK_FORMAT_R8_SNORM:
+	case VK_FORMAT_R8G8_SNORM:
+	case VK_FORMAT_R8G8B8_SNORM:
+	case VK_FORMAT_R8G8B8A8_SNORM:
+	case VK_FORMAT_A8B8G8R8_SNORM_PACK32:
+	case VK_FORMAT_B8G8R8A8_SNORM:
+	case VK_FORMAT_A2R10G10B10_SNORM_PACK32:
+	case VK_FORMAT_A2B10G10R10_SNORM_PACK32:
+	case VK_FORMAT_R16_SNORM:
+	case VK_FORMAT_R16G16_SNORM:
+	case VK_FORMAT_R16G16B16_SNORM:
+	case VK_FORMAT_R16G16B16A16_SNORM:
+		return true;
+	default:
+		return false;
+	}
+}
+
 bool Format::isSignedNonNormalizedInteger() const
 {
 	switch(format)
diff --git a/src/Vulkan/VkFormat.h b/src/Vulkan/VkFormat.h
index 8770c39..0825009 100644
--- a/src/Vulkan/VkFormat.h
+++ b/src/Vulkan/VkFormat.h
@@ -32,6 +32,8 @@
 	Format(VkFormat format) : format(format) {}
 	inline operator VkFormat() const { return format; }
 
+	bool isUnsignedNormalized() const;
+	bool isSignedNormalized() const;
 	bool isSignedNonNormalizedInteger() const;
 	bool isUnsignedNonNormalizedInteger() const;
 	bool isNonNormalizedInteger() const;