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;