• 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 Texture color conversion tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktYCbCrConversionTests.hpp"
25 
26 #include "vktShaderExecutor.hpp"
27 #include "vktTestCaseUtil.hpp"
28 #include "vktTestGroupUtil.hpp"
29 #include "vktYCbCrUtil.hpp"
30 
31 #include "vkImageUtil.hpp"
32 #include "vkMemUtil.hpp"
33 #include "vkPrograms.hpp"
34 #include "vkRefUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkQueryUtil.hpp"
37 
38 #include "tcuInterval.hpp"
39 #include "tcuTestLog.hpp"
40 #include "tcuTexture.hpp"
41 #include "tcuTextureUtil.hpp"
42 #include "tcuVector.hpp"
43 #include "tcuVectorUtil.hpp"
44 #include "tcuFloatFormat.hpp"
45 #include "tcuFloat.hpp"
46 
47 #include "deRandom.hpp"
48 #include "deSTLUtil.hpp"
49 #include "deSharedPtr.hpp"
50 
51 #include "deMath.h"
52 #include "deFloat16.h"
53 
54 #include <vector>
55 #include <iomanip>
56 
57 // \todo When defined color conversion extension is not used and conversion is performed in the shader
58 // #define FAKE_COLOR_CONVERSION
59 
60 using tcu::Vec2;
61 using tcu::Vec4;
62 
63 using tcu::UVec2;
64 using tcu::UVec4;
65 
66 using tcu::IVec2;
67 using tcu::IVec3;
68 using tcu::IVec4;
69 
70 using tcu::TestLog;
71 using tcu::FloatFormat;
72 
73 using std::vector;
74 using std::string;
75 
76 using namespace vkt::shaderexecutor;
77 
78 namespace vkt
79 {
80 namespace ycbcr
81 {
82 namespace
83 {
84 
85 template<typename T>
makeSharedPtr(vk::Move<T> move)86 inline de::SharedPtr<vk::Unique<T> > makeSharedPtr(vk::Move<T> move)
87 {
88 	return de::SharedPtr<vk::Unique<T> >(new vk::Unique<T>(move));
89 }
90 
createShaderSpec(deUint32 samplerBinding,const std::vector<vk::VkSamplerYcbcrModelConversion> & colorModels)91 ShaderSpec createShaderSpec (deUint32 samplerBinding, const std::vector<vk::VkSamplerYcbcrModelConversion>&	colorModels)
92 {
93 	ShaderSpec spec;
94 
95 	spec.inputs.push_back(Symbol("uv", glu::VarType(glu::TYPE_FLOAT_VEC2, glu::PRECISION_HIGHP)));
96 	// shader with single sampler
97 	if (colorModels.size()==1)
98 	{
99 		spec.globalDeclarations	= "layout(set=" + de::toString((int)EXTRA_RESOURCES_DESCRIPTOR_SET_INDEX) + ", binding=" + de::toString(samplerBinding) + ") uniform highp sampler2D u_sampler;";
100 
101 		spec.outputs.push_back(Symbol("o_color", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
102 
103 		spec.source				= "o_color = texture(u_sampler, uv);\n";
104 	}
105 	else // shader with array of samplers
106 	{
107 		spec.globalDeclarations	= "layout(set=" + de::toString((int)EXTRA_RESOURCES_DESCRIPTOR_SET_INDEX) + ", binding=" + de::toString(samplerBinding) + ") uniform highp sampler2D u_sampler[" + de::toString(colorModels.size()) +  "];";
108 
109 		for (int i = 0; i < (int)colorModels.size(); i++)
110 		{
111 			spec.outputs.push_back(Symbol(string("o_color") + de::toString(i), glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
112 
113 			spec.source += string("o_color") + de::toString(i) + " = texture(u_sampler[" + de::toString(i) + "], uv);\n";
114 		}
115 	}
116 	return spec;
117 }
118 
genTexCoords(std::vector<Vec2> & coords,const UVec2 & srcSize,const UVec2 & dstSize)119 void genTexCoords (std::vector<Vec2>&	coords,
120 				   const UVec2&			srcSize,
121 				   const UVec2&			dstSize)
122 {
123 	for (deUint32 y = 0; y < dstSize.y(); y++)
124 	for (deUint32 x = 0; x < dstSize.x(); x++)
125 	{
126 		const float	fx	= (float)x;
127 		const float	fy	= (float)y;
128 
129 		const float	fw	= (float)srcSize.x();
130 		const float	fh	= (float)srcSize.y();
131 
132 		const float	s	= 1.5f * ((fx * 1.5f * fw + fx) / (1.5f * fw * 1.5f * fw)) - 0.25f;
133 		const float	t	= 1.5f * ((fy * 1.5f * fh + fy) / (1.5f * fh * 1.5f * fh)) - 0.25f;
134 
135 		coords.push_back(Vec2(s, t));
136 	}
137 }
138 
genOneToOneTexCoords(std::vector<Vec2> & coords,const UVec2 & size)139 void genOneToOneTexCoords (std::vector<Vec2>&	coords,
140 						   const UVec2&			size)
141 {
142 	for (deUint32 y = 0; y < size.y(); y++)
143 	for (deUint32 x = 0; x < size.x(); x++)
144 	{
145 		const float s = ((float)x + 0.5f) / (float)size.x();
146 		const float t = ((float)y + 0.5f) / (float)size.y();
147 
148 		coords.push_back(Vec2(s, t));
149 	}
150 }
151 
152 struct TestConfig
153 {
TestConfigvkt::ycbcr::__anon548eae410111::TestConfig154 	TestConfig	(glu::ShaderType						shaderType_,
155 				 vk::VkFormat							format_,
156 				 vk::VkImageTiling						imageTiling_,
157 				 vk::VkFilter							textureFilter_,
158 				 vk::VkSamplerAddressMode				addressModeU_,
159 				 vk::VkSamplerAddressMode				addressModeV_,
160 
161 				 vk::VkFilter							chromaFilter_,
162 				 vk::VkChromaLocation					xChromaOffset_,
163 				 vk::VkChromaLocation					yChromaOffset_,
164 				 bool									explicitReconstruction_,
165 				 bool									disjoint_,
166 
167 				 vk::VkSamplerYcbcrRange				colorRange_,
168 				 vk::VkSamplerYcbcrModelConversion		colorModel_,
169 				 vk::VkComponentMapping					componentMapping_,
170 				 const UVec2							srcSize_,
171 				 const UVec2							dstSize_,
172 				 deUint32								samplerBinding_)
173 		: shaderType				(shaderType_)
174 		, format					(format_)
175 		, imageTiling				(imageTiling_)
176 		, textureFilter				(textureFilter_)
177 		, addressModeU				(addressModeU_)
178 		, addressModeV				(addressModeV_)
179 
180 		, chromaFilter				(chromaFilter_)
181 		, xChromaOffset				(xChromaOffset_)
182 		, yChromaOffset				(yChromaOffset_)
183 		, explicitReconstruction	(explicitReconstruction_)
184 		, disjoint					(disjoint_)
185 
186 		, colorRange				(colorRange_)
187 		, colorModel				(colorModel_)
188 		, componentMapping			(componentMapping_)
189 		, srcSize					(srcSize_)
190 		, dstSize					(dstSize_)
191 		, samplerBinding			(samplerBinding_)
192 	{
193 	}
194 
195 	glu::ShaderType							shaderType;
196 	vk::VkFormat							format;
197 	vk::VkImageTiling						imageTiling;
198 	vk::VkFilter							textureFilter;
199 	vk::VkSamplerAddressMode				addressModeU;
200 	vk::VkSamplerAddressMode				addressModeV;
201 
202 	vk::VkFilter							chromaFilter;
203 	vk::VkChromaLocation					xChromaOffset;
204 	vk::VkChromaLocation					yChromaOffset;
205 	bool									explicitReconstruction;
206 	bool									disjoint;
207 
208 	vk::VkSamplerYcbcrRange					colorRange;
209 	vk::VkSamplerYcbcrModelConversion		colorModel;
210 	vk::VkComponentMapping					componentMapping;
211 	const UVec2								srcSize;
212 	const UVec2								dstSize;
213 	deUint32								samplerBinding;
214 };
215 
createDescriptorSetLayout(const vk::DeviceInterface & vkd,vk::VkDevice device,const std::vector<de::SharedPtr<vk::Unique<vk::VkSampler>>> & samplers,deUint32 samplerBinding)216 vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout (const vk::DeviceInterface&											vkd,
217 															   vk::VkDevice															device,
218 															   const std::vector<de::SharedPtr<vk::Unique<vk::VkSampler> > >&		samplers,
219 															   deUint32																samplerBinding)
220 {
221 	std::vector<vk::VkSampler> sampler;
222 	for (size_t i = 0; i < samplers.size(); i++)
223 		sampler.push_back(samplers[i]->get());
224 	const vk::VkDescriptorSetLayoutBinding		layoutBindings[] =
225 	{
226 		{
227 			samplerBinding,
228 			vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
229 			(deUint32)sampler.size(),
230 			vk::VK_SHADER_STAGE_ALL,
231 			sampler.data()
232 		}
233 	};
234 	const vk::VkDescriptorSetLayoutCreateInfo	layoutCreateInfo	=
235 	{
236 		vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
237 		DE_NULL,
238 
239 		0u,
240 		DE_LENGTH_OF_ARRAY(layoutBindings),
241 		layoutBindings
242 	};
243 
244 	return vk::createDescriptorSetLayout(vkd, device, &layoutCreateInfo);
245 }
246 
createDescriptorPool(const vk::DeviceInterface & vkd,vk::VkDevice device,const std::vector<de::SharedPtr<vk::Unique<vk::VkSampler>>> & samplers,const deUint32 combinedSamplerDescriptorCount)247 vk::Move<vk::VkDescriptorPool> createDescriptorPool (const vk::DeviceInterface&											vkd,
248 													 vk::VkDevice														device,
249 													 const std::vector<de::SharedPtr<vk::Unique<vk::VkSampler> > >&		samplers,
250 													 const deUint32														combinedSamplerDescriptorCount)
251 {
252 	const vk::VkDescriptorPoolSize			poolSizes[]					=
253 	{
254 		{ vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, (deUint32)samplers.size() * combinedSamplerDescriptorCount }
255 	};
256 	const vk::VkDescriptorPoolCreateInfo	descriptorPoolCreateInfo	=
257 	{
258 		vk::VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
259 		DE_NULL,
260 		vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
261 
262 		1u,
263 		DE_LENGTH_OF_ARRAY(poolSizes),
264 		poolSizes
265 	};
266 
267 	return createDescriptorPool(vkd, device, &descriptorPoolCreateInfo);
268 }
269 
createDescriptorSet(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkDescriptorPool descriptorPool,vk::VkDescriptorSetLayout layout,const std::vector<de::SharedPtr<vk::Unique<vk::VkSampler>>> & samplers,const std::vector<de::SharedPtr<vk::Unique<vk::VkImageView>>> & imageViews,deUint32 samplerBinding)270 vk::Move<vk::VkDescriptorSet> createDescriptorSet (const vk::DeviceInterface&											vkd,
271 												   vk::VkDevice															device,
272 												   vk::VkDescriptorPool													descriptorPool,
273 												   vk::VkDescriptorSetLayout											layout,
274 												   const std::vector<de::SharedPtr<vk::Unique<vk::VkSampler> > >&		samplers,
275 												   const std::vector<de::SharedPtr<vk::Unique<vk::VkImageView> > >&		imageViews,
276 												   deUint32																samplerBinding)
277 {
278 	const vk::VkDescriptorSetAllocateInfo		descriptorSetAllocateInfo	=
279 	{
280 		vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
281 		DE_NULL,
282 
283 		descriptorPool,
284 		1u,
285 		&layout
286 	};
287 	vk::Move<vk::VkDescriptorSet>	descriptorSet	(vk::allocateDescriptorSet(vkd, device, &descriptorSetAllocateInfo));
288 	std::vector<vk::VkDescriptorImageInfo>	imageInfo;
289 	for (size_t i = 0; i < samplers.size(); i++)
290 	{
291 		const vk::VkDescriptorImageInfo	ii =
292 		{
293 			samplers[i]->get(),
294 			imageViews[i]->get(),
295 			vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
296 		};
297 		imageInfo.push_back(ii);
298 	}
299 
300 	{
301 		const vk::VkWriteDescriptorSet	writes[]	=
302 		{
303 			{
304 				vk::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
305 				DE_NULL,
306 
307 				*descriptorSet,
308 				samplerBinding,
309 				0u,
310 				(deUint32)imageInfo.size(),
311 				vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
312 				imageInfo.data(),
313 				DE_NULL,
314 				DE_NULL
315 			}
316 		};
317 
318 		vkd.updateDescriptorSets(device, DE_LENGTH_OF_ARRAY(writes), writes, 0u, DE_NULL);
319 	}
320 
321 	return descriptorSet;
322 }
323 
createSampler(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkFilter textureFilter,vk::VkSamplerAddressMode addressModeU,vk::VkSamplerAddressMode addressModeV,vk::VkSamplerYcbcrConversion conversion)324 vk::Move<vk::VkSampler> createSampler (const vk::DeviceInterface&		vkd,
325 									   vk::VkDevice						device,
326 									   vk::VkFilter						textureFilter,
327 									   vk::VkSamplerAddressMode			addressModeU,
328 									   vk::VkSamplerAddressMode			addressModeV,
329 									   vk::VkSamplerYcbcrConversion		conversion)
330 {
331 #if !defined(FAKE_COLOR_CONVERSION)
332 	const vk::VkSamplerYcbcrConversionInfo	samplerConversionInfo	=
333 	{
334 		vk::VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO,
335 		DE_NULL,
336 		conversion
337 	};
338 #else
339 	DE_UNREF(conversion);
340 #endif
341 	const vk::VkSamplerCreateInfo	createInfo	=
342 	{
343 		vk::VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
344 #if !defined(FAKE_COLOR_CONVERSION)
345 		&samplerConversionInfo,
346 #else
347 		DE_NULL,
348 #endif
349 
350 		0u,
351 		textureFilter,
352 		textureFilter,
353 		vk::VK_SAMPLER_MIPMAP_MODE_NEAREST,
354 		addressModeU,
355 		addressModeV,
356 		vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
357 		0.0f,
358 		VK_FALSE,
359 		1.0f,
360 		VK_FALSE,
361 		vk::VK_COMPARE_OP_ALWAYS,
362 		0.0f,
363 		0.0f,
364 		vk::VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,
365 		VK_FALSE,
366 	};
367 
368 	return createSampler(vkd, device, &createInfo);
369 }
370 
createImage(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkFormat format,const UVec2 & size,bool disjoint,vk::VkImageTiling tiling)371 vk::Move<vk::VkImage> createImage (const vk::DeviceInterface&	vkd,
372 								   vk::VkDevice					device,
373 								   vk::VkFormat					format,
374 								   const UVec2&					size,
375 								   bool							disjoint,
376 								   vk::VkImageTiling			tiling)
377 {
378 	const vk::VkImageCreateInfo createInfo =
379 	{
380 		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
381 		DE_NULL,
382 		disjoint ? (vk::VkImageCreateFlags)vk::VK_IMAGE_CREATE_DISJOINT_BIT : (vk::VkImageCreateFlags)0u,
383 
384 		vk::VK_IMAGE_TYPE_2D,
385 		format,
386 		vk::makeExtent3D(size.x(), size.y(), 1u),
387 		1u,
388 		1u,
389 		vk::VK_SAMPLE_COUNT_1_BIT,
390 		tiling,
391 		vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT | vk::VK_IMAGE_USAGE_SAMPLED_BIT,
392 		vk::VK_SHARING_MODE_EXCLUSIVE,
393 		0u,
394 		(const deUint32*)DE_NULL,
395 		vk::VK_IMAGE_LAYOUT_PREINITIALIZED,
396 	};
397 
398 	return vk::createImage(vkd, device, &createInfo);
399 }
400 
createImageView(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkImage image,vk::VkFormat format,vk::VkSamplerYcbcrConversion conversion)401 vk::Move<vk::VkImageView> createImageView (const vk::DeviceInterface&		vkd,
402 										   vk::VkDevice						device,
403 										   vk::VkImage						image,
404 										   vk::VkFormat						format,
405 										   vk::VkSamplerYcbcrConversion		conversion)
406 {
407 	// Both mappings should be equivalent: alternate between the two for different formats.
408 	const vk::VkComponentMapping	mappingA	= { vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY };
409 	const vk::VkComponentMapping	mappingB	= { vk::VK_COMPONENT_SWIZZLE_R, vk::VK_COMPONENT_SWIZZLE_G, vk::VK_COMPONENT_SWIZZLE_B, vk::VK_COMPONENT_SWIZZLE_A };
410 	const vk::VkComponentMapping&	mapping		= ((static_cast<int>(format) % 2 == 0) ? mappingA : mappingB);
411 
412 #if !defined(FAKE_COLOR_CONVERSION)
413 	const vk::VkSamplerYcbcrConversionInfo	conversionInfo	=
414 	{
415 		vk::VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO,
416 		DE_NULL,
417 		conversion
418 	};
419 #else
420 	DE_UNREF(conversion);
421 #endif
422 	const vk::VkImageViewCreateInfo				viewInfo		=
423 	{
424 		vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
425 #if defined(FAKE_COLOR_CONVERSION)
426 		DE_NULL,
427 #else
428 		&conversionInfo,
429 #endif
430 		(vk::VkImageViewCreateFlags)0,
431 
432 		image,
433 		vk::VK_IMAGE_VIEW_TYPE_2D,
434 		format,
435 		mapping,
436 		{ vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },
437 	};
438 
439 	return vk::createImageView(vkd, device, &viewInfo);
440 }
441 
createConversion(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkFormat format,vk::VkSamplerYcbcrModelConversion colorModel,vk::VkSamplerYcbcrRange colorRange,vk::VkChromaLocation xChromaOffset,vk::VkChromaLocation yChromaOffset,vk::VkFilter chromaFilter,const vk::VkComponentMapping & componentMapping,bool explicitReconstruction)442 vk::Move<vk::VkSamplerYcbcrConversion> createConversion (const vk::DeviceInterface&				vkd,
443 														 vk::VkDevice							device,
444 														 vk::VkFormat							format,
445 														 vk::VkSamplerYcbcrModelConversion		colorModel,
446 														 vk::VkSamplerYcbcrRange				colorRange,
447 														 vk::VkChromaLocation					xChromaOffset,
448 														 vk::VkChromaLocation					yChromaOffset,
449 														 vk::VkFilter							chromaFilter,
450 														 const vk::VkComponentMapping&			componentMapping,
451 														 bool									explicitReconstruction)
452 {
453 	const vk::VkSamplerYcbcrConversionCreateInfo	conversionInfo	=
454 	{
455 		vk::VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO,
456 		DE_NULL,
457 
458 		format,
459 		colorModel,
460 		colorRange,
461 		componentMapping,
462 		xChromaOffset,
463 		yChromaOffset,
464 		chromaFilter,
465 		explicitReconstruction ? VK_TRUE : VK_FALSE
466 	};
467 
468 	return vk::createSamplerYcbcrConversion(vkd, device, &conversionInfo);
469 }
470 
evalShader(Context & context,glu::ShaderType shaderType,const MultiPlaneImageData & imageData,const UVec2 & size,vk::VkFormat format,vk::VkImageTiling imageTiling,bool disjoint,vk::VkFilter textureFilter,vk::VkSamplerAddressMode addressModeU,vk::VkSamplerAddressMode addressModeV,const std::vector<vk::VkSamplerYcbcrModelConversion> & colorModels,vk::VkSamplerYcbcrRange colorRange,vk::VkChromaLocation xChromaOffset,vk::VkChromaLocation yChromaOffset,vk::VkFilter chromaFilter,const vk::VkComponentMapping & componentMapping,bool explicitReconstruction,const vector<Vec2> & sts,deUint32 samplerBinding,vector<vector<Vec4>> & results)471 void evalShader (Context&												context,
472 				 glu::ShaderType										shaderType,
473 				 const MultiPlaneImageData&								imageData,
474 				 const UVec2&											size,
475 				 vk::VkFormat											format,
476 				 vk::VkImageTiling										imageTiling,
477 				 bool													disjoint,
478 				 vk::VkFilter											textureFilter,
479 				 vk::VkSamplerAddressMode								addressModeU,
480 				 vk::VkSamplerAddressMode								addressModeV,
481 				 const std::vector<vk::VkSamplerYcbcrModelConversion>&	colorModels,
482 				 vk::VkSamplerYcbcrRange								colorRange,
483 				 vk::VkChromaLocation									xChromaOffset,
484 				 vk::VkChromaLocation									yChromaOffset,
485 				 vk::VkFilter											chromaFilter,
486 				 const vk::VkComponentMapping&							componentMapping,
487 				 bool													explicitReconstruction,
488 				 const vector<Vec2>&									sts,
489 				 deUint32												samplerBinding,
490 				 vector<vector<Vec4> >&									results)
491 {
492 	const vk::InstanceInterface&											vk				(context.getInstanceInterface());
493 	const vk::DeviceInterface&												vkd				(context.getDeviceInterface());
494 	const vk::VkDevice														device			(context.getDevice());
495 	std::vector<de::SharedPtr<vk::Unique<vk::VkSamplerYcbcrConversion> > >	conversions;
496 	std::vector<de::SharedPtr<vk::Unique<vk::VkSampler> > >					samplers;
497 #if !defined(FAKE_COLOR_CONVERSION)
498 	for (int i = 0; i < (int)colorModels.size(); i++)
499 	{
500 		conversions.push_back(makeSharedPtr(createConversion(vkd, device, format, colorModels[i], colorRange, xChromaOffset, yChromaOffset, chromaFilter, componentMapping, explicitReconstruction)));
501 		samplers.push_back(makeSharedPtr(createSampler(vkd, device, textureFilter, addressModeU, addressModeV, conversions[i]->get())));
502 	}
503 #else
504 	DE_UNREF(colorRange);
505 	DE_UNREF(xChromaOffset);
506 	DE_UNREF(yChromaOffset);
507 	DE_UNREF(chromaFilter);
508 	DE_UNREF(explicitReconstruction);
509 	DE_UNREF(componentMapping);
510 	samplers.push_back(makeSharedPtr(createSampler(vkd, device, textureFilter, addressModeU, addressModeV, (vk::VkSamplerYcbcrConversion)0u)));
511 #endif
512 	const vk::Unique<vk::VkImage>								image				(createImage(vkd, device, format, size, disjoint, imageTiling));
513 	const vk::MemoryRequirement									memoryRequirement	(imageTiling == vk::VK_IMAGE_TILING_OPTIMAL
514 																					? vk::MemoryRequirement::Any
515 																					: vk::MemoryRequirement::HostVisible);
516 	const vk::VkImageCreateFlags								createFlags			(disjoint ? vk::VK_IMAGE_CREATE_DISJOINT_BIT : (vk::VkImageCreateFlagBits)0u);
517 	const vector<AllocationSp>									imageMemory			(allocateAndBindImageMemory(vkd, device, context.getDefaultAllocator(), *image, format, createFlags, memoryRequirement));
518 	std::vector<de::SharedPtr<vk::Unique<vk::VkImageView > > >	imageViews;
519 #if defined(FAKE_COLOR_CONVERSION)
520 	imageViews.push_back(makeSharedPtr(createImageView(vkd, device, *image, format, (vk::VkSamplerYcbcrConversion)0)));
521 #else
522 	for (int i = 0; i < (int)colorModels.size(); i++)
523 	{
524 		imageViews.push_back(makeSharedPtr(createImageView(vkd, device, *image, format, conversions[i]->get())));
525 	}
526 #endif
527 
528 	deUint32 combinedSamplerDescriptorCount = 1;
529 	{
530 		const vk::VkPhysicalDeviceImageFormatInfo2 imageFormatInfo =
531 		{
532 			vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,	//VkStructureType		sType;
533 			DE_NULL,													//const void*			pNext;
534 			format,														//VkFormat				format;
535 			vk::VK_IMAGE_TYPE_2D,										//VkImageType			type;
536 			imageTiling,												//VkImageTiling			tiling;
537 			vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT |
538 			vk::VK_IMAGE_USAGE_SAMPLED_BIT,								//VkImageUsageFlags		usage;
539 			disjoint ?
540 			(vk::VkImageCreateFlags)vk::VK_IMAGE_CREATE_DISJOINT_BIT :
541 			(vk::VkImageCreateFlags)0u									//VkImageCreateFlags	flags;
542 		};
543 
544 		vk::VkSamplerYcbcrConversionImageFormatProperties samplerYcbcrConversionImage = {};
545 		samplerYcbcrConversionImage.sType = vk::VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES;
546 		samplerYcbcrConversionImage.pNext = DE_NULL;
547 
548 		vk::VkImageFormatProperties2 imageFormatProperties = {};
549 		imageFormatProperties.sType = vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
550 		imageFormatProperties.pNext = &samplerYcbcrConversionImage;
551 
552 		VK_CHECK(vk.getPhysicalDeviceImageFormatProperties2(context.getPhysicalDevice(), &imageFormatInfo, &imageFormatProperties));
553 		combinedSamplerDescriptorCount = samplerYcbcrConversionImage.combinedImageSamplerDescriptorCount;
554 	}
555 
556 
557 	const vk::Unique<vk::VkDescriptorSetLayout>			layout				(createDescriptorSetLayout(vkd, device, samplers, samplerBinding));
558 	const vk::Unique<vk::VkDescriptorPool>				descriptorPool		(createDescriptorPool(vkd, device, samplers, combinedSamplerDescriptorCount));
559 	const vk::Unique<vk::VkDescriptorSet>				descriptorSet		(createDescriptorSet(vkd, device, *descriptorPool, *layout, samplers, imageViews, samplerBinding));
560 
561 	const ShaderSpec									spec				(createShaderSpec(samplerBinding, colorModels));
562 	const de::UniquePtr<ShaderExecutor>					executor			(createExecutor(context, shaderType, spec, *layout));
563 
564 	if (imageTiling == vk::VK_IMAGE_TILING_OPTIMAL)
565 		uploadImage(vkd, device, context.getUniversalQueueFamilyIndex(), context.getDefaultAllocator(), *image, imageData, vk::VK_ACCESS_SHADER_READ_BIT, vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
566 	else
567 		fillImageMemory(vkd, device, context.getUniversalQueueFamilyIndex(), *image, imageMemory, imageData, vk::VK_ACCESS_SHADER_READ_BIT, vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
568 
569 	for(int i=0; i<(int)results.size(); i++)
570 		results[i].resize(sts.size());
571 
572 	{
573 		const void* const	inputs[]	=
574 		{
575 			&sts[0]
576 		};
577 		vector<void*> outputs;
578 		for (int i = 0; i < (int)results.size(); i++)
579 			outputs.push_back((void*)results[i].data());
580 
581 		executor->execute((int)sts.size(), inputs, outputs.data(), *descriptorSet);
582 	}
583 }
584 
logTestCaseInfo(TestLog & log,const TestConfig & config)585 void logTestCaseInfo (TestLog& log, const TestConfig& config)
586 {
587 	log << TestLog::Message << "ShaderType: " << config.shaderType << TestLog::EndMessage;
588 	log << TestLog::Message << "Format: "  << config.format << TestLog::EndMessage;
589 	log << TestLog::Message << "ImageTiling: " << config.imageTiling << TestLog::EndMessage;
590 	log << TestLog::Message << "TextureFilter: " << config.textureFilter << TestLog::EndMessage;
591 	log << TestLog::Message << "AddressModeU: " << config.addressModeU << TestLog::EndMessage;
592 	log << TestLog::Message << "AddressModeV: " << config.addressModeV << TestLog::EndMessage;
593 	log << TestLog::Message << "ChromaFilter: " << config.chromaFilter << TestLog::EndMessage;
594 	log << TestLog::Message << "XChromaOffset: " << config.xChromaOffset << TestLog::EndMessage;
595 	log << TestLog::Message << "YChromaOffset: " << config.yChromaOffset << TestLog::EndMessage;
596 	log << TestLog::Message << "ExplicitReconstruction: " << (config.explicitReconstruction ? "true" : "false") << TestLog::EndMessage;
597 	log << TestLog::Message << "Disjoint: " << (config.disjoint ? "true" : "false") << TestLog::EndMessage;
598 	log << TestLog::Message << "ColorRange: " << config.colorRange << TestLog::EndMessage;
599 	if( config.colorModel != vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_LAST )
600 		log << TestLog::Message << "ColorModel: " << config.colorModel << TestLog::EndMessage;
601 	else
602 		log << TestLog::Message << "ColorModel: array of samplers" << TestLog::EndMessage;
603 	log << TestLog::Message << "ComponentMapping: " << config.componentMapping << TestLog::EndMessage;
604 }
605 
checkSupport(Context & context,const TestConfig config)606 void checkSupport (Context& context, const TestConfig config)
607 {
608 #if !defined(FAKE_COLOR_CONVERSION)
609 	if (!context.isDeviceFunctionalitySupported("VK_KHR_sampler_ycbcr_conversion"))
610 		TCU_THROW(NotSupportedError, "Extension VK_KHR_sampler_ycbcr_conversion not supported");
611 
612 	try
613 	{
614 		const vk::VkFormatProperties	properties	(vk::getPhysicalDeviceFormatProperties(context.getInstanceInterface(), context.getPhysicalDevice(), config.format));
615 		const vk::VkFormatFeatureFlags	features	(config.imageTiling == vk::VK_IMAGE_TILING_OPTIMAL
616 			? properties.optimalTilingFeatures
617 			: properties.linearTilingFeatures);
618 
619 		if ((features & (vk::VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT | vk::VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT)) == 0)
620 			TCU_THROW(NotSupportedError, "Format doesn't support YCbCr conversions");
621 
622 		if ((features & vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) == 0)
623 			TCU_THROW(NotSupportedError, "Format doesn't support sampling");
624 
625 		if (config.textureFilter == vk::VK_FILTER_LINEAR && ((features & vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT) == 0))
626 			TCU_THROW(NotSupportedError, "Format doesn't support linear texture filtering");
627 
628 		if (config.chromaFilter == vk::VK_FILTER_LINEAR && ((features & vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT) == 0))
629 			TCU_THROW(NotSupportedError, "Format doesn't support YCbCr linear chroma reconstruction");
630 
631 		if (config.chromaFilter != config.textureFilter && ((features & vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT) == 0))
632 			TCU_THROW(NotSupportedError, "Format doesn't support different chroma and texture filters");
633 
634 		if (config.explicitReconstruction && ((features & vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT) == 0))
635 			TCU_THROW(NotSupportedError, "Format doesn't support explicit chroma reconstruction");
636 
637 		if (config.disjoint && ((features & vk::VK_FORMAT_FEATURE_DISJOINT_BIT) == 0))
638 			TCU_THROW(NotSupportedError, "Format doesn't disjoint planes");
639 
640 		if (isXChromaSubsampled(config.format) && (config.xChromaOffset == vk::VK_CHROMA_LOCATION_COSITED_EVEN) && ((features & vk::VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT) == 0))
641 			TCU_THROW(NotSupportedError, "Format doesn't support cosited chroma samples");
642 
643 		if (isXChromaSubsampled(config.format) && (config.xChromaOffset == vk::VK_CHROMA_LOCATION_MIDPOINT) && ((features & vk::VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT) == 0))
644 			TCU_THROW(NotSupportedError, "Format doesn't support midpoint chroma samples");
645 
646 		if (isYChromaSubsampled(config.format) && (config.yChromaOffset == vk::VK_CHROMA_LOCATION_COSITED_EVEN) && ((features & vk::VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT) == 0))
647 			TCU_THROW(NotSupportedError, "Format doesn't support cosited chroma samples");
648 
649 		if (isYChromaSubsampled(config.format) && (config.yChromaOffset == vk::VK_CHROMA_LOCATION_MIDPOINT) && ((features & vk::VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT) == 0))
650 			TCU_THROW(NotSupportedError, "Format doesn't support midpoint chroma samples");
651 	}
652 	catch (const vk::Error& err)
653 	{
654 		if (err.getError() == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
655 			TCU_THROW(NotSupportedError, "Format not supported");
656 
657 		throw;
658 	}
659 #endif
660 }
661 
textureConversionTest(Context & context,const TestConfig config)662 tcu::TestStatus textureConversionTest (Context& context, const TestConfig config)
663 {
664 	const std::vector<FloatFormat>	filteringPrecision		(getPrecision(config.format));
665 	const std::vector<FloatFormat>	conversionPrecision		(getPrecision(config.format));
666 	const deUint32					subTexelPrecisionBits	(vk::getPhysicalDeviceProperties(context.getInstanceInterface(), context.getPhysicalDevice()).limits.subTexelPrecisionBits);
667 	const tcu::UVec4				bitDepth				(getYCbCrBitDepth(config.format));
668 	TestLog&						log						(context.getTestContext().getLog());
669 	bool							explicitReconstruction	= config.explicitReconstruction;
670 	const UVec2						srcSize					= config.srcSize;
671 	const UVec2						dstSize					= config.dstSize;
672 	bool							isOk					= true;
673 
674 	logTestCaseInfo(log, config);
675 
676 #if !defined(FAKE_COLOR_CONVERSION)
677 	try
678 	{
679 		const vk::VkFormatProperties	properties	(vk::getPhysicalDeviceFormatProperties(context.getInstanceInterface(), context.getPhysicalDevice(), config.format));
680 		const vk::VkFormatFeatureFlags	features	(config.imageTiling == vk::VK_IMAGE_TILING_OPTIMAL
681 													? properties.optimalTilingFeatures
682 													: properties.linearTilingFeatures);
683 
684 		if ((features & vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT) != 0)
685 			explicitReconstruction = true;
686 
687 		log << TestLog::Message << "FormatFeatures: " << vk::getFormatFeatureFlagsStr(features) << TestLog::EndMessage;
688 	}
689 	catch (const vk::Error& err)
690 	{
691 		if (err.getError() == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
692 			TCU_THROW(NotSupportedError, "Format not supported");
693 
694 		throw;
695 	}
696 #endif
697 
698 	{
699 		const vk::PlanarFormatDescription	planeInfo				(vk::getPlanarFormatDescription(config.format));
700 		MultiPlaneImageData					src						(config.format, srcSize);
701 
702 		deUint32							nullAccessData			(0u);
703 		ChannelAccess						nullAccess				(tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT, 1u, IVec3(srcSize.x(), srcSize.y(), 1), IVec3(0, 0, 0), &nullAccessData, 0u);
704 		deUint32							nullAccessAlphaData		(~0u);
705 		ChannelAccess						nullAccessAlpha			(tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT, 1u, IVec3(srcSize.x(), srcSize.y(), 1), IVec3(0, 0, 0), &nullAccessAlphaData, 0u);
706 		ChannelAccess						rChannelAccess			(planeInfo.hasChannelNdx(0) ? getChannelAccess(src, planeInfo, srcSize, 0) : nullAccess);
707 		ChannelAccess						gChannelAccess			(planeInfo.hasChannelNdx(1) ? getChannelAccess(src, planeInfo, srcSize, 1) : nullAccess);
708 		ChannelAccess						bChannelAccess			(planeInfo.hasChannelNdx(2) ? getChannelAccess(src, planeInfo, srcSize, 2) : nullAccess);
709 		ChannelAccess						aChannelAccess			(planeInfo.hasChannelNdx(3) ? getChannelAccess(src, planeInfo, srcSize, 3) : nullAccessAlpha);
710 		const bool							implicitNearestCosited	((config.chromaFilter == vk::VK_FILTER_NEAREST && !config.explicitReconstruction) &&
711 																	 (config.xChromaOffset == vk::VK_CHROMA_LOCATION_COSITED_EVEN_KHR || config.yChromaOffset == vk::VK_CHROMA_LOCATION_COSITED_EVEN_KHR));
712 
713 		vector<Vec2>						sts;
714 		vector<vector<Vec4> >				results;
715 		vector<vector<Vec4> >				minBounds;
716 		vector<vector<Vec4> >				minMidpointBounds;
717 		vector<vector<Vec4> >				maxBounds;
718 		vector<vector<Vec4> >				maxMidpointBounds;
719 		vector<vector<Vec4> >				uvBounds;
720 		vector<vector<IVec4> >				ijBounds;
721 
722 		for (deUint32 planeNdx = 0; planeNdx < planeInfo.numPlanes; planeNdx++)
723 			deMemset(src.getPlanePtr(planeNdx), 0u, src.getPlaneSize(planeNdx));
724 
725 		// \todo Limit values to only values that produce defined values using selected colorRange and colorModel? The verification code handles those cases already correctly.
726 		if (planeInfo.hasChannelNdx(0))
727 		{
728 			for (int y = 0; y < rChannelAccess.getSize().y(); y++)
729 			for (int x = 0; x < rChannelAccess.getSize().x(); x++)
730 				rChannelAccess.setChannel(IVec3(x, y, 0), (float)x / (float)rChannelAccess.getSize().x());
731 		}
732 
733 		if (planeInfo.hasChannelNdx(1))
734 		{
735 			for (int y = 0; y < gChannelAccess.getSize().y(); y++)
736 			for (int x = 0; x < gChannelAccess.getSize().x(); x++)
737 				gChannelAccess.setChannel(IVec3(x, y, 0), (float)y / (float)gChannelAccess.getSize().y());
738 		}
739 
740 		if (planeInfo.hasChannelNdx(2))
741 		{
742 			for (int y = 0; y < bChannelAccess.getSize().y(); y++)
743 			for (int x = 0; x < bChannelAccess.getSize().x(); x++)
744 				bChannelAccess.setChannel(IVec3(x, y, 0), (float)(x + y) / (float)(bChannelAccess.getSize().x() + bChannelAccess.getSize().y()));
745 		}
746 
747 		if (planeInfo.hasChannelNdx(3))
748 		{
749 			for (int y = 0; y < aChannelAccess.getSize().y(); y++)
750 			for (int x = 0; x < aChannelAccess.getSize().x(); x++)
751 				aChannelAccess.setChannel(IVec3(x, y, 0), (float)(x * y) / (float)(aChannelAccess.getSize().x() * aChannelAccess.getSize().y()));
752 		}
753 
754 		if (dstSize.x() > srcSize.x() && dstSize.y() > srcSize.y())
755 			genTexCoords(sts, srcSize, dstSize);
756 		else
757 			genOneToOneTexCoords(sts, dstSize);
758 
759 		std::vector< vk::VkSamplerYcbcrModelConversion> colorModels;
760 		if (config.colorModel != vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_LAST)
761 		{
762 			colorModels.push_back(config.colorModel);
763 		}
764 		else
765 		{
766 			int ycbcrModelConverionCount = std::min( (int)vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_LAST, 4 );
767 			for (int i = 0; i < ycbcrModelConverionCount; i++)
768 			{
769 				colorModels.push_back((vk::VkSamplerYcbcrModelConversion)(vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY + i));
770 			}
771 		}
772 
773 		for (int i = 0; i < (int)colorModels.size(); i++)
774 		{
775 			vector<Vec4>				minBound;
776 			vector<Vec4>				minMidpointBound;
777 			vector<Vec4>				maxBound;
778 			vector<Vec4>				maxMidpointBound;
779 			vector<Vec4>				uvBound;
780 			vector<IVec4>				ijBound;
781 
782 			calculateBounds(rChannelAccess, gChannelAccess, bChannelAccess, aChannelAccess, bitDepth, sts, filteringPrecision, conversionPrecision, subTexelPrecisionBits, config.textureFilter, colorModels[i], config.colorRange, config.chromaFilter, config.xChromaOffset, config.yChromaOffset, config.componentMapping, explicitReconstruction, config.addressModeU, config.addressModeV, minBound, maxBound, uvBound, ijBound);
783 
784 			if (implicitNearestCosited)
785 			{
786 				calculateBounds(rChannelAccess, gChannelAccess, bChannelAccess, aChannelAccess, bitDepth, sts, filteringPrecision, conversionPrecision, subTexelPrecisionBits, config.textureFilter, colorModels[i], config.colorRange, config.chromaFilter, vk::VK_CHROMA_LOCATION_MIDPOINT_KHR, vk::VK_CHROMA_LOCATION_MIDPOINT_KHR, config.componentMapping, explicitReconstruction, config.addressModeU, config.addressModeV, minMidpointBound, maxMidpointBound, uvBound, ijBound);
787 			}
788 			results.push_back			(vector<Vec4>());
789 			minBounds.push_back			(minBound);
790 			minMidpointBounds.push_back	(minMidpointBound);
791 			maxBounds.push_back			(maxBound);
792 			maxMidpointBounds.push_back	(maxMidpointBound);
793 			uvBounds.push_back			(uvBound);
794 			ijBounds.push_back			(ijBound);
795 		}
796 
797 		if (vk::isYCbCrFormat(config.format))
798 		{
799 			tcu::TextureLevel	rImage	(tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT), rChannelAccess.getSize().x(), rChannelAccess.getSize().y());
800 			tcu::TextureLevel	gImage	(tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT), gChannelAccess.getSize().x(), gChannelAccess.getSize().y());
801 			tcu::TextureLevel	bImage	(tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT), bChannelAccess.getSize().x(), bChannelAccess.getSize().y());
802 			tcu::TextureLevel	aImage	(tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT), aChannelAccess.getSize().x(), aChannelAccess.getSize().y());
803 
804 			for (int y = 0; y < (int)rChannelAccess.getSize().y(); y++)
805 			for (int x = 0; x < (int)rChannelAccess.getSize().x(); x++)
806 				rImage.getAccess().setPixel(Vec4(rChannelAccess.getChannel(IVec3(x, y, 0))), x, y);
807 
808 			for (int y = 0; y < (int)gChannelAccess.getSize().y(); y++)
809 			for (int x = 0; x < (int)gChannelAccess.getSize().x(); x++)
810 				gImage.getAccess().setPixel(Vec4(gChannelAccess.getChannel(IVec3(x, y, 0))), x, y);
811 
812 			for (int y = 0; y < (int)bChannelAccess.getSize().y(); y++)
813 			for (int x = 0; x < (int)bChannelAccess.getSize().x(); x++)
814 				bImage.getAccess().setPixel(Vec4(bChannelAccess.getChannel(IVec3(x, y, 0))), x, y);
815 
816 			for (int y = 0; y < (int)aChannelAccess.getSize().y(); y++)
817 			for (int x = 0; x < (int)aChannelAccess.getSize().x(); x++)
818 				aImage.getAccess().setPixel(Vec4(aChannelAccess.getChannel(IVec3(x, y, 0))), x, y);
819 
820 			{
821 				const Vec4	scale	(1.0f);
822 				const Vec4	bias	(0.0f);
823 
824 				log << TestLog::Image("SourceImageR", "SourceImageR", rImage.getAccess(), scale, bias);
825 				log << TestLog::Image("SourceImageG", "SourceImageG", gImage.getAccess(), scale, bias);
826 				log << TestLog::Image("SourceImageB", "SourceImageB", bImage.getAccess(), scale, bias);
827 				log << TestLog::Image("SourceImageA", "SourceImageA", aImage.getAccess(), scale, bias);
828 			}
829 		}
830 		else
831 		{
832 			tcu::TextureLevel	srcImage	(vk::mapVkFormat(config.format), srcSize.x(), srcSize.y());
833 
834 			for (int y = 0; y < (int)srcSize.y(); y++)
835 			for (int x = 0; x < (int)srcSize.x(); x++)
836 			{
837 				const IVec3 pos (x, y, 0);
838 				srcImage.getAccess().setPixel(Vec4(rChannelAccess.getChannel(pos), gChannelAccess.getChannel(pos), bChannelAccess.getChannel(pos), aChannelAccess.getChannel(pos)), x, y);
839 			}
840 
841 			log << TestLog::Image("SourceImage", "SourceImage", srcImage.getAccess());
842 		}
843 
844 		evalShader(context, config.shaderType, src, srcSize, config.format, config.imageTiling, config.disjoint, config.textureFilter, config.addressModeU, config.addressModeV, colorModels, config.colorRange, config.xChromaOffset, config.yChromaOffset, config.chromaFilter, config.componentMapping, config.explicitReconstruction, sts, config.samplerBinding, results);
845 
846 		{
847 			std::vector<tcu::TextureLevel>	minImages;
848 			std::vector<tcu::TextureLevel>	maxImages;
849 			std::vector<tcu::TextureLevel>	minMidpointImages;
850 			std::vector<tcu::TextureLevel>	maxMidpointImages;
851 			std::vector<tcu::TextureLevel>	resImages;
852 			for (int i = 0; i < (int)colorModels.size(); i++)
853 			{
854 				minImages.push_back			(tcu::TextureLevel(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT), dstSize.x(), dstSize.y()));
855 				maxImages.push_back			(tcu::TextureLevel(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT), dstSize.x(), dstSize.y()));
856 				minMidpointImages.push_back	(tcu::TextureLevel(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT), dstSize.x(), dstSize.y()));
857 				maxMidpointImages.push_back	(tcu::TextureLevel(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT), dstSize.x(), dstSize.y()));
858 				resImages.push_back			(tcu::TextureLevel(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT), dstSize.x(), dstSize.y()));
859 			}
860 
861 			for (int i = 0; i < (int)colorModels.size(); i++)
862 			for (int y = 0; y < (int)(dstSize.y()); y++)
863 			for (int x = 0; x < (int)(dstSize.x()); x++)
864 			{
865 				const int ndx = x + y * (int)(dstSize.x());
866 				minImages[i].getAccess().setPixel(minBounds[i][ndx], x, y);
867 				maxImages[i].getAccess().setPixel(maxBounds[i][ndx], x, y);
868 			}
869 
870 			for (int i = 0; i < (int)colorModels.size(); i++)
871 			for (int y = 0; y < (int)(dstSize.y()); y++)
872 			for (int x = 0; x < (int)(dstSize.x()); x++)
873 			{
874 				const int ndx = x + y * (int)(dstSize.x());
875 				resImages[i].getAccess().setPixel(results[i][ndx], x, y);
876 			}
877 
878 			if (implicitNearestCosited)
879 			{
880 				for (int i = 0; i < (int)colorModels.size(); i++)
881 				for (int y = 0; y < (int)(dstSize.y()); y++)
882 				for (int x = 0; x < (int)(dstSize.x()); x++)
883 				{
884 					const int ndx = x + y * (int)(dstSize.x());
885 					minMidpointImages[i].getAccess().setPixel(minMidpointBounds[i][ndx], x, y);
886 					maxMidpointImages[i].getAccess().setPixel(maxMidpointBounds[i][ndx], x, y);
887 				}
888 			}
889 
890 			for (int i = 0; i < (int)colorModels.size(); i++)
891 			{
892 				const Vec4	scale	(1.0f);
893 				const Vec4	bias	(0.0f);
894 
895 				log << TestLog::Image(string("MinBoundImage_") + de::toString(i), string("MinBoundImage_") + de::toString(i), minImages[i].getAccess(), scale, bias);
896 				log << TestLog::Image(string("MaxBoundImage_") + de::toString(i), string("MaxBoundImage_") + de::toString(i), maxImages[i].getAccess(), scale, bias);
897 
898 				if (implicitNearestCosited)
899 				{
900 					log << TestLog::Image(string("MinMidpointBoundImage_") + de::toString(i), string("MinMidpointBoundImage_") + de::toString(i), minMidpointImages[i].getAccess(), scale, bias);
901 					log << TestLog::Image(string("MaxMidpointBoundImage_") + de::toString(i), string("MaxMidpointBoundImage_") + de::toString(i), maxMidpointImages[i].getAccess(), scale, bias);
902 				}
903 
904 				log << TestLog::Image(string("ResultImage_") + de::toString(i), string("ResultImage_") + de::toString(i), resImages[i].getAccess(), scale, bias);
905 			}
906 		}
907 
908 		size_t errorCount = 0;
909 
910 		for (int i = 0; i < (int)colorModels.size(); i++)
911 		for (size_t ndx = 0; ndx < sts.size(); ndx++)
912 		{
913 			bool fail;
914 			if (implicitNearestCosited)
915 			{
916 				fail = (tcu::boolAny(tcu::lessThan(results[i][ndx], minMidpointBounds[i][ndx])) || tcu::boolAny(tcu::greaterThan(results[i][ndx], maxMidpointBounds[i][ndx]))) &&
917 						(tcu::boolAny(tcu::lessThan(results[i][ndx], minBounds[i][ndx])) || tcu::boolAny(tcu::greaterThan(results[i][ndx], maxBounds[i][ndx])));
918 			}
919 			else
920 			{
921 				fail = tcu::boolAny(tcu::lessThan(results[i][ndx], minBounds[i][ndx])) || tcu::boolAny(tcu::greaterThan(results[i][ndx], maxBounds[i][ndx]));
922 			}
923 
924 			if (fail)
925 			{
926 				log << TestLog::Message << "Fail: " << i << " " << sts[ndx] << " " << results[i][ndx] << TestLog::EndMessage;
927 				log << TestLog::Message << "  Min : " << minBounds[i][ndx] << TestLog::EndMessage;
928 				log << TestLog::Message << "  Max : " << maxBounds[i][ndx] << TestLog::EndMessage;
929 				log << TestLog::Message << "  Threshold: " << (maxBounds[i][ndx] - minBounds[i][ndx]) << TestLog::EndMessage;
930 				log << TestLog::Message << "  UMin : " << uvBounds[i][ndx][0] << TestLog::EndMessage;
931 				log << TestLog::Message << "  UMax : " << uvBounds[i][ndx][1] << TestLog::EndMessage;
932 				log << TestLog::Message << "  VMin : " << uvBounds[i][ndx][2] << TestLog::EndMessage;
933 				log << TestLog::Message << "  VMax : " << uvBounds[i][ndx][3] << TestLog::EndMessage;
934 				log << TestLog::Message << "  IMin : " << ijBounds[i][ndx][0] << TestLog::EndMessage;
935 				log << TestLog::Message << "  IMax : " << ijBounds[i][ndx][1] << TestLog::EndMessage;
936 				log << TestLog::Message << "  JMin : " << ijBounds[i][ndx][2] << TestLog::EndMessage;
937 				log << TestLog::Message << "  JMax : " << ijBounds[i][ndx][3] << TestLog::EndMessage;
938 
939 				if (isXChromaSubsampled(config.format))
940 				{
941 					log << TestLog::Message << "  LumaAlphaValues : " << TestLog::EndMessage;
942 					log << TestLog::Message << "    Offset : (" << ijBounds[i][ndx][0] << ", " << ijBounds[i][ndx][2] << ")" << TestLog::EndMessage;
943 
944 					for (deInt32 k = ijBounds[i][ndx][2]; k <= ijBounds[i][ndx][3] + (config.textureFilter == vk::VK_FILTER_LINEAR ? 1 : 0); k++)
945 					{
946 						const deInt32		wrappedK	= wrap(config.addressModeV, k, gChannelAccess.getSize().y());
947 						bool				first		= true;
948 						std::ostringstream	line;
949 
950 						for (deInt32 j = ijBounds[i][ndx][0]; j <= ijBounds[i][ndx][1] + (config.textureFilter == vk::VK_FILTER_LINEAR ? 1 : 0); j++)
951 						{
952 							const deInt32	wrappedJ	= wrap(config.addressModeU, j, gChannelAccess.getSize().x());
953 
954 							if (!first)
955 							{
956 								line << ", ";
957 								first = false;
958 							}
959 
960 							line << "(" << std::setfill(' ') << std::setw(5) << gChannelAccess.getChannelUint(IVec3(wrappedJ, wrappedK, 0))
961 								<< ", " << std::setfill(' ') << std::setw(5) << aChannelAccess.getChannelUint(IVec3(wrappedJ, wrappedK, 0)) << ")";
962 						}
963 						log << TestLog::Message << "    " << line.str() << TestLog::EndMessage;
964 					}
965 
966 					{
967 						const IVec2 chromaJRange	(divFloor(ijBounds[i][ndx][0], 2) - 1, divFloor(ijBounds[i][ndx][1] + (config.textureFilter == vk::VK_FILTER_LINEAR ? 1 : 0), 2) + 1);
968 						const IVec2 chromaKRange	(isYChromaSubsampled(config.format)
969 													? IVec2(divFloor(ijBounds[i][ndx][2], 2) - 1, divFloor(ijBounds[i][ndx][3] + (config.textureFilter == vk::VK_FILTER_LINEAR ? 1 : 0), 2) + 1)
970 													: IVec2(ijBounds[i][ndx][2], ijBounds[i][ndx][3] + (config.textureFilter == vk::VK_FILTER_LINEAR ? 1 : 0)));
971 
972 						log << TestLog::Message << "  ChromaValues : " << TestLog::EndMessage;
973 						log << TestLog::Message << "    Offset : (" << chromaJRange[0] << ", " << chromaKRange[0] << ")" << TestLog::EndMessage;
974 
975 						for (deInt32 k = chromaKRange[0]; k <= chromaKRange[1]; k++)
976 						{
977 							const deInt32		wrappedK	= wrap(config.addressModeV, k, rChannelAccess.getSize().y());
978 							bool				first		= true;
979 							std::ostringstream	line;
980 
981 							for (deInt32 j = chromaJRange[0]; j <= chromaJRange[1]; j++)
982 							{
983 								const deInt32	wrappedJ	= wrap(config.addressModeU, j, rChannelAccess.getSize().x());
984 
985 								if (!first)
986 								{
987 									line << ", ";
988 									first = false;
989 								}
990 
991 								line << "(" << std::setfill(' ') << std::setw(5) << rChannelAccess.getChannelUint(IVec3(wrappedJ, wrappedK, 0))
992 									<< ", " << std::setfill(' ') << std::setw(5) << bChannelAccess.getChannelUint(IVec3(wrappedJ, wrappedK, 0)) << ")";
993 							}
994 							log << TestLog::Message << "    " << line.str() << TestLog::EndMessage;
995 						}
996 					}
997 				}
998 				else
999 				{
1000 					log << TestLog::Message << "  Values : " << TestLog::EndMessage;
1001 					log << TestLog::Message << "    Offset : (" << ijBounds[i][ndx][0] << ", " << ijBounds[i][ndx][2] << ")" << TestLog::EndMessage;
1002 
1003 					for (deInt32 k = ijBounds[i][ndx][2]; k <= ijBounds[i][ndx][3] + (config.textureFilter == vk::VK_FILTER_LINEAR ? 1 : 0); k++)
1004 					{
1005 						const deInt32		wrappedK	= wrap(config.addressModeV, k, rChannelAccess.getSize().y());
1006 						bool				first		= true;
1007 						std::ostringstream	line;
1008 
1009 						for (deInt32 j = ijBounds[i][ndx][0]; j <= ijBounds[i][ndx][1] + (config.textureFilter == vk::VK_FILTER_LINEAR ? 1 : 0); j++)
1010 						{
1011 							const deInt32	wrappedJ	= wrap(config.addressModeU, j, rChannelAccess.getSize().x());
1012 
1013 							if (!first)
1014 							{
1015 								line << ", ";
1016 								first = false;
1017 							}
1018 
1019 							line << "(" << std::setfill(' ') << std::setw(5) << rChannelAccess.getChannelUint(IVec3(wrappedJ, wrappedK, 0))
1020 								<< ", " << std::setfill(' ') << std::setw(5) << gChannelAccess.getChannelUint(IVec3(wrappedJ, wrappedK, 0))
1021 								<< ", " << std::setfill(' ') << std::setw(5) << bChannelAccess.getChannelUint(IVec3(wrappedJ, wrappedK, 0))
1022 								<< ", " << std::setfill(' ') << std::setw(5) << aChannelAccess.getChannelUint(IVec3(wrappedJ, wrappedK, 0)) << ")";
1023 						}
1024 						log << TestLog::Message << "    " << line.str() << TestLog::EndMessage;
1025 					}
1026 				}
1027 
1028 				errorCount++;
1029 				isOk = false;
1030 
1031 				if (errorCount > 30)
1032 				{
1033 					log << TestLog::Message << "Encountered " << errorCount << " errors. Omitting rest of the per result logs." << TestLog::EndMessage;
1034 					break;
1035 				}
1036 			}
1037 		}
1038 	}
1039 
1040 	if (isOk)
1041 		return tcu::TestStatus::pass("Pass");
1042 	else
1043 		return tcu::TestStatus::fail("Result comparison failed");
1044 }
1045 
1046 #if defined(FAKE_COLOR_CONVERSION)
swizzleToCompName(const char * identity,vk::VkComponentSwizzle swizzle)1047 const char* swizzleToCompName (const char* identity, vk::VkComponentSwizzle swizzle)
1048 {
1049 	switch (swizzle)
1050 	{
1051 		case vk::VK_COMPONENT_SWIZZLE_IDENTITY:	return identity;
1052 		case vk::VK_COMPONENT_SWIZZLE_R:		return "r";
1053 		case vk::VK_COMPONENT_SWIZZLE_G:		return "g";
1054 		case vk::VK_COMPONENT_SWIZZLE_B:		return "b";
1055 		case vk::VK_COMPONENT_SWIZZLE_A:		return "a";
1056 		default:
1057 			DE_FATAL("Unsupported swizzle");
1058 			return DE_NULL;
1059 	}
1060 }
1061 #endif
1062 
createTestShaders(vk::SourceCollections & dst,TestConfig config)1063 void createTestShaders (vk::SourceCollections& dst, TestConfig config)
1064 {
1065 	std::vector< vk::VkSamplerYcbcrModelConversion> colorModels;
1066 	if (config.colorModel != vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_LAST)
1067 	{
1068 		colorModels.push_back(config.colorModel);
1069 	}
1070 	else
1071 	{
1072 		int ycbcrModelConverionCount = std::min((int)vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_LAST, 4);
1073 		for (int i = 0; i < ycbcrModelConverionCount; i++)
1074 		{
1075 			colorModels.push_back((vk::VkSamplerYcbcrModelConversion)(vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY + i));
1076 		}
1077 	}
1078 #if !defined(FAKE_COLOR_CONVERSION)
1079 	const ShaderSpec spec (createShaderSpec(config.samplerBinding, colorModels));
1080 
1081 	generateSources(config.shaderType, spec, dst);
1082 #else
1083 	const tcu::UVec4	bits	(getYCbCrBitDepth(config.format));
1084 	ShaderSpec			spec;
1085 
1086 	spec.globalDeclarations = "layout(set=" + de::toString((int)EXTRA_RESOURCES_DESCRIPTOR_SET_INDEX) + ", binding=" + de::toString(config.samplerBinding) + ") uniform highp sampler2D u_sampler;";
1087 
1088 	spec.inputs.push_back(Symbol("uv", glu::VarType(glu::TYPE_FLOAT_VEC2, glu::PRECISION_HIGHP)));
1089 	spec.outputs.push_back(Symbol("o_color", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
1090 
1091 	std::ostringstream	source;
1092 
1093 	source << "highp vec4 inputColor = texture(u_sampler, uv);\n";
1094 
1095 	source << "highp float r = inputColor." << swizzleToCompName("r", config.componentMapping.r) << ";\n";
1096 	source << "highp float g = inputColor." << swizzleToCompName("g", config.componentMapping.g) << ";\n";
1097 	source << "highp float b = inputColor." << swizzleToCompName("b", config.componentMapping.b) << ";\n";
1098 	source << "highp float a = inputColor." << swizzleToCompName("a", config.componentMapping.a) << ";\n";
1099 
1100 	switch (config.colorRange)
1101 	{
1102 		case vk::VK_SAMPLER_YCBCR_RANGE_ITU_FULL:
1103 			source << "highp float cr = r - (float(" << (0x1u << (bits[0] - 0x1u)) << ") / float(" << ((0x1u << bits[0]) - 1u) << "));\n";
1104 			source << "highp float y  = g;\n";
1105 			source << "highp float cb = b - (float(" << (0x1u << (bits[2] - 0x1u)) << ") / float(" << ((0x1u << bits[2]) - 1u) << "));\n";
1106 			break;
1107 
1108 		case vk::VK_SAMPLER_YCBCR_RANGE_ITU_NARROW:
1109 			source << "highp float cr = (r * float(" << ((0x1u << bits[0]) - 1u) << ") - float(" << (128u * (0x1u << (bits[0] - 8))) << ")) / float(" << (224u * (0x1u << (bits[0] - 8))) << ");\n";
1110 			source << "highp float y  = (g * float(" << ((0x1u << bits[1]) - 1u) << ") - float(" << (16u * (0x1u << (bits[1] - 8))) << ")) / float(" << (219u * (0x1u << (bits[1] - 8))) << ");\n";
1111 			source << "highp float cb = (b * float(" << ((0x1u << bits[2]) - 1u) << ") - float(" << (128u * (0x1u << (bits[2] - 8))) << ")) / float(" << (224u * (0x1u << (bits[2] - 8))) << ");\n";
1112 			break;
1113 
1114 		default:
1115 			DE_FATAL("Unknown color range");
1116 	}
1117 
1118 	source << "highp vec4 color;\n";
1119 
1120 	switch (config.colorModel)
1121 	{
1122 		case vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY:
1123 			source << "color = vec4(r, g, b, a);\n";
1124 			break;
1125 
1126 		case vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY:
1127 			source << "color = vec4(cr, y, cb, a);\n";
1128 			break;
1129 
1130 		case vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601:
1131 			source << "color = vec4(y + 1.402 * cr, y - float(" << (0.202008 / 0.587) << ") * cb - float(" << (0.419198 / 0.587) << ") * cr, y + 1.772 * cb, a);\n";
1132 			break;
1133 
1134 		case vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709:
1135 			source << "color = vec4(y + 1.5748 * cr, y - float(" << (0.13397432 / 0.7152) << ") * cb - float(" << (0.33480248 / 0.7152) << ") * cr, y + 1.8556 * cb, a);\n";
1136 			break;
1137 
1138 		case vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020:
1139 			source << "color = vec4(y + 1.4746 * cr, (y - float(" << (0.11156702 / 0.6780) << ") * cb) - float(" << (0.38737742 / 0.6780) << ") * cr, y + 1.8814 * cb, a);\n";
1140 			break;
1141 
1142 		default:
1143 			DE_FATAL("Unknown color model");
1144 	};
1145 
1146 	source << "o_color = color;\n";
1147 
1148 	spec.source = source.str();
1149 	generateSources(config.shaderType, spec, dst);
1150 #endif
1151 }
1152 
1153 struct RangeNamePair
1154 {
1155 	const char*					name;
1156 	vk::VkSamplerYcbcrRange		value;
1157 };
1158 
1159 
1160 struct ChromaLocationNamePair
1161 {
1162 	const char*					name;
1163 	vk::VkChromaLocation		value;
1164 };
1165 
1166 // Alternate between swizzle_identity and their equivalents. Both should work.
getIdentitySwizzle(void)1167 const vk::VkComponentMapping& getIdentitySwizzle (void)
1168 {
1169 	static bool alternate = false;
1170 	static const vk::VkComponentMapping mappingA = { vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY };
1171 	static const vk::VkComponentMapping mappingB = { vk::VK_COMPONENT_SWIZZLE_R, vk::VK_COMPONENT_SWIZZLE_G, vk::VK_COMPONENT_SWIZZLE_B, vk::VK_COMPONENT_SWIZZLE_A };
1172 
1173 	const vk::VkComponentMapping& mapping = (alternate ? mappingB : mappingA);
1174 	alternate = (!alternate);
1175 	return mapping;
1176 }
1177 
1178 struct YCbCrConversionTestBuilder
1179 {
1180 	const std::vector<vk::VkFormat> noChromaSubsampledFormats =
1181 	{
1182 		vk::VK_FORMAT_R4G4B4A4_UNORM_PACK16,
1183 		vk::VK_FORMAT_B4G4R4A4_UNORM_PACK16,
1184 		vk::VK_FORMAT_R5G6B5_UNORM_PACK16,
1185 		vk::VK_FORMAT_B5G6R5_UNORM_PACK16,
1186 		vk::VK_FORMAT_R5G5B5A1_UNORM_PACK16,
1187 		vk::VK_FORMAT_B5G5R5A1_UNORM_PACK16,
1188 		vk::VK_FORMAT_A1R5G5B5_UNORM_PACK16,
1189 		vk::VK_FORMAT_R8G8B8_UNORM,
1190 		vk::VK_FORMAT_B8G8R8_UNORM,
1191 		vk::VK_FORMAT_R8G8B8A8_UNORM,
1192 		vk::VK_FORMAT_B8G8R8A8_UNORM,
1193 		vk::VK_FORMAT_A8B8G8R8_UNORM_PACK32,
1194 		vk::VK_FORMAT_A2R10G10B10_UNORM_PACK32,
1195 		vk::VK_FORMAT_A2B10G10R10_UNORM_PACK32,
1196 		vk::VK_FORMAT_R16G16B16_UNORM,
1197 		vk::VK_FORMAT_R16G16B16A16_UNORM,
1198 		vk::VK_FORMAT_R10X6_UNORM_PACK16,
1199 		vk::VK_FORMAT_R10X6G10X6_UNORM_2PACK16,
1200 		vk::VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
1201 		vk::VK_FORMAT_R12X4_UNORM_PACK16,
1202 		vk::VK_FORMAT_R12X4G12X4_UNORM_2PACK16,
1203 		vk::VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16,
1204 		vk::VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM,
1205 		vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16,
1206 		vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16,
1207 		vk::VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM,
1208 		vk::VK_FORMAT_G8_B8R8_2PLANE_444_UNORM_EXT,
1209 		vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16_EXT,
1210 		vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16_EXT,
1211 		vk::VK_FORMAT_G16_B16R16_2PLANE_444_UNORM_EXT,
1212 	};
1213 	const std::vector<vk::VkFormat> xChromaSubsampledFormats =
1214 	{
1215 		vk::VK_FORMAT_G8B8G8R8_422_UNORM,
1216 		vk::VK_FORMAT_B8G8R8G8_422_UNORM,
1217 		vk::VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM,
1218 		vk::VK_FORMAT_G8_B8R8_2PLANE_422_UNORM,
1219 
1220 		vk::VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16,
1221 		vk::VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16,
1222 		vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16,
1223 		vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16,
1224 		vk::VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16,
1225 		vk::VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16,
1226 		vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16,
1227 		vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16,
1228 		vk::VK_FORMAT_G16B16G16R16_422_UNORM,
1229 		vk::VK_FORMAT_B16G16R16G16_422_UNORM,
1230 		vk::VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM,
1231 		vk::VK_FORMAT_G16_B16R16_2PLANE_422_UNORM,
1232 	};
1233 	const std::vector<vk::VkFormat> xyChromaSubsampledFormats =
1234 	{
1235 		vk::VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM,
1236 		vk::VK_FORMAT_G8_B8R8_2PLANE_420_UNORM,
1237 		vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16,
1238 		vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16,
1239 		vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16,
1240 		vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16,
1241 		vk::VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM,
1242 		vk::VK_FORMAT_G16_B16R16_2PLANE_420_UNORM,
1243 	};
1244 	struct ColorModelStruct
1245 	{
1246 		const char* const							name;
1247 		const vk::VkSamplerYcbcrModelConversion	value;
1248 	};
1249 	const std::vector<ColorModelStruct> colorModels =
1250 	{
1251 		{ "rgb_identity",	vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY		},
1252 		{ "ycbcr_identity",	vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY	},
1253 		{ "ycbcr_709",		vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709			},
1254 		{ "ycbcr_601",		vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601			},
1255 		{ "ycbcr_2020",		vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020		}
1256 	};
1257 	const std::vector<RangeNamePair> colorRanges =
1258 	{
1259 		{ "itu_full",		vk::VK_SAMPLER_YCBCR_RANGE_ITU_FULL		},
1260 		{ "itu_narrow",		vk::VK_SAMPLER_YCBCR_RANGE_ITU_NARROW	}
1261 	};
1262 	const std::vector<ChromaLocationNamePair> chromaLocations =
1263 	{
1264 		{ "cosited",		vk::VK_CHROMA_LOCATION_COSITED_EVEN	},
1265 		{ "midpoint",		vk::VK_CHROMA_LOCATION_MIDPOINT		}
1266 	};
1267 	struct TextureFilterStruct
1268 	{
1269 		const char* const	name;
1270 		vk::VkFilter		value;
1271 	};
1272 	const std::vector<TextureFilterStruct> textureFilters =
1273 	{
1274 		{ "linear",			vk::VK_FILTER_LINEAR	},
1275 		{ "nearest",		vk::VK_FILTER_NEAREST	}
1276 	};
1277 	// Used by the chroma reconstruction tests
1278 	const vk::VkSamplerYcbcrModelConversion		defaultColorModel		= vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY;
1279 	const vk::VkSamplerYcbcrRange				defaultColorRange		= vk::VK_SAMPLER_YCBCR_RANGE_ITU_FULL;
1280 	const vk::VkComponentMapping				swappedChromaSwizzle	=
1281 	{
1282 		vk::VK_COMPONENT_SWIZZLE_B,
1283 		vk::VK_COMPONENT_SWIZZLE_IDENTITY,
1284 		vk::VK_COMPONENT_SWIZZLE_R,
1285 		vk::VK_COMPONENT_SWIZZLE_IDENTITY
1286 	};
1287 	const std::vector<glu::ShaderType> shaderTypes =
1288 	{
1289 		glu::SHADERTYPE_VERTEX,
1290 		glu::SHADERTYPE_FRAGMENT,
1291 		glu::SHADERTYPE_COMPUTE
1292 	};
1293 	struct ImageTilingStruct
1294 	{
1295 		const char*			name;
1296 		vk::VkImageTiling	value;
1297 	};
1298 	const std::vector<ImageTilingStruct> imageTilings =
1299 	{
1300 		{ "tiling_linear",	vk::VK_IMAGE_TILING_LINEAR },
1301 		{ "tiling_optimal",	vk::VK_IMAGE_TILING_OPTIMAL }
1302 	};
1303 	struct SamplerBindingStruct
1304 	{
1305 		const char*			name;
1306 		deUint32			value;
1307 	};
1308 	const std::vector<SamplerBindingStruct> samplerBindings =
1309 	{
1310 		{ "binding_0",		0	},
1311 		{ "binding_7",		7	},
1312 		{ "binding_15",		15	},
1313 		{ "binding_31",		31	}
1314 	};
1315 
buildTestsvkt::ycbcr::__anon548eae410111::YCbCrConversionTestBuilder1316 	void buildTests(tcu::TestCaseGroup* testGroup)
1317 	{
1318 		tcu::TestContext&							testCtx(testGroup->getTestContext());
1319 		de::Random									rng(1978765638u);
1320 
1321 		// Test formats without chroma reconstruction
1322 		for (size_t formatNdx = 0; formatNdx < noChromaSubsampledFormats.size(); formatNdx++)
1323 		{
1324 			const vk::VkFormat						format(noChromaSubsampledFormats[formatNdx]);
1325 			const std::string						formatName(de::toLower(std::string(getFormatName(format)).substr(10)));
1326 			de::MovePtr<tcu::TestCaseGroup>			formatGroup(new tcu::TestCaseGroup(testCtx, formatName.c_str(), ("Tests for color conversion using format " + formatName).c_str()));
1327 			const UVec2								srcSize(isXChromaSubsampled(format) ? 12 : 7,
1328 				isYChromaSubsampled(format) ? 8 : 13);
1329 			const UVec2								dstSize(srcSize.x() + srcSize.x() / 2,
1330 				srcSize.y() + srcSize.y() / 2);
1331 
1332 			for (size_t modelNdx = 0; modelNdx < colorModels.size(); modelNdx++)
1333 			{
1334 				const char* const						colorModelName(colorModels[modelNdx].name);
1335 				const vk::VkSamplerYcbcrModelConversion	colorModel(colorModels[modelNdx].value);
1336 
1337 				if (colorModel != vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY && getYCbCrFormatChannelCount(format) < 3)
1338 					continue;
1339 
1340 				de::MovePtr<tcu::TestCaseGroup>			colorModelGroup(new tcu::TestCaseGroup(testCtx, colorModelName, ("Tests for color model " + string(colorModelName)).c_str()));
1341 
1342 				if (colorModel == vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY)
1343 				{
1344 					for (size_t textureFilterNdx = 0; textureFilterNdx < textureFilters.size(); textureFilterNdx++)
1345 					{
1346 						const char* const					textureFilterName(textureFilters[textureFilterNdx].name);
1347 						const vk::VkFilter					textureFilter(textureFilters[textureFilterNdx].value);
1348 
1349 						for (size_t tilingNdx = 0; tilingNdx < imageTilings.size(); tilingNdx++)
1350 						{
1351 							const vk::VkImageTiling			tiling(imageTilings[tilingNdx].value);
1352 							const char* const				tilingName(imageTilings[tilingNdx].name);
1353 							const glu::ShaderType			shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1354 							const vk::VkSamplerYcbcrRange	colorRange(rng.choose<RangeNamePair>(begin(colorRanges), end(colorRanges)).value);
1355 							const vk::VkChromaLocation		chromaLocation(rng.choose<ChromaLocationNamePair>(begin(chromaLocations), end(chromaLocations)).value);
1356 
1357 							for (size_t bindingNdx = 0; bindingNdx < samplerBindings.size(); bindingNdx++)
1358 							{
1359 								const deUint32					samplerBinding(samplerBindings[bindingNdx].value);
1360 								string							samplerBindingName((samplerBindings[bindingNdx].value != 0) ? string("_") + samplerBindings[bindingNdx].name : string());
1361 								const TestConfig				config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1362 									textureFilter, chromaLocation, chromaLocation, false, false,
1363 									colorRange, colorModel, getIdentitySwizzle(), srcSize, dstSize, samplerBinding);
1364 
1365 								addFunctionCaseWithPrograms(colorModelGroup.get(), std::string(textureFilterName) + "_" + tilingName + samplerBindingName, "", checkSupport, createTestShaders, textureConversionTest, config);
1366 							}
1367 						}
1368 					}
1369 				}
1370 				else
1371 				{
1372 					for (size_t rangeNdx = 0; rangeNdx < colorRanges.size(); rangeNdx++)
1373 					{
1374 						const char* const				colorRangeName(colorRanges[rangeNdx].name);
1375 						const vk::VkSamplerYcbcrRange	colorRange(colorRanges[rangeNdx].value);
1376 
1377 						// Narrow range doesn't really work with formats that have less than 8 bits
1378 						if (colorRange == vk::VK_SAMPLER_YCBCR_RANGE_ITU_NARROW)
1379 						{
1380 							const UVec4					bitDepth(getYCbCrBitDepth(format));
1381 
1382 							if (bitDepth[0] < 8 || bitDepth[1] < 8 || bitDepth[2] < 8)
1383 								continue;
1384 						}
1385 
1386 						de::MovePtr<tcu::TestCaseGroup>		colorRangeGroup(new tcu::TestCaseGroup(testCtx, colorRangeName, ("Tests for color range " + string(colorRangeName)).c_str()));
1387 
1388 						for (size_t textureFilterNdx = 0; textureFilterNdx < textureFilters.size(); textureFilterNdx++)
1389 						{
1390 							const char* const				textureFilterName(textureFilters[textureFilterNdx].name);
1391 							const vk::VkFilter				textureFilter(textureFilters[textureFilterNdx].value);
1392 
1393 							for (size_t tilingNdx = 0; tilingNdx < imageTilings.size(); tilingNdx++)
1394 							{
1395 								const vk::VkImageTiling		tiling(imageTilings[tilingNdx].value);
1396 								const char* const			tilingName(imageTilings[tilingNdx].name);
1397 								const glu::ShaderType		shaderType(rng.choose<glu::ShaderType>(shaderTypes.begin(), shaderTypes.end()));
1398 								const vk::VkChromaLocation	chromaLocation(rng.choose<ChromaLocationNamePair>(chromaLocations.begin(), chromaLocations.end()).value);
1399 								for (size_t bindingNdx = 0; bindingNdx < samplerBindings.size(); bindingNdx++)								{
1400 									const deUint32				samplerBinding(samplerBindings[bindingNdx].value);
1401 									string						samplerBindingName((samplerBindings[bindingNdx].value != 0) ? string("_") + samplerBindings[bindingNdx].name : string());
1402 									const TestConfig			config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1403 										textureFilter, chromaLocation, chromaLocation, false, false,
1404 										colorRange, colorModel, getIdentitySwizzle(), srcSize, dstSize, samplerBinding);
1405 
1406 									addFunctionCaseWithPrograms(colorRangeGroup.get(), std::string(textureFilterName) + "_" + tilingName + samplerBindingName, "", checkSupport, createTestShaders, textureConversionTest, config);
1407 								}
1408 							}
1409 						}
1410 
1411 						colorModelGroup->addChild(colorRangeGroup.release());
1412 					}
1413 				}
1414 
1415 				formatGroup->addChild(colorModelGroup.release());
1416 			}
1417 
1418 			// Color conversion tests for array of samplers ( noChromaSubsampledFormats )
1419 			if (getYCbCrFormatChannelCount(format) >= 3)
1420 				buildArrayOfSamplersTests(format, srcSize, dstSize, formatGroup, testCtx, rng);
1421 
1422 			testGroup->addChild(formatGroup.release());
1423 		}
1424 
1425 		// Test formats with x chroma reconstruction
1426 		for (size_t formatNdx = 0; formatNdx < xChromaSubsampledFormats.size(); formatNdx++)
1427 		{
1428 			const vk::VkFormat				format(xChromaSubsampledFormats[formatNdx]);
1429 			const std::string				formatName(de::toLower(std::string(getFormatName(format)).substr(10)));
1430 			de::MovePtr<tcu::TestCaseGroup>	formatGroup(new tcu::TestCaseGroup(testCtx, formatName.c_str(), ("Tests for color conversion using format " + formatName).c_str()));
1431 			const UVec2						srcSize(isXChromaSubsampled(format) ? 12 : 7,
1432 				isYChromaSubsampled(format) ? 8 : 13);
1433 			const UVec2						dstSize(srcSize.x() + srcSize.x() / 2,
1434 				srcSize.y() + srcSize.y() / 2);
1435 
1436 			// Color conversion tests
1437 			{
1438 				de::MovePtr<tcu::TestCaseGroup>	conversionGroup(new tcu::TestCaseGroup(testCtx, "color_conversion", ""));
1439 
1440 				for (size_t xChromaOffsetNdx = 0; xChromaOffsetNdx < chromaLocations.size(); xChromaOffsetNdx++)
1441 				{
1442 					const char* const			xChromaOffsetName(chromaLocations[xChromaOffsetNdx].name);
1443 					const vk::VkChromaLocation	xChromaOffset(chromaLocations[xChromaOffsetNdx].value);
1444 
1445 					for (size_t modelNdx = 0; modelNdx < colorModels.size(); modelNdx++)
1446 					{
1447 						const char* const						colorModelName(colorModels[modelNdx].name);
1448 						const vk::VkSamplerYcbcrModelConversion	colorModel(colorModels[modelNdx].value);
1449 
1450 						if (colorModel != vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY && getYCbCrFormatChannelCount(format) < 3)
1451 							continue;
1452 
1453 
1454 						if (colorModel == vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY)
1455 						{
1456 							for (size_t tilingNdx = 0; tilingNdx < imageTilings.size(); tilingNdx++)
1457 							{
1458 								const vk::VkImageTiling			tiling(imageTilings[tilingNdx].value);
1459 								const char* const				tilingName(imageTilings[tilingNdx].name);
1460 								const vk::VkSamplerYcbcrRange	colorRange(rng.choose<RangeNamePair>(begin(colorRanges), end(colorRanges)).value);
1461 								const glu::ShaderType			shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1462 								const vk::VkChromaLocation		yChromaOffset(rng.choose<ChromaLocationNamePair>(begin(chromaLocations), end(chromaLocations)).value);
1463 								for (size_t bindingNdx = 0; bindingNdx < samplerBindings.size(); bindingNdx++)
1464 								{
1465 									const deUint32					samplerBinding(samplerBindings[bindingNdx].value);
1466 									string							samplerBindingName((samplerBindings[bindingNdx].value != 0) ? string("_") + samplerBindings[bindingNdx].name : string());
1467 									const TestConfig				config(shaderType, format, tiling, vk::VK_FILTER_NEAREST, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1468 										vk::VK_FILTER_NEAREST, xChromaOffset, yChromaOffset, false, false,
1469 										colorRange, colorModel, getIdentitySwizzle(), srcSize, dstSize, samplerBinding);
1470 
1471 									addFunctionCaseWithPrograms(conversionGroup.get(), string(colorModelName) + "_" + tilingName + "_" + xChromaOffsetName + samplerBindingName, "", checkSupport, createTestShaders, textureConversionTest, config);
1472 								}
1473 							}
1474 						}
1475 						else
1476 						{
1477 							for (size_t rangeNdx = 0; rangeNdx < colorRanges.size(); rangeNdx++)
1478 							{
1479 								const char* const				colorRangeName(colorRanges[rangeNdx].name);
1480 								const vk::VkSamplerYcbcrRange	colorRange(colorRanges[rangeNdx].value);
1481 
1482 								// Narrow range doesn't really work with formats that have less than 8 bits
1483 								if (colorRange == vk::VK_SAMPLER_YCBCR_RANGE_ITU_NARROW)
1484 								{
1485 									const UVec4					bitDepth(getYCbCrBitDepth(format));
1486 
1487 									if (bitDepth[0] < 8 || bitDepth[1] < 8 || bitDepth[2] < 8)
1488 										continue;
1489 								}
1490 
1491 								for (size_t tilingNdx = 0; tilingNdx < imageTilings.size(); tilingNdx++)
1492 								{
1493 									const vk::VkImageTiling		tiling(imageTilings[tilingNdx].value);
1494 									const char* const			tilingName(imageTilings[tilingNdx].name);
1495 									const glu::ShaderType		shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1496 									const vk::VkChromaLocation	yChromaOffset(rng.choose<ChromaLocationNamePair>(begin(chromaLocations), end(chromaLocations)).value);
1497 									for (size_t bindingNdx = 0; bindingNdx < samplerBindings.size(); bindingNdx++)
1498 									{
1499 										const deUint32				samplerBinding(samplerBindings[bindingNdx].value);
1500 										string						samplerBindingName((samplerBindings[bindingNdx].value != 0) ? string("_") + samplerBindings[bindingNdx].name : string());
1501 										const TestConfig			config(shaderType, format, tiling, vk::VK_FILTER_NEAREST, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1502 											vk::VK_FILTER_NEAREST, xChromaOffset, yChromaOffset, false, false,
1503 											colorRange, colorModel, getIdentitySwizzle(), srcSize, dstSize, samplerBinding);
1504 
1505 										addFunctionCaseWithPrograms(conversionGroup.get(), string(colorModelName) + "_" + colorRangeName + "_" + tilingName + "_" + xChromaOffsetName + samplerBindingName, "", checkSupport, createTestShaders, textureConversionTest, config);
1506 									}
1507 								}
1508 							}
1509 						}
1510 					}
1511 				}
1512 
1513 				formatGroup->addChild(conversionGroup.release());
1514 			}
1515 
1516 			// Color conversion tests for array of samplers ( xChromaSubsampledFormats )
1517 			if (getYCbCrFormatChannelCount(format) >= 3)
1518 				buildArrayOfSamplersTests(format, srcSize, dstSize, formatGroup, testCtx, rng);
1519 
1520 			// Chroma reconstruction tests
1521 			{
1522 				de::MovePtr<tcu::TestCaseGroup>	reconstrucGroup(new tcu::TestCaseGroup(testCtx, "chroma_reconstruction", ""));
1523 
1524 				for (size_t textureFilterNdx = 0; textureFilterNdx < textureFilters.size(); textureFilterNdx++)
1525 				{
1526 					const char* const				textureFilterName(textureFilters[textureFilterNdx].name);
1527 					const vk::VkFilter				textureFilter(textureFilters[textureFilterNdx].value);
1528 					de::MovePtr<tcu::TestCaseGroup>	textureFilterGroup(new tcu::TestCaseGroup(testCtx, textureFilterName, textureFilterName));
1529 
1530 					for (size_t explicitReconstructionNdx = 0; explicitReconstructionNdx < 2; explicitReconstructionNdx++)
1531 					{
1532 						const bool	explicitReconstruction(explicitReconstructionNdx == 1);
1533 
1534 						for (size_t disjointNdx = 0; disjointNdx < 2; disjointNdx++)
1535 						{
1536 							const bool	disjoint(disjointNdx == 1);
1537 
1538 							for (size_t xChromaOffsetNdx = 0; xChromaOffsetNdx < chromaLocations.size(); xChromaOffsetNdx++)
1539 							{
1540 								const vk::VkChromaLocation		xChromaOffset(chromaLocations[xChromaOffsetNdx].value);
1541 								const char* const				xChromaOffsetName(chromaLocations[xChromaOffsetNdx].name);
1542 
1543 								for (size_t tilingNdx = 0; tilingNdx < imageTilings.size(); tilingNdx++)
1544 								{
1545 									const vk::VkImageTiling		tiling(imageTilings[tilingNdx].value);
1546 									const char* const			tilingName(imageTilings[tilingNdx].name);
1547 
1548 									{
1549 										const glu::ShaderType			shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1550 										const vk::VkChromaLocation		yChromaOffset(rng.choose<ChromaLocationNamePair>(begin(chromaLocations), end(chromaLocations)).value);
1551 										const TestConfig				config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1552 											vk::VK_FILTER_LINEAR, xChromaOffset, yChromaOffset, explicitReconstruction, disjoint,
1553 											defaultColorRange, defaultColorModel, getIdentitySwizzle(), srcSize, dstSize, 0);
1554 
1555 										addFunctionCaseWithPrograms(textureFilterGroup.get(), string(explicitReconstruction ? "explicit_linear_" : "default_linear_") + xChromaOffsetName + "_" + tilingName + (disjoint ? "_disjoint" : ""), "", checkSupport, createTestShaders, textureConversionTest, config);
1556 									}
1557 
1558 									{
1559 										const glu::ShaderType			shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1560 										const vk::VkChromaLocation		yChromaOffset(rng.choose<ChromaLocationNamePair>(begin(chromaLocations), end(chromaLocations)).value);
1561 										const TestConfig				config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1562 											vk::VK_FILTER_LINEAR, xChromaOffset, yChromaOffset, explicitReconstruction, disjoint,
1563 											defaultColorRange, defaultColorModel, swappedChromaSwizzle, srcSize, dstSize, 0);
1564 
1565 										addFunctionCaseWithPrograms(textureFilterGroup.get(), string(explicitReconstruction ? "explicit_linear_" : "default_linear_") + xChromaOffsetName + "_" + tilingName + (disjoint ? "_disjoint" : "") + "_swapped_chroma", "", checkSupport, createTestShaders, textureConversionTest, config);
1566 									}
1567 
1568 									if (!explicitReconstruction)
1569 									{
1570 										{
1571 											const glu::ShaderType			shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1572 											const vk::VkChromaLocation		yChromaOffset(rng.choose<ChromaLocationNamePair>(begin(chromaLocations), end(chromaLocations)).value);
1573 											const TestConfig				config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1574 												vk::VK_FILTER_NEAREST, xChromaOffset, yChromaOffset, explicitReconstruction, disjoint,
1575 												defaultColorRange, defaultColorModel, getIdentitySwizzle(), srcSize, dstSize, 0);
1576 
1577 											addFunctionCaseWithPrograms(textureFilterGroup.get(), string("default_nearest_") + xChromaOffsetName + "_" + tilingName + (disjoint ? "_disjoint" : ""), "", checkSupport, createTestShaders, textureConversionTest, config);
1578 										}
1579 
1580 										{
1581 											const glu::ShaderType			shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1582 											const vk::VkChromaLocation		yChromaOffset(rng.choose<ChromaLocationNamePair>(begin(chromaLocations), end(chromaLocations)).value);
1583 											const TestConfig				config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1584 												vk::VK_FILTER_NEAREST, xChromaOffset, yChromaOffset, explicitReconstruction, disjoint,
1585 												defaultColorRange, defaultColorModel, swappedChromaSwizzle, srcSize, dstSize, 0);
1586 
1587 											addFunctionCaseWithPrograms(textureFilterGroup.get(), string("default_nearest_") + xChromaOffsetName + "_" + tilingName + (disjoint ? "_disjoint" : "") + "_swapped_chroma", "", checkSupport, createTestShaders, textureConversionTest, config);
1588 										}
1589 									}
1590 								}
1591 							}
1592 
1593 							if (explicitReconstruction)
1594 							{
1595 								for (size_t tilingNdx = 0; tilingNdx < imageTilings.size(); tilingNdx++)
1596 								{
1597 									const vk::VkImageTiling	tiling(imageTilings[tilingNdx].value);
1598 									const char* const		tilingName(imageTilings[tilingNdx].name);
1599 									{
1600 										const glu::ShaderType			shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1601 										const vk::VkChromaLocation		chromaLocation(rng.choose<ChromaLocationNamePair>(begin(chromaLocations), end(chromaLocations)).value);
1602 										const TestConfig				config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1603 											vk::VK_FILTER_NEAREST, chromaLocation, chromaLocation, explicitReconstruction, disjoint,
1604 											defaultColorRange, defaultColorModel, getIdentitySwizzle(), srcSize, dstSize, 0);
1605 
1606 										addFunctionCaseWithPrograms(textureFilterGroup.get(), string("explicit_nearest") + "_" + tilingName + (disjoint ? "_disjoint" : ""), "", checkSupport, createTestShaders, textureConversionTest, config);
1607 									}
1608 
1609 									{
1610 										const glu::ShaderType			shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1611 										const vk::VkChromaLocation		chromaLocation(rng.choose<ChromaLocationNamePair>(begin(chromaLocations), end(chromaLocations)).value);
1612 										const TestConfig				config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1613 											vk::VK_FILTER_NEAREST, chromaLocation, chromaLocation, explicitReconstruction, disjoint,
1614 											defaultColorRange, defaultColorModel, swappedChromaSwizzle, srcSize, dstSize, 0);
1615 
1616 										addFunctionCaseWithPrograms(textureFilterGroup.get(), string("explicit_nearest") + "_" + tilingName + (disjoint ? "_disjoint" : "") + "_swapped_chroma", "", checkSupport, createTestShaders, textureConversionTest, config);
1617 									}
1618 								}
1619 							}
1620 						}
1621 					}
1622 
1623 					reconstrucGroup->addChild(textureFilterGroup.release());
1624 				}
1625 
1626 				formatGroup->addChild(reconstrucGroup.release());
1627 			}
1628 
1629 			testGroup->addChild(formatGroup.release());
1630 		}
1631 
1632 		// Test formats with xy chroma reconstruction
1633 		for (size_t formatNdx = 0; formatNdx < xyChromaSubsampledFormats.size(); formatNdx++)
1634 		{
1635 			const vk::VkFormat				format(xyChromaSubsampledFormats[formatNdx]);
1636 			const std::string				formatName(de::toLower(std::string(getFormatName(format)).substr(10)));
1637 			de::MovePtr<tcu::TestCaseGroup>	formatGroup(new tcu::TestCaseGroup(testCtx, formatName.c_str(), ("Tests for color conversion using format " + formatName).c_str()));
1638 			const UVec2						srcSize(isXChromaSubsampled(format) ? 12 : 7,
1639 				isYChromaSubsampled(format) ? 8 : 13);
1640 			const UVec2						dstSize(srcSize.x() + srcSize.x() / 2,
1641 				srcSize.y() + srcSize.y() / 2);
1642 
1643 			// Color conversion tests
1644 			{
1645 				de::MovePtr<tcu::TestCaseGroup>	conversionGroup(new tcu::TestCaseGroup(testCtx, "color_conversion", ""));
1646 
1647 				for (size_t chromaOffsetNdx = 0; chromaOffsetNdx < chromaLocations.size(); chromaOffsetNdx++)
1648 				{
1649 					const char* const			chromaOffsetName(chromaLocations[chromaOffsetNdx].name);
1650 					const vk::VkChromaLocation	chromaOffset(chromaLocations[chromaOffsetNdx].value);
1651 
1652 					for (size_t modelNdx = 0; modelNdx < colorModels.size(); modelNdx++)
1653 					{
1654 						const char* const							colorModelName(colorModels[modelNdx].name);
1655 						const vk::VkSamplerYcbcrModelConversion		colorModel(colorModels[modelNdx].value);
1656 
1657 						if (colorModel != vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY && getYCbCrFormatChannelCount(format) < 3)
1658 							continue;
1659 
1660 						if (colorModel == vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY)
1661 						{
1662 							for (size_t tilingNdx = 0; tilingNdx < imageTilings.size(); tilingNdx++)
1663 							{
1664 								const vk::VkImageTiling				tiling(imageTilings[tilingNdx].value);
1665 								const char* const					tilingName(imageTilings[tilingNdx].name);
1666 								const vk::VkSamplerYcbcrRange		colorRange(rng.choose<RangeNamePair>(begin(colorRanges), end(colorRanges)).value);
1667 								const glu::ShaderType				shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1668 								for (size_t bindingNdx = 0; bindingNdx < samplerBindings.size(); bindingNdx++)
1669 								{
1670 									const deUint32						samplerBinding(samplerBindings[bindingNdx].value);
1671 									string								samplerBindingName((samplerBindings[bindingNdx].value != 0) ? string("_") + samplerBindings[bindingNdx].name : string());
1672 									const TestConfig					config(shaderType, format, tiling, vk::VK_FILTER_NEAREST, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1673 										vk::VK_FILTER_NEAREST, chromaOffset, chromaOffset, false, false,
1674 										colorRange, colorModel, getIdentitySwizzle(), srcSize, dstSize, samplerBinding);
1675 
1676 									addFunctionCaseWithPrograms(conversionGroup.get(), std::string(colorModelName) + "_" + tilingName + "_" + chromaOffsetName + samplerBindingName, "", checkSupport, createTestShaders, textureConversionTest, config);
1677 								}
1678 							}
1679 						}
1680 						else
1681 						{
1682 							for (size_t rangeNdx = 0; rangeNdx < colorRanges.size(); rangeNdx++)
1683 							{
1684 								const char* const					colorRangeName(colorRanges[rangeNdx].name);
1685 								const vk::VkSamplerYcbcrRange		colorRange(colorRanges[rangeNdx].value);
1686 
1687 								// Narrow range doesn't really work with formats that have less than 8 bits
1688 								if (colorRange == vk::VK_SAMPLER_YCBCR_RANGE_ITU_NARROW)
1689 								{
1690 									const UVec4	bitDepth(getYCbCrBitDepth(format));
1691 
1692 									if (bitDepth[0] < 8 || bitDepth[1] < 8 || bitDepth[2] < 8)
1693 										continue;
1694 								}
1695 
1696 								for (size_t tilingNdx = 0; tilingNdx < imageTilings.size(); tilingNdx++)
1697 								{
1698 									const vk::VkImageTiling			tiling(imageTilings[tilingNdx].value);
1699 									const char* const				tilingName(imageTilings[tilingNdx].name);
1700 									const glu::ShaderType			shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1701 									for (size_t bindingNdx = 0; bindingNdx < samplerBindings.size(); bindingNdx++)
1702 									{
1703 										const deUint32					samplerBinding(samplerBindings[bindingNdx].value);
1704 										string							samplerBindingName((samplerBindings[bindingNdx].value != 0) ? string("_") + samplerBindings[bindingNdx].name : string());
1705 										const TestConfig				config(shaderType, format, tiling, vk::VK_FILTER_NEAREST, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1706 											vk::VK_FILTER_NEAREST, chromaOffset, chromaOffset, false, false,
1707 											colorRange, colorModel, getIdentitySwizzle(), srcSize, dstSize, samplerBinding);
1708 
1709 										addFunctionCaseWithPrograms(conversionGroup.get(), string(colorModelName) + "_" + colorRangeName + "_" + tilingName + "_" + chromaOffsetName + samplerBindingName, "", checkSupport, createTestShaders, textureConversionTest, config);
1710 									}
1711 								}
1712 							}
1713 						}
1714 					}
1715 				}
1716 
1717 				formatGroup->addChild(conversionGroup.release());
1718 			}
1719 
1720 			// Color conversion tests for array of samplers ( xyChromaSubsampledFormats )
1721 			if (getYCbCrFormatChannelCount(format) >= 3)
1722 				buildArrayOfSamplersTests(format, srcSize, dstSize, formatGroup, testCtx, rng);
1723 
1724 			// Chroma reconstruction tests
1725 			{
1726 				de::MovePtr<tcu::TestCaseGroup>	reconstrucGroup(new tcu::TestCaseGroup(testCtx, "chroma_reconstruction", ""));
1727 
1728 				for (size_t textureFilterNdx = 0; textureFilterNdx < textureFilters.size(); textureFilterNdx++)
1729 				{
1730 					const char* const				textureFilterName(textureFilters[textureFilterNdx].name);
1731 					const vk::VkFilter				textureFilter(textureFilters[textureFilterNdx].value);
1732 					de::MovePtr<tcu::TestCaseGroup>	textureFilterGroup(new tcu::TestCaseGroup(testCtx, textureFilterName, textureFilterName));
1733 
1734 					for (size_t explicitReconstructionNdx = 0; explicitReconstructionNdx < 2; explicitReconstructionNdx++)
1735 					{
1736 						const bool	explicitReconstruction(explicitReconstructionNdx == 1);
1737 
1738 						for (size_t disjointNdx = 0; disjointNdx < 2; disjointNdx++)
1739 						{
1740 							const bool	disjoint(disjointNdx == 1);
1741 
1742 							for (size_t xChromaOffsetNdx = 0; xChromaOffsetNdx < chromaLocations.size(); xChromaOffsetNdx++)
1743 								for (size_t yChromaOffsetNdx = 0; yChromaOffsetNdx < chromaLocations.size(); yChromaOffsetNdx++)
1744 								{
1745 									const vk::VkChromaLocation		xChromaOffset(chromaLocations[xChromaOffsetNdx].value);
1746 									const char* const				xChromaOffsetName(chromaLocations[xChromaOffsetNdx].name);
1747 
1748 									const vk::VkChromaLocation		yChromaOffset(chromaLocations[yChromaOffsetNdx].value);
1749 									const char* const				yChromaOffsetName(chromaLocations[yChromaOffsetNdx].name);
1750 
1751 									for (size_t tilingNdx = 0; tilingNdx < imageTilings.size(); tilingNdx++)
1752 									{
1753 										const vk::VkImageTiling	tiling(imageTilings[tilingNdx].value);
1754 										const char* const		tilingName(imageTilings[tilingNdx].name);
1755 										{
1756 											const glu::ShaderType	shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1757 											const TestConfig		config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1758 												vk::VK_FILTER_LINEAR, xChromaOffset, yChromaOffset, explicitReconstruction, disjoint,
1759 												defaultColorRange, defaultColorModel, getIdentitySwizzle(), srcSize, dstSize, 0);
1760 
1761 											addFunctionCaseWithPrograms(textureFilterGroup.get(), string(explicitReconstruction ? "explicit_linear_" : "default_linear_") + xChromaOffsetName + "_" + yChromaOffsetName + "_" + tilingName + (disjoint ? "_disjoint" : ""), "", checkSupport, createTestShaders, textureConversionTest, config);
1762 										}
1763 
1764 										{
1765 											const glu::ShaderType	shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1766 											const TestConfig		config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1767 												vk::VK_FILTER_LINEAR, xChromaOffset, yChromaOffset, explicitReconstruction, disjoint,
1768 												defaultColorRange, defaultColorModel, swappedChromaSwizzle, srcSize, dstSize, 0);
1769 
1770 											addFunctionCaseWithPrograms(textureFilterGroup.get(), string(explicitReconstruction ? "explicit_linear_" : "default_linear_") + xChromaOffsetName + "_" + yChromaOffsetName + "_" + tilingName + (disjoint ? "_disjoint" : "") + "_swapped_chroma", "", checkSupport, createTestShaders, textureConversionTest, config);
1771 										}
1772 
1773 										if (!explicitReconstruction)
1774 										{
1775 											{
1776 												const glu::ShaderType	shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1777 												const TestConfig		config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1778 													vk::VK_FILTER_NEAREST, xChromaOffset, yChromaOffset, explicitReconstruction, disjoint,
1779 													defaultColorRange, defaultColorModel, getIdentitySwizzle(), srcSize, dstSize, 0);
1780 
1781 												addFunctionCaseWithPrograms(textureFilterGroup.get(), string("default_nearest_") + xChromaOffsetName + "_" + yChromaOffsetName + "_" + tilingName + (disjoint ? "_disjoint" : ""), "", checkSupport, createTestShaders, textureConversionTest, config);
1782 											}
1783 
1784 											{
1785 												const glu::ShaderType	shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1786 												const TestConfig		config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1787 													vk::VK_FILTER_NEAREST, xChromaOffset, yChromaOffset, explicitReconstruction, disjoint,
1788 													defaultColorRange, defaultColorModel, swappedChromaSwizzle, srcSize, dstSize, 0);
1789 
1790 												addFunctionCaseWithPrograms(textureFilterGroup.get(), string("default_nearest_") + xChromaOffsetName + "_" + yChromaOffsetName + "_" + tilingName + (disjoint ? "_disjoint" : "") + "_swapped_chroma", "", checkSupport, createTestShaders, textureConversionTest, config);
1791 											}
1792 										}
1793 									}
1794 								}
1795 
1796 							if (explicitReconstruction)
1797 							{
1798 								for (size_t tilingNdx = 0; tilingNdx < imageTilings.size(); tilingNdx++)
1799 								{
1800 									const vk::VkImageTiling	tiling(imageTilings[tilingNdx].value);
1801 									const char* const		tilingName(imageTilings[tilingNdx].name);
1802 									{
1803 										const glu::ShaderType			shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1804 										const vk::VkChromaLocation		chromaLocation(rng.choose<ChromaLocationNamePair>(begin(chromaLocations), end(chromaLocations)).value);
1805 										const TestConfig				config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1806 											vk::VK_FILTER_NEAREST, chromaLocation, chromaLocation, explicitReconstruction, disjoint,
1807 											defaultColorRange, defaultColorModel, getIdentitySwizzle(), srcSize, dstSize, 0);
1808 
1809 										addFunctionCaseWithPrograms(textureFilterGroup.get(), string("explicit_nearest") + "_" + tilingName + (disjoint ? "_disjoint" : ""), "", checkSupport, createTestShaders, textureConversionTest, config);
1810 									}
1811 
1812 									{
1813 										const glu::ShaderType			shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1814 										const vk::VkChromaLocation		chromaLocation(rng.choose<ChromaLocationNamePair>(begin(chromaLocations), end(chromaLocations)).value);
1815 										const TestConfig				config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1816 											vk::VK_FILTER_NEAREST, chromaLocation, chromaLocation, explicitReconstruction, disjoint,
1817 											defaultColorRange, defaultColorModel, swappedChromaSwizzle, srcSize, dstSize, 0);
1818 
1819 										addFunctionCaseWithPrograms(textureFilterGroup.get(), string("explicit_nearest") + "_" + tilingName + (disjoint ? "_disjoint" : "") + "_swapped_chroma", "", checkSupport, createTestShaders, textureConversionTest, config);
1820 									}
1821 								}
1822 							}
1823 						}
1824 					}
1825 
1826 					reconstrucGroup->addChild(textureFilterGroup.release());
1827 				}
1828 
1829 				formatGroup->addChild(reconstrucGroup.release());
1830 			}
1831 
1832 			testGroup->addChild(formatGroup.release());
1833 		}
1834 
1835 		{
1836 			const UVec2 imageSizes[] =
1837 			{
1838 				UVec2(16, 16),
1839 				UVec2(20, 12)
1840 			};
1841 
1842 			de::MovePtr<tcu::TestCaseGroup>				oneToOneGroup(new tcu::TestCaseGroup(testCtx, "one_to_one", "Ycbcr images sampled to a frame buffer of the same dimentions."));
1843 
1844 			const vk::VkFormat							format(vk::VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM_KHR);
1845 			const vk::VkFilter							filter(vk::VK_FILTER_NEAREST);
1846 
1847 			for (size_t sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(imageSizes); sizeNdx++)
1848 			{
1849 				const UVec2								srcSize(imageSizes[sizeNdx]);
1850 
1851 				for (size_t xChromaOffsetNdx = 0; xChromaOffsetNdx < chromaLocations.size(); xChromaOffsetNdx++)
1852 				{
1853 					const vk::VkChromaLocation			xChromaOffset(chromaLocations[xChromaOffsetNdx].value);
1854 					const char* const					xChromaOffsetName(chromaLocations[xChromaOffsetNdx].name);
1855 
1856 					for (size_t yChromaOffsetNdx = 0; yChromaOffsetNdx < chromaLocations.size(); yChromaOffsetNdx++)
1857 					{
1858 						const vk::VkChromaLocation		yChromaOffset(chromaLocations[yChromaOffsetNdx].value);
1859 						const char* const				yChromaOffsetName(chromaLocations[yChromaOffsetNdx].name);
1860 
1861 						for (size_t tilingNdx = 0; tilingNdx < imageTilings.size(); tilingNdx++)
1862 						{
1863 							const vk::VkImageTiling		tiling(imageTilings[tilingNdx].value);
1864 							const char* const			tilingName(imageTilings[tilingNdx].name);
1865 
1866 							const glu::ShaderType		shaderType(rng.choose<glu::ShaderType>(begin(shaderTypes), end(shaderTypes)));
1867 
1868 							const TestConfig			config(shaderType, format, tiling, filter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1869 								filter, xChromaOffset, yChromaOffset, false, false,
1870 								defaultColorRange, defaultColorModel, getIdentitySwizzle(), srcSize, srcSize, 0);
1871 							std::ostringstream			testName;
1872 							testName << string("implicit_nearest_") << srcSize.x() << "x" << srcSize.y() << "_" << tilingName << "_" << xChromaOffsetName << "_" << yChromaOffsetName;
1873 
1874 							addFunctionCaseWithPrograms(oneToOneGroup.get(), testName.str(), "", checkSupport, createTestShaders, textureConversionTest, config);
1875 						}
1876 					}
1877 				}
1878 			}
1879 
1880 			testGroup->addChild(oneToOneGroup.release());
1881 		}
1882 	}
1883 
buildArrayOfSamplersTestsvkt::ycbcr::__anon548eae410111::YCbCrConversionTestBuilder1884 	void buildArrayOfSamplersTests(const vk::VkFormat& format, const UVec2& srcSize, const UVec2& dstSize, de::MovePtr<tcu::TestCaseGroup>& formatGroup, tcu::TestContext& testCtx, de::Random& rng )
1885 	{
1886 		de::MovePtr<tcu::TestCaseGroup>			samplerArrayGroup(new tcu::TestCaseGroup(testCtx, "sampler_array", "Tests for array of samplers"));
1887 
1888 		for (size_t textureFilterNdx = 0; textureFilterNdx < textureFilters.size(); textureFilterNdx++)
1889 		{
1890 			const char* const					textureFilterName(textureFilters[textureFilterNdx].name);
1891 			const vk::VkFilter					textureFilter(textureFilters[textureFilterNdx].value);
1892 
1893 			for (size_t tilingNdx = 0; tilingNdx < imageTilings.size(); tilingNdx++)
1894 			{
1895 				const vk::VkImageTiling			tiling(imageTilings[tilingNdx].value);
1896 				const char* const				tilingName(imageTilings[tilingNdx].name);
1897 				const glu::ShaderType			shaderType(rng.choose<glu::ShaderType>(shaderTypes.begin(), shaderTypes.end()));
1898 				const vk::VkSamplerYcbcrRange	colorRange(vk::VK_SAMPLER_YCBCR_RANGE_ITU_FULL);
1899 				const vk::VkChromaLocation		chromaLocation(rng.choose<ChromaLocationNamePair>(chromaLocations.begin(), chromaLocations.end()).value);
1900 
1901 				for (size_t bindingNdx = 0; bindingNdx < samplerBindings.size(); bindingNdx++)
1902 				{
1903 					const deUint32					samplerBinding(samplerBindings[bindingNdx].value);
1904 					string							samplerBindingName((samplerBindings[bindingNdx].value != 0) ? string("_") + samplerBindings[bindingNdx].name : string());
1905 					// colorModel==VK_SAMPLER_YCBCR_MODEL_CONVERSION_LAST means that we want to create an array of samplers instead of a single sampler
1906 					const TestConfig				config(shaderType, format, tiling, textureFilter, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1907 						textureFilter, chromaLocation, chromaLocation, false, false,
1908 						colorRange, vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_LAST, getIdentitySwizzle(), srcSize, dstSize, samplerBinding);
1909 
1910 					addFunctionCaseWithPrograms(samplerArrayGroup.get(), std::string(textureFilterName) + "_" + tilingName + samplerBindingName, "", checkSupport, createTestShaders, textureConversionTest, config);
1911 				}
1912 			}
1913 		}
1914 		formatGroup->addChild(samplerArrayGroup.release());
1915 	}
1916 };
1917 
initTests(tcu::TestCaseGroup * testGroup)1918 void initTests(tcu::TestCaseGroup* testGroup)
1919 {
1920 	YCbCrConversionTestBuilder testBuilder;
1921 	testBuilder.buildTests(testGroup);
1922 }
1923 
1924 } // anonymous
1925 
createConversionTests(tcu::TestContext & testCtx)1926 tcu::TestCaseGroup* createConversionTests (tcu::TestContext& testCtx)
1927 {
1928 	return createTestGroup(testCtx, "conversion", "Sampler YCbCr Conversion Tests", initTests);
1929 }
1930 
1931 } // ycbcr
1932 } // vkt
1933