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