Use sampler data from sampler descriptor

Bug: b/129523279
Test: dEQP-VK.glsl.texture_functions.*
Test: dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.*
Change-Id: I4c02a36b35a25772e233346266ff6177a9186b9e
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/30249
Presubmit-Ready: Nicolas Capens <nicolascapens@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Chris Forbes <chrisforbes@google.com>
diff --git a/build/Visual Studio 15 2017 Win64/libvk_swiftshader.vcxproj b/build/Visual Studio 15 2017 Win64/libvk_swiftshader.vcxproj
index 2b11b1d..744d11b 100644
--- a/build/Visual Studio 15 2017 Win64/libvk_swiftshader.vcxproj
+++ b/build/Visual Studio 15 2017 Win64/libvk_swiftshader.vcxproj
@@ -212,7 +212,6 @@
     <ClCompile Include="$(SolutionDir)src\Device\Renderer.cpp" />

     <ClInclude Include="$(SolutionDir)src\Device\Renderer.hpp" />

     <ClInclude Include="$(SolutionDir)src\Device\RoutineCache.hpp" />

-    <ClCompile Include="$(SolutionDir)src\Device\Sampler.cpp" />

     <ClInclude Include="$(SolutionDir)src\Device\Sampler.hpp" />

     <ClCompile Include="$(SolutionDir)src\Device\SetupProcessor.cpp" />

     <ClInclude Include="$(SolutionDir)src\Device\SetupProcessor.hpp" />

diff --git a/build/Visual Studio 15 2017 Win64/libvk_swiftshader.vcxproj.filters b/build/Visual Studio 15 2017 Win64/libvk_swiftshader.vcxproj.filters
index b361084..f2db70a 100644
--- a/build/Visual Studio 15 2017 Win64/libvk_swiftshader.vcxproj.filters
+++ b/build/Visual Studio 15 2017 Win64/libvk_swiftshader.vcxproj.filters
@@ -37,9 +37,6 @@
     <ClCompile Include="$(SolutionDir)src\Device\Renderer.cpp">

       <Filter>src\Device</Filter>

     </ClCompile>

-    <ClCompile Include="$(SolutionDir)src\Device\Sampler.cpp">

-      <Filter>src\Device</Filter>

-    </ClCompile>

     <ClCompile Include="$(SolutionDir)src\Device\SetupProcessor.cpp">

       <Filter>src\Device</Filter>

     </ClCompile>

diff --git a/src/Device/Context.hpp b/src/Device/Context.hpp
index a5a69d5..7700440 100644
--- a/src/Device/Context.hpp
+++ b/src/Device/Context.hpp
@@ -34,7 +34,7 @@
 
 namespace sw
 {
-	class Sampler;
+	struct Sampler;
 	class PixelShader;
 	class VertexShader;
 	class SpirvShader;
diff --git a/src/Device/PixelProcessor.hpp b/src/Device/PixelProcessor.hpp
index b641ab5..6eb8220 100644
--- a/src/Device/PixelProcessor.hpp
+++ b/src/Device/PixelProcessor.hpp
@@ -65,7 +65,7 @@
 			bool frontFaceCCW;
 			VkFormat depthFormat;
 
-			Sampler::State sampler[TEXTURE_IMAGE_UNITS];
+			Sampler sampler[TEXTURE_IMAGE_UNITS];
 		};
 
 		struct State : States
diff --git a/src/Device/Renderer.cpp b/src/Device/Renderer.cpp
index 9886bce..c343193 100644
--- a/src/Device/Renderer.cpp
+++ b/src/Device/Renderer.cpp
@@ -1509,21 +1509,6 @@
 			PixelProcessor::setRoutineCacheSize(configuration.pixelRoutineCacheSize);
 			SetupProcessor::setRoutineCacheSize(configuration.setupRoutineCacheSize);
 
-			switch(configuration.textureSampleQuality)
-			{
-			case 0:  Sampler::setFilterQuality(FILTER_POINT);       break;
-			case 1:  Sampler::setFilterQuality(FILTER_LINEAR);      break;
-			case 2:  Sampler::setFilterQuality(FILTER_ANISOTROPIC); break;
-			default: Sampler::setFilterQuality(FILTER_ANISOTROPIC); break;
-			}
-
-			switch(configuration.mipmapQuality)
-			{
-			case 0:  Sampler::setMipmapQuality(MIPMAP_POINT);  break;
-			case 1:  Sampler::setMipmapQuality(MIPMAP_LINEAR); break;
-			default: Sampler::setMipmapQuality(MIPMAP_LINEAR); break;
-			}
-
 			setPerspectiveCorrection(configuration.perspectiveCorrection);
 
 			switch(configuration.transcendentalPrecision)
