Wire up texture border color correctly

Bug: b/129523279
Test: dEQP-VK.*border*
Change-Id: I76f3583ca9d4288c34ac897e5bc382b4c417488e
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/30111
Tested-by: Chris Forbes <chrisforbes@google.com>
Presubmit-Ready: Chris Forbes <chrisforbes@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Device/Sampler.cpp b/src/Device/Sampler.cpp
index b44f557..520f011 100644
--- a/src/Device/Sampler.cpp
+++ b/src/Device/Sampler.cpp
@@ -283,25 +283,6 @@
 		this->sRGB = sRGB;
 	}
 
-	void Sampler::setBorderColor(const Color<float> &borderColor)
-	{
-		// FIXME: Compact into generic function   // FIXME: Clamp
-		short r = iround(0xFFFF * borderColor.r);
-		short g = iround(0xFFFF * borderColor.g);
-		short b = iround(0xFFFF * borderColor.b);
-		short a = iround(0xFFFF * borderColor.a);
-
-		texture.borderColor4[0][0] = texture.borderColor4[0][1] = texture.borderColor4[0][2] = texture.borderColor4[0][3] = r;
-		texture.borderColor4[1][0] = texture.borderColor4[1][1] = texture.borderColor4[1][2] = texture.borderColor4[1][3] = g;
-		texture.borderColor4[2][0] = texture.borderColor4[2][1] = texture.borderColor4[2][2] = texture.borderColor4[2][3] = b;
-		texture.borderColor4[3][0] = texture.borderColor4[3][1] = texture.borderColor4[3][2] = texture.borderColor4[3][3] = a;
-
-		texture.borderColorF[0][0] = texture.borderColorF[0][1] = texture.borderColorF[0][2] = texture.borderColorF[0][3] = borderColor.r;
-		texture.borderColorF[1][0] = texture.borderColorF[1][1] = texture.borderColorF[1][2] = texture.borderColorF[1][3] = borderColor.g;
-		texture.borderColorF[2][0] = texture.borderColorF[2][1] = texture.borderColorF[2][2] = texture.borderColorF[2][3] = borderColor.b;
-		texture.borderColorF[3][0] = texture.borderColorF[3][1] = texture.borderColorF[3][2] = texture.borderColorF[3][3] = borderColor.a;
-	}
-
 	void Sampler::setMaxAnisotropy(float maxAnisotropy)
 	{
 		texture.maxAnisotropy = maxAnisotropy;
diff --git a/src/Device/Sampler.hpp b/src/Device/Sampler.hpp
index a9e0a4b..9f0e72f 100644
--- a/src/Device/Sampler.hpp
+++ b/src/Device/Sampler.hpp
@@ -55,8 +55,6 @@
 		float4 heightLOD;
 		float4 depthLOD;
 
-		word4 borderColor4[4];   // FIXME(b/129523279): Part of Vulkan sampler.
-		float4 borderColorF[4];  // FIXME(b/129523279): Part of Vulkan sampler.
 		float maxAnisotropy;     // FIXME(b/129523279): Part of Vulkan sampler.
 		float minLod;  // FIXME(b/129523279): Part of Vulkan sampler.
 		float maxLod;  // FIXME(b/129523279): Part of Vulkan sampler.
@@ -163,6 +161,7 @@
 			VkComponentMapping swizzle;
 			bool highPrecisionFiltering;
 			CompareFunc compare;
+			VkBorderColor border;
 
 			#if PERF_PROFILE
 			bool compressedFormat;
@@ -184,7 +183,6 @@
 		void setAddressingModeV(AddressingMode addressingMode);
 		void setAddressingModeW(AddressingMode addressingMode);
 		void setReadSRGB(bool sRGB);
-		void setBorderColor(const Color<float> &borderColor);
 		void setMaxAnisotropy(float maxAnisotropy);
 		void setHighPrecisionFiltering(bool highPrecisionFiltering);
 		void setCompareFunc(CompareFunc compare);
diff --git a/src/Pipeline/SamplerCore.cpp b/src/Pipeline/SamplerCore.cpp
index 377d10a..c29a185 100644
--- a/src/Pipeline/SamplerCore.cpp
+++ b/src/Pipeline/SamplerCore.cpp
@@ -170,6 +170,7 @@
 			case VK_FORMAT_R32G32_SINT:
 			case VK_FORMAT_R32G32_UINT:
 				c.z = As<Float4>(UInt4(0));
+				c.w = As<Float4>(UInt4(1));
 			case VK_FORMAT_R8G8B8A8_SINT:
 			case VK_FORMAT_R8G8B8A8_UINT:
 			case VK_FORMAT_R16G16B16A16_SINT:
@@ -359,12 +360,30 @@
 		   state.addressingModeV == ADDRESSING_BORDER ||
 		   (state.addressingModeW == ADDRESSING_BORDER && state.textureType == TEXTURE_3D))
 		{
-			Short4 b;
+			Short4 borderRgb;
+			Short4 borderA;
+			switch (state.border)
+			{
+			case VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK:
+				borderRgb = Short4(0);
+				borderA = Short4(0);
+				break;
+			case VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK:
+				borderRgb = Short4(0);
+				borderA = hasUnsignedTextureComponent(0) ? Short4(0xffff) : Short4(0x7fff);
+				break;
+			case VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE:
+				borderRgb = hasUnsignedTextureComponent(0) ? Short4(0xffff) : Short4(0x7fff);
+				borderA = hasUnsignedTextureComponent(0) ? Short4(0xffff) : Short4(0x7fff);
+				break;
+			default:
+				UNIMPLEMENTED("snorm/unorm border %u", state.border);
+			}
 
-			c.x = (borderMask & c.x) | (~borderMask & (*Pointer<Short4>(texture + OFFSET(Texture,borderColor4[0])) >> (hasUnsignedTextureComponent(0) ? 0 : 1)));
-			c.y = (borderMask & c.y) | (~borderMask & (*Pointer<Short4>(texture + OFFSET(Texture,borderColor4[1])) >> (hasUnsignedTextureComponent(1) ? 0 : 1)));
-			c.z = (borderMask & c.z) | (~borderMask & (*Pointer<Short4>(texture + OFFSET(Texture,borderColor4[2])) >> (hasUnsignedTextureComponent(2) ? 0 : 1)));
-			c.w = (borderMask & c.w) | (~borderMask & (*Pointer<Short4>(texture + OFFSET(Texture,borderColor4[3])) >> (hasUnsignedTextureComponent(3) ? 0 : 1)));
+			c.x = (borderMask & c.x) | (~borderMask & borderRgb);
+			c.y = (borderMask & c.y) | (~borderMask & borderRgb);
+			c.z = (borderMask & c.z) | (~borderMask & borderRgb);
+			c.w = (borderMask & c.w) | (~borderMask & borderA);
 		}
 
 		return c;
