Implement OpImageSampleExplicitLod

Emit a call to a different trampoline function for generating the
sampler code, which unifies the implementation with
OpImageSampleExplicitLod's by using a common EmitImageSample which
takes a sampler 'method' enum. This is then passed at shader execution
time to emitSamplerFunction.

The lod parameter is parsed from the instruction stream in
EmitImageSample. Other (optional) image operands are left unimplemented
for now.

Bug: b/129523279
Test: dEQP-VK.binding_model.shader_access.primary_cmd_buf.combined_image_sampler_mutable.fragment.single_descriptor.2d
Change-Id: I265b81d953fe5a0496d029704a0f5eeff4229823
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/29774
Tested-by: Nicolas Capens <nicolascapens@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Reviewed-by: Chris Forbes <chrisforbes@google.com>
diff --git a/src/Pipeline/SpirvShader.hpp b/src/Pipeline/SpirvShader.hpp
index 0d5c154..d11cbce 100644
--- a/src/Pipeline/SpirvShader.hpp
+++ b/src/Pipeline/SpirvShader.hpp
@@ -16,6 +16,7 @@
 #define sw_SpirvShader_hpp
 
 #include "ShaderCore.hpp"
+#include "SamplerCore.hpp"
 #include "SpirvID.hpp"
 #include "System/Types.hpp"
 #include "Vulkan/VkDebug.hpp"
@@ -256,6 +257,9 @@
 		using InsnStore = std::vector<uint32_t>;
 		InsnStore insns;
 
+		using ImageSampler = void(void* image, void* uvsIn, void* texelOut);
+		using GetImageSampler = ImageSampler*(const vk::ImageView *imageView, const vk::Sampler *sampler);
+
 		/* Pseudo-iterator over SPIRV instructions, designed to support range-based-for. */
 		class InsnIterator
 		{
@@ -827,6 +831,8 @@
 		EmitResult EmitKill(InsnIterator insn, EmitState *state) const;
 		EmitResult EmitPhi(InsnIterator insn, EmitState *state) const;
 		EmitResult EmitImageSampleImplicitLod(InsnIterator insn, EmitState *state) const;
+		EmitResult EmitImageSampleExplicitLod(InsnIterator insn, EmitState *state) const;
+		EmitResult EmitImageSample(GetImageSampler getImageSampler, InsnIterator insn, EmitState *state) const;
 		EmitResult EmitImageQuerySize(InsnIterator insn, EmitState *state) const;
 		EmitResult EmitImageRead(InsnIterator insn, EmitState *state) const;
 		EmitResult EmitImageWrite(InsnIterator insn, EmitState *state) const;
@@ -853,10 +859,11 @@
 		// Returns the pair <significand, exponent>
 		std::pair<SIMD::Float, SIMD::Int> Frexp(RValue<SIMD::Float> val) const;
 
-		using ImageSampler = void(void* image, void* uvsIn, void* texelOut);
-
-		static ImageSampler *getImageSampler(const vk::ImageView *imageView, const vk::Sampler *sampler);
+		static ImageSampler *getImageSamplerImplicitLod(const vk::ImageView *imageView, const vk::Sampler *sampler);
+		static ImageSampler *getImageSamplerExplicitLod(const vk::ImageView *imageView, const vk::Sampler *sampler);
+		static ImageSampler *getImageSampler(SamplerMethod samplerMethod, const vk::ImageView *imageView, const vk::Sampler *sampler);
 		static void emitSamplerFunction(
+			SamplerMethod samplerMethod,
 			const vk::ImageView *imageView, const vk::Sampler *sampler,
 			Pointer<Byte> image, Pointer<SIMD::Float> in, Pointer<Byte> out);