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