Merge vk-gl-cts/vulkan-cts-1.2.1 into vk-gl-cts/vulkan-cts-1.2.2
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / protected_memory / vktProtectedMemYCbCrConversionTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2017 The Khronos Group Inc.
6  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Protected memory YCbCr image conversion tests
23  *//*--------------------------------------------------------------------*/
24
25 #include "vktProtectedMemYCbCrConversionTests.hpp"
26
27 #include "tcuImageCompare.hpp"
28 #include "tcuStringTemplate.hpp"
29 #include "tcuTestLog.hpp"
30
31 #include "vkBuilderUtil.hpp"
32 #include "vkImageUtil.hpp"
33 #include "vkPrograms.hpp"
34 #include "vkTypeUtil.hpp"
35 #include "vkYCbCrImageWithMemory.hpp"
36 #include "vkCmdUtil.hpp"
37 #include "vkObjUtil.hpp"
38
39 #include "vktProtectedMemContext.hpp"
40 #include "vktProtectedMemUtils.hpp"
41 #include "vktTestCaseUtil.hpp"
42 #include "vktYCbCrUtil.hpp"
43
44
45 namespace vkt
46 {
47 namespace ProtectedMem
48 {
49
50 namespace
51 {
52 static const vk::VkFormat       s_colorFormat   = vk::VK_FORMAT_R8G8B8A8_UNORM;
53
54 enum {
55         CHECK_SIZE      = 50,
56 };
57
58 struct YCbCrValidationData {
59         tcu::Vec4       coord;
60         tcu::Vec4       minBound;
61         tcu::Vec4       maxBound;
62 };
63
64 std::vector<tcu::Vec2> computeVertexPositions (int numValues, const tcu::IVec2& renderSize)
65 {
66         std::vector<tcu::Vec2> positions(numValues);
67         for (int valNdx = 0; valNdx < numValues; valNdx++)
68         {
69                 const int       ix      = valNdx % renderSize.x();
70                 const int       iy      = valNdx / renderSize.x();
71                 const float     fx      = -1.0f + 2.0f*((float(ix) + 0.5f) / float(renderSize.x()));
72                 const float     fy      = -1.0f + 2.0f*((float(iy) + 0.5f) / float(renderSize.y()));
73
74                 positions[valNdx] = tcu::Vec2(fx, fy);
75         }
76
77         return positions;
78 }
79
80 void genTexCoords (std::vector<tcu::Vec2>& coords, const tcu::UVec2& size)
81 {
82         for (deUint32 y = 0; y < size.y(); y++)
83         for (deUint32 x = 0; x < size.x(); x++)
84         {
85                 const float     fx      = (float)x;
86                 const float     fy      = (float)y;
87
88                 const float     fw      = (float)size.x();
89                 const float     fh      = (float)size.y();
90
91                 const float     s       = 1.5f * ((fx * 1.5f * fw + fx) / (1.5f * fw * 1.5f * fw)) - 0.25f;
92                 const float     t       = 1.5f * ((fy * 1.5f * fh + fy) / (1.5f * fh * 1.5f * fh)) - 0.25f;
93
94                 coords.push_back(tcu::Vec2(s, t));
95         }
96 }
97
98 struct TestConfig
99 {
100         TestConfig      (glu::ShaderType                                                shaderType_,
101                                  vk::VkFormat                                                   format_,
102                                  vk::VkImageTiling                                              imageTiling_,
103                                  vk::VkFilter                                                   textureFilter_,
104                                  vk::VkSamplerAddressMode                               addressModeU_,
105                                  vk::VkSamplerAddressMode                               addressModeV_,
106
107                                  vk::VkFilter                                                   chromaFilter_,
108                                  vk::VkChromaLocation                                   xChromaOffset_,
109                                  vk::VkChromaLocation                                   yChromaOffset_,
110                                  bool                                                                   explicitReconstruction_,
111                                  bool                                                                   disjoint_,
112
113                                  vk::VkSamplerYcbcrRange                                colorRange_,
114                                  vk::VkSamplerYcbcrModelConversion              colorModel_,
115                                  vk::VkComponentMapping                                 componentMapping_)
116                 : shaderType                            (shaderType_)
117                 , format                                        (format_)
118                 , imageTiling                           (imageTiling_)
119                 , textureFilter                         (textureFilter_)
120                 , addressModeU                          (addressModeU_)
121                 , addressModeV                          (addressModeV_)
122
123                 , chromaFilter                          (chromaFilter_)
124                 , xChromaOffset                         (xChromaOffset_)
125                 , yChromaOffset                         (yChromaOffset_)
126                 , explicitReconstruction        (explicitReconstruction_)
127                 , disjoint                                      (disjoint_)
128
129                 , colorRange                            (colorRange_)
130                 , colorModel                            (colorModel_)
131                 , componentMapping                      (componentMapping_)
132         {
133         }
134
135         glu::ShaderType                                                 shaderType;
136         vk::VkFormat                                                    format;
137         vk::VkImageTiling                                               imageTiling;
138         vk::VkFilter                                                    textureFilter;
139         vk::VkSamplerAddressMode                                addressModeU;
140         vk::VkSamplerAddressMode                                addressModeV;
141
142         vk::VkFilter                                                    chromaFilter;
143         vk::VkChromaLocation                                    xChromaOffset;
144         vk::VkChromaLocation                                    yChromaOffset;
145         bool                                                                    explicitReconstruction;
146         bool                                                                    disjoint;
147
148         vk::VkSamplerYcbcrRange                                 colorRange;
149         vk::VkSamplerYcbcrModelConversion               colorModel;
150         vk::VkComponentMapping                                  componentMapping;
151 };
152
153 void checkSupport (Context& context, const TestConfig)
154 {
155         checkProtectedQueueSupport(context);
156 }
157
158 void validateFormatSupport (ProtectedContext& context, TestConfig& config)
159 {
160         tcu::TestLog&                                           log                     (context.getTestContext().getLog());
161
162         try
163         {
164                 const vk::VkFormatProperties    properties      (vk::getPhysicalDeviceFormatProperties(context.getInstanceDriver(), context.getPhysicalDevice(), config.format));
165                 const vk::VkFormatFeatureFlags  features        (config.imageTiling == vk::VK_IMAGE_TILING_OPTIMAL
166                                                                                                         ? properties.optimalTilingFeatures
167                                                                                                         : properties.linearTilingFeatures);
168
169                 if ((features & (vk::VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT | vk::VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT)) == 0)
170                         TCU_THROW(NotSupportedError, "Format doesn't support YCbCr conversions");
171
172                 if ((features & vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) == 0)
173                         TCU_THROW(NotSupportedError, "Format doesn't support sampling");
174
175                 if (config.textureFilter == vk::VK_FILTER_LINEAR && ((features & vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT) == 0))
176                         TCU_THROW(NotSupportedError, "Format doesn't support YCbCr linear chroma reconstruction");
177
178                 if (config.chromaFilter == vk::VK_FILTER_LINEAR && ((features & vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT) == 0))
179                         TCU_THROW(NotSupportedError, "Format doesn't support YCbCr linear chroma reconstruction");
180
181                 if (config.chromaFilter != config.textureFilter && ((features & vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT) == 0))
182                         TCU_THROW(NotSupportedError, "Format doesn't support different chroma and texture filters");
183
184                 if (config.explicitReconstruction && ((features & vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT) == 0))
185                         TCU_THROW(NotSupportedError, "Format doesn't support explicit chroma reconstruction");
186
187                 if (config.disjoint && ((features & vk::VK_FORMAT_FEATURE_DISJOINT_BIT) == 0))
188                         TCU_THROW(NotSupportedError, "Format doesn't disjoint planes");
189
190                 if (ycbcr::isXChromaSubsampled(config.format) && (config.xChromaOffset == vk::VK_CHROMA_LOCATION_COSITED_EVEN) && ((features & vk::VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT) == 0))
191                         TCU_THROW(NotSupportedError, "Format doesn't support cosited chroma samples");
192
193                 if (ycbcr::isXChromaSubsampled(config.format) && (config.xChromaOffset == vk::VK_CHROMA_LOCATION_MIDPOINT) && ((features & vk::VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT) == 0))
194                         TCU_THROW(NotSupportedError, "Format doesn't support midpoint chroma samples");
195
196                 if (ycbcr::isYChromaSubsampled(config.format) && (config.yChromaOffset == vk::VK_CHROMA_LOCATION_COSITED_EVEN) && ((features & vk::VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT) == 0))
197                         TCU_THROW(NotSupportedError, "Format doesn't support cosited chroma samples");
198
199                 if (ycbcr::isYChromaSubsampled(config.format) && (config.yChromaOffset == vk::VK_CHROMA_LOCATION_MIDPOINT) && ((features & vk::VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT) == 0))
200                         TCU_THROW(NotSupportedError, "Format doesn't support midpoint chroma samples");
201
202                 if ((features & vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT) != 0)
203                         config.explicitReconstruction = true;
204
205                 log << tcu::TestLog::Message << "FormatFeatures: " << vk::getFormatFeatureFlagsStr(features) << tcu::TestLog::EndMessage;
206         }
207         catch (const vk::Error& err)
208         {
209                 if (err.getError() == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
210                         TCU_THROW(NotSupportedError, "Format not supported");
211
212                 throw;
213         }
214 }
215
216 vk::Move<vk::VkSampler> createSampler (const vk::DeviceInterface&                               vkd,
217                                                                            const vk::VkDevice                                           device,
218                                                                            const vk::VkFilter                                           textureFilter,
219                                                                            const vk::VkSamplerAddressMode                       addressModeU,
220                                                                            const vk::VkSamplerAddressMode                       addressModeV,
221                                                                            const vk::VkSamplerYcbcrConversion           conversion)
222 {
223         const vk::VkSamplerYcbcrConversionInfo          samplerConversionInfo   =
224         {
225                 vk::VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO,
226                 DE_NULL,
227                 conversion
228         };
229
230         const vk::VkSamplerCreateInfo   createInfo      =
231         {
232                 vk::VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
233                 &samplerConversionInfo,
234                 0u,
235                 textureFilter,
236                 textureFilter,
237                 vk::VK_SAMPLER_MIPMAP_MODE_NEAREST,
238                 addressModeU,
239                 addressModeV,
240                 vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
241                 0.0f,
242                 VK_FALSE,
243                 1.0f,
244                 VK_FALSE,
245                 vk::VK_COMPARE_OP_ALWAYS,
246                 0.0f,
247                 0.0f,
248                 vk::VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,
249                 VK_FALSE,
250         };
251
252         return createSampler(vkd, device, &createInfo);
253 }
254
255 vk::Move<vk::VkImageView> createImageView (const vk::DeviceInterface&                           vkd,
256                                                                                    const vk::VkDevice                                           device,
257                                                                                    const vk::VkImage                                            image,
258                                                                                    const vk::VkFormat                                           format,
259                                                                                    const vk::VkSamplerYcbcrConversion           conversion)
260 {
261         const vk::VkSamplerYcbcrConversionInfo          conversionInfo  =
262         {
263                 vk::VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO,
264                 DE_NULL,
265                 conversion
266         };
267
268         const vk::VkImageViewCreateInfo                         viewInfo                =
269         {
270                 vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
271                 &conversionInfo,
272                 (vk::VkImageViewCreateFlags)0,
273                 image,
274                 vk::VK_IMAGE_VIEW_TYPE_2D,
275                 format,
276                 {
277                         vk::VK_COMPONENT_SWIZZLE_IDENTITY,
278                         vk::VK_COMPONENT_SWIZZLE_IDENTITY,
279                         vk::VK_COMPONENT_SWIZZLE_IDENTITY,
280                         vk::VK_COMPONENT_SWIZZLE_IDENTITY,
281                 },
282                 { vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },
283         };
284
285         return vk::createImageView(vkd, device, &viewInfo);
286 }
287
288 vk::Move<vk::VkSamplerYcbcrConversion> createConversion (const vk::DeviceInterface&                                     vkd,
289                                                                                                                 const vk::VkDevice                                                      device,
290                                                                                                                 const vk::VkFormat                                                      format,
291                                                                                                                 const vk::VkSamplerYcbcrModelConversion         colorModel,
292                                                                                                                 const vk::VkSamplerYcbcrRange                           colorRange,
293                                                                                                                 const vk::VkChromaLocation                                      xChromaOffset,
294                                                                                                                 const vk::VkChromaLocation                                      yChromaOffset,
295                                                                                                                 const vk::VkFilter                                                      chromaFilter,
296                                                                                                                 const vk::VkComponentMapping&                           componentMapping,
297                                                                                                                 const bool                                                                      explicitReconstruction)
298 {
299         const vk::VkSamplerYcbcrConversionCreateInfo    conversionInfo  =
300         {
301                 vk::VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO,
302                 DE_NULL,
303
304                 format,
305                 colorModel,
306                 colorRange,
307                 componentMapping,
308                 xChromaOffset,
309                 yChromaOffset,
310                 chromaFilter,
311                 explicitReconstruction ? VK_TRUE : VK_FALSE
312         };
313
314         return vk::createSamplerYcbcrConversion(vkd, device, &conversionInfo);
315 }
316
317 void uploadYCbCrImage (ProtectedContext&                                        ctx,
318                                            const vk::VkImage                                    image,
319                                            const ycbcr::MultiPlaneImageData&    imageData,
320                                            const vk::VkAccessFlags                              nextAccess,
321                                            const vk::VkImageLayout                              finalLayout)
322 {
323         const vk::DeviceInterface&                              vk                                      = ctx.getDeviceInterface();
324         const vk::VkDevice                                              device                          = ctx.getDevice();
325         const vk::VkQueue                                               queue                           = ctx.getQueue();
326         const deUint32                                                  queueFamilyIndex        = ctx.getQueueFamilyIndex();
327
328         const vk::Unique<vk::VkCommandPool>             cmdPool                         (makeCommandPool(vk, device, PROTECTION_ENABLED, queueFamilyIndex));
329         const vk::Unique<vk::VkCommandBuffer>   cmdBuffer                       (vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
330
331         const vk::PlanarFormatDescription&              formatDesc                      = imageData.getDescription();
332
333         std::vector<de::SharedPtr<de::MovePtr<vk::BufferWithMemory> > > stagingBuffers;
334         std::vector<vk::VkBufferMemoryBarrier>  bufferBarriers;
335
336         for (deUint32 planeNdx = 0; planeNdx < imageData.getDescription().numPlanes; ++planeNdx)
337         {
338                 de::MovePtr<vk::BufferWithMemory> buffer        (makeBuffer(ctx,
339                                                                                                                                                 PROTECTION_DISABLED,
340                                                                                                                                                 queueFamilyIndex,
341                                                                                                                                                 (deUint32)imageData.getPlaneSize(planeNdx),
342                                                                                                                                                 vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT,
343                                                                                                                                                 vk::MemoryRequirement::HostVisible));
344
345                 const vk::VkBufferMemoryBarrier         bufferBarrier   =
346                 {
347                         vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
348                         DE_NULL,
349                         (vk::VkAccessFlags)0,
350                         vk::VK_ACCESS_TRANSFER_READ_BIT,
351                         queueFamilyIndex,
352                         queueFamilyIndex,
353                         **buffer,
354                         0,
355                         (deUint32)imageData.getPlaneSize(planeNdx)
356                 };
357                 bufferBarriers.push_back(bufferBarrier);
358
359                 deMemcpy(buffer->getAllocation().getHostPtr(), imageData.getPlanePtr(planeNdx), imageData.getPlaneSize(planeNdx));
360                 flushMappedMemoryRange(vk, device, buffer->getAllocation().getMemory(), buffer->getAllocation().getOffset(), (deUint32)imageData.getPlaneSize(planeNdx));
361                 stagingBuffers.push_back(de::SharedPtr<de::MovePtr<vk::BufferWithMemory> >(new de::MovePtr<vk::BufferWithMemory>(buffer.release())));
362         }
363
364
365         beginCommandBuffer(vk, *cmdBuffer);
366
367         for (deUint32 planeNdx = 0; planeNdx < imageData.getDescription().numPlanes; ++planeNdx)
368         {
369                 const vk::VkImageAspectFlagBits aspect  = formatDesc.numPlanes > 1
370                                                                                                 ? vk::getPlaneAspect(planeNdx)
371                                                                                                 : vk::VK_IMAGE_ASPECT_COLOR_BIT;
372
373                 const vk::VkImageMemoryBarrier          preCopyBarrier  =
374                 {
375                         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
376                         DE_NULL,
377                         (vk::VkAccessFlags)0,
378                         vk::VK_ACCESS_TRANSFER_WRITE_BIT,
379                         vk::VK_IMAGE_LAYOUT_UNDEFINED,
380                         vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
381                         queueFamilyIndex,
382                         queueFamilyIndex,
383                         image,
384                         { aspect, 0u, 1u, 0u, 1u }
385                 };
386
387                 vk.cmdPipelineBarrier(*cmdBuffer,
388                                                                 (vk::VkPipelineStageFlags)vk::VK_PIPELINE_STAGE_HOST_BIT,
389                                                                 (vk::VkPipelineStageFlags)vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
390                                                                 (vk::VkDependencyFlags)0u,
391                                                                 0u, (const vk::VkMemoryBarrier*)DE_NULL,
392                                                                 (deUint32)bufferBarriers.size(), &bufferBarriers[0],
393                                                                 1u, &preCopyBarrier);
394         }
395
396         for (deUint32 planeNdx = 0; planeNdx < imageData.getDescription().numPlanes; ++planeNdx)
397         {
398                 const vk::VkImageAspectFlagBits aspect  = (formatDesc.numPlanes > 1)
399                                                                                                 ? vk::getPlaneAspect(planeNdx)
400                                                                                                 : vk::VK_IMAGE_ASPECT_COLOR_BIT;
401                 const deUint32                                  planeW  = (formatDesc.numPlanes > 1)
402                                                                                                 ? imageData.getSize().x() / formatDesc.planes[planeNdx].widthDivisor
403                                                                                                 : imageData.getSize().x();
404                 const deUint32                                  planeH  = (formatDesc.numPlanes > 1)
405                                                                                                 ? imageData.getSize().y() / formatDesc.planes[planeNdx].heightDivisor
406                                                                                                 : imageData.getSize().y();
407                 const vk::VkBufferImageCopy             copy    =
408                 {
409                         0u,             // bufferOffset
410                         0u,             // bufferRowLength
411                         0u,             // bufferImageHeight
412                         { (vk::VkImageAspectFlags)aspect, 0u, 0u, 1u },
413                         vk::makeOffset3D(0u, 0u, 0u),
414                         vk::makeExtent3D(planeW, planeH, 1u),
415                 };
416
417                 vk.cmdCopyBufferToImage(*cmdBuffer, ***stagingBuffers[planeNdx], image, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &copy);
418         }
419
420         for (deUint32 planeNdx = 0; planeNdx < imageData.getDescription().numPlanes; ++planeNdx)
421         {
422                 const vk::VkImageAspectFlagBits aspect  = formatDesc.numPlanes > 1
423                                                                                                 ? vk::getPlaneAspect(planeNdx)
424                                                                                                 : vk::VK_IMAGE_ASPECT_COLOR_BIT;
425
426                 const vk::VkImageMemoryBarrier          postCopyBarrier =
427                 {
428                         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
429                         DE_NULL,
430                         vk::VK_ACCESS_TRANSFER_WRITE_BIT,
431                         nextAccess,
432                         vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
433                         finalLayout,
434                         VK_QUEUE_FAMILY_IGNORED,
435                         VK_QUEUE_FAMILY_IGNORED,
436                         image,
437                         { aspect, 0u, 1u, 0u, 1u }
438                 };
439
440                 vk.cmdPipelineBarrier(*cmdBuffer,
441                                                                 (vk::VkPipelineStageFlags)vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
442                                                                 (vk::VkPipelineStageFlags)vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
443                                                                 (vk::VkDependencyFlags)0u,
444                                                                 0u, (const vk::VkMemoryBarrier*)DE_NULL,
445                                                                 0u, (const vk::VkBufferMemoryBarrier*)DE_NULL,
446                                                                 1u, &postCopyBarrier);
447         }
448
449         endCommandBuffer(vk, *cmdBuffer);
450
451         {
452                 const vk::Unique<vk::VkFence>   fence           (createFence(vk, device));
453                 VK_CHECK(queueSubmit(ctx, PROTECTION_ENABLED, queue, *cmdBuffer, *fence, ~0ull));
454         }
455 }
456
457 void logTestCaseInfo (tcu::TestLog& log, const TestConfig& config)
458 {
459         log << tcu::TestLog::Message << "ShaderType: " << config.shaderType << tcu::TestLog::EndMessage;
460         log << tcu::TestLog::Message << "Format: "  << config.format << tcu::TestLog::EndMessage;
461         log << tcu::TestLog::Message << "ImageTiling: " << config.imageTiling << tcu::TestLog::EndMessage;
462         log << tcu::TestLog::Message << "TextureFilter: " << config.textureFilter << tcu::TestLog::EndMessage;
463         log << tcu::TestLog::Message << "AddressModeU: " << config.addressModeU << tcu::TestLog::EndMessage;
464         log << tcu::TestLog::Message << "AddressModeV: " << config.addressModeV << tcu::TestLog::EndMessage;
465         log << tcu::TestLog::Message << "ChromaFilter: " << config.chromaFilter << tcu::TestLog::EndMessage;
466         log << tcu::TestLog::Message << "XChromaOffset: " << config.xChromaOffset << tcu::TestLog::EndMessage;
467         log << tcu::TestLog::Message << "YChromaOffset: " << config.yChromaOffset << tcu::TestLog::EndMessage;
468         log << tcu::TestLog::Message << "ExplicitReconstruction: " << (config.explicitReconstruction ? "true" : "false") << tcu::TestLog::EndMessage;
469         log << tcu::TestLog::Message << "Disjoint: " << (config.disjoint ? "true" : "false") << tcu::TestLog::EndMessage;
470         log << tcu::TestLog::Message << "ColorRange: " << config.colorRange << tcu::TestLog::EndMessage;
471         log << tcu::TestLog::Message << "ColorModel: " << config.colorModel << tcu::TestLog::EndMessage;
472         log << tcu::TestLog::Message << "ComponentMapping: " << config.componentMapping << tcu::TestLog::EndMessage;
473 }
474
475 void logBoundImages (tcu::TestLog& log, const tcu::UVec2 size, const std::vector<tcu::Vec4>& minBounds, const std::vector<tcu::Vec4>& maxBounds)
476 {
477         tcu::TextureLevel       minImage        (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT), size.x(), size.y());
478         tcu::TextureLevel       maxImage        (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT), size.x(), size.y());
479
480         for (int y = 0; y < (int)(size.y()); y++)
481         for (int x = 0; x < (int)(size.x()); x++)
482         {
483                 const int ndx = x + y * (int)(size.x());
484                 minImage.getAccess().setPixel(minBounds[ndx], x, y);
485                 maxImage.getAccess().setPixel(maxBounds[ndx], x, y);
486         }
487
488         const tcu::Vec4 scale   (1.0f);
489         const tcu::Vec4 bias    (0.0f);
490
491         log << tcu::TestLog::Image("MinBoundImage", "MinBoundImage", minImage.getAccess(), scale, bias);
492         log << tcu::TestLog::Image("MaxBoundImage", "MaxBoundImage", maxImage.getAccess(), scale, bias);
493 }
494
495 bool validateImage (ProtectedContext&                                                   ctx,
496                                          const std::vector<YCbCrValidationData>&        refData,
497                                          const vk::VkSampler                                            sampler,
498                                          const vk::VkImageView                                          imageView,
499                                          const deUint32                                                         combinedSamplerDescriptorCount)
500 {
501         {
502                 tcu::TestLog&   log     (ctx.getTestContext().getLog());
503
504                 log << tcu::TestLog::Message << "Reference values:" << tcu::TestLog::EndMessage;
505                 for (deUint32 ndx = 0; ndx < refData.size(); ndx++)
506                 {
507                         log << tcu::TestLog::Message << (ndx + 1) << refData[ndx].coord << ": [" << refData[ndx].minBound << ", " << refData[ndx].maxBound << "]" << tcu::TestLog::EndMessage;
508                 }
509         }
510
511         const deUint64                                                          oneSec                          = 1000 * 1000 * 1000;
512
513         const vk::DeviceInterface&                                      vk                                      = ctx.getDeviceInterface();
514         const vk::VkDevice                                                      device                          = ctx.getDevice();
515         const vk::VkQueue                                                       queue                           = ctx.getQueue();
516         const deUint32                                                          queueFamilyIndex        = ctx.getQueueFamilyIndex();
517
518         DE_ASSERT(refData.size() >= CHECK_SIZE && CHECK_SIZE > 0);
519         const deUint32                                                          refUniformSize          = (deUint32)(sizeof(YCbCrValidationData) * refData.size());
520         const de::UniquePtr<vk::BufferWithMemory>       refUniform                      (makeBuffer(ctx,
521                                                                                                                                                                 PROTECTION_DISABLED,
522                                                                                                                                                                 queueFamilyIndex,
523                                                                                                                                                                 refUniformSize,
524                                                                                                                                                                 vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
525                                                                                                                                                                 vk::MemoryRequirement::HostVisible));
526
527         // Set the reference uniform data
528         {
529                 deMemcpy(refUniform->getAllocation().getHostPtr(), &refData[0], refUniformSize);
530                 vk::flushMappedMemoryRange(vk, device, refUniform->getAllocation().getMemory(), refUniform->getAllocation().getOffset(), refUniformSize);
531         }
532
533         const deUint32                                                          helperBufferSize        = (deUint32)(2 * sizeof(deUint32));
534         const de::MovePtr<vk::BufferWithMemory>         helperBuffer            (makeBuffer(ctx,
535                                                                                                                                                                 PROTECTION_ENABLED,
536                                                                                                                                                                 queueFamilyIndex,
537                                                                                                                                                                 helperBufferSize,
538                                                                                                                                                                 vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
539                                                                                                                                                                 vk::MemoryRequirement::Protected));
540         const vk::Unique<vk::VkShaderModule>            resetSSBOShader         (vk::createShaderModule(vk, device, ctx.getBinaryCollection().get("ResetSSBO"), 0));
541         const vk::Unique<vk::VkShaderModule>            validatorShader         (vk::createShaderModule(vk, device, ctx.getBinaryCollection().get("ImageValidator"), 0));
542
543         // Create descriptors
544         const vk::Unique<vk::VkDescriptorSetLayout>     descriptorSetLayout(vk::DescriptorSetLayoutBuilder()
545                 .addSingleSamplerBinding(vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, vk::VK_SHADER_STAGE_COMPUTE_BIT, &sampler)
546                 .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT)
547                 .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT)
548                 .build(vk, device));
549         const vk::Unique<vk::VkDescriptorPool>          descriptorPool(vk::DescriptorPoolBuilder()
550                 .addType(vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, combinedSamplerDescriptorCount)
551                 .addType(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u)
552                 .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u)
553                 .build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
554         const vk::Unique<vk::VkDescriptorSet>           descriptorSet           (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
555
556         // Update descriptor set infirmation
557         {
558                 vk::VkDescriptorBufferInfo      descRefUniform  = makeDescriptorBufferInfo(**refUniform, 0, refUniformSize);
559                 vk::VkDescriptorBufferInfo      descBuffer              = makeDescriptorBufferInfo(**helperBuffer, 0, helperBufferSize);
560                 vk::VkDescriptorImageInfo       descSampledImg  = makeDescriptorImageInfo(sampler, imageView, vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
561
562                 vk::DescriptorSetUpdateBuilder()
563                         .writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &descSampledImg)
564                         .writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descRefUniform)
565                         .writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descBuffer)
566                         .update(vk, device);
567         }
568
569         const vk::Unique<vk::VkPipelineLayout>          pipelineLayout          (makePipelineLayout(vk, device, *descriptorSetLayout));
570         const vk::Unique<vk::VkCommandPool>                     cmdPool                         (makeCommandPool(vk, device, PROTECTION_ENABLED, queueFamilyIndex));
571
572         // Reset helper SSBO
573         {
574                 const vk::Unique<vk::VkFence>                   fence                           (vk::createFence(vk, device));
575                 const vk::Unique<vk::VkPipeline>                resetSSBOPipeline       (makeComputePipeline(vk, device, *pipelineLayout, *resetSSBOShader, DE_NULL));
576                 const vk::Unique<vk::VkCommandBuffer>   resetCmdBuffer          (vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
577                 beginCommandBuffer(vk, *resetCmdBuffer);
578
579                 vk.cmdBindPipeline(*resetCmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *resetSSBOPipeline);
580                 vk.cmdBindDescriptorSets(*resetCmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &*descriptorSet, 0u, DE_NULL);
581                 vk.cmdDispatch(*resetCmdBuffer, 1u, 1u, 1u);
582
583                 endCommandBuffer(vk, *resetCmdBuffer);
584                 VK_CHECK(queueSubmit(ctx, PROTECTION_ENABLED, queue, *resetCmdBuffer, *fence, ~0ull));
585         }
586
587         // Create validation compute commands & submit
588         vk::VkResult                                                    queueSubmitResult;
589         {
590                 const vk::Unique<vk::VkFence>                   fence                           (vk::createFence(vk, device));
591                 const vk::Unique<vk::VkPipeline>                validationPipeline      (makeComputePipeline(vk, device, *pipelineLayout, *validatorShader, DE_NULL));
592                 const vk::Unique<vk::VkCommandBuffer>   cmdBuffer                       (vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
593
594                 beginCommandBuffer(vk, *cmdBuffer);
595
596                 vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *validationPipeline);
597                 vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &*descriptorSet, 0u, DE_NULL);
598                 vk.cmdDispatch(*cmdBuffer, CHECK_SIZE, 1u, 1u);
599
600                 endCommandBuffer(vk, *cmdBuffer);
601
602                 queueSubmitResult = queueSubmit(ctx, PROTECTION_ENABLED, queue, *cmdBuffer, *fence, oneSec * 5);
603         }
604
605         // \todo do we need to check the fence status?
606         if (queueSubmitResult == vk::VK_TIMEOUT)
607                 return false;
608
609         // at this point the submit result should be VK_TRUE
610         VK_CHECK(queueSubmitResult);
611         return true;
612 }
613
614 void testShaders (vk::SourceCollections& dst, const TestConfig config)
615 {
616         const char* const       shaderHeader            =
617                         "layout(constant_id = 1) const float threshold = 0.01f;\n"
618                         "layout(set = 0, binding = 0) uniform highp sampler2D protectedImage;\n"
619                         "\n"
620                         "struct validationData {\n"
621                         "    highp vec4 imageCoord;\n"
622                         "    highp vec4 imageRefMinBound;\n"
623                         "    highp vec4 imageRefMaxBound;\n"
624                         "};\n"
625                         "layout(std140, set = 0, binding = 1) uniform Data\n"
626                         "{\n"
627                         "    validationData ref[250];\n"
628                         "};\n";
629
630         const char* const       compareFunction =
631                         "bool compare(highp vec4 value, highp vec4 minValue, highp vec4 maxValue)\n"
632                         "{\n"
633                         "    return all(greaterThanEqual(value, minValue - threshold)) && all(lessThanEqual(value, maxValue + threshold));\n"
634                         "}\n";
635
636         std::map<std::string, std::string> validatorSpec;
637         validatorSpec["CHECK_SIZE"]                     = de::toString((deUint32)CHECK_SIZE);
638         validatorSpec["SHADER_HEADER"]          = shaderHeader;
639         validatorSpec["COMPARE_FUNCTION"]       = compareFunction;
640
641         const char* const validatorShader =
642                 "#version 450\n"
643                 "\n"
644                 "${SHADER_HEADER}"
645                 "\n"
646                 "layout(std140, set = 0, binding = 2) buffer ProtectedHelper\n"
647                 "{\n"
648                 "    highp uint zero;\n"
649                 "    highp uint dummyOut;\n"
650                 "} helper;\n"
651                 "\n"
652                 "void error()\n"
653                 "{\n"
654                 "    for (uint x = 0u; x < 10u; x += helper.zero)\n"
655                 "        atomicAdd(helper.dummyOut, 1u);\n"
656                 "}\n"
657                 "\n"
658                 "${COMPARE_FUNCTION}"
659                 "\n"
660                 "void main(void)\n"
661                 "{\n"
662                 "    int idx = int(gl_GlobalInvocationID.x);\n"
663                 "    vec4 currentValue = texture(protectedImage, ref[idx].imageCoord.xy);\n"
664                 "    if (!compare(currentValue, ref[idx].imageRefMinBound, ref[idx].imageRefMaxBound))\n"
665                 "    {\n"
666                 "      error();\n"
667                 "    }\n"
668                 "}\n";
669
670         const char* const resetSSBOShader =
671                 "#version 450\n"
672                 "layout(local_size_x = 1) in;\n"
673                 "\n"
674                 "layout(std140, set=0, binding=2) buffer ProtectedHelper\n"
675                 "{\n"
676                 "    highp uint zero; // set to 0\n"
677                 "    highp uint dummyOut;\n"
678                 "} helper;\n"
679                 "\n"
680                 "void main (void)\n"
681                 "{\n"
682                 "    helper.zero = 0;\n"
683                 "    helper.dummyOut = 0;\n"
684                 "}\n";
685
686         dst.glslSources.add("ResetSSBO") << glu::ComputeSource(resetSSBOShader);
687         dst.glslSources.add("ImageValidator") << glu::ComputeSource(tcu::StringTemplate(validatorShader).specialize(validatorSpec));
688
689         if (config.shaderType == glu::SHADERTYPE_COMPUTE)
690                 return; // Bail early as the YCbCr image validator already have the test programs set for compute tests
691
692         const char* const compareOperation =
693                         "    highp vec4 currentValue = texture(protectedImage, ref[v_idx].imageCoord.xy);\n"
694                         "    if (compare(currentValue, ref[v_idx].imageRefMinBound, ref[v_idx].imageRefMaxBound))\n"
695                         "    {\n"
696                         "        o_color = vec4(0.0f, 1.0f, 0.0f, 1.0f);\n"     // everything is ok, green
697                         "    }\n"
698                         "    else"
699                         "    {\n"
700                         "        o_color = vec4(1.0f, 0.0f, 0.0f, 1.0f);\n"
701                         "    }\n";
702
703         std::map<std::string, std::string>      shaderSpec;
704         shaderSpec["SHADER_HEADER"]             = shaderHeader;
705         shaderSpec["COMPARE_FUNCTION"]  = compareFunction;
706         shaderSpec["COMPARE_OPERATION"] = compareOperation;
707
708         if (config.shaderType == glu::SHADERTYPE_VERTEX)
709         {
710                 const char* const vertexShader =
711                         "#version 450\n"
712                         "${SHADER_HEADER}\n"
713                         "\n"
714                         "layout(location = 0) in highp vec2 a_position;\n"
715                         "layout(location = 0) flat out highp vec4 o_color;\n"
716                         "\n"
717                         "${COMPARE_FUNCTION}"
718                         "\n"
719                         "void main(void)\n"
720                         "{\n"
721                         "    gl_Position = vec4(a_position, 0.0f, 1.0f);\n"
722                         "    gl_PointSize = 1.0f;\n"
723                         "    int v_idx = gl_VertexIndex;\n"
724                         "${COMPARE_OPERATION}"
725                         "}\n";
726
727                 const char* const fragmentShader =
728                         "#version 450\n"
729                         "\n"
730                         "layout(location = 0) flat in highp vec4 v_color;\n"
731                         "layout(location = 0) out highp vec4 o_color;\n"
732                         "\n"
733                         "void main(void)\n"
734                         "{\n"
735                         "    o_color = v_color;\n"
736                         "}\n";
737
738                 dst.glslSources.add("vert") << glu::VertexSource(tcu::StringTemplate(vertexShader).specialize(shaderSpec));
739                 dst.glslSources.add("frag") << glu::FragmentSource(fragmentShader);
740         }
741         else if (config.shaderType == glu::SHADERTYPE_FRAGMENT)
742         {
743                 const char* const vertexShader =
744                         "#version 450\n"
745                         "layout(location = 0) in highp vec2 a_position;\n"
746                         "layout(location = 0) flat out highp int o_idx;\n"
747                         "\n"
748                         "void main(void)\n"
749                         "{\n"
750                         "    gl_Position = vec4(a_position, 0.0f, 1.0f);\n"
751                         "    gl_PointSize = 1.0f;\n"
752                         "    o_idx = gl_VertexIndex;\n"
753                         "}\n";
754
755                 const char* const fragmentShader =
756                         "#version 450\n"
757                         "${SHADER_HEADER}\n"
758                         "\n"
759                         "layout(location = 0) flat in highp int v_idx;\n"
760                         "layout(location = 0) out highp vec4 o_color;\n"
761                         "\n"
762                         "${COMPARE_FUNCTION}"
763                         "\n"
764                         "void main(void)\n"
765                         "{\n"
766                         "${COMPARE_OPERATION}"
767                         "}\n";
768
769                 dst.glslSources.add("vert") << glu::VertexSource(vertexShader);
770                 dst.glslSources.add("frag") << glu::FragmentSource(tcu::StringTemplate(fragmentShader).specialize(shaderSpec));
771         }
772 }
773
774 de::MovePtr<vk::YCbCrImageWithMemory>   createYcbcrImage2D      (ProtectedContext&                              context,
775                                                                                                                          const ProtectionMode                   protectionMode,
776                                                                                                                          const deUint32                                 width,
777                                                                                                                          const deUint32                                 height,
778                                                                                                                          const vk::VkFormat                             format,
779                                                                                                                          const vk::VkImageCreateFlags   createFlags,
780                                                                                                                          const vk::VkImageUsageFlags    usageFlags)
781 {
782         const vk::DeviceInterface&      vk                      = context.getDeviceInterface();
783         const vk::VkDevice&                     device          = context.getDevice();
784         vk::Allocator&                          allocator       = context.getDefaultAllocator();
785         const deUint32                          queueIdx        = context.getQueueFamilyIndex();
786 #ifndef NOT_PROTECTED
787         const deUint32                          flags           = (protectionMode == PROTECTION_ENABLED) ? vk::VK_IMAGE_CREATE_PROTECTED_BIT : 0x0;
788         const vk::MemoryRequirement     memReq          = (protectionMode == PROTECTION_ENABLED) ? vk::MemoryRequirement::Protected : vk::MemoryRequirement::Any;
789 #else
790         const deUint32                          flags           = 0x0;
791         const vk::MemoryRequirement     memReq          = vk::MemoryRequirement::Any;
792         DE_UNREF(protectionMode);
793 #endif
794
795         const vk::VkImageCreateInfo     params          =
796         {
797                 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                // VkStructureType                      stype
798                 DE_NULL,                                                                                // const void*                          pNext
799                 (vk::VkImageCreateFlags)(flags | createFlags),  // VkImageCreateFlags           flags
800                 vk::VK_IMAGE_TYPE_2D,                                                   // VkImageType                          imageType
801                 format,                                                                                 // VkFormat                                     format
802                 { width, height, 1 },                                                   // VkExtent3D                           extent
803                 1u,                                                                                             // deUint32                                     mipLevels
804                 1u,                                                                                             // deUint32                                     arrayLayers
805                 vk::VK_SAMPLE_COUNT_1_BIT,                                              // VkSampleCountFlagBits        samples
806                 vk::VK_IMAGE_TILING_OPTIMAL,                                    // VkImageTiling                        tiling
807                 usageFlags,                                                                             // VkImageUsageFlags            usage
808                 vk::VK_SHARING_MODE_EXCLUSIVE,                                  // VkSharingMode                        sharingMode
809                 1u,                                                                                             // deUint32                                     queueFamilyIndexCount
810                 &queueIdx,                                                                              // const deUint32*                      pQueueFamilyIndices
811                 vk::VK_IMAGE_LAYOUT_UNDEFINED,                                  // VkImageLayout                        initialLayout
812         };
813
814         return de::MovePtr<vk::YCbCrImageWithMemory>(new vk::YCbCrImageWithMemory(vk, device, allocator, params, memReq));
815 }
816
817
818 void renderYCbCrToColor (ProtectedContext&                                                      ctx,
819                                                  const tcu::UVec2                                                       size,
820                                                  const vk::VkSampler                                            ycbcrSampler,
821                                                  const vk::VkImageView                                          ycbcrImageView,
822                                                  const vk::VkImage                                                      colorImage,
823                                                  const vk::VkImageView                                          colorImageView,
824                                                  const std::vector<YCbCrValidationData>&        referenceData,
825                                                  const std::vector<tcu::Vec2>&                          posCoords,
826                                                  const deUint32                                                         combinedSamplerDescriptorCount)
827 {
828         const vk::DeviceInterface&                                      vk                                      = ctx.getDeviceInterface();
829         const vk::VkDevice                                                      device                          = ctx.getDevice();
830         const vk::VkQueue                                                       queue                           = ctx.getQueue();
831         const deUint32                                                          queueFamilyIndex        = ctx.getQueueFamilyIndex();
832
833         const vk::Unique<vk::VkRenderPass>                      renderPass                      (createRenderPass(ctx, s_colorFormat));
834         const vk::Unique<vk::VkFramebuffer>                     framebuffer                     (createFramebuffer(ctx, size.x(), size.y(), *renderPass, colorImageView));
835         const vk::Unique<vk::VkShaderModule>            vertexShader            (createShaderModule(vk, device, ctx.getBinaryCollection().get("vert"), 0));
836         const vk::Unique<vk::VkShaderModule>            fragmentShader          (createShaderModule(vk, device, ctx.getBinaryCollection().get("frag"), 0));
837         const vk::Unique<vk::VkDescriptorSetLayout>     descriptorSetLayout (vk::DescriptorSetLayoutBuilder()
838                                                                                                                                                 .addSingleSamplerBinding(vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
839                                                                                                                                                                                          vk::VK_SHADER_STAGE_ALL,
840                                                                                                                                                                                          &ycbcrSampler)
841                                                                                                                                                 .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, vk::VK_SHADER_STAGE_ALL)
842                                                                                                                                                 .build(vk, device));
843         const vk::Unique<vk::VkDescriptorPool>          descriptorPool          (vk::DescriptorPoolBuilder()
844                                                                                                                                                 .addType(vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, combinedSamplerDescriptorCount)
845                                                                                                                                                 .addType(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u)
846                                                                                                                                                 .build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
847         const vk::Unique<vk::VkDescriptorSet>           descriptorSet           (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
848         const vk::Unique<vk::VkPipelineLayout>          pipelineLayout          (makePipelineLayout(vk, device, *descriptorSetLayout));
849
850
851         const deUint32                                                          refUniformSize          = (deUint32)(sizeof(YCbCrValidationData) * referenceData.size());
852         const de::UniquePtr<vk::BufferWithMemory>       refUniform                      (makeBuffer(ctx,
853                                                                                                                                                                 PROTECTION_DISABLED,
854                                                                                                                                                                 queueFamilyIndex,
855                                                                                                                                                                 refUniformSize,
856                                                                                                                                                                 vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
857                                                                                                                                                                 vk::MemoryRequirement::HostVisible));
858
859         // Set the reference uniform data
860         {
861                 deMemcpy(refUniform->getAllocation().getHostPtr(), &referenceData[0], refUniformSize);
862                 vk::flushMappedMemoryRange(vk, device, refUniform->getAllocation().getMemory(), refUniform->getAllocation().getOffset(), refUniformSize);
863         }
864
865         // Update descriptor set
866         {
867                 vk::VkDescriptorImageInfo       ycbcrSampled    (makeDescriptorImageInfo(ycbcrSampler, ycbcrImageView, vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL));
868                 vk::VkDescriptorBufferInfo      descRefUniform  = makeDescriptorBufferInfo(**refUniform, 0, refUniformSize);
869                 vk::DescriptorSetUpdateBuilder()
870                         .writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &ycbcrSampled)
871                         .writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descRefUniform)
872                         .update(vk, device);
873         }
874
875         VertexBindings                                                  vertexBindings;
876         VertexAttribs                                                   vertexAttribs;
877         de::MovePtr<vk::BufferWithMemory>               vertexBuffer;
878         {
879                 const deUint32  bufferSize              = (deUint32)(sizeof(tcu::Vec2) * posCoords.size());
880                 {
881                         const vk::VkVertexInputBindingDescription       inputBinding    =
882                         {
883                                 0u,                                                                     // deUint32                                     binding;
884                                 sizeof(tcu::Vec2),                                      // deUint32                                     strideInBytes;
885                                 vk::VK_VERTEX_INPUT_RATE_VERTEX         // VkVertexInputStepRate        inputRate;
886                         };
887                         const vk::VkVertexInputAttributeDescription     inputAttribute  =
888                         {
889                                 0u,                                                                     // deUint32     location;
890                                 0u,                                                                     // deUint32     binding;
891                                 vk::VK_FORMAT_R32G32_SFLOAT,            // VkFormat     format;
892                                 0u                                                                      // deUint32     offsetInBytes;
893                         };
894
895                         vertexBindings.push_back(inputBinding);
896                         vertexAttribs.push_back(inputAttribute);
897                 }
898
899                 vertexBuffer = makeBuffer(ctx,
900                                                                   PROTECTION_DISABLED,
901                                                                   queueFamilyIndex,
902                                                                   bufferSize,
903                                                                   vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
904                                                                   vk::MemoryRequirement::HostVisible);
905
906                 deMemcpy(vertexBuffer->getAllocation().getHostPtr(), &posCoords[0], bufferSize);
907                 vk::flushMappedMemoryRange(vk, device, vertexBuffer->getAllocation().getMemory(), vertexBuffer->getAllocation().getOffset(), bufferSize);
908         }
909
910         const vk::Unique<vk::VkPipeline>                pipeline                        (makeGraphicsPipeline(vk,
911                                                                                                                                                                           device,
912                                                                                                                                                                           *pipelineLayout,
913                                                                                                                                                                           *renderPass,
914                                                                                                                                                                           *vertexShader,
915                                                                                                                                                                           *fragmentShader,
916                                                                                                                                                                           vertexBindings,
917                                                                                                                                                                           vertexAttribs,
918                                                                                                                                                                           size,
919                                                                                                                                                                           vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST));
920         const vk::Unique<vk::VkCommandPool>             cmdPool                 (makeCommandPool(vk, device, PROTECTION_ENABLED, queueFamilyIndex));
921         const vk::Unique<vk::VkCommandBuffer>   cmdBuffer               (vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
922
923         beginCommandBuffer(vk, *cmdBuffer);
924         {
925                 const vk::VkImageMemoryBarrier  attachmentStartBarrier =
926                 {
927                         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
928                         DE_NULL,
929                         0u,
930                         vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
931                         vk::VK_IMAGE_LAYOUT_UNDEFINED,
932                         vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
933                         queueFamilyIndex,
934                         queueFamilyIndex,
935                         colorImage,
936                         { vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }
937                 };
938
939                 vk.cmdPipelineBarrier(*cmdBuffer,
940                                                           (vk::VkPipelineStageFlags)vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
941                                                           (vk::VkPipelineStageFlags)vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
942                                                           (vk::VkDependencyFlags)0u,
943                                                           0u, (const vk::VkMemoryBarrier*)DE_NULL,
944                                                           0u, (const vk::VkBufferMemoryBarrier*)DE_NULL,
945                                                           1u, &attachmentStartBarrier);
946         }
947
948         beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, vk::makeRect2D(0, 0, size.x(), size.y()), tcu::Vec4(0.0f, 0.0f, 0.5f, 1.0f));
949
950         vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
951         vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &*descriptorSet, 0u, DE_NULL);
952
953         {
954                 const vk::VkDeviceSize vertexBufferOffset = 0;
955                 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &**vertexBuffer, &vertexBufferOffset);
956         }
957
958         vk.cmdDraw(*cmdBuffer, /*vertexCount*/ (deUint32)posCoords.size(), 1u, 0u, 0u);
959
960         endRenderPass(vk, *cmdBuffer);
961
962         // color attachment render end barrier
963         {
964                 const vk::VkImageMemoryBarrier  attachmentEndBarrier =
965                 {
966                         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
967                         DE_NULL,
968                         vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
969                         vk::VK_ACCESS_SHADER_READ_BIT,
970                         vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
971                         vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
972                         queueFamilyIndex,
973                         queueFamilyIndex,
974                         colorImage,
975                         { vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }
976                 };
977
978                 vk.cmdPipelineBarrier(*cmdBuffer,
979                                                           (vk::VkPipelineStageFlags)vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
980                                                           (vk::VkPipelineStageFlags)vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
981                                                           (vk::VkDependencyFlags)0u,
982                                                           0u, (const vk::VkMemoryBarrier*)DE_NULL,
983                                                           0u, (const vk::VkBufferMemoryBarrier*)DE_NULL,
984                                                           1u, &attachmentEndBarrier);
985         }
986
987         endCommandBuffer(vk, *cmdBuffer);
988
989         // Submit command buffer
990         {
991                 const vk::Unique<vk::VkFence>   fence           (vk::createFence(vk, device));
992                 VK_CHECK(queueSubmit(ctx, PROTECTION_ENABLED, queue, *cmdBuffer, *fence, ~0ull));
993         }
994 }
995
996 void generateYCbCrImage (ProtectedContext&                              ctx,
997                                                 const TestConfig&                               config,
998                                                 const tcu::UVec2                                size,
999                                                 const std::vector<tcu::Vec2>&   texCoords,
1000                                                 ycbcr::MultiPlaneImageData&             ycbcrSrc,
1001                                                 std::vector<tcu::Vec4>&                 ycbcrMinBounds,
1002                                                 std::vector<tcu::Vec4>&                 ycbcrMaxBounds)
1003 {
1004         tcu::TestLog&                                           log                                             (ctx.getTestContext().getLog());
1005         const std::vector<tcu::FloatFormat>     filteringPrecision              (ycbcr::getPrecision(config.format));
1006         const std::vector<tcu::FloatFormat>     conversionPrecision             (ycbcr::getPrecision(config.format));
1007         const tcu::UVec4                                        bitDepth                                (ycbcr::getYCbCrBitDepth(config.format));
1008         bool                                                            explicitReconstruction  = config.explicitReconstruction;
1009         const deUint32                                          subTexelPrecisionBits   (vk::getPhysicalDeviceProperties(ctx.getInstanceDriver(),
1010                                                                                                                                                                                                  ctx.getPhysicalDevice()).limits.subTexelPrecisionBits);
1011
1012
1013         const vk::PlanarFormatDescription       planeInfo                               (vk::getPlanarFormatDescription(config.format));
1014
1015         deUint32                                                        nullAccessData                  (0u);
1016         ycbcr::ChannelAccess                            nullAccess                              (tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT, 1u, tcu::IVec3(size.x(), size.y(), 1), tcu::IVec3(0, 0, 0), &nullAccessData, 0u);
1017         deUint32                                                        nullAccessAlphaData             (~0u);
1018         ycbcr::ChannelAccess                            nullAccessAlpha                 (tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT, 1u, tcu::IVec3(size.x(), size.y(), 1), tcu::IVec3(0, 0, 0), &nullAccessAlphaData, 0u);
1019         ycbcr::ChannelAccess                            rChannelAccess                  (planeInfo.hasChannelNdx(0) ? getChannelAccess(ycbcrSrc, planeInfo, size, 0) : nullAccess);
1020         ycbcr::ChannelAccess                            gChannelAccess                  (planeInfo.hasChannelNdx(1) ? getChannelAccess(ycbcrSrc, planeInfo, size, 1) : nullAccess);
1021         ycbcr::ChannelAccess                            bChannelAccess                  (planeInfo.hasChannelNdx(2) ? getChannelAccess(ycbcrSrc, planeInfo, size, 2) : nullAccess);
1022         ycbcr::ChannelAccess                            aChannelAccess                  (planeInfo.hasChannelNdx(3) ? getChannelAccess(ycbcrSrc, planeInfo, size, 3) : nullAccessAlpha);
1023         const bool                                                      implicitNearestCosited  ((config.chromaFilter == vk::VK_FILTER_NEAREST && !explicitReconstruction) &&
1024                                                                                                                                  (config.xChromaOffset == vk::VK_CHROMA_LOCATION_COSITED_EVEN_KHR || config.yChromaOffset == vk::VK_CHROMA_LOCATION_COSITED_EVEN_KHR));
1025
1026         for (deUint32 planeNdx = 0; planeNdx < planeInfo.numPlanes; planeNdx++)
1027                 deMemset(ycbcrSrc.getPlanePtr(planeNdx), 0u, ycbcrSrc.getPlaneSize(planeNdx));
1028
1029         // \todo Limit values to only values that produce defined values using selected colorRange and colorModel? The verification code handles those cases already correctly.
1030         if (planeInfo.hasChannelNdx(0))
1031         {
1032                 for (int y = 0; y < rChannelAccess.getSize().y(); y++)
1033                 for (int x = 0; x < rChannelAccess.getSize().x(); x++)
1034                         rChannelAccess.setChannel(tcu::IVec3(x, y, 0), (float)x / (float)rChannelAccess.getSize().x());
1035         }
1036
1037         if (planeInfo.hasChannelNdx(1))
1038         {
1039                 for (int y = 0; y < gChannelAccess.getSize().y(); y++)
1040                 for (int x = 0; x < gChannelAccess.getSize().x(); x++)
1041                         gChannelAccess.setChannel(tcu::IVec3(x, y, 0), (float)y / (float)gChannelAccess.getSize().y());
1042         }
1043
1044         if (planeInfo.hasChannelNdx(2))
1045         {
1046                 for (int y = 0; y < bChannelAccess.getSize().y(); y++)
1047                 for (int x = 0; x < bChannelAccess.getSize().x(); x++)
1048                         bChannelAccess.setChannel(tcu::IVec3(x, y, 0), (float)(x + y) / (float)(bChannelAccess.getSize().x() + bChannelAccess.getSize().y()));
1049         }
1050
1051         if (planeInfo.hasChannelNdx(3))
1052         {
1053                 for (int y = 0; y < aChannelAccess.getSize().y(); y++)
1054                 for (int x = 0; x < aChannelAccess.getSize().x(); x++)
1055                         aChannelAccess.setChannel(tcu::IVec3(x, y, 0), (float)(x * y) / (float)(aChannelAccess.getSize().x() * aChannelAccess.getSize().y()));
1056         }
1057
1058         std::vector<tcu::Vec4>                          uvBounds;
1059         std::vector<tcu::IVec4>                         ijBounds;
1060         ycbcr::calculateBounds(rChannelAccess, gChannelAccess, bChannelAccess, aChannelAccess, bitDepth, texCoords, filteringPrecision, conversionPrecision, subTexelPrecisionBits, config.textureFilter, config.colorModel, config.colorRange, config.chromaFilter, config.xChromaOffset, config.yChromaOffset, config.componentMapping, explicitReconstruction, config.addressModeU, config.addressModeV, ycbcrMinBounds, ycbcrMaxBounds, uvBounds, ijBounds);
1061
1062         // Handle case: If implicit reconstruction and chromaFilter == NEAREST, an implementation may behave as if both chroma offsets are MIDPOINT.
1063         if (implicitNearestCosited)
1064         {
1065                 std::vector<tcu::Vec4>                  relaxedYcbcrMinBounds;
1066                 std::vector<tcu::Vec4>                  relaxedYcbcrMaxBounds;
1067
1068                 ycbcr::calculateBounds(rChannelAccess, gChannelAccess, bChannelAccess, aChannelAccess, bitDepth, texCoords, filteringPrecision, conversionPrecision, subTexelPrecisionBits, config.textureFilter, config.colorModel, config.colorRange, config.chromaFilter, vk::VK_CHROMA_LOCATION_MIDPOINT_KHR, vk::VK_CHROMA_LOCATION_MIDPOINT_KHR, config.componentMapping, explicitReconstruction, config.addressModeU, config.addressModeV, relaxedYcbcrMinBounds, relaxedYcbcrMaxBounds, uvBounds, ijBounds);
1069
1070                 DE_ASSERT(relaxedYcbcrMinBounds.size() == ycbcrMinBounds.size());
1071                 DE_ASSERT(relaxedYcbcrMaxBounds.size() == ycbcrMaxBounds.size());
1072
1073                 for (size_t i = 0; i < ycbcrMinBounds.size(); i++)
1074                 {
1075                         ycbcrMinBounds[i] = tcu::Vec4(de::min<float>(ycbcrMinBounds[i].x(), relaxedYcbcrMinBounds[i].x()),
1076                                                                                   de::min<float>(ycbcrMinBounds[i].y(), relaxedYcbcrMinBounds[i].y()),
1077                                                                                   de::min<float>(ycbcrMinBounds[i].z(), relaxedYcbcrMinBounds[i].z()),
1078                                                                                   de::min<float>(ycbcrMinBounds[i].w(), relaxedYcbcrMinBounds[i].w()));
1079
1080                         ycbcrMaxBounds[i] = tcu::Vec4(de::max<float>(ycbcrMaxBounds[i].x(), relaxedYcbcrMaxBounds[i].x()),
1081                                                                                   de::max<float>(ycbcrMaxBounds[i].y(), relaxedYcbcrMaxBounds[i].y()),
1082                                                                                   de::max<float>(ycbcrMaxBounds[i].z(), relaxedYcbcrMaxBounds[i].z()),
1083                                                                                   de::max<float>(ycbcrMaxBounds[i].w(), relaxedYcbcrMaxBounds[i].w()));
1084                 }
1085         }
1086
1087         if (vk::isYCbCrFormat(config.format))
1088         {
1089                 tcu::TextureLevel       rImage  (tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT), rChannelAccess.getSize().x(), rChannelAccess.getSize().y());
1090                 tcu::TextureLevel       gImage  (tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT), gChannelAccess.getSize().x(), gChannelAccess.getSize().y());
1091                 tcu::TextureLevel       bImage  (tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT), bChannelAccess.getSize().x(), bChannelAccess.getSize().y());
1092                 tcu::TextureLevel       aImage  (tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT), aChannelAccess.getSize().x(), aChannelAccess.getSize().y());
1093
1094                 for (int y = 0; y < (int)rChannelAccess.getSize().y(); y++)
1095                 for (int x = 0; x < (int)rChannelAccess.getSize().x(); x++)
1096                         rImage.getAccess().setPixel(tcu::Vec4(rChannelAccess.getChannel(tcu::IVec3(x, y, 0))), x, y);
1097
1098                 for (int y = 0; y < (int)gChannelAccess.getSize().y(); y++)
1099                 for (int x = 0; x < (int)gChannelAccess.getSize().x(); x++)
1100                         gImage.getAccess().setPixel(tcu::Vec4(gChannelAccess.getChannel(tcu::IVec3(x, y, 0))), x, y);
1101
1102                 for (int y = 0; y < (int)bChannelAccess.getSize().y(); y++)
1103                 for (int x = 0; x < (int)bChannelAccess.getSize().x(); x++)
1104                         bImage.getAccess().setPixel(tcu::Vec4(bChannelAccess.getChannel(tcu::IVec3(x, y, 0))), x, y);
1105
1106                 for (int y = 0; y < (int)aChannelAccess.getSize().y(); y++)
1107                 for (int x = 0; x < (int)aChannelAccess.getSize().x(); x++)
1108                         aImage.getAccess().setPixel(tcu::Vec4(aChannelAccess.getChannel(tcu::IVec3(x, y, 0))), x, y);
1109
1110                 {
1111                         const tcu::Vec4 scale   (1.0f);
1112                         const tcu::Vec4 bias    (0.0f);
1113
1114                         log << tcu::TestLog::Image("SourceImageR", "SourceImageR", rImage.getAccess(), scale, bias);
1115                         log << tcu::TestLog::Image("SourceImageG", "SourceImageG", gImage.getAccess(), scale, bias);
1116                         log << tcu::TestLog::Image("SourceImageB", "SourceImageB", bImage.getAccess(), scale, bias);
1117                         log << tcu::TestLog::Image("SourceImageA", "SourceImageA", aImage.getAccess(), scale, bias);
1118                 }
1119         }
1120         else
1121         {
1122                 tcu::TextureLevel       ycbcrSrcImage   (vk::mapVkFormat(config.format), size.x(), size.y());
1123
1124                 for (int y = 0; y < (int)size.y(); y++)
1125                 for (int x = 0; x < (int)size.x(); x++)
1126                 {
1127                         const tcu::IVec3 pos (x, y, 0);
1128                         ycbcrSrcImage.getAccess().setPixel(tcu::Vec4(rChannelAccess.getChannel(pos),
1129                                                                                                                  gChannelAccess.getChannel(pos),
1130                                                                                                                  bChannelAccess.getChannel(pos),
1131                                                                                                                  aChannelAccess.getChannel(pos)),
1132                                                                                            x, y);
1133                 }
1134
1135                 log << tcu::TestLog::Image("SourceImage", "SourceImage", ycbcrSrcImage.getAccess());
1136         }
1137 }
1138
1139 tcu::TestStatus conversionTest (Context& context, TestConfig config)
1140 {
1141         std::vector<std::string>                                                        requiredDevExt;
1142         requiredDevExt.push_back("VK_KHR_sampler_ycbcr_conversion");
1143         requiredDevExt.push_back("VK_KHR_get_memory_requirements2");
1144         requiredDevExt.push_back("VK_KHR_bind_memory2");
1145         requiredDevExt.push_back("VK_KHR_maintenance1");
1146
1147         const tcu::UVec2                                                                        size                                    (ycbcr::isXChromaSubsampled(config.format) ? 12 : 7,
1148                                                                                                                                                                  ycbcr::isYChromaSubsampled(config.format) ?  8 : 13);
1149
1150         ProtectedContext                                                                        ctx                                             (context, std::vector<std::string>(), requiredDevExt);
1151         const vk::DeviceInterface&                                                      vk                                              = ctx.getDeviceInterface();
1152         const vk::VkDevice                                                                      device                                  = ctx.getDevice();
1153         const deUint32                                                                          queueFamilyIndex                = ctx.getQueueFamilyIndex();
1154
1155         tcu::TestLog&                                                                           log                                             (context.getTestContext().getLog());
1156
1157         validateFormatSupport(ctx, config);
1158         logTestCaseInfo(log, config);
1159
1160         const vk::VkImageCreateFlagBits                                         ycbcrImageFlags                  = config.disjoint
1161                                                                                                                                                                         ? vk::VK_IMAGE_CREATE_DISJOINT_BIT
1162                                                                                                                                                                         : (vk::VkImageCreateFlagBits)0u;
1163         const de::MovePtr<vk::YCbCrImageWithMemory>                     ycbcrImage                              (createYcbcrImage2D(ctx, PROTECTION_ENABLED,
1164                                                                                                                                                                                                         size.x(), size.y(),
1165                                                                                                                                                                                                         config.format,
1166                                                                                                                                                                                                         ycbcrImageFlags,
1167                                                                                                                                                                                                         vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT
1168                                                                                                                                                                                                          | vk::VK_IMAGE_USAGE_SAMPLED_BIT));
1169         const vk::Unique<vk::VkSamplerYcbcrConversion>          conversion                              (createConversion(vk,
1170                                                                                                                                                                                                   device,
1171                                                                                                                                                                                                   config.format,
1172                                                                                                                                                                                                   config.colorModel,
1173                                                                                                                                                                                                   config.colorRange,
1174                                                                                                                                                                                                   config.xChromaOffset,
1175                                                                                                                                                                                                   config.yChromaOffset,
1176                                                                                                                                                                                                   config.chromaFilter,
1177                                                                                                                                                                                                   config.componentMapping,
1178                                                                                                                                                                                                   config.explicitReconstruction));
1179         const vk::Unique<vk::VkSampler>                                         ycbcrSampler                    (createSampler(vk,
1180                                                                                                                                                                                            device,
1181                                                                                                                                                                                            config.textureFilter,
1182                                                                                                                                                                                            config.addressModeU,
1183                                                                                                                                                                                            config.addressModeV,
1184                                                                                                                                                                                            *conversion));
1185         const vk::Unique<vk::VkImageView>                                       ycbcrImageView                  (createImageView(vk, device, **ycbcrImage, config.format, *conversion));
1186
1187         deUint32                                                                                        combinedSamplerDescriptorCount = 1;
1188         {
1189                 const vk::VkPhysicalDeviceImageFormatInfo2                      imageFormatInfo                         =
1190                 {
1191                         vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,      // sType
1192                         DE_NULL,                                                                                                        // pNext
1193                         config.format,                                                                                          // format
1194                         vk::VK_IMAGE_TYPE_2D,                                                                           // type
1195                         vk::VK_IMAGE_TILING_OPTIMAL,                                                            // tiling
1196                         vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT |
1197                         vk::VK_IMAGE_USAGE_SAMPLED_BIT,                                                         // usage
1198                         ycbcrImageFlags                                                                                         // flags
1199                 };
1200
1201                 vk::VkSamplerYcbcrConversionImageFormatProperties       samplerYcbcrConversionImage = {};
1202                 samplerYcbcrConversionImage.sType = vk::VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES;
1203                 samplerYcbcrConversionImage.pNext = DE_NULL;
1204
1205                 vk::VkImageFormatProperties2                                            imageFormatProperties           = {};
1206                 imageFormatProperties.sType = vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
1207                 imageFormatProperties.pNext = &samplerYcbcrConversionImage;
1208
1209                 VK_CHECK(context.getInstanceInterface().getPhysicalDeviceImageFormatProperties2(context.getPhysicalDevice(), &imageFormatInfo, &imageFormatProperties));
1210                 combinedSamplerDescriptorCount = samplerYcbcrConversionImage.combinedImageSamplerDescriptorCount;
1211         }
1212
1213         // Input attributes
1214         std::vector<tcu::Vec2>                                                          texCoords;
1215         std::vector<tcu::Vec2>                                                          posCoords;
1216         genTexCoords(texCoords, size);
1217         posCoords = computeVertexPositions((deUint32)texCoords.size(), size.cast<int>());
1218
1219         // Input validation data
1220         std::vector<tcu::Vec4>                                                          ycbcrMinBounds;
1221         std::vector<tcu::Vec4>                                                          ycbcrMaxBounds;
1222
1223         // Generate input ycbcr image and conversion reference
1224         {
1225                 ycbcr::MultiPlaneImageData                                              ycbcrSrc                                (config.format, size);
1226
1227                 generateYCbCrImage(ctx, config, size, texCoords, ycbcrSrc, ycbcrMinBounds, ycbcrMaxBounds);
1228                 logBoundImages(log, size, ycbcrMinBounds, ycbcrMaxBounds);
1229                 uploadYCbCrImage(ctx,
1230                                                  **ycbcrImage,
1231                                                  ycbcrSrc,
1232                                                  vk::VK_ACCESS_SHADER_READ_BIT,
1233                                                  vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1234         }
1235
1236         // Build up the reference data structure
1237         DE_ASSERT(posCoords.size() == ycbcrMinBounds.size());
1238         DE_ASSERT(posCoords.size() == ycbcrMaxBounds.size());
1239         DE_ASSERT(texCoords.size() >= CHECK_SIZE);
1240         std::vector<YCbCrValidationData>        referenceData;
1241         std::vector<YCbCrValidationData>        colorReferenceData;
1242
1243         for (deUint32 ndx = 0; ndx < texCoords.size(); ++ndx)
1244         {
1245                 YCbCrValidationData     data;
1246                 data.coord              = texCoords[ndx].toWidth<4>();
1247                 data.minBound   = ycbcrMinBounds[ndx];
1248                 data.maxBound   = ycbcrMaxBounds[ndx];
1249
1250                 referenceData.push_back(data);
1251
1252                 YCbCrValidationData     colorData;
1253                 colorData.coord         = posCoords[ndx].toWidth<4>();
1254                 colorData.minBound      = tcu::Vec4(0.0f, 0.9f, 0.0f, 1.0f);
1255                 colorData.maxBound      = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
1256
1257                 colorReferenceData.push_back(colorData);
1258         }
1259
1260         if (config.shaderType == glu::SHADERTYPE_VERTEX
1261                 || config.shaderType == glu::SHADERTYPE_FRAGMENT)
1262         {
1263                 const de::UniquePtr<vk::ImageWithMemory>        colorImage                      (createImage2D(ctx,
1264                                                                                                                                                                    PROTECTION_ENABLED,
1265                                                                                                                                                                    queueFamilyIndex,
1266                                                                                                                                                                    size.x(),
1267                                                                                                                                                                    size.y(),
1268                                                                                                                                                                    s_colorFormat,
1269                                                                                                                                                                    vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
1270                                                                                                                                                                     | vk::VK_IMAGE_USAGE_SAMPLED_BIT));
1271                 const vk::Unique<vk::VkImageView>                       colorImageView          (createImageView(ctx, **colorImage, s_colorFormat));
1272                 const vk::Unique<vk::VkSampler>                         colorSampler            (makeSampler(vk, device));
1273
1274                 renderYCbCrToColor(ctx, size, *ycbcrSampler, *ycbcrImageView, **colorImage, *colorImageView, referenceData, posCoords, combinedSamplerDescriptorCount);
1275
1276                 if (!validateImage(ctx, colorReferenceData, *colorSampler, *colorImageView, combinedSamplerDescriptorCount))
1277                         return tcu::TestStatus::fail("YCbCr image conversion via fragment shader failed");
1278         }
1279         else if (config.shaderType == glu::SHADERTYPE_COMPUTE)
1280         {
1281                 if (!validateImage(ctx, referenceData, *ycbcrSampler, *ycbcrImageView, combinedSamplerDescriptorCount))
1282                         return tcu::TestStatus::fail("YCbCr image conversion via compute shader failed");
1283         }
1284         else
1285         {
1286                 TCU_THROW(NotSupportedError, "Unsupported shader test type");
1287         }
1288
1289         return tcu::TestStatus::pass("YCbCr image conversion was OK");
1290 }
1291
1292 } // anonymous
1293
1294
1295 tcu::TestCaseGroup*     createYCbCrConversionTests (tcu::TestContext& testCtx)
1296 {
1297         de::MovePtr<tcu::TestCaseGroup> testGroup (new tcu::TestCaseGroup(testCtx, "ycbcr", "YCbCr conversion tests"));
1298
1299         struct {
1300                 const char *                    name;
1301                 const glu::ShaderType   type;
1302         } shaderTypes[] =
1303         {
1304                 { "fragment",   glu::SHADERTYPE_FRAGMENT        },
1305                 { "compute",    glu::SHADERTYPE_COMPUTE         }
1306         };
1307
1308         struct RangeNamePair
1309         {
1310                 const char*                                     name;
1311                 vk::VkSamplerYcbcrRange         value;
1312         };
1313         struct ChromaLocationNamePair
1314         {
1315                 const char*                             name;
1316                 vk::VkChromaLocation    value;
1317         };
1318
1319         const vk::VkComponentMapping                    identitySwizzle         =
1320         {
1321                 vk::VK_COMPONENT_SWIZZLE_IDENTITY,
1322                 vk::VK_COMPONENT_SWIZZLE_IDENTITY,
1323                 vk::VK_COMPONENT_SWIZZLE_IDENTITY,
1324                 vk::VK_COMPONENT_SWIZZLE_IDENTITY
1325         };
1326
1327         const RangeNamePair                                             colorRanges[]           =
1328         {
1329                 { "itu_full",           vk::VK_SAMPLER_YCBCR_RANGE_ITU_FULL             },
1330                 { "itu_narrow",         vk::VK_SAMPLER_YCBCR_RANGE_ITU_NARROW   }
1331         };
1332
1333         const ChromaLocationNamePair                    chromaLocations[] =
1334         {
1335                 { "cosited",            vk::VK_CHROMA_LOCATION_COSITED_EVEN             },
1336                 { "midpoint",           vk::VK_CHROMA_LOCATION_MIDPOINT                 }
1337         };
1338
1339         const struct
1340         {
1341                 const char* const                                                       name;
1342                 const vk::VkSamplerYcbcrModelConversion         value;
1343         }                                                                               colorModels[] =
1344         {
1345                 { "rgb_identity",       vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY              },
1346                 { "ycbcr_identity",     vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY    },
1347                 { "ycbcr_709",          vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709                 },
1348                 { "ycbcr_601",          vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601                 },
1349                 { "ycbcr_2020",         vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020                }
1350         };
1351
1352         const struct
1353         {
1354                 const char*                     name;
1355                 vk::VkImageTiling       value;
1356         }                                                                               imageTilings[] =
1357         {
1358                 { "tiling_linear",      vk::VK_IMAGE_TILING_LINEAR },
1359                 { "tiling_optimal",     vk::VK_IMAGE_TILING_OPTIMAL }
1360         };
1361
1362         const deUint32                                  tilingNdx                               = 1;
1363         const vk::VkImageTiling                 tiling                                  = imageTilings[tilingNdx].value;
1364         const char*                                             tilingName                              = imageTilings[tilingNdx].name;
1365
1366         const vk::VkFormat testFormats[] =
1367         {
1368                 // noChromaSubsampledFormats
1369                 vk::VK_FORMAT_R4G4B4A4_UNORM_PACK16,
1370                 vk::VK_FORMAT_B4G4R4A4_UNORM_PACK16,
1371                 vk::VK_FORMAT_R5G6B5_UNORM_PACK16,
1372                 vk::VK_FORMAT_B5G6R5_UNORM_PACK16,
1373                 vk::VK_FORMAT_R5G5B5A1_UNORM_PACK16,
1374                 vk::VK_FORMAT_B5G5R5A1_UNORM_PACK16,
1375                 vk::VK_FORMAT_A1R5G5B5_UNORM_PACK16,
1376                 vk::VK_FORMAT_R8G8B8_UNORM,
1377                 vk::VK_FORMAT_B8G8R8_UNORM,
1378                 vk::VK_FORMAT_R8G8B8A8_UNORM,
1379                 vk::VK_FORMAT_B8G8R8A8_UNORM,
1380                 vk::VK_FORMAT_A8B8G8R8_UNORM_PACK32,
1381                 vk::VK_FORMAT_A2R10G10B10_UNORM_PACK32,
1382                 vk::VK_FORMAT_A2B10G10R10_UNORM_PACK32,
1383                 vk::VK_FORMAT_R16G16B16_UNORM,
1384                 vk::VK_FORMAT_R16G16B16A16_UNORM,
1385                 vk::VK_FORMAT_R10X6_UNORM_PACK16,
1386                 vk::VK_FORMAT_R10X6G10X6_UNORM_2PACK16,
1387                 vk::VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
1388                 vk::VK_FORMAT_R12X4_UNORM_PACK16,
1389                 vk::VK_FORMAT_R12X4G12X4_UNORM_2PACK16,
1390                 vk::VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16,
1391                 vk::VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM,
1392                 vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16,
1393                 vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16,
1394                 vk::VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM,
1395
1396                 // xChromaSubsampledFormats
1397                 vk::VK_FORMAT_G8B8G8R8_422_UNORM,
1398                 vk::VK_FORMAT_B8G8R8G8_422_UNORM,
1399                 vk::VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM,
1400                 vk::VK_FORMAT_G8_B8R8_2PLANE_422_UNORM,
1401
1402                 vk::VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16,
1403                 vk::VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16,
1404                 vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16,
1405                 vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16,
1406                 vk::VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16,
1407                 vk::VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16,
1408                 vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16,
1409                 vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16,
1410                 vk::VK_FORMAT_G16B16G16R16_422_UNORM,
1411                 vk::VK_FORMAT_B16G16R16G16_422_UNORM,
1412                 vk::VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM,
1413                 vk::VK_FORMAT_G16_B16R16_2PLANE_422_UNORM,
1414
1415                 // xyChromaSubsampledFormats
1416                 vk::VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM,
1417                 vk::VK_FORMAT_G8_B8R8_2PLANE_420_UNORM,
1418                 vk::VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16,
1419                 vk::VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16,
1420                 vk::VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16,
1421                 vk::VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16,
1422                 vk::VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM,
1423                 vk::VK_FORMAT_G16_B16R16_2PLANE_420_UNORM,
1424         };
1425
1426         for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(testFormats); formatNdx++)
1427         {
1428                 const vk::VkFormat                              format          (testFormats[formatNdx]);
1429                 const std::string                               formatName      (de::toLower(std::string(getFormatName(format)).substr(10)));
1430                 de::MovePtr<tcu::TestCaseGroup> formatGroup     (new tcu::TestCaseGroup(testCtx, formatName.c_str(), ("Tests for color conversion using format " + formatName).c_str()));
1431
1432                 for (size_t shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(shaderTypes); shaderNdx++)
1433                 {
1434                         const char*                                             shaderTypeName  = shaderTypes[shaderNdx].name;
1435                         de::MovePtr<tcu::TestCaseGroup> shaderGroup (new tcu::TestCaseGroup(testCtx, shaderTypeName, "YCbCr conversion tests"));
1436
1437                         for (size_t modelNdx = 0; modelNdx < DE_LENGTH_OF_ARRAY(colorModels); modelNdx++)
1438                         {
1439                                 const char* const                                                       colorModelName  (colorModels[modelNdx].name);
1440                                 const vk::VkSamplerYcbcrModelConversion         colorModel              (colorModels[modelNdx].value);
1441
1442                                 if (colorModel != vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY && ycbcr::getYCbCrFormatChannelCount(format) < 3)
1443                                         continue;
1444
1445                                 de::MovePtr<tcu::TestCaseGroup> colorModelGroup (new tcu::TestCaseGroup(testCtx, colorModelName, "YCbCr conversion tests"));
1446
1447                                 for (size_t rangeNdx = 0; rangeNdx < DE_LENGTH_OF_ARRAY(colorRanges); rangeNdx++)
1448                                 {
1449                                         const char* const                                       colorRangeName  (colorRanges[rangeNdx].name);
1450                                         const vk::VkSamplerYcbcrRange           colorRange              (colorRanges[rangeNdx].value);
1451
1452                                         // Narrow range doesn't really work with formats that have less than 8 bits
1453                                         if (colorRange == vk::VK_SAMPLER_YCBCR_RANGE_ITU_NARROW)
1454                                         {
1455                                                 const tcu::UVec4 bitDepth       (ycbcr::getYCbCrBitDepth(format));
1456                                                 if (bitDepth[0] < 8 || bitDepth[1] < 8 || bitDepth[2] < 8)
1457                                                         continue;
1458                                         }
1459
1460                                         de::MovePtr<tcu::TestCaseGroup>         colorRangeGroup (new tcu::TestCaseGroup(testCtx, colorRangeName, ("Tests for color range " + std::string(colorRangeName)).c_str()));
1461
1462                                         for (size_t chromaOffsetNdx = 0; chromaOffsetNdx < DE_LENGTH_OF_ARRAY(chromaLocations); chromaOffsetNdx++)
1463                                         {
1464                                                 const char* const                               chromaOffsetName        (chromaLocations[chromaOffsetNdx].name);
1465                                                 const vk::VkChromaLocation              chromaOffset            (chromaLocations[chromaOffsetNdx].value);
1466
1467
1468                                                 for (deUint32 disjointNdx = 0; disjointNdx < 2; ++disjointNdx)
1469                                                 {
1470                                                         bool                            disjoint        = (disjointNdx == 1);
1471                                                         const TestConfig        config  (shaderTypes[shaderNdx].type,
1472                                                                                                                  format,
1473                                                                                                                  tiling,
1474                                                                                                                  vk::VK_FILTER_NEAREST,
1475                                                                                                                  vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1476                                                                                                                  vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1477                                                                                                                  vk::VK_FILTER_NEAREST,
1478                                                                                                                  chromaOffset,
1479                                                                                                                  chromaOffset,
1480                                                                                                                  false,
1481                                                                                                                  disjoint,
1482                                                                                                                  colorRange,
1483                                                                                                                  colorModel,
1484                                                                                                                  identitySwizzle);
1485
1486                                                         addFunctionCaseWithPrograms(colorRangeGroup.get(),
1487                                                                                                                 std::string(tilingName) + "_" + chromaOffsetName + (disjoint ? "_disjoint" : ""),
1488                                                                                                                 "",
1489                                                                                                                 checkSupport,
1490                                                                                                                 testShaders,
1491                                                                                                                 conversionTest,
1492                                                                                                                 config);
1493                                                 }
1494                                         }
1495
1496                                         colorModelGroup->addChild(colorRangeGroup.release());
1497                                 }
1498
1499                                 shaderGroup->addChild(colorModelGroup.release());
1500                         }
1501
1502                         formatGroup->addChild(shaderGroup.release());
1503
1504                 }
1505                 testGroup->addChild(formatGroup.release());
1506         }
1507
1508         return testGroup.release();
1509 }
1510
1511 } // ProtectedMem
1512 } // vkt