Add support for depth-stencil-mode to Sampler.

- Add depth-stencil-texture-mode to sampler.
- Support depth-stencil mode in glsTextureTestUtil.

Change-Id: Iedf9db561fea595309638a491e0024f9ca7d51ab
diff --git a/framework/common/tcuTexture.hpp b/framework/common/tcuTexture.hpp
index 84a28b9..307fb2d 100644
--- a/framework/common/tcuTexture.hpp
+++ b/framework/common/tcuTexture.hpp
@@ -205,39 +205,43 @@
 	};
 
 	// Wrap control
-	WrapMode		wrapS;
-	WrapMode		wrapT;
-	WrapMode		wrapR;
+	WrapMode			wrapS;
+	WrapMode			wrapT;
+	WrapMode			wrapR;
 
 	// Minifcation & magnification
-	FilterMode		minFilter;
-	FilterMode		magFilter;
-	float			lodThreshold;		// lod <= lodThreshold ? magnified : minified
+	FilterMode			minFilter;
+	FilterMode			magFilter;
+	float				lodThreshold;		// lod <= lodThreshold ? magnified : minified
 
 	// Coordinate normalization
-	bool			normalizedCoords;
+	bool				normalizedCoords;
 
 	// Shadow comparison
-	CompareMode		compare;
-	int				compareChannel;
+	CompareMode			compare;
+	int					compareChannel;
 
 	// Border color
 	Vec4			borderColor;
 
 	// Seamless cube map filtering
-	bool			seamlessCubeMap;
+	bool				seamlessCubeMap;
 
-	Sampler (WrapMode		wrapS_,
-			 WrapMode		wrapT_,
-			 WrapMode		wrapR_,
-			 FilterMode		minFilter_,
-			 FilterMode		magFilter_,
-			 float			lodThreshold_		= 0.0f,
-			 bool			normalizedCoords_	= true,
-			 CompareMode	compare_			= COMPAREMODE_NONE,
-			 int			compareChannel_		= 0,
-			 const Vec4&	borderColor_		= Vec4(0.0f, 0.0f, 0.0f, 0.0f),
-			 bool			seamlessCubeMap_	= false)
+	// Depth stencil mode
+	DepthStencilMode	depthStencilMode;
+
+	Sampler (WrapMode			wrapS_,
+			 WrapMode			wrapT_,
+			 WrapMode			wrapR_,
+			 FilterMode			minFilter_,
+			 FilterMode			magFilter_,
+			 float				lodThreshold_		= 0.0f,
+			 bool				normalizedCoords_	= true,
+			 CompareMode		compare_			= COMPAREMODE_NONE,
+			 int				compareChannel_		= 0,
+			 const Vec4&		borderColor_		= Vec4(0.0f, 0.0f, 0.0f, 0.0f),
+			 bool				seamlessCubeMap_	= false,
+			 DepthStencilMode	depthStencilMode_	= MODE_DEPTH)
 		: wrapS				(wrapS_)
 		, wrapT				(wrapT_)
 		, wrapR				(wrapR_)
@@ -249,6 +253,7 @@
 		, compareChannel	(compareChannel_)
 		, borderColor		(borderColor_)
 		, seamlessCubeMap	(seamlessCubeMap_)
+		, depthStencilMode	(depthStencilMode_)
 	{
 	}
 
@@ -264,6 +269,7 @@
 		, compareChannel	(0)
 		, borderColor		(0.0f, 0.0f, 0.0f, 0.0f)
 		, seamlessCubeMap	(false)
+		, depthStencilMode	(MODE_DEPTH)
 	{
 	}
 } DE_WARN_UNUSED_TYPE;
diff --git a/modules/glshared/glsTextureTestUtil.cpp b/modules/glshared/glsTextureTestUtil.cpp
index fb31621..0e285d3 100644
--- a/modules/glshared/glsTextureTestUtil.cpp
+++ b/modules/glshared/glsTextureTestUtil.cpp
@@ -152,6 +152,43 @@
 	return tcu::TextureCubeArrayView(numLevels, view.getLevels()+clampedBase);
 }
 
+template <typename ViewType>
+ViewType getEffectiveView (const ViewType& src, std::vector<tcu::ConstPixelBufferAccess>& storage, const tcu::Sampler& sampler)
+{
+	storage.resize(src.getNumLevels());
+
+	ViewType view = ViewType(src.getNumLevels(), &storage[0]);
+
+	for (int levelNdx = 0; levelNdx < src.getNumLevels(); ++levelNdx)
+		storage[levelNdx] = tcu::getEffectiveDepthStencilAccess(src.getLevel(levelNdx), sampler.depthStencilMode);
+
+	return view;
+}
+
+template <>
+tcu::TextureCubeView getEffectiveView (const tcu::TextureCubeView& src, std::vector<tcu::ConstPixelBufferAccess>& storage, const tcu::Sampler& sampler)
+{
+	storage.resize(tcu::CUBEFACE_LAST * src.getNumLevels());
+
+	const tcu::ConstPixelBufferAccess* storagePtrs[tcu::CUBEFACE_LAST] =
+	{
+		&storage[0 * src.getNumLevels()],
+		&storage[1 * src.getNumLevels()],
+		&storage[2 * src.getNumLevels()],
+		&storage[3 * src.getNumLevels()],
+		&storage[4 * src.getNumLevels()],
+		&storage[5 * src.getNumLevels()],
+	};
+
+	tcu::TextureCubeView view = tcu::TextureCubeView(src.getNumLevels(), storagePtrs);
+
+	for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; ++faceNdx)
+	for (int levelNdx = 0; levelNdx < src.getNumLevels(); ++levelNdx)
+		storage[faceNdx * src.getNumLevels() + levelNdx] = tcu::getEffectiveDepthStencilAccess(src.getLevelFace(levelNdx, (tcu::CubeFace)faceNdx), sampler.depthStencilMode);
+
+	return view;
+}
+
 inline float linearInterpolate (float t, float minVal, float maxVal)
 {
 	return minVal + (maxVal - minVal) * t;
@@ -426,17 +463,21 @@
 		return src.sample(params.sampler, s, t, lod);
 }
 
