182f9c0b97d57c3ebb63ca10b40617cee4e9894e
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / geometry / vktGeometryLayeredRenderingTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  * Copyright (c) 2014 The Android Open Source Project
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Geometry shader layered rendering tests
23  *//*--------------------------------------------------------------------*/
24
25 #include "vktGeometryLayeredRenderingTests.hpp"
26 #include "vktTestCase.hpp"
27 #include "vktTestCaseUtil.hpp"
28 #include "vktGeometryTestsUtil.hpp"
29
30 #include "vkPrograms.hpp"
31 #include "vkStrUtil.hpp"
32 #include "vkQueryUtil.hpp"
33 #include "vkMemUtil.hpp"
34 #include "vkRefUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkImageUtil.hpp"
37
38 #include "deStringUtil.hpp"
39 #include "deUniquePtr.hpp"
40
41 #include "tcuTextureUtil.hpp"
42 #include "tcuVectorUtil.hpp"
43
44 namespace vkt
45 {
46 namespace geometry
47 {
48 namespace
49 {
50 using namespace vk;
51 using de::MovePtr;
52 using de::UniquePtr;
53 using tcu::Vec4;
54 using tcu::IVec3;
55
56 enum TestType
57 {
58         TEST_TYPE_DEFAULT_LAYER,                                        // !< draw to default layer
59         TEST_TYPE_SINGLE_LAYER,                                         // !< draw to single layer
60         TEST_TYPE_ALL_LAYERS,                                           // !< draw all layers
61         TEST_TYPE_DIFFERENT_CONTENT,                            // !< draw different content to different layers
62         TEST_TYPE_LAYER_ID,                                                     // !< draw to all layers, verify gl_Layer fragment input
63         TEST_TYPE_INVOCATION_PER_LAYER,                         // !< draw to all layers, one invocation per layer
64         TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION,       // !< draw to all layers, multiple invocations write to multiple layers
65 };
66
67 struct ImageParams
68 {
69         VkImageViewType         viewType;
70         VkExtent3D                      size;
71         deUint32                        numLayers;
72 };
73
74 struct TestParams
75 {
76         TestType                        testType;
77         ImageParams                     image;
78 };
79
80 static const float s_colors[][4] =
81 {
82         { 1.0f, 1.0f, 1.0f, 1.0f },             // white
83         { 1.0f, 0.0f, 0.0f, 1.0f },             // red
84         { 0.0f, 1.0f, 0.0f, 1.0f },             // green
85         { 0.0f, 0.0f, 1.0f, 1.0f },             // blue
86         { 1.0f, 1.0f, 0.0f, 1.0f },             // yellow
87         { 1.0f, 0.0f, 1.0f, 1.0f },             // magenta
88 };
89
90 deUint32 getTargetLayer (const ImageParams& imageParams)
91 {
92         if (imageParams.viewType == VK_IMAGE_VIEW_TYPE_3D)
93                 return imageParams.size.depth / 2;
94         else
95                 return imageParams.numLayers / 2;
96 }
97
98 std::string getShortImageViewTypeName (const VkImageViewType imageViewType)
99 {
100         std::string s(getImageViewTypeName(imageViewType));
101         return de::toLower(s.substr(19));
102 }
103
104 VkImageType getImageType (const VkImageViewType viewType)
105 {
106         switch (viewType)
107         {
108                 case VK_IMAGE_VIEW_TYPE_1D:
109                 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
110                         return VK_IMAGE_TYPE_1D;
111
112                 case VK_IMAGE_VIEW_TYPE_2D:
113                 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
114                 case VK_IMAGE_VIEW_TYPE_CUBE:
115                 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
116                         return VK_IMAGE_TYPE_2D;
117
118                 case VK_IMAGE_VIEW_TYPE_3D:
119                         return VK_IMAGE_TYPE_3D;
120
121                 default:
122                         DE_ASSERT(0);
123                         return VK_IMAGE_TYPE_LAST;
124         }
125 }
126
127 inline bool isCubeImageViewType (const VkImageViewType viewType)
128 {
129         return viewType == VK_IMAGE_VIEW_TYPE_CUBE || viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
130 }
131
132 VkImageCreateInfo makeImageCreateInfo (const VkImageCreateFlags flags, const VkImageType type, const VkFormat format, const VkExtent3D size, const deUint32 numLayers, const VkImageUsageFlags usage)
133 {
134         const VkImageCreateInfo imageParams =
135         {
136                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                    // VkStructureType                      sType;
137                 DE_NULL,                                                                                // const void*                          pNext;
138                 flags,                                                                                  // VkImageCreateFlags           flags;
139                 type,                                                                                   // VkImageType                          imageType;
140                 format,                                                                                 // VkFormat                                     format;
141                 size,                                                                                   // VkExtent3D                           extent;
142                 1u,                                                                                             // deUint32                                     mipLevels;
143                 numLayers,                                                                              // deUint32                                     arrayLayers;
144                 VK_SAMPLE_COUNT_1_BIT,                                                  // VkSampleCountFlagBits        samples;
145                 VK_IMAGE_TILING_OPTIMAL,                                                // VkImageTiling                        tiling;
146                 usage,                                                                                  // VkImageUsageFlags            usage;
147                 VK_SHARING_MODE_EXCLUSIVE,                                              // VkSharingMode                        sharingMode;
148                 0u,                                                                                             // deUint32                                     queueFamilyIndexCount;
149                 DE_NULL,                                                                                // const deUint32*                      pQueueFamilyIndices;
150                 VK_IMAGE_LAYOUT_UNDEFINED,                                              // VkImageLayout                        initialLayout;
151         };
152         return imageParams;
153 }
154
155 Move<VkRenderPass> makeRenderPass (const DeviceInterface&       vk,
156                                                                    const VkDevice                       device,
157                                                                    const VkFormat                       colorFormat)
158 {
159         const VkAttachmentDescription colorAttachmentDescription =
160         {
161                 (VkAttachmentDescriptionFlags)0,                                        // VkAttachmentDescriptionFlags         flags;
162                 colorFormat,                                                                            // VkFormat                                                     format;
163                 VK_SAMPLE_COUNT_1_BIT,                                                          // VkSampleCountFlagBits                        samples;
164                 VK_ATTACHMENT_LOAD_OP_CLEAR,                                            // VkAttachmentLoadOp                           loadOp;
165                 VK_ATTACHMENT_STORE_OP_STORE,                                           // VkAttachmentStoreOp                          storeOp;
166                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,                                        // VkAttachmentLoadOp                           stencilLoadOp;
167                 VK_ATTACHMENT_STORE_OP_DONT_CARE,                                       // VkAttachmentStoreOp                          stencilStoreOp;
168                 VK_IMAGE_LAYOUT_UNDEFINED,                                                      // VkImageLayout                                        initialLayout;
169                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                       // VkImageLayout                                        finalLayout;
170         };
171
172         const VkAttachmentReference colorAttachmentRef =
173         {
174                 0u,                                                                                                     // deUint32                     attachment;
175                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL                        // VkImageLayout        layout;
176         };
177
178         const VkSubpassDescription subpassDescription =
179         {
180                 (VkSubpassDescriptionFlags)0,                                           // VkSubpassDescriptionFlags            flags;
181                 VK_PIPELINE_BIND_POINT_GRAPHICS,                                        // VkPipelineBindPoint                          pipelineBindPoint;
182                 0u,                                                                                                     // deUint32                                                     inputAttachmentCount;
183                 DE_NULL,                                                                                        // const VkAttachmentReference*         pInputAttachments;
184                 1u,                                                                                                     // deUint32                                                     colorAttachmentCount;
185                 &colorAttachmentRef,                                                            // const VkAttachmentReference*         pColorAttachments;
186                 DE_NULL,                                                                                        // const VkAttachmentReference*         pResolveAttachments;
187                 DE_NULL,                                                                                        // const VkAttachmentReference*         pDepthStencilAttachment;
188                 0u,                                                                                                     // deUint32                                                     preserveAttachmentCount;
189                 DE_NULL                                                                                         // const deUint32*                                      pPreserveAttachments;
190         };
191
192         const VkRenderPassCreateInfo renderPassInfo =
193         {
194                 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,                      // VkStructureType                                      sType;
195                 DE_NULL,                                                                                        // const void*                                          pNext;
196                 (VkRenderPassCreateFlags)0,                                                     // VkRenderPassCreateFlags                      flags;
197                 1u,                                                                                                     // deUint32                                                     attachmentCount;
198                 &colorAttachmentDescription,                                            // const VkAttachmentDescription*       pAttachments;
199                 1u,                                                                                                     // deUint32                                                     subpassCount;
200                 &subpassDescription,                                                            // const VkSubpassDescription*          pSubpasses;
201                 0u,                                                                                                     // deUint32                                                     dependencyCount;
202                 DE_NULL                                                                                         // const VkSubpassDependency*           pDependencies;
203         };
204
205         return createRenderPass(vk, device, &renderPassInfo);
206 }
207
208 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&           vk,
209                                                                            const VkDevice                               device,
210                                                                            const VkPipelineLayout               pipelineLayout,
211                                                                            const VkRenderPass                   renderPass,
212                                                                            const VkShaderModule                 vertexModule,
213                                                                            const VkShaderModule                 geometryModule,
214                                                                            const VkShaderModule                 fragmentModule,
215                                                                            const VkExtent2D                             renderSize)
216 {
217         const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
218         {
219                 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,              // VkStructureType                             sType;
220                 DE_NULL,                                                                                                                // const void*                                 pNext;
221                 (VkPipelineVertexInputStateCreateFlags)0,                                               // VkPipelineVertexInputStateCreateFlags       flags;
222                 0u,                                                                                                                             // uint32_t                                    vertexBindingDescriptionCount;
223                 DE_NULL,                                                                                                                // const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
224                 0u,                                                                                                                             // uint32_t                                    vertexAttributeDescriptionCount;
225                 DE_NULL,                                                                                                                // const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
226         };
227
228         const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
229         {
230                 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,    // VkStructureType                             sType;
231                 DE_NULL,                                                                                                                // const void*                                 pNext;
232                 (VkPipelineInputAssemblyStateCreateFlags)0,                                             // VkPipelineInputAssemblyStateCreateFlags     flags;
233                 VK_PRIMITIVE_TOPOLOGY_POINT_LIST,                                                               // VkPrimitiveTopology                         topology;
234                 VK_FALSE,                                                                                                               // VkBool32                                    primitiveRestartEnable;
235         };
236
237         const VkViewport viewport = makeViewport(
238                 0.0f, 0.0f,
239                 static_cast<float>(renderSize.width), static_cast<float>(renderSize.height),
240                 0.0f, 1.0f);
241         const VkRect2D scissor =
242         {
243                 makeOffset2D(0, 0),
244                 makeExtent2D(renderSize.width, renderSize.height),
245         };
246
247         const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
248         {
249                 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,                  // VkStructureType                             sType;
250                 DE_NULL,                                                                                                                // const void*                                 pNext;
251                 (VkPipelineViewportStateCreateFlags)0,                                                  // VkPipelineViewportStateCreateFlags          flags;
252                 1u,                                                                                                                             // uint32_t                                    viewportCount;
253                 &viewport,                                                                                                              // const VkViewport*                           pViewports;
254                 1u,                                                                                                                             // uint32_t                                    scissorCount;
255                 &scissor,                                                                                                               // const VkRect2D*                             pScissors;
256         };
257
258         const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
259         {
260                 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,             // VkStructureType                          sType;
261                 DE_NULL,                                                                                                                // const void*                              pNext;
262                 (VkPipelineRasterizationStateCreateFlags)0,                                             // VkPipelineRasterizationStateCreateFlags  flags;
263                 VK_FALSE,                                                                                                               // VkBool32                                 depthClampEnable;
264                 VK_FALSE,                                                                                                               // VkBool32                                 rasterizerDiscardEnable;
265                 VK_POLYGON_MODE_FILL,                                                                                   // VkPolygonMode                                                        polygonMode;
266                 VK_CULL_MODE_NONE,                                                                                              // VkCullModeFlags                                                      cullMode;
267                 VK_FRONT_FACE_COUNTER_CLOCKWISE,                                                                // VkFrontFace                                                          frontFace;
268                 VK_FALSE,                                                                                                               // VkBool32                                                                     depthBiasEnable;
269                 0.0f,                                                                                                                   // float                                                                        depthBiasConstantFactor;
270                 0.0f,                                                                                                                   // float                                                                        depthBiasClamp;
271                 0.0f,                                                                                                                   // float                                                                        depthBiasSlopeFactor;
272                 1.0f,                                                                                                                   // float                                                                        lineWidth;
273         };
274
275         const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
276         {
277                 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,               // VkStructureType                                                      sType;
278                 DE_NULL,                                                                                                                // const void*                                                          pNext;
279                 (VkPipelineMultisampleStateCreateFlags)0,                                               // VkPipelineMultisampleStateCreateFlags        flags;
280                 VK_SAMPLE_COUNT_1_BIT,                                                                                  // VkSampleCountFlagBits                                        rasterizationSamples;
281                 VK_FALSE,                                                                                                               // VkBool32                                                                     sampleShadingEnable;
282                 0.0f,                                                                                                                   // float                                                                        minSampleShading;
283                 DE_NULL,                                                                                                                // const VkSampleMask*                                          pSampleMask;
284                 VK_FALSE,                                                                                                               // VkBool32                                                                     alphaToCoverageEnable;
285                 VK_FALSE                                                                                                                // VkBool32                                                                     alphaToOneEnable;
286         };
287
288         const VkStencilOpState stencilOpState = makeStencilOpState(
289                 VK_STENCIL_OP_KEEP,                             // stencil fail
290                 VK_STENCIL_OP_KEEP,                             // depth & stencil pass
291                 VK_STENCIL_OP_KEEP,                             // depth only fail
292                 VK_COMPARE_OP_ALWAYS,                   // compare op
293                 0u,                                                             // compare mask
294                 0u,                                                             // write mask
295                 0u);                                                    // reference
296
297         VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
298         {
299                 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,             // VkStructureType                                                      sType;
300                 DE_NULL,                                                                                                                // const void*                                                          pNext;
301                 (VkPipelineDepthStencilStateCreateFlags)0,                                              // VkPipelineDepthStencilStateCreateFlags       flags;
302                 VK_FALSE,                                                                                                               // VkBool32                                                                     depthTestEnable;
303                 VK_FALSE,                                                                                                               // VkBool32                                                                     depthWriteEnable;
304                 VK_COMPARE_OP_LESS,                                                                                             // VkCompareOp                                                          depthCompareOp;
305                 VK_FALSE,                                                                                                               // VkBool32                                                                     depthBoundsTestEnable;
306                 VK_FALSE,                                                                                                               // VkBool32                                                                     stencilTestEnable;
307                 stencilOpState,                                                                                                 // VkStencilOpState                                                     front;
308                 stencilOpState,                                                                                                 // VkStencilOpState                                                     back;
309                 0.0f,                                                                                                                   // float                                                                        minDepthBounds;
310                 1.0f,                                                                                                                   // float                                                                        maxDepthBounds;
311         };
312
313         const VkColorComponentFlags                                     colorComponentsAll                                      = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
314         const VkPipelineColorBlendAttachmentState       pipelineColorBlendAttachmentState       =
315         {
316                 VK_FALSE,                                               // VkBool32                                     blendEnable;
317                 VK_BLEND_FACTOR_ONE,                    // VkBlendFactor                        srcColorBlendFactor;
318                 VK_BLEND_FACTOR_ZERO,                   // VkBlendFactor                        dstColorBlendFactor;
319                 VK_BLEND_OP_ADD,                                // VkBlendOp                            colorBlendOp;
320                 VK_BLEND_FACTOR_ONE,                    // VkBlendFactor                        srcAlphaBlendFactor;
321                 VK_BLEND_FACTOR_ZERO,                   // VkBlendFactor                        dstAlphaBlendFactor;
322                 VK_BLEND_OP_ADD,                                // VkBlendOp                            alphaBlendOp;
323                 colorComponentsAll,                             // VkColorComponentFlags        colorWriteMask;
324         };
325
326         const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
327         {
328                 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,               // VkStructureType                                                              sType;
329                 DE_NULL,                                                                                                                // const void*                                                                  pNext;
330                 (VkPipelineColorBlendStateCreateFlags)0,                                                // VkPipelineColorBlendStateCreateFlags                 flags;
331                 VK_FALSE,                                                                                                               // VkBool32                                                                             logicOpEnable;
332                 VK_LOGIC_OP_COPY,                                                                                               // VkLogicOp                                                                    logicOp;
333                 1u,                                                                                                                             // deUint32                                                                             attachmentCount;
334                 &pipelineColorBlendAttachmentState,                                                             // const VkPipelineColorBlendAttachmentState*   pAttachments;
335                 { 0.0f, 0.0f, 0.0f, 0.0f },                                                                             // float                                                                                blendConstants[4];
336         };
337
338         const VkPipelineShaderStageCreateInfo pShaderStages[] =
339         {
340                 {
341                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,            // VkStructureType                                              sType;
342                         DE_NULL,                                                                                                        // const void*                                                  pNext;
343                         (VkPipelineShaderStageCreateFlags)0,                                            // VkPipelineShaderStageCreateFlags             flags;
344                         VK_SHADER_STAGE_VERTEX_BIT,                                                                     // VkShaderStageFlagBits                                stage;
345                         vertexModule,                                                                                           // VkShaderModule                                               module;
346                         "main",                                                                                                         // const char*                                                  pName;
347                         DE_NULL,                                                                                                        // const VkSpecializationInfo*                  pSpecializationInfo;
348                 },
349                 {
350                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,            // VkStructureType                                              sType;
351                         DE_NULL,                                                                                                        // const void*                                                  pNext;
352                         (VkPipelineShaderStageCreateFlags)0,                                            // VkPipelineShaderStageCreateFlags             flags;
353                         VK_SHADER_STAGE_GEOMETRY_BIT,                                                           // VkShaderStageFlagBits                                stage;
354                         geometryModule,                                                                                         // VkShaderModule                                               module;
355                         "main",                                                                                                         // const char*                                                  pName;
356                         DE_NULL,                                                                                                        // const VkSpecializationInfo*                  pSpecializationInfo;
357                 },
358                 {
359                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,            // VkStructureType                                              sType;
360                         DE_NULL,                                                                                                        // const void*                                                  pNext;
361                         (VkPipelineShaderStageCreateFlags)0,                                            // VkPipelineShaderStageCreateFlags             flags;
362                         VK_SHADER_STAGE_FRAGMENT_BIT,                                                           // VkShaderStageFlagBits                                stage;
363                         fragmentModule,                                                                                         // VkShaderModule                                               module;
364                         "main",                                                                                                         // const char*                                                  pName;
365                         DE_NULL,                                                                                                        // const VkSpecializationInfo*                  pSpecializationInfo;
366                 },
367         };
368
369         const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
370         {
371                 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,        // VkStructureType                                                                      sType;
372                 DE_NULL,                                                                                        // const void*                                                                          pNext;
373                 (VkPipelineCreateFlags)0,                                                       // VkPipelineCreateFlags                                                        flags;
374                 DE_LENGTH_OF_ARRAY(pShaderStages),                                      // deUint32                                                                                     stageCount;
375                 pShaderStages,                                                                          // const VkPipelineShaderStageCreateInfo*                       pStages;
376                 &vertexInputStateInfo,                                                          // const VkPipelineVertexInputStateCreateInfo*          pVertexInputState;
377                 &pipelineInputAssemblyStateInfo,                                        // const VkPipelineInputAssemblyStateCreateInfo*        pInputAssemblyState;
378                 DE_NULL,                                                                                        // const VkPipelineTessellationStateCreateInfo*         pTessellationState;
379                 &pipelineViewportStateInfo,                                                     // const VkPipelineViewportStateCreateInfo*                     pViewportState;
380                 &pipelineRasterizationStateInfo,                                        // const VkPipelineRasterizationStateCreateInfo*        pRasterizationState;
381                 &pipelineMultisampleStateInfo,                                          // const VkPipelineMultisampleStateCreateInfo*          pMultisampleState;
382                 &pipelineDepthStencilStateInfo,                                         // const VkPipelineDepthStencilStateCreateInfo*         pDepthStencilState;
383                 &pipelineColorBlendStateInfo,                                           // const VkPipelineColorBlendStateCreateInfo*           pColorBlendState;
384                 DE_NULL,                                                                                        // const VkPipelineDynamicStateCreateInfo*                      pDynamicState;
385                 pipelineLayout,                                                                         // VkPipelineLayout                                                                     layout;
386                 renderPass,                                                                                     // VkRenderPass                                                                         renderPass;
387                 0u,                                                                                                     // deUint32                                                                                     subpass;
388                 DE_NULL,                                                                                        // VkPipeline                                                                           basePipelineHandle;
389                 0,                                                                                                      // deInt32                                                                                      basePipelineIndex;
390         };
391
392         return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
393 }
394
395 //! Convenience wrapper to access 1D, 2D, and 3D image layers/slices in a uniform way.
396 class LayeredImageAccess
397 {
398 public:
399         static LayeredImageAccess create (const VkImageType type, const VkFormat format, const VkExtent3D size, const deUint32 numLayers, const void* pData)
400         {
401                 if (type == VK_IMAGE_TYPE_1D)
402                         return LayeredImageAccess(format, size.width, numLayers, pData);
403                 else
404                         return LayeredImageAccess(type, format, size, numLayers, pData);
405         }
406
407         inline tcu::ConstPixelBufferAccess getLayer (const int layer) const
408         {
409                 return tcu::getSubregion(m_wholeImage, 0, (m_1dModifier * layer), ((~m_1dModifier & 1) * layer), m_width, m_height, 1);
410         }
411
412         inline int getNumLayersOrSlices (void) const
413         {
414                 return m_layers;
415         }
416
417 private:
418         // Specialized for 1D images.
419         LayeredImageAccess (const VkFormat format, const deUint32 width, const deUint32 numLayers, const void* pData)
420                 : m_width               (static_cast<int>(width))
421                 , m_height              (1)
422                 , m_1dModifier  (1)
423                 , m_layers              (numLayers)
424                 , m_wholeImage  (tcu::ConstPixelBufferAccess(mapVkFormat(format), m_width, m_layers, 1, pData))
425         {
426         }
427
428         LayeredImageAccess (const VkImageType type, const VkFormat format, const VkExtent3D size, const deUint32 numLayers, const void* pData)
429                 : m_width               (static_cast<int>(size.width))
430                 , m_height              (static_cast<int>(size.height))
431                 , m_1dModifier  (0)
432                 , m_layers              (static_cast<int>(type == VK_IMAGE_TYPE_3D ? size.depth : numLayers))
433                 , m_wholeImage  (tcu::ConstPixelBufferAccess(mapVkFormat(format), m_width, m_height, m_layers, pData))
434         {
435         }
436
437         const int                                                       m_width;
438         const int                                                       m_height;
439         const int                                                       m_1dModifier;
440         const int                                                       m_layers;
441         const tcu::ConstPixelBufferAccess       m_wholeImage;
442 };
443
444 inline bool compareColors (const Vec4& colorA, const Vec4& colorB, const Vec4& threshold)
445 {
446         return tcu::allEqual(
447                                 tcu::lessThan(tcu::abs(colorA - colorB), threshold),
448                                 tcu::BVec4(true, true, true, true));
449 }
450
451 bool verifyImageSingleColoredRow (tcu::TestLog& log, const tcu::ConstPixelBufferAccess image, const float rowWidthRatio, const tcu::Vec4& barColor)
452 {
453         DE_ASSERT(rowWidthRatio > 0.0f);
454
455         const Vec4                              black                           (0.0f, 0.0f, 0.0f, 1.0f);
456         const Vec4                              green                           (0.0f, 1.0f, 0.0f, 1.0f);
457         const Vec4                              red                                     (1.0f, 0.0f, 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
467                 << "Expecting all pixels with distance less or equal to (about) " << barLength
468                 << " pixels from left border to be of color " << barColor.swizzle(0, 1, 2) << "."
469                 << tcu::TestLog::EndMessage;
470
471         bool allPixelsOk = true;
472
473         for (int y = 0; y < image.getHeight(); ++y)
474         for (int x = 0; x < image.getWidth();  ++x)
475         {
476                 const Vec4      color           = image.getPixel(x, y);
477                 const bool      isBlack         = compareColors(color, black, threshold);
478                 const bool      isColor         = compareColors(color, barColor, threshold);
479
480                 bool isOk;
481
482                 if (x <= barLength - barLengthThreshold)
483                         isOk = isColor;
484                 else if (x >= barLength + barLengthThreshold)
485                         isOk = isBlack;
486                 else
487                         isOk = isColor || isBlack;
488
489                 allPixelsOk &= isOk;
490
491                 if (!isOk)
492                         errorMaskAccess.setPixel(red, x, y);
493         }
494
495         if (allPixelsOk)
496         {
497                 log << tcu::TestLog::Message << "Image is valid." << tcu::TestLog::EndMessage
498                         << tcu::TestLog::ImageSet("LayerContent", "Layer content")
499                         << tcu::TestLog::Image("Layer", "Layer", image)
500                         << tcu::TestLog::EndImageSet;
501                 return true;
502         }
503         else
504         {
505                 log << tcu::TestLog::Message << "Image verification failed. Got unexpected pixels." << tcu::TestLog::EndMessage
506                         << tcu::TestLog::ImageSet("LayerContent", "Layer content")
507                         << tcu::TestLog::Image("Layer",         "Layer",        image)
508                         << tcu::TestLog::Image("ErrorMask",     "Errors",       errorMask)
509                         << tcu::TestLog::EndImageSet;
510                 return false;
511         }
512
513         log << tcu::TestLog::Image("LayerContent", "Layer content", image);
514
515         return allPixelsOk;
516 }
517
518 bool verifyEmptyImage (tcu::TestLog& log, const tcu::ConstPixelBufferAccess image)
519 {
520         log << tcu::TestLog::Message << "Expecting empty image" << tcu::TestLog::EndMessage;
521
522         const Vec4      black           (0.0f, 0.0f, 0.0f, 1.0f);
523         const Vec4      threshold       (0.02f);
524
525         for (int y = 0; y < image.getHeight(); ++y)
526         for (int x = 0; x < image.getWidth();  ++x)
527         {
528                 const Vec4 color = image.getPixel(x, y);
529
530                 if (!compareColors(color, black, threshold))
531                 {
532                         log     << tcu::TestLog::Message
533                                 << "Found (at least) one bad pixel at " << x << "," << y << ". Pixel color is not background color."
534                                 << tcu::TestLog::EndMessage
535                                 << tcu::TestLog::ImageSet("LayerContent", "Layer content")
536                                 << tcu::TestLog::Image("Layer", "Layer", image)
537                                 << tcu::TestLog::EndImageSet;
538                         return false;
539                 }
540         }
541
542         log << tcu::TestLog::Message << "Image is valid" << tcu::TestLog::EndMessage;
543
544         return true;
545 }
546
547 bool verifyLayerContent (tcu::TestLog& log, const TestType testType, const tcu::ConstPixelBufferAccess image, const int layerNdx, const int numLayers)
548 {
549         const Vec4      white                           (1.0f, 1.0f, 1.0f, 1.0f);
550         const int       targetLayer                     = numLayers / 2;
551         const float     variableBarRatio        = static_cast<float>(layerNdx) / static_cast<float>(numLayers);
552
553         switch (testType)
554         {
555                 case TEST_TYPE_DEFAULT_LAYER:
556                         if (layerNdx == 0)
557                                 return verifyImageSingleColoredRow(log, image, 0.5f, white);
558                         else
559                                 return verifyEmptyImage(log, image);
560
561                 case TEST_TYPE_SINGLE_LAYER:
562                         if (layerNdx == targetLayer)
563                                 return verifyImageSingleColoredRow(log, image, 0.5f, white);
564                         else
565                                 return verifyEmptyImage(log, image);
566
567                 case TEST_TYPE_ALL_LAYERS:
568                 case TEST_TYPE_INVOCATION_PER_LAYER:
569                         return verifyImageSingleColoredRow(log, image, 0.5f, s_colors[layerNdx % DE_LENGTH_OF_ARRAY(s_colors)]);
570
571                 case TEST_TYPE_DIFFERENT_CONTENT:
572                 case TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION:
573                         if (layerNdx == 0)
574                                 return verifyEmptyImage(log, image);
575                         else
576                                 return verifyImageSingleColoredRow(log, image, variableBarRatio, white);
577
578                 case TEST_TYPE_LAYER_ID:
579                 {
580                         // This code must be in sync with the fragment shader.
581                         const tcu::Vec4 layerColor( (layerNdx    % 2) == 1 ? 1.0f : 0.5f,
582                                                                            ((layerNdx/2) % 2) == 1 ? 1.0f : 0.5f,
583                                                                              layerNdx         == 0 ? 1.0f : 0.0f,
584                                                                                                                                  1.0f);
585                         return verifyImageSingleColoredRow(log, image, 0.5f, layerColor);
586                 }
587
588                 default:
589                         DE_ASSERT(0);
590                         return false;
591         };
592 }
593
594 std::string getLayerDescription (const VkImageViewType viewType, const int layer)
595 {
596         std::ostringstream str;
597         const int numCubeFaces = 6;
598
599         if (isCubeImageViewType(viewType))
600                 str << "cube " << (layer / numCubeFaces) << ", face " << (layer % numCubeFaces);
601         else if (viewType == VK_IMAGE_VIEW_TYPE_3D)
602                 str << "slice z = " << layer;
603         else
604                 str << "layer " << layer;
605
606         return str.str();
607 }
608
609 bool verifyResults (tcu::TestLog& log, const TestParams& params, const VkFormat colorFormat, const void* resultData)
610 {
611         const LayeredImageAccess image = LayeredImageAccess::create(getImageType(params.image.viewType), colorFormat, params.image.size, params.image.numLayers, resultData);
612
613         int numGoodLayers = 0;
614
615         for (int layerNdx = 0; layerNdx < image.getNumLayersOrSlices(); ++layerNdx)
616         {
617                 const tcu::ConstPixelBufferAccess layerImage = image.getLayer(layerNdx);
618
619                 log << tcu::TestLog::Message << "Verifying " << getLayerDescription(params.image.viewType, layerNdx) << tcu::TestLog::EndMessage;
620
621                 if (verifyLayerContent(log, params.testType, layerImage, layerNdx, image.getNumLayersOrSlices()))
622                         ++numGoodLayers;
623         }
624
625         return numGoodLayers == image.getNumLayersOrSlices();
626 }
627
628 std::string toGlsl (const Vec4& v)
629 {
630         std::ostringstream str;
631         str << "vec4(";
632         for (int i = 0; i < 4; ++i)
633                 str << (i != 0 ? ", " : "") << de::floatToString(v[i], 1);
634         str << ")";
635         return str.str();
636 }
637
638 void initPrograms (SourceCollections& programCollection, const TestParams params)
639 {
640         const bool geomOutputColor = (params.testType == TEST_TYPE_ALL_LAYERS || params.testType == TEST_TYPE_INVOCATION_PER_LAYER);
641
642         // Vertex shader
643         {
644                 std::ostringstream src;
645                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
646                         << "\n"
647                         << "void main(void)\n"
648                         << "{\n"
649                         << "}\n";
650
651                 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
652         }
653
654         // Geometry shader
655         {
656                 const int numLayers             = static_cast<int>(params.image.viewType == VK_IMAGE_VIEW_TYPE_3D ? params.image.size.depth : params.image.numLayers);
657
658                 const int maxVertices   = (params.testType == TEST_TYPE_DIFFERENT_CONTENT)                                                                              ? (numLayers + 1) * numLayers :
659                                                                   (params.testType == TEST_TYPE_ALL_LAYERS || params.testType == TEST_TYPE_LAYER_ID)    ? numLayers * 4 :
660                                                                   (params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION)                                                 ? 6 : 4;
661
662                 std::ostringstream src;
663                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
664                         << "\n";
665
666                 if (params.testType == TEST_TYPE_INVOCATION_PER_LAYER || params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION)
667                         src << "layout(points, invocations = " << numLayers << ") in;\n";
668                 else
669                         src << "layout(points) in;\n";
670
671                 src << "layout(triangle_strip, max_vertices = " << maxVertices << ") out;\n"
672                         << "\n"
673                         << (geomOutputColor ? "layout(location = 0) out vec4 vert_color;\n\n" : "")
674                         << "out gl_PerVertex {\n"
675                         << "    vec4 gl_Position;\n"
676                         << "};\n"
677                         << "\n"
678                         << "void main(void)\n"
679                         << "{\n";
680
681                 std::ostringstream colorTable;
682                 {
683                         const int numColors = DE_LENGTH_OF_ARRAY(s_colors);
684
685                         colorTable << "    const vec4 colors[" << numColors << "] = vec4[" << numColors << "](";
686
687                         const std::string padding(colorTable.str().length(), ' ');
688
689                         for (int i = 0; i < numColors; ++i)
690                                 colorTable << (i != 0 ? ",\n" + padding : "") << toGlsl(s_colors[i]);
691
692                         colorTable << ");\n";
693                 }
694
695                 if (params.testType == TEST_TYPE_DEFAULT_LAYER)
696                 {
697                         src << "    gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
698                                 << "    EmitVertex();\n"
699                                 << "\n"
700                                 << "    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
701                                 << "    EmitVertex();\n"
702                                 << "\n"
703                                 << "    gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
704                                 << "    EmitVertex();\n"
705                                 << "\n"
706                                 << "    gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
707                                 << "    EmitVertex();\n";
708                 }
709                 else if (params.testType == TEST_TYPE_SINGLE_LAYER)
710                 {
711                         const deUint32 targetLayer = getTargetLayer(params.image);
712
713                         src << "    gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
714                                 << "    gl_Layer    = " << targetLayer << ";\n"
715                                 << "    EmitVertex();\n"
716                                 << "\n"
717                                 << "    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
718                                 << "    gl_Layer    = " << targetLayer << ";\n"
719                                 << "    EmitVertex();\n"
720                                 << "\n"
721                                 << "    gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
722                                 << "    gl_Layer    = " << targetLayer << ";\n"
723                                 << "    EmitVertex();\n"
724                                 << "\n"
725                                 << "    gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
726                                 << "    gl_Layer    = " << targetLayer << ";\n"
727                                 << "    EmitVertex();\n";
728                 }
729                 else if (params.testType == TEST_TYPE_ALL_LAYERS)
730                 {
731                         src << colorTable.str()
732                                 << "\n"
733                                 << "    for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
734                                 << "        const int colorNdx = layerNdx % " << DE_LENGTH_OF_ARRAY(s_colors) << ";\n"
735                                 << "\n"
736                                 << "        gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
737                                 << "        gl_Layer    = layerNdx;\n"
738                                 << "        vert_color  = colors[colorNdx];\n"
739                                 << "        EmitVertex();\n"
740                                 << "\n"
741                                 << "        gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
742                                 << "        gl_Layer    = layerNdx;\n"
743                                 << "        vert_color  = colors[colorNdx];\n"
744                                 << "        EmitVertex();\n"
745                                 << "\n"
746                                 << "        gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
747                                 << "        gl_Layer    = layerNdx;\n"
748                                 << "        vert_color  = colors[colorNdx];\n"
749                                 << "        EmitVertex();\n"
750                                 << "\n"
751                                 << "        gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
752                                 << "        gl_Layer    = layerNdx;\n"
753                                 << "        vert_color  = colors[colorNdx];\n"
754                                 << "        EmitVertex();\n"
755                                 << "        EndPrimitive();\n"
756                                 << "    };\n";
757                 }
758                 else if (params.testType == TEST_TYPE_LAYER_ID)
759                 {
760                         src << "    for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
761                                 << "        gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
762                                 << "        gl_Layer    = layerNdx;\n"
763                                 << "        EmitVertex();\n"
764                                 << "\n"
765                                 << "        gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
766                                 << "        gl_Layer    = layerNdx;\n"
767                                 << "        EmitVertex();\n"
768                                 << "\n"
769                                 << "        gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
770                                 << "        gl_Layer    = layerNdx;\n"
771                                 << "        EmitVertex();\n"
772                                 << "\n"
773                                 << "        gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
774                                 << "        gl_Layer    = layerNdx;\n"
775                                 << "        EmitVertex();\n"
776                                 << "        EndPrimitive();\n"
777                                 << "    };\n";
778                 }
779                 else if (params.testType == TEST_TYPE_DIFFERENT_CONTENT)
780                 {
781                         src << "    for (int layerNdx = 0; layerNdx < " << numLayers << "; ++layerNdx) {\n"
782                                 << "        for (int colNdx = 0; colNdx <= layerNdx; ++colNdx) {\n"
783                                 << "            const float posX = float(colNdx) / float(" << numLayers << ") * 2.0 - 1.0;\n"
784                                 << "\n"
785                                 << "            gl_Position = vec4(posX,  1.0, 0.0, 1.0);\n"
786                                 << "            gl_Layer    = layerNdx;\n"
787                                 << "            EmitVertex();\n"
788                                 << "\n"
789                                 << "            gl_Position = vec4(posX, -1.0, 0.0, 1.0);\n"
790                                 << "            gl_Layer    = layerNdx;\n"
791                                 << "            EmitVertex();\n"
792                                 << "        }\n"
793                                 << "        EndPrimitive();\n"
794                                 << "    }\n";
795                 }
796                 else if (params.testType == TEST_TYPE_INVOCATION_PER_LAYER)
797                 {
798                         src << colorTable.str()
799                                 << "    const int colorNdx = gl_InvocationID % " << DE_LENGTH_OF_ARRAY(s_colors) << ";\n"
800                                 << "\n"
801                                 << "    gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
802                                 << "    gl_Layer    = gl_InvocationID;\n"
803                                 << "    vert_color  = colors[colorNdx];\n"
804                                 << "    EmitVertex();\n"
805                                 << "\n"
806                                 << "    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
807                                 << "    gl_Layer    = gl_InvocationID;\n"
808                                 << "    vert_color  = colors[colorNdx];\n"
809                                 << "    EmitVertex();\n"
810                                 << "\n"
811                                 << "    gl_Position = vec4( 0.0, -1.0, 0.0, 1.0);\n"
812                                 << "    gl_Layer    = gl_InvocationID;\n"
813                                 << "    vert_color  = colors[colorNdx];\n"
814                                 << "    EmitVertex();\n"
815                                 << "\n"
816                                 << "    gl_Position = vec4( 0.0,  1.0, 0.0, 1.0);\n"
817                                 << "    gl_Layer    = gl_InvocationID;\n"
818                                 << "    vert_color  = colors[colorNdx];\n"
819                                 << "    EmitVertex();\n"
820                                 << "    EndPrimitive();\n";
821                 }
822                 else if (params.testType == TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION)
823                 {
824                         src << "    const int   layerA = gl_InvocationID;\n"
825                                 << "    const int   layerB = (gl_InvocationID + 1) % " << numLayers << ";\n"
826                                 << "    const float aEnd   = float(layerA) / float(" << numLayers << ") * 2.0 - 1.0;\n"
827                                 << "    const float bEnd   = float(layerB) / float(" << numLayers << ") * 2.0 - 1.0;\n"
828                                 << "\n"
829                                 << "    gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
830                                 << "    gl_Layer    = layerA;\n"
831                                 << "    EmitVertex();\n"
832                                 << "\n"
833                                 << "    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
834                                 << "    gl_Layer    = layerA;\n"
835                                 << "    EmitVertex();\n"
836                                 << "\n"
837                                 << "    gl_Position = vec4(aEnd, -1.0, 0.0, 1.0);\n"
838                                 << "    gl_Layer    = layerA;\n"
839                                 << "    EmitVertex();\n"
840                                 << "    EndPrimitive();\n"
841                                 << "\n"
842                                 << "    gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
843                                 << "    gl_Layer    = layerB;\n"
844                                 << "    EmitVertex();\n"
845                                 << "\n"
846                                 << "    gl_Position = vec4(bEnd,  1.0, 0.0, 1.0);\n"
847                                 << "    gl_Layer    = layerB;\n"
848                                 << "    EmitVertex();\n"
849                                 << "\n"
850                                 << "    gl_Position = vec4(bEnd, -1.0, 0.0, 1.0);\n"
851                                 << "    gl_Layer    = layerB;\n"
852                                 << "    EmitVertex();\n"
853                                 << "    EndPrimitive();\n";
854                 }
855                 else
856                         DE_ASSERT(0);
857
858                 src <<  "}\n";  // end main
859
860                 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
861         }
862
863         // Fragment shader
864         {
865                 std::ostringstream src;
866                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
867                         << "\n"
868                         << "layout(location = 0) out vec4 o_color;\n"
869                         << (geomOutputColor ? "layout(location = 0) in  vec4 vert_color;\n" : "")
870                         << "\n"
871                         << "void main(void)\n"
872                         << "{\n";
873
874                 if (params.testType == TEST_TYPE_LAYER_ID)
875                 {
876                         // This code must be in sync with verifyLayerContent()
877                         src << "    o_color = vec4( (gl_Layer    % 2) == 1 ? 1.0 : 0.5,\n"
878                                 << "                   ((gl_Layer/2) % 2) == 1 ? 1.0 : 0.5,\n"
879                                 << "                     gl_Layer         == 0 ? 1.0 : 0.0,\n"
880                                 << "                                             1.0);\n";
881                 }
882                 else if (geomOutputColor)
883                         src << "    o_color = vert_color;\n";
884                 else
885                         src << "    o_color = vec4(1.0);\n";
886
887                 src << "}\n";
888
889                 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
890         }
891 }
892
893 tcu::TestStatus test (Context& context, const TestParams params)
894 {
895         if (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType &&
896                 (!de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), "VK_KHR_maintenance1")))
897                 TCU_THROW(NotSupportedError, "Extension VK_KHR_maintenance1 not supported");
898
899         const DeviceInterface&                  vk                                              = context.getDeviceInterface();
900         const InstanceInterface&                vki                                             = context.getInstanceInterface();
901         const VkDevice                                  device                                  = context.getDevice();
902         const VkPhysicalDevice                  physDevice                              = context.getPhysicalDevice();
903         const deUint32                                  queueFamilyIndex                = context.getUniversalQueueFamilyIndex();
904         const VkQueue                                   queue                                   = context.getUniversalQueue();
905         Allocator&                                              allocator                               = context.getDefaultAllocator();
906
907         checkGeometryShaderSupport(vki, physDevice);
908
909         const VkFormat                                  colorFormat                             = VK_FORMAT_R8G8B8A8_UNORM;
910         const deUint32                                  numLayers                               = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? params.image.size.depth : params.image.numLayers);
911         const Vec4                                              clearColor                              = Vec4(0.0f, 0.0f, 0.0f, 1.0f);
912         const VkDeviceSize                              colorBufferSize                 = params.image.size.width * params.image.size.height * params.image.size.depth * params.image.numLayers * tcu::getPixelSize(mapVkFormat(colorFormat));
913         const VkImageCreateFlags                imageCreateFlags                = (isCubeImageViewType(params.image.viewType) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (VkImageCreateFlagBits)0) |
914                                                                                                                           (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR : (VkImageCreateFlagBits)0);
915         const VkImageViewType                   viewType                                = (VK_IMAGE_VIEW_TYPE_3D == params.image.viewType ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : params.image.viewType);
916
917         const Unique<VkImage>                   colorImage                              (makeImage                              (vk, device, makeImageCreateInfo(imageCreateFlags, getImageType(params.image.viewType), colorFormat, params.image.size,
918                                                                                                                                                                          params.image.numLayers, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
919         const UniquePtr<Allocation>             colorImageAlloc                 (bindImage                              (vk, device, allocator, *colorImage, MemoryRequirement::Any));
920         const Unique<VkImageView>               colorAttachment                 (makeImageView                  (vk, device, *colorImage, viewType, colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers)));
921
922         const Unique<VkBuffer>                  colorBuffer                             (makeBuffer                             (vk, device, makeBufferCreateInfo(colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT)));
923         const UniquePtr<Allocation>             colorBufferAlloc                (bindBuffer                             (vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
924
925         const Unique<VkShaderModule>    vertexModule                    (createShaderModule             (vk, device, context.getBinaryCollection().get("vert"), 0u));
926         const Unique<VkShaderModule>    geometryModule                  (createShaderModule             (vk, device, context.getBinaryCollection().get("geom"), 0u));
927         const Unique<VkShaderModule>    fragmentModule                  (createShaderModule             (vk, device, context.getBinaryCollection().get("frag"), 0u));
928
929         const Unique<VkRenderPass>              renderPass                              (makeRenderPass                 (vk, device, colorFormat));
930         const Unique<VkFramebuffer>             framebuffer                             (makeFramebuffer                (vk, device, *renderPass, *colorAttachment, params.image.size.width,  params.image.size.height, numLayers));
931         const Unique<VkPipelineLayout>  pipelineLayout                  (makePipelineLayout             (vk, device));
932         const Unique<VkPipeline>                pipeline                                (makeGraphicsPipeline   (vk, device, *pipelineLayout, *renderPass, *vertexModule, *geometryModule, *fragmentModule,
933                                                                                                                                                                          makeExtent2D(params.image.size.width, params.image.size.height)));
934         const Unique<VkCommandPool>             cmdPool                                 (makeCommandPool                (vk, device, queueFamilyIndex));
935         const Unique<VkCommandBuffer>   cmdBuffer                               (makeCommandBuffer              (vk, device, *cmdPool));
936
937         zeroBuffer(vk, device, *colorBufferAlloc, colorBufferSize);
938
939         beginCommandBuffer(vk, *cmdBuffer);
940
941         const VkClearValue                      clearValue      = makeClearValueColor(clearColor);
942         const VkRect2D                          renderArea      =
943         {
944                 makeOffset2D(0, 0),
945                 makeExtent2D(params.image.size.width, params.image.size.height),
946         };
947         const VkRenderPassBeginInfo renderPassBeginInfo =
948         {
949                 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,               // VkStructureType         sType;
950                 DE_NULL,                                                                                // const void*             pNext;
951                 *renderPass,                                                                    // VkRenderPass            renderPass;
952                 *framebuffer,                                                                   // VkFramebuffer           framebuffer;
953                 renderArea,                                                                             // VkRect2D                renderArea;
954                 1u,                                                                                             // uint32_t                clearValueCount;
955                 &clearValue,                                                                    // const VkClearValue*     pClearValues;
956         };
957         vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
958
959         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
960         vk.cmdDraw(*cmdBuffer, 1u, 1u, 0u, 0u);
961         vk.cmdEndRenderPass(*cmdBuffer);
962
963         // Prepare color image for copy
964         {
965                 const VkImageSubresourceRange   colorSubresourceRange   = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, params.image.numLayers);
966                 const VkImageMemoryBarrier              barriers[] =
967                 {
968                         {
969                                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                 // VkStructureType                      sType;
970                                 DE_NULL,                                                                                // const void*                          pNext;
971                                 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                   // VkAccessFlags                        outputMask;
972                                 VK_ACCESS_TRANSFER_READ_BIT,                                    // VkAccessFlags                        inputMask;
973                                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,               // VkImageLayout                        oldLayout;
974                                 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,                   // VkImageLayout                        newLayout;
975                                 VK_QUEUE_FAMILY_IGNORED,                                                // deUint32                                     srcQueueFamilyIndex;
976                                 VK_QUEUE_FAMILY_IGNORED,                                                // deUint32                                     destQueueFamilyIndex;
977                                 *colorImage,                                                                    // VkImage                                      image;
978                                 colorSubresourceRange,                                                  // VkImageSubresourceRange      subresourceRange;
979                         },
980                 };
981
982                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
983                         0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
984         }
985         // Color image -> host buffer
986         {
987                 const VkBufferImageCopy region =
988                 {
989                         0ull,                                                                                                                                                                           // VkDeviceSize                bufferOffset;
990                         0u,                                                                                                                                                                                     // uint32_t                    bufferRowLength;
991                         0u,                                                                                                                                                                                     // uint32_t                    bufferImageHeight;
992                         makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, params.image.numLayers),          // VkImageSubresourceLayers    imageSubresource;
993                         makeOffset3D(0, 0, 0),                                                                                                                                          // VkOffset3D                  imageOffset;
994                         params.image.size,                                                                                                                                                      // VkExtent3D                  imageExtent;
995                 };
996
997                 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, &region);
998         }
999         // Buffer write barrier
1000         {
1001                 const VkBufferMemoryBarrier barriers[] =
1002                 {
1003                         {
1004                                 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,                // VkStructureType    sType;
1005                                 DE_NULL,                                                                                // const void*        pNext;
1006                                 VK_ACCESS_TRANSFER_WRITE_BIT,                                   // VkAccessFlags      srcAccessMask;
1007                                 VK_ACCESS_HOST_READ_BIT,                                                // VkAccessFlags      dstAccessMask;
1008                                 VK_QUEUE_FAMILY_IGNORED,                                                // uint32_t           srcQueueFamilyIndex;
1009                                 VK_QUEUE_FAMILY_IGNORED,                                                // uint32_t           dstQueueFamilyIndex;
1010                                 *colorBuffer,                                                                   // VkBuffer           buffer;
1011                                 0ull,                                                                                   // VkDeviceSize       offset;
1012                                 VK_WHOLE_SIZE,                                                                  // VkDeviceSize       size;
1013                         },
1014                 };
1015
1016                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
1017                         0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers, DE_NULL, 0u);
1018         }
1019
1020         VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1021         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1022
1023         invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), colorBufferSize);
1024
1025         if (!verifyResults(context.getTestContext().getLog(), params, colorFormat, colorBufferAlloc->getHostPtr()))
1026                 return tcu::TestStatus::fail("Rendered images are incorrect");
1027         else
1028                 return tcu::TestStatus::pass("OK");
1029 }
1030
1031 } // anonymous
1032
1033 tcu::TestCaseGroup* createLayeredRenderingTests (tcu::TestContext& testCtx)
1034 {
1035         MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "layered", "Layered rendering tests."));
1036
1037         const struct
1038         {
1039                 TestType                test;
1040                 const char*             name;
1041                 const char*             description;
1042         } testTypes[] =
1043         {
1044                 { TEST_TYPE_DEFAULT_LAYER,                                      "render_to_default_layer",                      "Render to the default layer"                                                                                                                   },
1045                 { TEST_TYPE_SINGLE_LAYER,                                       "render_to_one",                                        "Render to one layer"                                                                                                                                   },
1046                 { TEST_TYPE_ALL_LAYERS,                                         "render_to_all",                                        "Render to all layers"                                                                                                                                  },
1047                 { TEST_TYPE_DIFFERENT_CONTENT,                          "render_different_content",                     "Render different data to different layers"                                                                                             },
1048                 { TEST_TYPE_LAYER_ID,                                           "fragment_layer",                                       "Read gl_Layer in fragment shader"                                                                                                              },
1049                 { TEST_TYPE_INVOCATION_PER_LAYER,                       "invocation_per_layer",                         "Render to multiple layers with multiple invocations, one invocation per layer"                 },
1050                 { TEST_TYPE_MULTIPLE_LAYERS_PER_INVOCATION,     "multiple_layers_per_invocation",       "Render to multiple layers with multiple invocations, multiple layers per invocation",  },
1051         };
1052
1053         const ImageParams imageParams[] =
1054         {
1055                 { VK_IMAGE_VIEW_TYPE_1D_ARRAY,          { 64,  1, 1 },  4       },
1056                 { VK_IMAGE_VIEW_TYPE_2D_ARRAY,          { 64, 64, 1 },  4       },
1057                 { VK_IMAGE_VIEW_TYPE_CUBE,                      { 64, 64, 1 },  6       },
1058                 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,        { 64, 64, 1 },  2*6     },
1059                 { VK_IMAGE_VIEW_TYPE_3D,                        { 64, 64, 8 },  1       }
1060         };
1061
1062         for (int imageParamNdx = 0; imageParamNdx < DE_LENGTH_OF_ARRAY(imageParams); ++imageParamNdx)
1063         {
1064                 MovePtr<tcu::TestCaseGroup> viewTypeGroup(new tcu::TestCaseGroup(testCtx, getShortImageViewTypeName(imageParams[imageParamNdx].viewType).c_str(), ""));
1065
1066                 for (int testTypeNdx = 0; testTypeNdx < DE_LENGTH_OF_ARRAY(testTypes); ++testTypeNdx)
1067                 {
1068                         const TestParams params =
1069                         {
1070                                 testTypes[testTypeNdx].test,
1071                                 imageParams[imageParamNdx],
1072                         };
1073                         addFunctionCaseWithPrograms(viewTypeGroup.get(), testTypes[testTypeNdx].name, testTypes[testTypeNdx].description, initPrograms, test, params);
1074                 }
1075
1076                 group->addChild(viewTypeGroup.release());
1077         }
1078
1079         return group.release();
1080 }
1081
1082 } // geometry
1083 } // vkt