Plumb constants through to the sampler, and make sRGB work

Change-Id: Ib4974a5f0dea325e198905cb94bae138ccac4c6e
Test: dEQP-VK.texture.swizzle.component_mapping.*
Bug: b/129523279
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/29950
Tested-by: Chris Forbes <chrisforbes@google.com>
Presubmit-Ready: Chris Forbes <chrisforbes@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
diff --git a/src/Pipeline/ComputeProgram.cpp b/src/Pipeline/ComputeProgram.cpp
index 50445b7..f0c7d61 100644
--- a/src/Pipeline/ComputeProgram.cpp
+++ b/src/Pipeline/ComputeProgram.cpp
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 #include "ComputeProgram.hpp"
+#include "Constants.hpp"
 
 #include "Vulkan/VkDebug.hpp"
 #include "Vulkan/VkPipelineLayout.hpp"
@@ -49,6 +50,7 @@
 		routine.descriptorSets = data + OFFSET(Data, descriptorSets);
 		routine.descriptorDynamicOffsets = data + OFFSET(Data, descriptorDynamicOffsets);
 		routine.pushConstants = data + OFFSET(Data, pushConstants);
+		routine.constants = *Pointer<Pointer<Byte>>(data + OFFSET(Data, constants));
 
 		auto &modes = shader->getModes();
 
@@ -189,6 +191,7 @@
 		data.numWorkgroups[Z] = groupCountZ;
 		data.numWorkgroups[3] = 0;
 		data.pushConstants = pushConstants;
+		data.constants = &sw::constants;
 
 		// TODO(bclayton): Split work across threads.
 		for (uint32_t groupZ = 0; groupZ < groupCountZ; groupZ++)
diff --git a/src/Pipeline/ComputeProgram.hpp b/src/Pipeline/ComputeProgram.hpp
index ab50592..61892b4 100644
--- a/src/Pipeline/ComputeProgram.hpp
+++ b/src/Pipeline/ComputeProgram.hpp
@@ -34,6 +34,7 @@
 	using namespace rr;
 
 	class DescriptorSetsLayout;
+	struct Constants;
 
 	// ComputeProgram builds a SPIR-V compute shader.
 	class ComputeProgram : public Function<Void(Pointer<Byte>)>
@@ -69,6 +70,7 @@
 			uint4 numWorkgroups;
 			uint4 workgroupID;
 			PushConstantStorage pushConstants;
+			const Constants *constants;
 		};
 
 		SpirvRoutine routine;
diff --git a/src/Pipeline/PixelProgram.cpp b/src/Pipeline/PixelProgram.cpp
index c7e54fa..dca8704 100644
--- a/src/Pipeline/PixelProgram.cpp
+++ b/src/Pipeline/PixelProgram.cpp
@@ -57,6 +57,7 @@
 		routine.descriptorSets = data + OFFSET(DrawData, descriptorSets);
 		routine.descriptorDynamicOffsets = data + OFFSET(DrawData, descriptorDynamicOffsets);
 		routine.pushConstants = data + OFFSET(DrawData, pushConstants);
+		routine.constants = *Pointer<Pointer<Byte>>(data + OFFSET(DrawData, constants));
 
 		auto it = spirvShader->inputBuiltins.find(spv::BuiltInFrontFacing);
 		if (it != spirvShader->inputBuiltins.end())
diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp
index 049d7f9..ff6c164 100644
--- a/src/Pipeline/SpirvShader.cpp
+++ b/src/Pipeline/SpirvShader.cpp
@@ -4517,7 +4517,7 @@
 		}
 
 		Array<SIMD::Float> out(4);
-		Call<ImageSampler>(samplerFunc, sampledImage.base, &in[0], &out[0]);
+		Call<ImageSampler>(samplerFunc, sampledImage.base, &in[0], &out[0], state->routine->constants);
 
 		for (int i = 0; i < 4; i++) { result.move(i, out[i]); }
 
diff --git a/src/Pipeline/SpirvShader.hpp b/src/Pipeline/SpirvShader.hpp
index 4910954..73e3e4a 100644
--- a/src/Pipeline/SpirvShader.hpp
+++ b/src/Pipeline/SpirvShader.hpp
@@ -258,7 +258,7 @@
 		using InsnStore = std::vector<uint32_t>;
 		InsnStore insns;
 
-		using ImageSampler = void(void* image, void* uvsIn, void* texelOut);
+		using ImageSampler = void(void* image, void* uvsIn, void* texelOut, void* constants);
 		using GetImageSampler = ImageSampler*(const vk::ImageView *imageView, const vk::Sampler *sampler);
 
 		/* Pseudo-iterator over SPIRV instructions, designed to support range-based-for. */
