Implement 1D image sampling

1D images are currently sampled as if they're 2D images, by setting the
second coordinate to 0.

Bug: b/129523279
Test: dEQP-VK.binding_model.shader_access.primary_cmd_buf.combined_image_sampler_mutable.fragment.single_descriptor.1d
Change-Id: I9aa20cb8b4d43cfdce28c1ec697a72fb6c49c6b5
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/29775
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Chris Forbes <chrisforbes@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
diff --git a/src/Device/Sampler.hpp b/src/Device/Sampler.hpp
index 841fe70..75bc8e1 100644
--- a/src/Device/Sampler.hpp
+++ b/src/Device/Sampler.hpp
@@ -70,14 +70,17 @@
 
 	enum TextureType ENUM_UNDERLYING_TYPE_UNSIGNED_INT
 	{
-		TEXTURE_NULL,
+		TEXTURE_NULL,       // TODO(b/129523279): Eliminate
+		TEXTURE_1D,
 		TEXTURE_2D,
-		TEXTURE_RECTANGLE,
-		TEXTURE_CUBE,
 		TEXTURE_3D,
+		TEXTURE_RECTANGLE,  // TODO(b/129523279): Eliminate
+		TEXTURE_CUBE,
+		TEXTURE_1D_ARRAY,
 		TEXTURE_2D_ARRAY,
+		TEXTURE_CUBE_ARRAY,
 
-		TEXTURE_LAST = TEXTURE_2D_ARRAY
+		TEXTURE_LAST = TEXTURE_CUBE_ARRAY
 	};
 
 	enum FilterType ENUM_UNDERLYING_TYPE_UNSIGNED_INT
diff --git a/src/Pipeline/SpirvShader.hpp b/src/Pipeline/SpirvShader.hpp
index d11cbce..634833d 100644
--- a/src/Pipeline/SpirvShader.hpp
+++ b/src/Pipeline/SpirvShader.hpp
@@ -868,6 +868,7 @@
 			Pointer<Byte> image, Pointer<SIMD::Float> in, Pointer<Byte> out);
 
 		// TODO(b/129523279): Eliminate conversion and use vk::Sampler members directly.
+		static sw::TextureType convertTextureType(VkImageViewType imageViewType);
 		static sw::FilterType convertFilterMode(const vk::Sampler *sampler);
 		static sw::MipmapType convertMipmapMode(const vk::Sampler *sampler);
 		static sw::AddressingMode convertAddressingMode(VkSamplerAddressMode);
diff --git a/src/Pipeline/SpirvShaderSampling.cpp b/src/Pipeline/SpirvShaderSampling.cpp
index d8bf659..8dca8fb 100644
--- a/src/Pipeline/SpirvShaderSampling.cpp
+++ b/src/Pipeline/SpirvShaderSampling.cpp
@@ -78,13 +78,10 @@
         const vk::ImageView *imageView, const vk::Sampler *sampler,
         Pointer<Byte> image, Pointer<SIMD::Float> in, Pointer<Byte> out)
 {
-	SIMD::Float u = in[0];
-	SIMD::Float v = in[1];
-
 	Pointer<Byte> constants;  // FIXME(b/129523279)
 
 	Sampler::State samplerState;
-	samplerState.textureType = TEXTURE_2D;                  ASSERT(imageView->getType() == VK_IMAGE_VIEW_TYPE_2D);  // TODO(b/129523279)
+	samplerState.textureType = convertTextureType(imageView->getType());
 	samplerState.textureFormat = imageView->getFormat();
 	samplerState.textureFilter = convertFilterMode(sampler);
 
@@ -110,6 +107,7 @@
 	SamplerCore s(constants, samplerState);
 
 	Pointer<Byte> texture = image + OFFSET(vk::SampledImageDescriptor, texture);  // sw::Texture*
+	SIMD::Float uv[2];
 	SIMD::Float w(0);     // TODO(b/129523279)
 	SIMD::Float q(0);     // TODO(b/129523279)
 	SIMD::Float bias(0);
@@ -118,12 +116,32 @@
 	Vector4f offset;      // TODO(b/129523279)
 	SamplerFunction samplerFunction = { samplerMethod, None };  // TODO(b/129523279)
 
-	if(samplerMethod == Lod)
+	// TODO(b/129523279): Currently 1D textures are treated as 2D by setting the second coordinate to 0.
+	// Implement optimized 1D sampling.
+	uv[1] = SIMD::Float(0);
+
+	int coordinateCount = 0;
+	switch(imageView->getType())
 	{
-		bias = in[2];  // TODO(b/129523279): Index depends on view dimensions and other optional operands.
+	case VK_IMAGE_VIEW_TYPE_1D: coordinateCount = 1; break;
+	case VK_IMAGE_VIEW_TYPE_2D: coordinateCount = 2; break;
+	default:
+		UNIMPLEMENTED("imageView type %d", imageView->getType());
 	}
 
-	Vector4f sample = s.sampleTexture(texture, u, v, w, q, bias, dsx, dsy, offset, samplerFunction);
+	for(int i = 0; i < coordinateCount; i++)
+	{
+		uv[i] = in[i];
+	}
+
+	if(samplerMethod == Lod)
+	{
+		// Lod is the second optional image operand, and is incompatible with the first one (Bias),
+		// so it always comes after the coordinates.
+		bias = in[coordinateCount];
+	}
+
+	Vector4f sample = s.sampleTexture(texture, uv[0], uv[1], w, q, bias, dsx, dsy, offset, samplerFunction);
 
 	Pointer<SIMD::Float> rgba = out;
 	rgba[0] = sample.x;
@@ -132,6 +150,23 @@
 	rgba[3] = sample.w;
 }
 
+sw::TextureType SpirvShader::convertTextureType(VkImageViewType imageViewType)
+{
+	switch(imageViewType)
+	{
+	case VK_IMAGE_VIEW_TYPE_1D:         return TEXTURE_1D;
+	case VK_IMAGE_VIEW_TYPE_2D:         return TEXTURE_2D;
+//	case VK_IMAGE_VIEW_TYPE_3D:         return TEXTURE_3D;
+//	case VK_IMAGE_VIEW_TYPE_CUBE:       return TEXTURE_CUBE;
+//	case VK_IMAGE_VIEW_TYPE_1D_ARRAY:   return TEXTURE_1D_ARRAY;
+//	case VK_IMAGE_VIEW_TYPE_2D_ARRAY:   return TEXTURE_2D_ARRAY;
+//	case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: return TEXTURE_CUBE_ARRAY;
+	default:
+		UNIMPLEMENTED("imageViewType %d", imageViewType);
+		return TEXTURE_2D;
+	}
+}
+
 sw::FilterType SpirvShader::convertFilterMode(const vk::Sampler *sampler)
 {
 	switch(sampler->magFilter)