Merge pull request #276 from Ella-0/master
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / ycbcr / vktYCbCrViewTests.cpp
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2017 Google Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief YCbCr Image View Tests
22  *//*--------------------------------------------------------------------*/
23
24 #include "vktYCbCrViewTests.hpp"
25 #include "vktYCbCrUtil.hpp"
26 #include "vktTestCaseUtil.hpp"
27 #include "vktTestGroupUtil.hpp"
28 #include "vktShaderExecutor.hpp"
29
30 #include "vkStrUtil.hpp"
31 #include "vkRef.hpp"
32 #include "vkRefUtil.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkQueryUtil.hpp"
35 #include "vkMemUtil.hpp"
36 #include "vkImageUtil.hpp"
37 #include "vkCmdUtil.hpp"
38
39 #include "tcuTestLog.hpp"
40 #include "tcuVectorUtil.hpp"
41
42 #include "deStringUtil.hpp"
43 #include "deSharedPtr.hpp"
44 #include "deUniquePtr.hpp"
45 #include "deRandom.hpp"
46 #include "deSTLUtil.hpp"
47
48 namespace vkt
49 {
50 namespace ycbcr
51 {
52 namespace
53 {
54
55 using namespace vk;
56 using namespace shaderexecutor;
57
58 using tcu::UVec2;
59 using tcu::Vec2;
60 using tcu::Vec4;
61 using tcu::TestLog;
62 using de::MovePtr;
63 using de::UniquePtr;
64 using std::vector;
65 using std::string;
66
67 // List of some formats compatible with formats listed in "Plane Format Compatibility Table".
68 const VkFormat s_compatible_formats[] =
69 {
70         // 8-bit compatibility class
71         // Compatible format for VK_FORMAT_R8_UNORM
72         VK_FORMAT_R4G4_UNORM_PACK8,
73         VK_FORMAT_R8_UINT,
74         VK_FORMAT_R8_SINT,
75         // 16-bit compatibility class
76         // Compatible formats with VK_FORMAT_R8G8_UNORM, VK_FORMAT_R10X6_UNORM_PACK16, VK_FORMAT_R12X4_UNORM_PACK16 and VK_FORMAT_R16_UNORM
77         VK_FORMAT_R8G8_UNORM,
78         VK_FORMAT_R8G8_UINT,
79         VK_FORMAT_R10X6_UNORM_PACK16,
80         VK_FORMAT_R12X4_UNORM_PACK16,
81         VK_FORMAT_R16_UNORM,
82         VK_FORMAT_R16_UINT,
83         VK_FORMAT_R16_SINT,
84         VK_FORMAT_R4G4B4A4_UNORM_PACK16,
85         // 32-bit compatibility class
86         // Compatible formats for VK_FORMAT_R10X6G10X6_UNORM_2PACK16, VK_FORMAT_R12X4G12X4_UNORM_2PACK16 and VK_FORMAT_R16G16_UNORM
87         VK_FORMAT_R10X6G10X6_UNORM_2PACK16,
88         VK_FORMAT_R12X4G12X4_UNORM_2PACK16,
89         VK_FORMAT_R16G16_UNORM,
90         VK_FORMAT_R8G8B8A8_UNORM,
91         VK_FORMAT_R8G8B8A8_UINT,
92         VK_FORMAT_R32_UINT,
93 };
94
95 inline bool formatsAreCompatible (const VkFormat format0, const VkFormat format1)
96 {
97         return format0 == format1 || mapVkFormat(format0).getPixelSize() == mapVkFormat(format1).getPixelSize();
98 }
99
100 Move<VkImage> createTestImage (const DeviceInterface&   vkd,
101                                                            VkDevice                                     device,
102                                                            VkFormat                                     format,
103                                                            const UVec2&                         size,
104                                                            VkImageCreateFlags           createFlags)
105 {
106         const VkImageCreateInfo         createInfo      =
107         {
108                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
109                 DE_NULL,
110                 createFlags,
111                 VK_IMAGE_TYPE_2D,
112                 format,
113                 makeExtent3D(size.x(), size.y(), 1u),
114                 1u,             // mipLevels
115                 1u,             // arrayLayers
116                 VK_SAMPLE_COUNT_1_BIT,
117                 VK_IMAGE_TILING_OPTIMAL,
118                 VK_IMAGE_USAGE_SAMPLED_BIT|VK_IMAGE_USAGE_TRANSFER_DST_BIT,
119                 VK_SHARING_MODE_EXCLUSIVE,
120                 0u,
121                 (const deUint32*)DE_NULL,
122                 VK_IMAGE_LAYOUT_UNDEFINED,
123         };
124
125         return createImage(vkd, device, &createInfo);
126 }
127
128 Move<VkImageView> createImageView (const DeviceInterface&                               vkd,
129                                                                    VkDevice                                                             device,
130                                                                    VkImage                                                              image,
131                                                                    VkFormat                                                             format,
132                                                                    VkImageAspectFlagBits                                imageAspect,
133                                                                    const VkSamplerYcbcrConversionInfo*  samplerConversionInfo)
134 {
135         const VkImageViewCreateInfo                             viewInfo        =
136         {
137                 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
138                 samplerConversionInfo,
139                 (VkImageViewCreateFlags)0,
140                 image,
141                 VK_IMAGE_VIEW_TYPE_2D,
142                 format,
143                 {
144                         VK_COMPONENT_SWIZZLE_IDENTITY,
145                         VK_COMPONENT_SWIZZLE_IDENTITY,
146                         VK_COMPONENT_SWIZZLE_IDENTITY,
147                         VK_COMPONENT_SWIZZLE_IDENTITY,
148                 },
149                 { (VkImageAspectFlags)imageAspect, 0u, 1u, 0u, 1u },
150         };
151
152         return createImageView(vkd, device, &viewInfo);
153 }
154
155 // Descriptor layout for set 1:
156 // 0: Plane view bound as COMBINED_IMAGE_SAMPLER
157 // 1: "Whole" image bound as COMBINED_IMAGE_SAMPLER
158 //    + immutable sampler (required for color conversion)
159
160 Move<VkDescriptorSetLayout> createDescriptorSetLayout (const DeviceInterface& vkd, VkDevice device, VkSampler conversionSampler)
161 {
162         const VkDescriptorSetLayoutBinding              bindings[]      =
163         {
164                 {
165                         0u,                                                                                             // binding
166                         VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
167                         1u,                                                                                             // descriptorCount
168                         VK_SHADER_STAGE_ALL,
169                         (const VkSampler*)DE_NULL
170                 },
171                 {
172                         1u,                                                                                             // binding
173                         VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
174                         1u,                                                                                             // descriptorCount
175                         VK_SHADER_STAGE_ALL,
176                         &conversionSampler
177                 }
178         };
179         const VkDescriptorSetLayoutCreateInfo   layoutInfo      =
180         {
181                 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
182                 DE_NULL,
183                 (VkDescriptorSetLayoutCreateFlags)0u,
184                 DE_LENGTH_OF_ARRAY(bindings),
185                 bindings,
186         };
187
188         return createDescriptorSetLayout(vkd, device, &layoutInfo);
189 }
190
191 Move<VkDescriptorPool> createDescriptorPool (const DeviceInterface& vkd, VkDevice device, const deUint32 combinedSamplerDescriptorCount)
192 {
193         const VkDescriptorPoolSize                      poolSizes[]     =
194         {
195                 { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,    2u * combinedSamplerDescriptorCount     },
196         };
197         const VkDescriptorPoolCreateInfo        poolInfo        =
198         {
199                 VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
200                 DE_NULL,
201                 (VkDescriptorPoolCreateFlags)VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
202                 1u,             // maxSets
203                 DE_LENGTH_OF_ARRAY(poolSizes),
204                 poolSizes,
205         };
206
207         return createDescriptorPool(vkd, device, & poolInfo);
208 }
209
210 Move<VkDescriptorSet> createDescriptorSet (const DeviceInterface&       vkd,
211                                                                                    VkDevice                                     device,
212                                                                                    VkDescriptorPool                     descPool,
213                                                                                    VkDescriptorSetLayout        descLayout,
214                                                                                    VkImageView                          planeView,
215                                                                                    VkSampler                            planeViewSampler,
216                                                                                    VkImageView                          wholeView,
217                                                                                    VkSampler                            wholeViewSampler)
218 {
219         Move<VkDescriptorSet>   descSet;
220
221         {
222                 const VkDescriptorSetAllocateInfo       allocInfo       =
223                 {
224                         VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
225                         DE_NULL,
226                         descPool,
227                         1u,
228                         &descLayout,
229                 };
230
231                 descSet = allocateDescriptorSet(vkd, device, &allocInfo);
232         }
233
234         {
235                 const VkDescriptorImageInfo             imageInfo0                      =
236                 {
237                         planeViewSampler,
238                         planeView,
239                         VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
240                 };
241                 const VkDescriptorImageInfo             imageInfo1                      =
242                 {
243                         wholeViewSampler,
244                         wholeView,
245                         VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
246                 };
247                 const VkWriteDescriptorSet              descriptorWrites[]              =
248                 {
249                         {
250                                 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
251                                 DE_NULL,
252                                 *descSet,
253                                 0u,             // dstBinding
254                                 0u,             // dstArrayElement
255                                 1u,             // descriptorCount
256                                 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
257                                 &imageInfo0,
258                                 (const VkDescriptorBufferInfo*)DE_NULL,
259                                 (const VkBufferView*)DE_NULL,
260                         },
261                         {
262                                 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
263                                 DE_NULL,
264                                 *descSet,
265                                 1u,             // dstBinding
266                                 0u,             // dstArrayElement
267                                 1u,             // descriptorCount
268                                 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
269                                 &imageInfo1,
270                                 (const VkDescriptorBufferInfo*)DE_NULL,
271                                 (const VkBufferView*)DE_NULL,
272                         }
273                 };
274
275                 vkd.updateDescriptorSets(device, DE_LENGTH_OF_ARRAY(descriptorWrites), descriptorWrites, 0u, DE_NULL);
276         }
277
278         return descSet;
279 }
280
281 void executeImageBarrier (const DeviceInterface&                vkd,
282                                                   VkDevice                                              device,
283                                                   deUint32                                              queueFamilyNdx,
284                                                   VkPipelineStageFlags                  srcStage,
285                                                   VkPipelineStageFlags                  dstStage,
286                                                   const VkImageMemoryBarrier&   barrier)
287 {
288         const VkQueue                                   queue           = getDeviceQueue(vkd, device, queueFamilyNdx, 0u);
289         const Unique<VkCommandPool>             cmdPool         (createCommandPool(vkd, device, (VkCommandPoolCreateFlags)0, queueFamilyNdx));
290         const Unique<VkCommandBuffer>   cmdBuffer       (allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
291
292         beginCommandBuffer(vkd, *cmdBuffer);
293
294         vkd.cmdPipelineBarrier(*cmdBuffer,
295                                                    srcStage,
296                                                    dstStage,
297                                                    (VkDependencyFlags)0u,
298                                                    0u,
299                                                    (const VkMemoryBarrier*)DE_NULL,
300                                                    0u,
301                                                    (const VkBufferMemoryBarrier*)DE_NULL,
302                                                    1u,
303                                                    &barrier);
304
305         endCommandBuffer(vkd, *cmdBuffer);
306
307         submitCommandsAndWait(vkd, device, queue, *cmdBuffer);
308 }
309
310 struct TestParameters
311 {
312         enum ViewType
313         {
314                 VIEWTYPE_IMAGE_VIEW     = 0,
315                 VIEWTYPE_MEMORY_ALIAS,
316
317                 VIEWTYPE_LAST
318         };
319
320         ViewType                        viewType;
321         VkFormat                        format;
322         UVec2                           size;
323         VkImageCreateFlags      createFlags;
324         deUint32                        planeNdx;
325         VkFormat                        planeCompatibleFormat;
326         glu::ShaderType         shaderType;
327         deBool                          isCompatibilityFormat;
328
329         TestParameters (ViewType viewType_, VkFormat format_, const UVec2& size_, VkImageCreateFlags createFlags_, deUint32 planeNdx_, VkFormat planeCompatibleFormat_, glu::ShaderType shaderType_, deBool isCompatibilityFormat_)
330                 : viewType                              (viewType_)
331                 , format                                (format_)
332                 , size                                  (size_)
333                 , createFlags                   (createFlags_)
334                 , planeNdx                              (planeNdx_)
335                 , planeCompatibleFormat (planeCompatibleFormat_)
336                 , shaderType                    (shaderType_)
337                 , isCompatibilityFormat (isCompatibilityFormat_)
338         {
339         }
340
341         TestParameters (void)
342                 : viewType                              (VIEWTYPE_LAST)
343                 , format                                (VK_FORMAT_UNDEFINED)
344                 , createFlags                   (0u)
345                 , planeNdx                              (0u)
346                 , planeCompatibleFormat (VK_FORMAT_UNDEFINED)
347                 , shaderType                    (glu::SHADERTYPE_LAST)
348                 , isCompatibilityFormat (false)
349         {
350         }
351 };
352
353 static std::string getSamplerDecl(VkFormat f) {
354         if (isIntFormat(f))                     return "isampler2D";
355         else if (isUintFormat(f))       return "usampler2D";
356         else                                            return "sampler2D";
357 }
358
359 ShaderSpec getShaderSpec (const TestParameters& params)
360 {
361         ShaderSpec spec;
362
363         spec.inputs.push_back(Symbol("texCoord", glu::VarType(glu::TYPE_FLOAT_VEC2, glu::PRECISION_HIGHP)));
364         spec.outputs.push_back(Symbol("result0", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
365         spec.outputs.push_back(Symbol("result1", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
366
367         const std::string sampler = getSamplerDecl(params.planeCompatibleFormat);
368         spec.globalDeclarations =
369                 "layout(binding = 1, set = 1) uniform highp sampler2D u_image;\n"
370                 "layout(binding = 0, set = 1) uniform highp " + sampler + " u_planeView;\n";
371
372         spec.source =
373                 "result0 = texture(u_image, texCoord);\n"
374                 "result1 = vec4(texture(u_planeView, texCoord));\n";
375
376         return spec;
377 }
378
379
380 void generateLookupCoordinates (const UVec2& imageSize, size_t numCoords, de::Random* rnd, vector<Vec2>* dst)
381 {
382         dst->resize(numCoords);
383
384         for (size_t coordNdx = 0; coordNdx < numCoords; ++coordNdx)
385         {
386                 const deUint32  texelX  = rnd->getUint32() % imageSize.x();
387                 const deUint32  texelY  = rnd->getUint32() % imageSize.y();
388                 const float             x               = ((float)texelX + 0.5f) / (float)imageSize.x();
389                 const float             y               = ((float)texelY + 0.5f) / (float)imageSize.y();
390
391                 (*dst)[coordNdx] = Vec2(x, y);
392         }
393 }
394
395 void checkImageUsageSupport (Context&                   context,
396                                                          VkFormat                       format,
397                                                          VkImageUsageFlags      usage)
398 {
399         const VkFormatProperties        formatProperties        = getPhysicalDeviceFormatProperties(context.getInstanceInterface(),
400                                                                                                                                                                                 context.getPhysicalDevice(),
401                                                                                                                                                                                 format);
402         const VkFormatFeatureFlags      featureFlags            = formatProperties.optimalTilingFeatures;
403
404         if ((usage & VK_IMAGE_USAGE_SAMPLED_BIT) != 0
405                 && (featureFlags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) == 0)
406         {
407                 TCU_THROW(NotSupportedError, "Format doesn't support sampling");
408         }
409
410         // Other image usages are not handled currently
411         DE_ASSERT((usage & ~(VK_IMAGE_USAGE_TRANSFER_SRC_BIT|VK_IMAGE_USAGE_TRANSFER_DST_BIT|VK_IMAGE_USAGE_SAMPLED_BIT)) == 0);
412 }
413
414 void checkSupport(Context& context, TestParameters params)
415 {
416         const VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
417
418         checkImageSupport(context, params.format, params.createFlags);
419         checkImageUsageSupport(context, params.format, usage);
420         checkImageUsageSupport(context, params.planeCompatibleFormat, usage);
421 }
422
423 tcu::TestStatus testPlaneView (Context& context, TestParameters params)
424 {
425         de::Random                                              randomGen               (deInt32Hash((deUint32)params.format)   ^
426                                                                                                          deInt32Hash((deUint32)params.planeNdx) ^
427                                                                                                          deInt32Hash((deUint32)params.shaderType));
428
429         const InstanceInterface&                vk                              = context.getInstanceInterface();
430         const DeviceInterface&                  vkd                             = context.getDeviceInterface();
431         const VkDevice                                  device                  = context.getDevice();
432
433         const VkFormat                                  format                  = params.format;
434         const VkImageCreateFlags                createFlags             = params.createFlags;
435         const PlanarFormatDescription   formatInfo              = getPlanarFormatDescription(format);
436         const UVec2                                             size                    = params.size;
437         const UVec2                                             planeExtent             = getPlaneExtent(formatInfo, size, params.planeNdx, 0);
438         const Unique<VkImage>                   image                   (createTestImage(vkd, device, format, size, createFlags));
439         const Unique<VkImage>                   imageAlias              ((params.viewType == TestParameters::VIEWTYPE_MEMORY_ALIAS)
440                                                                                                          ? createTestImage(vkd, device, params.planeCompatibleFormat, planeExtent, createFlags)
441                                                                                                          : Move<VkImage>());
442         const vector<AllocationSp>              allocations             (allocateAndBindImageMemory(vkd, device, context.getDefaultAllocator(), *image, format, createFlags));
443
444         if (imageAlias)
445         {
446                 if ((createFlags & VK_IMAGE_CREATE_DISJOINT_BIT) != 0)
447                 {
448                         VkBindImagePlaneMemoryInfo      planeInfo       =
449                         {
450                                 VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO_KHR,
451                                 DE_NULL,
452                                 VK_IMAGE_ASPECT_PLANE_0_BIT_KHR
453                         };
454
455                         VkBindImageMemoryInfo coreInfo  =
456                         {
457                                 VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO_KHR,
458                                 &planeInfo,
459                                 *imageAlias,
460                                 allocations[params.planeNdx]->getMemory(),
461                                 allocations[params.planeNdx]->getOffset(),
462                         };
463
464                         VK_CHECK(vkd.bindImageMemory2(device, 1, &coreInfo));
465                 }
466                 else
467                 {
468                         VK_CHECK(vkd.bindImageMemory(device, *imageAlias, allocations[params.planeNdx]->getMemory(), allocations[params.planeNdx]->getOffset()));
469                 }
470         }
471
472         const VkSamplerYcbcrConversionCreateInfo        conversionInfo  =
473         {
474                 VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO,
475                 DE_NULL,
476                 format,
477                 VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY,
478                 VK_SAMPLER_YCBCR_RANGE_ITU_FULL,
479                 {
480                         VK_COMPONENT_SWIZZLE_IDENTITY,
481                         VK_COMPONENT_SWIZZLE_IDENTITY,
482                         VK_COMPONENT_SWIZZLE_IDENTITY,
483                         VK_COMPONENT_SWIZZLE_IDENTITY,
484                 },
485                 VK_CHROMA_LOCATION_MIDPOINT,
486                 VK_CHROMA_LOCATION_MIDPOINT,
487                 VK_FILTER_NEAREST,
488                 VK_FALSE,                                                                       // forceExplicitReconstruction
489         };
490         const Unique<VkSamplerYcbcrConversion>          conversion      (createSamplerYcbcrConversion(vkd, device, &conversionInfo));
491         const VkSamplerYcbcrConversionInfo                      samplerConversionInfo   =
492         {
493                 VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO,
494                 DE_NULL,
495                 *conversion,
496         };
497         const Unique<VkImageView>                                       wholeView       (createImageView(vkd, device, *image, format, VK_IMAGE_ASPECT_COLOR_BIT, &samplerConversionInfo));
498         const Unique<VkImageView>                                       planeView       (createImageView(vkd,
499                                                                                                                                                          device,
500                                                                                                                                                          !imageAlias ? *image : *imageAlias,
501                                                                                                                                                          params.planeCompatibleFormat,
502                                                                                                                                                          !imageAlias ? getPlaneAspect(params.planeNdx) : VK_IMAGE_ASPECT_COLOR_BIT,
503                                                                                                                                                          DE_NULL));
504
505         const VkSamplerCreateInfo                                       wholeSamplerInfo                =
506         {
507                 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
508                 &samplerConversionInfo,
509                 0u,
510                 VK_FILTER_NEAREST,                                                      // magFilter
511                 VK_FILTER_NEAREST,                                                      // minFilter
512                 VK_SAMPLER_MIPMAP_MODE_NEAREST,                         // mipmapMode
513                 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,          // addressModeU
514                 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,          // addressModeV
515                 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,          // addressModeW
516                 0.0f,                                                                           // mipLodBias
517                 VK_FALSE,                                                                       // anisotropyEnable
518                 1.0f,                                                                           // maxAnisotropy
519                 VK_FALSE,                                                                       // compareEnable
520                 VK_COMPARE_OP_ALWAYS,                                           // compareOp
521                 0.0f,                                                                           // minLod
522                 0.0f,                                                                           // maxLod
523                 VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,        // borderColor
524                 VK_FALSE,                                                                       // unnormalizedCoords
525         };
526         const VkSamplerCreateInfo                                       planeSamplerInfo                =
527         {
528                 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
529                 DE_NULL,
530                 0u,
531                 VK_FILTER_NEAREST,                                                      // magFilter
532                 VK_FILTER_NEAREST,                                                      // minFilter
533                 VK_SAMPLER_MIPMAP_MODE_NEAREST,                         // mipmapMode
534                 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,          // addressModeU
535                 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,          // addressModeV
536                 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,          // addressModeW
537                 0.0f,                                                                           // mipLodBias
538                 VK_FALSE,                                                                       // anisotropyEnable
539                 1.0f,                                                                           // maxAnisotropy
540                 VK_FALSE,                                                                       // compareEnable
541                 VK_COMPARE_OP_ALWAYS,                                           // compareOp
542                 0.0f,                                                                           // minLod
543                 0.0f,                                                                           // maxLod
544                 VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,        // borderColor
545                 VK_FALSE,                                                                       // unnormalizedCoords
546         };
547
548         deUint32                                                                        combinedSamplerDescriptorCount = 1;
549         {
550                 const VkPhysicalDeviceImageFormatInfo2                  imageFormatInfo                         =
551                 {
552                         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,  // sType;
553                         DE_NULL,                                                                                                // pNext;
554                         format,                                                                                                 // format;
555                         VK_IMAGE_TYPE_2D,                                                                               // type;
556                         VK_IMAGE_TILING_OPTIMAL,                                                                // tiling;
557                         VK_IMAGE_USAGE_TRANSFER_DST_BIT |
558                         VK_IMAGE_USAGE_SAMPLED_BIT,                                                             // usage;
559                         createFlags                                                                                             // flags;
560                 };
561
562                 VkSamplerYcbcrConversionImageFormatProperties   samplerYcbcrConversionImage = {};
563                 samplerYcbcrConversionImage.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES;
564                 samplerYcbcrConversionImage.pNext = DE_NULL;
565
566                 VkImageFormatProperties2                                                imageFormatProperties           = {};
567                 imageFormatProperties.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
568                 imageFormatProperties.pNext = &samplerYcbcrConversionImage;
569
570                 VkResult result = vk.getPhysicalDeviceImageFormatProperties2(context.getPhysicalDevice(), &imageFormatInfo, &imageFormatProperties);
571                 if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
572                         TCU_THROW(NotSupportedError, "Format not supported.");
573                 VK_CHECK(result);
574                 combinedSamplerDescriptorCount = samplerYcbcrConversionImage.combinedImageSamplerDescriptorCount;
575         }
576
577         const Unique<VkSampler>                                 wholeSampler(createSampler(vkd, device, &wholeSamplerInfo));
578         const Unique<VkSampler>                                 planeSampler(createSampler(vkd, device, &planeSamplerInfo));
579
580         const Unique<VkDescriptorSetLayout>             descLayout      (createDescriptorSetLayout(vkd, device, *wholeSampler));
581         const Unique<VkDescriptorPool>                  descPool        (createDescriptorPool(vkd, device, combinedSamplerDescriptorCount));
582         const Unique<VkDescriptorSet>                   descSet         (createDescriptorSet(vkd, device, *descPool, *descLayout, *planeView, *planeSampler, *wholeView, *wholeSampler));
583
584         MultiPlaneImageData                                             imageData       (format, size);
585
586         // Prepare texture data
587         fillRandom(&randomGen, &imageData);
588
589         if (imageAlias)
590         {
591                 // Transition alias to right layout first
592                 const VkImageMemoryBarrier              initAliasBarrier        =
593                 {
594                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
595                         DE_NULL,
596                         (VkAccessFlags)0,
597                         VK_ACCESS_SHADER_READ_BIT,
598                         VK_IMAGE_LAYOUT_UNDEFINED,
599                         VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
600                         VK_QUEUE_FAMILY_IGNORED,
601                         VK_QUEUE_FAMILY_IGNORED,
602                         *imageAlias,
603                         { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }
604                 };
605
606                 executeImageBarrier(vkd,
607                                                         device,
608                                                         context.getUniversalQueueFamilyIndex(),
609                                                         (VkPipelineStageFlags)VK_PIPELINE_STAGE_HOST_BIT,
610                                                         (VkPipelineStageFlags)VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
611                                                         initAliasBarrier);
612         }
613
614         // Upload and prepare image
615         uploadImage(vkd,
616                                 device,
617                                 context.getUniversalQueueFamilyIndex(),
618                                 context.getDefaultAllocator(),
619                                 *image,
620                                 imageData,
621                                 (VkAccessFlags)VK_ACCESS_SHADER_READ_BIT,
622                                 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
623
624         {
625                 const size_t    numValues               = 500;
626                 vector<Vec2>    texCoord                (numValues);
627                 vector<Vec4>    resultWhole             (numValues);
628                 vector<Vec4>    resultPlane             (numValues);
629                 vector<Vec4>    referenceWhole  (numValues);
630                 vector<Vec4>    referencePlane  (numValues);
631                 bool                    allOk                   = true;
632                 Vec4                    threshold               (0.02f);
633
634                 generateLookupCoordinates(size, numValues, &randomGen, &texCoord);
635
636                 {
637                         UniquePtr<ShaderExecutor>       executor        (createExecutor(context, params.shaderType, getShaderSpec(params), *descLayout));
638                         const void*                                     inputs[]        = { texCoord[0].getPtr() };
639                         void*                                           outputs[]       = { resultWhole[0].getPtr(), resultPlane[0].getPtr() };
640
641                         executor->execute((int)numValues, inputs, outputs, *descSet);
642                 }
643
644                 // Whole image sampling reference
645                 for (deUint32 channelNdx = 0; channelNdx < 4; channelNdx++)
646                 {
647                         if (formatInfo.hasChannelNdx(channelNdx))
648                         {
649                                 const tcu::ConstPixelBufferAccess       channelAccess   = imageData.getChannelAccess(channelNdx);
650                                 const tcu::Sampler                                      refSampler              = mapVkSampler(wholeSamplerInfo);
651                                 const tcu::Texture2DView                        refTexView              (1u, &channelAccess);
652
653                                 for (size_t ndx = 0; ndx < numValues; ++ndx)
654                                 {
655                                         const Vec2&     coord   = texCoord[ndx];
656                                         referenceWhole[ndx][channelNdx] = refTexView.sample(refSampler, coord.x(), coord.y(), 0.0f)[0];
657                                 }
658                         }
659                         else
660                         {
661                                 for (size_t ndx = 0; ndx < numValues; ++ndx)
662                                         referenceWhole[ndx][channelNdx] = channelNdx == 3 ? 1.0f : 0.0f;
663                         }
664                 }
665
666                 // Plane view sampling reference
667                 {
668                         const tcu::ConstPixelBufferAccess       planeAccess             (mapVkFormat(params.planeCompatibleFormat),
669                                                                                                                                  tcu::IVec3((int)planeExtent.x(), (int)planeExtent.y(), 1),
670                                                                                                                                  imageData.getPlanePtr(params.planeNdx));
671                         const tcu::Sampler                                      refSampler              = mapVkSampler(planeSamplerInfo);
672                         const tcu::Texture2DView                        refTexView              (1u, &planeAccess);
673
674                         for (size_t ndx = 0; ndx < numValues; ++ndx)
675                         {
676                                 const Vec2&     coord   = texCoord[ndx];
677                                 referencePlane[ndx] = refTexView.sample(refSampler, coord.x(), coord.y(), 0.0f);
678                         }
679                 }
680
681                 for (int viewNdx = 0; viewNdx < 2; ++viewNdx)
682                 {
683                         const char* const       viewName        = (viewNdx == 0) ? "complete image"     : "plane view";
684                         const vector<Vec4>&     reference       = (viewNdx == 0) ? referenceWhole       : referencePlane;
685                         const vector<Vec4>&     result          = (viewNdx == 0) ? resultWhole          : resultPlane;
686
687                         for (size_t ndx = 0; ndx < numValues; ++ndx)
688                         {
689                                 if (boolAny(greaterThanEqual(abs(result[ndx] - reference[ndx]), threshold)))
690                                 {
691                                         context.getTestContext().getLog()
692                                                 << TestLog::Message << "ERROR: When sampling " << viewName << " at " << texCoord[ndx]
693                                                                                         << ": got " << result[ndx]
694                                                                                         << ", expected " << reference[ndx]
695                                                 << TestLog::EndMessage;
696                                         allOk = false;
697                                 }
698                         }
699                 }
700
701                 if (allOk)
702                         return tcu::TestStatus::pass("All samples passed");
703                 else
704                         return tcu::TestStatus::fail("Got invalid results");
705         }
706 }
707
708 void initPrograms (SourceCollections& dst, TestParameters params)
709 {
710         const ShaderSpec        spec    = getShaderSpec(params);
711
712         generateSources(params.shaderType, spec, dst);
713 }
714
715 void addPlaneViewCase (tcu::TestCaseGroup* group, const TestParameters& params)
716 {
717         std::ostringstream name;
718
719         name << de::toLower(de::toString(params.format).substr(10));
720
721         if ((params.viewType != TestParameters::VIEWTYPE_MEMORY_ALIAS) &&
722                 ((params.createFlags & VK_IMAGE_CREATE_DISJOINT_BIT) != 0))
723                 name << "_disjoint";
724
725         name << "_plane_" << params.planeNdx;
726
727         if (params.isCompatibilityFormat)
728         {
729                 name << "_compatible_format_" << de::toLower(de::toString(params.planeCompatibleFormat).substr(10));
730         }
731
732         addFunctionCaseWithPrograms(group, name.str(), "", checkSupport, initPrograms, testPlaneView, params);
733 }
734
735 void populateViewTypeGroup (tcu::TestCaseGroup* group, TestParameters::ViewType viewType)
736 {
737         const glu::ShaderType           shaderType      = glu::SHADERTYPE_FRAGMENT;
738         const UVec2                                     size            (32, 58);
739         const VkImageCreateFlags        baseFlags       = (VkImageCreateFlags)VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT
740                                                                                         | (viewType == TestParameters::VIEWTYPE_MEMORY_ALIAS ? (VkImageCreateFlags)VK_IMAGE_CREATE_ALIAS_BIT : 0u);
741
742         auto addTests = [&](int formatNdx)
743         {
744                 const VkFormat  format          = (VkFormat)formatNdx;
745                 const deUint32  numPlanes       = getPlaneCount(format);
746
747                 if (numPlanes == 1)
748                         return; // Plane views not possible
749
750                 for (int isDisjoint = 0; isDisjoint < 2; ++isDisjoint)
751                 {
752                         const VkImageCreateFlags        flags   = baseFlags | (isDisjoint == 1 ? (VkImageCreateFlags)VK_IMAGE_CREATE_DISJOINT_BIT : 0u);
753
754                         if ((viewType == TestParameters::VIEWTYPE_MEMORY_ALIAS) &&
755                                 ((flags & VK_IMAGE_CREATE_DISJOINT_BIT) == 0))
756                                 continue; // Memory alias cases require disjoint planes
757
758                         for (deUint32 planeNdx = 0; planeNdx < numPlanes; ++planeNdx)
759                         {
760                                 const VkFormat planeFormat = getPlaneCompatibleFormat(format, planeNdx);
761                                 // Add test case using image view with a format taken from the "Plane Format Compatibility Table"
762                                 addPlaneViewCase(group, TestParameters(viewType, format, size, flags, planeNdx, planeFormat, shaderType, DE_FALSE));
763
764                                 // Add test cases using image view with a format that is compatible with the plane's format.
765                                 // For example: VK_FORMAT_R4G4_UNORM_PACK8 is compatible with VK_FORMAT_R8_UNORM.
766                                 for (const auto& compatibleFormat : s_compatible_formats)
767                                 {
768                                         if (compatibleFormat == planeFormat)
769                                                 continue;
770
771                                         if (!formatsAreCompatible(planeFormat, compatibleFormat))
772                                                 continue;
773
774                                         addPlaneViewCase(group, TestParameters(viewType, format, size, flags, planeNdx, compatibleFormat, shaderType, DE_TRUE));
775                                 }
776                         }
777                 }
778         };
779
780         for (int formatNdx = VK_YCBCR_FORMAT_FIRST; formatNdx < VK_YCBCR_FORMAT_LAST; formatNdx++)
781         {
782                 addTests(formatNdx);
783         }
784
785         for (int formatNdx = VK_FORMAT_G8_B8R8_2PLANE_444_UNORM_EXT; formatNdx < VK_FORMAT_G16_B16R16_2PLANE_444_UNORM_EXT; formatNdx++)
786         {
787                 addTests(formatNdx);
788         }
789 }
790
791 void populateViewGroup (tcu::TestCaseGroup* group)
792 {
793         addTestGroup(group, "image_view",       "Plane View via VkImageView",           populateViewTypeGroup,  TestParameters::VIEWTYPE_IMAGE_VIEW);
794         addTestGroup(group, "memory_alias",     "Plane View via Memory Aliasing",       populateViewTypeGroup,  TestParameters::VIEWTYPE_MEMORY_ALIAS);
795 }
796
797 } // anonymous
798
799 tcu::TestCaseGroup* createViewTests (tcu::TestContext& testCtx)
800 {
801         return createTestGroup(testCtx, "plane_view", "YCbCr Plane View Tests", populateViewGroup);
802 }
803
804 } // ycbcr
805 } // vkt
806