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