Clamp LOD during image Fetch for robustness

Bug: chromium:1504556
Change-Id: Ie110fe4e1b065a815c09986ab91b1336ef4761ad
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/72948
Presubmit-Ready: Shahbaz Youssefi <syoussefi@google.com>
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Tested-by: Ben Clayton <bclayton@google.com>
diff --git a/src/Pipeline/SamplerCore.cpp b/src/Pipeline/SamplerCore.cpp
index 403ed3b..d629362 100644
--- a/src/Pipeline/SamplerCore.cpp
+++ b/src/Pipeline/SamplerCore.cpp
@@ -133,6 +133,7 @@
 	{
 		// TODO: Eliminate int-float-int conversion.
 		lod = Float(As<Int>(lodOrBias));
+		lod = Min(lod, state.maxLod);
 	}
 	else if(function == Base || function == Gather)
 	{
diff --git a/src/Pipeline/SpirvShaderSampling.cpp b/src/Pipeline/SpirvShaderSampling.cpp
index 47ce57b..cb2d1d8 100644
--- a/src/Pipeline/SpirvShaderSampling.cpp
+++ b/src/Pipeline/SpirvShaderSampling.cpp
@@ -108,6 +108,11 @@
 				samplerState.minLod = 0.0f;
 				samplerState.maxLod = 0.0f;
 			}
+			// Otherwise make sure LOD is clamped for robustness
+			else
+			{
+				samplerState.maxLod = imageViewState.maxLod;
+			}
 		}
 		else if(samplerMethod == Write)
 		{
diff --git a/src/Vulkan/VkImageView.cpp b/src/Vulkan/VkImageView.cpp
index 511c02c..26b69ae 100644
--- a/src/Vulkan/VkImageView.cpp
+++ b/src/Vulkan/VkImageView.cpp
@@ -89,13 +89,13 @@
 	const Image *sampledImage = image->getSampledImage(viewFormat);
 
 	vk::Format samplingFormat = (image == sampledImage) ? viewFormat : sampledImage->getFormat().getAspectFormat(subresource.aspectMask);
-	pack({ pCreateInfo->viewType, samplingFormat, ResolveComponentMapping(pCreateInfo->components, viewFormat), subresource.levelCount <= 1u });
+	pack({ pCreateInfo->viewType, samplingFormat, ResolveComponentMapping(pCreateInfo->components, viewFormat), static_cast<uint8_t>(subresource.baseMipLevel + subresource.levelCount), subresource.levelCount <= 1u });
 }
 
 Identifier::Identifier(VkFormat bufferFormat)
 {
 	constexpr VkComponentMapping identityMapping = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
-	pack({ VK_IMAGE_VIEW_TYPE_1D, bufferFormat, ResolveComponentMapping(identityMapping, bufferFormat), true });
+	pack({ VK_IMAGE_VIEW_TYPE_1D, bufferFormat, ResolveComponentMapping(identityMapping, bufferFormat), 1, true });
 }
 
 void Identifier::pack(const State &state)
@@ -106,6 +106,7 @@
 	g = static_cast<uint32_t>(state.mapping.g);
 	b = static_cast<uint32_t>(state.mapping.b);
 	a = static_cast<uint32_t>(state.mapping.a);
+	maxLod = state.maxLod;
 	singleMipLevel = state.singleMipLevel;
 }
 
@@ -117,6 +118,7 @@
 		       static_cast<VkComponentSwizzle>(g),
 		       static_cast<VkComponentSwizzle>(b),
 		       static_cast<VkComponentSwizzle>(a) },
+		     static_cast<uint8_t>(maxLod),
 		     static_cast<bool>(singleMipLevel) };
 }
 
diff --git a/src/Vulkan/VkImageView.hpp b/src/Vulkan/VkImageView.hpp
index bf4d666..5acb896 100644
--- a/src/Vulkan/VkImageView.hpp
+++ b/src/Vulkan/VkImageView.hpp
@@ -53,6 +53,7 @@
 		VkImageViewType imageViewType;
 		VkFormat format;
 		VkComponentMapping mapping;
+		uint8_t maxLod;
 		bool singleMipLevel;
 	};
 	State getState() const;
@@ -61,6 +62,7 @@
 	void pack(const State &data);
 
 	// Identifier is a union of this struct and the integer below.
+	static_assert(sw::MIPMAP_LEVELS <= 15);
 	struct
 	{
 		uint32_t imageViewType : 3;
@@ -69,6 +71,7 @@
 		uint32_t g : 3;
 		uint32_t b : 3;
 		uint32_t a : 3;
+		uint32_t maxLod : 4;
 		uint32_t singleMipLevel : 1;
 	};