diff --git a/src/Device/Sampler.cpp b/src/Device/Sampler.cpp
deleted file mode 100644
index 19e2365..0000000
--- a/src/Device/Sampler.cpp
+++ /dev/null
@@ -1,438 +0,0 @@
-// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//    http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "Sampler.hpp"
-
-#include "Context.hpp"
-#include "Pipeline/PixelRoutine.hpp"
-#include "Vulkan/VkDebug.hpp"
-#include "Vulkan/VkImage.hpp"
-
-#include <cstring>
-
-namespace sw
-{
-	FilterType Sampler::maximumTextureFilterQuality = FILTER_LINEAR;
-	MipmapType Sampler::maximumMipmapFilterQuality = MIPMAP_POINT;
-
-	Sampler::State::State()
-	{
-		memset(this, 0, sizeof(State));
-	}
-
-	Sampler::Sampler()
-	{
-		// FIXME: Mipmap::init
-		static const unsigned int zero = 0x00FF00FF;
-
-		for(int level = 0; level < MIPMAP_LEVELS; level++)
-		{
-			Mipmap &mipmap = texture.mipmap[level];
-
-			memset(&mipmap, 0, sizeof(Mipmap));
-
-			for(int face = 0; face < 6; face++)
-			{
-				mipmap.buffer[face] = &zero;
-			}
-		}
-
-		textureFormat = VK_FORMAT_UNDEFINED;
-		textureType = TEXTURE_NULL;
-
-		textureFilter = FILTER_LINEAR;
-		addressingModeU = ADDRESSING_WRAP;
-		addressingModeV = ADDRESSING_WRAP;
-		addressingModeW = ADDRESSING_WRAP;
-		mipmapFilterState = MIPMAP_NONE;
-		sRGB = false;
-		gather = false;
-		highPrecisionFiltering = false;
-		border = 0;
-
-		swizzle = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
-
-		compare = COMPARE_BYPASS;
-
-		exp2LOD = 1.0f;
-
-		texture.maxLod = MAX_TEXTURE_LOD;
-		texture.minLod = 0;
-	}
-
-	Sampler::~Sampler()
-	{
-	}
-
-	Sampler::State Sampler::samplerState() const
-	{
-		State state;
-
-		if(textureType != TEXTURE_NULL)
-		{
-			state.textureType = textureType;
-			state.textureFormat = textureFormat;
-			state.textureFilter = getTextureFilter();
-			state.addressingModeU = getAddressingModeU();
-			state.addressingModeV = getAddressingModeV();
-			state.addressingModeW = getAddressingModeW();
-			state.mipmapFilter = mipmapFilter();
-			state.swizzle = swizzle;
-			state.highPrecisionFiltering = highPrecisionFiltering;
-			state.compare = getCompareFunc();
-
-			#if PERF_PROFILE
-				state.compressedFormat = Surface::isCompressed(externalTextureFormat);
-			#endif
-		}
-
-		return state;
-	}
-
-	void Sampler::setTextureLevel(int face, int level, vk::Image *image, TextureType type)
-	{
-		if(image)
-		{
-			Mipmap &mipmap = texture.mipmap[level];
-
-			border = image->isCube() ? 1 : 0;
-			VkImageSubresourceLayers subresourceLayers =
-			{
-				VK_IMAGE_ASPECT_COLOR_BIT,
-				static_cast<uint32_t>(level),
-				static_cast<uint32_t>(face),
-				1
-			};
-			mipmap.buffer[face] = image->getTexelPointer({ -border, -border, 0 }, subresourceLayers);
-
-			if(face == 0)
-			{
-				VkImageAspectFlagBits aspect = VK_IMAGE_ASPECT_COLOR_BIT; // FIXME: get proper aspect
-				textureFormat = image->getFormat(aspect);
-
-				VkExtent3D mipLevelExtent = image->getMipLevelExtent(level);
-				int width = mipLevelExtent.width;
-				int height = mipLevelExtent.height;
-				int depth = mipLevelExtent.depth;
-				int pitchP = image->rowPitchBytes(aspect, level);
-				int sliceP = image->slicePitchBytes(aspect, level);
-
-				if(level == 0)
-				{
-					texture.widthHeightLOD[0] = width * exp2LOD;
-					texture.widthHeightLOD[1] = width * exp2LOD;
-					texture.widthHeightLOD[2] = height * exp2LOD;
-					texture.widthHeightLOD[3] = height * exp2LOD;
-
-					texture.widthLOD[0] = width * exp2LOD;
-					texture.widthLOD[1] = width * exp2LOD;
-					texture.widthLOD[2] = width * exp2LOD;
-					texture.widthLOD[3] = width * exp2LOD;
-
-					texture.heightLOD[0] = height * exp2LOD;
-					texture.heightLOD[1] = height * exp2LOD;
-					texture.heightLOD[2] = height * exp2LOD;
-					texture.heightLOD[3] = height * exp2LOD;
-
-					texture.depthLOD[0] = depth * exp2LOD;
-					texture.depthLOD[1] = depth * exp2LOD;
-					texture.depthLOD[2] = depth * exp2LOD;
-					texture.depthLOD[3] = depth * exp2LOD;
-				}
-
-				if(textureFormat.isFloatFormat())
-				{
-					mipmap.fWidth[0] = (float)width / 65536.0f;
-					mipmap.fWidth[1] = (float)width / 65536.0f;
-					mipmap.fWidth[2] = (float)width / 65536.0f;
-					mipmap.fWidth[3] = (float)width / 65536.0f;
-
-					mipmap.fHeight[0] = (float)height / 65536.0f;
-					mipmap.fHeight[1] = (float)height / 65536.0f;
-					mipmap.fHeight[2] = (float)height / 65536.0f;
-					mipmap.fHeight[3] = (float)height / 65536.0f;
-
-					mipmap.fDepth[0] = (float)depth / 65536.0f;
-					mipmap.fDepth[1] = (float)depth / 65536.0f;
-					mipmap.fDepth[2] = (float)depth / 65536.0f;
-					mipmap.fDepth[3] = (float)depth / 65536.0f;
-				}
-
-				short halfTexelU = 0x8000 / width;
-				short halfTexelV = 0x8000 / height;
-				short halfTexelW = 0x8000 / depth;
-
-				mipmap.uHalf[0] = halfTexelU;
-				mipmap.uHalf[1] = halfTexelU;
-				mipmap.uHalf[2] = halfTexelU;
-				mipmap.uHalf[3] = halfTexelU;
-
-				mipmap.vHalf[0] = halfTexelV;
-				mipmap.vHalf[1] = halfTexelV;
-				mipmap.vHalf[2] = halfTexelV;
-				mipmap.vHalf[3] = halfTexelV;
-
-				mipmap.wHalf[0] = halfTexelW;
-				mipmap.wHalf[1] = halfTexelW;
-				mipmap.wHalf[2] = halfTexelW;
-				mipmap.wHalf[3] = halfTexelW;
-
-				mipmap.width[0] = width;
-				mipmap.width[1] = width;
-				mipmap.width[2] = width;
-				mipmap.width[3] = width;
-
-				mipmap.height[0] = height;
-				mipmap.height[1] = height;
-				mipmap.height[2] = height;
-				mipmap.height[3] = height;
-
-				mipmap.depth[0] = depth;
-				mipmap.depth[1] = depth;
-				mipmap.depth[2] = depth;
-				mipmap.depth[3] = depth;
-
-				mipmap.onePitchP[0] = 1;
-				mipmap.onePitchP[1] = pitchP;
-				mipmap.onePitchP[2] = 1;
-				mipmap.onePitchP[3] = pitchP;
-
-				mipmap.pitchP[0] = pitchP;
-				mipmap.pitchP[1] = pitchP;
-				mipmap.pitchP[2] = pitchP;
-				mipmap.pitchP[3] = pitchP;
-
-				mipmap.sliceP[0] = sliceP;
-				mipmap.sliceP[1] = sliceP;
-				mipmap.sliceP[2] = sliceP;
-				mipmap.sliceP[3] = sliceP;
-
-				if(textureFormat.hasYuvFormat())
-				{
-					unsigned int YStride = pitchP;
-					unsigned int YSize = YStride * height;
-					unsigned int CStride = align<16>(YStride / 2);
-					unsigned int CSize = CStride * height / 2;
-
-					mipmap.buffer[1] = (byte*)mipmap.buffer[0] + YSize;
-					mipmap.buffer[2] = (byte*)mipmap.buffer[1] + CSize;
-
-					texture.mipmap[1].width[0] = width / 2;
-					texture.mipmap[1].width[1] = width / 2;
-					texture.mipmap[1].width[2] = width / 2;
-					texture.mipmap[1].width[3] = width / 2;
-					texture.mipmap[1].height[0] = height / 2;
-					texture.mipmap[1].height[1] = height / 2;
-					texture.mipmap[1].height[2] = height / 2;
-					texture.mipmap[1].height[3] = height / 2;
-					texture.mipmap[1].onePitchP[0] = 1;
-					texture.mipmap[1].onePitchP[1] = CStride;
-					texture.mipmap[1].onePitchP[2] = 1;
-					texture.mipmap[1].onePitchP[3] = CStride;
-				}
-			}
-		}
-
-		textureType = type;
-	}
-
-	void Sampler::setTextureFilter(FilterType textureFilter)
-	{
-		this->textureFilter = (FilterType)min(textureFilter, maximumTextureFilterQuality);
-	}
-
-	void Sampler::setMipmapFilter(MipmapType mipmapFilter)
-	{
-		mipmapFilterState = (MipmapType)min(mipmapFilter, maximumMipmapFilterQuality);
-	}
-
-	void Sampler::setGatherEnable(bool enable)
-	{
-		gather = enable;
-	}
-
-	void Sampler::setAddressingModeU(AddressingMode addressingMode)
-	{
-		addressingModeU = addressingMode;
-	}
-
-	void Sampler::setAddressingModeV(AddressingMode addressingMode)
-	{
-		addressingModeV = addressingMode;
-	}
-
-	void Sampler::setAddressingModeW(AddressingMode addressingMode)
-	{
-		addressingModeW = addressingMode;
-	}
-
-	void Sampler::setMaxAnisotropy(float maxAnisotropy)
-	{
-		texture.maxAnisotropy = maxAnisotropy;
-	}
-
-	void Sampler::setHighPrecisionFiltering(bool highPrecisionFiltering)
-	{
-		this->highPrecisionFiltering = highPrecisionFiltering;
-	}
-
-	void Sampler::setCompareFunc(CompareFunc compare)
-	{
-		this->compare = compare;
-	}
-
-	void Sampler::setMinLod(float minLod)
-	{
-		texture.minLod = clamp(minLod, 0.0f, (float)(MAX_TEXTURE_LOD));
-	}
-
-	void Sampler::setMaxLod(float maxLod)
-	{
-		texture.maxLod = clamp(maxLod, 0.0f, (float)(MAX_TEXTURE_LOD));
-	}
-
-	void Sampler::setFilterQuality(FilterType maximumFilterQuality)
-	{
-		Sampler::maximumTextureFilterQuality = maximumFilterQuality;
-	}
-
-	void Sampler::setMipmapQuality(MipmapType maximumFilterQuality)
-	{
-		Sampler::maximumMipmapFilterQuality = maximumFilterQuality;
-	}
-
-	void Sampler::setMipmapLOD(float LOD)
-	{
-		exp2LOD = exp2(LOD);
-	}
-
-	bool Sampler::hasTexture() const
-	{
-		return textureType != TEXTURE_NULL;
-	}
-
-	bool Sampler::hasUnsignedTexture() const
-	{
-		return textureFormat.isUnsignedComponent(0) &&
-		       textureFormat.isUnsignedComponent(1) &&
-		       textureFormat.isUnsignedComponent(2) &&
-		       textureFormat.isUnsignedComponent(3);
-	}
-
-	bool Sampler::hasCubeTexture() const
-	{
-		return textureType == TEXTURE_CUBE;
-	}
-
-	bool Sampler::hasVolumeTexture() const
-	{
-		return textureType == TEXTURE_3D || textureType == TEXTURE_2D_ARRAY;
-	}
-
-	const Texture &Sampler::getTextureData()
-	{
-		return texture;
-	}
-
-	MipmapType Sampler::mipmapFilter() const
-	{
-		if(mipmapFilterState != MIPMAP_NONE)
-		{
-			for(int i = 1; i < MIPMAP_LEVELS; i++)
-			{
-				if(texture.mipmap[0].buffer[0] != texture.mipmap[i].buffer[0])
-				{
-					return mipmapFilterState;
-				}
-			}
-		}
-
-		// Only one mipmap level
-		return MIPMAP_NONE;
-	}
-
-	TextureType Sampler::getTextureType() const
-	{
-		return textureType;
-	}
-
-	FilterType Sampler::getTextureFilter() const
-	{
-		// Don't filter 1x1 textures.
-		if(texture.mipmap[0].width[0] == 1 && texture.mipmap[0].height[0] == 1 && texture.mipmap[0].depth[0] == 1)
-		{
-			if(mipmapFilter() == MIPMAP_NONE)
-			{
-				return FILTER_POINT;
-			}
-		}
-
-		FilterType filter = textureFilter;
-
-		if(gather && textureFormat.componentCount() == 1)
-		{
-			filter = FILTER_GATHER;
-		}
-
-		if(textureType != TEXTURE_2D || texture.maxAnisotropy == 1.0f)
-		{
-			return (FilterType)min(filter, FILTER_LINEAR);
-		}
-
-		return filter;
-	}
-
-	AddressingMode Sampler::getAddressingModeU() const
-	{
-		if(textureType == TEXTURE_CUBE)
-		{
-			return border ? ADDRESSING_SEAMLESS : ADDRESSING_CLAMP;
-		}
-
-		return addressingModeU;
-	}
-
-	AddressingMode Sampler::getAddressingModeV() const
-	{
-		if(textureType == TEXTURE_CUBE)
-		{
-			return border ? ADDRESSING_SEAMLESS : ADDRESSING_CLAMP;
-		}
-
-		return addressingModeV;
-	}
-
-	AddressingMode Sampler::getAddressingModeW() const
-	{
-		if(textureType == TEXTURE_2D_ARRAY ||
-		   textureType == TEXTURE_2D ||
-		   textureType == TEXTURE_CUBE ||
-		   textureType == TEXTURE_RECTANGLE)
-		{
-			return ADDRESSING_LAYER;
-		}
-
-		return addressingModeW;
-	}
-
-	CompareFunc Sampler::getCompareFunc() const
-	{
-		if(getTextureFilter() == FILTER_GATHER)
-		{
-			return COMPARE_BYPASS;
-		}
-
-		return compare;
-	}
-}
diff --git a/src/Device/Sampler.hpp b/src/Device/Sampler.hpp
index af6c428..2347fe0 100644
--- a/src/Device/Sampler.hpp
+++ b/src/Device/Sampler.hpp
@@ -50,14 +50,10 @@
 	{
 		Mipmap mipmap[MIPMAP_LEVELS];
 
-		float4 widthHeightLOD;
-		float4 widthLOD;
-		float4 heightLOD;
-		float4 depthLOD;
-
-		float maxAnisotropy;     // FIXME(b/129523279): Part of Vulkan sampler.
-		float minLod;  // FIXME(b/129523279): Part of Vulkan sampler.
-		float maxLod;  // FIXME(b/129523279): Part of Vulkan sampler.
+		float4 widthWidthHeightHeight;
+		float4 width;
+		float4 height;
+		float4 depth;
 	};
 
 	enum SamplerType