-static void sampleTextureNonProjected (const SurfaceAccess& dst, const tcu::Texture1DView& src, const tcu::Vec4& sq, const ReferenceParams& params)
+static void sampleTextureNonProjected (const SurfaceAccess& dst, const tcu::Texture1DView& rawSrc, const tcu::Vec4& sq, const ReferenceParams& params)
 {
-	float		lodBias		= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
+	// Separate combined DS formats
+	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
+	const tcu::Texture1DView					src					= getEffectiveView(rawSrc, srcLevelStorage, params.sampler);
 
-	tcu::IVec2	dstSize		= tcu::IVec2(dst.getWidth(), dst.getHeight());
-	int			srcSize		= src.getWidth();
+	float										lodBias				= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
+
+	tcu::IVec2									dstSize				= tcu::IVec2(dst.getWidth(), dst.getHeight());
+	int											srcSize				= src.getWidth();
 
 	// Coordinates and lod per triangle.
-	tcu::Vec3	triS[2]		= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
-	float		triLod[2]	= { de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0]) + lodBias, params.minLod, params.maxLod),
-								de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[1]) + lodBias, params.minLod, params.maxLod) };
+	tcu::Vec3									triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
+	float										triLod[2]			= { de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0]) + lodBias, params.minLod, params.maxLod),
+																		de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[1]) + lodBias, params.minLod, params.maxLod) };
 
 	for (int y = 0; y < dst.getHeight(); y++)
 	{
@@ -457,18 +498,22 @@
 	}
 }
 
-static void sampleTextureNonProjected (const SurfaceAccess& dst, const tcu::Texture2DView& src, const tcu::Vec4& sq, const tcu::Vec4& tq, const ReferenceParams& params)
+static void sampleTextureNonProjected (const SurfaceAccess& dst, const tcu::Texture2DView& rawSrc, const tcu::Vec4& sq, const tcu::Vec4& tq, const ReferenceParams& params)
 {
-	float		lodBias		= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
+	// Separate combined DS formats
+	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
+	const tcu::Texture2DView					src					= getEffectiveView(rawSrc, srcLevelStorage, params.sampler);
 
-	tcu::IVec2	dstSize		= tcu::IVec2(dst.getWidth(), dst.getHeight());
-	tcu::IVec2	srcSize		= tcu::IVec2(src.getWidth(), src.getHeight());
+	float										lodBias				= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
+
+	tcu::IVec2									dstSize				= tcu::IVec2(dst.getWidth(), dst.getHeight());
+	tcu::IVec2									srcSize				= tcu::IVec2(src.getWidth(), src.getHeight());
 
 	// Coordinates and lod per triangle.
-	tcu::Vec3	triS[2]		= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
-	tcu::Vec3	triT[2]		= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
-	float		triLod[2]	= { de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0], triT[0]) + lodBias, params.minLod, params.maxLod),
-								de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[1], triT[1]) + lodBias, params.minLod, params.maxLod) };
+	tcu::Vec3									triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
+	tcu::Vec3									triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
+	float										triLod[2]			= { de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0], triT[0]) + lodBias, params.minLod, params.maxLod),
+																		de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[1], triT[1]) + lodBias, params.minLod, params.maxLod) };
 
 	for (int y = 0; y < dst.getHeight(); y++)
 	{
@@ -490,17 +535,21 @@
 	}
 }
 
-static void sampleTextureProjected (const SurfaceAccess& dst, const tcu::Texture1DView& src, const tcu::Vec4& sq, const ReferenceParams& params)
+static void sampleTextureProjected (const SurfaceAccess& dst, const tcu::Texture1DView& rawSrc, const tcu::Vec4& sq, const ReferenceParams& params)
 {
-	float		lodBias		= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
-	float		dstW		= (float)dst.getWidth();
-	float		dstH		= (float)dst.getHeight();
+	// Separate combined DS formats
+	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
+	const tcu::Texture1DView					src					= getEffectiveView(rawSrc, srcLevelStorage, params.sampler);
 
-	tcu::Vec4	uq			= sq * (float)src.getWidth();
+	float										lodBias				= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
+	float										dstW				= (float)dst.getWidth();
+	float										dstH				= (float)dst.getHeight();
 
-	tcu::Vec3	triS[2]		= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
-	tcu::Vec3	triU[2]		= { uq.swizzle(0, 1, 2), uq.swizzle(3, 2, 1) };
-	tcu::Vec3	triW[2]		= { params.w.swizzle(0, 1, 2), params.w.swizzle(3, 2, 1) };
+	tcu::Vec4									uq					= sq * (float)src.getWidth();
+
+	tcu::Vec3									triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
+	tcu::Vec3									triU[2]				= { uq.swizzle(0, 1, 2), uq.swizzle(3, 2, 1) };
+	tcu::Vec3									triW[2]				= { params.w.swizzle(0, 1, 2), params.w.swizzle(3, 2, 1) };
 
 	for (int py = 0; py < dst.getHeight(); py++)
 	{
@@ -526,20 +575,24 @@
 	}
 }
 