@@ -831,12 +850,43 @@
 		   state.addressingModeV == ADDRESSING_BORDER ||
 		   (state.addressingModeW == ADDRESSING_BORDER && state.textureType == TEXTURE_3D))
 		{
-			Int4 b;
+			Int4 borderRgb;
+			Int4 borderA;
 
-			c.x = As<Float4>((borderMask & As<Int4>(c.x)) | (~borderMask & *Pointer<Int4>(texture + OFFSET(Texture,borderColorF[0]))));
-			c.y = As<Float4>((borderMask & As<Int4>(c.y)) | (~borderMask & *Pointer<Int4>(texture + OFFSET(Texture,borderColorF[1]))));
-			c.z = As<Float4>((borderMask & As<Int4>(c.z)) | (~borderMask & *Pointer<Int4>(texture + OFFSET(Texture,borderColorF[2]))));
-			c.w = As<Float4>((borderMask & As<Int4>(c.w)) | (~borderMask & *Pointer<Int4>(texture + OFFSET(Texture,borderColorF[3]))));
+			switch (state.border)
+			{
+			case VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK:
+				borderRgb = As<Int4>(Float4(0));
+				borderA = As<Int4>(Float4(0));
+				break;
+			case VK_BORDER_COLOR_INT_TRANSPARENT_BLACK:
+				borderRgb = Int4(0);
+				borderA = Int4(0);
+				break;
+			case VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK:
+				borderRgb = As<Int4>(Float4(0));
+				borderA = As<Int4>(Float4(1));
+				break;
+			case VK_BORDER_COLOR_INT_OPAQUE_BLACK:
+				borderRgb = Int4(0);
+				borderA = Int4(1);
+				break;
+			case VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE:
+				borderRgb = As<Int4>(Float4(1));
+				borderA = As<Int4>(Float4(1));
+				break;
+			case VK_BORDER_COLOR_INT_OPAQUE_WHITE:
+				borderRgb = Int4(1);
+				borderA = Int4(1);
+				break;
+			default:
+				UNIMPLEMENTED("sint/uint/sfloat border: %u", state.border);
+			}
+
+			c.x = As<Float4>((borderMask & As<Int4>(c.x)) | (~borderMask & borderRgb));
+			c.y = As<Float4>((borderMask & As<Int4>(c.y)) | (~borderMask & borderRgb));
+			c.z = As<Float4>((borderMask & As<Int4>(c.z)) | (~borderMask & borderRgb));
+			c.w = As<Float4>((borderMask & As<Int4>(c.w)) | (~borderMask & borderA));
 		}
 
 		return c;
diff --git a/src/Pipeline/SpirvShaderSampling.cpp b/src/Pipeline/SpirvShaderSampling.cpp
index 593cdbb..c46f6f8 100644
--- a/src/Pipeline/SpirvShaderSampling.cpp
+++ b/src/Pipeline/SpirvShaderSampling.cpp
@@ -83,6 +83,7 @@
 	samplerState.textureType = convertTextureType(imageView->getType());
 	samplerState.textureFormat = imageView->getFormat();
 	samplerState.textureFilter = convertFilterMode(sampler);
+	samplerState.border = sampler->borderColor;
 
 	samplerState.addressingModeU = convertAddressingMode(sampler->addressModeU, imageView->getType());
 	samplerState.addressingModeV = convertAddressingMode(sampler->addressModeV, imageView->getType());
diff --git a/src/Vulkan/VkDescriptorSetLayout.cpp b/src/Vulkan/VkDescriptorSetLayout.cpp
index a383c22..b624057 100644
--- a/src/Vulkan/VkDescriptorSetLayout.cpp
+++ b/src/Vulkan/VkDescriptorSetLayout.cpp
@@ -560,4 +560,4 @@
 	memcpy(memToWrite, memToRead, writeSize);
 }
 
-} // namespace vk
\ No newline at end of file
+} // namespace vk