@@ -143,91 +139,24 @@
 		SWIZZLE_LAST = SWIZZLE_ONE
 	};
 
-	class Sampler
+	struct Sampler
 	{
-	public:
-		struct State
-		{
-			State();
-
-			TextureType textureType;
-			vk::Format textureFormat;
-			FilterType textureFilter;
-			AddressingMode addressingModeU;
-			AddressingMode addressingModeV;
-			AddressingMode addressingModeW;
-			MipmapType mipmapFilter;
-			VkComponentMapping swizzle;
-			bool highPrecisionFiltering;
-			CompareFunc compare;
-			VkBorderColor border;
-
-			#if PERF_PROFILE
-			bool compressedFormat;
-			#endif
-		};
-
-		Sampler();
-
-		~Sampler();
-
-		State samplerState() const;
-
-		void setTextureLevel(int face, int level, vk::Image *image, TextureType type);
-
-		void setTextureFilter(FilterType textureFilter);
-		void setMipmapFilter(MipmapType mipmapFilter);
-		void setGatherEnable(bool enable);
-		void setAddressingModeU(AddressingMode addressingMode);
-		void setAddressingModeV(AddressingMode addressingMode);
-		void setAddressingModeW(AddressingMode addressingMode);
-		void setMaxAnisotropy(float maxAnisotropy);
-		void setHighPrecisionFiltering(bool highPrecisionFiltering);
-		void setCompareFunc(CompareFunc compare);
-		void setMinLod(float minLod);
-		void setMaxLod(float maxLod);
-
-		static void setFilterQuality(FilterType maximumFilterQuality);
-		static void setMipmapQuality(MipmapType maximumFilterQuality);
-		void setMipmapLOD(float lod);
-
-		bool hasTexture() const;
-		bool hasUnsignedTexture() const;
-		bool hasCubeTexture() const;
-		bool hasVolumeTexture() const;
-
-		const Texture &getTextureData();
-
-	private:
-		MipmapType mipmapFilter() const;
-		TextureType getTextureType() const;
-		FilterType getTextureFilter() const;
-		AddressingMode getAddressingModeU() const;
-		AddressingMode getAddressingModeV() const;
-		AddressingMode getAddressingModeW() const;
-		CompareFunc getCompareFunc() const;
-
-		vk::Format textureFormat;
 		TextureType textureType;
-
+		vk::Format textureFormat;
 		FilterType textureFilter;
 		AddressingMode addressingModeU;
 		AddressingMode addressingModeV;
 		AddressingMode addressingModeW;
-		MipmapType mipmapFilterState;
+		MipmapType mipmapFilter;
 		bool sRGB;
-		bool gather;
-		bool highPrecisionFiltering;
-		int border;
-
 		VkComponentMapping swizzle;
+		bool highPrecisionFiltering;
 		CompareFunc compare;
+		VkBorderColor border;
 
-		Texture texture;
-		float exp2LOD;
-
-		static FilterType maximumTextureFilterQuality;
-		static MipmapType maximumMipmapFilterQuality;
+		#if PERF_PROFILE
+		bool compressedFormat;
+		#endif
 	};
 }
 