@@ -868,7 +868,7 @@
 		static void emitSamplerFunction(
 			SamplerMethod samplerMethod,
 			const vk::ImageView *imageView, const vk::Sampler *sampler,
-			Pointer<Byte> image, Pointer<SIMD::Float> in, Pointer<Byte> out);
+			Pointer<Byte> image, Pointer<SIMD::Float> in, Pointer<Byte> out, Pointer<Byte> constants);
 
 		// TODO(b/129523279): Eliminate conversion and use vk::Sampler members directly.
 		static sw::TextureType convertTextureType(VkImageViewType imageViewType);
@@ -898,6 +898,7 @@
 		Pointer<Pointer<Byte>> descriptorSets;
 		Pointer<Int> descriptorDynamicOffsets;
 		Pointer<Byte> pushConstants;
+		Pointer<Byte> constants;
 		Int killMask = Int{0};
 		SIMD::Int windowSpacePosition[2];
 
diff --git a/src/Pipeline/SpirvShaderSampling.cpp b/src/Pipeline/SpirvShaderSampling.cpp
index 8709464..5d978d2 100644
--- a/src/Pipeline/SpirvShaderSampling.cpp
+++ b/src/Pipeline/SpirvShaderSampling.cpp
@@ -63,11 +63,12 @@
 	if (it != cache.end()) { return it->second; }
 
 	// TODO: Hold a separate mutex lock for the sampler being built.
-	auto function = rr::Function<Void(Pointer<Byte> image, Pointer<SIMD::Float>, Pointer<SIMD::Float>)>();
+	auto function = rr::Function<Void(Pointer<Byte> image, Pointer<SIMD::Float>, Pointer<SIMD::Float>, Pointer<Byte>)>();
 	Pointer<Byte> image = function.Arg<0>();
 	Pointer<SIMD::Float> in = function.Arg<1>();
 	Pointer<SIMD::Float> out = function.Arg<2>();
-	emitSamplerFunction(samplerMethod, imageView, sampler, image, in, out);
+	Pointer<Byte> constants = function.Arg<3>();
+	emitSamplerFunction(samplerMethod, imageView, sampler, image, in, out, constants);
 	auto fptr = reinterpret_cast<ImageSampler*>((void *)function("sampler")->getEntry());
 	cache.emplace(key, fptr);
 	return fptr;
@@ -76,10 +77,8 @@
 void SpirvShader::emitSamplerFunction(
         SamplerMethod samplerMethod,
         const vk::ImageView *imageView, const vk::Sampler *sampler,
-        Pointer<Byte> image, Pointer<SIMD::Float> in, Pointer<Byte> out)
+        Pointer<Byte> image, Pointer<SIMD::Float> in, Pointer<Byte> out, Pointer<Byte> constants)
 {
-	Pointer<Byte> constants;  // FIXME(b/129523279)
-
 	Sampler::State samplerState;
 	samplerState.textureType = convertTextureType(imageView->getType());
 	samplerState.textureFormat = imageView->getFormat();
@@ -89,7 +88,7 @@
 	samplerState.addressingModeV = convertAddressingMode(sampler->addressModeV);
 	samplerState.addressingModeW = convertAddressingMode(sampler->addressModeW);
 	samplerState.mipmapFilter = convertMipmapMode(sampler);
-	samplerState.sRGB = false;                              ASSERT(imageView->getFormat().isSRGBformat() == false);  // TODO(b/129523279)
+	samplerState.sRGB = imageView->getFormat().isSRGBformat();
 	samplerState.swizzle = imageView->getComponentMapping();
 	samplerState.highPrecisionFiltering = false;
 	samplerState.compare = COMPARE_BYPASS;                  ASSERT(sampler->compareEnable == VK_FALSE);  // TODO(b/129523279)
diff --git a/src/Pipeline/VertexProgram.cpp b/src/Pipeline/VertexProgram.cpp
index 63c890f..686db48 100644
--- a/src/Pipeline/VertexProgram.cpp
+++ b/src/Pipeline/VertexProgram.cpp
@@ -44,6 +44,7 @@
 		routine.descriptorSets = data + OFFSET(DrawData, descriptorSets);
 		routine.descriptorDynamicOffsets = data + OFFSET(DrawData, descriptorDynamicOffsets);
 		routine.pushConstants = data + OFFSET(DrawData, pushConstants);
+		routine.constants = *Pointer<Pointer<Byte>>(data + OFFSET(DrawData, constants));
 
 		it = spirvShader->inputBuiltins.find(spv::BuiltInSubgroupSize);
 		if (it != spirvShader->inputBuiltins.end())