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