Split vk::Sampler state off into a structure

This enables deriving the state structure from Memset<> so we can ensure
it is fully zero-initialized and becomes comparable, while vk::Sampler
holds the identifier for the state.

Bug: b/151235334
Change-Id: I23a09eda9b50409c761bdd6ed10911ec159dc3ba
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/42768
Presubmit-Ready: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Pipeline/SpirvShaderSampling.cpp b/src/Pipeline/SpirvShaderSampling.cpp
index 23acd23..5434645 100644
--- a/src/Pipeline/SpirvShaderSampling.cpp
+++ b/src/Pipeline/SpirvShaderSampling.cpp
@@ -84,12 +84,9 @@
 		samplerState.compareOp = sampler->compareOp;
 		samplerState.unnormalizedCoordinates = (sampler->unnormalizedCoordinates != VK_FALSE);
 
-		if(sampler->ycbcrConversion)
-		{
-			samplerState.ycbcrModel = sampler->ycbcrConversion->ycbcrModel;
-			samplerState.studioSwing = (sampler->ycbcrConversion->ycbcrRange == VK_SAMPLER_YCBCR_RANGE_ITU_NARROW);
-			samplerState.swappedChroma = (sampler->ycbcrConversion->components.r != VK_COMPONENT_SWIZZLE_R);
-		}
+		samplerState.ycbcrModel = sampler->ycbcrModel;
+		samplerState.studioSwing = sampler->studioSwing;
+		samplerState.swappedChroma = sampler->swappedChroma;
 
 		samplerState.mipLodBias = sampler->mipLodBias;
 		samplerState.maxAnisotropy = sampler->maxAnisotropy;
@@ -270,7 +267,7 @@
 		return MIPMAP_POINT;  // Samplerless operations (OpImageFetch) can take an integer Lod operand.
 	}
 
-	if(sampler->ycbcrConversion)
+	if(sampler->ycbcrModel != VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY)
 	{
 		// TODO(b/151263485): Check image view level count instead.
 		return MIPMAP_NONE;
diff --git a/src/Vulkan/VkSampler.cpp b/src/Vulkan/VkSampler.cpp
index df62cc2..e5adb19 100644
--- a/src/Vulkan/VkSampler.cpp
+++ b/src/Vulkan/VkSampler.cpp
@@ -18,4 +18,35 @@
 
 std::atomic<uint32_t> Sampler::nextID(1);
 
+SamplerState::SamplerState(const VkSamplerCreateInfo *pCreateInfo, const vk::SamplerYcbcrConversion *ycbcrConversion)
+    : Memset(this, 0)
+    , magFilter(pCreateInfo->magFilter)
+    , minFilter(pCreateInfo->minFilter)
+    , mipmapMode(pCreateInfo->mipmapMode)
+    , addressModeU(pCreateInfo->addressModeU)
+    , addressModeV(pCreateInfo->addressModeV)
+    , addressModeW(pCreateInfo->addressModeW)
+    , mipLodBias(pCreateInfo->mipLodBias)
+    , anisotropyEnable(pCreateInfo->anisotropyEnable)
+    , maxAnisotropy(pCreateInfo->maxAnisotropy)
+    , compareEnable(pCreateInfo->compareEnable)
+    , compareOp(pCreateInfo->compareOp)
+    , minLod(ClampLod(pCreateInfo->minLod))
+    , maxLod(ClampLod(pCreateInfo->maxLod))
+    , borderColor(pCreateInfo->borderColor)
+    , unnormalizedCoordinates(pCreateInfo->unnormalizedCoordinates)
+{
+	if(ycbcrConversion)
+	{
+		ycbcrModel = ycbcrConversion->ycbcrModel;
+		studioSwing = (ycbcrConversion->ycbcrRange == VK_SAMPLER_YCBCR_RANGE_ITU_NARROW);
+		swappedChroma = (ycbcrConversion->components.r != VK_COMPONENT_SWIZZLE_R);
+	}
+}
+
+Sampler::Sampler(const VkSamplerCreateInfo *pCreateInfo, void *mem, const vk::SamplerYcbcrConversion *ycbcrConversion)
+    : SamplerState(pCreateInfo, ycbcrConversion)
+{
+}
+
 }  // namespace vk
