Fix missing dependency on sparse binds
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / geometry / vktGeometryLayeredRenderingTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2019 Google Inc.
6  * Copyright (c) 2019 The Khronos Group Inc.
7  * Copyright (c) 2014 The Android Open Source Project
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Geometry shader layered rendering tests
24  *//*--------------------------------------------------------------------*/
25
26 #include "vktGeometryLayeredRenderingTests.hpp"
27 #include "vktTestCase.hpp"
28 #include "vktTestCaseUtil.hpp"
29 #include "vktGeometryTestsUtil.hpp"
30
31 #include "vkPrograms.hpp"
32 #include "vkStrUtil.hpp"
33 #include "vkQueryUtil.hpp"
34 #include "vkMemUtil.hpp"
35 #include "vkRefUtil.hpp"
36 #include "vkBarrierUtil.hpp"
37 #include "vkTypeUtil.hpp"
38 #include "vkImageUtil.hpp"
39 #include "vkBuilderUtil.hpp"
40 #include "vkCmdUtil.hpp"
41 #include "vkObjUtil.hpp"
42
43 #include "deStringUtil.hpp"
44 #include "deUniquePtr.hpp"
45
46 #include "tcuTextureUtil.hpp"
47 #include "tcuVectorUtil.hpp"
48 #include "tcuTestLog.hpp"
49
50 namespace vkt
51 {
52 namespace geometry
53 {
54 namespace
55 {
56 using namespace vk;
57 using de::MovePtr;
58 using de::UniquePtr;
59 using tcu::Vec4;
60 using tcu::IVec3;
61
62 enum TestType
63 {
64         TEST_TYPE_DEFAULT_LAYER,                                        // !< draw to default layer
65         TEST_TYPE_SINGLE_LAYER,                                         // !< draw to single layer
66         TEST_TYPE_ALL_LAYERS,                                           // !< draw all layers
67         TEST_TYPE_DIFFERENT_CONTENT,                            // !< draw different content to different layers
68         TEST_TYPE_LAYER_ID,                                                     // !< draw to all layers, verify gl_Layer fragment input
69         TEST_TYPE_INVOCATION_PER_LAYER,                         // !< draw to all layers, one invocation per layer
70         TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION,       // !< draw to all layers, multiple invocations write to multiple layers
71         TEST_TYPE_LAYERED_READBACK,                                     // !< draw to two layers multiple times
72         TEST_TYPE_SECONDARY_CMD_BUFFER                          // !< layered rendering using secondary command buffer
73 };
74
75 struct ImageParams
76 {
77         VkImageViewType viewType;
78         VkExtent3D              size;
79         deUint32                numLayers;
80 };
81
82 struct TestParams
83 {
84         TestType        testType;
85         ImageParams     image;
86         bool            inheritFramebuffer;
87 };
88
89 const float             s_colors[][4]                                   =
90 {
91         { 1.0f, 1.0f, 1.0f, 1.0f },             // white
92         { 1.0f, 0.0f, 0.0f, 1.0f },             // red
93         { 0.0f, 1.0f, 0.0f, 1.0f },             // green
94         { 0.0f, 0.0f, 1.0f, 1.0f },             // blue
95         { 1.0f, 1.0f, 0.0f, 1.0f },             // yellow
96         { 1.0f, 0.0f, 1.0f, 1.0f },             // magenta
97 };
98
99 const tcu::Vec4 secondaryCmdBufClearColors[]    =
100 {
101         tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
102         tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
103         tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
104         tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f),
105         tcu::Vec4(0.0f, 1.0f, 1.0f, 1.0f),
106         tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f)
107 };
108
109 tcu::Vec4 scaleColor(const tcu::Vec4& color, float factor)
110 {
111         return tcu::Vec4(color[0] * factor,
112                                          color[1] * factor,
113                                          color[2] * factor,
114                                          color[3]);
115 }
116
117 deUint32 getTargetLayer (const ImageParams& imageParams)
118 {
119         if (imageParams.viewType == VK_IMAGE_VIEW_TYPE_3D)
120                 return imageParams.size.depth / 2;
121         else
122                 return imageParams.numLayers / 2;
123 }
124
125 std::string getShortImageViewTypeName (const VkImageViewType imageViewType)
126 {
127         std::string s(getImageViewTypeName(imageViewType));
128         return de::toLower(s.substr(19));
129 }
130
131 VkImageType getImageType (const VkImageViewType viewType)
132 {
133         switch (viewType)
134         {
135                 case VK_IMAGE_VIEW_TYPE_1D:
136                 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
137                         return VK_IMAGE_TYPE_1D;
138
139                 case VK_IMAGE_VIEW_TYPE_2D:
140                 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
141                 case VK_IMAGE_VIEW_TYPE_CUBE:
142                 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
143                         return VK_IMAGE_TYPE_2D;
144
145                 case VK_IMAGE_VIEW_TYPE_3D:
146                         return VK_IMAGE_TYPE_3D;
147
148                 default:
149                         DE_ASSERT(0);
150                         return VK_IMAGE_TYPE_LAST;
151         }
152 }
153
154 VkFormat getStencilBufferFormat(VkFormat depthStencilImageFormat)
155 {
156         const tcu::TextureFormat tcuFormat = mapVkFormat(depthStencilImageFormat);
157         const VkFormat result = (tcuFormat.order == tcu::TextureFormat::S || tcuFormat.order == tcu::TextureFormat::DS) ? VK_FORMAT_S8_UINT : VK_FORMAT_UNDEFINED;
158
159         DE_ASSERT(result != VK_FORMAT_UNDEFINED);
160
161         return result;
162 }
163
164 inline bool isCubeImageViewType (const VkImageViewType viewType)
165 {
166         return viewType == VK_IMAGE_VIEW_TYPE_CUBE || viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
167 }
168
169 void checkImageFormatProperties (const InstanceInterface&       vki,
170                                                                  const VkPhysicalDevice&        physDevice,
171                                                                  const VkImageType&                     imageType,
172                                                                  const VkImageTiling&           imageTiling,
173                                                                  const VkImageUsageFlags        imageUsageFlags,
174                                                                  const VkImageCreateFlags       imageCreateFlags,
175                                                                  const VkFormat                         format,
176                                                                  const VkExtent3D&                      requiredSize,
177                                                                  const deUint32                         requiredLayers)
178 {
179         VkImageFormatProperties imageFormatProperties;
180         VkResult                                result;
181
182         deMemset(&imageFormatProperties, 0, sizeof(imageFormatProperties));
183
184         result = vki.getPhysicalDeviceImageFormatProperties(physDevice, format, imageType, imageTiling, imageUsageFlags, imageCreateFlags, &imageFormatProperties);
185
186         if (result                                                                      != VK_SUCCESS                   ||
187                 imageFormatProperties.maxArrayLayers    <  requiredLayers               ||
188                 imageFormatProperties.maxExtent.height  <  requiredSize.height  ||
189                 imageFormatProperties.maxExtent.width   <  requiredSize.width   ||
190                 imageFormatProperties.maxExtent.depth   <  requiredSize.depth)
191         {
192                 TCU_THROW(NotSupportedError, "Depth/stencil format is not supported");
193         }
194 }
195
196 VkImageCreateInfo makeImageCreateInfo (const VkImageCreateFlags flags, const VkImageType type, const VkFormat format, const VkExtent3D size, const deUint32 numLayers, const VkImageUsageFlags usage)
197 {
198         const VkImageCreateInfo imageParams =
199         {
200                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                    // VkStructureType                      sType;
201                 DE_NULL,                                                                                // const void*                          pNext;
202                 flags,                                                                                  // VkImageCreateFlags           flags;
203                 type,                                                                                   // VkImageType                          imageType;
204                 format,                                                                                 // VkFormat                                     format;
205                 size,                                                                                   // VkExtent3D                           extent;
206                 1u,                                                                                             // deUint32                                     mipLevels;
207                 numLayers,                                                                              // deUint32                                     arrayLayers;
208                 VK_SAMPLE_COUNT_1_BIT,                                                  // VkSampleCountFlagBits        samples;
209                 VK_IMAGE_TILING_OPTIMAL,                                                // VkImageTiling                        tiling;
210                 usage,                                                                                  // VkImageUsageFlags            usage;
211                 VK_SHARING_MODE_EXCLUSIVE,                                              // VkSharingMode                        sharingMode;
212                 0u,                                                                                             // deUint32                                     queueFamilyIndexCount;
213                 DE_NULL,                                                                                // const deUint32*                      pQueueFamilyIndices;
214                 VK_IMAGE_LAYOUT_UNDEFINED,                                              // VkImageLayout                        initialLayout;
215         };
216         return imageParams;
217 }
218
219 Move<VkRenderPass> makeRenderPass (const DeviceInterface&       vk,
220                                                                    const VkDevice                       device,
221                                                                    const VkFormat                       colorFormat,
222                                                                    const VkFormat                       dsFormat,
223                                                                    const bool                           useDepthStencil)
224 {
225         return vk::makeRenderPass(vk, device, colorFormat, useDepthStencil ? dsFormat : VK_FORMAT_UNDEFINED, VK_ATTACHMENT_LOAD_OP_LOAD);
226 }
227
228 Move<VkRenderPass> makeRenderPassWithSelfDependency (const DeviceInterface&     vk,
229                                                                                                          const VkDevice                 device,
230                                                                                                          const VkFormat                 colorFormat)
231 {
232         const VkAttachmentDescription   attachmentDescription   =
233         {
234                 (VkAttachmentDescriptionFlags)0,                        // VkAttachmentDescriptionFlags flags
235                 colorFormat,                                                            // VkFormat                                             format
236                 VK_SAMPLE_COUNT_1_BIT,                                          // VkSampleCountFlagBits                samples
237                 VK_ATTACHMENT_LOAD_OP_CLEAR,                            // VkAttachmentLoadOp                   loadOp
238                 VK_ATTACHMENT_STORE_OP_STORE,                           // VkAttachmentStoreOp                  storeOp
239                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,                        // VkAttachmentLoadOp                   stencilLoadOp
240                 VK_ATTACHMENT_STORE_OP_DONT_CARE,                       // VkAttachmentStoreOp                  stencilStoreOp
241                 VK_IMAGE_LAYOUT_UNDEFINED,                                      // VkImageLayout                                initialLayout
242                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL        // VkImageLayout                                finalLayout
243         };
244
245         const VkAttachmentReference             colorAttachmentRef              =
246         {
247                 0u,                                                                                     // deUint32                     attachment
248                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL        // VkImageLayout        layout
249         };
250
251         const VkSubpassDescription              subpassDescription              =
252         {
253                 (VkSubpassDescriptionFlags)0,           // VkSubpassDescriptionFlags            flags
254                 VK_PIPELINE_BIND_POINT_GRAPHICS,        // VkPipelineBindPoint                          pipelineBindPoint
255                 0u,                                                                     // deUint32                                                     inputAttachmentCount
256                 DE_NULL,                                                        // const VkAttachmentReference*         pInputAttachments
257                 1u,                                                                     // deUint32                                                     colorAttachmentCount
258                 &colorAttachmentRef,                            // const VkAttachmentReference*         pColorAttachments
259                 DE_NULL,                                                        // const VkAttachmentReference*         pResolveAttachments
260                 DE_NULL,                                                        // const VkAttachmentReference*         pDepthStencilAttachment
261                 0u,                                                                     // deUint32                                                     preserveAttachmentCount
262                 DE_NULL                                                         // const deUint32*                                      pPreserveAttachments
263         };
264
265         const VkSubpassDependency               subpassDependency               =
266         {
267                 0u,                                                                             // deUint32                             srcSubpass
268                 0u,                                                                             // deUint32                             dstSubpass
269                 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,  // VkPipelineStageFlags srcStageMask
270                 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,  // VkPipelineStageFlags dstStageMask
271                 VK_ACCESS_SHADER_WRITE_BIT,                             // VkAccessFlags                srcAccessMask
272                 VK_ACCESS_SHADER_READ_BIT,                              // VkAccessFlags                dstAccessMask
273                 VK_DEPENDENCY_BY_REGION_BIT,                    // VkDependencyFlags    dependencyFlags
274         };
275
276         const VkRenderPassCreateInfo    renderPassInfo                  =
277         {
278                 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,      // VkStructureType                                      sType
279                 DE_NULL,                                                                        // const void*                                          pNext
280                 (VkRenderPassCreateFlags)0,                                     // VkRenderPassCreateFlags                      flags
281                 1u,                                                                                     // deUint32                                                     attachmentCount
282                 &attachmentDescription,                                         // const VkAttachmentDescription*       pAttachments
283                 1u,                                                                                     // deUint32                                                     subpassCount
284                 &subpassDescription,                                            // const VkSubpassDescription*          pSubpasses
285                 1u,                                                                                     // deUint32                                                     dependencyCount
286                 &subpassDependency                                                      // const VkSubpassDependency*           pDependencies
287         };
288
289         return createRenderPass(vk, device, &renderPassInfo);
290 }
291
292 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&           vk,
293                                                                            const VkDevice                               device,
294                                                                            const VkPipelineLayout               pipelineLayout,
295                                                                            const VkRenderPass                   renderPass,
296                                                                            const VkShaderModule                 vertexModule,
297                                                                            const VkShaderModule                 geometryModule,
298                                                                            const VkShaderModule                 fragmentModule,
299                                                                            const VkExtent2D                             renderSize,
300                                                                            const bool                                   useDepthStencil = false)
301 {
302         const std::vector<VkViewport>                           viewports                                               (1, makeViewport(renderSize));
303         const std::vector<VkRect2D>                                     scissors                                                (1, makeRect2D(renderSize));
304
305         const VkStencilOpState                                          stencilOpState                                  = makeStencilOpState(
306                 VK_STENCIL_OP_KEEP,                                     // stencil fail
307                 VK_STENCIL_OP_INCREMENT_AND_CLAMP,      // depth & stencil pass
308                 VK_STENCIL_OP_KEEP,                                     // depth only fail
309                 VK_COMPARE_OP_ALWAYS,                           // compare op
310                 ~0u,                                                            // compare mask
311                 ~0u,                                                            // write mask
312                 0u);                                                            // reference
313
314         const VkPipelineDepthStencilStateCreateInfo     pipelineDepthStencilStateInfo   =
315         {
316                 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,     // VkStructureType                                                      sType
317                 DE_NULL,                                                                                                        // const void*                                                          pNext
318                 (VkPipelineDepthStencilStateCreateFlags)0,                                      // VkPipelineDepthStencilStateCreateFlags       flags
319                 useDepthStencil ? VK_TRUE : VK_FALSE,                                           // VkBool32                                                                     depthTestEnable
320                 useDepthStencil ? VK_TRUE : VK_FALSE,                                           // VkBool32                                                                     depthWriteEnable
321                 VK_COMPARE_OP_LESS,                                                                                     // VkCompareOp                                                          depthCompareOp
322                 VK_FALSE,                                                                                                       // VkBool32                                                                     depthBoundsTestEnable
323                 useDepthStencil ? VK_TRUE : VK_FALSE,                                           // VkBool32                                                                     stencilTestEnable
324                 stencilOpState,                                                                                         // VkStencilOpState                                                     front
325                 stencilOpState,                                                                                         // VkStencilOpState                                                     back
326                 0.0f,                                                                                                           // float                                                                        minDepthBounds
327                 1.0f                                                                                                            // float                                                                        maxDepthBounds
328         };
329
330         const VkPipelineVertexInputStateCreateInfo      vertexInputStateInfo                    =
331         {
332                 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,      // VkStructureType                                                      sType
333                 DE_NULL,                                                                                                        // const void*                                                          pNext
334                 0u,                                                                                                                     // VkPipelineVertexInputStateCreateFlags        flags
335                 0u,                                                                                                                     // deUint32                                                                     vertexBindingDescriptionCount
336                 DE_NULL,                                                                                                        // const VkVertexInputBindingDescription*       pVertexBindingDescriptions
337                 0u,                                                                                                                     // deUint32                                                                     vertexAttributeDescriptionCount
338                 DE_NULL                                                                                                         // const VkVertexInputAttributeDescription*     pVertexAttributeDescriptions
339         };
340
341         return vk::makeGraphicsPipeline(vk,                                                                     // const DeviceInterface&                                                       vk
342                                                                         device,                                                         // const VkDevice                                                                       device
343                                                                         pipelineLayout,                                         // const VkPipelineLayout                                                       pipelineLayout
344                                                                         vertexModule,                                           // const VkShaderModule                                                         vertexShaderModule
345                                                                         DE_NULL,                                                        // const VkShaderModule                                                         tessellationControlModule
346                                                                         DE_NULL,                                                        // const VkShaderModule                                                         tessellationEvalModule
347                                                                         geometryModule,                                         // const VkShaderModule                                                         geometryShaderModule
348                                                                         fragmentModule,                                         // const VkShaderModule                                                         fragmentShaderModule
349                                                                         renderPass,                                                     // const VkRenderPass                                                           renderPass
350                                                                         viewports,                                                      // const std::vector<VkViewport>&                                       viewports
351                                                                         scissors,                                                       // const std::vector<VkRect2D>&                                         scissors
352                                                                         VK_PRIMITIVE_TOPOLOGY_POINT_LIST,       // const VkPrimitiveTopology                                            topology
353                                                                         0u,                                                                     // const deUint32                                                                       subpass
354                                                                         0u,                                                                     // const deUint32                                                                       patchControlPoints
355                                                                         &vertexInputStateInfo,                          // const VkPipelineVertexInputStateCreateInfo*          vertexInputStateCreateInfo
356                                                                         DE_NULL,                                                        // const VkPipelineRasterizationStateCreateInfo*        rasterizationStateCreateInfo
357                                                                         DE_NULL,                                                        // const VkPipelineMultisampleStateCreateInfo*          multisampleStateCreateInfo
358                                                                         &pipelineDepthStencilStateInfo);        // const VkPipelineDepthStencilStateCreateInfo*         depthStencilStateCreateInfo
359 }
360
361 void copyLayeredImageToBuffer(const DeviceInterface& vk, VkCommandBuffer cmdBuffer, VkImage image, VkBuffer buffer, const ImageParams& imageParams)
362 {
363         // Image read barrier
364         {
365                 const VkImageSubresourceRange   colorSubresourceRange   = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, imageParams.numLayers);
366                 const VkImageMemoryBarrier              barrier =
367                 {
368                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,         // VkStructureType                      sType
369                         DE_NULL,                                                                        // const void*                          pNext
370                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,           // VkAccessFlags                        outputMask
371                         VK_ACCESS_TRANSFER_READ_BIT,                            // VkAccessFlags                        inputMask
372                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,       // VkImageLayout                        oldLayout
373                         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,           // VkImageLayout                        newLayout
374                         VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                                     srcQueueFamilyIndex
375                         VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                                     destQueueFamilyIndex
376                         image,                                                                          // VkImage                                      image
377                         colorSubresourceRange                                           // VkImageSubresourceRange      subresourceRange
378                 };
379
380                 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &barrier);
381         }
382         // Color image -> host buffer
383         {
384                 const VkBufferImageCopy region =
385                 {
386                         0ull,                                                                                                                                                                   // VkDeviceSize                         bufferOffset
387                         0u,                                                                                                                                                                             // deUint32                                     bufferRowLength
388                         0u,                                                                                                                                                                             // deUint32                                     bufferImageHeight
389                         makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, imageParams.numLayers),   // VkImageSubresourceLayers     imageSubresource
390                         makeOffset3D(0, 0, 0),                                                                                                                                  // VkOffset3D                           imageOffset
391                         imageParams.size                                                                                                                                                // VkExtent3D                           imageExtent
392                 };
393
394                 vk.cmdCopyImageToBuffer(cmdBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, 1u, &region);
395         }
396         // Buffer write barrier
397         {
398                 const VkBufferMemoryBarrier barrier =
399                 {
400                         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,        // VkStructureType      sType
401                         DE_NULL,                                                                        // const void*          pNext
402                         VK_ACCESS_TRANSFER_WRITE_BIT,                           // VkAccessFlags        srcAccessMask
403                         VK_ACCESS_HOST_READ_BIT,                                        // VkAccessFlags        dstAccessMask
404                         VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                     srcQueueFamilyIndex
405                         VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                     dstQueueFamilyIndex
406                         buffer,                                                                         // VkBuffer                     buffer
407                         0ull,                                                                           // VkDeviceSize         offset
408                         VK_WHOLE_SIZE                                                           // VkDeviceSize         size
409                 };
410
411                 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &barrier, DE_NULL, 0u);
412         }
413 }
414
415 //! Convenience wrapper to access 1D, 2D, and 3D image layers/slices in a uniform way.
416 class LayeredImageAccess
417 {
418 public:
419         static LayeredImageAccess create (const VkImageType type, const VkFormat format, const VkExtent3D size, const deUint32 numLayers, const void* pData)
420         {
421                 if (type == VK_IMAGE_TYPE_1D)
422                         return LayeredImageAccess(format, size.width, numLayers, pData);
423                 else
424                         return LayeredImageAccess(type, format, size, numLayers, pData);
425         }
426
427         inline tcu::ConstPixelBufferAccess getLayer (const int layer) const
428         {
429                 return tcu::getSubregion(m_wholeImage, 0, (m_1dModifier * layer), ((~m_1dModifier & 1) * layer), m_width, m_height, 1);
430         }
431
432         inline int getNumLayersOrSlices (void) const
433         {
434                 return m_layers;
435         }
436
437 private:
438         // Specialized for 1D images.
439         LayeredImageAccess (const VkFormat format, const deUint32 width, const deUint32 numLayers, const void* pData)
440                 : m_width               (static_cast<int>(width))
441                 , m_height              (1)
442                 , m_1dModifier  (1)
443                 , m_layers              (numLayers)
444                 , m_wholeImage  (tcu::ConstPixelBufferAccess(mapVkFormat(format), m_width, m_layers, 1, pData))
445         {
446         }
447
448         LayeredImageAccess (const VkImageType type, const VkFormat format, const VkExtent3D size, const deUint32 numLayers, const void* pData)
449                 : m_width               (static_cast<int>(size.width))
450                 , m_height              (static_cast<int>(size.height))
451                 , m_1dModifier  (0)
452                 , m_layers              (static_cast<int>(type == VK_IMAGE_TYPE_3D ? size.depth : numLayers))
453                 , m_wholeImage  (tcu::ConstPixelBufferAccess(mapVkFormat(format), m_width, m_height, m_layers, pData))
454         {
455         }
456
457         const int                                                       m_width;
458         const int                                                       m_height;
459         const int                                                       m_1dModifier;
460         const int                                                       m_layers;
461         const tcu::ConstPixelBufferAccess       m_wholeImage;
462 };
463
464 inline bool compareColors (const Vec4& colorA, const Vec4& colorB, const Vec4& threshold)
465 {
466         return tcu::allEqual(
467                                 tcu::lessThan(tcu::abs(colorA - colorB), threshold),
468                                 tcu::BVec4(true, true, true, true));
469 }
470
471 bool verifyImageSingleColoredRow (tcu::TestLog& log, const tcu::ConstPixelBufferAccess image, const float rowWidthRatio, const tcu::Vec4& barColor, bool topRightCleared = false, bool bottomRightCleared = false)
472 {
473         DE_ASSERT(rowWidthRatio > 0.0f);
474
475         const Vec4                              black                           (0.0f, 0.0f, 0.0f, 1.0f);
476         const Vec4                              green                           (0.0f, 1.0f, 0.0f, 1.0f);
477         const Vec4                              red                                     (1.0f, 0.0f, 0.0f, 1.0f);
478         const Vec4                              brown                           (0.5f, 0.25f, 0.0f, 1.0f);
479         const Vec4                              threshold                       (0.02f);
480         const int                               barLength                       = static_cast<int>(rowWidthRatio * static_cast<float>(image.getWidth()));
481         const int                               barLengthThreshold      = 1;
482         tcu::TextureLevel               errorMask                       (image.getFormat(), image.getWidth(), image.getHeight());
483         tcu::PixelBufferAccess  errorMaskAccess         = errorMask.getAccess();
484
485         tcu::clear(errorMask.getAccess(), green);
486
487         log << tcu::TestLog::Message
488                 << "Expecting all pixels with distance less or equal to (about) " << barLength
489                 << " pixels from left border to be of color " << barColor.swizzle(0, 1, 2) << "."
490                 << tcu::TestLog::EndMessage;
491
492         bool allPixelsOk = true;
493
494         for (int y = 0; y < image.getHeight(); ++y)
495         for (int x = 0; x < image.getWidth();  ++x)
496         {
497                 const Vec4      color                   = image.getPixel(x, y);
498                 const bool      isBlack                 = compareColors(color, black, threshold);
499                 const bool      isBrown                 = compareColors(color, brown, threshold);
500                 const bool      isColor                 = compareColors(color, barColor, threshold);
501                 const bool      isOutsideColor  = ((topRightCleared && y < image.getHeight() / 2) || (bottomRightCleared && y >= image.getHeight() / 2)) ? isBrown : isBlack;
502
503                 bool isOk;
504
505                 if (x <= barLength - barLengthThreshold)
506                         isOk = isColor;
507                 else if (x >= barLength + barLengthThreshold)
508                 {
509                         isOk = isOutsideColor;
510                 }
511                 else
512                         isOk = isColor || isOutsideColor;
513
514                 allPixelsOk &= isOk;
515
516                 if (!isOk)
517                         errorMaskAccess.setPixel(red, x, y);
518         }
519
520         if (allPixelsOk)
521         {
522                 log << tcu::TestLog::Message << "Image is valid." << tcu::TestLog::EndMessage
523                         << tcu::TestLog::ImageSet("LayerContent", "Layer content")
524                         << tcu::TestLog::Image("Layer", "Layer", image)
525                         << tcu::TestLog::EndImageSet;
526                 return true;
527         }
528         else
529         {
530                 log << tcu::TestLog::Message << "Image verification failed. Got unexpected pixels." << tcu::TestLog::EndMessage
531                         << tcu::TestLog::ImageSet("LayerContent", "Layer content")
532                         << tcu::TestLog::Image("Layer",         "Layer",        image)
533                         << tcu::TestLog::Image("ErrorMask",     "Errors",       errorMask)
534                         << tcu::TestLog::EndImageSet;
535                 return false;
536         }
537
538         // Note: this is never reached
539         log << tcu::TestLog::Image("LayerContent", "Layer content", image);
540
541         return allPixelsOk;
542 }
543
544 static bool verifyImageMultipleBars (tcu::TestLog&                                              log,
545                                                                          const tcu::ConstPixelBufferAccess      image,
546                                                                          const float*                                           barWidthRatios,
547                                                                          const tcu::Vec4*                                       barValues,
548                                                                          const int                                                      barsCount,
549                                                                          const int                                                      numUsedChannels,
550                                                                          const std::string&                                     imageTypeName)
551 {
552         const Vec4                                      green                           (0.0f, 1.0f, 0.0f, 1.0f);
553         const Vec4                                      red                                     (1.0f, 0.0f, 0.0f, 1.0f);
554         const Vec4                                      threshold                       (0.02f);
555         const tcu::TextureFormat        errorMaskFormat         (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8));
556         tcu::TextureLevel                       errorMask                       (errorMaskFormat, image.getWidth(), image.getHeight());
557         tcu::PixelBufferAccess          errorMaskAccess         = errorMask.getAccess();
558         bool                                            allPixelsOk                     = true;
559
560         DE_ASSERT(barsCount > 0);
561
562         tcu::clear(errorMask.getAccess(), green);
563
564         // Format information message
565         {
566                 int                                     leftBorder      = 0;
567                 int                                     rightBorder     = 0;
568                 std::ostringstream      str;
569
570                 for (int barNdx = 0; barNdx < barsCount; ++barNdx)
571                 {
572                         leftBorder      = rightBorder;
573                         rightBorder     = static_cast<int>(barWidthRatios[barNdx] * static_cast<float>(image.getWidth()));
574
575                         DE_ASSERT(leftBorder < rightBorder);
576
577                         str << std::endl << " [" << leftBorder << "," <<rightBorder << "): ";
578
579                         switch (numUsedChannels)
580                         {
581                                 case 1: str << barValues[barNdx][0];    break;
582                                 case 4: str << barValues[barNdx];               break;
583                                 default: DE_ASSERT(false);                              break;
584                         }
585                 }
586
587                 log << tcu::TestLog::Message
588                         << "Expecting " + imageTypeName + " values depending x-axis position to be of following values: "
589                         << str.str()
590                         << tcu::TestLog::EndMessage;
591         }
592
593         for (int x = 0; x < image.getWidth();  ++x)
594         {
595                 tcu::Vec4       expectedValue   = barValues[0];
596
597                 for (int barNdx = 0; barNdx < barsCount; ++barNdx)
598                 {
599                         const int rightBorder   = static_cast<int>(barWidthRatios[barNdx] * static_cast<float>(image.getWidth()));
600
601                         if (x < rightBorder)
602                         {
603                                 expectedValue = barValues[barNdx];
604
605                                 break;
606                         }
607                 }
608
609                 for (int y = 0; y < image.getHeight(); ++y)
610                 {
611                         const tcu::Vec4 realValue       = image.getPixel(x, y);
612                         bool                    isOk            = false;
613
614                         switch (numUsedChannels)
615                         {
616                                 case 1: isOk = fabs(realValue[0] - expectedValue[0]) < threshold[0];    break;
617                                 case 4: isOk = compareColors(realValue, expectedValue, threshold);              break;
618                                 default: DE_ASSERT(false);                                                                                              break;
619                         }
620
621                         if (!isOk)
622                                 errorMaskAccess.setPixel(red, x, y);
623
624                         allPixelsOk = allPixelsOk && isOk;
625                 }
626         }
627
628         if (allPixelsOk)
629         {
630                 log << tcu::TestLog::Message << "Image is valid." << tcu::TestLog::EndMessage
631                         << tcu::TestLog::ImageSet(imageTypeName + "LayerContent", imageTypeName + " Layer Content")
632                         << tcu::TestLog::Image("Layer", "Layer", image)
633                         << tcu::TestLog::EndImageSet;
634         }
635         else
636         {
637                 log << tcu::TestLog::Message << "Image verification failed. Got unexpected pixels." << tcu::TestLog::EndMessage
638                         << tcu::TestLog::ImageSet(imageTypeName + "LayerContent", imageTypeName + " Layer Content")
639                         << tcu::TestLog::Image("Layer",         "Layer",        image)
640                         << tcu::TestLog::Image("ErrorMask",     "Errors",       errorMask)
641                         << tcu::TestLog::EndImageSet;
642         }
643
644         return allPixelsOk;
645 }
646
647 static void convertDepthToColorBufferAccess (const tcu::ConstPixelBufferAccess& inputImage, tcu::PixelBufferAccess& outputImage)
648 {
649         for (int y = 0; y < inputImage.getHeight(); y++)
650         for (int x = 0; x < inputImage.getWidth(); x++)
651         {
652                 const float             depth   = inputImage.getPixDepth(x, y);
653                 const tcu::Vec4 color   = tcu::Vec4(depth, depth, depth, 1.0f);
654
655                 outputImage.setPixel(color, x, y);
656         }
657 }
658
659 static void convertStencilToColorBufferAccess (const tcu::ConstPixelBufferAccess& inputImage, tcu::PixelBufferAccess& outputImage, int maxValue)
660 {
661         for (int y = 0; y < inputImage.getHeight(); y++)
662         for (int x = 0; x < inputImage.getWidth(); x++)
663         {
664                 const int               stencilInt      = inputImage.getPixStencil(x, y);
665                 const float             stencil         = (stencilInt < maxValue) ? float(stencilInt) / float(maxValue) : 1.0f;
666                 const tcu::Vec4 color           = tcu::Vec4(stencil, stencil, stencil, 1.0f);
667
668                 outputImage.setPixel(color, x, y);
669         }
670 }
671
672 bool verifyEmptyImage (tcu::TestLog& log, const tcu::ConstPixelBufferAccess image)
673 {
674         log << tcu::TestLog::Message << "Expecting empty image" << tcu::TestLog::EndMessage;
675
676         const Vec4      black           (0.0f, 0.0f, 0.0f, 1.0f);
677         const Vec4      threshold       (0.02f);
678
679         for (int y = 0; y < image.getHeight(); ++y)
680         for (int x = 0; x < image.getWidth();  ++x)
681         {
682                 const Vec4 color = image.getPixel(x, y);
683
684                 if (!compareColors(color, black, threshold))
685                 {
686                         log     << tcu::TestLog::Message
687                                 << "Found (at least) one bad pixel at " << x << "," << y << ". Pixel color is not background color."
688                                 << tcu::TestLog::EndMessage
689                                 << tcu::TestLog::ImageSet("LayerContent", "Layer content")
690                                 << tcu::TestLog::Image("Layer", "Layer", image)
691                                 << tcu::TestLog::EndImageSet;
692                         return false;
693                 }
694         }
695
696         log << tcu::TestLog::Message << "Image is valid" << tcu::TestLog::EndMessage;
697
698         return true;
699 }
700
701 bool verifyLayerContent (tcu::TestLog& log, const TestType testType, const tcu::ConstPixelBufferAccess image, const int layerNdx, const int numLayers, const bool depthCheck, const bool stencilCheck)
702 {
703         const Vec4      white                           (1.0f, 1.0f, 1.0f, 1.0f);
704         const int       targetLayer                     = numLayers / 2;
705         const float     variableBarRatio        = static_cast<float>(layerNdx) / static_cast<float>(numLayers);
706
707         switch (testType)
708         {
709                 case TEST_TYPE_DEFAULT_LAYER:
710                         if (layerNdx == 0)
711                                 return verifyImageSingleColoredRow(log, image, 0.5f, white);
712                         else
713                                 return verifyEmptyImage(log, image);
714
715                 case TEST_TYPE_SINGLE_LAYER:
716                         if (layerNdx == targetLayer)
717                                 return verifyImageSingleColoredRow(log, image, 0.5f, white);
718                         else
719                                 return verifyEmptyImage(log, image);
720
721                 case TEST_TYPE_ALL_LAYERS:
722                 case TEST_TYPE_INVOCATION_PER_LAYER:
723                         return verifyImageSingleColoredRow(log, image, 0.5f, s_colors[layerNdx % DE_LENGTH_OF_ARRAY(s_colors)]);
724
725                 case TEST_TYPE_DIFFERENT_CONTENT:
726                 case TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION:
727                         if (layerNdx == 0)
728                                 return verifyEmptyImage(log, image);
729                         else
730                                 return verifyImageSingleColoredRow(log, image, variableBarRatio, white);
731
732                 case TEST_TYPE_LAYER_ID:
733                 {
734                         // This code must be in sync with the fragment shader.
735                         const tcu::Vec4 layerColor( (layerNdx    % 2) == 1 ? 1.0f : 0.5f,
736                                                                            ((layerNdx/2) % 2) == 1 ? 1.0f : 0.5f,
737                                                                              layerNdx         == 0 ? 1.0f : 0.0f,
738                                                                                                                                  1.0f);
739                         return verifyImageSingleColoredRow(log, image, 0.5f, layerColor);
740                 }
741
742                 case TEST_TYPE_LAYERED_READBACK:
743                 {
744                         const float     barWidthRatios[]        = { 0.25f, 0.5f, 1.0f };
745                         const int       barsCount                       = DE_LENGTH_OF_ARRAY(barWidthRatios);
746                         bool            result                          = false;
747
748                         if (depthCheck)
749                         {
750                                 const std::string               checkType                               = "Depth";
751                                 const float                             pass0depth                              = static_cast<float>(layerNdx + 1) / static_cast<float>(2 * numLayers);
752                                 const float                             pass1depth                              = static_cast<float>(layerNdx + 0) / static_cast<float>(2 * numLayers);
753                                 const tcu::Vec4                 barDepths[barsCount]    = { tcu::Vec4(pass1depth), tcu::Vec4(pass0depth), tcu::Vec4(1.0f) };
754                                 tcu::TextureLevel               depthAsColorBuffer              (tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT), image.getWidth(), image.getHeight());
755                                 tcu::PixelBufferAccess  depthAsColor                    (depthAsColorBuffer);
756                                 const int                               numUsedChannels                 (tcu::getNumUsedChannels(depthAsColor.getFormat().order));
757
758                                 convertDepthToColorBufferAccess(image, depthAsColor);
759
760                                 result = verifyImageMultipleBars(log, depthAsColor, barWidthRatios, barDepths, barsCount, numUsedChannels, checkType);
761                         }
762                         else if (stencilCheck)
763                         {
764                                 const std::string               checkType                               = "Stencil";
765                                 const int                               maxStencilValue                 = 4;
766                                 const float                             pass0stencil                    = static_cast<float>(1.0f / maxStencilValue);
767                                 const float                             pass1stencil                    = static_cast<float>(2.0f / maxStencilValue);
768                                 const tcu::Vec4                 barStencils[barsCount]  = { tcu::Vec4(pass1stencil), tcu::Vec4(pass0stencil), tcu::Vec4(0.0f) };
769                                 tcu::TextureLevel               stencilAsColorBuffer    (tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT), image.getWidth(), image.getHeight());
770                                 tcu::PixelBufferAccess  stencilAsColor                  (stencilAsColorBuffer);
771                                 const int                               numUsedChannels                 (tcu::getNumUsedChannels(stencilAsColor.getFormat().order));
772
773                                 convertStencilToColorBufferAccess(image, stencilAsColor, maxStencilValue);
774
775                                 result = verifyImageMultipleBars(log, stencilAsColor, barWidthRatios, barStencils, barsCount, numUsedChannels, checkType);
776                         }
777                         else
778                         {
779                                 const std::string               checkType                               = "Color";
780                                 const tcu::Vec4                 baseColor                               (s_colors[layerNdx % DE_LENGTH_OF_ARRAY(s_colors)]);
781                                 const tcu::Vec4                 barColors[barsCount]    = { scaleColor(baseColor, 1.00f), scaleColor(baseColor, 0.50f), scaleColor(baseColor, 0.25f) };
782                                 const int                               numUsedChannels                 (tcu::getNumUsedChannels(image.getFormat().order));
783
784                                 result = verifyImageMultipleBars(log, image, barWidthRatios, barColors, barsCount, numUsedChannels, checkType);
785                         }
786
787                         return result;
788                 }
789
790                 case TEST_TYPE_SECONDARY_CMD_BUFFER:
791                 {
792                         const tcu::Vec4 clearColor      = secondaryCmdBufClearColors[layerNdx % DE_LENGTH_OF_ARRAY(secondaryCmdBufClearColors)];
793                         const tcu::Vec4 quadColor       = s_colors[layerNdx % DE_LENGTH_OF_ARRAY(s_colors)];
794                         // The first draw: blend clearColor and quadColor
795                         const tcu::Vec4 firstDraw       = (clearColor + quadColor) * 0.5f;
796                         // The second draw: blend previous result and quadColor
797                         const tcu::Vec4 secondDraw      = (firstDraw + quadColor) * 0.5f;
798
799                         return verifyImageSingleColoredRow(log, image, 0.5f, secondDraw, layerNdx < numLayers / 2, layerNdx >= numLayers / 2);
800                 }
801
802                 default:
803                         DE_ASSERT(0);
804                         return false;
805         }
806 }
807
808 std::string getLayerDescription (const VkImageViewType viewType, const int layer)
809 {
810         std::ostringstream str;
811         const int numCubeFaces = 6;
812
813         if (isCubeImageViewType(viewType))
814                 str << "cube " << (layer / numCubeFaces) << ", face " << (layer % numCubeFaces);
815         else if (viewType == VK_IMAGE_VIEW_TYPE_3D)
816                 str << "slice z = " << layer;
817         else
818                 str << "layer " << layer;
819
820         return str.str();
821 }
822
823 bool verifyResults (tcu::TestLog& log, const TestParams& params, const VkFormat imageFormat, const void* resultData, const bool depthCheck = false, const bool stencilCheck = false)
824 {
825         const LayeredImageAccess image = LayeredImageAccess::create(getImageType(params.image.viewType), imageFormat, params.image.size, params.image.numLayers, resultData);
826
827         int numGoodLayers = 0;
828
829         for (int layerNdx = 0; layerNdx < image.getNumLayersOrSlices(); ++layerNdx)
830         {
831                 const tcu::ConstPixelBufferAccess layerImage = image.getLayer(layerNdx);
832
833                 log << tcu::TestLog::Message << "Verifying " << getLayerDescription(params.image.viewType, layerNdx) << tcu::TestLog::EndMessage;
834
835                 if (verifyLayerContent(log, params.testType, layerImage, layerNdx, image.getNumLayersOrSlices(), depthCheck, stencilCheck))
836                         ++numGoodLayers;
837         }
838
839         return numGoodLayers == image.getNumLayersOrSlices();
840 }
841
842 std::string toGlsl (const Vec4& v)
843 {
844         std::ostringstream str;
845         str << "vec4(";
846         for (int i = 0; i < 4; ++i)
847                 str << (i != 0 ? ", " : "") << de::floatToString(v[i], 1);
848         str << ")";
849         return str.str();
850 }
851
852 void initPrograms (SourceCollections& programCollection, const TestParams params)
853 {
854         const bool geomOutputColor = (params.testType == TEST_TYPE_ALL_LAYERS || params.testType == TEST_TYPE_INVOCATION_PER_LAYER || params.testType == TEST_TYPE_LAYERED_READBACK || params.testType == TEST_TYPE_SECONDARY_CMD_BUFFER);
855
856         // Vertex shader
857         {
858                 std::ostringstream src;
859                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
860                         << "\n"
861                         << "void main(void)\n"
862                         << "{\n"
863                         << "}\n";
864
865                 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
866         }
867
868         // Geometry shader
869         {
870                 const int numLayers             = static_cast<int>(params.image.viewType == VK_IMAGE_VIEW_TYPE_3D ? params.image.size.depth : params.image.numLayers);
871
872                 const int maxVertices   = (params.testType == TEST_TYPE_DIFFERENT_CONTENT)                              ? (numLayers + 1) * numLayers :
873                                                                   (params.testType == TEST_TYPE_ALL_LAYERS
874                                                                    || params.testType == TEST_TYPE_LAYER_ID
875                                                                    || params.testType == TEST_TYPE_LAYERED_READBACK
876                                                                    || params.testType == TEST_TYPE_SECONDARY_CMD_BUFFER)                ? numLayers * 4 :
877                                                                   (params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION) ? 6 : 4;
878
879                 std::ostringstream src;
880                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
881                         << "\n";
882
883                 if (params.testType == TEST_TYPE_LAYERED_READBACK)
884                         src << "layout(binding = 0) readonly uniform Input {\n"
885                                 << "    int pass;\n"
886                                 << "} uInput;\n\n";
887
888                 if (params.testType == TEST_TYPE_INVOCATION_PER_LAYER || params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION)
889                         src << "layout(points, invocations = " << numLayers << ") in;\n";
890                 else
891                         src << "layout(points) in;\n";
892
893                 src << "layout(triangle_strip, max_vertices = " << maxVertices << ") out;\n"
894                         << "\n"
895                         << (geomOutputColor ? "layout(location = 0) out vec4 vert_color;\n\n" : "")
896                         << "out gl_PerVertex {\n"
897                         << "    vec4 gl_Position;\n"
898                         << "    float gl_PointSize;\n"
899                         << "};\n"
900                         << "\n"
901                         << "void main(void)\n"
902                         << "{\n";
903
904                 std::ostringstream colorTable;
905                 {
906                         const int numColors = DE_LENGTH_OF_ARRAY(s_colors);
907
908                         colorTable << "    const vec4 colors[" << numColors << "] = vec4[" << numColors << "](";
909
910                         const std::string padding(colorTable.str().length(), ' ');
911
912                         for (int i = 0; i < numColors; ++i)
913                                 colorTable << (i != 0 ? ",\n" + padding : "") << toGlsl(s_colors[i]);
914
915                         colorTable << ");\n";
916                 }
917
918                 if (params.testType == TEST_TYPE_DEFAULT_LAYER)
919                 {
920                         src << "    gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
921                                 << "    gl_PointSize = 1.0;\n"
922                                 << "    EmitVertex();\n"
923                                 << "\n"
924                                 << "    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
925                                 << "    gl_PointSize = 1.0;\n"
926                                 << "    EmitVertex();\n"
927                                 << "\n"
928                                 << "    gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
929                                 << "    gl_PointSize = 1.0;\n"
930                                 << "    EmitVertex();\n"
931                                 << "\n"
932                                 << "    gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
933                                 << "    gl_PointSize = 1.0;\n"
934                                 << "    EmitVertex();\n";
935                 }
936                 else if (params.testType == TEST_TYPE_SINGLE_LAYER)
937                 {
938                         const deUint32 targetLayer = getTargetLayer(params.image);
939
940                         src << "    gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
941                                 << "    gl_Layer    = " << targetLayer << ";\n"
942                                 << "    gl_PointSize = 1.0;\n"
943                                 << "    EmitVertex();\n"
944                                 << "\n"
945                                 << "    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
946                                 << "    gl_Layer    = " << targetLayer << ";\n"
947                                 << "    gl_PointSize = 1.0;\n"
948                                 << "    EmitVertex();\n"
949                                 << "\n"
950                                 << "    gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
951                                 << "    gl_Layer    = " << targetLayer << ";\n"
952                                 << "    gl_PointSize = 1.0;\n"
953                                 << "    EmitVertex();\n"
954                                 << "\n"
955                                 << "    gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
956                                 << "    gl_Layer    = " << targetLayer << ";\n"
957                                 << "    gl_PointSize = 1.0;\n"
958                                 << "    EmitVertex();\n";
959                 }
960                 else if (params.testType == TEST_TYPE_ALL_LAYERS || params.testType == TEST_TYPE_SECONDARY_CMD_BUFFER)
961                 {
962                         src << colorTable.str()
963                                 << "\n"
964                                 << "    for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
965                                 << "        const int colorNdx = layerNdx % " << DE_LENGTH_OF_ARRAY(s_colors) << ";\n"
966                                 << "\n"
967                                 << "        gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
968                                 << "        gl_Layer    = layerNdx;\n"
969                                 << "        vert_color  = colors[colorNdx];\n"
970                                 << "        gl_PointSize = 1.0;\n"
971                                 << "        EmitVertex();\n"
972                                 << "\n"
973                                 << "        gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
974                                 << "        gl_Layer    = layerNdx;\n"
975                                 << "        vert_color  = colors[colorNdx];\n"
976                                 << "        gl_PointSize = 1.0;\n"
977                                 << "        EmitVertex();\n"
978                                 << "\n"
979                                 << "        gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
980                                 << "        gl_Layer    = layerNdx;\n"
981                                 << "        vert_color  = colors[colorNdx];\n"
982                                 << "        gl_PointSize = 1.0;\n"
983                                 << "        EmitVertex();\n"
984                                 << "\n"
985                                 << "        gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
986                                 << "        gl_Layer    = layerNdx;\n"
987                                 << "        vert_color  = colors[colorNdx];\n"
988                                 << "        gl_PointSize = 1.0;\n"
989                                 << "        EmitVertex();\n"
990                                 << "        EndPrimitive();\n"
991                                 << "    };\n";
992                 }
993                 else if (params.testType == TEST_TYPE_LAYER_ID)
994                 {
995                         src << "    for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
996                                 << "        gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
997                                 << "        gl_Layer    = layerNdx;\n"
998                                 << "        gl_PointSize = 1.0;\n"
999                                 << "        EmitVertex();\n"
1000                                 << "\n"
1001                                 << "        gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
1002                                 << "        gl_Layer    = layerNdx;\n"
1003                                 << "        gl_PointSize = 1.0;\n"
1004                                 << "        EmitVertex();\n"
1005                                 << "\n"
1006                                 << "        gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
1007                                 << "        gl_Layer    = layerNdx;\n"
1008                                 << "        gl_PointSize = 1.0;\n"
1009                                 << "        EmitVertex();\n"
1010                                 << "\n"
1011                                 << "        gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
1012                                 << "        gl_Layer    = layerNdx;\n"
1013                                 << "        gl_PointSize = 1.0;\n"
1014                                 << "        EmitVertex();\n"
1015                                 << "        EndPrimitive();\n"
1016                                 << "    };\n";
1017                 }
1018                 else if (params.testType == TEST_TYPE_DIFFERENT_CONTENT)
1019                 {
1020                         src << "    for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
1021                                 << "        for (int colNdx = 0; colNdx <= layerNdx; ++colNdx) {\n"
1022                                 << "            const float posX = float(colNdx) / float(" << numLayers << ") * 2.0 - 1.0;\n"
1023                                 << "\n"
1024                                 << "            gl_Position = vec4(posX,  1.0, 0.0, 1.0);\n"
1025                                 << "            gl_Layer    = layerNdx;\n"
1026                                 << "            gl_PointSize = 1.0;\n"
1027                                 << "            EmitVertex();\n"
1028                                 << "\n"
1029                                 << "            gl_Position = vec4(posX, -1.0, 0.0, 1.0);\n"
1030                                 << "            gl_Layer    = layerNdx;\n"
1031                                 << "            gl_PointSize = 1.0;\n"
1032                                 << "            EmitVertex();\n"
1033                                 << "        }\n"
1034                                 << "        EndPrimitive();\n"
1035                                 << "    }\n";
1036                 }
1037                 else if (params.testType == TEST_TYPE_INVOCATION_PER_LAYER)
1038                 {
1039                         src << colorTable.str()
1040                                 << "    const int colorNdx = gl_InvocationID % " << DE_LENGTH_OF_ARRAY(s_colors) << ";\n"
1041                                 << "\n"
1042                                 << "    gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
1043                                 << "    gl_Layer    = gl_InvocationID;\n"
1044                                 << "    gl_PointSize = 1.0;\n"
1045                                 << "    vert_color  = colors[colorNdx];\n"
1046                                 << "    EmitVertex();\n"
1047                                 << "\n"
1048                                 << "    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
1049                                 << "    gl_Layer    = gl_InvocationID;\n"
1050                                 << "    gl_PointSize = 1.0;\n"
1051                                 << "    vert_color  = colors[colorNdx];\n"
1052                                 << "    EmitVertex();\n"
1053                                 << "\n"
1054                                 << "    gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
1055                                 << "    gl_Layer    = gl_InvocationID;\n"
1056                                 << "    gl_PointSize = 1.0;\n"
1057                                 << "    vert_color  = colors[colorNdx];\n"
1058                                 << "    EmitVertex();\n"
1059                                 << "\n"
1060                                 << "    gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
1061                                 << "    gl_Layer    = gl_InvocationID;\n"
1062                                 << "    gl_PointSize = 1.0;\n"
1063                                 << "    vert_color  = colors[colorNdx];\n"
1064                                 << "    EmitVertex();\n"
1065                                 << "    EndPrimitive();\n";
1066                 }
1067                 else if (params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION)
1068                 {
1069                         src << "    const int   layerA = gl_InvocationID;\n"
1070                                 << "    const int   layerB = (gl_InvocationID + 1) % " << numLayers << ";\n"
1071                                 << "    const float aEnd   = float(layerA) / float(" << numLayers << ") * 2.0 - 1.0;\n"
1072                                 << "    const float bEnd   = float(layerB) / float(" << numLayers << ") * 2.0 - 1.0;\n"
1073                                 << "\n"
1074                                 << "    gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
1075                                 << "    gl_Layer    = layerA;\n"
1076                                 << "    gl_PointSize = 1.0;\n"
1077                                 << "    EmitVertex();\n"
1078                                 << "\n"
1079                                 << "    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
1080                                 << "    gl_Layer    = layerA;\n"
1081                                 << "    gl_PointSize = 1.0;\n"
1082                                 << "    EmitVertex();\n"
1083                                 << "\n"
1084                                 << "    gl_Position = vec4(aEnd, -1.0, 0.0, 1.0);\n"
1085                                 << "    gl_Layer    = layerA;\n"
1086                                 << "    gl_PointSize = 1.0;\n"
1087                                 << "    EmitVertex();\n"
1088                                 << "    EndPrimitive();\n"
1089                                 << "\n"
1090                                 << "    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
1091                                 << "    gl_Layer    = layerB;\n"
1092                                 << "    gl_PointSize = 1.0;\n"
1093                                 << "    EmitVertex();\n"
1094                                 << "\n"
1095                                 << "    gl_Position = vec4(bEnd,  1.0, 0.0, 1.0);\n"
1096                                 << "    gl_Layer    = layerB;\n"
1097                                 << "    gl_PointSize = 1.0;\n"
1098                                 << "    EmitVertex();\n"
1099                                 << "\n"
1100                                 << "    gl_Position = vec4(bEnd, -1.0, 0.0, 1.0);\n"
1101                                 << "    gl_Layer    = layerB;\n"
1102                                 << "    gl_PointSize = 1.0;\n"
1103                                 << "    EmitVertex();\n"
1104                                 << "    EndPrimitive();\n";
1105                 }
1106                 else if (params.testType == TEST_TYPE_LAYERED_READBACK)
1107                 {
1108                         src << colorTable.str()
1109                                 << "    for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
1110                                 << "        const int   colorNdx   = layerNdx % " << DE_LENGTH_OF_ARRAY(s_colors) << ";\n"
1111                                 << "        const vec3  passColor0 = (uInput.pass == 0 ? 0.5 :  1.0) * vec3(colors[colorNdx]);\n"
1112                                 << "        const vec4  passColor  = vec4(passColor0, 1.0);\n"
1113                                 << "        const float posX       = (uInput.pass == 0 ? 0.0 : -0.5);\n"
1114                                 << "        const float posZ       = float(layerNdx + 1 - uInput.pass) / float(" << 2*numLayers << ");\n"
1115                                 << "\n"
1116                                 << "        gl_Position = vec4(-1.0, -1.0, posZ, 1.0);\n"
1117                                 << "        gl_Layer    = layerNdx;\n"
1118                                 << "        gl_PointSize = 1.0;\n"
1119                                 << "        vert_color  = passColor;\n"
1120                                 << "        EmitVertex();\n"
1121                                 << "\n"
1122                                 << "        gl_Position = vec4(-1.0,  1.0, posZ, 1.0);\n"
1123                                 << "        gl_Layer    = layerNdx;\n"
1124                                 << "        gl_PointSize = 1.0;\n"
1125                                 << "        vert_color  = passColor;\n"
1126                                 << "        EmitVertex();\n"
1127                                 << "\n"
1128                                 << "        gl_Position = vec4(posX, -1.0, posZ, 1.0);\n"
1129                                 << "        gl_Layer    = layerNdx;\n"
1130                                 << "        gl_PointSize = 1.0;\n"
1131                                 << "        vert_color  = passColor;\n"
1132                                 << "        EmitVertex();\n"
1133                                 << "\n"
1134                                 << "        gl_Position = vec4(posX,  1.0, posZ, 1.0);\n"
1135                                 << "        gl_Layer    = layerNdx;\n"
1136                                 << "        gl_PointSize = 1.0;\n"
1137                                 << "        vert_color  = passColor;\n"
1138                                 << "        EmitVertex();\n"
1139                                 << "\n"
1140                                 << "        EndPrimitive();\n"
1141                                 << "    }\n";
1142                 }
1143                 else
1144                         DE_ASSERT(0);
1145
1146                 src <<  "}\n";  // end main
1147
1148                 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
1149         }
1150
1151         // Fragment shader
1152         {
1153                 std::string imageViewString;
1154
1155                 switch (params.image.viewType)
1156                 {
1157                         case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
1158                                 imageViewString = "image1DArray";
1159                                 break;
1160                         case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
1161                                 imageViewString = "image2DArray";
1162                                 break;
1163                         case VK_IMAGE_VIEW_TYPE_CUBE:
1164                                 imageViewString = "imageCube";
1165                                 break;
1166                         case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
1167                                 imageViewString = "imageCubeArray";
1168                                 break;
1169                         default:
1170                                 DE_ASSERT(params.image.viewType == VK_IMAGE_VIEW_TYPE_3D);
1171                                 imageViewString = "image3D";
1172                                 break;
1173                 }
1174
1175                 std::ostringstream src;
1176                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1177                         << "\n"
1178                         << "layout(location = 0) out vec4 o_color;\n"
1179                         << (geomOutputColor ? "layout(location = 0) in  vec4 vert_color;\n" : "")
1180                         << (params.testType == TEST_TYPE_SECONDARY_CMD_BUFFER ? std::string("layout(set = 0, binding = 0, rgba8) uniform " + imageViewString + " storageImage;\n") : std::string(""))
1181                         << "\n"
1182                         << "void main(void)\n"
1183                         << "{\n";
1184
1185                 if (params.testType == TEST_TYPE_LAYER_ID)
1186                 {
1187                         // This code must be in sync with verifyLayerContent()
1188                         src << "    o_color = vec4( (gl_Layer    % 2) == 1 ? 1.0 : 0.5,\n"
1189                                 << "                   ((gl_Layer/2) % 2) == 1 ? 1.0 : 0.5,\n"
1190                                 << "                     gl_Layer         == 0 ? 1.0 : 0.0,\n"
1191                                 << "                                             1.0);\n";
1192                 }
1193                 else if (params.testType == TEST_TYPE_SECONDARY_CMD_BUFFER)
1194                 {
1195                         switch (params.image.viewType)
1196                         {
1197                                 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
1198                                         src << "    ivec2 coord = ivec2(int(gl_FragCoord.x), gl_Layer);\n";
1199                                         break;
1200                                 default:
1201                                         src << "    ivec3 coord = ivec3(int(gl_FragCoord.x), int(gl_FragCoord.y), gl_Layer);\n";
1202                                         break;
1203                         }
1204
1205                         src << "    vec4 src_color = imageLoad(storageImage, coord);\n"
1206                                 << "    o_color = (vert_color + src_color) / 2.0;\n"
1207                                 << "    imageStore(storageImage, coord, o_color);\n";
1208                 }
1209                 else if (geomOutputColor)
1210                         src << "    o_color = vert_color;\n";
1211                 else
1212                         src << "    o_color = vec4(1.0);\n";
1213
1214                 src << "}\n";
1215
1216                 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1217         }
1218 }
1219
1220 tcu::TestStatus test (Context& context, const TestParams params)
1221 {
1222         const DeviceInterface&                  vk                                              = context.getDeviceInterface();
1223         const InstanceInterface&                vki                                             = context.getInstanceInterface();
1224         const VkDevice                                  device                                  = context.getDevice();
1225         const VkPhysicalDevice                  physDevice                              = context.getPhysicalDevice();
1226         const deUint32                                  queueFamilyIndex                = context.getUniversalQueueFamilyIndex();
1227         const VkQueue                                   queue                                   = context.getUniversalQueue();
1228         Allocator&                                              allocator                               = context.getDefaultAllocator();
1229         VkDeviceSize                                    nonCoherentAtomSize             = vk::getPhysicalDeviceProperties(vki, physDevice).limits.nonCoherentAtomSize;
1230         VkDeviceSize                                    alignmentSize                   = std::max<VkDeviceSize>(nonCoherentAtomSize, 4u);
1231
1232         const VkFormat                                  colorFormat                             = VK_FORMAT_R8G8B8A8_UNORM;
1233         const deUint32                                  numLayers                               = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? params.image.size.depth : params.image.numLayers);
1234         const Vec4                                              clearColor                              = Vec4(0.0f, 0.0f, 0.0f, 1.0f);
1235         const deUint32                                  colorImagePixelSize             = static_cast<deUint32>(tcu::getPixelSize(mapVkFormat(colorFormat)));
1236         const VkDeviceSize                              colorBufferSize                 = static_cast<VkDeviceSize>(deAlignSize(params.image.size.width * params.image.size.height * colorImagePixelSize, static_cast<std::size_t>(alignmentSize)) * params.image.size.depth * params.image.numLayers);
1237         const VkImageCreateFlags                imageCreateFlags                = (isCubeImageViewType(params.image.viewType) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (VkImageCreateFlagBits)0) |
1238                                                                                                                           (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT : (VkImageCreateFlagBits)0);
1239         const VkImageViewType                   viewType                                = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : params.image.viewType);
1240
1241         const Unique<VkImage>                   colorImage                              (makeImage                              (vk, device, makeImageCreateInfo(imageCreateFlags, getImageType(params.image.viewType), colorFormat, params.image.size,
1242                                                                                                                                                                          params.image.numLayers, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
1243         const UniquePtr<Allocation>             colorImageAlloc                 (bindImage                              (vk, device, allocator, *colorImage, MemoryRequirement::Any));
1244         const Unique<VkImageView>               colorAttachment                 (makeImageView                  (vk, device, *colorImage, viewType, colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers)));
1245
1246         const Unique<VkBuffer>                  colorBuffer                             (makeBuffer                             (vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1247         const UniquePtr<Allocation>             colorBufferAlloc                (bindBuffer                             (vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1248
1249         const Unique<VkShaderModule>    vertexModule                    (createShaderModule             (vk, device, context.getBinaryCollection().get("vert"), 0u));
1250         const Unique<VkShaderModule>    geometryModule                  (createShaderModule             (vk, device, context.getBinaryCollection().get("geom"), 0u));
1251         const Unique<VkShaderModule>    fragmentModule                  (createShaderModule             (vk, device, context.getBinaryCollection().get("frag"), 0u));
1252
1253         const Unique<VkRenderPass>              renderPass                              (makeRenderPass                 (vk, device, colorFormat));
1254         const Unique<VkFramebuffer>             framebuffer                             (makeFramebuffer                (vk, device, *renderPass, *colorAttachment, params.image.size.width,  params.image.size.height, numLayers));
1255         const Unique<VkPipelineLayout>  pipelineLayout                  (makePipelineLayout             (vk, device));
1256         const Unique<VkPipeline>                pipeline                                (makeGraphicsPipeline   (vk, device, *pipelineLayout, *renderPass, *vertexModule, *geometryModule, *fragmentModule,
1257                                                                                                                                                                          makeExtent2D(params.image.size.width, params.image.size.height)));
1258         const Unique<VkCommandPool>             cmdPool                                 (createCommandPool              (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1259         const Unique<VkCommandBuffer>   cmdBuffer                               (allocateCommandBuffer  (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1260
1261         zeroBuffer(vk, device, *colorBufferAlloc, colorBufferSize);
1262
1263         beginCommandBuffer(vk, *cmdBuffer);
1264
1265         beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, params.image.size.width, params.image.size.height), clearColor);
1266
1267         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1268         vk.cmdDraw(*cmdBuffer, 1u, 1u, 0u, 0u);
1269         endRenderPass(vk, *cmdBuffer);
1270
1271         // Copy color image to buffer
1272         copyLayeredImageToBuffer(vk, *cmdBuffer, *colorImage, *colorBuffer, params.image);
1273
1274         endCommandBuffer(vk, *cmdBuffer);
1275         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1276
1277         invalidateAlloc(vk, device, *colorBufferAlloc);
1278
1279         if (!verifyResults(context.getTestContext().getLog(), params, colorFormat, colorBufferAlloc->getHostPtr()))
1280                 return tcu::TestStatus::fail("Rendered images are incorrect");
1281         else
1282                 return tcu::TestStatus::pass("OK");
1283 }
1284
1285 tcu::TestStatus testLayeredReadBack (Context& context, const TestParams params)
1286 {
1287         const DeviceInterface&                          vk                                      = context.getDeviceInterface();
1288         const InstanceInterface&                        vki                                     = context.getInstanceInterface();
1289         const VkDevice                                          device                          = context.getDevice();
1290         const VkPhysicalDevice                          physDevice                      = context.getPhysicalDevice();
1291         const deUint32                                          queueFamilyIndex        = context.getUniversalQueueFamilyIndex();
1292         const VkQueue                                           queue                           = context.getUniversalQueue();
1293         Allocator&                                                      allocator                       = context.getDefaultAllocator();
1294         VkDeviceSize                                            nonCoherentAtomSize = vk::getPhysicalDeviceProperties(vki, physDevice).limits.nonCoherentAtomSize;
1295         VkDeviceSize                                            alignmentSize           = std::max<VkDeviceSize>(nonCoherentAtomSize, 4u);
1296
1297         const size_t                                            passCount                       = 2;
1298         const deUint32                                          numLayers                       = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? params.image.size.depth : params.image.numLayers);
1299         const VkImageCreateFlags                        imageCreateFlags        = (isCubeImageViewType(params.image.viewType) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (VkImageCreateFlagBits)0) |
1300                                                                                                                           (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT : (VkImageCreateFlagBits)0);
1301         const VkImageViewType                           viewType                        = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : params.image.viewType);
1302         const VkImageType                                       imageType                       = getImageType(params.image.viewType);
1303         const VkExtent2D                                        imageExtent2D           = makeExtent2D(params.image.size.width, params.image.size.height);
1304
1305         const VkFormat                                          colorFormat                     = VK_FORMAT_R8G8B8A8_UNORM;
1306         const deUint32                                          colorImagePixelSize     = static_cast<deUint32>(tcu::getPixelSize(mapVkFormat(colorFormat)));
1307         const VkDeviceSize                                      colorBufferSize         = static_cast<VkDeviceSize>( deAlignSize(params.image.size.width * params.image.size.height * colorImagePixelSize, static_cast<std::size_t>(alignmentSize)) * params.image.size.depth * params.image.numLayers );
1308         const VkImageUsageFlags                         colorImageUsage         = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
1309
1310         const bool                                                      dsUsed                          = true;
1311         const VkFormat                                          dsFormat                        = VK_FORMAT_D24_UNORM_S8_UINT;
1312         const VkImageType                                       dsImageType                     = (imageType == VK_IMAGE_TYPE_3D ? VK_IMAGE_TYPE_2D : imageType); // depth/stencil 2D_ARRAY attachments cannot be taken from 3D image, use 2D_ARRAY image instead.
1313         const VkExtent3D                                        dsImageSize                     = makeExtent3D(params.image.size.width, params.image.size.height, 1u);
1314         const VkImageCreateFlags                        dsImageCreateFlags      = (isCubeImageViewType(params.image.viewType) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (VkImageCreateFlagBits)0);
1315         const deUint32                                          dsImagePixelSize        = static_cast<deUint32>(tcu::getPixelSize(mapVkFormat(dsFormat)));
1316         const VkImageUsageFlags                         dsImageUsage            = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
1317         const VkImageAspectFlags                        dsAspectFlags           = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
1318         const VkDeviceSize                                      depthBufferSize         = static_cast<VkDeviceSize>(deAlignSize(params.image.size.width * params.image.size.height * dsImagePixelSize, static_cast<std::size_t>(alignmentSize)) * params.image.size.depth * params.image.numLayers);
1319
1320         const VkFormat                                          stencilBufferFormat     = getStencilBufferFormat(dsFormat);
1321         const deUint32                                          stencilPixelSize        = static_cast<deUint32>(tcu::getPixelSize(mapVkFormat(stencilBufferFormat)));
1322         const VkDeviceSize                                      stencilBufferSize       = static_cast<VkDeviceSize>(deAlignSize( params.image.size.width * params.image.size.height * stencilPixelSize, static_cast<std::size_t>(alignmentSize)) * params.image.size.depth * params.image.numLayers);
1323
1324         checkImageFormatProperties(vki, physDevice, imageType, VK_IMAGE_TILING_OPTIMAL, dsImageUsage, imageCreateFlags, dsFormat, params.image.size, params.image.numLayers);
1325
1326         const Unique<VkImage>                           colorImage                      (makeImage                              (vk, device, makeImageCreateInfo(imageCreateFlags, imageType, colorFormat, params.image.size, params.image.numLayers, colorImageUsage)));
1327         const UniquePtr<Allocation>                     colorImageAlloc         (bindImage                              (vk, device, allocator, *colorImage, MemoryRequirement::Any));
1328         const Unique<VkImageView>                       colorAttachment         (makeImageView                  (vk, device, *colorImage, viewType, colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers)));
1329         const Unique<VkBuffer>                          colorBuffer                     (makeBuffer                             (vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1330         const UniquePtr<Allocation>                     colorBufferAlloc        (bindBuffer                             (vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1331
1332         const Unique<VkImage>                           dsImage                         (makeImage                              (vk, device, makeImageCreateInfo(dsImageCreateFlags, dsImageType, dsFormat, dsImageSize, numLayers, dsImageUsage)));
1333         const UniquePtr<Allocation>                     dsImageAlloc            (bindImage                              (vk, device, allocator, *dsImage, MemoryRequirement::Any));
1334         const Unique<VkImageView>                       dsAttachment            (makeImageView                  (vk, device, *dsImage, viewType, dsFormat, makeImageSubresourceRange(dsAspectFlags, 0u, 1u, 0u, numLayers)));
1335         const Unique<VkBuffer>                          depthBuffer                     (makeBuffer                             (vk, device, depthBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1336         const UniquePtr<Allocation>                     depthBufferAlloc        (bindBuffer                             (vk, device, allocator, *depthBuffer, MemoryRequirement::HostVisible));
1337         const Unique<VkBuffer>                          stencilBuffer           (makeBuffer                             (vk, device, stencilBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1338         const UniquePtr<Allocation>                     stencilBufferAlloc      (bindBuffer                             (vk, device, allocator, *stencilBuffer, MemoryRequirement::HostVisible));
1339
1340         const VkImageView                                       attachments[]           = {*colorAttachment, *dsAttachment};
1341         const deUint32                                          attachmentsCount        = dsUsed ? DE_LENGTH_OF_ARRAY(attachments) : 1u;
1342
1343         const Unique<VkShaderModule>            vertexModule            (createShaderModule             (vk, device, context.getBinaryCollection().get("vert"), 0u));
1344         const Unique<VkShaderModule>            geometryModule          (createShaderModule             (vk, device, context.getBinaryCollection().get("geom"), 0u));
1345         const Unique<VkShaderModule>            fragmentModule          (createShaderModule             (vk, device, context.getBinaryCollection().get("frag"), 0u));
1346
1347         const Unique<VkRenderPass>                      renderPass                      (makeRenderPass                 (vk, device, colorFormat, dsFormat, dsUsed));
1348         const Unique<VkFramebuffer>                     framebuffer                     (makeFramebuffer                (vk, device, *renderPass, attachmentsCount, attachments, params.image.size.width, params.image.size.height, numLayers));
1349
1350         const Move<VkDescriptorPool>            descriptorPool          = DescriptorPoolBuilder()
1351                                                                                                                           .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, passCount)
1352                                                                                                                           .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, passCount);
1353         const Move<VkDescriptorSetLayout>       descriptorSetLayout     = DescriptorSetLayoutBuilder()
1354                                                                                                                           .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_GEOMETRY_BIT)
1355                                                                                                                           .build(vk, device);
1356         const Move<VkDescriptorSet>                     descriptorSet[]         =
1357         {
1358                 makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout),
1359                 makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout),
1360         };
1361
1362         const size_t                                            uniformBufSize          = sizeof(deUint32);
1363         const VkBufferCreateInfo                        uniformBufCI            = makeBufferCreateInfo(uniformBufSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
1364         const Move<VkBuffer>                            uniformBuf[]            = { createBuffer(vk, device, &uniformBufCI), createBuffer(vk, device, &uniformBufCI) };
1365         const MovePtr<Allocation>                       uniformBufAlloc[]       =
1366         {
1367                 allocator.allocate(getBufferMemoryRequirements(vk, device, *uniformBuf[0]), MemoryRequirement::HostVisible),
1368                 allocator.allocate(getBufferMemoryRequirements(vk, device, *uniformBuf[1]), MemoryRequirement::HostVisible),
1369         };
1370         const VkDescriptorBufferInfo            uniformBufDesc[]        =
1371         {
1372                 makeDescriptorBufferInfo(*uniformBuf[0], 0ull, uniformBufSize),
1373                 makeDescriptorBufferInfo(*uniformBuf[1], 0ull, uniformBufSize),
1374         };
1375
1376         const Unique<VkPipelineLayout>          pipelineLayout          (makePipelineLayout             (vk, device, *descriptorSetLayout));
1377         const Unique<VkPipeline>                        pipeline                        (makeGraphicsPipeline   (vk, device, *pipelineLayout, *renderPass, *vertexModule, *geometryModule, *fragmentModule, imageExtent2D, dsUsed));
1378         const Unique<VkCommandPool>                     cmdPool                         (createCommandPool              (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1379         const Unique<VkCommandBuffer>           cmdBuffer                       (allocateCommandBuffer  (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1380         const VkImageSubresourceRange           colorSubresRange        = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, params.image.numLayers);
1381         const VkImageSubresourceRange           dsSubresRange           = makeImageSubresourceRange(dsAspectFlags, 0u, 1u, 0u, numLayers);
1382         std::string                                                     result;
1383
1384         beginCommandBuffer(vk, *cmdBuffer);
1385         {
1386                 // Transition the images to new layouts
1387                 const VkImageMemoryBarrier              colorBarrier    = makeImageMemoryBarrier(0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1388                                                                                                                                                                  VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, *colorImage, colorSubresRange);
1389                 const VkImageMemoryBarrier              dsBarrier               = makeImageMemoryBarrier(0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1390                                                                                                                                                                  VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, *dsImage, dsSubresRange);
1391
1392                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &colorBarrier);
1393
1394                 if (dsUsed)
1395                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &dsBarrier);
1396
1397                 for (deUint32 layerNdx = 0; layerNdx < numLayers; ++layerNdx)
1398                 {
1399                         const VkExtent3D        imageExtent = makeExtent3D(params.image.size.width, params.image.size.height, 1u);
1400
1401                         // Clear color image with initial value
1402                         {
1403                                 const deUint32                                  layer                                   = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType) ? 0u : layerNdx;
1404                                 const deUint32                                  imageDepth                              = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType) ? layerNdx : 0u;
1405                                 const VkOffset3D                                imageOffset                             = makeOffset3D(0u, 0u, imageDepth);
1406
1407                                 const tcu::Vec4                                 clearColor                              = scaleColor(s_colors[layerNdx % DE_LENGTH_OF_ARRAY(s_colors)], 0.25f);
1408                                 const deUint32                                  bufferSliceSize                 = deAlign32( params.image.size.width * params.image.size.height * colorImagePixelSize, static_cast<deInt32>(alignmentSize));
1409                                 const VkDeviceSize                              bufferOffset                    = layerNdx * bufferSliceSize;
1410                                 const VkImageSubresourceLayers  imageSubresource                = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, layer, 1u);
1411                                 const VkBufferImageCopy                 bufferImageCopyRegion   = makeBufferImageCopy(bufferOffset, imageSubresource, imageOffset, imageExtent);
1412
1413                                 fillBuffer(vk, device, *colorBufferAlloc, bufferOffset, bufferSliceSize, colorFormat, clearColor);
1414                                 vk.cmdCopyBufferToImage(*cmdBuffer, *colorBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferImageCopyRegion);
1415                         }
1416
1417                         // Clear depth image with initial value
1418                         if (dsUsed)
1419                         {
1420                                 const float                                             depthValue                              = 1.0f;
1421                                 const deUint32                                  bufferSliceSize                 = deAlign32( params.image.size.width * params.image.size.height * dsImagePixelSize, static_cast<deInt32>(alignmentSize));
1422                                 const VkDeviceSize                              bufferOffset                    = layerNdx * bufferSliceSize;
1423                                 const VkImageSubresourceLayers  imageSubresource                = makeImageSubresourceLayers(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, layerNdx, 1u);
1424                                 const VkBufferImageCopy                 bufferImageCopyRegion   = makeBufferImageCopy(bufferOffset, imageSubresource, makeOffset3D(0u, 0u, 0u), imageExtent);
1425
1426                                 fillBuffer(vk, device, *depthBufferAlloc, bufferOffset, bufferSliceSize, dsFormat, depthValue);
1427                                 vk.cmdCopyBufferToImage(*cmdBuffer, *depthBuffer, *dsImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferImageCopyRegion);
1428                         }
1429
1430                         // Clear stencil image with initial value
1431                         if (dsUsed)
1432                         {
1433                                 const deUint8                                   stencilValue                    = 0;
1434                                 const deUint32                                  bufferSliceSize                 = deAlign32( params.image.size.width * params.image.size.height * stencilPixelSize, static_cast<deInt32>(alignmentSize));
1435                                 const VkDeviceSize                              bufferOffset                    = layerNdx * bufferSliceSize;
1436                                 const VkImageSubresourceLayers  imageSubresource                = makeImageSubresourceLayers(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, layerNdx, 1u);
1437                                 const VkBufferImageCopy                 bufferImageCopyRegion   = makeBufferImageCopy(bufferOffset, imageSubresource, makeOffset3D(0u, 0u, 0u), imageExtent);
1438                                 deUint8*                                                bufferStart                             = static_cast<deUint8*>((*stencilBufferAlloc).getHostPtr());
1439                                 deUint8*                                                bufferLayerStart                = &bufferStart[bufferOffset];
1440
1441                                 deMemset(bufferLayerStart, stencilValue, bufferSliceSize);
1442                                 flushMappedMemoryRange(vk, device, stencilBufferAlloc->getMemory(), stencilBufferAlloc->getOffset() + bufferOffset, bufferSliceSize);
1443                                 vk.cmdCopyBufferToImage(*cmdBuffer, *stencilBuffer, *dsImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferImageCopyRegion);
1444                         }
1445                 }
1446         }
1447         // Change images layouts
1448         {
1449                 // VK_ATTACHMENT_LOAD_OP_LOAD is used for both color and D/S attachments. Thus,
1450                 // VK_ACCESS_COLOR_ATTACHMENT_READ_BIT and VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
1451                 // bits must be included in the destination access mask of the color and depth barriers
1452                 // respectively.
1453                 const VkImageMemoryBarrier              colorBarrier    = makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,
1454                                                                                                                                                                  VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *colorImage, colorSubresRange);
1455                 const VkImageMemoryBarrier              dsBarrier               = makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
1456                                                                                                                                                                  VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, *dsImage, dsSubresRange);
1457
1458                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &colorBarrier);
1459
1460                 if (dsUsed)
1461                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &dsBarrier);
1462         }
1463
1464         {
1465                 // These barriers are inserted between each pair of renderpasses in the following
1466                 // loop. Note that VK_ATTACHMENT_LOAD_OP_LOAD is used for color and D/S attachments
1467                 // hence VK_ACCESS_COLOR_ATTACHMENT_READ_BIT and VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
1468                 // bits are included in src and dst access mask of the color and depth barriers.
1469                 const VkImageMemoryBarrier                      colorPassBarrier        = makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,
1470                                                                                                                                                                                  VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,
1471                                                                                                                                                                                  VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *colorImage, colorSubresRange);
1472                 const VkImageMemoryBarrier                      dsPassBarrier           = makeImageMemoryBarrier(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
1473                                                                                                                                                                                  VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
1474                                                                                                                                                                                  VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, *dsImage, dsSubresRange);
1475                 for (deUint32 pass = 0; pass < passCount; ++pass)
1476                 {
1477                         DE_ASSERT(sizeof(pass) == uniformBufSize);
1478
1479                         VK_CHECK(vk.bindBufferMemory(device, *uniformBuf[pass], uniformBufAlloc[pass]->getMemory(), uniformBufAlloc[pass]->getOffset()));
1480                         deMemcpy(uniformBufAlloc[pass]->getHostPtr(), &pass, uniformBufSize);
1481                         flushMappedMemoryRange(vk, device, uniformBufAlloc[pass]->getMemory(), uniformBufAlloc[pass]->getOffset(), VK_WHOLE_SIZE);
1482
1483                         DescriptorSetUpdateBuilder()
1484                                 .writeSingle(*descriptorSet[pass], DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &uniformBufDesc[pass])
1485                                 .update(vk, device);
1486
1487                         vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &*descriptorSet[pass], 0u, DE_NULL);
1488                         beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(imageExtent2D));
1489                         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1490                         vk.cmdDraw(*cmdBuffer, 1u, 1u, 0u, 0u);
1491                         endRenderPass(vk, *cmdBuffer);
1492
1493                         // Don't add the barrier after the last renderpass
1494                         if (pass < passCount - 1)
1495                         {
1496                                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &colorPassBarrier);
1497
1498                                 if (dsUsed)
1499                                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &dsPassBarrier);
1500                         }
1501                 }
1502         }
1503         endCommandBuffer(vk, *cmdBuffer);
1504         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1505
1506         zeroBuffer(vk, device, *colorBufferAlloc, colorBufferSize);
1507         zeroBuffer(vk, device, *depthBufferAlloc, depthBufferSize);
1508         zeroBuffer(vk, device, *stencilBufferAlloc, stencilBufferSize);
1509
1510         beginCommandBuffer(vk, *cmdBuffer);
1511         {
1512                 // Copy color image
1513                 {
1514                         const VkImageMemoryBarrier      preCopyBarrier  = makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,
1515                                                                                                                                                                  VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorImage, colorSubresRange);
1516                         const VkBufferImageCopy         region                  = makeBufferImageCopy(params.image.size, makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, params.image.numLayers));
1517                         const VkBufferMemoryBarrier     postCopyBarrier = makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *colorBuffer, 0ull, VK_WHOLE_SIZE);
1518
1519                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &preCopyBarrier);
1520                         vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, &region);
1521                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &postCopyBarrier, DE_NULL, 0u);
1522                 }
1523
1524                 // Depth/Stencil image copy
1525                 if (dsUsed)
1526                 {
1527                         const VkImageMemoryBarrier      preCopyBarrier          = makeImageMemoryBarrier(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
1528                                                                                                                                                                          VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *dsImage, dsSubresRange);
1529                         const VkBufferImageCopy         depthCopyRegion         = makeBufferImageCopy(dsImageSize, makeImageSubresourceLayers(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 0u, numLayers));
1530                         const VkBufferImageCopy         stencilCopyRegion       = makeBufferImageCopy(dsImageSize, makeImageSubresourceLayers(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 0u, numLayers));
1531                         const VkBufferMemoryBarrier     postCopyBarriers[]      =
1532                         {
1533                                 makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *depthBuffer, 0ull, VK_WHOLE_SIZE),
1534                                 makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *stencilBuffer, 0ull, VK_WHOLE_SIZE),
1535                         };
1536
1537                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &preCopyBarrier);
1538                         vk.cmdCopyImageToBuffer(*cmdBuffer, *dsImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *depthBuffer, 1u, &depthCopyRegion);
1539                         vk.cmdCopyImageToBuffer(*cmdBuffer, *dsImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *stencilBuffer, 1u, &stencilCopyRegion);
1540                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(postCopyBarriers), postCopyBarriers, DE_NULL, 0u);
1541                 }
1542         }
1543         endCommandBuffer(vk, *cmdBuffer);
1544         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1545
1546         invalidateAlloc(vk, device, *colorBufferAlloc);
1547         invalidateAlloc(vk, device, *depthBufferAlloc);
1548         invalidateAlloc(vk, device, *stencilBufferAlloc);
1549
1550         if (!verifyResults(context.getTestContext().getLog(), params, colorFormat, colorBufferAlloc->getHostPtr()))
1551                 result += " Color";
1552
1553         if (dsUsed)
1554         {
1555                 if (!verifyResults(context.getTestContext().getLog(), params, dsFormat, depthBufferAlloc->getHostPtr(), true, false))
1556                         result += " Depth";
1557
1558                 if (!verifyResults(context.getTestContext().getLog(), params, stencilBufferFormat, stencilBufferAlloc->getHostPtr(), false, true))
1559                         result += " Stencil";
1560         }
1561
1562         if (result.empty())
1563                 return tcu::TestStatus::pass("OK");
1564         else
1565                 return tcu::TestStatus::fail("Following parts of image are incorrect:" + result);
1566 }
1567
1568 tcu::TestStatus testSecondaryCmdBuffer (Context& context, const TestParams params)
1569 {
1570         const DeviceInterface&                          vk                                      = context.getDeviceInterface();
1571         const InstanceInterface&                        vki                                     = context.getInstanceInterface();
1572         const VkDevice                                          device                          = context.getDevice();
1573         const VkPhysicalDevice                          physDevice                      = context.getPhysicalDevice();
1574         const deUint32                                          queueFamilyIndex        = context.getUniversalQueueFamilyIndex();
1575         const VkQueue                                           queue                           = context.getUniversalQueue();
1576         Allocator&                                                      allocator                       = context.getDefaultAllocator();
1577         VkDeviceSize                                            nonCoherentAtomSize     = vk::getPhysicalDeviceProperties(vki, physDevice).limits.nonCoherentAtomSize;
1578         VkDeviceSize                                            alignmentSize           = std::max<VkDeviceSize>(nonCoherentAtomSize, 4u);
1579
1580         const VkFormat                                          colorFormat                     = VK_FORMAT_R8G8B8A8_UNORM;
1581         const deUint32                                          numLayers                       = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? params.image.size.depth : params.image.numLayers);
1582         const Vec4                                                      clearColor                      = Vec4(0.0f, 0.0f, 0.0f, 1.0f);
1583         const deUint32                                          colorImagePixelSize     = static_cast<deUint32>(tcu::getPixelSize(mapVkFormat(colorFormat)));
1584         const VkDeviceSize                                      colorBufferSize         = static_cast<VkDeviceSize>(deAlignSize(params.image.size.width * params.image.size.height * colorImagePixelSize, static_cast<std::size_t>(alignmentSize)) * params.image.size.depth * params.image.numLayers);
1585
1586         const VkImageCreateFlags                        imageCreateFlags        = (isCubeImageViewType(params.image.viewType) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (VkImageCreateFlagBits)0) |
1587                                                                                                                           (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT : (VkImageCreateFlagBits)0);
1588         const VkImageViewType                           viewType                        = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : params.image.viewType);
1589
1590         const Unique<VkImage>                           colorImage                      (makeImage(vk, device, makeImageCreateInfo(imageCreateFlags, getImageType(params.image.viewType), colorFormat, params.image.size,
1591                                                                                                                                            params.image.numLayers, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
1592         const UniquePtr<Allocation>                     colorImageAlloc         (bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
1593         const Unique<VkImageView>                       colorImageView          (makeImageView(vk, device, *colorImage, viewType, colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers)));
1594
1595         const Unique<VkImage>                           offscreenImage          (makeImage(vk, device, makeImageCreateInfo(imageCreateFlags, getImageType(params.image.viewType), colorFormat, params.image.size,
1596                                                                                                                                            params.image.numLayers, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT)));
1597         const UniquePtr<Allocation>                     offscreenImageAlloc     (bindImage(vk, device, allocator, *offscreenImage, MemoryRequirement::Any));
1598         const Unique<VkImageView>                       offscreenImageView      (makeImageView(vk, device, *offscreenImage, params.image.viewType, colorFormat,
1599                                                                                                                                                    makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, params.image.numLayers)));
1600
1601         const Unique<VkBuffer>                          colorBuffer                     (makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1602         const UniquePtr<Allocation>                     colorBufferAlloc        (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1603
1604         const Move<VkDescriptorPool>            descriptorPool          = DescriptorPoolBuilder() .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1u) .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1605         const Move<VkDescriptorSetLayout>       descriptorSetLayout     = DescriptorSetLayoutBuilder() .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT) .build(vk, device);
1606         const Move<VkDescriptorSet>                     descriptorSet           = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
1607
1608         const Unique<VkShaderModule>            vertexModule            (createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u));
1609         const Unique<VkShaderModule>            geometryModule          (createShaderModule(vk, device, context.getBinaryCollection().get("geom"), 0u));
1610         const Unique<VkShaderModule>            fragmentModule          (createShaderModule(vk, device, context.getBinaryCollection().get("frag"), 0u));
1611
1612         const Unique<VkRenderPass>                      renderPass                      (makeRenderPassWithSelfDependency(vk, device, colorFormat));
1613         const Unique<VkFramebuffer>                     framebuffer                     (makeFramebuffer(vk, device, *renderPass, *colorImageView, params.image.size.width, params.image.size.height, numLayers));
1614         const Unique<VkPipelineLayout>          pipelineLayout          (makePipelineLayout(vk, device, *descriptorSetLayout));
1615         const Unique<VkPipeline>                        pipeline                        (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *geometryModule, *fragmentModule,
1616                                                                                                                                                                   makeExtent2D(params.image.size.width, params.image.size.height)));
1617
1618         const Unique<VkCommandPool>                     cmdPool                         (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1619         const Unique<VkCommandBuffer>           cmdBuffer                       (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1620         const Unique<VkCommandBuffer>           secondaryCmdBuffer      (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY));
1621
1622         zeroBuffer(vk, device, *colorBufferAlloc, colorBufferSize);
1623
1624         const VkDescriptorImageInfo imageDescriptorInfo = makeDescriptorImageInfo(DE_NULL, *offscreenImageView, VK_IMAGE_LAYOUT_GENERAL);
1625
1626         DescriptorSetUpdateBuilder()
1627                 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &imageDescriptorInfo)
1628                 .update(vk, device);
1629
1630         // Clear each layer of storage image
1631         {
1632                 vk::Unique<vk::VkCommandBuffer> clearCmdBuffer (vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1633                 beginCommandBuffer(vk, *clearCmdBuffer);
1634
1635                 const vk::VkImageSubresourceRange       subresourceRange        =
1636                 {
1637                         vk::VK_IMAGE_ASPECT_COLOR_BIT,  // VkImageAspectFlags   aspectMask
1638                         0u,                                                             // deUint32                             baseMipLevel
1639                         1u,                                                             // deUint32                             levelCount
1640                         0u,                                                             // deUint32                             baseArrayLayer
1641                         params.image.numLayers                  // deUint32                             layerCount
1642                 };
1643
1644                 const vk::VkImageMemoryBarrier          preImageBarrier         =
1645                 {
1646                         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,     // VkStructureType                      sType
1647                         DE_NULL,                                                                        // const void*                          pNext
1648                         0u,                                                                                     // VkAccessFlags                        srcAccessMask
1649                         vk::VK_ACCESS_TRANSFER_WRITE_BIT,                       // VkAccessFlags                        dstAccessMask
1650                         vk::VK_IMAGE_LAYOUT_UNDEFINED,                          // VkImageLayout                        oldLayout
1651                         vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,       // VkImageLayout                        newLayout
1652                         queueFamilyIndex,                                                       // deUint32                                     srcQueueFamilyIndex
1653                         queueFamilyIndex,                                                       // deUint32                                     dstQueueFamilyIndex
1654                         *offscreenImage,                                                        // VkImage                                      image
1655                         subresourceRange                                                        // VkImageSubresourceRange      subresourceRange
1656                 };
1657
1658                 const vk::VkImageMemoryBarrier          postImageBarrier        =
1659                 {
1660                         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,     // VkStructureType                      sType
1661                         DE_NULL,                                                                        // const void*                          pNext
1662                         vk::VK_ACCESS_TRANSFER_WRITE_BIT,                       // VkAccessFlags                        srcAccessMask
1663                         vk::VK_ACCESS_SHADER_WRITE_BIT,                         // VkAccessFlags                        dstAccessMask
1664                         vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,       // VkImageLayout                        oldLayout
1665                         vk::VK_IMAGE_LAYOUT_GENERAL,                            // VkImageLayout                        newLayout
1666                         queueFamilyIndex,                                                       // deUint32                                     srcQueueFamilyIndex
1667                         queueFamilyIndex,                                                       // deUint32                                     dstQueueFamilyIndex
1668                         *offscreenImage,                                                        // VkImage                                      image
1669                         subresourceRange                                                        // VkImageSubresourceRange      subresourceRange
1670                 };
1671
1672                 vk.cmdPipelineBarrier(*clearCmdBuffer,
1673                                 vk::VK_PIPELINE_STAGE_HOST_BIT,
1674                                 vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
1675                                 (vk::VkDependencyFlags)0,
1676                                 0, (const vk::VkMemoryBarrier*)DE_NULL,
1677                                 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
1678                                 1, &preImageBarrier);
1679
1680                 for (deUint32 layerNdx = 0; layerNdx < numLayers; ++layerNdx)
1681                 {
1682                         const deUint32          imageDepth      = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType) ? layerNdx :       0u;
1683                         const deUint32          layer           = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType) ?       0u : layerNdx;
1684                         const VkOffset3D        imageOffset = makeOffset3D(0u, 0u, imageDepth);
1685                         const VkExtent3D        imageExtent = makeExtent3D(params.image.size.width, params.image.size.height, 1u);
1686
1687                         {
1688                                 const tcu::Vec4                                 storageImageClearColor  = secondaryCmdBufClearColors[layerNdx % DE_LENGTH_OF_ARRAY(secondaryCmdBufClearColors)];
1689                                 const deUint32                                  bufferSliceSize                 = deAlign32(params.image.size.width * params.image.size.height * colorImagePixelSize, static_cast<deInt32>(alignmentSize));
1690                                 const VkDeviceSize                              bufferOffset                    = layerNdx * bufferSliceSize;
1691                                 const VkImageSubresourceLayers  imageSubresource                = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, layer, 1u);
1692                                 const VkBufferImageCopy                 bufferImageCopyRegion   = makeBufferImageCopy(bufferOffset, imageSubresource, imageOffset, imageExtent);
1693
1694                                 fillBuffer(vk, device, *colorBufferAlloc, bufferOffset, bufferSliceSize, colorFormat, storageImageClearColor);
1695                                 vk.cmdCopyBufferToImage(*clearCmdBuffer, *colorBuffer, *offscreenImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &bufferImageCopyRegion);
1696                         }
1697                 }
1698
1699                 vk.cmdPipelineBarrier(*clearCmdBuffer,
1700                                 vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
1701                                 vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
1702                                 (vk::VkDependencyFlags)0,
1703                                 0, (const vk::VkMemoryBarrier*)DE_NULL,
1704                                 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
1705                                 1, &postImageBarrier);
1706
1707                 endCommandBuffer(vk, *clearCmdBuffer);
1708
1709                 submitCommandsAndWait(vk, device, queue, *clearCmdBuffer);
1710         }
1711
1712         // Begin secondary command buffer
1713         {
1714                 const VkCommandBufferInheritanceInfo    commandBufferInheritanceInfo    =
1715                 {
1716                         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,                              // VkStructureType                                      sType
1717                         DE_NULL,                                                                                                                // const void*                                          pNext
1718                         *renderPass,                                                                                                    // VkRenderPass                                         renderPass
1719                         0u,                                                                                                                             // deUint32                                                     subpass
1720                         params.inheritFramebuffer ? *framebuffer : (VkFramebuffer)0,    // VkFramebuffer                                        framebuffer
1721                         VK_FALSE,                                                                                                               // VkBool32                                                     occlusionQueryEnable
1722                         0u,                                                                                                                             // VkQueryControlFlags                          queryFlags
1723                         0u                                                                                                                              // VkQueryPipelineStatisticFlags        pipelineStatistics
1724                 };
1725
1726                 const VkCommandBufferBeginInfo                  commandBufferBeginInfo                  =
1727                 {
1728                         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,            // VkStructureType                                                      sType
1729                         DE_NULL,                                                                                        // const void*                                                          pNext
1730                         VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
1731                         | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT,     // VkCommandBufferUsageFlags                            flags
1732                         &commandBufferInheritanceInfo                                           // const VkCommandBufferInheritanceInfo*        pInheritanceInfo
1733                 };
1734
1735                 VK_CHECK(vk.beginCommandBuffer(*secondaryCmdBuffer, &commandBufferBeginInfo));
1736         }
1737
1738         vk.cmdBindDescriptorSets(*secondaryCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &*descriptorSet, 0u, DE_NULL);
1739
1740         // Clear framebuffer: upper right corner for half of the layers and bottom right for the others.
1741         {
1742                 const VkClearAttachment clearAttachment =
1743                 {
1744                         VK_IMAGE_ASPECT_COLOR_BIT,                                              // VkImageAspectFlags   aspectMask
1745                         0u,                                                                                             // deUint32                             colorAttachment
1746                         makeClearValueColorF32(0.5f, 0.25, 0.0f, 1.0f)  // VkClearValue                 clearValue
1747                 };
1748
1749                 const VkOffset2D                offsetTop               = { (deInt32)params.image.size.width / 2, 0 };
1750                 const VkOffset2D                offsetBottom    = { (deInt32)params.image.size.width / 2, (deInt32)params.image.size.height / 2 };
1751                 const VkExtent2D                extentTop               = { params.image.size.width / 2, params.image.size.height / 2 };
1752                 const VkExtent2D                extentBottom    = { params.image.size.width / 2, de::max(params.image.size.height / 2, 1u) };
1753                 const VkRect2D                  rectRightTop    = { offsetTop, extentTop };
1754                 const VkRect2D                  rectRightBottom = { offsetBottom, extentBottom };
1755
1756                 const VkClearRect               rects[]                 =
1757                 {
1758                         {
1759                                 rectRightBottom,        // VkRect2D     rect
1760                                 numLayers / 2,          // deUint32     baseArrayLayer
1761                                 numLayers / 2           // deUint32     layerCount
1762                         },
1763                         {
1764                                 rectRightTop,           // VkRect2D     rect
1765                                 0u,                                     // deUint32     baseArrayLayer
1766                                 numLayers / 2           // deUint32     layerCount
1767                         }
1768                 };
1769
1770                 vk.cmdClearAttachments(*secondaryCmdBuffer, 1u, &clearAttachment, extentTop.height > 0 ? 2u : 1u, rects);
1771         }
1772
1773         vk.cmdBindPipeline(*secondaryCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1774         vk.cmdDraw(*secondaryCmdBuffer, 1u, 1u, 0u, 0u);
1775         // Barrier between draws
1776         {
1777                 const VkMemoryBarrier barrier =
1778                 {
1779                         VK_STRUCTURE_TYPE_MEMORY_BARRIER,       // VkStructureType      sType
1780                         DE_NULL,                                                        // const void*          pNext
1781                         VK_ACCESS_SHADER_WRITE_BIT,                     // VkAccessFlags        srcAccessMask
1782                         VK_ACCESS_SHADER_READ_BIT                       // VkAccessFlags        dstAccessMask
1783                 };
1784
1785                 vk.cmdPipelineBarrier(*secondaryCmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 1u, &barrier, 0u, DE_NULL, 0u, DE_NULL);
1786         }
1787         vk.cmdDraw(*secondaryCmdBuffer, 1u, 1u, 0u, 0u);
1788         endCommandBuffer(vk, *secondaryCmdBuffer);
1789
1790         beginCommandBuffer(vk, *cmdBuffer);
1791         beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, params.image.size.width, params.image.size.height), clearColor, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
1792         vk.cmdExecuteCommands(*cmdBuffer, 1u, &(*secondaryCmdBuffer));
1793         endRenderPass(vk, *cmdBuffer);
1794
1795         copyLayeredImageToBuffer(vk, *cmdBuffer, *colorImage, *colorBuffer, params.image);
1796
1797         endCommandBuffer(vk, *cmdBuffer);
1798         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1799
1800         invalidateAlloc(vk, device, *colorBufferAlloc);
1801
1802         if (!verifyResults(context.getTestContext().getLog(), params, colorFormat, colorBufferAlloc->getHostPtr()))
1803                 return tcu::TestStatus::fail("Rendered images are incorrect");
1804         else
1805                 return tcu::TestStatus::pass("OK");
1806 }
1807
1808 void checkSupport (Context& context, const TestParams params)
1809 {
1810         context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
1811
1812         if (params.image.viewType == VK_IMAGE_VIEW_TYPE_3D)
1813         {
1814                 context.requireDeviceFunctionality("VK_KHR_maintenance1");
1815
1816 #ifndef CTS_USES_VULKANSC
1817                 if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
1818                         !context.getPortabilitySubsetFeatures().imageView2DOn3DImage)
1819                 {
1820                         TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Implementation does not support 2D or 2D array image view to be created on a 3D VkImage");
1821                 }
1822 #endif // CTS_USES_VULKANSC
1823         }
1824
1825         if (params.testType == TEST_TYPE_SECONDARY_CMD_BUFFER)
1826         {
1827                 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_FRAGMENT_STORES_AND_ATOMICS);
1828 #ifdef CTS_USES_VULKANSC
1829                 if (!params.inheritFramebuffer && context.getDeviceVulkanSC10Properties().secondaryCommandBufferNullOrImagelessFramebuffer == VK_FALSE)
1830                         TCU_THROW(NotSupportedError, "secondaryCommandBufferNullFramebuffer is not supported");
1831 #endif
1832         }
1833 }
1834
1835 } // anonymous
1836
1837 tcu::TestCaseGroup* createLayeredRenderingTests (tcu::TestContext& testCtx)
1838 {
1839         MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "layered", "Layered rendering tests."));
1840
1841         const struct
1842         {
1843                 TestType                test;
1844                 const char*             name;
1845                 const char*             description;
1846         } testTypes[] =
1847         {
1848                 { TEST_TYPE_DEFAULT_LAYER,                                      "render_to_default_layer",                      "Render to the default layer"                                                                                                                   },
1849                 { TEST_TYPE_SINGLE_LAYER,                                       "render_to_one",                                        "Render to one layer"                                                                                                                                   },
1850                 { TEST_TYPE_ALL_LAYERS,                                         "render_to_all",                                        "Render to all layers"                                                                                                                                  },
1851                 { TEST_TYPE_DIFFERENT_CONTENT,                          "render_different_content",                     "Render different data to different layers"                                                                                             },
1852                 { TEST_TYPE_LAYER_ID,                                           "fragment_layer",                                       "Read gl_Layer in fragment shader"                                                                                                              },
1853                 { TEST_TYPE_INVOCATION_PER_LAYER,                       "invocation_per_layer",                         "Render to multiple layers with multiple invocations, one invocation per layer"                 },
1854                 { TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION,     "multiple_layers_per_invocation",       "Render to multiple layers with multiple invocations, multiple layers per invocation",  },
1855                 { TEST_TYPE_LAYERED_READBACK,                           "readback",                                                     "Render to multiple layers with two passes to check LOAD_OP_LOAD capability"                    },
1856                 { TEST_TYPE_SECONDARY_CMD_BUFFER,                       "secondary_cmd_buffer",                         "Layered rendering using secondary command buffer"                                                                              }
1857         };
1858
1859         const struct
1860         {
1861                 VkImageViewType viewType;
1862                 ImageParams             imageParams[2];
1863         } imageParamGroups[] =
1864         {
1865                 { VK_IMAGE_VIEW_TYPE_1D_ARRAY,          { { VK_IMAGE_VIEW_TYPE_1D_ARRAY,        { 64,  1, 1 },  4       },      { VK_IMAGE_VIEW_TYPE_1D_ARRAY,          { 12,  1, 1 },  6       } } },
1866                 { VK_IMAGE_VIEW_TYPE_2D_ARRAY,          { { VK_IMAGE_VIEW_TYPE_2D_ARRAY,        { 64, 64, 1 },  4       },      { VK_IMAGE_VIEW_TYPE_2D_ARRAY,          { 12, 36, 1 },  6       } } },
1867                 { VK_IMAGE_VIEW_TYPE_CUBE,                      { { VK_IMAGE_VIEW_TYPE_CUBE,            { 64, 64, 1 },  6       },      { VK_IMAGE_VIEW_TYPE_CUBE,                      { 36, 36, 1 },  6       } } },
1868                 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,        { { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,      { 64, 64, 1 },  2*6     },      { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,        { 36, 36, 1 },  2*6     } } },
1869                 { VK_IMAGE_VIEW_TYPE_3D,                        { { VK_IMAGE_VIEW_TYPE_3D,                      { 64, 64, 8 },  1       },      { VK_IMAGE_VIEW_TYPE_3D,                        { 12, 36, 6 },  1       } } }
1870         };
1871
1872         for (int imageParamGroupNdx = 0; imageParamGroupNdx < DE_LENGTH_OF_ARRAY(imageParamGroups); ++imageParamGroupNdx)
1873         {
1874                 MovePtr<tcu::TestCaseGroup> viewTypeMainGroup(new tcu::TestCaseGroup(testCtx, getShortImageViewTypeName(imageParamGroups[imageParamGroupNdx].viewType).c_str(), ""));
1875
1876                 for (int imageParamNdx = 0; imageParamNdx < 2; imageParamNdx++)
1877                 {
1878                         std::ostringstream viewTypeGroupName;
1879                         viewTypeGroupName << imageParamGroups[imageParamGroupNdx].imageParams[imageParamNdx].size.width << "_" << imageParamGroups[imageParamGroupNdx].imageParams[imageParamNdx].size.height << "_";
1880                         if (imageParamGroups[imageParamGroupNdx].imageParams[imageParamNdx].viewType == VK_IMAGE_VIEW_TYPE_3D)
1881                                 viewTypeGroupName << imageParamGroups[imageParamGroupNdx].imageParams[imageParamNdx].size.depth;
1882                         else
1883                                 viewTypeGroupName << imageParamGroups[imageParamGroupNdx].imageParams[imageParamNdx].numLayers;
1884                         MovePtr<tcu::TestCaseGroup> viewTypeGroup(new tcu::TestCaseGroup(testCtx, viewTypeGroupName.str().c_str(), ""));
1885
1886                         for (int testTypeNdx = 0; testTypeNdx < DE_LENGTH_OF_ARRAY(testTypes); ++testTypeNdx)
1887                         {
1888                                 TestParams params =
1889                                 {
1890                                         testTypes[testTypeNdx].test,
1891                                         imageParamGroups[imageParamGroupNdx].imageParams[imageParamNdx],
1892                                         false
1893                                 };
1894
1895                                 if (testTypes[testTypeNdx].test == TEST_TYPE_LAYERED_READBACK)
1896                                         addFunctionCaseWithPrograms(viewTypeGroup.get(), testTypes[testTypeNdx].name, testTypes[testTypeNdx].description, checkSupport, initPrograms, testLayeredReadBack, params);
1897                                 else if (testTypes[testTypeNdx].test == TEST_TYPE_SECONDARY_CMD_BUFFER)
1898                                 {
1899                                         addFunctionCaseWithPrograms(viewTypeGroup.get(), "secondary_cmd_buffer", testTypes[testTypeNdx].description, checkSupport, initPrograms, testSecondaryCmdBuffer, params);
1900                                         params.inheritFramebuffer = true;
1901                                         addFunctionCaseWithPrograms(viewTypeGroup.get(), "secondary_cmd_buffer_inherit_framebuffer", testTypes[testTypeNdx].description, checkSupport, initPrograms, testSecondaryCmdBuffer, params);
1902                                 }
1903                                 else
1904                                         addFunctionCaseWithPrograms(viewTypeGroup.get(), testTypes[testTypeNdx].name, testTypes[testTypeNdx].description, checkSupport, initPrograms, test, params);
1905                         }
1906                         viewTypeMainGroup->addChild(viewTypeGroup.release());
1907                 }
1908                 group->addChild(viewTypeMainGroup.release());
1909         }
1910
1911         return group.release();
1912 }
1913
1914 } // geometry
1915 } // vkt