• 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 YCbCr Image View Tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktYCbCrViewTests.hpp"
25 #include "vktYCbCrUtil.hpp"
26 #include "vktTestCaseUtil.hpp"
27 #include "vktTestGroupUtil.hpp"
28 #include "vktShaderExecutor.hpp"
29 
30 #include "vkStrUtil.hpp"
31 #include "vkRef.hpp"
32 #include "vkRefUtil.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkQueryUtil.hpp"
35 #include "vkMemUtil.hpp"
36 #include "vkImageUtil.hpp"
37 #include "vkCmdUtil.hpp"
38 
39 #include "tcuTestLog.hpp"
40 #include "tcuVectorUtil.hpp"
41 
42 #include "deStringUtil.hpp"
43 #include "deSharedPtr.hpp"
44 #include "deUniquePtr.hpp"
45 #include "deRandom.hpp"
46 #include "deSTLUtil.hpp"
47 
48 namespace vkt
49 {
50 namespace ycbcr
51 {
52 namespace
53 {
54 
55 using namespace vk;
56 using namespace shaderexecutor;
57 
58 using tcu::UVec2;
59 using tcu::Vec2;
60 using tcu::Vec4;
61 using tcu::TestLog;
62 using de::MovePtr;
63 using de::UniquePtr;
64 using std::vector;
65 using std::string;
66 
67 // List of some formats compatible with formats listed in "Plane Format Compatibility Table".
68 const VkFormat s_compatible_formats[] =
69 {
70 	// 8-bit compatibility class
71 	// Compatible format for VK_FORMAT_R8_UNORM
72 	VK_FORMAT_R4G4_UNORM_PACK8,
73 	VK_FORMAT_R8_UINT,
74 	VK_FORMAT_R8_SINT,
75 	// 16-bit compatibility class
76 	// Compatible formats with VK_FORMAT_R8G8_UNORM, VK_FORMAT_R10X6_UNORM_PACK16, VK_FORMAT_R12X4_UNORM_PACK16 and VK_FORMAT_R16_UNORM
77 	VK_FORMAT_R8G8_UNORM,
78 	VK_FORMAT_R8G8_UINT,
79 	VK_FORMAT_R10X6_UNORM_PACK16,
80 	VK_FORMAT_R12X4_UNORM_PACK16,
81 	VK_FORMAT_R16_UNORM,
82 	VK_FORMAT_R16_UINT,
83 	VK_FORMAT_R16_SINT,
84 	VK_FORMAT_R4G4B4A4_UNORM_PACK16,
85 	// 32-bit compatibility class
86 	// Compatible formats for VK_FORMAT_R10X6G10X6_UNORM_2PACK16, VK_FORMAT_R12X4G12X4_UNORM_2PACK16 and VK_FORMAT_R16G16_UNORM
87 	VK_FORMAT_R10X6G10X6_UNORM_2PACK16,
88 	VK_FORMAT_R12X4G12X4_UNORM_2PACK16,
89 	VK_FORMAT_R16G16_UNORM,
90 	VK_FORMAT_R8G8B8A8_UNORM,
91 	VK_FORMAT_R8G8B8A8_UINT,
92 	VK_FORMAT_R32_UINT,
93 };
94 
formatsAreCompatible(const VkFormat format0,const VkFormat format1)95 inline bool formatsAreCompatible (const VkFormat format0, const VkFormat format1)
96 {
97 	return format0 == format1 || mapVkFormat(format0).getPixelSize() == mapVkFormat(format1).getPixelSize();
98 }
99 
createTestImage(const DeviceInterface & vkd,VkDevice device,VkFormat format,const UVec2 & size,VkImageCreateFlags createFlags)100 Move<VkImage> createTestImage (const DeviceInterface&	vkd,
101 							   VkDevice					device,
102 							   VkFormat					format,
103 							   const UVec2&				size,
104 							   VkImageCreateFlags		createFlags)
105 {
106 	const VkImageCreateInfo		createInfo	=
107 	{
108 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
109 		DE_NULL,
110 		createFlags,
111 		VK_IMAGE_TYPE_2D,
112 		format,
113 		makeExtent3D(size.x(), size.y(), 1u),
114 		1u,		// mipLevels
115 		1u,		// arrayLayers
116 		VK_SAMPLE_COUNT_1_BIT,
117 		VK_IMAGE_TILING_OPTIMAL,
118 		VK_IMAGE_USAGE_SAMPLED_BIT|VK_IMAGE_USAGE_TRANSFER_DST_BIT,
119 		VK_SHARING_MODE_EXCLUSIVE,
120 		0u,
121 		(const deUint32*)DE_NULL,
122 		VK_IMAGE_LAYOUT_UNDEFINED,
123 	};
124 
125 	return createImage(vkd, device, &createInfo);
126 }
127 
createImageView(const DeviceInterface & vkd,VkDevice device,VkImage image,VkFormat format,VkImageAspectFlagBits imageAspect,const VkSamplerYcbcrConversionInfo * samplerConversionInfo)128 Move<VkImageView> createImageView (const DeviceInterface&				vkd,
129 								   VkDevice								device,
130 								   VkImage								image,
131 								   VkFormat								format,
132 								   VkImageAspectFlagBits				imageAspect,
133 								   const VkSamplerYcbcrConversionInfo*	samplerConversionInfo)
134 {
135 	const VkImageViewCreateInfo				viewInfo	=
136 	{
137 		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
138 		samplerConversionInfo,
139 		(VkImageViewCreateFlags)0,
140 		image,
141 		VK_IMAGE_VIEW_TYPE_2D,
142 		format,
143 		{
144 			VK_COMPONENT_SWIZZLE_IDENTITY,
145 			VK_COMPONENT_SWIZZLE_IDENTITY,
146 			VK_COMPONENT_SWIZZLE_IDENTITY,
147 			VK_COMPONENT_SWIZZLE_IDENTITY,
148 		},
149 		{ (VkImageAspectFlags)imageAspect, 0u, 1u, 0u, 1u },
150 	};
151 
152 	return createImageView(vkd, device, &viewInfo);
153 }
154 
155 // Descriptor layout for set 1:
156 // 0: Plane view bound as COMBINED_IMAGE_SAMPLER
157 // 1: "Whole" image bound as COMBINED_IMAGE_SAMPLER
158 //    + immutable sampler (required for color conversion)
159 
createDescriptorSetLayout(const DeviceInterface & vkd,VkDevice device,VkSampler conversionSampler)160 Move<VkDescriptorSetLayout> createDescriptorSetLayout (const DeviceInterface& vkd, VkDevice device, VkSampler conversionSampler)
161 {
162 	const VkDescriptorSetLayoutBinding		bindings[]	=
163 	{
164 		{
165 			0u,												// binding
166 			VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
167 			1u,												// descriptorCount
168 			VK_SHADER_STAGE_ALL,
169 			(const VkSampler*)DE_NULL
170 		},
171 		{
172 			1u,												// binding
173 			VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
174 			1u,												// descriptorCount
175 			VK_SHADER_STAGE_ALL,
176 			&conversionSampler
177 		}
178 	};
179 	const VkDescriptorSetLayoutCreateInfo	layoutInfo	=
180 	{
181 		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
182 		DE_NULL,
183 		(VkDescriptorSetLayoutCreateFlags)0u,
184 		DE_LENGTH_OF_ARRAY(bindings),
185 		bindings,
186 	};
187 
188 	return createDescriptorSetLayout(vkd, device, &layoutInfo);
189 }
190 
createDescriptorPool(const DeviceInterface & vkd,VkDevice device,const deUint32 combinedSamplerDescriptorCount)191 Move<VkDescriptorPool> createDescriptorPool (const DeviceInterface& vkd, VkDevice device, const deUint32 combinedSamplerDescriptorCount)
192 {
193 	const VkDescriptorPoolSize			poolSizes[]	=
194 	{
195 		{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,	2u * combinedSamplerDescriptorCount	},
196 	};
197 	const VkDescriptorPoolCreateInfo	poolInfo	=
198 	{
199 		VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
200 		DE_NULL,
201 		(VkDescriptorPoolCreateFlags)VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
202 		1u,		// maxSets
203 		DE_LENGTH_OF_ARRAY(poolSizes),
204 		poolSizes,
205 	};
206 
207 	return createDescriptorPool(vkd, device, & poolInfo);
208 }
209 
createDescriptorSet(const DeviceInterface & vkd,VkDevice device,VkDescriptorPool descPool,VkDescriptorSetLayout descLayout,VkImageView planeView,VkSampler planeViewSampler,VkImageView wholeView,VkSampler wholeViewSampler)210 Move<VkDescriptorSet> createDescriptorSet (const DeviceInterface&	vkd,
211 										   VkDevice					device,
212 										   VkDescriptorPool			descPool,
213 										   VkDescriptorSetLayout	descLayout,
214 										   VkImageView				planeView,
215 										   VkSampler				planeViewSampler,
216 										   VkImageView				wholeView,
217 										   VkSampler				wholeViewSampler)
218 {
219 	Move<VkDescriptorSet>	descSet;
220 
221 	{
222 		const VkDescriptorSetAllocateInfo	allocInfo	=
223 		{
224 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
225 			DE_NULL,
226 			descPool,
227 			1u,
228 			&descLayout,
229 		};
230 
231 		descSet = allocateDescriptorSet(vkd, device, &allocInfo);
232 	}
233 
234 	{
235 		const VkDescriptorImageInfo		imageInfo0			=
236 		{
237 			planeViewSampler,
238 			planeView,
239 			VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
240 		};
241 		const VkDescriptorImageInfo		imageInfo1			=
242 		{
243 			wholeViewSampler,
244 			wholeView,
245 			VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
246 		};
247 		const VkWriteDescriptorSet		descriptorWrites[]		=
248 		{
249 			{
250 				VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
251 				DE_NULL,
252 				*descSet,
253 				0u,		// dstBinding
254 				0u,		// dstArrayElement
255 				1u,		// descriptorCount
256 				VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
257 				&imageInfo0,
258 				(const VkDescriptorBufferInfo*)DE_NULL,
259 				(const VkBufferView*)DE_NULL,
260 			},
261 			{
262 				VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
263 				DE_NULL,
264 				*descSet,
265 				1u,		// dstBinding
266 				0u,		// dstArrayElement
267 				1u,		// descriptorCount
268 				VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
269 				&imageInfo1,
270 				(const VkDescriptorBufferInfo*)DE_NULL,
271 				(const VkBufferView*)DE_NULL,
272 			}
273 		};
274 
275 		vkd.updateDescriptorSets(device, DE_LENGTH_OF_ARRAY(descriptorWrites), descriptorWrites, 0u, DE_NULL);
276 	}
277 
278 	return descSet;
279 }
280 
executeImageBarrier(const DeviceInterface & vkd,VkDevice device,deUint32 queueFamilyNdx,VkPipelineStageFlags srcStage,VkPipelineStageFlags dstStage,const VkImageMemoryBarrier & barrier)281 void executeImageBarrier (const DeviceInterface&		vkd,
282 						  VkDevice						device,
283 						  deUint32						queueFamilyNdx,
284 						  VkPipelineStageFlags			srcStage,
285 						  VkPipelineStageFlags			dstStage,
286 						  const VkImageMemoryBarrier&	barrier)
287 {
288 	const VkQueue					queue		= getDeviceQueue(vkd, device, queueFamilyNdx, 0u);
289 	const Unique<VkCommandPool>		cmdPool		(createCommandPool(vkd, device, (VkCommandPoolCreateFlags)0, queueFamilyNdx));
290 	const Unique<VkCommandBuffer>	cmdBuffer	(allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
291 
292 	beginCommandBuffer(vkd, *cmdBuffer);
293 
294 	vkd.cmdPipelineBarrier(*cmdBuffer,
295 						   srcStage,
296 						   dstStage,
297 						   (VkDependencyFlags)0u,
298 						   0u,
299 						   (const VkMemoryBarrier*)DE_NULL,
300 						   0u,
301 						   (const VkBufferMemoryBarrier*)DE_NULL,
302 						   1u,
303 						   &barrier);
304 
305 	endCommandBuffer(vkd, *cmdBuffer);
306 
307 	submitCommandsAndWait(vkd, device, queue, *cmdBuffer);
308 }
309 
310 struct TestParameters
311 {
312 	enum ViewType
313 	{
314 		VIEWTYPE_IMAGE_VIEW	= 0,
315 		VIEWTYPE_MEMORY_ALIAS,
316 
317 		VIEWTYPE_LAST
318 	};
319 
320 	ViewType			viewType;
321 	VkFormat			format;
322 	UVec2				size;
323 	VkImageCreateFlags	createFlags;
324 	deUint32			planeNdx;
325 	VkFormat			planeCompatibleFormat;
326 	glu::ShaderType		shaderType;
327 	deBool				isCompatibilityFormat;
328 
TestParametersvkt::ycbcr::__anon16ce7d170111::TestParameters329 	TestParameters (ViewType viewType_, VkFormat format_, const UVec2& size_, VkImageCreateFlags createFlags_, deUint32 planeNdx_, VkFormat planeCompatibleFormat_, glu::ShaderType shaderType_, deBool isCompatibilityFormat_)
330 		: viewType				(viewType_)
331 		, format				(format_)
332 		, size					(size_)
333 		, createFlags			(createFlags_)
334 		, planeNdx				(planeNdx_)
335 		, planeCompatibleFormat	(planeCompatibleFormat_)
336 		, shaderType			(shaderType_)
337 		, isCompatibilityFormat	(isCompatibilityFormat_)
338 	{
339 	}
340 
TestParametersvkt::ycbcr::__anon16ce7d170111::TestParameters341 	TestParameters (void)
342 		: viewType				(VIEWTYPE_LAST)
343 		, format				(VK_FORMAT_UNDEFINED)
344 		, createFlags			(0u)
345 		, planeNdx				(0u)
346 		, planeCompatibleFormat	(VK_FORMAT_UNDEFINED)
347 		, shaderType			(glu::SHADERTYPE_LAST)
348 		, isCompatibilityFormat	(false)
349 	{
350 	}
351 };
352 
getSamplerDecl(VkFormat f)353 static std::string getSamplerDecl(VkFormat f) {
354 	if (isIntFormat(f))			return "isampler2D";
355 	else if (isUintFormat(f))	return "usampler2D";
356 	else						return "sampler2D";
357 }
358 
getShaderSpec(const TestParameters & params)359 ShaderSpec getShaderSpec (const TestParameters& params)
360 {
361 	ShaderSpec spec;
362 
363 	spec.inputs.push_back(Symbol("texCoord", glu::VarType(glu::TYPE_FLOAT_VEC2, glu::PRECISION_HIGHP)));
364 	spec.outputs.push_back(Symbol("result0", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
365 	spec.outputs.push_back(Symbol("result1", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
366 
367 	const std::string sampler = getSamplerDecl(params.planeCompatibleFormat);
368 	spec.globalDeclarations =
369 		"layout(binding = 1, set = 1) uniform highp sampler2D u_image;\n"
370 		"layout(binding = 0, set = 1) uniform highp " + sampler + " u_planeView;\n";
371 
372 	spec.source =
373 		"result0 = texture(u_image, texCoord);\n"
374 		"result1 = vec4(texture(u_planeView, texCoord));\n";
375 
376 	return spec;
377 }
378 
379 
generateLookupCoordinates(const UVec2 & imageSize,size_t numCoords,de::Random * rnd,vector<Vec2> * dst)380 void generateLookupCoordinates (const UVec2& imageSize, size_t numCoords, de::Random* rnd, vector<Vec2>* dst)
381 {
382 	dst->resize(numCoords);
383 
384 	for (size_t coordNdx = 0; coordNdx < numCoords; ++coordNdx)
385 	{
386 		const deUint32	texelX	= rnd->getUint32() % imageSize.x();
387 		const deUint32	texelY	= rnd->getUint32() % imageSize.y();
388 		const float		x		= ((float)texelX + 0.5f) / (float)imageSize.x();
389 		const float		y		= ((float)texelY + 0.5f) / (float)imageSize.y();
390 
391 		(*dst)[coordNdx] = Vec2(x, y);
392 	}
393 }
394 
checkImageUsageSupport(Context & context,VkFormat format,VkImageUsageFlags usage)395 void checkImageUsageSupport (Context&			context,
396 							 VkFormat			format,
397 							 VkImageUsageFlags	usage)
398 {
399 	const VkFormatProperties	formatProperties	= getPhysicalDeviceFormatProperties(context.getInstanceInterface(),
400 																						context.getPhysicalDevice(),
401 																						format);
402 	const VkFormatFeatureFlags	featureFlags		= formatProperties.optimalTilingFeatures;
403 
404 	if ((usage & VK_IMAGE_USAGE_SAMPLED_BIT) != 0
405 		&& (featureFlags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) == 0)
406 	{
407 		TCU_THROW(NotSupportedError, "Format doesn't support sampling");
408 	}
409 
410 	// Other image usages are not handled currently
411 	DE_ASSERT((usage & ~(VK_IMAGE_USAGE_TRANSFER_SRC_BIT|VK_IMAGE_USAGE_TRANSFER_DST_BIT|VK_IMAGE_USAGE_SAMPLED_BIT)) == 0);
412 }
413 
checkSupport(Context & context,TestParameters params)414 void checkSupport(Context& context, TestParameters params)
415 {
416 	const VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
417 
418 	checkImageSupport(context, params.format, params.createFlags);
419 	checkImageUsageSupport(context, params.format, usage);
420 	checkImageUsageSupport(context, params.planeCompatibleFormat, usage);
421 }
422 
testPlaneView(Context & context,TestParameters params)423 tcu::TestStatus testPlaneView (Context& context, TestParameters params)
424 {
425 	de::Random						randomGen		(deInt32Hash((deUint32)params.format)	^
426 													 deInt32Hash((deUint32)params.planeNdx)	^
427 													 deInt32Hash((deUint32)params.shaderType));
428 
429 	const InstanceInterface&		vk				= context.getInstanceInterface();
430 	const DeviceInterface&			vkd				= context.getDeviceInterface();
431 	const VkDevice					device			= context.getDevice();
432 
433 	const VkFormat					format			= params.format;
434 	const VkImageCreateFlags		createFlags		= params.createFlags;
435 	const PlanarFormatDescription	formatInfo		= getPlanarFormatDescription(format);
436 	const UVec2						size			= params.size;
437 	const UVec2						planeExtent		= getPlaneExtent(formatInfo, size, params.planeNdx, 0);
438 	const Unique<VkImage>			image			(createTestImage(vkd, device, format, size, createFlags));
439 	const Unique<VkImage>			imageAlias		((params.viewType == TestParameters::VIEWTYPE_MEMORY_ALIAS)
440 													 ? createTestImage(vkd, device, params.planeCompatibleFormat, planeExtent, createFlags)
441 													 : Move<VkImage>());
442 	const vector<AllocationSp>		allocations		(allocateAndBindImageMemory(vkd, device, context.getDefaultAllocator(), *image, format, createFlags));
443 
444 	if (imageAlias)
445 	{
446 		if ((createFlags & VK_IMAGE_CREATE_DISJOINT_BIT) != 0)
447 		{
448 			VkBindImagePlaneMemoryInfo	planeInfo	=
449 			{
450 				VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO_KHR,
451 				DE_NULL,
452 				VK_IMAGE_ASPECT_PLANE_0_BIT_KHR
453 			};
454 
455 			VkBindImageMemoryInfo coreInfo	=
456 			{
457 				VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHR,
458 				&planeInfo,
459 				*imageAlias,
460 				allocations[params.planeNdx]->getMemory(),
461 				allocations[params.planeNdx]->getOffset(),
462 			};
463 
464 			VK_CHECK(vkd.bindImageMemory2(device, 1, &coreInfo));
465 		}
466 		else
467 		{
468 			VK_CHECK(vkd.bindImageMemory(device, *imageAlias, allocations[params.planeNdx]->getMemory(), allocations[params.planeNdx]->getOffset()));
469 		}
470 	}
471 
472 	const VkSamplerYcbcrConversionCreateInfo	conversionInfo	=
473 	{
474 		VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO,
475 		DE_NULL,
476 		format,
477 		VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY,
478 		VK_SAMPLER_YCBCR_RANGE_ITU_FULL,
479 		{
480 			VK_COMPONENT_SWIZZLE_IDENTITY,
481 			VK_COMPONENT_SWIZZLE_IDENTITY,
482 			VK_COMPONENT_SWIZZLE_IDENTITY,
483 			VK_COMPONENT_SWIZZLE_IDENTITY,
484 		},
485 		VK_CHROMA_LOCATION_MIDPOINT,
486 		VK_CHROMA_LOCATION_MIDPOINT,
487 		VK_FILTER_NEAREST,
488 		VK_FALSE,									// forceExplicitReconstruction
489 	};
490 	const Unique<VkSamplerYcbcrConversion>		conversion	(createSamplerYcbcrConversion(vkd, device, &conversionInfo));
491 	const VkSamplerYcbcrConversionInfo			samplerConversionInfo	=
492 	{
493 		VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO,
494 		DE_NULL,
495 		*conversion,
496 	};
497 	const Unique<VkImageView>					wholeView	(createImageView(vkd, device, *image, format, VK_IMAGE_ASPECT_COLOR_BIT, &samplerConversionInfo));
498 	const Unique<VkImageView>					planeView	(createImageView(vkd,
499 																			 device,
500 																			 !imageAlias ? *image : *imageAlias,
501 																			 params.planeCompatibleFormat,
502 																			 !imageAlias ? getPlaneAspect(params.planeNdx) : VK_IMAGE_ASPECT_COLOR_BIT,
503 																			 DE_NULL));
504 
505 	const VkSamplerCreateInfo					wholeSamplerInfo		=
506 	{
507 		VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
508 		&samplerConversionInfo,
509 		0u,
510 		VK_FILTER_NEAREST,							// magFilter
511 		VK_FILTER_NEAREST,							// minFilter
512 		VK_SAMPLER_MIPMAP_MODE_NEAREST,				// mipmapMode
513 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// addressModeU
514 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// addressModeV
515 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// addressModeW
516 		0.0f,										// mipLodBias
517 		VK_FALSE,									// anisotropyEnable
518 		1.0f,										// maxAnisotropy
519 		VK_FALSE,									// compareEnable
520 		VK_COMPARE_OP_ALWAYS,						// compareOp
521 		0.0f,										// minLod
522 		0.0f,										// maxLod
523 		VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,	// borderColor
524 		VK_FALSE,									// unnormalizedCoords
525 	};
526 	const VkSamplerCreateInfo					planeSamplerInfo		=
527 	{
528 		VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
529 		DE_NULL,
530 		0u,
531 		VK_FILTER_NEAREST,							// magFilter
532 		VK_FILTER_NEAREST,							// minFilter
533 		VK_SAMPLER_MIPMAP_MODE_NEAREST,				// mipmapMode
534 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// addressModeU
535 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// addressModeV
536 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// addressModeW
537 		0.0f,										// mipLodBias
538 		VK_FALSE,									// anisotropyEnable
539 		1.0f,										// maxAnisotropy
540 		VK_FALSE,									// compareEnable
541 		VK_COMPARE_OP_ALWAYS,						// compareOp
542 		0.0f,										// minLod
543 		0.0f,										// maxLod
544 		VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,	// borderColor
545 		VK_FALSE,									// unnormalizedCoords
546 	};
547 
548 	deUint32									combinedSamplerDescriptorCount = 1;
549 	{
550 		const VkPhysicalDeviceImageFormatInfo2			imageFormatInfo				=
551 		{
552 			VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,	// sType;
553 			DE_NULL,												// pNext;
554 			format,													// format;
555 			VK_IMAGE_TYPE_2D,										// type;
556 			VK_IMAGE_TILING_OPTIMAL,								// tiling;
557 			VK_IMAGE_USAGE_TRANSFER_DST_BIT |
558 			VK_IMAGE_USAGE_SAMPLED_BIT,								// usage;
559 			createFlags												// flags;
560 		};
561 
562 		VkSamplerYcbcrConversionImageFormatProperties	samplerYcbcrConversionImage = {};
563 		samplerYcbcrConversionImage.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES;
564 		samplerYcbcrConversionImage.pNext = DE_NULL;
565 
566 		VkImageFormatProperties2						imageFormatProperties		= {};
567 		imageFormatProperties.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
568 		imageFormatProperties.pNext = &samplerYcbcrConversionImage;
569 
570 		VkResult result = vk.getPhysicalDeviceImageFormatProperties2(context.getPhysicalDevice(), &imageFormatInfo, &imageFormatProperties);
571 		if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
572 			TCU_THROW(NotSupportedError, "Format not supported.");
573 		VK_CHECK(result);
574 		combinedSamplerDescriptorCount = samplerYcbcrConversionImage.combinedImageSamplerDescriptorCount;
575 	}
576 
577 	const Unique<VkSampler>					wholeSampler(createSampler(vkd, device, &wholeSamplerInfo));
578 	const Unique<VkSampler>					planeSampler(createSampler(vkd, device, &planeSamplerInfo));
579 
580 	const Unique<VkDescriptorSetLayout>		descLayout	(createDescriptorSetLayout(vkd, device, *wholeSampler));
581 	const Unique<VkDescriptorPool>			descPool	(createDescriptorPool(vkd, device, combinedSamplerDescriptorCount));
582 	const Unique<VkDescriptorSet>			descSet		(createDescriptorSet(vkd, device, *descPool, *descLayout, *planeView, *planeSampler, *wholeView, *wholeSampler));
583 
584 	MultiPlaneImageData						imageData	(format, size);
585 
586 	// Prepare texture data
587 	fillRandom(&randomGen, &imageData);
588 
589 	if (imageAlias)
590 	{
591 		// Transition alias to right layout first
592 		const VkImageMemoryBarrier		initAliasBarrier	=
593 		{
594 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
595 			DE_NULL,
596 			(VkAccessFlags)0,
597 			VK_ACCESS_SHADER_READ_BIT,
598 			VK_IMAGE_LAYOUT_UNDEFINED,
599 			VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
600 			VK_QUEUE_FAMILY_IGNORED,
601 			VK_QUEUE_FAMILY_IGNORED,
602 			*imageAlias,
603 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }
604 		};
605 
606 		executeImageBarrier(vkd,
607 							device,
608 							context.getUniversalQueueFamilyIndex(),
609 							(VkPipelineStageFlags)VK_PIPELINE_STAGE_HOST_BIT,
610 							(VkPipelineStageFlags)VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
611 							initAliasBarrier);
612 	}
613 
614 	// Upload and prepare image
615 	uploadImage(vkd,
616 				device,
617 				context.getUniversalQueueFamilyIndex(),
618 				context.getDefaultAllocator(),
619 				*image,
620 				imageData,
621 				(VkAccessFlags)VK_ACCESS_SHADER_READ_BIT,
622 				VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
623 
624 	{
625 		const size_t	numValues		= 500;
626 		vector<Vec2>	texCoord		(numValues);
627 		vector<Vec4>	resultWhole		(numValues);
628 		vector<Vec4>	resultPlane		(numValues);
629 		vector<Vec4>	referenceWhole	(numValues);
630 		vector<Vec4>	referencePlane	(numValues);
631 		bool			allOk			= true;
632 		Vec4			threshold		(0.02f);
633 
634 		generateLookupCoordinates(size, numValues, &randomGen, &texCoord);
635 
636 		{
637 			UniquePtr<ShaderExecutor>	executor	(createExecutor(context, params.shaderType, getShaderSpec(params), *descLayout));
638 			const void*					inputs[]	= { texCoord[0].getPtr() };
639 			void*						outputs[]	= { resultWhole[0].getPtr(), resultPlane[0].getPtr() };
640 
641 			executor->execute((int)numValues, inputs, outputs, *descSet);
642 		}
643 
644 		// Whole image sampling reference
645 		for (deUint32 channelNdx = 0; channelNdx < 4; channelNdx++)
646 		{
647 			if (formatInfo.hasChannelNdx(channelNdx))
648 			{
649 				const tcu::ConstPixelBufferAccess	channelAccess	= imageData.getChannelAccess(channelNdx);
650 				const tcu::Sampler					refSampler		= mapVkSampler(wholeSamplerInfo);
651 				const tcu::Texture2DView			refTexView		(1u, &channelAccess);
652 
653 				for (size_t ndx = 0; ndx < numValues; ++ndx)
654 				{
655 					const Vec2&	coord	= texCoord[ndx];
656 					referenceWhole[ndx][channelNdx] = refTexView.sample(refSampler, coord.x(), coord.y(), 0.0f)[0];
657 				}
658 			}
659 			else
660 			{
661 				for (size_t ndx = 0; ndx < numValues; ++ndx)
662 					referenceWhole[ndx][channelNdx] = channelNdx == 3 ? 1.0f : 0.0f;
663 			}
664 		}
665 
666 		// Plane view sampling reference
667 		{
668 			const tcu::ConstPixelBufferAccess	planeAccess		(mapVkFormat(params.planeCompatibleFormat),
669 																 tcu::IVec3((int)planeExtent.x(), (int)planeExtent.y(), 1),
670 																 imageData.getPlanePtr(params.planeNdx));
671 			const tcu::Sampler					refSampler		= mapVkSampler(planeSamplerInfo);
672 			const tcu::Texture2DView			refTexView		(1u, &planeAccess);
673 
674 			for (size_t ndx = 0; ndx < numValues; ++ndx)
675 			{
676 				const Vec2&	coord	= texCoord[ndx];
677 				referencePlane[ndx] = refTexView.sample(refSampler, coord.x(), coord.y(), 0.0f);
678 			}
679 		}
680 
681 		for (int viewNdx = 0; viewNdx < 2; ++viewNdx)
682 		{
683 			const char* const	viewName	= (viewNdx == 0) ? "complete image"	: "plane view";
684 			const vector<Vec4>&	reference	= (viewNdx == 0) ? referenceWhole	: referencePlane;
685 			const vector<Vec4>&	result		= (viewNdx == 0) ? resultWhole		: resultPlane;
686 
687 			for (size_t ndx = 0; ndx < numValues; ++ndx)
688 			{
689 				if (boolAny(greaterThanEqual(abs(result[ndx] - reference[ndx]), threshold)))
690 				{
691 					context.getTestContext().getLog()
692 						<< TestLog::Message << "ERROR: When sampling " << viewName << " at " << texCoord[ndx]
693 											<< ": got " << result[ndx]
694 											<< ", expected " << reference[ndx]
695 						<< TestLog::EndMessage;
696 					allOk = false;
697 				}
698 			}
699 		}
700 
701 		if (allOk)
702 			return tcu::TestStatus::pass("All samples passed");
703 		else
704 			return tcu::TestStatus::fail("Got invalid results");
705 	}
706 }
707 
initPrograms(SourceCollections & dst,TestParameters params)708 void initPrograms (SourceCollections& dst, TestParameters params)
709 {
710 	const ShaderSpec	spec	= getShaderSpec(params);
711 
712 	generateSources(params.shaderType, spec, dst);
713 }
714 
addPlaneViewCase(tcu::TestCaseGroup * group,const TestParameters & params)715 void addPlaneViewCase (tcu::TestCaseGroup* group, const TestParameters& params)
716 {
717 	std::ostringstream name;
718 
719 	name << de::toLower(de::toString(params.format).substr(10));
720 
721 	if ((params.viewType != TestParameters::VIEWTYPE_MEMORY_ALIAS) &&
722 		((params.createFlags & VK_IMAGE_CREATE_DISJOINT_BIT) != 0))
723 		name << "_disjoint";
724 
725 	name << "_plane_" << params.planeNdx;
726 
727 	if (params.isCompatibilityFormat)
728 	{
729 		name << "_compatible_format_" << de::toLower(de::toString(params.planeCompatibleFormat).substr(10));
730 	}
731 
732 	addFunctionCaseWithPrograms(group, name.str(), "", checkSupport, initPrograms, testPlaneView, params);
733 }
734 
populateViewTypeGroup(tcu::TestCaseGroup * group,TestParameters::ViewType viewType)735 void populateViewTypeGroup (tcu::TestCaseGroup* group, TestParameters::ViewType viewType)
736 {
737 	const glu::ShaderType		shaderType	= glu::SHADERTYPE_FRAGMENT;
738 	const UVec2					size		(32, 58);
739 	const VkImageCreateFlags	baseFlags	= (VkImageCreateFlags)VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT
740 											| (viewType == TestParameters::VIEWTYPE_MEMORY_ALIAS ? (VkImageCreateFlags)VK_IMAGE_CREATE_ALIAS_BIT : 0u);
741 
742 	auto addTests = [&](int formatNdx)
743 	{
744 		const VkFormat	format		= (VkFormat)formatNdx;
745 		const deUint32	numPlanes	= getPlaneCount(format);
746 
747 		if (numPlanes == 1)
748 			return; // Plane views not possible
749 
750 		for (int isDisjoint = 0; isDisjoint < 2; ++isDisjoint)
751 		{
752 			const VkImageCreateFlags	flags	= baseFlags | (isDisjoint == 1 ? (VkImageCreateFlags)VK_IMAGE_CREATE_DISJOINT_BIT : 0u);
753 
754 			if ((viewType == TestParameters::VIEWTYPE_MEMORY_ALIAS) &&
755 				((flags & VK_IMAGE_CREATE_DISJOINT_BIT) == 0))
756 				continue; // Memory alias cases require disjoint planes
757 
758 			for (deUint32 planeNdx = 0; planeNdx < numPlanes; ++planeNdx)
759 			{
760 				const VkFormat planeFormat = getPlaneCompatibleFormat(format, planeNdx);
761 				// Add test case using image view with a format taken from the "Plane Format Compatibility Table"
762 				addPlaneViewCase(group, TestParameters(viewType, format, size, flags, planeNdx, planeFormat, shaderType, DE_FALSE));
763 
764 				// Add test cases using image view with a format that is compatible with the plane's format.
765 				// For example: VK_FORMAT_R4G4_UNORM_PACK8 is compatible with VK_FORMAT_R8_UNORM.
766 				for (const auto& compatibleFormat : s_compatible_formats)
767 				{
768 					if (compatibleFormat == planeFormat)
769 						continue;
770 
771 					if (!formatsAreCompatible(planeFormat, compatibleFormat))
772 						continue;
773 
774 					addPlaneViewCase(group, TestParameters(viewType, format, size, flags, planeNdx, compatibleFormat, shaderType, DE_TRUE));
775 				}
776 			}
777 		}
778 	};
779 
780 	for (int formatNdx = VK_YCBCR_FORMAT_FIRST; formatNdx < VK_YCBCR_FORMAT_LAST; formatNdx++)
781 	{
782 		addTests(formatNdx);
783 	}
784 
785 	for (int formatNdx = VK_FORMAT_G8_B8R8_2PLANE_444_UNORM_EXT; formatNdx < VK_FORMAT_G16_B16R16_2PLANE_444_UNORM_EXT; formatNdx++)
786 	{
787 		addTests(formatNdx);
788 	}
789 }
790 
populateViewGroup(tcu::TestCaseGroup * group)791 void populateViewGroup (tcu::TestCaseGroup* group)
792 {
793 	addTestGroup(group, "image_view",	"Plane View via VkImageView",		populateViewTypeGroup,	TestParameters::VIEWTYPE_IMAGE_VIEW);
794 	addTestGroup(group, "memory_alias",	"Plane View via Memory Aliasing",	populateViewTypeGroup,	TestParameters::VIEWTYPE_MEMORY_ALIAS);
795 }
796 
797 } // anonymous
798 
createViewTests(tcu::TestContext & testCtx)799 tcu::TestCaseGroup* createViewTests (tcu::TestContext& testCtx)
800 {
801 	return createTestGroup(testCtx, "plane_view", "YCbCr Plane View Tests", populateViewGroup);
802 }
803 
804 } // ycbcr
805 } // vkt
806 
807