diff --git a/src/Device/VertexProcessor.hpp b/src/Device/VertexProcessor.hpp
index 6d57e71..0c04b6c 100644
--- a/src/Device/VertexProcessor.hpp
+++ b/src/Device/VertexProcessor.hpp
@@ -53,7 +53,7 @@
 			bool textureSampling           : 1;   // TODO: Eliminate by querying shader.
 			unsigned char verticesPerPrimitive                : 2; // 1 (points), 2 (lines) or 3 (triangles)
 
-			Sampler::State sampler[VERTEX_TEXTURE_IMAGE_UNITS];
+			Sampler sampler[VERTEX_TEXTURE_IMAGE_UNITS];
 
 			struct Input
 			{
diff --git a/src/Pipeline/SamplerCore.cpp b/src/Pipeline/SamplerCore.cpp
index 96999ac..1bb238c 100644
--- a/src/Pipeline/SamplerCore.cpp
+++ b/src/Pipeline/SamplerCore.cpp
@@ -47,7 +47,7 @@
 
 namespace sw
 {
-	SamplerCore::SamplerCore(Pointer<Byte> &constants, const Sampler::State &state) : constants(constants), state(state)
+	SamplerCore::SamplerCore(Pointer<Byte> &constants, const Sampler &state) : constants(constants), state(state)
 	{
 	}
 
@@ -79,18 +79,18 @@
 		{
 			if(state.textureType != TEXTURE_CUBE)
 			{
-				computeLod(texture, lod, anisotropy, uDelta, vDelta, uuuu, vvvv, lodOrBias.x, dsx, dsy, function);
+				computeLod(texture, sampler, lod, anisotropy, uDelta, vDelta, uuuu, vvvv, lodOrBias.x, dsx, dsy, function);
 			}
 			else
 			{
 				Float4 M;
 				cubeFace(face, uuuu, vvvv, u, v, w, M);
-				computeLodCube(texture, lod, u, v, w, lodOrBias.x, dsx, dsy, M, function);
+				computeLodCube(texture, sampler, lod, u, v, w, lodOrBias.x, dsx, dsy, M, function);
 			}
 		}
 		else
 		{
-			computeLod3D(texture, lod, uuuu, vvvv, wwww, lodOrBias.x, dsx, dsy, function);
+			computeLod3D(texture, sampler, lod, uuuu, vvvv, wwww, lodOrBias.x, dsx, dsy, function);
 		}
 
 		// FIXME: YUV is not supported by the floating point path
@@ -1154,7 +1154,7 @@
 		return lod;
 	}
 
-	void SamplerCore::computeLod(Pointer<Byte> &texture, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Float4 &uuuu, Float4 &vvvv, const Float &lodOrBias, Vector4f &dsx, Vector4f &dsy, SamplerFunction function)
+	void SamplerCore::computeLod(Pointer<Byte> &texture, Pointer<Byte> &sampler, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Float4 &uuuu, Float4 &vvvv, const Float &lodOrBias, Vector4f &dsx, Vector4f &dsy, SamplerFunction function)
 	{
 		if(function != Lod && function != Fetch)
 		{
@@ -1172,8 +1172,8 @@
 				duvdxy = Float4(dudxy.xz, dvdxy.xz);
 			}
 
-			// Scale by texture dimensions and sampler LOD bias.
-			Float4 dUVdxy = duvdxy * *Pointer<Float4>(texture + OFFSET(Texture,widthHeightLOD));
+			// Scale by texture dimensions.
+			Float4 dUVdxy = duvdxy * *Pointer<Float4>(texture + OFFSET(Texture, widthWidthHeightHeight));
 
 			Float4 dUV2dxy = dUVdxy * dUVdxy;
 			Float4 dUV2 = dUV2dxy.xy + dUV2dxy.zw;
@@ -1194,7 +1194,7 @@
 				vDelta = As<Float4>((As<Int4>(dvdx) & mask) | ((As<Int4>(dvdy) & ~mask)));
 
 				anisotropy = lod * Rcp_pp(det);
-				anisotropy = Min(anisotropy, *Pointer<Float>(texture + OFFSET(Texture,maxAnisotropy)));
+				anisotropy = Min(anisotropy, *Pointer<Float>(sampler + OFFSET(vk::Sampler,maxAnisotropy)));
 
 				lod *= Rcp_pp(anisotropy * anisotropy);
 			}
@@ -1221,11 +1221,11 @@
 		}
 		else assert(false);
 
