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