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