-		lod = Max(lod, *Pointer<Float>(texture + OFFSET(Texture, minLod)));
-		lod = Min(lod, *Pointer<Float>(texture + OFFSET(Texture, maxLod)));
+		lod = Max(lod, *Pointer<Float>(sampler + OFFSET(vk::Sampler, minLod)));
+		lod = Min(lod, *Pointer<Float>(sampler + OFFSET(vk::Sampler, maxLod)));
 	}
 
-	void SamplerCore::computeLodCube(Pointer<Byte> &texture, Float &lod, Float4 &u, Float4 &v, Float4 &w, const Float &lodOrBias, Vector4f &dsx, Vector4f &dsy, Float4 &M, SamplerFunction function)
+	void SamplerCore::computeLodCube(Pointer<Byte> &texture, Pointer<Byte> &sampler, Float &lod, Float4 &u, Float4 &v, Float4 &w, const Float &lodOrBias, Vector4f &dsx, Vector4f &dsy, Float4 &M, SamplerFunction function)
 	{
 		if(function != Lod && function != Fetch)
 		{
@@ -1263,7 +1263,7 @@
 			lod = Max(Float(dudxy.y), Float(dudxy.z));   // FIXME: Max(dudxy.y, dudxy.z);
 
 			// Scale by texture dimension and global LOD.
-			lod *= *Pointer<Float>(texture + OFFSET(Texture,widthLOD));
+			lod *= *Pointer<Float>(texture + OFFSET(Texture,width));
 
 			lod = log2(lod);
 
@@ -1287,11 +1287,11 @@
 		}
 		else assert(false);
 
-		lod = Max(lod, *Pointer<Float>(texture + OFFSET(Texture, minLod)));
-		lod = Min(lod, *Pointer<Float>(texture + OFFSET(Texture, maxLod)));
+		lod = Max(lod, *Pointer<Float>(sampler + OFFSET(vk::Sampler, minLod)));
+		lod = Min(lod, *Pointer<Float>(sampler + OFFSET(vk::Sampler, maxLod)));
 	}
 
