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