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