-static void sampleTextureProjected (const SurfaceAccess& dst, const tcu::Texture2DView& src, const tcu::Vec4& sq, const tcu::Vec4& tq, const ReferenceParams& params)
+static void sampleTextureProjected (const SurfaceAccess& dst, const tcu::Texture2DView& rawSrc, const tcu::Vec4& sq, const tcu::Vec4& tq, const ReferenceParams& params)
 {
-	float		lodBias		= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
-	float		dstW		= (float)dst.getWidth();
-	float		dstH		= (float)dst.getHeight();
+	// Separate combined DS formats
+	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
+	const tcu::Texture2DView					src					= getEffectiveView(rawSrc, srcLevelStorage, params.sampler);
 
-	tcu::Vec4	uq			= sq * (float)src.getWidth();
-	tcu::Vec4	vq			= tq * (float)src.getHeight();
+	float										lodBias				= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
+	float										dstW				= (float)dst.getWidth();
+	float										dstH				= (float)dst.getHeight();
 
-	tcu::Vec3	triS[2]		= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
-	tcu::Vec3	triT[2]		= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
-	tcu::Vec3	triU[2]		= { uq.swizzle(0, 1, 2), uq.swizzle(3, 2, 1) };
-	tcu::Vec3	triV[2]		= { vq.swizzle(0, 1, 2), vq.swizzle(3, 2, 1) };
-	tcu::Vec3	triW[2]		= { params.w.swizzle(0, 1, 2), params.w.swizzle(3, 2, 1) };
+	tcu::Vec4									uq					= sq * (float)src.getWidth();
+	tcu::Vec4									vq					= tq * (float)src.getHeight();
+
+	tcu::Vec3									triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
+	tcu::Vec3									triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
+	tcu::Vec3									triU[2]				= { uq.swizzle(0, 1, 2), uq.swizzle(3, 2, 1) };
+	tcu::Vec3									triV[2]				= { vq.swizzle(0, 1, 2), vq.swizzle(3, 2, 1) };
+	tcu::Vec3									triW[2]				= { params.w.swizzle(0, 1, 2), params.w.swizzle(3, 2, 1) };
 
 	for (int py = 0; py < dst.getHeight(); py++)
 	{
@@ -628,20 +681,24 @@
 	}
 }
 
-static void sampleTexture (const SurfaceAccess& dst, const tcu::TextureCubeView& src, const tcu::Vec4& sq, const tcu::Vec4& tq, const tcu::Vec4& rq, const ReferenceParams& params)
+static void sampleTextureCube (const SurfaceAccess& dst, const tcu::TextureCubeView& rawSrc, const tcu::Vec4& sq, const tcu::Vec4& tq, const tcu::Vec4& rq, const ReferenceParams& params)
 {
-	const tcu::IVec2	dstSize			= tcu::IVec2(dst.getWidth(), dst.getHeight());
-	const float			dstW			= float(dstSize.x());
-	const float			dstH			= float(dstSize.y());
-	const int			srcSize			= src.getSize();
+	// Separate combined DS formats
+	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
+	const tcu::TextureCubeView					src					= getEffectiveView(rawSrc, srcLevelStorage, params.sampler);
+
+	const tcu::IVec2							dstSize				= tcu::IVec2(dst.getWidth(), dst.getHeight());
+	const float									dstW				= float(dstSize.x());
+	const float									dstH				= float(dstSize.y());
+	const int									srcSize				= src.getSize();
 
 	// Coordinates per triangle.
-	const tcu::Vec3		triS[2]			= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
-	const tcu::Vec3		triT[2]			= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
-	const tcu::Vec3		triR[2]			= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
-	const tcu::Vec3		triW[2]			= { params.w.swizzle(0, 1, 2), params.w.swizzle(3, 2, 1) };
+	const tcu::Vec3								triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
+	const tcu::Vec3								triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
+	const tcu::Vec3								triR[2]				= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
+	const tcu::Vec3								triW[2]				= { params.w.swizzle(0, 1, 2), params.w.swizzle(3, 2, 1) };
 
-	const float			lodBias			((params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f);
+	const float									lodBias				((params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f);
 
 	for (int py = 0; py < dst.getHeight(); py++)
 	{
@@ -680,22 +737,26 @@
 	const tcu::Vec4				tq		= tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]);
 	const tcu::Vec4				rq		= tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]);
 
-	return sampleTexture(dst, view, sq, tq, rq, params);
+	return sampleTextureCube(dst, view, sq, tq, rq, params);
 }
 
-static void sampleTextureNonProjected (const SurfaceAccess& dst, const tcu::Texture2DArrayView& src, const tcu::Vec4& sq, const tcu::Vec4& tq, const tcu::Vec4& rq, const ReferenceParams& params)
+static void sampleTextureNonProjected (const SurfaceAccess& dst, const tcu::Texture2DArrayView& rawSrc, const tcu::Vec4& sq, const tcu::Vec4& tq, const tcu::Vec4& rq, const ReferenceParams& params)
 {
-	float		lodBias		= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
+	// Separate combined DS formats
+	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
+	const tcu::Texture2DArrayView				src					= getEffectiveView(rawSrc, srcLevelStorage, params.sampler);
 
-	tcu::IVec2	dstSize		= tcu::IVec2(dst.getWidth(), dst.getHeight());
-	tcu::IVec2	srcSize		= tcu::IVec2(src.getWidth(), src.getHeight());
+	float										lodBias				= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
+
+	tcu::IVec2									dstSize				= tcu::IVec2(dst.getWidth(), dst.getHeight());
+	tcu::IVec2									srcSize				= tcu::IVec2(src.getWidth(), src.getHeight());
 
 	// Coordinates and lod per triangle.
-	tcu::Vec3	triS[2]		= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
-	tcu::Vec3	triT[2]		= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
-	tcu::Vec3	triR[2]		= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
-	float		triLod[2]	= { computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0], triT[0]) + lodBias,
-								computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[1], triT[1]) + lodBias};
+	tcu::Vec3									triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
+	tcu::Vec3									triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
+	tcu::Vec3									triR[2]				= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
+	float										triLod[2]			= { computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0], triT[0]) + lodBias,
+																		computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[1], triT[1]) + lodBias};
 
 	for (int y = 0; y < dst.getHeight(); y++)
 	{
@@ -728,18 +789,22 @@
 	sampleTextureNonProjected(dst, src, sq, tq, rq, params);
 }
 