-	void SamplerCore::computeLod3D(Pointer<Byte> &texture, Float &lod, Float4 &uuuu, Float4 &vvvv, Float4 &wwww, const Float &lodOrBias, Vector4f &dsx, Vector4f &dsy, SamplerFunction function)
+	void SamplerCore::computeLod3D(Pointer<Byte> &texture, Pointer<Byte> &sampler, Float &lod, Float4 &uuuu, Float4 &vvvv, Float4 &wwww, const Float &lodOrBias, Vector4f &dsx, Vector4f &dsy, SamplerFunction function)
 	{
 		if(function != Lod && function != Fetch)
 		{
@@ -1311,9 +1311,9 @@
 			}
 
 			// Scale by texture dimensions and global LOD.
-			dudxy *= *Pointer<Float4>(texture + OFFSET(Texture,widthLOD));
-			dvdxy *= *Pointer<Float4>(texture + OFFSET(Texture,heightLOD));
-			dsdxy *= *Pointer<Float4>(texture + OFFSET(Texture,depthLOD));
+			dudxy *= *Pointer<Float4>(texture + OFFSET(Texture, width));
+			dvdxy *= *Pointer<Float4>(texture + OFFSET(Texture, height));
+			dsdxy *= *Pointer<Float4>(texture + OFFSET(Texture, depth));
 
 			dudxy *= dudxy;
 			dvdxy *= dvdxy;
@@ -1346,8 +1346,8 @@
 		}
 		else assert(false);
 