diff --git a/src/Vulkan/VkSampler.hpp b/src/Vulkan/VkSampler.hpp
index 5a6ecf0..84d3373 100644
--- a/src/Vulkan/VkSampler.hpp
+++ b/src/Vulkan/VkSampler.hpp
@@ -15,42 +15,18 @@
 #ifndef VK_SAMPLER_HPP_
 #define VK_SAMPLER_HPP_
 
-#include "VkDevice.hpp"
 #include "VkImageView.hpp"  // For ResolveIdentityMapping()
 #include "Device/Config.hpp"
+#include "Device/Memset.hpp"
 #include "System/Math.hpp"
 
 #include <atomic>
 
 namespace vk {
 
-class Sampler : public Object<Sampler, VkSampler>
+struct SamplerState : sw::Memset<SamplerState>
 {
-public:
-	Sampler(const VkSamplerCreateInfo *pCreateInfo, void *mem, const vk::SamplerYcbcrConversion *ycbcrConversion)
-	    : magFilter(pCreateInfo->magFilter)
-	    , minFilter(pCreateInfo->minFilter)
-	    , mipmapMode(pCreateInfo->mipmapMode)
-	    , addressModeU(pCreateInfo->addressModeU)
-	    , addressModeV(pCreateInfo->addressModeV)
-	    , addressModeW(pCreateInfo->addressModeW)
-	    , mipLodBias(pCreateInfo->mipLodBias)
-	    , anisotropyEnable(pCreateInfo->anisotropyEnable)
-	    , maxAnisotropy(pCreateInfo->maxAnisotropy)
-	    , compareEnable(pCreateInfo->compareEnable)
-	    , compareOp(pCreateInfo->compareOp)
-	    , minLod(ClampLod(pCreateInfo->minLod))
-	    , maxLod(ClampLod(pCreateInfo->maxLod))
-	    , borderColor(pCreateInfo->borderColor)
-	    , unnormalizedCoordinates(pCreateInfo->unnormalizedCoordinates)
-	    , ycbcrConversion(ycbcrConversion)
-	{
-	}
-
-	static size_t ComputeRequiredAllocationSize(const VkSamplerCreateInfo *pCreateInfo)
-	{
-		return 0;
-	}
+	SamplerState(const VkSamplerCreateInfo *pCreateInfo, const vk::SamplerYcbcrConversion *ycbcrConversion);
 
 	// Prevents accessing mipmap levels out of range.
 	static float ClampLod(float lod)
@@ -58,7 +34,6 @@
 		return sw::clamp(lod, 0.0f, (float)(sw::MAX_TEXTURE_LOD));
 	}
 
-	const uint32_t id = nextID++;
 	const VkFilter magFilter = VK_FILTER_NEAREST;
 	const VkFilter minFilter = VK_FILTER_NEAREST;
 	const VkSamplerMipmapMode mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
@@ -75,7 +50,22 @@
 	const VkBorderColor borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
 	const VkBool32 unnormalizedCoordinates = VK_FALSE;
 
-	const vk::SamplerYcbcrConversion *ycbcrConversion = nullptr;
+	VkSamplerYcbcrModelConversion ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY;
+	bool studioSwing = false;    // Narrow range
+	bool swappedChroma = false;  // Cb/Cr components in reverse order
+};
+
+class Sampler : public Object<Sampler, VkSampler>, public SamplerState
+{
+public:
+	Sampler(const VkSamplerCreateInfo *pCreateInfo, void *mem, const vk::SamplerYcbcrConversion *ycbcrConversion);
+
+	static size_t ComputeRequiredAllocationSize(const VkSamplerCreateInfo *pCreateInfo)
+	{
+		return 0;
+	}
+
+	const uint32_t id = nextID++;
 
 private:
 	static std::atomic<uint32_t> nextID;