1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2015 Imagination Technologies Ltd.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Sampler Tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktPipelineSamplerTests.hpp"
26 #include "vktPipelineImageSamplingInstance.hpp"
27 #ifndef CTS_USES_VULKANSC
28 #include "vktPipelineSamplerBorderSwizzleTests.hpp"
29 #endif // CTS_USES_VULKANSC
30 #include "vktPipelineImageUtil.hpp"
31 #include "vktPipelineVertexUtil.hpp"
32 #include "vktTestCase.hpp"
33 
34 #include "vkImageUtil.hpp"
35 #include "vkQueryUtil.hpp"
36 #include "vkTypeUtil.hpp"
37 #include "vkObjUtil.hpp"
38 #include "vkBuilderUtil.hpp"
39 #include "vkBarrierUtil.hpp"
40 #include "vkCmdUtil.hpp"
41 #include "vkPrograms.hpp"
42 #include "vkImageWithMemory.hpp"
43 #include "vkBufferWithMemory.hpp"
44 
45 #include "tcuPlatform.hpp"
46 #include "tcuTextureUtil.hpp"
47 #include "tcuTestLog.hpp"
48 #include "tcuMaybe.hpp"
49 
50 #include "deStringUtil.hpp"
51 #include "deMemory.h"
52 
53 #include <iomanip>
54 #include <sstream>
55 #include <vector>
56 #include <string>
57 #include <memory>
58 #include <utility>
59 #include <algorithm>
60 
61 namespace vkt
62 {
63 namespace pipeline
64 {
65 
66 using namespace vk;
67 using de::MovePtr;
68 
69 namespace
70 {
71 
72 class SamplerViewType
73 {
74 public:
SamplerViewType(vk::VkImageViewType type, bool normalized = true)75 	SamplerViewType (vk::VkImageViewType type, bool normalized = true)
76 		: m_viewType(type), m_normalized(normalized)
77 	{
78 		if (!normalized)
79 			DE_ASSERT(type == vk::VK_IMAGE_VIEW_TYPE_2D || type == vk::VK_IMAGE_VIEW_TYPE_1D);
80 	}
81 
operator vk::VkImageViewType() const82 	operator vk::VkImageViewType () const
83 	{
84 		return m_viewType;
85 	}
86 
isNormalized() const87 	bool isNormalized () const
88 	{
89 		return m_normalized;
90 	}
91 
92 private:
93 	vk::VkImageViewType m_viewType;
94 	bool				m_normalized;
95 };
96 
97 class SamplerTest : public vkt::TestCase
98 {
99 public:
100 										SamplerTest						(tcu::TestContext&			testContext,
101 																		 const char*				name,
102 																		 const char*				description,
103 																		 PipelineConstructionType	pipelineConstructionType,
104 																		 SamplerViewType			imageViewType,
105 																		 VkFormat					imageFormat,
106 																		 int						imageSize,
107 																		 float						samplerLod,
108 																		 bool						separateStencilUsage,
109 																		 bool						sampleStencil);
~SamplerTest(void)110 	virtual								~SamplerTest					(void) {}
111 
112 	virtual ImageSamplingInstanceParams	getImageSamplingInstanceParams	(SamplerViewType	imageViewType,
113 																		 VkFormat			imageFormat,
114 																		 int				imageSize,
115 																		 float				samplerLod,
116 																		 bool				separateStencilUsage,
117 																		 bool				sampleStencil) const;
118 
119 	tcu::Vec4							swizzle							(tcu::Vec4 inputData, VkComponentMapping componentMapping, float zeroOrOneValue) const;
120 	virtual void						initPrograms					(SourceCollections& sourceCollections) const;
121 	virtual void						checkSupport					(Context& context) const;
122 	virtual TestInstance*				createInstance					(Context& context) const;
123 	virtual tcu::UVec2					getRenderSize					(SamplerViewType viewType) const;
124 	virtual std::vector<Vertex4Tex4>	createVertices					(void) const;
125 	virtual VkSamplerCreateInfo			getSamplerCreateInfo			(void) const;
126 	virtual VkComponentMapping			getComponentMapping				(void) const;
127 
128 	static std::string					getGlslSamplerType				(const tcu::TextureFormat& format, SamplerViewType type, bool sampleStencil);
129 	static tcu::IVec3					getImageSize					(SamplerViewType viewType, int size);
130 	static int							getArraySize					(SamplerViewType viewType);
131 
132 protected:
133 	PipelineConstructionType			m_pipelineConstructionType;
134 	SamplerViewType						m_imageViewType;
135 	VkFormat							m_imageFormat;
136 	int									m_imageSize;
137 	float								m_samplerLod;
138 	bool								m_separateStencilUsage;
139 	bool								m_sampleStencil;
140 };
141 
142 class SamplerMagFilterTest : public SamplerTest
143 {
144 public:
145 									SamplerMagFilterTest	(tcu::TestContext&			testContext,
146 															 const char*				name,
147 															 const char*				description,
148 															 PipelineConstructionType	pipelineConstructionType,
149 															 SamplerViewType			imageViewType,
150 															 VkFormat					imageFormat,
151 															 VkFilter					magFilter,
152 															 bool						separateStencilUsage);
~SamplerMagFilterTest(void)153 	virtual							~SamplerMagFilterTest	(void) {}
154 	virtual VkSamplerCreateInfo		getSamplerCreateInfo	(void) const;
155 
156 private:
157 	VkFilter						m_magFilter;
158 };
159 
160 class SamplerMinFilterTest : public SamplerTest
161 {
162 public:
163 									SamplerMinFilterTest	(tcu::TestContext&			testContext,
164 															 const char*				name,
165 															 const char*				description,
166 															 PipelineConstructionType	pipelineConstructionType,
167 															 SamplerViewType			imageViewType,
168 															 VkFormat					imageFormat,
169 															 VkFilter					minFilter,
170 															 bool						separateStencilUsage);
~SamplerMinFilterTest(void)171 	virtual							~SamplerMinFilterTest	(void) {}
172 	virtual VkSamplerCreateInfo		getSamplerCreateInfo	(void) const;
173 
174 private:
175 	VkFilter						m_minFilter;
176 };
177 
178 class SamplerMagReduceFilterTest : public SamplerMagFilterTest
179 {
180 public:
181 												SamplerMagReduceFilterTest	(tcu::TestContext&			testContext,
182 																			const char*					name,
183 																			const char*					description,
184 																			PipelineConstructionType	pipelineConstructionType,
185 																			SamplerViewType				imageViewType,
186 																			VkFormat					imageFormat,
187 																			VkComponentMapping			componentMapping,
188 																			VkSamplerReductionMode		reductionMode,
189 																			bool						separateStencilUsage);
190 
~SamplerMagReduceFilterTest(void)191 	virtual										~SamplerMagReduceFilterTest	(void) {}
192 	virtual VkSamplerCreateInfo					getSamplerCreateInfo		(void) const;
193 	virtual VkComponentMapping					getComponentMapping			(void) const;
194 
195 private:
196 	const VkSamplerReductionModeCreateInfo		m_reductionCreaterInfo;
197 	VkComponentMapping							m_componentMapping;
198 };
199 
200 class SamplerMinReduceFilterTest : public SamplerMinFilterTest
201 {
202 public:
203 												SamplerMinReduceFilterTest	(tcu::TestContext&			testContext,
204 																			 const char*				name,
205 																			 const char*				description,
206 																			 PipelineConstructionType	pipelineConstructionType,
207 																			 SamplerViewType			imageViewType,
208 																			 VkFormat					imageFormat,
209 																			 VkComponentMapping			componentMapping,
210 																			 VkSamplerReductionMode		reductionMode,
211 																			 bool						separateStencilUsage);
212 
~SamplerMinReduceFilterTest(void)213 	virtual										~SamplerMinReduceFilterTest	(void) {}
214 	virtual VkSamplerCreateInfo					getSamplerCreateInfo		(void) const;
215 	virtual VkComponentMapping					getComponentMapping			(void) const;
216 
217 private:
218 	const VkSamplerReductionModeCreateInfo		m_reductionCreaterInfo;
219 	VkComponentMapping							m_componentMapping;
220 };
221 
222 class SamplerLodTest : public SamplerTest
223 {
224 public:
225 									SamplerLodTest			(tcu::TestContext&			testContext,
226 															 const char*				name,
227 															 const char*				description,
228 															 PipelineConstructionType	pipelineConstructionType,
229 															 SamplerViewType			imageViewType,
230 															 VkFormat					imageFormat,
231 															 VkSamplerMipmapMode		mipmapMode,
232 															 float						minLod,
233 															 float						maxLod,
234 															 float						mipLodBias,
235 															 float						samplerLod,
236 															 bool						separateStencilUsage);
~SamplerLodTest(void)237 	virtual							~SamplerLodTest			(void) {}
238 	virtual VkSamplerCreateInfo		getSamplerCreateInfo	(void) const;
239 	virtual void					checkSupport			(Context& context) const;
240 
241 private:
242 	VkSamplerMipmapMode				m_mipmapMode;
243 	float							m_minLod;
244 	float							m_maxLod;
245 	float							m_mipLodBias;
246 };
247 
checkSupport(Context& context) const248 void SamplerLodTest::checkSupport (Context& context) const
249 {
250 	SamplerTest::checkSupport(context);
251 
252 #ifndef CTS_USES_VULKANSC
253 	if (m_mipLodBias != 0.0f && context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
254 		!context.getPortabilitySubsetFeatures().samplerMipLodBias)
255 	{
256 		TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Sampler mipmap LOD bias is not supported by this implementation");
257 	}
258 #endif // CTS_USES_VULKANSC
259 }
260 
261 class SamplerAddressModesTest : public SamplerTest
262 {
263 public:
264 										SamplerAddressModesTest		(tcu::TestContext&			testContext,
265 																	 const char*				name,
266 																	 const char*				description,
267 																	 PipelineConstructionType	pipelineConstructionType,
268 																	 SamplerViewType			imageViewType,
269 																	 VkFormat					imageFormat,
270 																	 VkSamplerAddressMode		addressU,
271 																	 VkSamplerAddressMode		addressV,
272 																	 VkSamplerAddressMode		addressW,
273 																	 VkBorderColor				borderColor,
274 																	 rr::GenericVec4			customBorderColorValue,
275 																	 bool						customBorderColorFormatless,
276 																	 bool						separateStencilUsage,
277 																	 bool						sampleStencil);
~SamplerAddressModesTest(void)278 	virtual								~SamplerAddressModesTest	(void) {}
279 	virtual tcu::UVec2					getRenderSize				(SamplerViewType viewType) const;
280 	virtual std::vector<Vertex4Tex4>	createVertices				(void) const;
281 	virtual VkSamplerCreateInfo			getSamplerCreateInfo		(void) const;
282 
283 	VkSamplerCustomBorderColorCreateInfoEXT	getSamplerCustomBorderColorCreateInfo	(VkFormat format, rr::GenericVec4 customBorderColorValue, bool customBorderColorFormatless) const;
284 
285 private:
286 	VkSamplerAddressMode				m_addressU;
287 	VkSamplerAddressMode				m_addressV;
288 	VkSamplerAddressMode				m_addressW;
289 	VkBorderColor						m_borderColor;
290 
291 	const VkSamplerCustomBorderColorCreateInfoEXT	m_customBorderColorCreateInfo;
292 };
293 
294 
295 // SamplerTest
296 
SamplerTest(tcu::TestContext& testContext, const char* name, const char* description, PipelineConstructionType pipelineConstructionType, SamplerViewType imageViewType, VkFormat imageFormat, int imageSize, float samplerLod, bool separateStencilUsage, bool sampleStencil)297 SamplerTest::SamplerTest	(tcu::TestContext&			testContext,
298 							 const char*				name,
299 							 const char*				description,
300 							 PipelineConstructionType	pipelineConstructionType,
301 							 SamplerViewType			imageViewType,
302 							 VkFormat					imageFormat,
303 							 int						imageSize,
304 							 float						samplerLod,
305 							 bool						separateStencilUsage,
306 							 bool						sampleStencil)
307 	: vkt::TestCase					(testContext, name, description)
308 	, m_pipelineConstructionType	(pipelineConstructionType)
309 	, m_imageViewType				(imageViewType)
310 	, m_imageFormat					(imageFormat)
311 	, m_imageSize					(imageSize)
312 	, m_samplerLod					(samplerLod)
313 	, m_separateStencilUsage		(separateStencilUsage)
314 	, m_sampleStencil				(sampleStencil)
315 {
316 	// Can't do both at the same time with the current code.
317 	DE_ASSERT(!separateStencilUsage || !sampleStencil);
318 }
319 
getImageSamplingInstanceParams(SamplerViewType imageViewType, VkFormat imageFormat, int imageSize, float samplerLod, bool separateStencilUsage, bool sampleStencil) const320 ImageSamplingInstanceParams SamplerTest::getImageSamplingInstanceParams (SamplerViewType	imageViewType,
321 																		 VkFormat			imageFormat,
322 																		 int				imageSize,
323 																		 float				samplerLod,
324 																		 bool				separateStencilUsage,
325 																		 bool				sampleStencil) const
326 {
327 	const tcu::UVec2				renderSize			= getRenderSize(imageViewType);
328 	const std::vector<Vertex4Tex4>	vertices			= createVertices();
329 	const VkSamplerCreateInfo		samplerParams		= getSamplerCreateInfo();
330 	const VkComponentMapping		componentMapping	= getComponentMapping();
331 
332 	const auto						isDSFormat			= isDepthStencilFormat(imageFormat);
333 	const auto						tcuFormat			= (isDSFormat ? mapVkFormat(imageFormat) : tcu::TextureFormat());
334 	const auto						hasDepth			= (isDSFormat && tcu::hasDepthComponent(tcuFormat.order));
335 	const auto						hasStencil			= (isDSFormat && tcu::hasStencilComponent(tcuFormat.order));
336 	const auto						imageAspect			= (isDSFormat ? (sampleStencil ? VK_IMAGE_ASPECT_STENCIL_BIT : VK_IMAGE_ASPECT_DEPTH_BIT) : VK_IMAGE_ASPECT_COLOR_BIT);
337 	const deUint32					mipLevels			= (imageViewType.isNormalized() ? static_cast<deUint32>(deLog2Floor32(imageSize)) + 1u : 1u);
338 
339 	DE_UNREF(hasDepth);		// For debug builds.
340 	DE_UNREF(hasStencil);	// For debug builds.
341 	DE_ASSERT(imageAspect != VK_IMAGE_ASPECT_DEPTH_BIT || hasDepth);
342 	DE_ASSERT(imageAspect != VK_IMAGE_ASPECT_STENCIL_BIT || hasStencil);
343 
344 	const VkImageSubresourceRange	subresourceRange	=
345 	{
346 		imageAspect,										// VkImageAspectFlags	aspectMask;
347 		0u,													// deUint32				baseMipLevel;
348 		mipLevels,											// deUint32				mipLevels;
349 		0u,													// deUint32				baseArrayLayer;
350 		(deUint32)SamplerTest::getArraySize(imageViewType)	// deUint32				arraySize;
351 	};
352 
353 	return ImageSamplingInstanceParams(m_pipelineConstructionType, renderSize, imageViewType, imageFormat,
354 									   getImageSize(imageViewType, imageSize),
355 									   getArraySize(imageViewType),
356 									   componentMapping, subresourceRange,
357 									   samplerParams, samplerLod, vertices, separateStencilUsage);
358 }
359 
checkSupport(Context& context) const360 void SamplerTest::checkSupport (Context& context) const
361 {
362 	checkPipelineLibraryRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_pipelineConstructionType);
363 	checkSupportImageSamplingInstance(context, getImageSamplingInstanceParams(m_imageViewType, m_imageFormat, m_imageSize, m_samplerLod, m_separateStencilUsage, m_sampleStencil));
364 }
365 
swizzle(tcu::Vec4 inputData, VkComponentMapping componentMapping, float zeroOrOneValue) const366 tcu::Vec4 SamplerTest::swizzle (tcu::Vec4 inputData, VkComponentMapping componentMapping, float zeroOrOneValue) const
367 {
368 	// Remove VK_COMPONENT_SWIZZLE_IDENTITY to avoid addressing channelValues[0]
369 	const vk::VkComponentMapping nonIdentityMapping =
370 	{
371 		componentMapping.r == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_R : componentMapping.r,
372 		componentMapping.g == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_G : componentMapping.g,
373 		componentMapping.b == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_B : componentMapping.b,
374 		componentMapping.a == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_A : componentMapping.a
375 
376 	};
377 	// array map with enum VkComponentSwizzle
378 	const float channelValues[] =
379 	{
380 		-1.0f,					// impossible
381 		zeroOrOneValue,			// SWIZZLE_0
382 		zeroOrOneValue,			// SWIZZLE_1
383 		inputData.x(),
384 		inputData.y(),
385 		inputData.z(),
386 		inputData.w(),
387 		-1.0f
388 	};
389 
390 	return tcu::Vec4(channelValues[nonIdentityMapping.r],
391 					 channelValues[nonIdentityMapping.g],
392 					 channelValues[nonIdentityMapping.b],
393 					 channelValues[nonIdentityMapping.a]);
394 }
395 
initPrograms(SourceCollections& sourceCollections) const396 void SamplerTest::initPrograms (SourceCollections& sourceCollections) const
397 {
398 	std::ostringstream				vertexSrc;
399 	std::ostringstream				fragmentSrc;
400 	const char*						texCoordSwizzle	= DE_NULL;
401 	tcu::TextureFormat				format			= (isCompressedFormat(m_imageFormat)) ? tcu::getUncompressedFormat(mapVkCompressedFormat(m_imageFormat))
402 																						  : mapVkFormat(m_imageFormat);
403 	tcu::Vec4						lookupScale;
404 	tcu::Vec4						lookupBias;
405 
406 	getLookupScaleBias(m_imageFormat, lookupScale, lookupBias, m_sampleStencil);
407 
408 	tcu::Vec4						swizzledScale	= swizzle(lookupScale,	getComponentMapping(), 1.0f);
409 	tcu::Vec4						swizzledBias	= swizzle(lookupBias,	getComponentMapping(), 0.0f);
410 
411 	switch (m_imageViewType)
412 	{
413 		case VK_IMAGE_VIEW_TYPE_1D:
414 			texCoordSwizzle = "x";
415 			break;
416 		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
417 		case VK_IMAGE_VIEW_TYPE_2D:
418 			texCoordSwizzle = "xy";
419 			break;
420 		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
421 		case VK_IMAGE_VIEW_TYPE_3D:
422 		case VK_IMAGE_VIEW_TYPE_CUBE:
423 			texCoordSwizzle = "xyz";
424 			break;
425 		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
426 			texCoordSwizzle = "xyzw";
427 			break;
428 		default:
429 			DE_ASSERT(false);
430 			break;
431 	}
432 
433 	vertexSrc << "#version 440\n"
434 			  << "layout(location = 0) in vec4 position;\n"
435 			  << "layout(location = 1) in vec4 texCoords;\n"
436 			  << "layout(location = 0) out highp vec4 vtxTexCoords;\n"
437 			  << "out gl_PerVertex {\n"
438 			  << "	vec4 gl_Position;\n"
439 			  << "};\n"
440 			  << "void main (void)\n"
441 			  << "{\n"
442 			  << "	gl_Position = position;\n"
443 			  << "	vtxTexCoords = texCoords;\n"
444 			  << "}\n";
445 
446 	fragmentSrc << "#version 440\n"
447 				<< "layout(set = 0, binding = 0) uniform highp " << getGlslSamplerType(format, m_imageViewType, m_sampleStencil) << " texSampler;\n"
448 				<< "layout(location = 0) in highp vec4 vtxTexCoords;\n"
449 				<< "layout(location = 0) out highp vec4 fragColor;\n"
450 				<< "void main (void)\n"
451 				<< "{\n"
452 				<< "	fragColor = ";
453 
454 	if (m_samplerLod > 0.0f || !m_imageViewType.isNormalized())
455 	{
456 		DE_ASSERT(m_imageViewType.isNormalized() || (m_samplerLod == 0.0f && !m_imageViewType.isNormalized()));
457 		fragmentSrc << "textureLod(texSampler, vtxTexCoords." << texCoordSwizzle << ", " << std::fixed <<  m_samplerLod << ")";
458 	}
459 	else
460 	{
461 		fragmentSrc << "texture(texSampler, vtxTexCoords." << texCoordSwizzle << ")" << std::fixed;
462 	}
463 
464 	fragmentSrc << " * vec4" << std::scientific << swizzledScale << " + vec4" << swizzledBias << ";\n"
465 				<< "}\n";
466 
467 	sourceCollections.glslSources.add("tex_vert") << glu::VertexSource(vertexSrc.str());
468 	sourceCollections.glslSources.add("tex_frag") << glu::FragmentSource(fragmentSrc.str());
469 }
470 
createInstance(Context& context) const471 TestInstance* SamplerTest::createInstance (Context& context) const
472 {
473 	return new ImageSamplingInstance(context, getImageSamplingInstanceParams(m_imageViewType, m_imageFormat, m_imageSize, m_samplerLod, m_separateStencilUsage, m_sampleStencil));
474 }
475 
getRenderSize(SamplerViewType viewType) const476 tcu::UVec2 SamplerTest::getRenderSize (SamplerViewType viewType) const
477 {
478 	if (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_2D)
479 	{
480 		return tcu::UVec2(16u, 16u);
481 	}
482 	else
483 	{
484 		return tcu::UVec2(16u * 3u, 16u * 2u);
485 	}
486 }
487 
createVertices(void) const488 std::vector<Vertex4Tex4> SamplerTest::createVertices (void) const
489 {
490 	std::vector<Vertex4Tex4> vertices = createTestQuadMosaic(m_imageViewType);
491 	// Adjust texture coordinate to avoid doing NEAREST filtering exactly on texel boundaries.
492 	// TODO: Would be nice to base this on number of texels and subtexel precision. But this
493 	// seems to work.
494 	for (unsigned int i = 0; i < vertices.size(); ++i) {
495 		vertices[i].texCoord += tcu::Vec4(0.002f, 0.002f, 0.002f, 0.0f);
496 		if (!m_imageViewType.isNormalized()) {
497 			const float imageSize = static_cast<float>(m_imageSize);
498 			for (int j = 0; j < tcu::Vec4::SIZE; ++j)
499 				vertices[i].texCoord[j] *= imageSize;
500 		}
501 	}
502 	return vertices;
503 }
504 
getSamplerCreateInfo(void) const505 VkSamplerCreateInfo SamplerTest::getSamplerCreateInfo (void) const
506 {
507 	const VkSamplerCreateInfo defaultSamplerParams =
508 	{
509 		VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,													// VkStructureType			sType;
510 		DE_NULL,																				// const void*				pNext;
511 		0u,																						// VkSamplerCreateFlags		flags;
512 		VK_FILTER_NEAREST,																		// VkFilter					magFilter;
513 		VK_FILTER_NEAREST,																		// VkFilter					minFilter;
514 		VK_SAMPLER_MIPMAP_MODE_NEAREST,															// VkSamplerMipmapMode		mipmapMode;
515 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,													// VkSamplerAddressMode		addressModeU;
516 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,													// VkSamplerAddressMode		addressModeV;
517 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,													// VkSamplerAddressMode		addressModeW;
518 		0.0f,																					// float					mipLodBias;
519 		VK_FALSE,																				// VkBool32					anisotropyEnable;
520 		1.0f,																					// float					maxAnisotropy;
521 		false,																					// VkBool32					compareEnable;
522 		VK_COMPARE_OP_NEVER,																	// VkCompareOp				compareOp;
523 		0.0f,																					// float					minLod;
524 		(m_imageViewType.isNormalized() ? 0.25f : 0.0f),										// float					maxLod;
525 		getFormatBorderColor(BORDER_COLOR_TRANSPARENT_BLACK, m_imageFormat, m_sampleStencil),	// VkBorderColor			borderColor;
526 		!m_imageViewType.isNormalized(),														// VkBool32					unnormalizedCoordinates;
527 	};
528 
529 	return defaultSamplerParams;
530 }
531 
getComponentMapping(void) const532 VkComponentMapping SamplerTest::getComponentMapping (void) const
533 {
534 	const VkComponentMapping	componentMapping	= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
535 	return componentMapping;
536 }
537 
getGlslSamplerType(const tcu::TextureFormat& format, SamplerViewType type, bool sampleStencil)538 std::string SamplerTest::getGlslSamplerType (const tcu::TextureFormat& format, SamplerViewType type, bool sampleStencil)
539 {
540 	std::ostringstream samplerType;
541 
542 	if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER || sampleStencil)
543 		samplerType << "u";
544 	else if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
545 		samplerType << "i";
546 
547 	switch (type)
548 	{
549 		case VK_IMAGE_VIEW_TYPE_1D:
550 			samplerType << "sampler1D";
551 			break;
552 
553 		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
554 			samplerType << "sampler1DArray";
555 			break;
556 
557 		case VK_IMAGE_VIEW_TYPE_2D:
558 			samplerType << "sampler2D";
559 			break;
560 
561 		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
562 			samplerType << "sampler2DArray";
563 			break;
564 
565 		case VK_IMAGE_VIEW_TYPE_3D:
566 			samplerType << "sampler3D";
567 			break;
568 
569 		case VK_IMAGE_VIEW_TYPE_CUBE:
570 			samplerType << "samplerCube";
571 			break;
572 
573 		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
574 			samplerType << "samplerCubeArray";
575 			break;
576 
577 		default:
578 			DE_FATAL("Unknown image view type");
579 			break;
580 	}
581 
582 	return samplerType.str();
583 }
584 
getImageSize(SamplerViewType viewType, int size)585 tcu::IVec3 SamplerTest::getImageSize (SamplerViewType viewType, int size)
586 {
587 	switch (viewType)
588 	{
589 		case VK_IMAGE_VIEW_TYPE_1D:
590 		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
591 			return tcu::IVec3(size, 1, 1);
592 
593 		case VK_IMAGE_VIEW_TYPE_3D:
594 			return tcu::IVec3(size, size, 4);
595 
596 		default:
597 			break;
598 	}
599 
600 	return tcu::IVec3(size, size, 1);
601 }
602 
getArraySize(SamplerViewType viewType)603 int SamplerTest::getArraySize (SamplerViewType viewType)
604 {
605 	switch (viewType)
606 	{
607 		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
608 		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
609 		case VK_IMAGE_VIEW_TYPE_CUBE:
610 			return 6;
611 
612 		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
613 			return 36;
614 
615 		default:
616 			break;
617 	}
618 
619 	return 1;
620 }
621 
622 
623 // SamplerMagFilterTest
624 
SamplerMagFilterTest(tcu::TestContext& testContext, const char* name, const char* description, PipelineConstructionType pipelineConstructionType, SamplerViewType imageViewType, VkFormat imageFormat, VkFilter magFilter, bool separateStencilUsage)625 SamplerMagFilterTest::SamplerMagFilterTest (tcu::TestContext&			testContext,
626 											const char*					name,
627 											const char*					description,
628 											PipelineConstructionType	pipelineConstructionType,
629 											SamplerViewType				imageViewType,
630 											VkFormat					imageFormat,
631 											VkFilter					magFilter,
632 											bool						separateStencilUsage)
633 	: SamplerTest	(testContext, name, description, pipelineConstructionType, imageViewType, imageFormat, 8, 0.0f, separateStencilUsage, false)
634 	, m_magFilter	(magFilter)
635 {
636 }
637 
getSamplerCreateInfo(void) const638 VkSamplerCreateInfo SamplerMagFilterTest::getSamplerCreateInfo (void) const
639 {
640 	VkSamplerCreateInfo samplerParams = SamplerTest::getSamplerCreateInfo();
641 	samplerParams.magFilter = m_magFilter;
642 
643 	return samplerParams;
644 }
645 
646 
647 // SamplerMinFilterTest
648 
SamplerMinFilterTest(tcu::TestContext& testContext, const char* name, const char* description, PipelineConstructionType pipelineConstructionType, SamplerViewType imageViewType, VkFormat imageFormat, VkFilter minFilter, bool separateStencilUsage)649 SamplerMinFilterTest::SamplerMinFilterTest (tcu::TestContext&			testContext,
650 											const char*					name,
651 											const char*					description,
652 											PipelineConstructionType	pipelineConstructionType,
653 											SamplerViewType				imageViewType,
654 											VkFormat					imageFormat,
655 											VkFilter					minFilter,
656 											bool						separateStencilUsage)
657 	: SamplerTest	(testContext, name, description, pipelineConstructionType, imageViewType, imageFormat, 32, 0.0f, separateStencilUsage, false)
658 	, m_minFilter	(minFilter)
659 {
660 }
661 
getSamplerCreateInfo(void) const662 VkSamplerCreateInfo SamplerMinFilterTest::getSamplerCreateInfo (void) const
663 {
664 	VkSamplerCreateInfo samplerParams = SamplerTest::getSamplerCreateInfo();
665 	samplerParams.minFilter = m_minFilter;
666 	// set minLod to epsilon, to force use of the minFilter
667 	samplerParams.minLod = 0.01f;
668 
669 	return samplerParams;
670 }
671 
672 
673 namespace
674 {
675 
getSamplerReductionCreateInfo(VkSamplerReductionMode reductionMode)676 VkSamplerReductionModeCreateInfo getSamplerReductionCreateInfo (VkSamplerReductionMode reductionMode)
677 {
678 	const VkSamplerReductionModeCreateInfo ret =
679 	{
680 		VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO,		// VkStructureType				sType
681 		DE_NULL,													// const void*					pNext
682 		reductionMode												// VkSamplerReductionMode		reductionMode
683 	};
684 	return ret;
685 }
686 
687 }
688 
689 
690 // SamplerMagReduceFilterTest
691 
SamplerMagReduceFilterTest(tcu::TestContext& testContext, const char* name, const char* description, PipelineConstructionType pipelineConstructionType, SamplerViewType imageViewType, VkFormat imageFormat, VkComponentMapping componentMapping, VkSamplerReductionMode reductionMode, bool separateStencilUsage)692 SamplerMagReduceFilterTest::SamplerMagReduceFilterTest (tcu::TestContext&			testContext,
693 														const char*					name,
694 														const char*					description,
695 														PipelineConstructionType	pipelineConstructionType,
696 														SamplerViewType				imageViewType,
697 														VkFormat					imageFormat,
698 														VkComponentMapping			componentMapping,
699 														VkSamplerReductionMode		reductionMode,
700 														bool						separateStencilUsage)
701 	: SamplerMagFilterTest		(testContext, name, description, pipelineConstructionType, imageViewType, imageFormat, VK_FILTER_LINEAR, separateStencilUsage)
702 	, m_reductionCreaterInfo	(getSamplerReductionCreateInfo(reductionMode))
703 	, m_componentMapping		(componentMapping)
704 {
705 }
706 
getSamplerCreateInfo(void) const707 VkSamplerCreateInfo SamplerMagReduceFilterTest::getSamplerCreateInfo (void) const
708 {
709 	VkSamplerCreateInfo samplerParams	= SamplerMagFilterTest::getSamplerCreateInfo();
710 
711 	samplerParams.pNext					= &m_reductionCreaterInfo;
712 
713 	return samplerParams;
714 }
715 
getComponentMapping(void) const716 VkComponentMapping SamplerMagReduceFilterTest::getComponentMapping (void) const
717 {
718 	return m_componentMapping;
719 }
720 
721 // SamplerMinReduceFilterTest
722 
SamplerMinReduceFilterTest(tcu::TestContext& testContext, const char* name, const char* description, PipelineConstructionType pipelineConstructionType, SamplerViewType imageViewType, VkFormat imageFormat, VkComponentMapping componentMapping, VkSamplerReductionMode reductionMode, bool separateStencilUsage)723 SamplerMinReduceFilterTest::SamplerMinReduceFilterTest (tcu::TestContext&			testContext,
724 														const char*					name,
725 														const char*					description,
726 														PipelineConstructionType	pipelineConstructionType,
727 														SamplerViewType				imageViewType,
728 														VkFormat					imageFormat,
729 														VkComponentMapping			componentMapping,
730 														VkSamplerReductionMode		reductionMode,
731 														bool						separateStencilUsage)
732 	: SamplerMinFilterTest		(testContext, name, description, pipelineConstructionType, imageViewType, imageFormat, VK_FILTER_LINEAR, separateStencilUsage)
733 	, m_reductionCreaterInfo	(getSamplerReductionCreateInfo(reductionMode))
734 	, m_componentMapping		(componentMapping)
735 {
736 }
737 
getSamplerCreateInfo(void) const738 VkSamplerCreateInfo SamplerMinReduceFilterTest::getSamplerCreateInfo (void) const
739 {
740 	VkSamplerCreateInfo samplerParams	= SamplerMinFilterTest::getSamplerCreateInfo();
741 
742 	samplerParams.pNext					= &m_reductionCreaterInfo;
743 
744 	return samplerParams;
745 }
746 
getComponentMapping(void) const747 VkComponentMapping SamplerMinReduceFilterTest::getComponentMapping (void) const
748 {
749 	return m_componentMapping;
750 }
751 
752 // SamplerLodTest
753 
SamplerLodTest(tcu::TestContext& testContext, const char* name, const char* description, PipelineConstructionType pipelineConstructionType, SamplerViewType imageViewType, VkFormat imageFormat, VkSamplerMipmapMode mipmapMode, float minLod, float maxLod, float mipLodBias, float samplerLod, bool separateStencilUsage)754 SamplerLodTest::SamplerLodTest (tcu::TestContext&			testContext,
755 								const char*					name,
756 								const char*					description,
757 								PipelineConstructionType	pipelineConstructionType,
758 								SamplerViewType				imageViewType,
759 								VkFormat					imageFormat,
760 								VkSamplerMipmapMode			mipmapMode,
761 								float						minLod,
762 								float						maxLod,
763 								float						mipLodBias,
764 								float						samplerLod,
765 								bool						separateStencilUsage)
766 	: SamplerTest	(testContext, name, description, pipelineConstructionType, imageViewType, imageFormat, 32, samplerLod, separateStencilUsage, false)
767 	, m_mipmapMode	(mipmapMode)
768 	, m_minLod		(minLod)
769 	, m_maxLod		(maxLod)
770 	, m_mipLodBias	(mipLodBias)
771 {
772 }
773 
getSamplerCreateInfo(void) const774 VkSamplerCreateInfo SamplerLodTest::getSamplerCreateInfo (void) const
775 {
776 	VkSamplerCreateInfo samplerParams = SamplerTest::getSamplerCreateInfo();
777 
778 	samplerParams.mipmapMode	= m_mipmapMode;
779 	samplerParams.minLod		= m_minLod;
780 	samplerParams.maxLod		= m_maxLod;
781 	samplerParams.mipLodBias	= m_mipLodBias;
782 
783 	return samplerParams;
784 }
785 
786 
787 // SamplerAddressModesTest
788 
SamplerAddressModesTest(tcu::TestContext& testContext, const char* name, const char* description, PipelineConstructionType pipelineConstructionType, SamplerViewType imageViewType, VkFormat imageFormat, VkSamplerAddressMode addressU, VkSamplerAddressMode addressV, VkSamplerAddressMode addressW, VkBorderColor borderColor, rr::GenericVec4 customBorderColorValue, bool customBorderColorFormatless, bool separateStencilUsage, bool sampleStencil)789 SamplerAddressModesTest::SamplerAddressModesTest (tcu::TestContext&			testContext,
790 												  const char*				name,
791 												  const char*				description,
792 												  PipelineConstructionType	pipelineConstructionType,
793 												  SamplerViewType			imageViewType,
794 												  VkFormat					imageFormat,
795 												  VkSamplerAddressMode		addressU,
796 												  VkSamplerAddressMode		addressV,
797 												  VkSamplerAddressMode		addressW,
798 												  VkBorderColor				borderColor,
799 												  rr::GenericVec4			customBorderColorValue,
800 												  bool						customBorderColorFormatless,
801 												  bool						separateStencilUsage,
802 												  bool						sampleStencil)
803 	: SamplerTest	(testContext, name, description, pipelineConstructionType, imageViewType, imageFormat, 8, 0.0f, separateStencilUsage, sampleStencil)
804 	, m_addressU	(addressU)
805 	, m_addressV	(addressV)
806 	, m_addressW	(addressW)
807 	, m_borderColor	(borderColor)
808 	, m_customBorderColorCreateInfo	(getSamplerCustomBorderColorCreateInfo(imageFormat, customBorderColorValue, customBorderColorFormatless))
809 {
810 }
811 
getRenderSize(SamplerViewType viewType) const812 tcu::UVec2 SamplerAddressModesTest::getRenderSize (SamplerViewType viewType) const
813 {
814 	return 4u * SamplerTest::getRenderSize(viewType);
815 }
816 
createVertices(void) const817 std::vector<Vertex4Tex4> SamplerAddressModesTest::createVertices (void) const
818 {
819 	std::vector<Vertex4Tex4> vertices = SamplerTest::createVertices();
820 
821 	switch (m_imageViewType)
822 	{
823 		case VK_IMAGE_VIEW_TYPE_1D: case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
824 			for (size_t vertexNdx = 0; vertexNdx < vertices.size(); vertexNdx++)
825 				vertices[vertexNdx].texCoord.x() = (vertices[vertexNdx].texCoord.x() - 0.5f) * 4.0f;
826 
827 			break;
828 
829 		case VK_IMAGE_VIEW_TYPE_2D:
830 		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
831 			for (size_t vertexNdx = 0; vertexNdx < vertices.size(); vertexNdx++)
832 				vertices[vertexNdx].texCoord.xy() = (vertices[vertexNdx].texCoord.swizzle(0, 1) - tcu::Vec2(0.5f)) * 4.0f;
833 
834 			break;
835 
836 		case VK_IMAGE_VIEW_TYPE_3D:
837 			for (size_t vertexNdx = 0; vertexNdx < vertices.size(); vertexNdx++)
838 				vertices[vertexNdx].texCoord.xyz() = (vertices[vertexNdx].texCoord.swizzle(0, 1, 2) - tcu::Vec3(0.5f)) * 4.0f;
839 
840 			break;
841 
842 		case VK_IMAGE_VIEW_TYPE_CUBE:
843 		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
844 			break;
845 
846 		default:
847 			DE_ASSERT(false);
848 	}
849 
850 	return vertices;
851 }
852 
getSamplerCreateInfo(void) const853 VkSamplerCreateInfo SamplerAddressModesTest::getSamplerCreateInfo (void) const
854 {
855 	VkSamplerCreateInfo samplerParams = SamplerTest::getSamplerCreateInfo();
856 	samplerParams.addressModeU	= m_addressU;
857 	samplerParams.addressModeV	= m_addressV;
858 	samplerParams.addressModeW	= m_addressW;
859 	samplerParams.borderColor	= m_borderColor;
860 
861 	if (m_borderColor == VK_BORDER_COLOR_FLOAT_CUSTOM_EXT ||
862 		m_borderColor == VK_BORDER_COLOR_INT_CUSTOM_EXT)
863 	{
864 		samplerParams.pNext = &m_customBorderColorCreateInfo;
865 	}
866 
867 	return samplerParams;
868 }
869 
getSamplerCustomBorderColorCreateInfo(VkFormat format, rr::GenericVec4 customBorderColorValue, bool customBorderColorFormatless) const870 VkSamplerCustomBorderColorCreateInfoEXT	SamplerAddressModesTest::getSamplerCustomBorderColorCreateInfo	(VkFormat format, rr::GenericVec4 customBorderColorValue, bool customBorderColorFormatless) const
871 {
872 	const VkSamplerCustomBorderColorCreateInfoEXT defaultSamplerCustomBorderColorParams =
873 	{
874 		VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT,
875 		DE_NULL,
876 		mapVkColor(customBorderColorValue),
877 		customBorderColorFormatless ? VK_FORMAT_UNDEFINED : format
878 	};
879 
880 	return defaultSamplerCustomBorderColorParams;
881 }
882 
883 
884 // Utilities to create test nodes
885 
getFormatCaseName(const VkFormat format)886 std::string getFormatCaseName (const VkFormat format)
887 {
888 	const std::string fullName = getFormatName(format);
889 
890 	DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_"));
891 
892 	return de::toLower(fullName.substr(10));
893 }
894 
createSamplerMagFilterTests(tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType, SamplerViewType imageViewType, VkFormat imageFormat, bool separateStencilUsage)895 MovePtr<tcu::TestCaseGroup> createSamplerMagFilterTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType, SamplerViewType imageViewType, VkFormat imageFormat, bool separateStencilUsage)
896 {
897 	MovePtr<tcu::TestCaseGroup> samplerMagFilterTests (new tcu::TestCaseGroup(testCtx, "mag_filter", "Tests for magnification filter"));
898 
899 	if (imageViewType.isNormalized() && (isCompressedFormat(imageFormat) || (!isIntFormat(imageFormat) && !isUintFormat(imageFormat))))
900 		samplerMagFilterTests->addChild(new SamplerMagFilterTest(testCtx, "linear", "Magnifies image using VK_FILTER_LINEAR", pipelineConstructionType, imageViewType, imageFormat, VK_FILTER_LINEAR, separateStencilUsage));
901 	samplerMagFilterTests->addChild(new SamplerMagFilterTest(testCtx, "nearest", "Magnifies image using VK_FILTER_NEAREST", pipelineConstructionType, imageViewType, imageFormat, VK_FILTER_NEAREST, separateStencilUsage));
902 
903 	return samplerMagFilterTests;
904 }
905 
createSamplerMinFilterTests(tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType, SamplerViewType imageViewType, VkFormat imageFormat, bool separateStencilUsage)906 MovePtr<tcu::TestCaseGroup> createSamplerMinFilterTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType, SamplerViewType imageViewType, VkFormat imageFormat, bool separateStencilUsage)
907 {
908 	MovePtr<tcu::TestCaseGroup> samplerMinFilterTests (new tcu::TestCaseGroup(testCtx, "min_filter", "Tests for minification filter"));
909 
910 	if (imageViewType.isNormalized() && (isCompressedFormat(imageFormat) || (!isIntFormat(imageFormat) && !isUintFormat(imageFormat))))
911 		samplerMinFilterTests->addChild(new SamplerMinFilterTest(testCtx, "linear", "Minifies image using VK_FILTER_LINEAR", pipelineConstructionType, imageViewType, imageFormat, VK_FILTER_LINEAR, separateStencilUsage));
912 	samplerMinFilterTests->addChild(new SamplerMinFilterTest(testCtx, "nearest", "Minifies image using VK_FILTER_NEAREST", pipelineConstructionType, imageViewType, imageFormat, VK_FILTER_NEAREST, separateStencilUsage));
913 
914 	return samplerMinFilterTests;
915 }
916 
917 const VkComponentMapping reduceFilterComponentMappings[]	=
918 {
919 	// filterMinmaxImageComponentMapping  == false - compatible mappings:
920 	{ VK_COMPONENT_SWIZZLE_IDENTITY,	VK_COMPONENT_SWIZZLE_ZERO,	VK_COMPONENT_SWIZZLE_ZERO,		VK_COMPONENT_SWIZZLE_ZERO	},
921 	{ VK_COMPONENT_SWIZZLE_R,			VK_COMPONENT_SWIZZLE_ZERO,	VK_COMPONENT_SWIZZLE_ZERO,		VK_COMPONENT_SWIZZLE_ZERO	},
922 
923 	// other mappings
924 	{ VK_COMPONENT_SWIZZLE_R,			VK_COMPONENT_SWIZZLE_G,		VK_COMPONENT_SWIZZLE_B,			VK_COMPONENT_SWIZZLE_A		},
925 	{ VK_COMPONENT_SWIZZLE_B,			VK_COMPONENT_SWIZZLE_G,		VK_COMPONENT_SWIZZLE_R,			VK_COMPONENT_SWIZZLE_A		},
926 	{ VK_COMPONENT_SWIZZLE_ONE,			VK_COMPONENT_SWIZZLE_R,		VK_COMPONENT_SWIZZLE_R,			VK_COMPONENT_SWIZZLE_R		},
927 };
928 
getShortComponentSwizzleName(VkComponentSwizzle componentSwizzle)929 static std::string getShortComponentSwizzleName (VkComponentSwizzle componentSwizzle)
930 {
931 	const std::string	fullName	= getComponentSwizzleName(componentSwizzle);
932 	const char*			prefix		= "VK_COMPONENT_SWIZZLE_";
933 
934 	DE_ASSERT(de::beginsWith(fullName, prefix));
935 
936 	return de::toLower(fullName.substr(deStrnlen(prefix, -1)));
937 }
938 
getComponentMappingGroupName(const VkComponentMapping& componentMapping)939 static std::string getComponentMappingGroupName (const VkComponentMapping& componentMapping)
940 {
941 	std::ostringstream name;
942 
943 	name << "comp_";
944 
945 	name << getShortComponentSwizzleName(componentMapping.r) << "_"
946 		 << getShortComponentSwizzleName(componentMapping.g) << "_"
947 		 << getShortComponentSwizzleName(componentMapping.b) << "_"
948 		 << getShortComponentSwizzleName(componentMapping.a);
949 
950 	return name.str();
951 }
952 
createSamplerMagReduceFilterTests(tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType, SamplerViewType imageViewType, VkFormat imageFormat, bool separateStencilUsage)953 MovePtr<tcu::TestCaseGroup> createSamplerMagReduceFilterTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType, SamplerViewType imageViewType, VkFormat imageFormat, bool separateStencilUsage)
954 {
955 	MovePtr<tcu::TestCaseGroup> samplerMagReduceFilterTests (new tcu::TestCaseGroup(testCtx, "mag_reduce", "Tests for magnification reduce filter"));
956 
957 	for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(reduceFilterComponentMappings); ++i)
958 	{
959 		const VkComponentMapping&	mapping		= reduceFilterComponentMappings[i];
960 
961 		MovePtr<tcu::TestCaseGroup> componentGroup (new tcu::TestCaseGroup(testCtx, getComponentMappingGroupName(mapping).c_str(), "Group for given view component mapping"));
962 
963 		if (isCompressedFormat(imageFormat) || (!isIntFormat(imageFormat) && !isUintFormat(imageFormat)))
964 		{
965 			componentGroup->addChild(new SamplerMagReduceFilterTest(testCtx, "average", "Magnifies image using VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE", pipelineConstructionType, imageViewType, imageFormat, mapping, VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE, separateStencilUsage));
966 		}
967 		componentGroup->addChild(new SamplerMagReduceFilterTest(testCtx, "min", "Magnifies and reduces image using VK_SAMPLER_REDUCTION_MODE_MIN", pipelineConstructionType, imageViewType, imageFormat, mapping, VK_SAMPLER_REDUCTION_MODE_MIN, separateStencilUsage));
968 		componentGroup->addChild(new SamplerMagReduceFilterTest(testCtx, "max", "Magnifies and reduces image using VK_SAMPLER_REDUCTION_MODE_MAX", pipelineConstructionType, imageViewType, imageFormat, mapping, VK_SAMPLER_REDUCTION_MODE_MAX, separateStencilUsage));
969 		samplerMagReduceFilterTests->addChild(componentGroup.release());
970 	}
971 	return samplerMagReduceFilterTests;
972 }
973 
createSamplerMinReduceFilterTests(tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType, SamplerViewType imageViewType, VkFormat imageFormat, bool separateStencilUsage)974 MovePtr<tcu::TestCaseGroup> createSamplerMinReduceFilterTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType, SamplerViewType imageViewType, VkFormat imageFormat, bool separateStencilUsage)
975 {
976 	MovePtr<tcu::TestCaseGroup> samplerMinReduceFilterTests (new tcu::TestCaseGroup(testCtx, "min_reduce", "Tests for minification reduce filter"));
977 
978 	for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(reduceFilterComponentMappings); ++i)
979 	{
980 		const VkComponentMapping&	mapping = reduceFilterComponentMappings[i];
981 
982 		MovePtr<tcu::TestCaseGroup> componentGroup (new tcu::TestCaseGroup(testCtx, getComponentMappingGroupName(mapping).c_str(), "Group for given view component mapping"));
983 
984 		if (isCompressedFormat(imageFormat) || (!isIntFormat(imageFormat) && !isUintFormat(imageFormat)))
985 		{
986 			componentGroup->addChild(new SamplerMinReduceFilterTest(testCtx, "average", "Minifies image using VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE", pipelineConstructionType, imageViewType, imageFormat, mapping, VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE, separateStencilUsage));
987 		}
988 		componentGroup->addChild(new SamplerMinReduceFilterTest(testCtx, "min", "Minifies and reduces image using VK_SAMPLER_REDUCTION_MODE_MIN", pipelineConstructionType, imageViewType, imageFormat, mapping, VK_SAMPLER_REDUCTION_MODE_MIN, separateStencilUsage));
989 		componentGroup->addChild(new SamplerMinReduceFilterTest(testCtx, "max", "Minifies and reduces image using VK_SAMPLER_REDUCTION_MODE_MAX", pipelineConstructionType, imageViewType, imageFormat, mapping, VK_SAMPLER_REDUCTION_MODE_MAX, separateStencilUsage));
990 		samplerMinReduceFilterTests->addChild(componentGroup.release());
991 	}
992 	return samplerMinReduceFilterTests;
993 }
994 
createSamplerLodTests(tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType, SamplerViewType imageViewType, VkFormat imageFormat, VkSamplerMipmapMode mipmapMode, bool separateStencilUsage)995 MovePtr<tcu::TestCaseGroup> createSamplerLodTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType, SamplerViewType imageViewType, VkFormat imageFormat, VkSamplerMipmapMode mipmapMode, bool separateStencilUsage)
996 {
997 	struct TestCaseConfig
998 	{
999 		const char*	name;
1000 		const char*	description;
1001 		float		minLod;
1002 		float		maxLod;
1003 		float		mipLodBias;
1004 		float		lod;
1005 	};
1006 
1007 	TestCaseConfig testCaseConfigs [] =
1008 	{
1009 		{ "equal_min_3_max_3",		"minLod = 3, maxLod = 3, mipLodBias = 0, lod = 0",		3.0f, 3.0f, 0.0f, 0.0f },
1010 		{ "select_min_1",			"minLod = 1, maxLod = 5, mipLodBias = 0, lod = 0",		1.0f, 5.0f, 0.0f, 0.0f },
1011 		{ "select_max_4",			"minLod = 0, maxLod = 4, mipLodBias = 0, lod = 5",		0.0f, 4.0f, 0.0f, 5.0f },
1012 		{ "select_bias_2_1",		"minLod = 0, maxLod = 2.1, mipLodBias = 5.0, lod = 0",	0.0f, 2.1f, 5.0f, 0.0f },
1013 		{ "select_bias_2_5",		"minLod = 0, maxLod = 5, mipLodBias = 2.5, lod = 0",	0.0f, 5.0f, 2.5f, 0.00001f },
1014 		{ "select_bias_3_1",		"minLod = 0, maxLod = 5, mipLodBias = -0.9, lod = 4.0",	0.0f, 5.0f, -0.9f, 4.0f },
1015 		{ "select_bias_3_7",		"minLod = 0, maxLod = 5, mipLodBias = 3.0, lod = 0.7",	0.0f, 5.0f, 3.0f, 0.7f },
1016 	};
1017 
1018 	MovePtr<tcu::TestCaseGroup> samplerLodTests (new tcu::TestCaseGroup(testCtx, "lod", "Tests for sampler LOD"));
1019 
1020 	for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(testCaseConfigs); configNdx++)
1021 	{
1022 		const TestCaseConfig& config = testCaseConfigs[configNdx];
1023 
1024 		samplerLodTests->addChild(new SamplerLodTest(testCtx, config.name, config.description, pipelineConstructionType, imageViewType, imageFormat, mipmapMode, config.minLod, config.maxLod, config.mipLodBias, config.lod, separateStencilUsage));
1025 	}
1026 
1027 	return samplerLodTests;
1028 }
1029 
createSamplerMipmapTests(tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType, SamplerViewType imageViewType, VkFormat imageFormat, bool separateStencilUsage)1030 MovePtr<tcu::TestCaseGroup> createSamplerMipmapTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType, SamplerViewType imageViewType, VkFormat imageFormat, bool separateStencilUsage)
1031 {
1032 	MovePtr<tcu::TestCaseGroup> samplerMipmapTests (new tcu::TestCaseGroup(testCtx, "mipmap", "Tests for mipmap modes"));
1033 
1034 	// Mipmap mode: nearest
1035 	MovePtr<tcu::TestCaseGroup> mipmapNearestTests (new tcu::TestCaseGroup(testCtx, "nearest", "Uses VK_TEX_MIPMAP_MODE_NEAREST"));
1036 	mipmapNearestTests->addChild(createSamplerLodTests(testCtx, pipelineConstructionType, imageViewType, imageFormat, VK_SAMPLER_MIPMAP_MODE_NEAREST, separateStencilUsage).release());
1037 	samplerMipmapTests->addChild(mipmapNearestTests.release());
1038 
1039 	// Mipmap mode: linear
1040 	if (isCompressedFormat(imageFormat) || (!isIntFormat(imageFormat) && !isUintFormat(imageFormat)))
1041 	{
1042 		MovePtr<tcu::TestCaseGroup> mipmapLinearTests(new tcu::TestCaseGroup(testCtx, "linear", "Uses VK_TEX_MIPMAP_MODE_LINEAR"));
1043 		mipmapLinearTests->addChild(createSamplerLodTests(testCtx, pipelineConstructionType, imageViewType, imageFormat, VK_SAMPLER_MIPMAP_MODE_LINEAR, separateStencilUsage).release());
1044 		samplerMipmapTests->addChild(mipmapLinearTests.release());
1045 	}
1046 
1047 	return samplerMipmapTests;
1048 }
1049 
getAddressModesCaseName(VkSamplerAddressMode u, VkSamplerAddressMode v, VkSamplerAddressMode w, BorderColor border, tcu::IVec4 customIntValue, bool formatless, bool sampleStencil)1050 std::string getAddressModesCaseName (VkSamplerAddressMode u, VkSamplerAddressMode v, VkSamplerAddressMode w, BorderColor border, tcu::IVec4 customIntValue, bool formatless, bool sampleStencil)
1051 {
1052 	static const char* borderColorNames[BORDER_COLOR_COUNT] =
1053 	{
1054 		"opaque_black",
1055 		"opaque_white",
1056 		"transparent_black",
1057 		"custom"
1058 	};
1059 
1060 	std::ostringstream caseName;
1061 
1062 	if (u == v && v == w)
1063 	{
1064 		const std::string fullName = getSamplerAddressModeName(u);
1065 		DE_ASSERT(de::beginsWith(fullName, "VK_SAMPLER_ADDRESS_"));
1066 
1067 		caseName << "all_";
1068 		caseName << de::toLower(fullName.substr(19));
1069 
1070 		if (u == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER)
1071 		{
1072 			caseName << "_" << borderColorNames[border];
1073 		}
1074 	}
1075 	else
1076 	{
1077 		const std::string fullNameU = getSamplerAddressModeName(u);
1078 		const std::string fullNameV = getSamplerAddressModeName(v);
1079 		const std::string fullNameW = getSamplerAddressModeName(w);
1080 
1081 		DE_ASSERT(de::beginsWith(fullNameU, "VK_SAMPLER_ADDRESS_"));
1082 		DE_ASSERT(de::beginsWith(fullNameV, "VK_SAMPLER_ADDRESS_"));
1083 		DE_ASSERT(de::beginsWith(fullNameW, "VK_SAMPLER_ADDRESS_"));
1084 
1085 		caseName << "uvw"
1086 				 << "_" << de::toLower(fullNameU.substr(19))
1087 				 << "_" << de::toLower(fullNameV.substr(19))
1088 				 << "_" << de::toLower(fullNameW.substr(19));
1089 	}
1090 
1091 	if (border == BORDER_COLOR_CUSTOM)
1092 	{
1093 		caseName << "_";
1094 		for (int i = 0; i < 4; i++)
1095 			caseName << customIntValue[i];
1096 
1097 		if (formatless)
1098 			caseName << "_formatless";
1099 
1100 	}
1101 
1102 	if (sampleStencil)
1103 		caseName << "_stencil";
1104 
1105 	return caseName.str();
1106 }
1107 
createSamplerAddressModesTests(tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType, SamplerViewType imageViewType, VkFormat imageFormat, bool separateStencilUsage)1108 MovePtr<tcu::TestCaseGroup> createSamplerAddressModesTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType, SamplerViewType imageViewType, VkFormat imageFormat, bool separateStencilUsage)
1109 {
1110 	struct TestCaseConfig
1111 	{
1112 		TestCaseConfig	(VkSamplerAddressMode	_u,
1113 						 VkSamplerAddressMode	_v,
1114 						 VkSamplerAddressMode	_w,
1115 						 BorderColor			_border,
1116 						 bool					_customColorFormatless	= false,
1117 						 tcu::Vec4				_customColorValueFloat	= tcu::Vec4(),
1118 						 tcu::IVec4				_customColorValueInt	= tcu::IVec4())
1119 			: u(_u), v(_v), w(_w), border(_border), customColorFormatless(_customColorFormatless)
1120 			, customColorValueFloat(_customColorValueFloat), customColorValueInt(_customColorValueInt)
1121 		{
1122 
1123 		}
1124 
1125 		VkSamplerAddressMode	u;
1126 		VkSamplerAddressMode	v;
1127 		VkSamplerAddressMode	w;
1128 		BorderColor				border;
1129 		bool					customColorFormatless;
1130 		tcu::Vec4				customColorValueFloat;
1131 		tcu::IVec4				customColorValueInt;
1132 	};
1133 
1134 	const TestCaseConfig testCaseConfigs[] =
1135 	{
1136 		// All address modes equal
1137 		{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			BORDER_COLOR_TRANSPARENT_BLACK },
1138 		{ VK_SAMPLER_ADDRESS_MODE_REPEAT,				VK_SAMPLER_ADDRESS_MODE_REPEAT,					VK_SAMPLER_ADDRESS_MODE_REPEAT,					BORDER_COLOR_TRANSPARENT_BLACK },
1139 		{ VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,		VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,		VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,		BORDER_COLOR_TRANSPARENT_BLACK },
1140 		{ VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,	VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,	VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,	BORDER_COLOR_TRANSPARENT_BLACK },
1141 
1142 		// All address modes equal using border color
1143 		{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		BORDER_COLOR_TRANSPARENT_BLACK },
1144 		{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		BORDER_COLOR_OPAQUE_BLACK },
1145 		{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		BORDER_COLOR_OPAQUE_WHITE },
1146 
1147 		// Pairwise combinations of address modes not covered by previous tests
1148 		{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,	VK_SAMPLER_ADDRESS_MODE_REPEAT,					BORDER_COLOR_OPAQUE_WHITE},
1149 		{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,		VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,	BORDER_COLOR_OPAQUE_WHITE },
1150 		{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_REPEAT,					VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,		BORDER_COLOR_OPAQUE_WHITE },
1151 		{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			BORDER_COLOR_OPAQUE_WHITE },
1152 		{ VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,	VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,		BORDER_COLOR_OPAQUE_WHITE },
1153 		{ VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,	VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,	VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		BORDER_COLOR_OPAQUE_WHITE },
1154 		{ VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,	VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,		VK_SAMPLER_ADDRESS_MODE_REPEAT,					BORDER_COLOR_OPAQUE_WHITE },
1155 		{ VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,	VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,	BORDER_COLOR_OPAQUE_WHITE },
1156 		{ VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,	VK_SAMPLER_ADDRESS_MODE_REPEAT,					VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			BORDER_COLOR_OPAQUE_WHITE },
1157 		{ VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,	BORDER_COLOR_OPAQUE_WHITE },
1158 		{ VK_SAMPLER_ADDRESS_MODE_REPEAT,				VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,	VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,	BORDER_COLOR_OPAQUE_WHITE },
1159 		{ VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,		VK_SAMPLER_ADDRESS_MODE_REPEAT,					VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		BORDER_COLOR_OPAQUE_WHITE },
1160 		{ VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			VK_SAMPLER_ADDRESS_MODE_REPEAT,					BORDER_COLOR_OPAQUE_WHITE },
1161 		{ VK_SAMPLER_ADDRESS_MODE_REPEAT,				VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			BORDER_COLOR_OPAQUE_WHITE },
1162 		{ VK_SAMPLER_ADDRESS_MODE_REPEAT,				VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		BORDER_COLOR_OPAQUE_WHITE },
1163 		{ VK_SAMPLER_ADDRESS_MODE_REPEAT,				VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,		BORDER_COLOR_OPAQUE_WHITE },
1164 		{ VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,		VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,	VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			BORDER_COLOR_OPAQUE_WHITE },
1165 		{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		BORDER_COLOR_OPAQUE_WHITE },
1166 		{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_REPEAT,					BORDER_COLOR_OPAQUE_WHITE },
1167 		{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		VK_SAMPLER_ADDRESS_MODE_REPEAT,					VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,	BORDER_COLOR_OPAQUE_WHITE },
1168 		{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			BORDER_COLOR_OPAQUE_WHITE },
1169 		{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,	VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,		BORDER_COLOR_OPAQUE_WHITE },
1170 
1171 		// Custom border color tests
1172 		{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		BORDER_COLOR_CUSTOM,
1173 			false,	tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),	tcu::IVec4(0, 0, 0, 0) },
1174 		{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		BORDER_COLOR_CUSTOM,
1175 			false,	tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),	tcu::IVec4(0, 0, 1, 1) },
1176 		{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		BORDER_COLOR_CUSTOM,
1177 			false,	tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f),	tcu::IVec4(1, 0, 0, 0) },
1178 		{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		BORDER_COLOR_CUSTOM,
1179 			false,	tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),	tcu::IVec4(1, 0, 0, 1) },
1180 		{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		BORDER_COLOR_CUSTOM,
1181 			false,	tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f),	tcu::IVec4(1, 0, 1, 1) },
1182 		{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		BORDER_COLOR_CUSTOM,
1183 			false,	tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f),	tcu::IVec4(1, 1, 0, 1) },
1184 
1185 		// Custom border color formatless
1186 		{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		BORDER_COLOR_CUSTOM,
1187 			true,	tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f),	tcu::IVec4(1, 0, 1, 1) },
1188 		{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		BORDER_COLOR_CUSTOM,
1189 			true,	tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f),	tcu::IVec4(1, 1, 0, 1) },
1190 	};
1191 
1192 	MovePtr<tcu::TestCaseGroup> samplerAddressModesTests (new tcu::TestCaseGroup(testCtx, "address_modes", "Tests for address modes"));
1193 
1194 	for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(testCaseConfigs); configNdx++)
1195 	{
1196 		const TestCaseConfig& config = testCaseConfigs[configNdx];
1197 
1198 		if (!imageViewType.isNormalized() &&
1199 			((config.u != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE && config.u != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER) ||
1200 			 (config.v != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE && config.v != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER)))
1201 			 continue;
1202 
1203 		// VK_FORMAT_B4G4R4A4_UNORM_PACK16, VK_FORMAT_B5G6R5_UNORM_PACK16 and VK_FORMAT_B5G5R5A1_UNORM_PACK16 are forbidden
1204 		// for non-formatless custom border color.
1205 		if ((imageFormat == VK_FORMAT_B4G4R4A4_UNORM_PACK16 ||
1206 			 imageFormat == VK_FORMAT_B5G6R5_UNORM_PACK16   ||
1207 			 imageFormat == VK_FORMAT_B5G5R5A1_UNORM_PACK16)  && config.border == BORDER_COLOR_CUSTOM && config.customColorFormatless)
1208 			continue;
1209 
1210 		for (int i = 0; i < 2; ++i)
1211 		{
1212 			const bool isDSFormat		= isDepthStencilFormat(imageFormat);
1213 			const bool sampleStencil	= (i > 0);
1214 
1215 			if (separateStencilUsage && sampleStencil)
1216 				continue;
1217 
1218 			if (!isDSFormat && sampleStencil)
1219 				continue;
1220 
1221 			if (isDSFormat)
1222 			{
1223 				const auto tcuFormat = mapVkFormat(imageFormat);
1224 
1225 				if (!sampleStencil && !tcu::hasDepthComponent(tcuFormat.order))
1226 					continue;
1227 				if (sampleStencil && !tcu::hasStencilComponent(tcuFormat.order))
1228 					continue;
1229 			}
1230 
1231 			samplerAddressModesTests->addChild(new SamplerAddressModesTest(testCtx,
1232 																		getAddressModesCaseName(config.u, config.v, config.w, config.border, config.customColorValueInt, config.customColorFormatless, sampleStencil).c_str(),
1233 																		"",
1234 																		pipelineConstructionType,
1235 																		imageViewType,
1236 																		imageFormat,
1237 																		config.u, config.v, config.w,
1238 																		getFormatBorderColor(config.border, imageFormat, sampleStencil),
1239 																		getFormatCustomBorderColor(config.customColorValueFloat, config.customColorValueInt, imageFormat, sampleStencil),
1240 																		config.customColorFormatless,
1241 																		separateStencilUsage,
1242 																		sampleStencil));
1243 		}
1244 	}
1245 
1246 	return samplerAddressModesTests;
1247 }
1248 
1249 // Exact sampling case:
1250 //	1) Create a texture and a framebuffer image of the same size.
1251 //	2) Draw a full screen quad with the texture and VK_FILTER_NEAREST.
1252 //	3) Verify the rendered image matches the texture exactly.
1253 class ExactSamplingCase : public vkt::TestCase
1254 {
1255 public:
1256 	struct Params
1257 	{
1258 		PipelineConstructionType	pipelineConstructionType;
1259 		vk::VkFormat				format;
1260 		bool						unnormalizedCoordinates;
1261 		bool						solidColor;
1262 		tcu::Maybe<float>			offsetSign; // -1.0 or 1.0
1263 	};
1264 
1265 	struct PushConstants
1266 	{
1267 		float texWidth;
1268 		float texHeight;
1269 	};
1270 
1271 	struct VertexData
1272 	{
1273 		tcu::Vec2 vtxCoords;
1274 		tcu::Vec2 texCoords;
1275 
1276 		static vk::VkVertexInputBindingDescription					getBindingDescription		(void);
1277 		static std::vector<vk::VkVertexInputAttributeDescription>	getAttributeDescriptions	(void);
1278 	};
1279 
1280 									ExactSamplingCase		(tcu::TestContext& testCtx, const std::string& name, const std::string& description, const Params& params);
~ExactSamplingCase(void)1281 	virtual							~ExactSamplingCase		(void) {}
1282 
1283 	virtual void					initPrograms			(vk::SourceCollections& programCollection) const;
1284 	virtual TestInstance*			createInstance			(Context& context) const;
1285 	virtual void					checkSupport			(Context& context) const;
1286 
1287 private:
1288 	Params m_params;
1289 };
1290 
1291 class ExactSamplingInstance : public vkt::TestInstance
1292 {
1293 public:
1294 	using Params = ExactSamplingCase::Params;
1295 
1296 								ExactSamplingInstance	(Context& context, const Params& params);
~ExactSamplingInstance(void)1297 	virtual						~ExactSamplingInstance	(void) {}
1298 
1299 	virtual tcu::TestStatus		iterate					(void);
1300 
1301 	vk::VkExtent3D				getTextureExtent		(void) const;
1302 
1303 private:
1304 	Params m_params;
1305 };
1306 
getBindingDescription(void)1307 vk::VkVertexInputBindingDescription ExactSamplingCase::VertexData::getBindingDescription (void)
1308 {
1309 	static const vk::VkVertexInputBindingDescription desc =
1310 	{
1311 		0u,																// deUint32				binding;
1312 		static_cast<deUint32>(sizeof(ExactSamplingCase::VertexData)),	// deUint32				stride;
1313 		vk::VK_VERTEX_INPUT_RATE_VERTEX,								// VkVertexInputRate	inputRate;
1314 	};
1315 
1316 	return desc;
1317 }
1318 
getAttributeDescriptions(void)1319 std::vector<vk::VkVertexInputAttributeDescription> ExactSamplingCase::VertexData::getAttributeDescriptions (void)
1320 {
1321 	static const std::vector<vk::VkVertexInputAttributeDescription> desc =
1322 	{
1323 		{
1324 			0u,																			// deUint32	location;
1325 			0u,																			// deUint32	binding;
1326 			vk::VK_FORMAT_R32G32_SFLOAT,												// VkFormat	format;
1327 			static_cast<deUint32>(offsetof(ExactSamplingCase::VertexData, vtxCoords)),	// deUint32	offset;
1328 		},
1329 		{
1330 			1u,																			// deUint32	location;
1331 			0u,																			// deUint32	binding;
1332 			vk::VK_FORMAT_R32G32_SFLOAT,												// VkFormat	format;
1333 			static_cast<deUint32>(offsetof(ExactSamplingCase::VertexData, texCoords)),	// deUint32	offset;
1334 		},
1335 	};
1336 
1337 	return desc;
1338 }
1339 
1340 
ExactSamplingCase(tcu::TestContext& testCtx, const std::string& name, const std::string& description, const Params& params)1341 ExactSamplingCase::ExactSamplingCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const Params& params)
1342 	: vkt::TestCase{testCtx, name, description}, m_params(params)
1343 {
1344 }
1345 
initPrograms(vk::SourceCollections& programCollection) const1346 void ExactSamplingCase::initPrograms (vk::SourceCollections& programCollection) const
1347 {
1348 	std::ostringstream vertexShader;
1349 
1350 	std::string texCoordX = "inTexCoord.x";
1351 	std::string texCoordY = "inTexCoord.y";
1352 
1353 	if (m_params.unnormalizedCoordinates)
1354 	{
1355 		texCoordX += " * pushc.texWidth";
1356 		texCoordY += " * pushc.texHeight";
1357 	}
1358 
1359 	vertexShader
1360 		<< "#version 450\n"
1361 		<< "\n"
1362 		<< "layout(push_constant, std430) uniform PushConstants\n"
1363 		<< "{\n"
1364 		<< "    float texWidth;\n"
1365 		<< "    float texHeight;\n"
1366 		<< "} pushc;\n"
1367 		<< "\n"
1368 		<< "layout(location = 0) in vec2 inPosition;\n"
1369 		<< "layout(location = 1) in vec2 inTexCoord;\n"
1370 		<< "\n"
1371 		<< "layout(location = 0) out vec2 fragTexCoord;\n"
1372 		<< "\n"
1373 		<< "void main() {\n"
1374 		<< "    gl_Position = vec4(inPosition, 0.0, 1.0);\n"
1375 		<< "    fragTexCoord = vec2(" << texCoordX << ", " << texCoordY << ");\n"
1376 		<< "}\n"
1377 		;
1378 
1379 	programCollection.glslSources.add("vert") << glu::VertexSource{vertexShader.str()};
1380 
1381 	std::ostringstream fragmentShader;
1382 
1383 	std::string typePrefix;
1384 	if (vk::isIntFormat(m_params.format))
1385 		typePrefix = "i";
1386 	else if (vk::isUintFormat(m_params.format))
1387 		typePrefix = "u";
1388 
1389 	const std::string samplerType = typePrefix + "sampler2D";
1390 	const std::string colorType = typePrefix + "vec4";
1391 
1392 	fragmentShader
1393 		<< "#version 450\n"
1394 		<< "\n"
1395 		<< "layout(set = 0, binding = 0) uniform " << samplerType << " texSampler;\n"
1396 		<< "\n"
1397 		<< "layout(location = 0) in vec2 fragTexCoord;\n"
1398 		<< "\n"
1399 		<< "layout(location = 0) out " << colorType << " outColor;\n"
1400 		<< "\n"
1401 		<< "void main() {\n";
1402 
1403 	if (m_params.unnormalizedCoordinates)
1404 	{
1405 		fragmentShader << "    outColor = textureLod(texSampler, fragTexCoord, 0.0f);";
1406 	}
1407 	else
1408 	{
1409 		fragmentShader << "    outColor = texture(texSampler, fragTexCoord);\n";
1410 	}
1411 
1412 	fragmentShader << "}\n";
1413 
1414 	programCollection.glslSources.add("frag") << glu::FragmentSource{fragmentShader.str()};
1415 }
1416 
createInstance(Context& context) const1417 TestInstance* ExactSamplingCase::createInstance (Context& context) const
1418 {
1419 	return new ExactSamplingInstance{context, m_params};
1420 }
1421 
checkSupport(Context& context) const1422 void ExactSamplingCase::checkSupport (Context& context) const
1423 {
1424 	const auto&						vki					= context.getInstanceInterface();
1425 	const auto						physicalDevice		= context.getPhysicalDevice();
1426 	const auto						props				= vk::getPhysicalDeviceFormatProperties(vki, physicalDevice, m_params.format);
1427 	const vk::VkFormatFeatureFlags	requiredFeatures	=
1428 		(vk::VK_FORMAT_FEATURE_TRANSFER_DST_BIT
1429 		|vk::VK_FORMAT_FEATURE_TRANSFER_SRC_BIT
1430 		|vk::VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT
1431 		|vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT
1432 		|(m_params.solidColor ? vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT : 0)
1433 		);
1434 
1435 	checkPipelineLibraryRequirements(vki, physicalDevice, m_params.pipelineConstructionType);
1436 
1437 	if ((props.optimalTilingFeatures & requiredFeatures) != requiredFeatures)
1438 		TCU_THROW(NotSupportedError, "Selected format does not support the required features");
1439 }
1440 
ExactSamplingInstance(Context& context, const Params& params)1441 ExactSamplingInstance::ExactSamplingInstance (Context& context, const Params& params)
1442 	: vkt::TestInstance{context}, m_params(params)
1443 {
1444 }
1445 
getTextureExtent(void) const1446 vk::VkExtent3D ExactSamplingInstance::getTextureExtent (void) const
1447 {
1448 	return vk::makeExtent3D(256u, 256u, 1u);
1449 }
1450 
iterate(void)1451 tcu::TestStatus ExactSamplingInstance::iterate (void)
1452 {
1453 	const auto&	vkd			= m_context.getDeviceInterface();
1454 	const auto	device		= m_context.getDevice();
1455 	auto&		allocator	= m_context.getDefaultAllocator();
1456 	const auto	queue		= m_context.getUniversalQueue();
1457 	const auto	queueIndex	= m_context.getUniversalQueueFamilyIndex();
1458 
1459 	const auto	tcuFormat	= vk::mapVkFormat(m_params.format);
1460 	const auto	formatInfo	= tcu::getTextureFormatInfo(tcuFormat);
1461 	const auto	texExtent	= getTextureExtent();
1462 	const auto	texUsage	= (vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT | vk::VK_IMAGE_USAGE_SAMPLED_BIT);
1463 	const auto	fbUsage		= (vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
1464 	const auto	descType	= vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
1465 	const auto	texLayout	= vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
1466 	const bool&	unnorm		= m_params.unnormalizedCoordinates;
1467 
1468 	// Some code below depends on this.
1469 	DE_ASSERT(texExtent.depth == 1u);
1470 
1471 	const vk::VkImageCreateInfo texImgCreateInfo =
1472 	{
1473 		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType;
1474 		nullptr,									// const void*				pNext;
1475 		0u,											// VkImageCreateFlags		flags;
1476 		vk::VK_IMAGE_TYPE_2D,						// VkImageType				imageType;
1477 		m_params.format,							// VkFormat					format;
1478 		texExtent,									// VkExtent3D				extent;
1479 		1u,											// deUint32					mipLevels;
1480 		1u,											// deUint32					arrayLayers;
1481 		vk::VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples;
1482 		vk::VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling;
1483 		texUsage,									// VkImageUsageFlags		usage;
1484 		vk::VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode;
1485 		1u,											// deUint32					queueFamilyIndexCount;
1486 		&queueIndex,								// const deUint32*			pQueueFamilyIndices;
1487 		vk::VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			initialLayout;
1488 	};
1489 
1490 	const vk::VkImageCreateInfo fbImgCreateInfo =
1491 	{
1492 		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType;
1493 		nullptr,									// const void*				pNext;
1494 		0u,											// VkImageCreateFlags		flags;
1495 		vk::VK_IMAGE_TYPE_2D,						// VkImageType				imageType;
1496 		m_params.format,							// VkFormat					format;
1497 		texExtent,									// VkExtent3D				extent;
1498 		1u,											// deUint32					mipLevels;
1499 		1u,											// deUint32					arrayLayers;
1500 		vk::VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples;
1501 		vk::VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling;
1502 		fbUsage,									// VkImageUsageFlags		usage;
1503 		vk::VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode;
1504 		1u,											// deUint32					queueFamilyIndexCount;
1505 		&queueIndex,								// const deUint32*			pQueueFamilyIndices;
1506 		vk::VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			initialLayout;
1507 	};
1508 
1509 	// Create main and framebuffer images.
1510 	const vk::ImageWithMemory texImage	{vkd, device, allocator, texImgCreateInfo,	vk::MemoryRequirement::Any};
1511 	const vk::ImageWithMemory fbImage	{vkd, device, allocator, fbImgCreateInfo,	vk::MemoryRequirement::Any};
1512 
1513 	// Corresponding image views.
1514 	const auto colorSubresourceRange	= vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1515 	const auto texView					= vk::makeImageView(vkd, device, texImage.get(),	vk::VK_IMAGE_VIEW_TYPE_2D, m_params.format, colorSubresourceRange);
1516 	const auto fbView					= vk::makeImageView(vkd, device, fbImage.get(),		vk::VK_IMAGE_VIEW_TYPE_2D, m_params.format, colorSubresourceRange);
1517 
1518 	// Buffers to create the texture and verify results.
1519 	const vk::VkDeviceSize		texBufferSize		= static_cast<vk::VkDeviceSize>(static_cast<deUint32>(tcu::getPixelSize(tcuFormat)) * texExtent.width * texExtent.height * texExtent.depth);
1520 	const auto					texBufferInfo		= vk::makeBufferCreateInfo(texBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
1521 	const auto					resultsBufferInfo	= vk::makeBufferCreateInfo(texBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1522 	const vk::BufferWithMemory	texBuffer			{vkd, device, allocator, texBufferInfo, vk::MemoryRequirement::HostVisible};
1523 	const vk::BufferWithMemory	resultsBuffer		{vkd, device, allocator, resultsBufferInfo, vk::MemoryRequirement::HostVisible};
1524 
1525 	// Create texture.
1526 	const tcu::IVec2					iImgSize		{static_cast<int>(texExtent.width), static_cast<int>(texExtent.height)};
1527 	auto&								texBufferAlloc	= texBuffer.getAllocation();
1528 	auto								texBufferPtr	= reinterpret_cast<char*>(texBufferAlloc.getHostPtr()) + texBufferAlloc.getOffset();
1529 	const tcu::PixelBufferAccess		texPixels		{tcuFormat, iImgSize[0], iImgSize[1], 1, texBufferPtr};
1530 
1531 	const int W = texPixels.getWidth();
1532 	const int H = texPixels.getHeight();
1533 	const int D = texPixels.getDepth();
1534 
1535 	const float divX = static_cast<float>(W - 1);
1536 	const float divY = static_cast<float>(H - 1);
1537 
1538 	tcu::Vec4 texColor;
1539 
1540 	for (int x = 0; x < W; ++x)
1541 	for (int y = 0; y < H; ++y)
1542 	for (int z = 0; z < D; ++z)
1543 	{
1544 		if (m_params.solidColor)
1545 		{
1546 			// Texture with solid color for filtered sampling.
1547 			texColor = tcu::Vec4{0.5f, 0.25f, 0.7529411764705882f, 1.0f};
1548 		}
1549 		else
1550 		{
1551 			// Use a color gradient otherwise.
1552 			const float colorX = static_cast<float>(x) / divX;
1553 			const float colorY = static_cast<float>(y) / divY;
1554 			const float colorZ = std::min(colorX, colorY);
1555 
1556 			texColor = tcu::Vec4{colorX, colorY, colorZ, 1.0f};
1557 		}
1558 		const tcu::Vec4 finalColor = (texColor - formatInfo.lookupBias) / formatInfo.lookupScale;
1559 		texPixels.setPixel(finalColor, x, y, z);
1560 	}
1561 
1562 	vk::flushAlloc(vkd, device, texBufferAlloc);
1563 
1564 	float minU = 0.0f;
1565 	float maxU = 1.0f;
1566 	float minV = 0.0f;
1567 	float maxV = 1.0f;
1568 
1569 	// When testing the edges, apply a texture offset of almost half a texel, so the sample location is very close to the texel border.
1570 	if (m_params.offsetSign)
1571 	{
1572 		const float sign			= m_params.offsetSign.get(); DE_ASSERT(sign == 1.0f || sign == -1.0f);
1573 		const float offsetWidth		= 0.499f / static_cast<float>(texExtent.width);
1574 		const float offsetHeight	= 0.499f / static_cast<float>(texExtent.height);
1575 
1576 		minU += sign * offsetWidth;
1577 		maxU += sign * offsetWidth;
1578 		minV += sign * offsetHeight;
1579 		maxV += sign * offsetHeight;
1580 	}
1581 
1582 	const std::vector<ExactSamplingCase::VertexData> fullScreenQuad =
1583 	{
1584 		{{  1.f, -1.f }, { maxU, minV }, },
1585 		{{ -1.f, -1.f }, { minU, minV }, },
1586 		{{ -1.f,  1.f }, { minU, maxV }, },
1587 		{{ -1.f,  1.f }, { minU, maxV }, },
1588 		{{  1.f, -1.f }, { maxU, minV }, },
1589 		{{  1.f,  1.f }, { maxU, maxV }, },
1590 	};
1591 
1592 	// Vertex buffer.
1593 	const vk::VkDeviceSize		vertexBufferSize	= static_cast<vk::VkDeviceSize>(fullScreenQuad.size() * sizeof(decltype(fullScreenQuad)::value_type));
1594 	const auto					vertexBufferInfo	= vk::makeBufferCreateInfo(vertexBufferSize, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1595 	const vk::BufferWithMemory	vertexBuffer		{vkd, device, allocator, vertexBufferInfo, vk::MemoryRequirement::HostVisible};
1596 
1597 	// Copy data to vertex buffer.
1598 	const auto&	vertexAlloc		= vertexBuffer.getAllocation();
1599 	const auto	vertexDataPtr	= reinterpret_cast<char*>(vertexAlloc.getHostPtr()) + vertexAlloc.getOffset();
1600 	deMemcpy(vertexDataPtr, fullScreenQuad.data(), static_cast<size_t>(vertexBufferSize));
1601 	vk::flushAlloc(vkd, device, vertexAlloc);
1602 
1603 	// Descriptor set layout.
1604 	vk::DescriptorSetLayoutBuilder layoutBuilder;
1605 	layoutBuilder.addSingleBinding(descType, vk::VK_SHADER_STAGE_FRAGMENT_BIT);
1606 	const auto descriptorSetLayout = layoutBuilder.build(vkd, device);
1607 
1608 	// Descriptor pool.
1609 	vk::DescriptorPoolBuilder poolBuilder;
1610 	poolBuilder.addType(descType);
1611 	const auto descriptorPool = poolBuilder.build(vkd, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1612 
1613 	// Descriptor set.
1614 	const auto descriptorSet = vk::makeDescriptorSet(vkd, device, descriptorPool.get(), descriptorSetLayout.get());
1615 
1616 	// Texture sampler. When using a solid color, test linear filtering. Linear filtering may incur in a small precission loss, but
1617 	// it should be minimal and we should get the same color when converting back to the original format.
1618 	const auto	minMagFilter			= (m_params.solidColor ? vk::VK_FILTER_LINEAR : vk::VK_FILTER_NEAREST);
1619 	const auto	addressMode				= (unnorm ? vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE : vk::VK_SAMPLER_ADDRESS_MODE_REPEAT);
1620 	const auto	unnormalizedCoordinates	= (unnorm ? VK_TRUE : VK_FALSE);
1621 
1622 	const vk::VkSamplerCreateInfo samplerCreateInfo =
1623 	{
1624 		vk::VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,		// VkStructureType		sType;
1625 		nullptr,										// const void*			pNext;
1626 		0u,												// VkSamplerCreateFlags	flags;
1627 		minMagFilter,									// VkFilter				magFilter;
1628 		minMagFilter,									// VkFilter				minFilter;
1629 		vk::VK_SAMPLER_MIPMAP_MODE_NEAREST,				// VkSamplerMipmapMode	mipmapMode;
1630 		addressMode,									// VkSamplerAddressMode	addressModeU;
1631 		addressMode,									// VkSamplerAddressMode	addressModeV;
1632 		addressMode,									// VkSamplerAddressMode	addressModeW;
1633 		0.0f,											// float				mipLodBias;
1634 		VK_FALSE,										// VkBool32				anisotropyEnable;
1635 		1.0f,											// float				maxAnisotropy;
1636 		VK_FALSE,										// VkBool32				compareEnable;
1637 		vk::VK_COMPARE_OP_NEVER,						// VkCompareOp			compareOp;
1638 		0.0f,											// float				minLod;
1639 		0.0f,											// float				maxLod;
1640 		vk::VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,	// VkBorderColor		borderColor;
1641 		unnormalizedCoordinates,						// VkBool32				unnormalizedCoordinates;
1642 	};
1643 	const auto texSampler = vk::createSampler(vkd, device, &samplerCreateInfo);
1644 
1645 	// Update descriptor set with the descriptor.
1646 	vk::DescriptorSetUpdateBuilder updateBuilder;
1647 	const auto descriptorImageInfo = vk::makeDescriptorImageInfo(texSampler.get(), texView.get(), texLayout);
1648 	updateBuilder.writeSingle(descriptorSet.get(), vk::DescriptorSetUpdateBuilder::Location::binding(0u), descType, &descriptorImageInfo);
1649 	updateBuilder.update(vkd, device);
1650 
1651 	// Shader modules.
1652 	const auto vertexModule	= vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("vert"), 0u);
1653 	const auto fragModule	= vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("frag"), 0u);
1654 
1655 	// Render pass.
1656 	const vk::VkAttachmentDescription fbAttachment =
1657 	{
1658 		0u,												// VkAttachmentDescriptionFlags	flags;
1659 		m_params.format,								// VkFormat						format;
1660 		vk::VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits		samples;
1661 		vk::VK_ATTACHMENT_LOAD_OP_CLEAR,				// VkAttachmentLoadOp			loadOp;
1662 		vk::VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp			storeOp;
1663 		vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp			stencilLoadOp;
1664 		vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp			stencilStoreOp;
1665 		vk::VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout				initialLayout;
1666 		vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout				finalLayout;
1667 	};
1668 
1669 	const vk::VkAttachmentReference colorRef =
1670 	{
1671 		0u,												// deUint32			attachment;
1672 		vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout	layout;
1673 	};
1674 
1675 	const vk::VkSubpassDescription subpass =
1676 	{
1677 		0u,										// VkSubpassDescriptionFlags		flags;
1678 		vk::VK_PIPELINE_BIND_POINT_GRAPHICS,	// VkPipelineBindPoint				pipelineBindPoint;
1679 		0u,										// deUint32							inputAttachmentCount;
1680 		nullptr,								// const VkAttachmentReference*		pInputAttachments;
1681 		1u,										// deUint32							colorAttachmentCount;
1682 		&colorRef,								// const VkAttachmentReference*		pColorAttachments;
1683 		0u,										// const VkAttachmentReference*		pResolveAttachments;
1684 		nullptr,								// const VkAttachmentReference*		pDepthStencilAttachment;
1685 		0u,										// deUint32							preserveAttachmentCount;
1686 		nullptr,								// const deUint32*					pPreserveAttachments;
1687 	};
1688 
1689 	const vk::VkRenderPassCreateInfo renderPassInfo =
1690 	{
1691 		vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,	// VkStructureType					sType;
1692 		nullptr,										// const void*						pNext;
1693 		0u,												// VkRenderPassCreateFlags			flags;
1694 		1u,												// deUint32							attachmentCount;
1695 		&fbAttachment,									// const VkAttachmentDescription*	pAttachments;
1696 		1u,												// deUint32							subpassCount;
1697 		&subpass,										// const VkSubpassDescription*		pSubpasses;
1698 		0u,												// deUint32							dependencyCount;
1699 		nullptr,										// const VkSubpassDependency*		pDependencies;
1700 	};
1701 	const auto renderPass = vk::createRenderPass(vkd, device, &renderPassInfo);
1702 
1703 	// Framebuffer.
1704 	std::vector<vk::VkImageView> attachments;
1705 	attachments.push_back(fbView.get());
1706 	const auto framebuffer = vk::makeFramebuffer(vkd, device, renderPass.get(), 1u, &fbView.get(), texExtent.width, texExtent.height, texExtent.depth);
1707 
1708 	// Push constant range.
1709 	const vk::VkPushConstantRange pcRange =
1710 	{
1711 		vk::VK_SHADER_STAGE_VERTEX_BIT,										// VkShaderStageFlags	stageFlags;
1712 		0u,																	// deUint32				offset;
1713 		static_cast<deUint32>(sizeof(ExactSamplingCase::PushConstants)),	// deUint32				size;
1714 	};
1715 
1716 	// Pipeline layout.
1717 	const vk::VkPipelineLayoutCreateInfo pipelineLayoutInfo =
1718 	{
1719 		vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,	// VkStructureType					sType;
1720 		nullptr,											// const void*						pNext;
1721 		0u,													// VkPipelineLayoutCreateFlags		flags;
1722 		1u,													// deUint32							setLayoutCount;
1723 		&descriptorSetLayout.get(),							// const VkDescriptorSetLayout*		pSetLayouts;
1724 		1u,													// deUint32							pushConstantRangeCount;
1725 		&pcRange,											// const VkPushConstantRange*		pPushConstantRanges;
1726 	};
1727 	const auto pipelineLayout = vk::createPipelineLayout(vkd, device, &pipelineLayoutInfo);
1728 
1729 	// Graphics pipeline.
1730 	const std::vector<vk::VkViewport>	viewports	{ vk::makeViewport(texExtent) };
1731 	const vk::VkRect2D					renderArea	= vk::makeRect2D(texExtent);
1732 	const std::vector<vk::VkRect2D>		scissors	{ renderArea };
1733 
1734 	const auto vtxBindingDescription	= ExactSamplingCase::VertexData::getBindingDescription();
1735 	const auto vtxAttributeDescriptions	= ExactSamplingCase::VertexData::getAttributeDescriptions();
1736 
1737 	const vk::VkPipelineVertexInputStateCreateInfo vertexInputInfo =
1738 	{
1739 		vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType                             sType
1740 		nullptr,														// const void*                                 pNext
1741 		0u,																// VkPipelineVertexInputStateCreateFlags       flags
1742 		1u,																// deUint32                                    vertexBindingDescriptionCount
1743 		&vtxBindingDescription,											// const VkVertexInputBindingDescription*      pVertexBindingDescriptions
1744 		static_cast<deUint32>(vtxAttributeDescriptions.size()),			// deUint32                                    vertexAttributeDescriptionCount
1745 		vtxAttributeDescriptions.data(),								// const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions
1746 	};
1747 
1748 	GraphicsPipelineWrapper pipeline(vkd, device, m_params.pipelineConstructionType);
1749 	pipeline.setDefaultDepthStencilState()
1750 			.setDefaultRasterizationState()
1751 			.setDefaultMultisampleState()
1752 			.setDefaultColorBlendState()
1753 			.setupVertexInputState(&vertexInputInfo)
1754 			.setupPreRasterizationShaderState(viewports,
1755 							scissors,
1756 							*pipelineLayout,
1757 							*renderPass,
1758 							0u,
1759 							*vertexModule)
1760 			.setupFragmentShaderState(*pipelineLayout, *renderPass, 0u, *fragModule)
1761 			.setupFragmentOutputState(*renderPass)
1762 			.setMonolithicPipelineLayout(*pipelineLayout)
1763 			.buildPipeline();
1764 
1765 	// Command pool and command buffer.
1766 	const auto cmdPool		= vk::createCommandPool(vkd, device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueIndex);
1767 	const auto cmdBufferPtr	= vk::allocateCommandBuffer(vkd, device, cmdPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1768 	const auto cmdBuffer	= cmdBufferPtr.get();
1769 
1770 	// Draw quad.
1771 	const ExactSamplingCase::PushConstants pushConstants =
1772 	{
1773 		static_cast<float>(texExtent.width),
1774 		static_cast<float>(texExtent.height),
1775 	};
1776 
1777 	const tcu::Vec4			clearFbColor		(0.0f, 0.0f, 0.0f, 1.0f);
1778 	const vk::VkDeviceSize	vertexBufferOffset	= 0ull;
1779 
1780 	const auto vertexBufferBarrier	= vk::makeBufferMemoryBarrier(vk::VK_ACCESS_HOST_WRITE_BIT, vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, vertexBuffer.get(), 0ull, vertexBufferSize);
1781 	const auto preBufferCopyBarrier	= vk::makeBufferMemoryBarrier(vk::VK_ACCESS_HOST_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT, texBuffer.get(), 0ull, texBufferSize);
1782 	const auto preTexCopyBarrier	= vk::makeImageMemoryBarrier(0u, vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, texImage.get(), colorSubresourceRange);
1783 	const auto postTexCopyBarrier	= vk::makeImageMemoryBarrier(vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_ACCESS_SHADER_READ_BIT, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, texLayout, texImage.get(), colorSubresourceRange);
1784 	const auto texCopyRange			= vk::makeImageSubresourceLayers(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
1785 	const auto texImageCopy			= vk::makeBufferImageCopy(texExtent, texCopyRange);
1786 
1787 	vk::beginCommandBuffer(vkd, cmdBuffer);
1788 
1789 	vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0u, 0u, nullptr, 1u, &vertexBufferBarrier, 0u, nullptr);
1790 	vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 1u, &preBufferCopyBarrier, 0u, nullptr);
1791 	vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &preTexCopyBarrier);
1792 	vkd.cmdCopyBufferToImage(cmdBuffer, texBuffer.get(), texImage.get(), vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &texImageCopy);
1793 	vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &postTexCopyBarrier);
1794 
1795 	vk::beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), renderArea, clearFbColor);
1796 	vkd.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.getPipeline());
1797 	vkd.cmdBindDescriptorSets(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr);
1798 	vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1799 	vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), vk::VK_SHADER_STAGE_VERTEX_BIT, 0u, static_cast<deUint32>(sizeof(pushConstants)), &pushConstants);
1800 	vkd.cmdDraw(cmdBuffer, static_cast<deUint32>(fullScreenQuad.size()), 1u, 0u, 0u);
1801 	vk::endRenderPass(vkd, cmdBuffer);
1802 
1803 	vk::copyImageToBuffer(vkd, cmdBuffer, fbImage.get(), resultsBuffer.get(), iImgSize);
1804 
1805 	vk::endCommandBuffer(vkd, cmdBuffer);
1806 	vk::submitCommandsAndWait(vkd, device, queue, cmdBuffer);
1807 
1808 	// Check results.
1809 	const auto& resultsBufferAlloc = resultsBuffer.getAllocation();
1810 	vk::invalidateAlloc(vkd, device, resultsBufferAlloc);
1811 
1812 	const auto							resultsBufferPtr	= reinterpret_cast<const char*>(resultsBufferAlloc.getHostPtr()) + resultsBufferAlloc.getOffset();
1813 	const tcu::ConstPixelBufferAccess	resultPixels		{tcuFormat, iImgSize[0], iImgSize[1], 1, resultsBufferPtr};
1814 
1815 	const tcu::TextureFormat			diffFormat			{tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8};
1816 	const auto							diffBytes			= tcu::getPixelSize(diffFormat) * iImgSize[0] * iImgSize[1];
1817 	std::unique_ptr<deUint8[]>			diffData			{new deUint8[diffBytes]};
1818 	const tcu::PixelBufferAccess		diffImg				{diffFormat, iImgSize[0], iImgSize[1], 1, diffData.get()};
1819 
1820 	const tcu::Vec4						colorRed			{1.0f, 0.0f, 0.0f, 1.0f};
1821 	const tcu::Vec4						colorGreen			{0.0f, 1.0f, 0.0f, 1.0f};
1822 
1823 	// Clear diff image.
1824 	deMemset(diffData.get(), 0, static_cast<size_t>(diffBytes));
1825 
1826 	bool pass = true;
1827 	for (int x = 0; x < W; ++x)
1828 	for (int y = 0; y < H; ++y)
1829 	for (int z = 0; z < D; ++z)
1830 	{
1831 		const auto inPix	= texPixels.getPixel(x, y, z);
1832 		const auto outPix	= resultPixels.getPixel(x, y, z);
1833 		if (inPix == outPix)
1834 		{
1835 			diffImg.setPixel(colorGreen, x, y, z);
1836 		}
1837 		else
1838 		{
1839 			pass = false;
1840 			diffImg.setPixel(colorRed, x, y, z);
1841 		}
1842 	}
1843 
1844 	tcu::TestStatus status = tcu::TestStatus::pass("Pass");
1845 	if (!pass)
1846 	{
1847 		auto& log = m_context.getTestContext().getLog();
1848 		log << tcu::TestLog::Image("input", "Input texture", texPixels);
1849 		log << tcu::TestLog::Image("output", "Rendered image", resultPixels);
1850 		log << tcu::TestLog::Image("diff", "Mismatched pixels in red", diffImg);
1851 		status = tcu::TestStatus::fail("Pixel mismatch; please check the rendered image");
1852 	}
1853 
1854 	return status;
1855 }
1856 
1857 } // anonymous
1858 
createAllFormatsSamplerTests(tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType, bool separateStencilUsage = false)1859 tcu::TestCaseGroup* createAllFormatsSamplerTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType, bool separateStencilUsage = false)
1860 {
1861 	const struct
1862 	{
1863 		SamplerViewType		type;
1864 		const char*			name;
1865 	}
1866 	imageViewTypes[] =
1867 	{
1868 		{ VK_IMAGE_VIEW_TYPE_1D,			"1d" },
1869 		{ { VK_IMAGE_VIEW_TYPE_1D, false },	"1d_unnormalized" },
1870 		{ VK_IMAGE_VIEW_TYPE_1D_ARRAY,		"1d_array" },
1871 		{ VK_IMAGE_VIEW_TYPE_2D,			"2d" },
1872 		{ { VK_IMAGE_VIEW_TYPE_2D, false },	"2d_unnormalized" },
1873 		{ VK_IMAGE_VIEW_TYPE_2D_ARRAY,		"2d_array" },
1874 		{ VK_IMAGE_VIEW_TYPE_3D,			"3d" },
1875 		{ VK_IMAGE_VIEW_TYPE_CUBE,			"cube" },
1876 		{ VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,	"cube_array" }
1877 	};
1878 
1879 	const VkFormat formats[] =
1880 	{
1881 		// Packed formats
1882 		VK_FORMAT_R4G4_UNORM_PACK8,
1883 		VK_FORMAT_R4G4B4A4_UNORM_PACK16,
1884 		VK_FORMAT_R5G6B5_UNORM_PACK16,
1885 		VK_FORMAT_R5G5B5A1_UNORM_PACK16,
1886 		VK_FORMAT_A2B10G10R10_UNORM_PACK32,
1887 		VK_FORMAT_A2R10G10B10_UINT_PACK32,
1888 		VK_FORMAT_B10G11R11_UFLOAT_PACK32,
1889 		VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
1890 		VK_FORMAT_B4G4R4A4_UNORM_PACK16,
1891 		VK_FORMAT_B5G5R5A1_UNORM_PACK16,
1892 		VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT,
1893 		VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT,
1894 
1895 		// Pairwise combinations of 8-bit channel formats, UNORM/SNORM/SINT/UINT/SRGB type x 1-to-4 channels x RGBA/BGRA order
1896 		VK_FORMAT_R8_SRGB,
1897 		VK_FORMAT_R8G8B8_UINT,
1898 		VK_FORMAT_B8G8R8A8_SINT,
1899 		VK_FORMAT_R8G8_UNORM,
1900 		VK_FORMAT_B8G8R8_SNORM,
1901 		VK_FORMAT_R8G8B8A8_SNORM,
1902 		VK_FORMAT_R8G8_UINT,
1903 		VK_FORMAT_R8_SINT,
1904 		VK_FORMAT_R8G8B8A8_SRGB,
1905 		VK_FORMAT_R8G8B8A8_UNORM,
1906 		VK_FORMAT_B8G8R8A8_UNORM,
1907 		VK_FORMAT_B8G8R8_SRGB,
1908 		VK_FORMAT_R8G8_SRGB,
1909 		VK_FORMAT_R8_UINT,
1910 		VK_FORMAT_R8G8B8A8_UINT,
1911 		VK_FORMAT_R8G8_SINT,
1912 		VK_FORMAT_R8_SNORM,
1913 		VK_FORMAT_B8G8R8_SINT,
1914 		VK_FORMAT_R8G8_SNORM,
1915 		VK_FORMAT_B8G8R8_UNORM,
1916 		VK_FORMAT_R8_UNORM,
1917 
1918 		// Pairwise combinations of 16/32-bit channel formats x SINT/UINT/SFLOAT type x 1-to-4 channels
1919 		VK_FORMAT_R32G32_SFLOAT,
1920 		VK_FORMAT_R32G32B32_UINT,
1921 		VK_FORMAT_R16G16B16A16_SFLOAT,
1922 		VK_FORMAT_R16G16_UINT,
1923 		VK_FORMAT_R32G32B32A32_SINT,
1924 		VK_FORMAT_R16G16B16_SINT,
1925 		VK_FORMAT_R16_SFLOAT,
1926 		VK_FORMAT_R32_SINT,
1927 		VK_FORMAT_R32_UINT,
1928 		VK_FORMAT_R16G16B16_SFLOAT,
1929 		VK_FORMAT_R16G16_SINT,
1930 
1931 		// More 16/32-bit formats required for testing VK_EXT_sampler_filter_minmax
1932 		VK_FORMAT_R16_SNORM,
1933 		VK_FORMAT_R32_SFLOAT,
1934 
1935 		// Scaled formats
1936 		VK_FORMAT_R8G8B8A8_SSCALED,
1937 		VK_FORMAT_A2R10G10B10_USCALED_PACK32,
1938 
1939 		// Compressed formats
1940 		VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,
1941 		VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK,
1942 		VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK,
1943 		VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK,
1944 		VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK,
1945 		VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK,
1946 		VK_FORMAT_EAC_R11_UNORM_BLOCK,
1947 		VK_FORMAT_EAC_R11_SNORM_BLOCK,
1948 		VK_FORMAT_EAC_R11G11_UNORM_BLOCK,
1949 		VK_FORMAT_EAC_R11G11_SNORM_BLOCK,
1950 		VK_FORMAT_ASTC_4x4_UNORM_BLOCK,
1951 		VK_FORMAT_ASTC_5x4_SRGB_BLOCK,
1952 		VK_FORMAT_ASTC_6x5_UNORM_BLOCK,
1953 		VK_FORMAT_ASTC_6x6_SRGB_BLOCK,
1954 		VK_FORMAT_ASTC_8x6_UNORM_BLOCK,
1955 		VK_FORMAT_ASTC_8x8_SRGB_BLOCK,
1956 		VK_FORMAT_ASTC_10x6_UNORM_BLOCK,
1957 		VK_FORMAT_ASTC_10x8_SRGB_BLOCK,
1958 		VK_FORMAT_ASTC_12x10_UNORM_BLOCK,
1959 		VK_FORMAT_ASTC_12x12_SRGB_BLOCK,
1960 
1961 		// Depth formats required for testing VK_EXT_sampler_filter_minmax
1962 		VK_FORMAT_D16_UNORM,
1963 		VK_FORMAT_X8_D24_UNORM_PACK32,
1964 		VK_FORMAT_D32_SFLOAT,
1965 		VK_FORMAT_D16_UNORM_S8_UINT,
1966 		VK_FORMAT_D24_UNORM_S8_UINT,
1967 		VK_FORMAT_D32_SFLOAT_S8_UINT,
1968 	};
1969 
1970 	de::MovePtr<tcu::TestCaseGroup> viewTypeTests		(new tcu::TestCaseGroup(testCtx, "view_type", ""));
1971 
1972 	for (int viewTypeNdx = 0; viewTypeNdx < DE_LENGTH_OF_ARRAY(imageViewTypes); viewTypeNdx++)
1973 	{
1974 		const SamplerViewType			viewType		= imageViewTypes[viewTypeNdx].type;
1975 		de::MovePtr<tcu::TestCaseGroup>	viewTypeGroup	(new tcu::TestCaseGroup(testCtx, imageViewTypes[viewTypeNdx].name, (std::string("Uses a ") + imageViewTypes[viewTypeNdx].name + " view").c_str()));
1976 		de::MovePtr<tcu::TestCaseGroup>	formatTests		(new tcu::TestCaseGroup(testCtx, "format", "Tests samplable formats"));
1977 
1978 		for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
1979 		{
1980 			const VkFormat	format			= formats[formatNdx];
1981 			const bool		isCompressed	= isCompressedFormat(format);
1982 			const bool		isDepthStencil	= !isCompressed
1983 											  && tcu::hasDepthComponent(mapVkFormat(format).order) && tcu::hasStencilComponent(mapVkFormat(format).order);
1984 			if (isCompressed)
1985 			{
1986 				// Do not use compressed formats with 1D and 1D array textures.
1987 				if (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_1D_ARRAY)
1988 					break;
1989 			}
1990 
1991 			if (separateStencilUsage && !isDepthStencil)
1992 				continue;
1993 
1994 			de::MovePtr<tcu::TestCaseGroup>	formatGroup	(new tcu::TestCaseGroup(testCtx,
1995 																				getFormatCaseName(format).c_str(),
1996 																				(std::string("Samples a texture of format ") + getFormatName(format)).c_str()));
1997 
1998 			if (!isCompressed && viewType.isNormalized())
1999 			{
2000 				// Do not include minFilter tests with compressed formats.
2001 				// Randomly generated compressed textures are too noisy and will derive in false positives.
2002 				de::MovePtr<tcu::TestCaseGroup>	minFilterTests			= createSamplerMinFilterTests(testCtx, pipelineConstructionType, viewType, format, separateStencilUsage);
2003 				de::MovePtr<tcu::TestCaseGroup>	minReduceFilterTests	= createSamplerMinReduceFilterTests(testCtx, pipelineConstructionType, viewType, format, separateStencilUsage);
2004 				formatGroup->addChild(minFilterTests.release());
2005 				formatGroup->addChild(minReduceFilterTests.release());
2006 			}
2007 
2008 			de::MovePtr<tcu::TestCaseGroup>	magFilterTests = createSamplerMagFilterTests(testCtx, pipelineConstructionType, viewType, format, separateStencilUsage);
2009 			formatGroup->addChild(magFilterTests.release());
2010 
2011 			if (viewType.isNormalized())
2012 			{
2013 				de::MovePtr<tcu::TestCaseGroup> magReduceFilterTests	= createSamplerMagReduceFilterTests(testCtx, pipelineConstructionType, viewType, format, separateStencilUsage);
2014 				de::MovePtr<tcu::TestCaseGroup> mipmapTests				= createSamplerMipmapTests(testCtx, pipelineConstructionType, viewType, format, separateStencilUsage);
2015 
2016 				formatGroup->addChild(magReduceFilterTests.release());
2017 				formatGroup->addChild(mipmapTests.release());
2018 			}
2019 
2020 			if (viewType != VK_IMAGE_VIEW_TYPE_CUBE && viewType != VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
2021 			{
2022 				de::MovePtr<tcu::TestCaseGroup>	addressModesTests	= createSamplerAddressModesTests(testCtx, pipelineConstructionType, viewType, format, separateStencilUsage);
2023 				formatGroup->addChild(addressModesTests.release());
2024 			}
2025 
2026 			formatTests->addChild(formatGroup.release());
2027 		}
2028 
2029 		viewTypeGroup->addChild(formatTests.release());
2030 		viewTypeTests->addChild(viewTypeGroup.release());
2031 	}
2032 
2033 	return viewTypeTests.release();
2034 }
2035 
createExactSamplingTests(tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)2036 tcu::TestCaseGroup* createExactSamplingTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
2037 {
2038 	de::MovePtr<tcu::TestCaseGroup> exactSamplingTests(new tcu::TestCaseGroup(testCtx, "exact_sampling", "Exact sampling tests"));
2039 
2040 	static const std::vector<vk::VkFormat> formats =
2041 	{
2042 		vk::VK_FORMAT_R8_SRGB,
2043 		vk::VK_FORMAT_R8G8B8_UINT,
2044 		vk::VK_FORMAT_B8G8R8A8_SINT,
2045 		vk::VK_FORMAT_R8G8_UNORM,
2046 		vk::VK_FORMAT_B8G8R8_SNORM,
2047 		vk::VK_FORMAT_R8G8B8A8_SNORM,
2048 		vk::VK_FORMAT_R8G8_UINT,
2049 		vk::VK_FORMAT_R8_SINT,
2050 		vk::VK_FORMAT_R8G8B8A8_SRGB,
2051 		vk::VK_FORMAT_R8G8B8A8_UNORM,
2052 		vk::VK_FORMAT_B8G8R8A8_UNORM,
2053 		vk::VK_FORMAT_B8G8R8_SRGB,
2054 		vk::VK_FORMAT_R8G8_SRGB,
2055 		vk::VK_FORMAT_R8_UINT,
2056 		vk::VK_FORMAT_R8G8B8A8_UINT,
2057 		vk::VK_FORMAT_R8G8_SINT,
2058 		vk::VK_FORMAT_R8_SNORM,
2059 		vk::VK_FORMAT_B8G8R8_SINT,
2060 		vk::VK_FORMAT_R8G8_SNORM,
2061 		vk::VK_FORMAT_B8G8R8_UNORM,
2062 		vk::VK_FORMAT_R8_UNORM,
2063 
2064 		vk::VK_FORMAT_R32G32_SFLOAT,
2065 		vk::VK_FORMAT_R32G32B32_UINT,
2066 		vk::VK_FORMAT_R16G16B16A16_SFLOAT,
2067 		vk::VK_FORMAT_R16G16_UINT,
2068 		vk::VK_FORMAT_R32G32B32A32_SINT,
2069 		vk::VK_FORMAT_R16G16B16_SINT,
2070 		vk::VK_FORMAT_R16_SFLOAT,
2071 		vk::VK_FORMAT_R32_SINT,
2072 		vk::VK_FORMAT_R32_UINT,
2073 		vk::VK_FORMAT_R16G16B16_SFLOAT,
2074 		vk::VK_FORMAT_R16G16_SINT,
2075 
2076 		vk::VK_FORMAT_R16_SNORM,
2077 		vk::VK_FORMAT_R32_SFLOAT,
2078 	};
2079 
2080 	static const struct
2081 	{
2082 		const bool			unnormalized;
2083 		const std::string	name;
2084 		const std::string	desc;
2085 	} unnormalizedCoordinates[] =
2086 	{
2087 		{ false,	"normalized_coords",	"Normalized coordinates"	},
2088 		{ true,		"unnormalized_coords",	"Unnormalized coordinates"	},
2089 	};
2090 
2091 	static const struct
2092 	{
2093 		const tcu::Maybe<float>	offset;
2094 		const std::string		name;
2095 		const std::string		desc;
2096 	} testEdges[] =
2097 	{
2098 		{ tcu::Nothing,				"centered",		"Sampling points centered in texel"		},
2099 		{ tcu::just<float>(-1.0f),	"edge_left",	"Sampling points near left edge"		},
2100 		{ tcu::just<float>(+1.0f),	"edge_right",	"Sampling points near right edge"		},
2101 	};
2102 
2103 	static const std::vector<std::pair<bool, std::string>> solidColor =
2104 	{
2105 		{ false,	"gradient"		},
2106 		{ true,		"solid_color"	},
2107 	};
2108 
2109 	for (const auto format : formats)
2110 	{
2111 		const std::string formatName	= getFormatCaseName(format);
2112 		const std::string description	= std::string("Exact sampling tests with image format ") + getFormatName(format);
2113 
2114 		de::MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(testCtx, formatName.c_str(), description.c_str()));
2115 
2116 		for (const auto& solid : solidColor)
2117 		{
2118 			de::MovePtr<tcu::TestCaseGroup> solidColorGroup(new tcu::TestCaseGroup(testCtx, solid.second.c_str(), ""));
2119 
2120 			for (int unIdx = 0; unIdx < DE_LENGTH_OF_ARRAY(unnormalizedCoordinates); ++unIdx)
2121 			{
2122 				const auto&						unnorm		= unnormalizedCoordinates[unIdx];
2123 				de::MovePtr<tcu::TestCaseGroup> coordGroup	(new tcu::TestCaseGroup(testCtx, unnorm.name.c_str(), unnorm.desc.c_str()));
2124 
2125 				for (int edgeIdx = 0; edgeIdx < DE_LENGTH_OF_ARRAY(testEdges); ++edgeIdx)
2126 				{
2127 					const auto&						edges	= testEdges[edgeIdx];
2128 					const ExactSamplingCase::Params	params	= { pipelineConstructionType, format, unnorm.unnormalized, solid.first, edges.offset };
2129 					coordGroup->addChild(new ExactSamplingCase{testCtx, edges.name, edges.desc, params});
2130 				}
2131 
2132 				solidColorGroup->addChild(coordGroup.release());
2133 			}
2134 
2135 			formatGroup->addChild(solidColorGroup.release());
2136 		}
2137 
2138 		exactSamplingTests->addChild(formatGroup.release());
2139 	}
2140 
2141 	return exactSamplingTests.release();
2142 }
2143 
createSamplerTests(tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)2144 tcu::TestCaseGroup* createSamplerTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
2145 {
2146 	de::MovePtr<tcu::TestCaseGroup> samplerTests(new tcu::TestCaseGroup(testCtx, "sampler", "Sampler tests"));
2147 	{
2148 		samplerTests->addChild(createAllFormatsSamplerTests(testCtx, pipelineConstructionType));
2149 		samplerTests->addChild(createExactSamplingTests(testCtx, pipelineConstructionType));
2150 	}
2151 
2152 	// tests for VK_EXT_separate_stencil_usage
2153 	de::MovePtr<tcu::TestCaseGroup> separateStencilUsageSamplerTests (new tcu::TestCaseGroup(testCtx, "separate_stencil_usage", "testing VK_EXT_separate_stencil_uasge"));
2154 	{
2155 		separateStencilUsageSamplerTests->addChild(createAllFormatsSamplerTests(testCtx, pipelineConstructionType, true));
2156 		samplerTests->addChild(separateStencilUsageSamplerTests.release());
2157 	}
2158 
2159 #ifndef CTS_USES_VULKANSC
2160 	// Border color swizzle tests.
2161 	samplerTests->addChild(createSamplerBorderSwizzleTests(testCtx, pipelineConstructionType));
2162 #endif // CTS_USES_VULKANSC
2163 
2164 	return samplerTests.release();
2165 }
2166 
2167 } // pipeline
2168 } // vkt
2169