-		lod = Max(lod, *Pointer<Float>(texture + OFFSET(Texture, minLod)));
-		lod = Min(lod, *Pointer<Float>(texture + OFFSET(Texture, maxLod)));
+		lod = Max(lod, *Pointer<Float>(sampler + OFFSET(vk::Sampler, minLod)));
+		lod = Min(lod, *Pointer<Float>(sampler + OFFSET(vk::Sampler, maxLod)));
 	}
 
 	void SamplerCore::cubeFace(Int face[4], Float4 &U, Float4 &V, Float4 &x, Float4 &y, Float4 &z, Float4 &M)
diff --git a/src/Pipeline/SamplerCore.hpp b/src/Pipeline/SamplerCore.hpp
index b822299..059daca7 100644
--- a/src/Pipeline/SamplerCore.hpp
+++ b/src/Pipeline/SamplerCore.hpp
@@ -58,7 +58,7 @@
 	class SamplerCore
 	{
 	public:
-		SamplerCore(Pointer<Byte> &constants, const Sampler::State &state);
+		SamplerCore(Pointer<Byte> &constants, const Sampler &state);
 
 		Vector4f sampleTexture(Pointer<Byte> &texture, Pointer<Byte> &sampler, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Float4 &lodOrBias, Vector4f &dsx, Vector4f &dsy, Vector4f &offset, SamplerFunction function);
 
@@ -78,9 +78,9 @@
 		Vector4f sampleFloat3D(Pointer<Byte> &texture, Float4 &u, Float4 &v, Float4 &w, Vector4f &offset, Float &lod, bool secondLOD, SamplerFunction function);
 		Float log2sqrt(Float lod);
 		Float log2(Float lod);
-		void computeLod(Pointer<Byte> &texture, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Float4 &u, Float4 &v, const Float &lodOrBias, Vector4f &dsx, Vector4f &dsy, SamplerFunction function);
-		void computeLodCube(Pointer<Byte> &texture, Float &lod, Float4 &u, Float4 &v, Float4 &w, const Float &lodOrBias, Vector4f &dsx, Vector4f &dsy, Float4 &M, SamplerFunction function);
-		void computeLod3D(Pointer<Byte> &texture, Float &lod, Float4 &u, Float4 &v, Float4 &w, const Float &lodOrBias, Vector4f &dsx, Vector4f &dsy, SamplerFunction function);
+		void computeLod(Pointer<Byte> &texture, Pointer<Byte> &sampler, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Float4 &u, Float4 &v, const Float &lodOrBias, Vector4f &dsx, Vector4f &dsy, SamplerFunction function);
+		void computeLodCube(Pointer<Byte> &texture, Pointer<Byte> &sampler, Float &lod, Float4 &u, Float4 &v, Float4 &w, const Float &lodOrBias, Vector4f &dsx, Vector4f &dsy, Float4 &M, SamplerFunction function);
+		void computeLod3D(Pointer<Byte> &texture, Pointer<Byte> &sampler, Float &lod, Float4 &u, Float4 &v, Float4 &w, const Float &lodOrBias, Vector4f &dsx, Vector4f &dsy, SamplerFunction function);
 		void cubeFace(Int face[4], Float4 &U, Float4 &V, Float4 &x, Float4 &y, Float4 &z, Float4 &M);
 		Short4 applyOffset(Short4 &uvw, Float4 &offset, const Int4 &whd, AddressingMode mode);
 		void computeIndices(UInt index[4], Short4 uuuu, Short4 vvvv, Short4 wwww, Vector4f &offset, const Pointer<Byte> &mipmap, SamplerFunction function);
@@ -110,7 +110,7 @@
 		bool isRGBComponent(int component) const;
 
 		Pointer<Byte> &constants;
-		const Sampler::State &state;
+		const Sampler &state;
 	};
 }
 
diff --git a/src/Pipeline/SpirvShader.hpp b/src/Pipeline/SpirvShader.hpp
index 3423968..b8f1c50 100644
--- a/src/Pipeline/SpirvShader.hpp
+++ b/src/Pipeline/SpirvShader.hpp
@@ -928,7 +928,7 @@
 		std::pair<SIMD::Float, SIMD::Int> Frexp(RValue<SIMD::Float> val) const;
 
 		static ImageSampler *getImageSampler(uint32_t instruction, const vk::ImageView *imageView, const vk::Sampler *sampler);
-		static ImageSampler *emitSamplerFunction(ImageInstruction instruction, const Sampler::State &samplerState);
+		static ImageSampler *emitSamplerFunction(ImageInstruction instruction, const Sampler &samplerState);
 
 		// TODO(b/129523279): Eliminate conversion and use vk::Sampler members directly.
 		static sw::TextureType convertTextureType(VkImageViewType imageViewType);
diff --git a/src/Pipeline/SpirvShaderSampling.cpp b/src/Pipeline/SpirvShaderSampling.cpp
index bd9222d..52bf802 100644
--- a/src/Pipeline/SpirvShaderSampling.cpp
+++ b/src/Pipeline/SpirvShaderSampling.cpp
@@ -50,7 +50,7 @@
 	auto it = cache.find(key);
 	if (it != cache.end()) { return it->second; }
 