-static void sampleTextureNonProjected (const SurfaceAccess& dst, const tcu::Texture1DArrayView& src, const tcu::Vec4& sq, const tcu::Vec4& tq, const ReferenceParams& params)
+static void sampleTextureNonProjected (const SurfaceAccess& dst, const tcu::Texture1DArrayView& rawSrc, const tcu::Vec4& sq, const tcu::Vec4& tq, const ReferenceParams& params)
 {
-	float		lodBias		= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
+	// Separate combined DS formats
+	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
+	const tcu::Texture1DArrayView				src					= getEffectiveView(rawSrc, srcLevelStorage, params.sampler);
 
-	tcu::IVec2	dstSize		= tcu::IVec2(dst.getWidth(), dst.getHeight());
-	deInt32		srcSize		= src.getWidth();
+	float										lodBias				= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
+
+	tcu::IVec2									dstSize				= tcu::IVec2(dst.getWidth(), dst.getHeight());
+	deInt32										srcSize				= src.getWidth();
 
 	// Coordinates and lod per triangle.
-	tcu::Vec3	triS[2]		= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
-	tcu::Vec3	triT[2]		= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
-	float		triLod[2]	= { computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0]) + lodBias,
-								computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[1]) + lodBias};
+	tcu::Vec3									triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
+	tcu::Vec3									triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
+	float										triLod[2]			= { computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0]) + lodBias,
+																		computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[1]) + lodBias};
 
 	for (int y = 0; y < dst.getHeight(); y++)
 	{
@@ -770,19 +835,23 @@
 	sampleTextureNonProjected(dst, src, sq, tq, params);
 }
 
-static void sampleTextureNonProjected (const SurfaceAccess& dst, const tcu::Texture3DView& src, const tcu::Vec4& sq, const tcu::Vec4& tq, const tcu::Vec4& rq, const ReferenceParams& params)
+static void sampleTextureNonProjected (const SurfaceAccess& dst, const tcu::Texture3DView& rawSrc, const tcu::Vec4& sq, const tcu::Vec4& tq, const tcu::Vec4& rq, const ReferenceParams& params)
 {
-	float		lodBias		= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
+	// Separate combined DS formats
+	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
+	const tcu::Texture3DView					src					= getEffectiveView(rawSrc, srcLevelStorage, params.sampler);
 
-	tcu::IVec2	dstSize		= tcu::IVec2(dst.getWidth(), dst.getHeight());
-	tcu::IVec3	srcSize		= tcu::IVec3(src.getWidth(), src.getHeight(), src.getDepth());
+	float										lodBias				= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
+
+	tcu::IVec2									dstSize				= tcu::IVec2(dst.getWidth(), dst.getHeight());
+	tcu::IVec3									srcSize				= tcu::IVec3(src.getWidth(), src.getHeight(), src.getDepth());
 
 	// Coordinates and lod per triangle.
-	tcu::Vec3	triS[2]		= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
-	tcu::Vec3	triT[2]		= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
-	tcu::Vec3	triR[2]		= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
-	float		triLod[2]	= { de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0], triT[0], triR[0]) + lodBias, params.minLod, params.maxLod),
-								de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[1], triT[1], triR[1]) + lodBias, params.minLod, params.maxLod) };
+	tcu::Vec3									triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
+	tcu::Vec3									triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
+	tcu::Vec3									triR[2]				= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
+	float										triLod[2]			= { de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[0], triT[0], triR[0]) + lodBias, params.minLod, params.maxLod),
+																		de::clamp(computeNonProjectedTriLod(params.lodMode, dstSize, srcSize, triS[1], triT[1], triR[1]) + lodBias, params.minLod, params.maxLod) };
 
 	for (int y = 0; y < dst.getHeight(); y++)
 	{
@@ -805,23 +874,27 @@
 	}
 }
 
