• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2017 Google Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief OpImageQuery & YCbCr Tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktYCbCrImageQueryTests.hpp"
25 #include "vktTestCaseUtil.hpp"
26 #include "vktTestGroupUtil.hpp"
27 #include "vktShaderExecutor.hpp"
28 #include "vktYCbCrUtil.hpp"
29 #include "vktDrawUtil.hpp"
30 
31 #include "vkStrUtil.hpp"
32 #include "vkRef.hpp"
33 #include "vkRefUtil.hpp"
34 #include "vkTypeUtil.hpp"
35 #include "vkQueryUtil.hpp"
36 #include "vkMemUtil.hpp"
37 #include "vkImageUtil.hpp"
38 
39 #include "tcuTestLog.hpp"
40 #include "tcuVectorUtil.hpp"
41 #include "tcuTexLookupVerifier.hpp"
42 
43 #include "deStringUtil.hpp"
44 #include "deSharedPtr.hpp"
45 #include "deUniquePtr.hpp"
46 #include "deRandom.hpp"
47 #include "deSTLUtil.hpp"
48 
49 namespace vkt
50 {
51 namespace ycbcr
52 {
53 namespace
54 {
55 
56 using namespace vk;
57 using namespace shaderexecutor;
58 
59 using tcu::UVec2;
60 using tcu::Vec2;
61 using tcu::Vec4;
62 using tcu::TestLog;
63 using de::MovePtr;
64 using de::UniquePtr;
65 using std::vector;
66 using std::string;
67 
68 typedef de::SharedPtr<Allocation>				AllocationSp;
69 typedef de::SharedPtr<vk::Unique<VkBuffer> >	VkBufferSp;
70 
71 enum QueryType
72 {
73 	QUERY_TYPE_IMAGE_SIZE_LOD,			// OpImageQuerySizeLod
74 	QUERY_TYPE_IMAGE_LOD,				// OpImageQueryLod
75 	QUERY_TYPE_IMAGE_LEVELS,			// OpImageQueryLevels
76 
77 	QUERY_TYPE_LAST
78 };
79 
80 struct TestParameters
81 {
82 	QueryType			query;
83 	VkFormat			format;
84 	VkImageCreateFlags	flags;
85 	glu::ShaderType		shaderType;
86 
TestParametersvkt::ycbcr::__anon37eb4e340111::TestParameters87 	TestParameters (QueryType query_, VkFormat format_, VkImageCreateFlags flags_, glu::ShaderType shaderType_)
88 		: query		(query_)
89 		, format	(format_)
90 		, flags		(flags_)
91 		, shaderType(shaderType_)
92 	{
93 	}
94 
TestParametersvkt::ycbcr::__anon37eb4e340111::TestParameters95 	TestParameters (void)
96 		: query		(QUERY_TYPE_LAST)
97 		, format	(VK_FORMAT_UNDEFINED)
98 		, flags		(0u)
99 		, shaderType(glu::SHADERTYPE_LAST)
100 	{
101 	}
102 };
103 
getShaderSpec(const TestParameters & params)104 ShaderSpec getShaderSpec (const TestParameters& params)
105 {
106 	ShaderSpec		spec;
107 	const char*		expr		= DE_NULL;
108 	glu::DataType	resultType	= glu::TYPE_LAST;
109 
110 	switch (params.query)
111 	{
112 		case QUERY_TYPE_IMAGE_SIZE_LOD:
113 			expr		= "textureSize(u_image, lod)";
114 			resultType	= glu::TYPE_INT_VEC2;
115 			break;
116 
117 		case QUERY_TYPE_IMAGE_LEVELS:
118 			expr		= "textureQueryLevels(u_image)";
119 			resultType	= glu::TYPE_INT;
120 			break;
121 
122 		default:
123 			DE_FATAL("Unknown query");
124 	}
125 
126 	spec.glslVersion = glu::GLSL_VERSION_450;
127 
128 	spec.inputs.push_back(Symbol("lod", glu::VarType(glu::TYPE_INT, glu::PRECISION_HIGHP)));
129 	spec.outputs.push_back(Symbol("result", glu::VarType(resultType, glu::PRECISION_HIGHP)));
130 
131 	spec.globalDeclarations =
132 		"layout(binding = 0, set = 1) uniform highp sampler2D u_image;\n";
133 
134 	spec.source =
135 		string("result = ") + expr + ";\n";
136 
137 	return spec;
138 }
139 
createTestImage(const DeviceInterface & vkd,VkDevice device,VkFormat format,const UVec2 & size,VkImageCreateFlags createFlags)140 Move<VkImage> createTestImage (const DeviceInterface&	vkd,
141 							   VkDevice					device,
142 							   VkFormat					format,
143 							   const UVec2&				size,
144 							   VkImageCreateFlags		createFlags)
145 {
146 	const VkImageCreateInfo		createInfo	=
147 	{
148 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
149 		DE_NULL,
150 		createFlags,
151 		VK_IMAGE_TYPE_2D,
152 		format,
153 		makeExtent3D(size.x(), size.y(), 1u),
154 		1u,		// mipLevels
155 		1u,		// arrayLayers
156 		VK_SAMPLE_COUNT_1_BIT,
157 		VK_IMAGE_TILING_OPTIMAL,
158 		VK_IMAGE_USAGE_TRANSFER_DST_BIT|VK_IMAGE_USAGE_SAMPLED_BIT,
159 		VK_SHARING_MODE_EXCLUSIVE,
160 		0u,
161 		(const deUint32*)DE_NULL,
162 		VK_IMAGE_LAYOUT_UNDEFINED,
163 	};
164 
165 	return createImage(vkd, device, &createInfo);
166 }
167 
createImageView(const DeviceInterface & vkd,VkDevice device,VkImage image,VkFormat format)168 Move<VkImageView> createImageView (const DeviceInterface&	vkd,
169 								   VkDevice					device,
170 								   VkImage					image,
171 								   VkFormat					format)
172 {
173 	const VkImageViewCreateInfo	viewInfo	=
174 	{
175 		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
176 		DE_NULL,
177 		(VkImageViewCreateFlags)0,
178 		image,
179 		VK_IMAGE_VIEW_TYPE_2D,
180 		format,
181 		{
182 			VK_COMPONENT_SWIZZLE_IDENTITY,
183 			VK_COMPONENT_SWIZZLE_IDENTITY,
184 			VK_COMPONENT_SWIZZLE_IDENTITY,
185 			VK_COMPONENT_SWIZZLE_IDENTITY,
186 		},
187 		{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },
188 	};
189 
190 	return createImageView(vkd, device, &viewInfo);
191 }
192 
193 class TestImage
194 {
195 public:
196 								TestImage		(const DeviceInterface&		vkd,
197 												 VkDevice					device,
198 												 Allocator&					allocator,
199 												 VkFormat					format,
200 												 const UVec2&				size,
201 												 const VkImageCreateFlags	createFlags);
202 
getSize(void) const203 	const UVec2&				getSize			(void) const { return m_size;		}
getImageView(void) const204 	VkImageView					getImageView	(void) const { return *m_imageView; }
205 
206 private:
207 	const UVec2					m_size;
208 	const Unique<VkImage>		m_image;
209 	const vector<AllocationSp>	m_allocations;
210 	const Unique<VkImageView>	m_imageView;
211 };
212 
TestImage(const DeviceInterface & vkd,VkDevice device,Allocator & allocator,VkFormat format,const UVec2 & size,const VkImageCreateFlags createFlags)213 TestImage::TestImage (const DeviceInterface&	vkd,
214 					  VkDevice					device,
215 					  Allocator&				allocator,
216 					  VkFormat					format,
217 					  const UVec2&				size,
218 					  const VkImageCreateFlags	createFlags)
219 	: m_size		(size)
220 	, m_image		(createTestImage(vkd, device, format, size, createFlags))
221 	, m_allocations	(allocateAndBindImageMemory(vkd, device, allocator, *m_image, format, createFlags))
222 	, m_imageView	(createImageView(vkd, device, *m_image, format))
223 {
224 }
225 
226 typedef de::SharedPtr<TestImage> TestImageSp;
227 
createDescriptorSetLayout(const DeviceInterface & vkd,VkDevice device,VkSampler sampler)228 Move<VkDescriptorSetLayout> createDescriptorSetLayout (const DeviceInterface& vkd, VkDevice device, VkSampler sampler)
229 {
230 	const VkDescriptorSetLayoutBinding		binding		=
231 	{
232 		0u,												// binding
233 		VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
234 		1u,												// descriptorCount
235 		VK_SHADER_STAGE_ALL,
236 		&sampler
237 	};
238 	const VkDescriptorSetLayoutCreateInfo	layoutInfo	=
239 	{
240 		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
241 		DE_NULL,
242 		(VkDescriptorSetLayoutCreateFlags)0u,
243 		1u,
244 		&binding,
245 	};
246 
247 	return createDescriptorSetLayout(vkd, device, &layoutInfo);
248 }
249 
createDescriptorPool(const DeviceInterface & vkd,VkDevice device)250 Move<VkDescriptorPool> createDescriptorPool (const DeviceInterface& vkd, VkDevice device)
251 {
252 	const VkDescriptorPoolSize			poolSizes[]	=
253 	{
254 		{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,	1u	},
255 	};
256 	const VkDescriptorPoolCreateInfo	poolInfo	=
257 	{
258 		VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
259 		DE_NULL,
260 		(VkDescriptorPoolCreateFlags)VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
261 		1u,		// maxSets
262 		DE_LENGTH_OF_ARRAY(poolSizes),
263 		poolSizes,
264 	};
265 
266 	return createDescriptorPool(vkd, device, & poolInfo);
267 }
268 
createDescriptorSet(const DeviceInterface & vkd,VkDevice device,VkDescriptorPool descPool,VkDescriptorSetLayout descLayout)269 Move<VkDescriptorSet> createDescriptorSet (const DeviceInterface&	vkd,
270 										   VkDevice					device,
271 										   VkDescriptorPool			descPool,
272 										   VkDescriptorSetLayout	descLayout)
273 {
274 	const VkDescriptorSetAllocateInfo	allocInfo	=
275 	{
276 		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
277 		DE_NULL,
278 		descPool,
279 		1u,
280 		&descLayout,
281 	};
282 
283 	return allocateDescriptorSet(vkd, device, &allocInfo);
284 }
285 
bindImage(const DeviceInterface & vkd,VkDevice device,VkDescriptorSet descriptorSet,VkImageView imageView,VkSampler sampler)286 void bindImage (const DeviceInterface& vkd,
287 				VkDevice device,
288 				VkDescriptorSet descriptorSet,
289 				VkImageView imageView,
290 				VkSampler sampler)
291 {
292 	const VkDescriptorImageInfo		imageInfo			=
293 	{
294 		sampler,
295 		imageView,
296 		VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
297 	};
298 	const VkWriteDescriptorSet		descriptorWrite		=
299 	{
300 		VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
301 		DE_NULL,
302 		descriptorSet,
303 		0u,		// dstBinding
304 		0u,		// dstArrayElement
305 		1u,		// descriptorCount
306 		VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
307 		&imageInfo,
308 		(const VkDescriptorBufferInfo*)DE_NULL,
309 		(const VkBufferView*)DE_NULL,
310 	};
311 
312 	vkd.updateDescriptorSets(device, 1u, &descriptorWrite, 0u, DE_NULL);
313 }
314 
getMaxPlaneDivisor(const PlanarFormatDescription & formatDesc)315 UVec2 getMaxPlaneDivisor (const PlanarFormatDescription& formatDesc)
316 {
317 	UVec2	maxDivisor	(1u, 1u);
318 
319 	for (deUint32 ndx = 0; ndx < formatDesc.numPlanes; ++ndx)
320 	{
321 		maxDivisor.x() = de::max<deUint32>(maxDivisor.x(), formatDesc.planes[ndx].widthDivisor);
322 		maxDivisor.y() = de::max<deUint32>(maxDivisor.y(), formatDesc.planes[ndx].heightDivisor);
323 	}
324 
325 	return maxDivisor;
326 }
327 
testImageQuery(Context & context,TestParameters params)328 tcu::TestStatus testImageQuery (Context& context, TestParameters params)
329 {
330 	const bool							isYCbCrImage	= isYCbCrFormat(params.format);
331 
332 	if (isYCbCrImage)
333 		checkImageSupport(context, params.format, params.flags);
334 
335 	const DeviceInterface&				vkd				= context.getDeviceInterface();
336 	const VkDevice						device			= context.getDevice();
337 
338 	const VkSamplerYcbcrConversionCreateInfoKHR			conversionInfo			=
339 	{
340 		VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO_KHR,
341 		DE_NULL,
342 		params.format,
343 		VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY_KHR,
344 		VK_SAMPLER_YCBCR_RANGE_ITU_FULL_KHR,
345 		{
346 			VK_COMPONENT_SWIZZLE_IDENTITY,
347 			VK_COMPONENT_SWIZZLE_IDENTITY,
348 			VK_COMPONENT_SWIZZLE_IDENTITY,
349 			VK_COMPONENT_SWIZZLE_IDENTITY,
350 		},
351 		VK_CHROMA_LOCATION_MIDPOINT_KHR,
352 		VK_CHROMA_LOCATION_MIDPOINT_KHR,
353 		VK_FILTER_NEAREST,
354 		VK_FALSE,									// forceExplicitReconstruction
355 	};
356 	const Unique<VkSamplerYcbcrConversionKHR>			conversion				(isYCbCrImage
357 																				 ? createSamplerYcbcrConversionKHR(vkd, device, &conversionInfo)
358 																				 : Move<VkSamplerYcbcrConversionKHR>());
359 
360 	const VkSamplerYcbcrConversionInfoKHR				samplerConversionInfo	=
361 	{
362 		VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO_KHR,
363 		DE_NULL,
364 		*conversion,
365 	};
366 
367 	const VkSamplerCreateInfo							samplerInfo				=
368 	{
369 		VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
370 		isYCbCrImage ? &samplerConversionInfo : DE_NULL,
371 		0u,
372 		VK_FILTER_NEAREST,							// magFilter
373 		VK_FILTER_NEAREST,							// minFilter
374 		VK_SAMPLER_MIPMAP_MODE_NEAREST,				// mipmapMode
375 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// addressModeU
376 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// addressModeV
377 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// addressModeW
378 		0.0f,										// mipLodBias
379 		VK_FALSE,									// anisotropyEnable
380 		1.0f,										// maxAnisotropy
381 		VK_FALSE,									// compareEnable
382 		VK_COMPARE_OP_ALWAYS,						// compareOp
383 		0.0f,										// minLod
384 		0.0f,										// maxLod
385 		VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,	// borderColor
386 		VK_FALSE,									// unnormalizedCoords
387 	};
388 
389 	const Unique<VkSampler>				sampler		(createSampler(vkd, device, &samplerInfo));
390 	const Unique<VkDescriptorSetLayout>	descLayout	(createDescriptorSetLayout(vkd, device, *sampler));
391 	const Unique<VkDescriptorPool>		descPool	(createDescriptorPool(vkd, device));
392 	const Unique<VkDescriptorSet>		descSet		(createDescriptorSet(vkd, device, *descPool, *descLayout));
393 
394 	vector<TestImageSp>					testImages;
395 
396 	if (params.query == QUERY_TYPE_IMAGE_SIZE_LOD)
397 	{
398 		const PlanarFormatDescription&		formatDesc	= getPlanarFormatDescription(params.format);
399 		const UVec2							maxDivisor	= getMaxPlaneDivisor(formatDesc);
400 		vector<UVec2>						testSizes;
401 
402 		testSizes.push_back(maxDivisor);
403 		testSizes.push_back(maxDivisor * UVec2(2u, 1u));
404 		testSizes.push_back(maxDivisor * UVec2(1u, 2u));
405 		testSizes.push_back(maxDivisor * UVec2(63u, 79u));
406 		testSizes.push_back(maxDivisor * UVec2(99u, 1u));
407 		testSizes.push_back(maxDivisor * UVec2(421u, 1117u));
408 
409 		testImages.resize(testSizes.size());
410 
411 		for (size_t ndx = 0; ndx < testSizes.size(); ++ndx)
412 			testImages[ndx] = TestImageSp(new TestImage(vkd, device, context.getDefaultAllocator(), params.format, testSizes[ndx], params.flags));
413 	}
414 	else
415 		testImages.push_back(TestImageSp(new TestImage(vkd, device, context.getDefaultAllocator(), params.format, UVec2(16, 18), params.flags)));
416 
417 	{
418 		UniquePtr<ShaderExecutor>	executor	(createExecutor(context, params.shaderType, getShaderSpec(params), *descLayout));
419 		bool						allOk		= true;
420 
421 		for (size_t imageNdx = 0; imageNdx < testImages.size(); ++imageNdx)
422 		{
423 			const deUint32	lod			= 0u;
424 			UVec2			result		(~0u, ~0u);
425 			const void*		inputs[]	= { &lod };
426 			void*			outputs[]	= { result.getPtr() };
427 
428 			bindImage(vkd, device, *descSet, testImages[imageNdx]->getImageView(), *sampler);
429 
430 			executor->execute(1, inputs, outputs, *descSet);
431 
432 			switch (params.query)
433 			{
434 				case QUERY_TYPE_IMAGE_SIZE_LOD:
435 				{
436 					const UVec2	reference	= testImages[imageNdx]->getSize();
437 
438 					if (result != reference)
439 					{
440 						context.getTestContext().getLog()
441 							<< TestLog::Message << "ERROR: Image " << imageNdx
442 												<< ": got " << result
443 												<< ", expected " << reference
444 							<< TestLog::EndMessage;
445 						allOk = false;
446 					}
447 					break;
448 				}
449 
450 				case QUERY_TYPE_IMAGE_LEVELS:
451 				{
452 					if (result.x() != 1u)
453 					{
454 						context.getTestContext().getLog()
455 							<< TestLog::Message << "ERROR: Image " << imageNdx
456 												<< ": got " << result.x()
457 												<< ", expected " << 1
458 							<< TestLog::EndMessage;
459 						allOk = false;
460 					}
461 					break;
462 				}
463 
464 				default:
465 					DE_FATAL("Invalid query type");
466 			}
467 		}
468 
469 		if (allOk)
470 			return tcu::TestStatus::pass("Queries passed");
471 		else
472 			return tcu::TestStatus::fail("Got invalid results");
473 	}
474 }
475 
testImageQueryLod(Context & context,TestParameters params)476 tcu::TestStatus testImageQueryLod (Context& context, TestParameters params)
477 {
478 	const bool							isYCbCrImage	= isYCbCrFormat(params.format);
479 
480 	if (isYCbCrImage)
481 		checkImageSupport(context, params.format, params.flags);
482 
483 	const DeviceInterface&				vkd				= context.getDeviceInterface();
484 	const VkDevice						device			= context.getDevice();
485 
486 	const VkSamplerYcbcrConversionCreateInfoKHR			conversionInfo			=
487 	{
488 		VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO_KHR,
489 		DE_NULL,
490 		params.format,
491 		VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY_KHR,
492 		VK_SAMPLER_YCBCR_RANGE_ITU_FULL_KHR,
493 		{
494 			VK_COMPONENT_SWIZZLE_IDENTITY,
495 			VK_COMPONENT_SWIZZLE_IDENTITY,
496 			VK_COMPONENT_SWIZZLE_IDENTITY,
497 			VK_COMPONENT_SWIZZLE_IDENTITY,
498 		},
499 		VK_CHROMA_LOCATION_MIDPOINT_KHR,
500 		VK_CHROMA_LOCATION_MIDPOINT_KHR,
501 		VK_FILTER_NEAREST,
502 		VK_FALSE,									// forceExplicitReconstruction
503 	};
504 	const Unique<VkSamplerYcbcrConversionKHR>			conversion				(isYCbCrImage
505 																				 ? createSamplerYcbcrConversionKHR(vkd, device, &conversionInfo)
506 																				 : Move<VkSamplerYcbcrConversionKHR>());
507 
508 	const VkSamplerYcbcrConversionInfoKHR				samplerConversionInfo	=
509 	{
510 		VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO_KHR,
511 		DE_NULL,
512 		*conversion,
513 	};
514 
515 	const VkSamplerCreateInfo							samplerInfo				=
516 	{
517 		VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
518 		isYCbCrImage ? &samplerConversionInfo : DE_NULL,
519 		0u,
520 		VK_FILTER_NEAREST,							// magFilter
521 		VK_FILTER_NEAREST,							// minFilter
522 		VK_SAMPLER_MIPMAP_MODE_NEAREST,				// mipmapMode
523 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// addressModeU
524 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// addressModeV
525 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// addressModeW
526 		0.0f,										// mipLodBias
527 		VK_FALSE,									// anisotropyEnable
528 		1.0f,										// maxAnisotropy
529 		VK_FALSE,									// compareEnable
530 		VK_COMPARE_OP_ALWAYS,						// compareOp
531 		0.0f,										// minLod
532 		0.0f,										// maxLod
533 		VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,	// borderColor
534 		VK_FALSE,									// unnormalizedCoords
535 	};
536 
537 	const Unique<VkSampler>				sampler		(createSampler(vkd, device, &samplerInfo));
538 	const Unique<VkDescriptorSetLayout>	descLayout	(createDescriptorSetLayout(vkd, device, *sampler));
539 	const Unique<VkDescriptorPool>		descPool	(createDescriptorPool(vkd, device));
540 	const Unique<VkDescriptorSet>		descSet		(createDescriptorSet(vkd, device, *descPool, *descLayout));
541 
542 	vector<TestImageSp>					testImages;
543 
544 	DE_ASSERT(params.query == QUERY_TYPE_IMAGE_LOD);
545 	DE_ASSERT(params.shaderType == glu::SHADERTYPE_FRAGMENT);
546 
547 	{
548 		const PlanarFormatDescription&		formatDesc	= getPlanarFormatDescription(params.format);
549 		const UVec2							maxDivisor	= getMaxPlaneDivisor(formatDesc);
550 		vector<UVec2>						testSizes;
551 
552 		testSizes.push_back(maxDivisor);
553 		testSizes.push_back(maxDivisor * UVec2(2u, 1u));
554 		testSizes.push_back(maxDivisor * UVec2(1u, 2u));
555 		testSizes.push_back(maxDivisor * UVec2(4u, 123u));
556 		testSizes.push_back(maxDivisor * UVec2(312u, 13u));
557 		testSizes.push_back(maxDivisor * UVec2(841u, 917u));
558 
559 		testImages.resize(testSizes.size());
560 
561 		for (size_t ndx = 0; ndx < testSizes.size(); ++ndx)
562 			testImages[ndx] = TestImageSp(new TestImage(vkd, device, context.getDefaultAllocator(), params.format, testSizes[ndx], params.flags));
563 	}
564 
565 	{
566 		using namespace drawutil;
567 
568 		struct LocalUtil
569 		{
570 			static DrawState getDrawState (UVec2 renderSize)
571 			{
572 				DrawState state(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, renderSize.x(), renderSize.y());
573 				state.colorFormat = VK_FORMAT_R32G32_SFLOAT;
574 				return state;
575 			}
576 
577 			static vector<Vec4> getVertices (void)
578 			{
579 				vector<Vec4> vertices;
580 
581 				vertices.push_back(Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
582 				vertices.push_back(Vec4(+1.0f, -1.0f, 0.0f, 1.0f));
583 				vertices.push_back(Vec4(-1.0f, +1.0f, 0.0f, 1.0f));
584 
585 				vertices.push_back(Vec4(+1.0f, -1.0f, 0.0f, 1.0f));
586 				vertices.push_back(Vec4(-1.0f, +1.0f, 0.0f, 1.0f));
587 				vertices.push_back(Vec4(+1.0f, +1.0f, 0.0f, 1.0f));
588 
589 				return vertices;
590 			}
591 
592 			static VulkanProgram getProgram (Context& ctx, VkDescriptorSetLayout descriptorLayout, VkDescriptorSet descriptorSet)
593 			{
594 				VulkanProgram	prog;
595 
596 				prog.shaders.push_back(VulkanShader(VK_SHADER_STAGE_VERTEX_BIT,		ctx.getBinaryCollection().get("vert")));
597 				prog.shaders.push_back(VulkanShader(VK_SHADER_STAGE_FRAGMENT_BIT,	ctx.getBinaryCollection().get("frag")));
598 
599 				prog.descriptorSet			= descriptorSet;
600 				prog.descriptorSetLayout	= descriptorLayout;
601 
602 				return prog;
603 			}
604 		};
605 
606 		const UVec2					renderSize	(128, 256);
607 		const vector<Vec4>			vertices	(LocalUtil::getVertices());
608 		const DrawState				drawState	(LocalUtil::getDrawState(renderSize));
609 		const DrawCallData			drawCallData(vertices);
610 		const VulkanProgram			program		(LocalUtil::getProgram(context, *descLayout, *descSet));
611 
612 		bool						allOk		= true;
613 
614 		context.getTestContext().getLog()
615 			<< TestLog::Message << "Rendering " << renderSize << " quad" << TestLog::EndMessage;
616 
617 		for (size_t imageNdx = 0; imageNdx < testImages.size(); ++imageNdx)
618 		{
619 			context.getTestContext().getLog()
620 				<< TestLog::Message << "Testing image size " << testImages[imageNdx]->getSize() << TestLog::EndMessage;
621 
622 			bindImage(vkd, device, *descSet, testImages[imageNdx]->getImageView(), *sampler);
623 
624 			VulkanDrawContext	renderer	(context, drawState, drawCallData, program);
625 			renderer.draw();
626 
627 			{
628 				// Only du/dx and dv/dy are non-zero
629 				const Vec2					dtdp		= testImages[imageNdx]->getSize().cast<float>() / renderSize.cast<float>();
630 				const tcu::LodPrecision		lodPrec		(16, 4); // Pretty lax since we are not verifying LOD precision
631 				const Vec2					lodBounds	(tcu::computeLodBoundsFromDerivates(dtdp.x(), 0.0f, 0.0f, dtdp.y(), lodPrec));
632 				tcu::ConstPixelBufferAccess	resultImg	(renderer.getColorPixels());
633 				const int					maxErrors	= 5;
634 				int							numErrors	= 0;
635 
636 				for (int y = 0; y < resultImg.getHeight(); ++y)
637 				for (int x = 0; x < resultImg.getWidth(); ++x)
638 				{
639 					const Vec2	result		= resultImg.getPixel(x, y).swizzle(0,1);
640 					const bool	levelOk		= result.x() == 0.0f;
641 					const bool	lodOk		= de::inRange(result.y(), lodBounds.x(), lodBounds.y());
642 
643 					if (!levelOk || !lodOk)
644 					{
645 						if (numErrors < maxErrors)
646 						{
647 							context.getTestContext().getLog()
648 								<< TestLog::Message << "ERROR: At (" << x << ", " << y << ")"
649 													<< ": got " << result
650 													<< ", expected (0, [" << lodBounds.x() << ", " << lodBounds.y() << "])"
651 								<< TestLog::EndMessage;
652 						}
653 						else if (numErrors == maxErrors)
654 							context.getTestContext().getLog() << TestLog::Message << "..." << TestLog::EndMessage;
655 
656 						numErrors += 1;
657 					}
658 				}
659 
660 				allOk = allOk && (numErrors  == 0);
661 			}
662 		}
663 
664 		if (allOk)
665 			return tcu::TestStatus::pass("Queries passed");
666 		else
667 			return tcu::TestStatus::fail("Got invalid results");
668 	}
669 }
670 
initImageQueryPrograms(SourceCollections & dst,TestParameters params)671 void initImageQueryPrograms (SourceCollections& dst, TestParameters params)
672 {
673 	const ShaderSpec	spec	= getShaderSpec(params);
674 
675 	generateSources(params.shaderType, spec, dst);
676 }
677 
initImageQueryLodPrograms(SourceCollections & dst,TestParameters)678 void initImageQueryLodPrograms (SourceCollections& dst, TestParameters)
679 {
680 	dst.glslSources.add("vert")
681 		<< glu::VertexSource("#version 450\n"
682 							 "layout(location = 0) in highp vec4 a_position;\n"
683 							 "layout(location = 0) out highp vec2 v_texCoord;\n"
684 							 "\n"
685 							 "void main (void)\n"
686 							 "{\n"
687 							 "	gl_Position = a_position;\n"
688 							 "	v_texCoord = a_position.xy * 0.5 - 0.5;\n"
689 							 "}\n");
690 	dst.glslSources.add("frag")
691 		<< glu::FragmentSource("#version 450\n"
692 							   "layout(binding = 0, set = 0) uniform highp sampler2D u_image;\n"
693 							   "layout(location = 0) in highp vec2 v_texCoord;\n"
694 							   "layout(location = 0) out highp vec2 o_lod;\n"
695 							   "\n"
696 							   "void main (void)\n"
697 							   "{\n"
698 							   "	o_lod = textureQueryLod(u_image, v_texCoord);\n"
699 							   "}\n");
700 }
701 
addImageQueryCase(tcu::TestCaseGroup * group,const TestParameters & params)702 void addImageQueryCase (tcu::TestCaseGroup* group, const TestParameters& params)
703 {
704 	std::string	name	= de::toLower(de::toString(params.format).substr(10));
705 	const bool	isLod	= params.query == QUERY_TYPE_IMAGE_LOD;
706 
707 	if ((params.flags & VK_IMAGE_CREATE_DISJOINT_BIT_KHR) != 0)
708 		name += "_disjoint";
709 
710 	addFunctionCaseWithPrograms(group,
711 								name,
712 								"",
713 								isLod ? initImageQueryLodPrograms : initImageQueryPrograms,
714 								isLod ? testImageQueryLod : testImageQuery,
715 								params);
716 }
717 
718 struct QueryGroupParams
719 {
720 	QueryType		query;
721 	glu::ShaderType	shaderType;
722 
QueryGroupParamsvkt::ycbcr::__anon37eb4e340111::QueryGroupParams723 	QueryGroupParams (QueryType query_, glu::ShaderType shaderType_)
724 		: query		(query_)
725 		, shaderType(shaderType_)
726 	{}
727 
QueryGroupParamsvkt::ycbcr::__anon37eb4e340111::QueryGroupParams728 	QueryGroupParams (void)
729 		: query		(QUERY_TYPE_LAST)
730 		, shaderType(glu::SHADERTYPE_LAST)
731 	{}
732 };
733 
populateQueryInShaderGroup(tcu::TestCaseGroup * group,QueryGroupParams params)734 void populateQueryInShaderGroup (tcu::TestCaseGroup* group, QueryGroupParams params)
735 {
736 	// "Reference" formats for testing
737 	addImageQueryCase(group, TestParameters(params.query, VK_FORMAT_R8G8B8A8_UNORM, 0u, params.shaderType));
738 
739 	for (int formatNdx = VK_YCBCR_FORMAT_FIRST; formatNdx < VK_YCBCR_FORMAT_LAST; formatNdx++)
740 	{
741 		const VkFormat	format	= (VkFormat)formatNdx;
742 
743 		addImageQueryCase(group, TestParameters(params.query, format, 0u, params.shaderType));
744 
745 		if (getPlaneCount(format) > 1)
746 			addImageQueryCase(group, TestParameters(params.query, format, (VkImageCreateFlags)VK_IMAGE_CREATE_DISJOINT_BIT_KHR, params.shaderType));
747 	}
748 }
749 
populateQueryGroup(tcu::TestCaseGroup * group,QueryType query)750 void populateQueryGroup (tcu::TestCaseGroup* group, QueryType query)
751 {
752 	for (int shaderTypeNdx = 0; shaderTypeNdx < glu::SHADERTYPE_LAST; ++shaderTypeNdx)
753 	{
754 		const glu::ShaderType	shaderType	= (glu::ShaderType)shaderTypeNdx;
755 
756 		if (query == QUERY_TYPE_IMAGE_LOD && shaderType != glu::SHADERTYPE_FRAGMENT)
757 			continue;
758 
759 		addTestGroup(group, glu::getShaderTypeName(shaderType), "", populateQueryInShaderGroup, QueryGroupParams(query, shaderType));
760 	}
761 }
762 
populateImageQueryGroup(tcu::TestCaseGroup * group)763 void populateImageQueryGroup (tcu::TestCaseGroup* group)
764 {
765 	addTestGroup(group, "size_lod",	"OpImageQuerySizeLod",	populateQueryGroup, QUERY_TYPE_IMAGE_SIZE_LOD);
766 	addTestGroup(group, "lod",		"OpImageQueryLod",		populateQueryGroup, QUERY_TYPE_IMAGE_LOD);
767 	addTestGroup(group, "levels",	"OpImageQueryLevels",	populateQueryGroup, QUERY_TYPE_IMAGE_LEVELS);
768 }
769 
770 } // namespace
771 
createImageQueryTests(tcu::TestContext & testCtx)772 tcu::TestCaseGroup* createImageQueryTests (tcu::TestContext& testCtx)
773 {
774 	return createTestGroup(testCtx, "query", "Image Query Tests", populateImageQueryGroup);
775 }
776 
777 } // ycbcr
778 } // vkt
779