-	Sampler::State samplerState = {};
+	Sampler samplerState = {};
 	samplerState.textureType = convertTextureType(imageView->getType());
 	samplerState.textureFormat = imageView->getFormat();
 	samplerState.textureFilter = convertFilterMode(sampler);
@@ -78,7 +78,7 @@
 	return fptr;
 }
 
-SpirvShader::ImageSampler *SpirvShader::emitSamplerFunction(ImageInstruction instruction, const Sampler::State &samplerState)
+SpirvShader::ImageSampler *SpirvShader::emitSamplerFunction(ImageInstruction instruction, const Sampler &samplerState)
 {
 	// TODO(b/129523279): Hold a separate mutex lock for the sampler being built.
 	Function<Void(Pointer<Byte>, Pointer<Byte>, Pointer<SIMD::Float>, Pointer<SIMD::Float>, Pointer<Byte>)> function;
diff --git a/src/Vulkan/VkDescriptorSetLayout.cpp b/src/Vulkan/VkDescriptorSetLayout.cpp
index e769163..f92327c 100644
--- a/src/Vulkan/VkDescriptorSetLayout.cpp
+++ b/src/Vulkan/VkDescriptorSetLayout.cpp
@@ -258,12 +258,9 @@
 
 void SampledImageDescriptor::updateSampler(const vk::Sampler *sampler)
 {
-	if (sampler)
+	if(sampler)
 	{
-		memcpy(&this->sampler, sampler, sizeof(*sampler));
-
-		texture.minLod = sampler->minLod;
-		texture.maxLod = sampler->maxLod;
+		memcpy(&this->sampler, sampler, sizeof(this->sampler));
 	}
 }
 
@@ -357,29 +354,27 @@
 				int pitchP = imageView->rowPitchBytes(aspect, level) / format.bytes();
 				int sliceP = (layers > 1 ? imageView->layerPitchBytes(aspect) : imageView->slicePitchBytes(aspect, level)) / format.bytes();
 
-				float exp2LOD = 1.0f;
-
 				if(mipmapLevel == 0)
 				{
-					texture->widthHeightLOD[0] = width * exp2LOD;
-					texture->widthHeightLOD[1] = width * exp2LOD;
-					texture->widthHeightLOD[2] = height * exp2LOD;
-					texture->widthHeightLOD[3] = height * exp2LOD;
+					texture->widthWidthHeightHeight[0] = width;
+					texture->widthWidthHeightHeight[1] = width;
+					texture->widthWidthHeightHeight[2] = height;
+					texture->widthWidthHeightHeight[3] = height;
 
-					texture->widthLOD[0] = width * exp2LOD;
-					texture->widthLOD[1] = width * exp2LOD;
-					texture->widthLOD[2] = width * exp2LOD;
-					texture->widthLOD[3] = width * exp2LOD;
+					texture->width[0] = width;
+					texture->width[1] = width;
+					texture->width[2] = width;
+					texture->width[3] = width;
 
-					texture->heightLOD[0] = height * exp2LOD;
-					texture->heightLOD[1] = height * exp2LOD;
-					texture->heightLOD[2] = height * exp2LOD;
-					texture->heightLOD[3] = height * exp2LOD;
+					texture->height[0] = height;
+					texture->height[1] = height;
+					texture->height[2] = height;
+					texture->height[3] = height;
 
-					texture->depthLOD[0] = depth * exp2LOD;
-					texture->depthLOD[1] = depth * exp2LOD;
-					texture->depthLOD[2] = depth * exp2LOD;
-					texture->depthLOD[3] = depth * exp2LOD;
+					texture->depth[0] = depth;
+					texture->depth[1] = depth;
+					texture->depth[2] = depth;
+					texture->depth[3] = depth;
 				}
 
 				if(format.isFloatFormat())
diff --git a/src/Vulkan/vulkan.vcxproj b/src/Vulkan/vulkan.vcxproj
index 53aa1b9..1157cac 100644
--- a/src/Vulkan/vulkan.vcxproj
+++ b/src/Vulkan/vulkan.vcxproj
@@ -148,7 +148,6 @@
     <ClCompile Include="..\Device\Point.cpp" />

     <ClCompile Include="..\Device\QuadRasterizer.cpp" />

     <ClCompile Include="..\Device\Renderer.cpp" />

-    <ClCompile Include="..\Device\Sampler.cpp" />

     <ClCompile Include="..\Device\SetupProcessor.cpp" />

     <ClCompile Include="..\Device\SwiftConfig.cpp" />

     <ClCompile Include="..\Device\Vector.cpp" />

diff --git a/src/Vulkan/vulkan.vcxproj.filters b/src/Vulkan/vulkan.vcxproj.filters
index f43aabe..916c493 100644
--- a/src/Vulkan/vulkan.vcxproj.filters
+++ b/src/Vulkan/vulkan.vcxproj.filters
@@ -57,9 +57,6 @@
     <ClCompile Include="..\Device\SetupProcessor.cpp">

       <Filter>Source Files\Device</Filter>

     </ClCompile>

-    <ClCompile Include="..\Device\Sampler.cpp">

-      <Filter>Source Files\Device</Filter>

-    </ClCompile>

     <ClCompile Include="..\Device\Renderer.cpp">

       <Filter>Source Files\Device</Filter>

     </ClCompile>