-static void sampleTextureProjected (const SurfaceAccess& dst, const tcu::Texture3DView& src, const tcu::Vec4& sq, const tcu::Vec4& tq, const tcu::Vec4& rq, const ReferenceParams& params)
+static void sampleTextureProjected (const SurfaceAccess& dst, const tcu::Texture3DView& rawSrc, const tcu::Vec4& sq, const tcu::Vec4& tq, const tcu::Vec4& rq, const ReferenceParams& params)
 {
-	float		lodBias		= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
-	float		dstW		= (float)dst.getWidth();
-	float		dstH		= (float)dst.getHeight();
+	// Separate combined DS formats
+	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
+	const tcu::Texture3DView					src					= getEffectiveView(rawSrc, srcLevelStorage, params.sampler);
 
-	tcu::Vec4	uq			= sq * (float)src.getWidth();
-	tcu::Vec4	vq			= tq * (float)src.getHeight();
-	tcu::Vec4	wq			= rq * (float)src.getDepth();
+	float										lodBias				= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
+	float										dstW				= (float)dst.getWidth();
+	float										dstH				= (float)dst.getHeight();
 
-	tcu::Vec3	triS[2]		= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
-	tcu::Vec3	triT[2]		= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
-	tcu::Vec3	triR[2]		= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
-	tcu::Vec3	triU[2]		= { uq.swizzle(0, 1, 2), uq.swizzle(3, 2, 1) };
-	tcu::Vec3	triV[2]		= { vq.swizzle(0, 1, 2), vq.swizzle(3, 2, 1) };
-	tcu::Vec3	triW[2]		= { wq.swizzle(0, 1, 2), wq.swizzle(3, 2, 1) };
-	tcu::Vec3	triP[2]		= { params.w.swizzle(0, 1, 2), params.w.swizzle(3, 2, 1) };
+	tcu::Vec4									uq					= sq * (float)src.getWidth();
+	tcu::Vec4									vq					= tq * (float)src.getHeight();
+	tcu::Vec4									wq					= rq * (float)src.getDepth();
+
+	tcu::Vec3									triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
+	tcu::Vec3									triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
+	tcu::Vec3									triR[2]				= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
+	tcu::Vec3									triU[2]				= { uq.swizzle(0, 1, 2), uq.swizzle(3, 2, 1) };
+	tcu::Vec3									triV[2]				= { vq.swizzle(0, 1, 2), vq.swizzle(3, 2, 1) };
+	tcu::Vec3									triW[2]				= { wq.swizzle(0, 1, 2), wq.swizzle(3, 2, 1) };
+	tcu::Vec3									triP[2]				= { params.w.swizzle(0, 1, 2), params.w.swizzle(3, 2, 1) };
 
 	for (int py = 0; py < dst.getHeight(); py++)
 	{
@@ -862,19 +935,23 @@
 		sampleTextureNonProjected(dst, view, sq, tq, rq, params);
 }
 
-static void sampleTexture (const SurfaceAccess& dst, const tcu::TextureCubeArrayView& src, const tcu::Vec4& sq, const tcu::Vec4& tq, const tcu::Vec4& rq, const tcu::Vec4& qq, const ReferenceParams& params)
+static void sampleTextureCubeArray (const SurfaceAccess& dst, const tcu::TextureCubeArrayView& rawSrc, const tcu::Vec4& sq, const tcu::Vec4& tq, const tcu::Vec4& rq, const tcu::Vec4& qq, const ReferenceParams& params)
 {
-	const float		dstW	= (float)dst.getWidth();
-	const float		dstH	= (float)dst.getHeight();
+	// Separate combined DS formats
+	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
+	const tcu::TextureCubeArrayView				src					= getEffectiveView(rawSrc, srcLevelStorage, params.sampler);
+
+	const float									dstW				= (float)dst.getWidth();
+	const float									dstH				= (float)dst.getHeight();
 
 	// Coordinates per triangle.
-	tcu::Vec3		triS[2]	= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
-	tcu::Vec3		triT[2]	= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
-	tcu::Vec3		triR[2]	= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
-	tcu::Vec3		triQ[2]	= { qq.swizzle(0, 1, 2), qq.swizzle(3, 2, 1) };
-	const tcu::Vec3	triW[2]	= { params.w.swizzle(0, 1, 2), params.w.swizzle(3, 2, 1) };
+	tcu::Vec3									triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
+	tcu::Vec3									triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
+	tcu::Vec3									triR[2]				= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
+	tcu::Vec3									triQ[2]				= { qq.swizzle(0, 1, 2), qq.swizzle(3, 2, 1) };
+	const tcu::Vec3								triW[2]				= { params.w.swizzle(0, 1, 2), params.w.swizzle(3, 2, 1) };
 
-	const float		lodBias	= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
+	const float									lodBias				= (params.flags & ReferenceParams::USE_BIAS) ? params.bias : 0.0f;
 
 	for (int py = 0; py < dst.getHeight(); py++)
 	{
@@ -916,7 +993,7 @@
 	tcu::Vec4 rq = tcu::Vec4(texCoord[0+2], texCoord[4+2], texCoord[8+2], texCoord[12+2]);
 	tcu::Vec4 qq = tcu::Vec4(texCoord[0+3], texCoord[4+3], texCoord[8+3], texCoord[12+3]);
 
-	sampleTexture(dst, src, sq, tq, rq, qq, params);
+	sampleTextureCubeArray(dst, src, sq, tq, rq, qq, params);
 }
 
 void fetchTexture (const SurfaceAccess& dst, const tcu::ConstPixelBufferAccess& src, const float* texCoord, const tcu::Vec4& colorScale, const tcu::Vec4& colorBias)
@@ -1666,22 +1743,23 @@
 	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
 	DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
 
-	const tcu::Texture1DView	src		= getSubView(baseView, sampleParams.baseLevel, sampleParams.maxLevel);
+	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
+	const tcu::Texture1DView					src					= getEffectiveView(getSubView(baseView, sampleParams.baseLevel, sampleParams.maxLevel), srcLevelStorage, sampleParams.sampler);
 
-	const tcu::Vec4		sq				= tcu::Vec4(texCoord[0], texCoord[1], texCoord[2], texCoord[3]);
+	const tcu::Vec4								sq					= tcu::Vec4(texCoord[0], texCoord[1], texCoord[2], texCoord[3]);
 
-	const tcu::IVec2	dstSize			= tcu::IVec2(result.getWidth(), result.getHeight());
-	const float			dstW			= float(dstSize.x());
-	const float			dstH			= float(dstSize.y());
-	const int			srcSize			= src.getWidth();
+	const tcu::IVec2							dstSize				= tcu::IVec2(result.getWidth(), result.getHeight());
+	const float									dstW				= float(dstSize.x());
+	const float									dstH				= float(dstSize.y());
+	const int									srcSize				= src.getWidth();
 
 	// Coordinates and lod per triangle.
-	const tcu::Vec3		triS[2]			= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
-	const tcu::Vec3		triW[2]			= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
+	const tcu::Vec3								triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
+	const tcu::Vec3								triW[2]				= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
 
-	const tcu::Vec2		lodBias			((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
+	const tcu::Vec2								lodBias				((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
 
-	int					numFailed		= 0;
+	int											numFailed			= 0;
 
 	const tcu::Vec2 lodOffsets[] =
 	{
@@ -1768,24 +1846,25 @@
 	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
 	DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
 
-	const tcu::Texture2DView	src		= getSubView(baseView, sampleParams.baseLevel, sampleParams.maxLevel);
+	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
+	const tcu::Texture2DView					src					= getEffectiveView(getSubView(baseView, sampleParams.baseLevel, sampleParams.maxLevel), srcLevelStorage, sampleParams.sampler);
 
-	const tcu::Vec4		sq				= tcu::Vec4(texCoord[0+0], texCoord[2+0], texCoord[4+0], texCoord[6+0]);
-	const tcu::Vec4		tq				= tcu::Vec4(texCoord[0+1], texCoord[2+1], texCoord[4+1], texCoord[6+1]);
+	const tcu::Vec4								sq					= tcu::Vec4(texCoord[0+0], texCoord[2+0], texCoord[4+0], texCoord[6+0]);
+	const tcu::Vec4								tq					= tcu::Vec4(texCoord[0+1], texCoord[2+1], texCoord[4+1], texCoord[6+1]);
 
-	const tcu::IVec2	dstSize			= tcu::IVec2(result.getWidth(), result.getHeight());
-	const float			dstW			= float(dstSize.x());
-	const float			dstH			= float(dstSize.y());
-	const tcu::IVec2	srcSize			= tcu::IVec2(src.getWidth(), src.getHeight());
+	const tcu::IVec2							dstSize				= tcu::IVec2(result.getWidth(), result.getHeight());
+	const float									dstW				= float(dstSize.x());
+	const float									dstH				= float(dstSize.y());
+	const tcu::IVec2							srcSize				= tcu::IVec2(src.getWidth(), src.getHeight());
 
 	// Coordinates and lod per triangle.
-	const tcu::Vec3		triS[2]			= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
-	const tcu::Vec3		triT[2]			= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
-	const tcu::Vec3		triW[2]			= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
+	const tcu::Vec3								triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
+	const tcu::Vec3								triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
+	const tcu::Vec3								triW[2]				= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
 
-	const tcu::Vec2		lodBias			((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
+	const tcu::Vec2								lodBias				((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
 
-	int					numFailed		= 0;
+	int											numFailed			= 0;
 
 	const tcu::Vec2 lodOffsets[] =
 	{
@@ -1950,28 +2029,29 @@
 	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
 	DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
 
-	const tcu::TextureCubeView	src		= getSubView(baseView, sampleParams.baseLevel, sampleParams.maxLevel);
+	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
+	const tcu::TextureCubeView					src					= getEffectiveView(getSubView(baseView, sampleParams.baseLevel, sampleParams.maxLevel), srcLevelStorage, sampleParams.sampler);
 
-	const tcu::Vec4		sq				= tcu::Vec4(texCoord[0+0], texCoord[3+0], texCoord[6+0], texCoord[9+0]);
-	const tcu::Vec4		tq				= tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]);
-	const tcu::Vec4		rq				= tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]);
+	const tcu::Vec4								sq					= tcu::Vec4(texCoord[0+0], texCoord[3+0], texCoord[6+0], texCoord[9+0]);
+	const tcu::Vec4								tq					= tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]);
+	const tcu::Vec4								rq					= tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]);
 
-	const tcu::IVec2	dstSize			= tcu::IVec2(result.getWidth(), result.getHeight());
-	const float			dstW			= float(dstSize.x());
-	const float			dstH			= float(dstSize.y());
-	const int			srcSize			= src.getSize();
+	const tcu::IVec2							dstSize				= tcu::IVec2(result.getWidth(), result.getHeight());
+	const float									dstW				= float(dstSize.x());
+	const float									dstH				= float(dstSize.y());
+	const int									srcSize				= src.getSize();
 
 	// Coordinates per triangle.
-	const tcu::Vec3		triS[2]			= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
-	const tcu::Vec3		triT[2]			= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
-	const tcu::Vec3		triR[2]			= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
-	const tcu::Vec3		triW[2]			= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
+	const tcu::Vec3								triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
+	const tcu::Vec3								triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
+	const tcu::Vec3								triR[2]				= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
+	const tcu::Vec3								triW[2]				= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
 
-	const tcu::Vec2		lodBias			((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
+	const tcu::Vec2								lodBias				((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
 
-	const float			posEps			= 1.0f / float(1<<MIN_SUBPIXEL_BITS);
+	const float									posEps				= 1.0f / float(1<<MIN_SUBPIXEL_BITS);
 
-	int					numFailed		= 0;
+	int											numFailed			= 0;
 
 	const tcu::Vec2 lodOffsets[] =
 	{
@@ -2129,28 +2209,29 @@
 	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
 	DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
 
-	const tcu::Texture3DView	src		= getSubView(baseView, sampleParams.baseLevel, sampleParams.maxLevel);
+	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
+	const tcu::Texture3DView					src					= getEffectiveView(getSubView(baseView, sampleParams.baseLevel, sampleParams.maxLevel), srcLevelStorage, sampleParams.sampler);
 
-	const tcu::Vec4		sq				= tcu::Vec4(texCoord[0+0], texCoord[3+0], texCoord[6+0], texCoord[9+0]);
-	const tcu::Vec4		tq				= tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]);
-	const tcu::Vec4		rq				= tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]);
+	const tcu::Vec4								sq					= tcu::Vec4(texCoord[0+0], texCoord[3+0], texCoord[6+0], texCoord[9+0]);
+	const tcu::Vec4								tq					= tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]);
+	const tcu::Vec4								rq					= tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]);
 
-	const tcu::IVec2	dstSize			= tcu::IVec2(result.getWidth(), result.getHeight());
-	const float			dstW			= float(dstSize.x());
-	const float			dstH			= float(dstSize.y());
-	const tcu::IVec3	srcSize			= tcu::IVec3(src.getWidth(), src.getHeight(), src.getDepth());
+	const tcu::IVec2							dstSize				= tcu::IVec2(result.getWidth(), result.getHeight());
+	const float									dstW				= float(dstSize.x());
+	const float									dstH				= float(dstSize.y());
+	const tcu::IVec3							srcSize				= tcu::IVec3(src.getWidth(), src.getHeight(), src.getDepth());
 
 	// Coordinates and lod per triangle.
-	const tcu::Vec3		triS[2]			= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
-	const tcu::Vec3		triT[2]			= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
-	const tcu::Vec3		triR[2]			= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
-	const tcu::Vec3		triW[2]			= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
+	const tcu::Vec3								triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
+	const tcu::Vec3								triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
+	const tcu::Vec3								triR[2]				= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
+	const tcu::Vec3								triW[2]				= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
 
-	const tcu::Vec2		lodBias			((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
+	const tcu::Vec2								lodBias				((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
 
-	const float			posEps			= 1.0f / float(1<<MIN_SUBPIXEL_BITS);
+	const float									posEps				= 1.0f / float(1<<MIN_SUBPIXEL_BITS);
 
-	int					numFailed		= 0;
+	int											numFailed			= 0;
 
 	const tcu::Vec2 lodOffsets[] =
 	{
@@ -2289,7 +2370,7 @@
 int computeTextureLookupDiff (const tcu::ConstPixelBufferAccess&	result,
 							  const tcu::ConstPixelBufferAccess&	reference,
 							  const tcu::PixelBufferAccess&			errorMask,
-							  const tcu::Texture1DArrayView&		src,
+							  const tcu::Texture1DArrayView&		baseView,
 							  const float*							texCoord,
 							  const ReferenceParams&				sampleParams,
 							  const tcu::LookupPrecision&			lookupPrec,
@@ -2299,22 +2380,25 @@
 	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
 	DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
 
-	const tcu::Vec4		sq				= tcu::Vec4(texCoord[0+0], texCoord[2+0], texCoord[4+0], texCoord[6+0]);
-	const tcu::Vec4		tq				= tcu::Vec4(texCoord[0+1], texCoord[2+1], texCoord[4+1], texCoord[6+1]);
+	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
+	const tcu::Texture1DArrayView				src					= getEffectiveView(baseView, srcLevelStorage, sampleParams.sampler);
 
-	const tcu::IVec2	dstSize			= tcu::IVec2(result.getWidth(), result.getHeight());
-	const float			dstW			= float(dstSize.x());
-	const float			dstH			= float(dstSize.y());
-	const float			srcSize			= float(src.getWidth()); // For lod computation, thus #layers is ignored.
+	const tcu::Vec4								sq					= tcu::Vec4(texCoord[0+0], texCoord[2+0], texCoord[4+0], texCoord[6+0]);
+	const tcu::Vec4								tq					= tcu::Vec4(texCoord[0+1], texCoord[2+1], texCoord[4+1], texCoord[6+1]);
+
+	const tcu::IVec2							dstSize				= tcu::IVec2(result.getWidth(), result.getHeight());
+	const float									dstW				= float(dstSize.x());
+	const float									dstH				= float(dstSize.y());
+	const float									srcSize				= float(src.getWidth()); // For lod computation, thus #layers is ignored.
 
 	// Coordinates and lod per triangle.
-	const tcu::Vec3		triS[2]			= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
-	const tcu::Vec3		triT[2]			= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
-	const tcu::Vec3		triW[2]			= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
+	const tcu::Vec3								triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
+	const tcu::Vec3								triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
+	const tcu::Vec3								triW[2]				= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
 
-	const tcu::Vec2		lodBias			((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
+	const tcu::Vec2								lodBias				((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
 
-	int					numFailed		= 0;
+	int											numFailed			= 0;
 
 	const tcu::Vec2 lodOffsets[] =
 	{
@@ -2393,7 +2477,7 @@
 int computeTextureLookupDiff (const tcu::ConstPixelBufferAccess&	result,
 							  const tcu::ConstPixelBufferAccess&	reference,
 							  const tcu::PixelBufferAccess&			errorMask,
-							  const tcu::Texture2DArrayView&		src,
+							  const tcu::Texture2DArrayView&		baseView,
 							  const float*							texCoord,
 							  const ReferenceParams&				sampleParams,
 							  const tcu::LookupPrecision&			lookupPrec,
@@ -2403,24 +2487,27 @@
 	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
 	DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
 
-	const tcu::Vec4		sq				= tcu::Vec4(texCoord[0+0], texCoord[3+0], texCoord[6+0], texCoord[9+0]);
-	const tcu::Vec4		tq				= tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]);
-	const tcu::Vec4		rq				= tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]);
+	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
+	const tcu::Texture2DArrayView				src					= getEffectiveView(baseView, srcLevelStorage, sampleParams.sampler);
 
-	const tcu::IVec2	dstSize			= tcu::IVec2(result.getWidth(), result.getHeight());
-	const float			dstW			= float(dstSize.x());
-	const float			dstH			= float(dstSize.y());
-	const tcu::Vec2		srcSize			= tcu::IVec2(src.getWidth(), src.getHeight()).asFloat(); // For lod computation, thus #layers is ignored.
+	const tcu::Vec4								sq					= tcu::Vec4(texCoord[0+0], texCoord[3+0], texCoord[6+0], texCoord[9+0]);
+	const tcu::Vec4								tq					= tcu::Vec4(texCoord[0+1], texCoord[3+1], texCoord[6+1], texCoord[9+1]);
+	const tcu::Vec4								rq					= tcu::Vec4(texCoord[0+2], texCoord[3+2], texCoord[6+2], texCoord[9+2]);
+
+	const tcu::IVec2							dstSize				= tcu::IVec2(result.getWidth(), result.getHeight());
+	const float									dstW				= float(dstSize.x());
+	const float									dstH				= float(dstSize.y());
+	const tcu::Vec2								srcSize				= tcu::IVec2(src.getWidth(), src.getHeight()).asFloat(); // For lod computation, thus #layers is ignored.
 
 	// Coordinates and lod per triangle.
-	const tcu::Vec3		triS[2]			= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
-	const tcu::Vec3		triT[2]			= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
-	const tcu::Vec3		triR[2]			= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
-	const tcu::Vec3		triW[2]			= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
+	const tcu::Vec3								triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
+	const tcu::Vec3								triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
+	const tcu::Vec3								triR[2]				= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
+	const tcu::Vec3								triW[2]				= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
 
-	const tcu::Vec2		lodBias			((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
+	const tcu::Vec2								lodBias				((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
 
-	int					numFailed		= 0;
+	int											numFailed			= 0;
 
 	const tcu::Vec2 lodOffsets[] =
 	{
@@ -2587,31 +2674,31 @@
 	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
 	DE_ASSERT(result.getWidth() == errorMask.getWidth() && result.getHeight() == errorMask.getHeight());
 
-	const tcu::TextureCubeArrayView	src	= getSubView(baseView, sampleParams.baseLevel, sampleParams.maxLevel);
+	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
+	const tcu::TextureCubeArrayView				src					= getEffectiveView(getSubView(baseView, sampleParams.baseLevel, sampleParams.maxLevel), srcLevelStorage, sampleParams.sampler);
 
-	// What is the 'q' in all these names? Also a two char name for something that is in scope for ~120 lines and only used twice each seems excessive
-	const tcu::Vec4		sq				= tcu::Vec4(texCoord[0+0], texCoord[4+0], texCoord[8+0], texCoord[12+0]);
-	const tcu::Vec4		tq				= tcu::Vec4(texCoord[0+1], texCoord[4+1], texCoord[8+1], texCoord[12+1]);
-	const tcu::Vec4		rq				= tcu::Vec4(texCoord[0+2], texCoord[4+2], texCoord[8+2], texCoord[12+2]);
-	const tcu::Vec4		qq				= tcu::Vec4(texCoord[0+3], texCoord[4+3], texCoord[8+3], texCoord[12+3]);
+	const tcu::Vec4								sq					= tcu::Vec4(texCoord[0+0], texCoord[4+0], texCoord[8+0], texCoord[12+0]);
+	const tcu::Vec4								tq					= tcu::Vec4(texCoord[0+1], texCoord[4+1], texCoord[8+1], texCoord[12+1]);
+	const tcu::Vec4								rq					= tcu::Vec4(texCoord[0+2], texCoord[4+2], texCoord[8+2], texCoord[12+2]);
+	const tcu::Vec4								qq					= tcu::Vec4(texCoord[0+3], texCoord[4+3], texCoord[8+3], texCoord[12+3]);
 
-	const tcu::IVec2	dstSize			= tcu::IVec2(result.getWidth(), result.getHeight());
-	const float			dstW			= float(dstSize.x());
-	const float			dstH			= float(dstSize.y());
-	const int			srcSize			= src.getSize();
+	const tcu::IVec2							dstSize				= tcu::IVec2(result.getWidth(), result.getHeight());
+	const float									dstW				= float(dstSize.x());
+	const float									dstH				= float(dstSize.y());
+	const int									srcSize				= src.getSize();
 
 	// Coordinates per triangle.
-	const tcu::Vec3		triS[2]			= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
-	const tcu::Vec3		triT[2]			= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
-	const tcu::Vec3		triR[2]			= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
-	const tcu::Vec3		triQ[2]			= { qq.swizzle(0, 1, 2), qq.swizzle(3, 2, 1) };
-	const tcu::Vec3		triW[2]			= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
+	const tcu::Vec3								triS[2]				= { sq.swizzle(0, 1, 2), sq.swizzle(3, 2, 1) };
+	const tcu::Vec3								triT[2]				= { tq.swizzle(0, 1, 2), tq.swizzle(3, 2, 1) };
+	const tcu::Vec3								triR[2]				= { rq.swizzle(0, 1, 2), rq.swizzle(3, 2, 1) };
+	const tcu::Vec3								triQ[2]				= { qq.swizzle(0, 1, 2), qq.swizzle(3, 2, 1) };
+	const tcu::Vec3								triW[2]				= { sampleParams.w.swizzle(0, 1, 2), sampleParams.w.swizzle(3, 2, 1) };
 
-	const tcu::Vec2		lodBias			((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
+	const tcu::Vec2								lodBias				((sampleParams.flags & ReferenceParams::USE_BIAS) ? sampleParams.bias : 0.0f);
 
-	const float			posEps			= 1.0f / float((1<<4) + 1); // ES3 requires at least 4 subpixel bits.
+	const float									posEps				= 1.0f / float((1<<4) + 1); // ES3 requires at least 4 subpixel bits.
 
-	int					numFailed		= 0;
+	int											numFailed			= 0;
 
 	const tcu::Vec2 lodOffsets[] =
 	{