Added test for color attachments with different sizes.
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / pipeline / vktPipelineFramebufferAttachmentTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2017 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file vktPipelineFramebuferAttachmentTests.cpp
21  * \brief Render to a framebuffer with attachments of different sizes and with
22  *        no attachments at all
23  *
24  *//*--------------------------------------------------------------------*/
25
26 #include "vktPipelineFramebufferAttachmentTests.hpp"
27 #include "vktPipelineMakeUtil.hpp"
28 #include "vktTestCase.hpp"
29 #include "vktTestCaseUtil.hpp"
30 #include "vktPipelineVertexUtil.hpp"
31 #include "vktTestGroupUtil.hpp"
32
33 #include "vkMemUtil.hpp"
34 #include "vkQueryUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkRefUtil.hpp"
37 #include "vkBuilderUtil.hpp"
38 #include "vkPrograms.hpp"
39 #include "vkImageUtil.hpp"
40
41 #include "tcuTextureUtil.hpp"
42 #include "tcuImageCompare.hpp"
43
44 #include "deUniquePtr.hpp"
45 #include "deSharedPtr.hpp"
46
47 #include <string>
48 #include <vector>
49
50 namespace vkt
51 {
52 namespace pipeline
53 {
54 namespace
55 {
56 using namespace vk;
57 using de::UniquePtr;
58 using de::MovePtr;
59 using de::SharedPtr;
60 using tcu::IVec3;
61 using tcu::Vec4;
62 using tcu::UVec4;
63 using tcu::IVec4;
64 using std::vector;
65
66 static const VkFormat COLOR_FORMAT      =               VK_FORMAT_R8G8B8A8_UNORM;
67
68 typedef SharedPtr<Unique<VkImageView> > SharedPtrVkImageView;
69 typedef SharedPtr<Unique<VkPipeline> >  SharedPtrVkPipeline;
70
71 struct CaseDef
72 {
73         VkImageViewType imageType;
74         IVec3                   renderSize;
75         IVec3                   attachmentSize;
76         deUint32                numLayers;
77         bool                    multisample;
78 };
79
80 template<typename T>
81 inline SharedPtr<Unique<T> > makeSharedPtr(Move<T> move)
82 {
83         return SharedPtr<Unique<T> >(new Unique<T>(move));
84 }
85
86 template<typename T>
87 inline VkDeviceSize sizeInBytes(const vector<T>& vec)
88 {
89         return vec.size() * sizeof(vec[0]);
90 }
91
92 VkImageType getImageType(const VkImageViewType viewType)
93 {
94         switch (viewType)
95         {
96                 case VK_IMAGE_VIEW_TYPE_1D:
97                 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
98                         return VK_IMAGE_TYPE_1D;
99
100                 case VK_IMAGE_VIEW_TYPE_2D:
101                 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
102                 case VK_IMAGE_VIEW_TYPE_CUBE:
103                 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
104                         return VK_IMAGE_TYPE_2D;
105
106                 case VK_IMAGE_VIEW_TYPE_3D:
107                         return VK_IMAGE_TYPE_3D;
108
109                 default:
110                         DE_ASSERT(0);
111                         return VK_IMAGE_TYPE_LAST;
112         }
113 }
114
115 //! Make a render pass with one subpass per color attachment and one attachment per image layer.
116 Move<VkRenderPass> makeRenderPass (const DeviceInterface& vk,
117                                                                    const VkDevice                 device,
118                                                                    const VkFormat                 colorFormat,
119                                                                    const deUint32                 numLayers,
120                                                                    const bool                     multisample)
121 {
122         vector<VkAttachmentDescription> attachmentDescriptions          (numLayers);
123         deUint32                                                attachmentIndex                         = 0;
124         vector<VkAttachmentReference>   colorAttachmentReferences       (numLayers);
125         vector<VkSubpassDescription>    subpasses;
126
127         for (deUint32 i = 0; i < numLayers; i++)
128         {
129                 VkAttachmentDescription colorAttachmentDescription =
130                 {
131                         (VkAttachmentDescriptionFlags)0,                                                                // VkAttachmentDescriptionFla   flags;
132                         colorFormat,                                                                                                    // VkFormat                                             format;
133                         !multisample ? VK_SAMPLE_COUNT_1_BIT : VK_SAMPLE_COUNT_4_BIT,   // VkSampleCountFlagBits                samples;
134                         VK_ATTACHMENT_LOAD_OP_LOAD,                                                                             // VkAttachmentLoadOp                   loadOp;
135                         VK_ATTACHMENT_STORE_OP_STORE,                                                                   // VkAttachmentStoreOp                  storeOp;
136                         VK_ATTACHMENT_LOAD_OP_DONT_CARE,                                                                // VkAttachmentLoadOp                   stencilLoadOp;
137                         VK_ATTACHMENT_STORE_OP_DONT_CARE,                                                               // VkAttachmentStoreOp                  stencilStoreOp;
138                         VK_IMAGE_LAYOUT_GENERAL,                                                                                // VkImageLayout                                initialLayout;
139                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                                               // VkImageLayout                                finalLayout;
140                 };
141                 attachmentDescriptions[attachmentIndex++] = colorAttachmentDescription;
142         }
143
144         // Create a subpass for each attachment (each attachment is a layer of an arrayed image).
145         for (deUint32 i = 0; i < numLayers; ++i)
146         {
147                 const VkAttachmentReference attachmentRef =
148                 {
149                         i,                                                                                      // deUint32                     attachment;
150                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL        // VkImageLayout        layout;
151                 };
152                 colorAttachmentReferences[i] = attachmentRef;
153
154                 const VkSubpassDescription subpassDescription =
155                 {
156                         (VkSubpassDescriptionFlags)0,           // VkSubpassDescriptionFlags            flags;
157                         VK_PIPELINE_BIND_POINT_GRAPHICS,        // VkPipelineBindPoint                          pipelineBindPoint;
158                         0u,                                                                     // deUint32                                                     inputAttachmentCount;
159                         DE_NULL,                                                        // const VkAttachmentReference*         pInputAttachments;
160                         1u,                                                                     // deUint32                                                     colorAttachmentCount;
161                         &colorAttachmentReferences[i],          // const VkAttachmentReference*         pColorAttachments;
162                         DE_NULL,                                                        // const VkAttachmentReference*         pResolveAttachments;
163                         DE_NULL,                                                        // const VkAttachmentReference*         pDepthStencilAttachment;
164                         0u,                                                                     // deUint32                                                     preserveAttachmentCount;
165                         DE_NULL                                                         // const deUint32*                                      pPreserveAttachments;
166                 };
167                 subpasses.push_back(subpassDescription);
168         }
169
170         const VkRenderPassCreateInfo renderPassInfo =
171         {
172                 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,      // VkStructureType                                      sType;
173                 DE_NULL,                                                                        // const void*                                          pNext;
174                 (VkRenderPassCreateFlags)0,                                     // VkRenderPassCreateFlags                      flags;
175                 numLayers,                                                                      // deUint32                                                     attachmentCount;
176                 &attachmentDescriptions[0],                                     // const VkAttachmentDescription*       pAttachments;
177                 static_cast<deUint32>(subpasses.size()),        // deUint32                                                     subpassCount;
178                 &subpasses[0],                                                          // const VkSubpassDescription*          pSubpasses;
179                 0u,                                                                                     // deUint32                                                     dependencyCount;
180                 DE_NULL                                                                         // const VkSubpassDependency*           pDependencies;
181         };
182
183         return createRenderPass(vk, device, &renderPassInfo);
184 }
185
186 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&           vk,
187                                                                            const VkDevice                               device,
188                                                                            const VkPipelineLayout               pipelineLayout,
189                                                                            const VkRenderPass                   renderPass,
190                                                                            const VkShaderModule                 vertexModule,
191                                                                            const VkShaderModule                 fragmentModule,
192                                                                            const IVec3                                  renderSize,
193                                                                            const VkPrimitiveTopology    topology,
194                                                                            const deUint32                               subpass,
195                                                                            const deUint32                               numAttachments,
196                                                                            const bool                                   multisample)
197 {
198         const VkVertexInputBindingDescription vertexInputBindingDescription =
199         {
200                 0u,                                                             // uint32_t                             binding;
201                 sizeof(tcu::Vec4),                              // uint32_t                             stride;
202                 VK_VERTEX_INPUT_RATE_VERTEX,    // VkVertexInputRate    inputRate;
203         };
204
205         const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
206         {
207                 {
208                         0u,                                                             // uint32_t             location;
209                         0u,                                                             // uint32_t             binding;
210                         VK_FORMAT_R32G32B32A32_SFLOAT,  // VkFormat             format;
211                         0u,                                                             // uint32_t             offset;
212                 },
213         };
214
215         const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
216         {
217                 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,      // VkStructureType                                                      sType;
218                 DE_NULL,                                                                                                        // const void*                                                          pNext;
219                 (VkPipelineVertexInputStateCreateFlags)0,                                       // VkPipelineVertexInputStateCreateFlags        flags;
220                 1u,                                                                                                                     // uint32_t                                                                     vertexBindingDescriptionCount;
221                 &vertexInputBindingDescription,                                                         // const VkVertexInputBindingDescription*       pVertexBindingDescriptions;
222                 DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions),           // uint32_t                                                                     vertexAttributeDescriptionCount;
223                 vertexInputAttributeDescriptions,                                                       // const VkVertexInputAttributeDescription*     pVertexAttributeDescriptions;
224         };
225
226         const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
227         {
228                 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,    // VkStructureType                                                      sType;
229                 DE_NULL,                                                                                                                // const void*                                                          pNext;
230                 (VkPipelineInputAssemblyStateCreateFlags)0,                                             // VkPipelineInputAssemblyStateCreateFlags      flags;
231                 topology,                                                                                                               // VkPrimitiveTopology                                          topology;
232                 VK_FALSE,                                                                                                               // VkBool32                                                                     primitiveRestartEnable;
233         };
234
235         const VkViewport viewport = makeViewport(
236                 0.0f, 0.0f,
237                 static_cast<float>(renderSize.x()), static_cast<float>(renderSize.y()),
238                 0.0f, 1.0f);
239
240         // We must set the scissor rect to the renderSize, since the renderArea specified
241         // during the begin render pass command does not ensure that rendering is strictly
242         // limited to the rect provided there and the spec clearly states that the scissor
243         // must be configured appropriately to ensure this
244         const VkRect2D scissor =
245         {
246                 makeOffset2D(0, 0),
247                 makeExtent2D(renderSize.x(), renderSize.y()),
248         };
249
250         const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
251         {
252                 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,  // VkStructureType                                              sType;
253                 DE_NULL,                                                                                                // const void*                                                  pNext;
254                 (VkPipelineViewportStateCreateFlags)0,                                  // VkPipelineViewportStateCreateFlags   flags;
255                 1u,                                                                                                             // uint32_t                                                             viewportCount;
256                 &viewport,                                                                                              // const VkViewport*                                    pViewports;
257                 1u,                                                                                                             // uint32_t                                                             scissorCount;
258                 &scissor,                                                                                               // const VkRect2D*                                              pScissors;
259         };
260
261         const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
262         {
263                 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,     // VkStructureType                                                      sType;
264                 DE_NULL,                                                                                                        // const void*                                                          pNext;
265                 (VkPipelineRasterizationStateCreateFlags)0,                                     // VkPipelineRasterizationStateCreateFlags      flags;
266                 VK_FALSE,                                                                                                       // VkBool32                                                                     depthClampEnable;
267                 VK_FALSE,                                                                                                       // VkBool32                                                                     rasterizerDiscardEnable;
268                 VK_POLYGON_MODE_FILL,                                                                           // VkPolygonMode                                                        polygonMode;
269                 VK_CULL_MODE_NONE,                                                                                      // VkCullModeFlags                                                      cullMode;
270                 VK_FRONT_FACE_COUNTER_CLOCKWISE,                                                        // VkFrontFace                                                          frontFace;
271                 VK_FALSE,                                                                                                       // VkBool32                                                                     depthBiasEnable;
272                 0.0f,                                                                                                           // float                                                                        depthBiasConstantFactor;
273                 0.0f,                                                                                                           // float                                                                        depthBiasClamp;
274                 0.0f,                                                                                                           // float                                                                        depthBiasSlopeFactor;
275                 1.0f,                                                                                                           // float                                                                        lineWidth;
276         };
277
278         const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
279         {
280                 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,               // VkStructureType                                                      sType;
281                 DE_NULL,                                                                                                                // const void*                                                          pNext;
282                 (VkPipelineMultisampleStateCreateFlags)0,                                               // VkPipelineMultisampleStateCreateFlags        flags;
283                 !multisample ? VK_SAMPLE_COUNT_1_BIT : VK_SAMPLE_COUNT_4_BIT,   // VkSampleCountFlagBits                                        rasterizationSamples;
284                 !multisample ? VK_FALSE : VK_TRUE,                                                              // VkBool32                                                                     sampleShadingEnable;
285                 1.0f,                                                                                                                   // float                                                                        minSampleShading;
286                 DE_NULL,                                                                                                                // const VkSampleMask*                                          pSampleMask;
287                 VK_FALSE,                                                                                                               // VkBool32                                                                     alphaToCoverageEnable;
288                 VK_FALSE                                                                                                                // VkBool32                                                                     alphaToOneEnable;
289         };
290
291         const VkStencilOpState stencilOpState = makeStencilOpState(
292                 VK_STENCIL_OP_KEEP,             // stencil fail
293                 VK_STENCIL_OP_KEEP,             // depth & stencil pass
294                 VK_STENCIL_OP_KEEP,             // depth only fail
295                 VK_COMPARE_OP_ALWAYS,   // compare op
296                 0u,                                             // compare mask
297                 0u,                                             // write mask
298                 0u);                                    // reference
299
300         const VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
301         {
302                 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,     // VkStructureType                                                      sType;
303                 DE_NULL,                                                                                                        // const void*                                                          pNext;
304                 (VkPipelineDepthStencilStateCreateFlags)0,                                      // VkPipelineDepthStencilStateCreateFlags       flags;
305                 VK_FALSE,                                                                                                       // VkBool32                                                                     depthTestEnable;
306                 VK_FALSE,                                                                                                       // VkBool32                                                                     depthWriteEnable;
307                 VK_COMPARE_OP_LESS,                                                                                     // VkCompareOp                                                          depthCompareOp;
308                 VK_FALSE,                                                                                                       // VkBool32                                                                     depthBoundsTestEnable;
309                 VK_FALSE,                                                                                                       // VkBool32                                                                     stencilTestEnable;
310                 stencilOpState,                                                                                         // VkStencilOpState                                                     front;
311                 stencilOpState,                                                                                         // VkStencilOpState                                                     back;
312                 0.0f,                                                                                                           // float                                                                        minDepthBounds;
313                 1.0f,                                                                                                           // float                                                                        maxDepthBounds;
314         };
315
316         const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
317         // Number of blend attachments must equal the number of color attachments during any subpass.
318         const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
319         {
320                 VK_FALSE,                                       // VkBool32                                     blendEnable;
321                 VK_BLEND_FACTOR_ONE,            // VkBlendFactor                        srcColorBlendFactor;
322                 VK_BLEND_FACTOR_ZERO,           // VkBlendFactor                        dstColorBlendFactor;
323                 VK_BLEND_OP_ADD,                        // VkBlendOp                            colorBlendOp;
324                 VK_BLEND_FACTOR_ONE,            // VkBlendFactor                        srcAlphaBlendFactor;
325                 VK_BLEND_FACTOR_ZERO,           // VkBlendFactor                        dstAlphaBlendFactor;
326                 VK_BLEND_OP_ADD,                        // VkBlendOp                            alphaBlendOp;
327                 colorComponentsAll,                     // VkColorComponentFlags        colorWriteMask;
328         };
329
330         std::vector<VkPipelineColorBlendAttachmentState> colorBlendAttachmentStates;
331         for (deUint32 attachmentIdx = 0; attachmentIdx < numAttachments; attachmentIdx++)
332                 colorBlendAttachmentStates.push_back(pipelineColorBlendAttachmentState);
333
334         const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
335         {
336                 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,               // VkStructureType                                                              sType;
337                 DE_NULL,                                                                                                                // const void*                                                                  pNext;
338                 (VkPipelineColorBlendStateCreateFlags)0,                                                // VkPipelineColorBlendStateCreateFlags                 flags;
339                 VK_FALSE,                                                                                                               // VkBool32                                                                             logicOpEnable;
340                 VK_LOGIC_OP_COPY,                                                                                               // VkLogicOp                                                                    logicOp;
341                 numAttachments,                                                                                                 // deUint32                                                                             attachmentCount;
342                 numAttachments == 0 ? DE_NULL : &colorBlendAttachmentStates[0], // const VkPipelineColorBlendAttachmentState*   pAttachments;
343                 { 0.0f, 0.0f, 0.0f, 0.0f },                                                                             // float                                                                                blendConstants[4];
344         };
345
346         const VkPipelineShaderStageCreateInfo pShaderStages[] =
347         {
348                 {
349                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    // VkStructureType                                              sType;
350                         DE_NULL,                                                                                                // const void*                                                  pNext;
351                         (VkPipelineShaderStageCreateFlags)0,                                    // VkPipelineShaderStageCreateFlags             flags;
352                         VK_SHADER_STAGE_VERTEX_BIT,                                                             // VkShaderStageFlagBits                                stage;
353                         vertexModule,                                                                                   // VkShaderModule                                               module;
354                         "main",                                                                                                 // const char*                                                  pName;
355                         DE_NULL,                                                                                                // const VkSpecializationInfo*                  pSpecializationInfo;
356                 },
357                 {
358                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    // VkStructureType                                              sType;
359                         DE_NULL,                                                                                                // const void*                                                  pNext;
360                         (VkPipelineShaderStageCreateFlags)0,                                    // VkPipelineShaderStageCreateFlags             flags;
361                         VK_SHADER_STAGE_FRAGMENT_BIT,                                                   // VkShaderStageFlagBits                                stage;
362                         fragmentModule,                                                                                 // VkShaderModule                                               module;
363                         "main",                                                                                                 // const char*                                                  pName;
364                         DE_NULL,                                                                                                // const VkSpecializationInfo*                  pSpecializationInfo;
365                 }
366         };
367
368         const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
369         {
370                 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,        // VkStructureType                                                                      sType;
371                 DE_NULL,                                                                                        // const void*                                                                          pNext;
372                 (VkPipelineCreateFlags)0,                                                       // VkPipelineCreateFlags                                                        flags;
373                 DE_LENGTH_OF_ARRAY(pShaderStages),                                      // deUint32                                                                                     stageCount;
374                 pShaderStages,                                                                          // const VkPipelineShaderStageCreateInfo*                       pStages;
375                 &vertexInputStateInfo,                                                          // const VkPipelineVertexInputStateCreateInfo*          pVertexInputState;
376                 &pipelineInputAssemblyStateInfo,                                        // const VkPipelineInputAssemblyStateCreateInfo*        pInputAssemblyState;
377                 DE_NULL,                                                                                        // const VkPipelineTessellationStateCreateInfo*         pTessellationState;
378                 &pipelineViewportStateInfo,                                                     // const VkPipelineViewportStateCreateInfo*                     pViewportState;
379                 &pipelineRasterizationStateInfo,                                        // const VkPipelineRasterizationStateCreateInfo*        pRasterizationState;
380                 &pipelineMultisampleStateInfo,                                          // const VkPipelineMultisampleStateCreateInfo*          pMultisampleState;
381                 &pipelineDepthStencilStateInfo,                                         // const VkPipelineDepthStencilStateCreateInfo*         pDepthStencilState;
382                 &pipelineColorBlendStateInfo,                                           // const VkPipelineColorBlendStateCreateInfo*           pColorBlendState;
383                 DE_NULL,                                                                                        // const VkPipelineDynamicStateCreateInfo*                      pDynamicState;
384                 pipelineLayout,                                                                         // VkPipelineLayout                                                                     layout;
385                 renderPass,                                                                                     // VkRenderPass                                                                         renderPass;
386                 subpass,                                                                                        // deUint32                                                                                     subpass;
387                 DE_NULL,                                                                                        // VkPipeline                                                                           basePipelineHandle;
388                 0,                                                                                                      // deInt32                                                                                      basePipelineIndex;
389         };
390
391         return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
392 }
393
394 Move<VkImage> makeImage (const DeviceInterface&         vk,
395                                                  const VkDevice                         device,
396                                                  const VkImageCreateFlags       flags,
397                                                  const VkImageType                      imageType,
398                                                  const VkFormat                         format,
399                                                  const IVec3&                           size,
400                                                  const deUint32                         numLayers,
401                                                  const VkImageUsageFlags        usage,
402                                                  const bool                                     multisample)
403 {
404         const VkImageCreateInfo imageParams =
405         {
406                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                                    // VkStructureType                      sType;
407                 DE_NULL,                                                                                                                // const void*                          pNext;
408                 flags,                                                                                                                  // VkImageCreateFlags           flags;
409                 imageType,                                                                                                              // VkImageType                          imageType;
410                 format,                                                                                                                 // VkFormat                                     format;
411                 makeExtent3D(size),                                                                                             // VkExtent3D                           extent;
412                 1u,                                                                                                                             // deUint32                                     mipLevels;
413                 numLayers,                                                                                                              // deUint32                                     arrayLayers;
414                 multisample ? VK_SAMPLE_COUNT_4_BIT : VK_SAMPLE_COUNT_1_BIT,    // VkSampleCountFlagBits        samples;
415                 VK_IMAGE_TILING_OPTIMAL,                                                                                // VkImageTiling                        tiling;
416                 usage,                                                                                                                  // VkImageUsageFlags            usage;
417                 VK_SHARING_MODE_EXCLUSIVE,                                                                              // VkSharingMode                        sharingMode;
418                 0u,                                                                                                                             // deUint32                                     queueFamilyIndexCount;
419                 DE_NULL,                                                                                                                // const deUint32*                      pQueueFamilyIndices;
420                 VK_IMAGE_LAYOUT_UNDEFINED,                                                                              // VkImageLayout                        initialLayout;
421         };
422
423         return createImage(vk, device, &imageParams);
424 }
425
426 vector<tcu::Vec4> genFullQuadVertices (const int subpassCount)
427 {
428         vector<tcu::Vec4>       vectorData;
429         for (int subpassNdx = 0; subpassNdx < subpassCount; ++subpassNdx)
430         {
431                 vectorData.push_back(Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
432                 vectorData.push_back(Vec4(-1.0f,  1.0f, 0.0f, 1.0f));
433                 vectorData.push_back(Vec4(1.0f, -1.0f, 0.0f, 1.0f));
434                 vectorData.push_back(Vec4(1.0f,  1.0f, 0.0f, 1.0f));
435         }
436         return vectorData;
437 }
438
439 void initColorPrograms (SourceCollections& programCollection, const CaseDef caseDef)
440 {
441         (void)caseDef;
442
443         // Vertex shader
444         {
445                 std::ostringstream src;
446                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
447                         << "\n"
448                         << "layout(location = 0) in vec4 in_position;\n"
449                         << "\n"
450                         << "out gl_PerVertex {\n"
451                         << "    vec4 gl_Position;\n"
452                         << "};\n"
453                         << "\n"
454                         << "void main(void)\n"
455                         << "{\n"
456                         << "    gl_Position     = in_position;\n"
457                         << "}\n";
458
459                 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
460         }
461
462         // Fragment shader
463         {
464                 std::ostringstream src;
465                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
466                         << "\n"
467                         << "layout(location = 0) out vec4 o_color;\n"
468                         << "\n"
469                         << "void main(void)\n"
470                         << "{\n"
471                         << "    o_color = vec4(1.0, 0.5, 0.25, 1.0);\n"
472                         << "}\n";
473
474                 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
475         }
476 }
477
478 tcu::PixelBufferAccess getExpectedData (tcu::TextureLevel& textureLevel, const CaseDef& caseDef)
479 {
480         const tcu::PixelBufferAccess    expectedImage   (textureLevel);
481         const int                                               renderDepth             = deMax32(caseDef.renderSize.z(), caseDef.numLayers);
482
483         for (int z = 0; z < expectedImage.getDepth(); ++z)
484         {
485                 for (int y = 0; y < expectedImage.getHeight(); ++y)
486                 {
487                         for (int x = 0; x < expectedImage.getWidth(); ++x)
488                         {
489                                 if (x < caseDef.renderSize.x() && y < caseDef.renderSize.y() && z < renderDepth)
490                                         expectedImage.setPixel(tcu::Vec4(1.0, 0.5, 0.25, 1.0), x, y, z);
491                                 else
492                                         expectedImage.setPixel(tcu::Vec4(0.0, 0.0, 0.0, 1.0), x, y, z);
493                         }
494                 }
495         }
496         return expectedImage;
497 }
498
499 inline Move<VkBuffer> makeBuffer (const DeviceInterface& vk, const VkDevice device, const VkDeviceSize bufferSize, const VkBufferUsageFlags usage)
500 {
501         const VkBufferCreateInfo        bufferCreateInfo        = makeBufferCreateInfo(bufferSize, usage);
502         return createBuffer(vk, device, &bufferCreateInfo);
503 }
504
505 inline VkImageSubresourceRange makeColorSubresourceRange (const deUint32 baseArrayLayer, const deUint32 layerCount)
506 {
507         return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, baseArrayLayer, layerCount);
508 }
509
510 // Tests rendering to a a framebuffer with color attachments larger than the
511 // framebuffer dimensions and verifies that rendering does not affect the areas
512 // of the attachment outside the framebuffer dimensions. Tests both single-sample
513 // and multi-sample configurations.
514 tcu::TestStatus test (Context& context, const CaseDef caseDef)
515 {
516         const DeviceInterface&                  vk                                      = context.getDeviceInterface();
517         const VkDevice                                  device                          = context.getDevice();
518         const VkQueue                                   queue                           = context.getUniversalQueue();
519         const deUint32                                  queueFamilyIndex        = context.getUniversalQueueFamilyIndex();
520         Allocator&                                              allocator                       = context.getDefaultAllocator();
521
522         // Color image for rendering in single-sample tests or resolve target for multi-sample tests
523         Move<VkImage>                                   colorImage;
524         MovePtr<Allocation>                             colorImageAlloc;
525
526         // For multisampled tests, this is the rendering target
527         Move<VkImage>                                   msColorImage;
528         MovePtr<Allocation>                             msColorImageAlloc;
529
530         // Host memory buffer where we will copy the rendered image for verification
531         const deUint32                                  att_size_x                      = caseDef.attachmentSize.x();
532         const deUint32                                  att_size_y                      = caseDef.attachmentSize.y();
533         const deUint32                                  att_size_z                      = caseDef.attachmentSize.z();
534         const VkDeviceSize                              colorBufferSize         = att_size_x * att_size_y * att_size_z * caseDef.numLayers * tcu::getPixelSize(mapVkFormat(COLOR_FORMAT));
535         const Unique<VkBuffer>                  colorBuffer                     (makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
536         const UniquePtr<Allocation>             colorBufferAlloc        (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
537
538         Move<VkBuffer>                                  vertexBuffer;
539         MovePtr<Allocation>                             vertexBufferAlloc;
540
541         vector<SharedPtrVkImageView>    colorAttachments;
542         vector<VkImageView>                             attachmentHandles;
543
544         const Unique<VkPipelineLayout>  pipelineLayout          (makePipelineLayout(vk, device));
545         vector<SharedPtrVkPipeline>             pipeline;
546         const Unique<VkRenderPass>              renderPass                      (makeRenderPass(vk, device, COLOR_FORMAT, caseDef.numLayers, caseDef.multisample));
547         Move<VkFramebuffer>                             framebuffer;
548
549         const Unique<VkShaderModule>    vertexModule            (createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u));
550         const Unique<VkShaderModule>    fragmentModule          (createShaderModule(vk, device, context.getBinaryCollection().get("frag"), 0u));
551
552         const Unique<VkCommandPool>             cmdPool                         (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
553         const Unique<VkCommandBuffer>   cmdBuffer                       (makeCommandBuffer(vk, device, *cmdPool));
554
555         const VkImageViewType                   imageViewType           = caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE || caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY
556                 ? VK_IMAGE_VIEW_TYPE_2D : caseDef.imageType;
557
558         // create vertexBuffer
559         {
560                 const vector<tcu::Vec4> vertices                        = genFullQuadVertices(caseDef.numLayers);
561                 const VkDeviceSize              vertexBufferSize        = sizeInBytes(vertices);
562
563                 vertexBuffer            = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
564                 vertexBufferAlloc       = bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
565
566                 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
567                 flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSize);
568         }
569
570         // create colorImage (and msColorImage) using the configured attachmentsize
571         {
572                 const VkImageUsageFlags colorImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
573
574                 colorImage              = makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType), COLOR_FORMAT,
575                         caseDef.attachmentSize, caseDef.numLayers, colorImageUsage, false);
576                 colorImageAlloc = bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any);
577
578                 if (caseDef.multisample)
579                 {
580                         const VkImageUsageFlags msImageUsage    = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
581
582                         msColorImage            = makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType), COLOR_FORMAT,
583                                 caseDef.attachmentSize, caseDef.numLayers, msImageUsage, true);
584                         msColorImageAlloc       = bindImage(vk, device, allocator, *msColorImage, MemoryRequirement::Any);
585                 }
586         }
587
588         // create attachmentHandles and pipelines (one for each layer). We use the renderSize for viewport and scissor
589         for (deUint32 layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx)
590         {
591                 colorAttachments.push_back(makeSharedPtr(makeImageView(vk, device, ! caseDef.multisample ? *colorImage : *msColorImage,
592                         imageViewType, COLOR_FORMAT, makeColorSubresourceRange(layerNdx, 1))));
593                 attachmentHandles.push_back(**colorAttachments.back());
594
595                 pipeline.push_back(makeSharedPtr(makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule,
596                         caseDef.renderSize, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, layerNdx, 1u, caseDef.multisample)));
597         }
598
599         // create framebuffer
600         framebuffer = makeFramebuffer(vk, device, *renderPass, caseDef.numLayers, &attachmentHandles[0],
601                 static_cast<deUint32>(caseDef.renderSize.x()), static_cast<deUint32>(caseDef.renderSize.y()));
602
603         // record command buffer
604         beginCommandBuffer(vk, *cmdBuffer);
605         {
606                 // Clear the entire image attachment to black
607                 {
608                         const VkImageMemoryBarrier      imageLayoutBarriers[]   =
609                         {
610                                 {
611                                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                         // VkStructureType                      sType;
612                                         DE_NULL,                                                                                        // const void*                          pNext;
613                                         0u,                                                                                                     // VkAccessFlags                        srcAccessMask;
614                                         VK_ACCESS_TRANSFER_WRITE_BIT,                                           // VkAccessFlags                        dstAccessMask;
615                                         VK_IMAGE_LAYOUT_UNDEFINED,                                                      // VkImageLayout                        oldLayout;
616                                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,                           // VkImageLayout                        newLayout;
617                                         VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     srcQueueFamilyIndex;
618                                         VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     destQueueFamilyIndex;
619                                         caseDef.multisample ? *msColorImage : *colorImage,      // VkImage                                      image;
620                                         makeColorSubresourceRange(0, caseDef.numLayers)         // VkImageSubresourceRange      subresourceRange;
621                                 },
622                         };
623
624                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0u,
625                                 0u, DE_NULL, 0u, DE_NULL, 1u, imageLayoutBarriers);
626
627                         const VkImageSubresourceRange   ranges          = makeColorSubresourceRange(0, caseDef.numLayers);
628                         const VkClearColorValue                 clearColor      =
629                 {
630                 {0.0f, 0.0f, 0.0f, 1.0f}
631                         };
632                         vk.cmdClearColorImage(*cmdBuffer, caseDef.multisample ? *msColorImage : *colorImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor, 1u, &ranges);
633
634                         const VkImageMemoryBarrier      imageClearBarriers[]    =
635                         {
636                                 {
637                                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                         // VkStructureType                      sType;
638                                         DE_NULL,                                                                                        // const void*                          pNext;
639                                         VK_ACCESS_TRANSFER_WRITE_BIT,                                           // VkAccessFlags                        srcAccessMask;
640                                         VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,                            // VkAccessFlags                        dstAccessMask;
641                                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,                           // VkImageLayout                        oldLayout;
642                                         VK_IMAGE_LAYOUT_GENERAL,                                                        // VkImageLayout                        newLayout;
643                                         VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     srcQueueFamilyIndex;
644                                         VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     destQueueFamilyIndex;
645                                         caseDef.multisample ? *msColorImage : *colorImage,      // VkImage                                      image;
646                                         makeColorSubresourceRange(0, caseDef.numLayers)         // VkImageSubresourceRange      subresourceRange;
647                                 },
648                         };
649
650                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u,
651                                 0u, DE_NULL, 0u, DE_NULL, 1u, imageClearBarriers);
652                 }
653
654                 // Render pass: this should render only to the area defined by renderSize (smaller than the size of the attachment)
655                 {
656                         const VkRect2D                          renderArea                      =
657                         {
658                                 makeOffset2D(0, 0),
659                                 makeExtent2D(caseDef.renderSize.x(), caseDef.renderSize.y()),
660                         };
661                         const VkRenderPassBeginInfo renderPassBeginInfo =
662                         {
663                                 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,       // VkStructureType         sType;
664                                 DE_NULL,                                                                        // const void*             pNext;
665                                 *renderPass,                                                            // VkRenderPass            renderPass;
666                                 *framebuffer,                                                           // VkFramebuffer           framebuffer;
667                                 renderArea,                                                                     // VkRect2D                renderArea;
668                                 0,                                                                                      // uint32_t                clearValueCount;
669                                 DE_NULL,                                                                        // const VkClearValue*     pClearValues;
670                         };
671                         const VkDeviceSize                      vertexBufferOffset      = 0ull;
672
673                         vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
674                         {
675                                 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
676                                 for (deUint32 layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx)
677                                 {
678                                         if (layerNdx != 0)
679                                                 vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
680
681                                         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipeline[layerNdx]);
682                                         vk.cmdDraw(*cmdBuffer, 4u, 1u, layerNdx*4u, 0u);
683                                 }
684                         }
685                         vk.cmdEndRenderPass(*cmdBuffer);
686                 }
687
688                 // If we are using a multi-sampled render target (msColorImage), resolve it now (to colorImage)
689                 if (caseDef.multisample)
690                 {
691                         // Transition msColorImage (from layout COLOR_ATTACHMENT_OPTIMAL) and colorImage (from layout UNDEFINED) to layout GENERAL before resolving
692                         const VkImageMemoryBarrier      imageBarriers[] =
693                         {
694                                 {
695                                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                 // VkStructureType                      sType;
696                                         DE_NULL,                                                                                // const void*                          pNext;
697                                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                   // VkAccessFlags                        srcAccessMask;
698                                         VK_ACCESS_TRANSFER_READ_BIT,                                    // VkAccessFlags                        dstAccessMask;
699                                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,               // VkImageLayout                        oldLayout;
700                                         VK_IMAGE_LAYOUT_GENERAL,                                                // VkImageLayout                        newLayout;
701                                         VK_QUEUE_FAMILY_IGNORED,                                                // deUint32                                     srcQueueFamilyIndex;
702                                         VK_QUEUE_FAMILY_IGNORED,                                                // deUint32                                     destQueueFamilyIndex;
703                                         *msColorImage,                                                                  // VkImage                                      image;
704                                         makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange      subresourceRange;
705                                 },
706                                 {
707                                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                 // VkStructureType                      sType;
708                                         DE_NULL,                                                                                // const void*                          pNext;
709                                         (VkAccessFlags)0,                                                               // VkAccessFlags                        srcAccessMask;
710                                         VK_ACCESS_TRANSFER_WRITE_BIT,                                   // VkAccessFlags                        dstAccessMask;
711                                         VK_IMAGE_LAYOUT_UNDEFINED,                                              // VkImageLayout                        oldLayout;
712                                         VK_IMAGE_LAYOUT_GENERAL,                                                // VkImageLayout                        newLayout;
713                                         VK_QUEUE_FAMILY_IGNORED,                                                // deUint32                                     srcQueueFamilyIndex;
714                                         VK_QUEUE_FAMILY_IGNORED,                                                // deUint32                                     destQueueFamilyIndex;
715                                         *colorImage,                                                                    // VkImage                                      image;
716                                         makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange      subresourceRange;
717                                 }
718                         };
719
720                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
721                                 0u, DE_NULL, 0u, DE_NULL, 2u, imageBarriers);
722
723                         const VkImageResolve    region  =
724                         {
725                                 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, caseDef.numLayers), // VkImageSubresourceLayers    srcSubresource;
726                                 makeOffset3D(0, 0, 0),                                                                                                                  // VkOffset3D                  srcOffset;
727                                 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, caseDef.numLayers), // VkImageSubresourceLayers    dstSubresource;
728                                 makeOffset3D(0, 0, 0),                                                                                                                  // VkOffset3D                  dstOffset;
729                                 makeExtent3D(caseDef.attachmentSize)                                                                                    // VkExtent3D                  extent;
730                         };
731
732                         vk.cmdResolveImage(*cmdBuffer, *msColorImage, VK_IMAGE_LAYOUT_GENERAL, *colorImage, VK_IMAGE_LAYOUT_GENERAL, 1, &region);
733                 }
734
735                 // copy colorImage to host visible colorBuffer
736                 {
737                         const VkImageMemoryBarrier      imageBarriers[]         =
738                         {
739                                 {
740                                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                                                                                                         // VkStructureType                      sType;
741                                         DE_NULL,                                                                                                                                                                        // const void*                          pNext;
742                                         (vk::VkAccessFlags)(caseDef.multisample ? VK_ACCESS_TRANSFER_WRITE_BIT : VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
743                                         VK_ACCESS_TRANSFER_READ_BIT,                                                                                                                            // VkAccessFlags                        dstAccessMask;
744                                         caseDef.multisample ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,       // VkImageLayout                        oldLayout;
745                                         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,                                                                                                           // VkImageLayout                        newLayout;
746                                         VK_QUEUE_FAMILY_IGNORED,                                                                                                                                        // deUint32                                     srcQueueFamilyIndex;
747                                         VK_QUEUE_FAMILY_IGNORED,                                                                                                                                        // deUint32                                     destQueueFamilyIndex;
748                                         *colorImage,                                                                                                                                                            // VkImage                                      image;
749                                         makeColorSubresourceRange(0, caseDef.numLayers)                                                                                         // VkImageSubresourceRange      subresourceRange;
750                                 }
751                         };
752
753                         vk.cmdPipelineBarrier(*cmdBuffer, caseDef.multisample ? VK_PIPELINE_STAGE_TRANSFER_BIT : VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
754                                 0u, DE_NULL, 0u, DE_NULL, 1u, imageBarriers);
755
756                         const VkBufferImageCopy         region                          =
757                         {
758                                 0ull,                                                                                                                                                           // VkDeviceSize                bufferOffset;
759                                 0u,                                                                                                                                                                     // uint32_t                    bufferRowLength;
760                                 0u,                                                                                                                                                                     // uint32_t                    bufferImageHeight;
761                                 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, caseDef.numLayers),       // VkImageSubresourceLayers    imageSubresource;
762                                 makeOffset3D(0, 0, 0),                                                                                                                          // VkOffset3D                  imageOffset;
763                                 makeExtent3D(caseDef.attachmentSize),                                                                                           // VkExtent3D                  imageExtent;
764                         };
765
766                         vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, &region);
767
768                         const VkBufferMemoryBarrier     bufferBarriers[]        =
769                         {
770                                 {
771                                         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,        // VkStructureType    sType;
772                                         DE_NULL,                                                                        // const void*        pNext;
773                                         VK_ACCESS_TRANSFER_WRITE_BIT,                           // VkAccessFlags      srcAccessMask;
774                                         VK_ACCESS_HOST_READ_BIT,                                        // VkAccessFlags      dstAccessMask;
775                                         VK_QUEUE_FAMILY_IGNORED,                                        // uint32_t           srcQueueFamilyIndex;
776                                         VK_QUEUE_FAMILY_IGNORED,                                        // uint32_t           dstQueueFamilyIndex;
777                                         *colorBuffer,                                                           // VkBuffer           buffer;
778                                         0ull,                                                                           // VkDeviceSize       offset;
779                                         VK_WHOLE_SIZE,                                                          // VkDeviceSize       size;
780                                 },
781                         };
782
783                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
784                                 0u, DE_NULL, DE_LENGTH_OF_ARRAY(bufferBarriers), bufferBarriers, 0u, DE_NULL);
785                 }
786         } // beginCommandBuffer
787
788         VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
789         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
790
791         // Verify results
792         {
793                 invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
794                 const tcu::TextureFormat                        format                  = mapVkFormat(COLOR_FORMAT);
795                 const int                                                       depth                   = deMax32(caseDef.attachmentSize.z(), caseDef.numLayers);
796                 tcu::TextureLevel                                       textureLevel    (format, caseDef.attachmentSize.x(), caseDef.attachmentSize.y(), depth);
797                 const tcu::PixelBufferAccess            expectedImage   = getExpectedData(textureLevel, caseDef);
798                 const tcu::ConstPixelBufferAccess       resultImage             (format, caseDef.attachmentSize.x(), caseDef.attachmentSize.y(), depth, colorBufferAlloc->getHostPtr());
799
800                 if (!tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT))
801                         return tcu::TestStatus::fail("Fail");
802         }
803
804         return tcu::TestStatus::pass("Pass");
805 }
806
807 void initImagePrograms (SourceCollections& programCollection, const bool multisample)
808 {
809         // Vertex shader
810         {
811                 std::ostringstream src;
812                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
813                         << "\n"
814                         << "layout(location = 0) in vec4 in_position;\n"
815                         << "\n"
816                         << "out gl_PerVertex {\n"
817                         << "    vec4 gl_Position;\n"
818                         << "};\n"
819                         << "\n"
820                         << "void main(void)\n"
821                         << "{\n"
822                         << "    gl_Position     = in_position;\n"
823                         << "}\n";
824
825                 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
826         }
827
828         // Fragment shader
829         {
830                 std::ostringstream src;
831                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
832                         << "\n"
833                         << "layout(binding = 0, rgba8) writeonly uniform image2D image;\n"
834                         << "\n"
835                         << "void main(void)\n"
836                         << "{\n";
837                         if (!multisample)
838                                 src << "    imageStore(image, ivec2(gl_PrimitiveID % 4, 0), vec4(1.0, 0.5, 0.25, 1.0));\n";
839                         else
840                                 src << "    imageStore(image, ivec2(gl_PrimitiveID % 4, gl_SampleID % 4), vec4(1.0, 0.5, 0.25, 1.0));\n";
841                         src << "}\n";
842
843                 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
844         }
845 }
846
847 //! Make a render pass with no attachments
848 Move<VkRenderPass> makeRenderPassNoAtt (const DeviceInterface& vk, const VkDevice device)
849 {
850         // Create a single subpass with no attachment references
851         vector<VkSubpassDescription>    subpasses;
852
853         const VkSubpassDescription              subpassDescription      =
854         {
855                 (VkSubpassDescriptionFlags)0,           // VkSubpassDescriptionFlags            flags;
856                 VK_PIPELINE_BIND_POINT_GRAPHICS,        // VkPipelineBindPoint                          pipelineBindPoint;
857                 0u,                                                                     // deUint32                                                     inputAttachmentCount;
858                 DE_NULL,                                                        // const VkAttachmentReference*         pInputAttachments;
859                 0u,                                                                     // deUint32                                                     colorAttachmentCount;
860                 DE_NULL,                                                        // const VkAttachmentReference*         pColorAttachments;
861                 DE_NULL,                                                        // const VkAttachmentReference*         pResolveAttachments;
862                 DE_NULL,                                                        // const VkAttachmentReference*         pDepthStencilAttachment;
863                 0u,                                                                     // deUint32                                                     preserveAttachmentCount;
864                 DE_NULL                                                         // const deUint32*                                      pPreserveAttachments;
865         };
866         subpasses.push_back(subpassDescription);
867
868         const VkRenderPassCreateInfo    renderPassInfo  =
869         {
870                 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,      // VkStructureType                                      sType;
871                 DE_NULL,                                                                        // const void*                                          pNext;
872                 (VkRenderPassCreateFlags)0,                                     // VkRenderPassCreateFlags                      flags;
873                 0,                                                                                      // deUint32                                                     attachmentCount;
874                 DE_NULL,                                                                        // const VkAttachmentDescription*       pAttachments;
875                 1,                                                                                      // deUint32                                                     subpassCount;
876                 &subpasses[0],                                                          // const VkSubpassDescription*          pSubpasses;
877                 0u,                                                                                     // deUint32                                                     dependencyCount;
878                 DE_NULL                                                                         // const VkSubpassDependency*           pDependencies;
879         };
880
881         return createRenderPass(vk, device, &renderPassInfo);
882 }
883
884 tcu::PixelBufferAccess getExpectedDataNoAtt (tcu::TextureLevel& textureLevel)
885 {
886         const tcu::PixelBufferAccess    expectedImage   (textureLevel);
887         for (int z = 0; z < expectedImage.getDepth(); ++z)
888         {
889                 for (int y = 0; y < expectedImage.getHeight(); ++y)
890                 {
891                         for (int x = 0; x < expectedImage.getWidth(); ++x)
892                         {
893                                 expectedImage.setPixel(tcu::Vec4(1.0, 0.5, 0.25, 1.0), x, y, z);
894                         }
895                 }
896         }
897         return expectedImage;
898 }
899
900 vector<tcu::Vec4> genPointVertices (void)
901 {
902         vector<tcu::Vec4>       vectorData;
903         vectorData.push_back(Vec4(-0.25f, -0.25f, 0, 1));
904         vectorData.push_back(Vec4(-0.25f,  0.25f, 0, 1));
905         vectorData.push_back(Vec4(0.25f, -0.25f, 0, 1));
906         vectorData.push_back(Vec4(0.25f,  0.25f, 0, 1));
907         return vectorData;
908 }
909
910 // Tests rendering to a framebuffer without color attachments, checking that
911 // the fragment shader is run even in the absence of color output. In this case
912 // we render 4 point primitives and we make the fragment shader write to a
913 // different pixel of an image via an imageStore command. For the single-sampled
914 // configuration we use a 4x1 image to record the output and for the
915 // multi-sampled case we use a 4x4 image to record all 16 samples produced by
916 // 4-sample multi-sampling
917 tcu::TestStatus testNoAtt (Context& context, const bool multisample)
918 {
919         const VkPhysicalDeviceFeatures          features                                = context.getDeviceFeatures();
920         if (!features.fragmentStoresAndAtomics)
921                 throw tcu::NotSupportedError("fragmentStoresAndAtomics feature not supported");
922         if (!features.geometryShader && !features.tessellationShader) // Shader uses gl_PrimitiveID
923                 throw tcu::NotSupportedError("geometryShader or tessellationShader feature not supported");
924         if (multisample && !features.sampleRateShading) // MS shader uses gl_SampleID
925                 throw tcu::NotSupportedError("sampleRateShading feature not supported");
926
927         const DeviceInterface&                          vk                                              = context.getDeviceInterface();
928         const VkDevice                                          device                                  = context.getDevice();
929         const VkQueue                                           queue                                   = context.getUniversalQueue();
930         const deUint32                                          queueFamilyIndex                = context.getUniversalQueueFamilyIndex();
931         Allocator&                                                      allocator                               = context.getDefaultAllocator();
932         const IVec3                                                     renderSize                              (32, 32, 1);
933
934         Move<VkBuffer>                                          vertexBuffer;
935         MovePtr<Allocation>                                     vertexBufferAlloc;
936
937         const Unique<VkShaderModule>            vertexModule                    (createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u));
938         const Unique<VkShaderModule>            fragmentModule                  (createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u));
939
940         // Create image where we will record the writes. For single-sampled cases this is a 4x1 image
941         // and for multi-sampled cases this is a 4x<num_samples> image.
942         const deUint8                                           numSamples                              = multisample ? 4 : 1;
943         const deUint8                                           imageWidth                              = 4;
944         const deUint8                                           imageHeight                             = numSamples;
945         const deUint8                                           imageDepth                              = 1;
946         const deUint8                                           imageLayers                             = 1;
947         const IVec3                                                     imageDim                                = IVec3(imageWidth, imageHeight, imageDepth);
948         const VkImageUsageFlags                         imageUsage                              = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_STORAGE_BIT;
949         const Move<VkImage>                                     image                                   = makeImage(vk, device, VkImageViewCreateFlags(0), VK_IMAGE_TYPE_2D, COLOR_FORMAT, imageDim, imageLayers, imageUsage, false);
950         const VkImageSubresourceRange           imageSubresourceRange   = makeColorSubresourceRange(0u, imageLayers);
951         const MovePtr<Allocation>                       imageAlloc                              = bindImage(vk, device, allocator, *image, MemoryRequirement::Any);
952         const Move<VkImageView>                         imageView                               = makeImageView(vk, device, *image, VK_IMAGE_VIEW_TYPE_2D, COLOR_FORMAT, imageSubresourceRange);
953
954         // Create a buffer where we will copy the image for verification
955         const VkDeviceSize                                      colorBufferSize         = imageWidth * imageHeight * imageDepth * numSamples * tcu::getPixelSize(mapVkFormat(COLOR_FORMAT));
956         const Unique<VkBuffer>                          colorBuffer                     (makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
957         const UniquePtr<Allocation>                     colorBufferAlloc        (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
958
959         // Create pipeline descriptor set for the image
960         const Move<VkDescriptorSetLayout>       descriptorSetLayout             = DescriptorSetLayoutBuilder()
961                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT)
962                 .build(vk, device);
963
964         const Move<VkDescriptorPool>            descriptorPool                  = DescriptorPoolBuilder()
965                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1)
966                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
967
968         const Move<VkDescriptorSet>                     descriptorSet                   = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
969         const VkDescriptorImageInfo                     descriptorImageInfo             = makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL);
970         DescriptorSetUpdateBuilder()
971                 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
972                 .update(vk, device);
973
974         const Unique<VkPipelineLayout>          pipelineLayout                  (makePipelineLayout (vk, device, *descriptorSetLayout));
975         vector<SharedPtrVkPipeline>                     pipeline;
976         const Unique<VkRenderPass>                      renderPass                              (makeRenderPassNoAtt (vk, device));
977         Move<VkFramebuffer>                                     framebuffer;
978
979         const Unique<VkCommandPool>                     cmdPool                                 (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
980         const Unique<VkCommandBuffer>           cmdBuffer                               (makeCommandBuffer (vk, device, *cmdPool));
981
982         // create vertexBuffer
983         {
984                 const vector<tcu::Vec4> vertices                        = genPointVertices();
985                 const VkDeviceSize              vertexBufferSize        = sizeInBytes(vertices);
986
987                 vertexBuffer            = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
988                 vertexBufferAlloc       = bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
989                 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
990                 flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSize);
991         }
992
993         // Create render pass and pipeline
994         pipeline.push_back(makeSharedPtr(makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule,
995                 renderSize, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0, 0u, multisample)));
996         framebuffer = makeFramebuffer(vk, device, *renderPass, 0, DE_NULL, renderSize.x(), renderSize.y());
997
998         // Record command buffer
999         beginCommandBuffer(vk, *cmdBuffer);
1000         {
1001                 // shader image layout transition undefined -> general
1002                 {
1003                         const VkImageMemoryBarrier setImageLayoutBarrier = makeImageMemoryBarrier(
1004                                 0u, VK_ACCESS_SHADER_WRITE_BIT,
1005                                 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
1006                                 *image, imageSubresourceRange);
1007
1008                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0,
1009                                 0, DE_NULL, 0, DE_NULL, 1, &setImageLayoutBarrier);
1010                 }
1011
1012                 // Render pass
1013                 {
1014                         const VkRect2D renderArea =
1015                         {
1016                                 makeOffset2D(0, 0),
1017                                 makeExtent2D(renderSize.x(), renderSize.y()),
1018                         };
1019                         const VkRenderPassBeginInfo renderPassBeginInfo =
1020                         {
1021                                 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,       // VkStructureType         sType;
1022                                 DE_NULL,                                                                        // const void*             pNext;
1023                                 *renderPass,                                                            // VkRenderPass            renderPass;
1024                                 *framebuffer,                                                           // VkFramebuffer           framebuffer;
1025                                 renderArea,                                                                     // VkRect2D                renderArea;
1026                                 0,                                                                                      // uint32_t                clearValueCount;
1027                                 DE_NULL,                                                                        // const VkClearValue*     pClearValues;
1028                         };
1029                         const VkDeviceSize vertexBufferOffset = 0ull;
1030
1031                         vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1032
1033                         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipeline[0]);
1034                         vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1035                         vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
1036                         vk.cmdDraw(*cmdBuffer, 4u, 1u, 0u, 0u);
1037
1038                         vk.cmdEndRenderPass(*cmdBuffer);
1039                 }
1040
1041                 // copy image to host visible colorBuffer
1042                 {
1043                         const VkImageMemoryBarrier      imageBarriers[]         =
1044                         {
1045                                 {
1046                                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,         // VkStructureType                      sType;
1047                                         DE_NULL,                                                                        // const void*                          pNext;
1048                                         VK_ACCESS_SHADER_WRITE_BIT,                                     // VkAccessFlags                        srcAccessMask;
1049                                         VK_ACCESS_TRANSFER_READ_BIT,                            // VkAccessFlags                        dstAccessMask;
1050                                         VK_IMAGE_LAYOUT_GENERAL,                                        // VkImageLayout                        oldLayout;
1051                                         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,           // VkImageLayout                        newLayout;
1052                                         VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                                     srcQueueFamilyIndex;
1053                                         VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                                     destQueueFamilyIndex;
1054                                         *image,                                                                         // VkImage                                      image;
1055                                         makeColorSubresourceRange(0, 1)                         // VkImageSubresourceRange      subresourceRange;
1056                                 }
1057                         };
1058
1059                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1060                                 0u, DE_NULL, 0u, DE_NULL, 1u, imageBarriers);
1061
1062                         const VkBufferImageCopy         region                          =
1063                         {
1064                                 0ull,                                                                                                                           // VkDeviceSize                bufferOffset;
1065                                 0u,                                                                                                                                     // uint32_t                    bufferRowLength;
1066                                 0u,                                                                                                                                     // uint32_t                    bufferImageHeight;
1067                                 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1),       // VkImageSubresourceLayers    imageSubresource;
1068                                 makeOffset3D(0, 0, 0),                                                                                          // VkOffset3D                  imageOffset;
1069                                 makeExtent3D(IVec3(imageWidth, imageHeight, imageDepth)),                       // VkExtent3D                  imageExtent;
1070                         };
1071
1072                         vk.cmdCopyImageToBuffer(*cmdBuffer, *image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, &region);
1073
1074                         const VkBufferMemoryBarrier     bufferBarriers[]        =
1075                         {
1076                                 {
1077                                         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,        // VkStructureType    sType;
1078                                         DE_NULL,                                                                        // const void*        pNext;
1079                                         VK_ACCESS_TRANSFER_WRITE_BIT,                           // VkAccessFlags      srcAccessMask;
1080                                         VK_ACCESS_HOST_READ_BIT,                                        // VkAccessFlags      dstAccessMask;
1081                                         VK_QUEUE_FAMILY_IGNORED,                                        // uint32_t           srcQueueFamilyIndex;
1082                                         VK_QUEUE_FAMILY_IGNORED,                                        // uint32_t           dstQueueFamilyIndex;
1083                                         *colorBuffer,                                                           // VkBuffer           buffer;
1084                                         0ull,                                                                           // VkDeviceSize       offset;
1085                                         VK_WHOLE_SIZE,                                                          // VkDeviceSize       size;
1086                                 },
1087                         };
1088
1089                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
1090                                 0u, DE_NULL, DE_LENGTH_OF_ARRAY(bufferBarriers), bufferBarriers, 0u, DE_NULL);
1091                 }
1092         } // beginCommandBuffer
1093
1094         VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1095         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1096
1097         // Verify results
1098         {
1099                 invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1100                 const tcu::TextureFormat                        format                  = mapVkFormat(COLOR_FORMAT);
1101                 tcu::TextureLevel                                       textureLevel    (format, imageWidth, imageHeight, imageDepth);
1102                 const tcu::PixelBufferAccess            expectedImage   = getExpectedDataNoAtt(textureLevel);
1103                 const tcu::ConstPixelBufferAccess       resultImage             (format, imageWidth, imageHeight, imageDepth, colorBufferAlloc->getHostPtr());
1104
1105                 if (!tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT))
1106                         return tcu::TestStatus::fail("Fail");
1107         }
1108
1109         return tcu::TestStatus::pass("Pass");
1110 }
1111
1112 //! Make a render pass with three color attachments
1113 Move<VkRenderPass> makeRenderPassDifferentAttachmentSizes       (const DeviceInterface& vk,
1114                                                                                                                          const VkDevice                 device,
1115                                                                                                                          const VkFormat                 colorFormat,
1116                                                                                                                          deUint32                               numAttachments,
1117                                                                                                                          const bool                             multisample)
1118 {
1119         vector<VkAttachmentDescription> attachmentDescriptions          (numAttachments);
1120         vector<VkAttachmentReference>   colorAttachmentReferences       (numAttachments);
1121
1122         for (deUint32 i = 0; i < numAttachments; i++)
1123         {
1124                 VkAttachmentDescription colorAttachmentDescription =
1125                 {
1126                         (VkAttachmentDescriptionFlags)0,                                                                // VkAttachmentDescriptionFla   flags;
1127                         colorFormat,                                                                                                    // VkFormat                                             format;
1128                         !multisample ? VK_SAMPLE_COUNT_1_BIT : VK_SAMPLE_COUNT_4_BIT,   // VkSampleCountFlagBits                samples;
1129                         VK_ATTACHMENT_LOAD_OP_LOAD,                                                                             // VkAttachmentLoadOp                   loadOp;
1130                         VK_ATTACHMENT_STORE_OP_STORE,                                                                   // VkAttachmentStoreOp                  storeOp;
1131                         VK_ATTACHMENT_LOAD_OP_DONT_CARE,                                                                // VkAttachmentLoadOp                   stencilLoadOp;
1132                         VK_ATTACHMENT_STORE_OP_DONT_CARE,                                                               // VkAttachmentStoreOp                  stencilStoreOp;
1133                         VK_IMAGE_LAYOUT_GENERAL,                                                                                // VkImageLayout                                initialLayout;
1134                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                                               // VkImageLayout                                finalLayout;
1135                 };
1136                 attachmentDescriptions[i] = colorAttachmentDescription;
1137
1138                 const VkAttachmentReference attachmentRef =
1139                 {
1140                         i,                                                                                      // deUint32                     attachment;
1141                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL        // VkImageLayout        layout;
1142                 };
1143                 colorAttachmentReferences[i] = attachmentRef;
1144         }
1145
1146         const VkSubpassDescription subpassDescription =
1147         {
1148                 (VkSubpassDescriptionFlags)0,           // VkSubpassDescriptionFlags            flags;
1149                 VK_PIPELINE_BIND_POINT_GRAPHICS,        // VkPipelineBindPoint                          pipelineBindPoint;
1150                 0u,                                                                     // deUint32                                                     inputAttachmentCount;
1151                 DE_NULL,                                                        // const VkAttachmentReference*         pInputAttachments;
1152                 numAttachments,                                         // deUint32                                                     colorAttachmentCount;
1153                 &colorAttachmentReferences[0],          // const VkAttachmentReference*         pColorAttachments;
1154                 DE_NULL,                                                        // const VkAttachmentReference*         pResolveAttachments;
1155                 DE_NULL,                                                        // const VkAttachmentReference*         pDepthStencilAttachment;
1156                 0u,                                                                     // deUint32                                                     preserveAttachmentCount;
1157                 DE_NULL                                                         // const deUint32*                                      pPreserveAttachments;
1158         };
1159
1160         const VkRenderPassCreateInfo renderPassInfo =
1161         {
1162                 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,      // VkStructureType                                      sType;
1163                 DE_NULL,                                                                        // const void*                                          pNext;
1164                 (VkRenderPassCreateFlags)0,                                     // VkRenderPassCreateFlags                      flags;
1165                 numAttachments,                                                         // deUint32                                                     attachmentCount;
1166                 &attachmentDescriptions[0],                                     // const VkAttachmentDescription*       pAttachments;
1167                 1u,                                                                                     // deUint32                                                     subpassCount;
1168                 &subpassDescription,                                            // const VkSubpassDescription*          pSubpasses;
1169                 0u,                                                                                     // deUint32                                                     dependencyCount;
1170                 DE_NULL                                                                         // const VkSubpassDependency*           pDependencies;
1171         };
1172
1173         return createRenderPass(vk, device, &renderPassInfo);
1174 }
1175
1176 // Tests framebuffer with attachments of different sizes
1177 tcu::TestStatus testDifferentAttachmentSizes (Context& context, const CaseDef caseDef)
1178 {
1179         const DeviceInterface&                  vk                                      = context.getDeviceInterface();
1180         const VkDevice                                  device                          = context.getDevice();
1181         const VkQueue                                   queue                           = context.getUniversalQueue();
1182         const deUint32                                  queueFamilyIndex        = context.getUniversalQueueFamilyIndex();
1183         Allocator&                                              allocator                       = context.getDefaultAllocator();
1184         const deUint32                                  numRenderTargets        = 3;
1185
1186         // Color images for rendering in single-sample tests or resolve targets for multi-sample tests
1187         Move<VkImage>                                   colorImages[numRenderTargets];
1188         MovePtr<Allocation>                             colorImageAllocs[numRenderTargets];
1189
1190         // For multisampled tests, these are the rendering targets
1191         Move<VkImage>                                   msColorImages[numRenderTargets];
1192         MovePtr<Allocation>                             msColorImageAllocs[numRenderTargets];
1193
1194         Move<VkBuffer>                                  colorBuffers[numRenderTargets];
1195         MovePtr<Allocation>                             colorBufferAllocs[numRenderTargets];
1196
1197         // Vary attachment sizes by adding an offset to the base size.
1198         const IVec3                                             attachmentSizes[]       =
1199         {
1200                 caseDef.attachmentSize,
1201                 caseDef.attachmentSize + IVec3(10, caseDef.attachmentSize.y() == 1 ? 0 : 15, 0),
1202                 caseDef.attachmentSize + IVec3(27, caseDef.attachmentSize.y() == 1 ? 0 : 4, 0)
1203         };
1204
1205         // Use unique clear color for each render target to verify no leaking happens between render target clears.
1206         const VkClearColorValue                 clearColors[]           =
1207         {
1208                 {{1.0f, 0.0f, 0.0f, 1.0f}},
1209                 {{0.0f, 1.0f, 0.0f, 1.0f}},
1210                 {{0.0f, 0.0f, 1.0f, 1.0f}}
1211         };
1212
1213         Move<VkBuffer>                                  vertexBuffer;
1214         MovePtr<Allocation>                             vertexBufferAlloc;
1215
1216         vector<SharedPtrVkImageView>    colorAttachments;
1217         vector<VkImageView>                             attachmentHandles;
1218
1219         const Unique<VkPipelineLayout>  pipelineLayout          (makePipelineLayout(vk, device));
1220         Move<VkPipeline>                                pipeline;
1221         const Unique<VkRenderPass>              renderPass                      (makeRenderPassDifferentAttachmentSizes(vk, device, COLOR_FORMAT, numRenderTargets, caseDef.multisample));
1222         Move<VkFramebuffer>                             framebuffer;
1223
1224         const Unique<VkShaderModule>    vertexModule            (createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u));
1225         const Unique<VkShaderModule>    fragmentModule          (createShaderModule(vk, device, context.getBinaryCollection().get("frag"), 0u));
1226
1227         const Unique<VkCommandPool>             cmdPool                         (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1228         const Unique<VkCommandBuffer>   cmdBuffer                       (makeCommandBuffer(vk, device, *cmdPool));
1229
1230         const VkImageViewType                   imageViewType           = caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE || caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY
1231                 ? VK_IMAGE_VIEW_TYPE_2D : caseDef.imageType;
1232
1233         const VkImageSubresourceRange   range                           = makeColorSubresourceRange(0, 1);
1234
1235         // create color buffers
1236         for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1237         {
1238                 // Host memory buffer where we will copy the rendered image for verification
1239                 const deUint32                                  att_size_x                      = attachmentSizes[renderTargetIdx].x();
1240                 const deUint32                                  att_size_y                      = attachmentSizes[renderTargetIdx].y();
1241                 const deUint32                                  att_size_z                      = attachmentSizes[renderTargetIdx].z();
1242                 const VkDeviceSize                              colorBufferSize         = att_size_x * att_size_y * att_size_z * tcu::getPixelSize(mapVkFormat(COLOR_FORMAT));
1243                 colorBuffers[renderTargetIdx]                                           = makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1244                 colorBufferAllocs[renderTargetIdx]                                      = bindBuffer(vk, device, allocator, *colorBuffers[renderTargetIdx], MemoryRequirement::HostVisible);
1245         }
1246
1247         // create vertexBuffer
1248         {
1249                 const vector<tcu::Vec4> vertices                        = genFullQuadVertices(1);
1250                 const VkDeviceSize              vertexBufferSize        = sizeInBytes(vertices);
1251
1252                 vertexBuffer                                                            = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1253                 vertexBufferAlloc                                                       = bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
1254
1255                 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
1256                 flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSize);
1257         }
1258
1259         // create colorImages (and msColorImages) using the configured attachmentsize
1260         for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1261         {
1262                 const VkImageUsageFlags colorImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
1263                 colorImages[renderTargetIdx]                    = makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType), COLOR_FORMAT,
1264                         attachmentSizes[renderTargetIdx], 1, colorImageUsage, false);
1265                 colorImageAllocs[renderTargetIdx]               = bindImage(vk, device, allocator, *colorImages[renderTargetIdx], MemoryRequirement::Any);
1266
1267                 if (caseDef.multisample)
1268                 {
1269                         const VkImageUsageFlags msImageUsage    = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1270
1271                         msColorImages[renderTargetIdx]                  = makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType), COLOR_FORMAT, attachmentSizes[renderTargetIdx], 1, msImageUsage, true);
1272                         msColorImageAllocs[renderTargetIdx]             = bindImage(vk, device, allocator, *msColorImages[renderTargetIdx], MemoryRequirement::Any);
1273                 }
1274         }
1275
1276         // create attachmentHandles. We use the renderSize for viewport and scissor
1277         for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1278         {
1279                 colorAttachments.push_back(makeSharedPtr(makeImageView(vk, device, ! caseDef.multisample ? *colorImages[renderTargetIdx] : *msColorImages[renderTargetIdx], imageViewType, COLOR_FORMAT, range)));
1280                 attachmentHandles.push_back(**colorAttachments.back());
1281         }
1282
1283         pipeline = makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, caseDef.renderSize, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0, numRenderTargets, caseDef.multisample);
1284
1285         // create framebuffer
1286         framebuffer = makeFramebuffer(vk, device, *renderPass, numRenderTargets, &attachmentHandles[0], static_cast<deUint32>(caseDef.renderSize.x()), static_cast<deUint32>(caseDef.renderSize.y()));
1287
1288         // record command buffer
1289         beginCommandBuffer(vk, *cmdBuffer);
1290
1291         // Clear image attachments
1292         for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1293         {
1294                 {
1295                         const VkImageMemoryBarrier      imageLayoutBarriers[]   =
1296                         {
1297                                 {
1298                                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                                                                                                 // VkStructureType                      sType;
1299                                         DE_NULL,                                                                                                                                                                // const void*                          pNext;
1300                                         0u,                                                                                                                                                                             // VkAccessFlags                        srcAccessMask;
1301                                         VK_ACCESS_TRANSFER_WRITE_BIT,                                                                                                                   // VkAccessFlags                        dstAccessMask;
1302                                         VK_IMAGE_LAYOUT_UNDEFINED,                                                                                                                              // VkImageLayout                        oldLayout;
1303                                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,                                                                                                   // VkImageLayout                        newLayout;
1304                                         VK_QUEUE_FAMILY_IGNORED,                                                                                                                                // deUint32                                     srcQueueFamilyIndex;
1305                                         VK_QUEUE_FAMILY_IGNORED,                                                                                                                                // deUint32                                     destQueueFamilyIndex;
1306                                         caseDef.multisample ? *msColorImages[renderTargetIdx] : *colorImages[renderTargetIdx],  // VkImage                                      image;
1307                                         range                                                                                                                                                                   // VkImageSubresourceRange      subresourceRange;
1308                                 },
1309                         };
1310
1311                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0u,
1312                                 0u, DE_NULL, 0u, DE_NULL, 1u, imageLayoutBarriers);
1313
1314                         vk.cmdClearColorImage(*cmdBuffer, caseDef.multisample ? *msColorImages[renderTargetIdx] : *colorImages[renderTargetIdx], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColors[renderTargetIdx], 1u, &range);
1315
1316                         const VkImageMemoryBarrier      imageClearBarriers[]    =
1317                         {
1318                                 {
1319                                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                                                                                                 // VkStructureType                      sType;
1320                                         DE_NULL,                                                                                                                                                                // const void*                          pNext;
1321                                         VK_ACCESS_TRANSFER_WRITE_BIT,                                                                                                                   // VkAccessFlags                        srcAccessMask;
1322                                         VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,                                                                                                    // VkAccessFlags                        dstAccessMask;
1323                                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,                                                                                                   // VkImageLayout                        oldLayout;
1324                                         VK_IMAGE_LAYOUT_GENERAL,                                                                                                                                // VkImageLayout                        newLayout;
1325                                         VK_QUEUE_FAMILY_IGNORED,                                                                                                                                // deUint32                                     srcQueueFamilyIndex;
1326                                         VK_QUEUE_FAMILY_IGNORED,                                                                                                                                // deUint32                                     destQueueFamilyIndex;
1327                                         caseDef.multisample ? *msColorImages[renderTargetIdx] : *colorImages[renderTargetIdx],  // VkImage                                      image;
1328                                         range                                                                                                                                                                   // VkImageSubresourceRange      subresourceRange;
1329                                 },
1330                         };
1331
1332                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, imageClearBarriers);
1333                 }
1334         }
1335
1336         // Render pass: this should render only to the area defined by renderSize (smaller than the size of the attachment)
1337         {
1338                 const VkRect2D                          renderArea                      =
1339                 {
1340                         makeOffset2D(0, 0),
1341                         makeExtent2D(caseDef.renderSize.x(), caseDef.renderSize.y()),
1342                 };
1343                 const VkRenderPassBeginInfo renderPassBeginInfo =
1344                 {
1345                         VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,       // VkStructureType         sType;
1346                         DE_NULL,                                                                        // const void*             pNext;
1347                         *renderPass,                                                            // VkRenderPass            renderPass;
1348                         *framebuffer,                                                           // VkFramebuffer           framebuffer;
1349                         renderArea,                                                                     // VkRect2D                renderArea;
1350                         0,                                                                                      // uint32_t                clearValueCount;
1351                         DE_NULL,                                                                        // const VkClearValue*     pClearValues;
1352                 };
1353                 const VkDeviceSize                      vertexBufferOffset      = 0ull;
1354
1355                 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1356                 {
1357                         vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1358                         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1359                         vk.cmdDraw(*cmdBuffer, 4u, 1u, 0u, 0u);
1360                 }
1361                 vk.cmdEndRenderPass(*cmdBuffer);
1362         }
1363
1364         // If we are using a multi-sampled render target (msColorImage), resolve it now (to colorImage)
1365         if (caseDef.multisample)
1366         {
1367                 for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1368                 {
1369                         // Transition msColorImage (from layout COLOR_ATTACHMENT_OPTIMAL) and colorImage (from layout UNDEFINED) to layout GENERAL before resolving
1370                         const VkImageMemoryBarrier      imageBarriers[] =
1371                         {
1372                                 {
1373                                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,         // VkStructureType                      sType;
1374                                         DE_NULL,                                                                        // const void*                          pNext;
1375                                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,           // VkAccessFlags                        srcAccessMask;
1376                                         VK_ACCESS_TRANSFER_READ_BIT,                            // VkAccessFlags                        dstAccessMask;
1377                                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,       // VkImageLayout                        oldLayout;
1378                                         VK_IMAGE_LAYOUT_GENERAL,                                        // VkImageLayout                        newLayout;
1379                                         VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                                     srcQueueFamilyIndex;
1380                                         VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                                     destQueueFamilyIndex;
1381                                         *msColorImages[renderTargetIdx],                        // VkImage                                      image;
1382                                         range                                                                           // VkImageSubresourceRange      subresourceRange;
1383                                 },
1384                                 {
1385                                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType                      sType;
1386                                         DE_NULL,                                                                // const void*                          pNext;
1387                                         (VkAccessFlags)0,                                               // VkAccessFlags                        srcAccessMask;
1388                                         VK_ACCESS_TRANSFER_WRITE_BIT,                   // VkAccessFlags                        dstAccessMask;
1389                                         VK_IMAGE_LAYOUT_UNDEFINED,                              // VkImageLayout                        oldLayout;
1390                                         VK_IMAGE_LAYOUT_GENERAL,                                // VkImageLayout                        newLayout;
1391                                         VK_QUEUE_FAMILY_IGNORED,                                // deUint32                                     srcQueueFamilyIndex;
1392                                         VK_QUEUE_FAMILY_IGNORED,                                // deUint32                                     destQueueFamilyIndex;
1393                                         *colorImages[renderTargetIdx],                  // VkImage                                      image;
1394                                         range                                                                   // VkImageSubresourceRange      subresourceRange;
1395                                 }
1396                         };
1397
1398                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1399                                 0u, DE_NULL, 0u, DE_NULL, 2u, imageBarriers);
1400
1401                         const VkImageResolve    region  =
1402                         {
1403                                 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1), // VkImageSubresourceLayers    srcSubresource;
1404                                 makeOffset3D(0, 0, 0),                                                                                  // VkOffset3D                  srcOffset;
1405                                 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1), // VkImageSubresourceLayers    dstSubresource;
1406                                 makeOffset3D(0, 0, 0),                                                                                  // VkOffset3D                  dstOffset;
1407                                 makeExtent3D(attachmentSizes[renderTargetIdx])                                  // VkExtent3D                  extent;
1408                         };
1409
1410                         vk.cmdResolveImage(*cmdBuffer, *msColorImages[renderTargetIdx], VK_IMAGE_LAYOUT_GENERAL, *colorImages[renderTargetIdx], VK_IMAGE_LAYOUT_GENERAL, 1, &region);
1411                 }
1412         }
1413
1414         for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1415         {
1416                 // copy colorImage to host visible colorBuffer
1417                 const VkImageMemoryBarrier      imageBarrier            =
1418                 {
1419                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                                                                                                         // VkStructureType                      sType;
1420                         DE_NULL,                                                                                                                                                                        // const void*                          pNext;
1421                         (vk::VkAccessFlags)(caseDef.multisample ? VK_ACCESS_TRANSFER_WRITE_BIT : VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
1422                         VK_ACCESS_TRANSFER_READ_BIT,                                                                                                                            // VkAccessFlags                        dstAccessMask;
1423                         caseDef.multisample ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,       // VkImageLayout                        oldLayout;
1424                         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,                                                                                                           // VkImageLayout                        newLayout;
1425                         VK_QUEUE_FAMILY_IGNORED,                                                                                                                                        // deUint32                                     srcQueueFamilyIndex;
1426                         VK_QUEUE_FAMILY_IGNORED,                                                                                                                                        // deUint32                                     destQueueFamilyIndex;
1427                         *colorImages[renderTargetIdx],                                                                                                                          // VkImage                                      image;
1428                         range                                                                                                                                                                           // VkImageSubresourceRange      subresourceRange;
1429                 };
1430
1431                 vk.cmdPipelineBarrier(*cmdBuffer, caseDef.multisample ? VK_PIPELINE_STAGE_TRANSFER_BIT : VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1432                         0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
1433
1434                 const VkBufferImageCopy         region                          =
1435                 {
1436                         0ull,                                                                                                                           // VkDeviceSize                bufferOffset;
1437                         0u,                                                                                                                                     // uint32_t                    bufferRowLength;
1438                         0u,                                                                                                                                     // uint32_t                    bufferImageHeight;
1439                         makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u),      // VkImageSubresourceLayers    imageSubresource;
1440                         makeOffset3D(0, 0, 0),                                                                                          // VkOffset3D                  imageOffset;
1441                         makeExtent3D(attachmentSizes[renderTargetIdx]),                                         // VkExtent3D                  imageExtent;
1442                 };
1443
1444                 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImages[renderTargetIdx], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffers[renderTargetIdx], 1u, &region);
1445
1446                 const VkBufferMemoryBarrier     bufferBarrier           =
1447                 {
1448                         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,        // VkStructureType    sType;
1449                         DE_NULL,                                                                        // const void*        pNext;
1450                         VK_ACCESS_TRANSFER_WRITE_BIT,                           // VkAccessFlags      srcAccessMask;
1451                         VK_ACCESS_HOST_READ_BIT,                                        // VkAccessFlags      dstAccessMask;
1452                         VK_QUEUE_FAMILY_IGNORED,                                        // uint32_t           srcQueueFamilyIndex;
1453                         VK_QUEUE_FAMILY_IGNORED,                                        // uint32_t           dstQueueFamilyIndex;
1454                         *colorBuffers[renderTargetIdx],                         // VkBuffer           buffer;
1455                         0ull,                                                                           // VkDeviceSize       offset;
1456                         VK_WHOLE_SIZE,                                                          // VkDeviceSize       size;
1457                 };
1458
1459                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
1460                         0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
1461         }
1462
1463         VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1464         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1465
1466         // Verify results
1467         for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1468         {
1469                 const tcu::TextureFormat                        format                          = mapVkFormat(COLOR_FORMAT);
1470                 const IVec3                                                     size                            = attachmentSizes[renderTargetIdx];
1471                 tcu::TextureLevel                                       textureLevel            (format, size.x(), size.y(), size.z());
1472                 const tcu::PixelBufferAccess            expectedImage           (textureLevel);
1473
1474                 const tcu::Vec4                                         expectedColors[]        =
1475                 {
1476                         tcu::Vec4(1.0f, 0.5f, 0.25f, 1.0f),
1477                         tcu::Vec4(0.5f, 1.0f, 0.25f, 1.0f),
1478                         tcu::Vec4(0.25f, 0.5f, 1.0, 1.0f)
1479                 };
1480
1481                 invalidateMappedMemoryRange(vk, device, colorBufferAllocs[renderTargetIdx]->getMemory(), colorBufferAllocs[renderTargetIdx]->getOffset(), VK_WHOLE_SIZE);
1482
1483                 for (int z = 0; z < expectedImage.getDepth(); ++z)
1484                 {
1485                         for (int y = 0; y < expectedImage.getHeight(); ++y)
1486                         {
1487                                 for (int x = 0; x < expectedImage.getWidth(); ++x)
1488                                 {
1489                                         if (x < caseDef.renderSize.x() && y < caseDef.renderSize.y() && z < caseDef.renderSize.z())
1490                                                 expectedImage.setPixel(expectedColors[renderTargetIdx], x, y, z);
1491                                         else
1492                                                 expectedImage.setPixel(tcu::Vec4(clearColors[renderTargetIdx].float32), x, y, z);
1493                                 }
1494                         }
1495                 }
1496                 const tcu::ConstPixelBufferAccess       resultImage             (format, size.x(), size.y(), size.z(), colorBufferAllocs[renderTargetIdx]->getHostPtr());
1497
1498                 if (!tcu::intThresholdCompare(context.getTestContext().getLog(), (std::string("Image Comparison of render target ") + de::toString(renderTargetIdx)).c_str(), "", expectedImage, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT))
1499                         return tcu::TestStatus::fail("Fail");
1500         }
1501
1502         return tcu::TestStatus::pass("Pass");
1503 }
1504
1505 void initDifferentAttachmentSizesPrograms (SourceCollections& programCollection, const CaseDef caseDef)
1506 {
1507         DE_UNREF(caseDef);
1508
1509         // Vertex shader
1510         {
1511                 std::ostringstream src;
1512                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1513                         << "\n"
1514                         << "layout(location = 0) in vec4 in_position;\n"
1515                         << "\n"
1516                         << "out gl_PerVertex {\n"
1517                         << "    vec4 gl_Position;\n"
1518                         << "};\n"
1519                         << "\n"
1520                         << "void main(void)\n"
1521                         << "{\n"
1522                         << "    gl_Position     = in_position;\n"
1523                         << "}\n";
1524
1525                 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1526         }
1527
1528         // Fragment shader
1529         {
1530                 std::ostringstream src;
1531                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1532                         << "\n"
1533                         << "layout(location = 0) out vec4 o_color0;\n"
1534                         << "layout(location = 1) out vec4 o_color1;\n"
1535                         << "layout(location = 2) out vec4 o_color2;\n"
1536                         << "\n"
1537                         << "void main(void)\n"
1538                         << "{\n"
1539                         << "    o_color0 = vec4(1.0,  0.5, 0.25, 1.0);\n"
1540                         << "    o_color1 = vec4(0.5,  1.0, 0.25, 1.0);\n"
1541                         << "    o_color2 = vec4(0.25, 0.5, 1.0,  1.0);\n"
1542                         << "}\n";
1543
1544                 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1545         }
1546 }
1547
1548 std::string getShortImageViewTypeName (const VkImageViewType imageViewType)
1549 {
1550         std::string     s       (getImageViewTypeName(imageViewType));
1551         return de::toLower(s.substr(19));
1552 }
1553
1554 std::string getSizeString (const CaseDef& caseDef)
1555 {
1556         std::ostringstream      str;
1557
1558                                                                                 str << caseDef.renderSize.x();
1559         if (caseDef.renderSize.y() > 1)         str << "x" << caseDef.renderSize.y();
1560         if (caseDef.renderSize.z() > 1)         str << "x" << caseDef.renderSize.z();
1561
1562                                                                                 str << "_" << caseDef.attachmentSize.x();
1563
1564         if (caseDef.attachmentSize.y() > 1)     str << "x" << caseDef.attachmentSize.y();
1565         if (caseDef.attachmentSize.z() > 1)     str << "x" << caseDef.attachmentSize.z();
1566         if (caseDef.numLayers > 1)                      str << "_" << caseDef.numLayers;
1567
1568         return str.str();
1569 }
1570
1571 std::string getTestCaseString (const CaseDef& caseDef)
1572 {
1573         std::ostringstream str;
1574
1575         str << getShortImageViewTypeName (caseDef.imageType).c_str();
1576         str << "_";
1577         str << getSizeString(caseDef);
1578
1579         if (caseDef.multisample)
1580                 str << "_ms";
1581
1582         return str.str();
1583 }
1584
1585 void addAttachmentTestCasesWithFunctions (tcu::TestCaseGroup* group)
1586 {
1587
1588         // Add test cases for attachment strictly sizes larger than the framebuffer
1589         const CaseDef   caseDef[]       =
1590         {
1591                 // Single-sample test cases
1592                 { VK_IMAGE_VIEW_TYPE_1D,                        IVec3(32, 1, 1),        IVec3(64, 1, 1),        1,              false },
1593                 { VK_IMAGE_VIEW_TYPE_1D,                        IVec3(32, 1, 1),        IVec3(48, 1, 1),        1,              false },
1594                 { VK_IMAGE_VIEW_TYPE_1D,                        IVec3(32, 1, 1),        IVec3(39, 1, 1),        1,              false },
1595                 { VK_IMAGE_VIEW_TYPE_1D,                        IVec3(19, 1, 1),        IVec3(32, 1, 1),        1,              false },
1596
1597                 { VK_IMAGE_VIEW_TYPE_1D_ARRAY,          IVec3(32, 1, 1),        IVec3(64, 1, 1),        4,              false },
1598                 { VK_IMAGE_VIEW_TYPE_1D_ARRAY,          IVec3(32, 1, 1),        IVec3(48, 1, 1),        4,              false },
1599                 { VK_IMAGE_VIEW_TYPE_1D_ARRAY,          IVec3(32, 1, 1),        IVec3(39, 1, 1),        4,              false },
1600                 { VK_IMAGE_VIEW_TYPE_1D_ARRAY,          IVec3(19, 1, 1),        IVec3(32, 1, 1),        4,              false },
1601
1602                 { VK_IMAGE_VIEW_TYPE_2D,                        IVec3(32, 32, 1),       IVec3(64, 64, 1),       1,              false },
1603                 { VK_IMAGE_VIEW_TYPE_2D,                        IVec3(32, 32, 1),       IVec3(48, 48, 1),       1,              false },
1604                 { VK_IMAGE_VIEW_TYPE_2D,                        IVec3(32, 32, 1),       IVec3(39, 41, 1),       1,              false },
1605                 { VK_IMAGE_VIEW_TYPE_2D,                        IVec3(19, 27, 1),       IVec3(32, 32, 1),       1,              false },
1606
1607                 { VK_IMAGE_VIEW_TYPE_2D_ARRAY,          IVec3(32, 32, 1),       IVec3(64, 64, 1),       4,              false },
1608                 { VK_IMAGE_VIEW_TYPE_2D_ARRAY,          IVec3(32, 32, 1),       IVec3(48, 48, 1),       4,              false },
1609                 { VK_IMAGE_VIEW_TYPE_2D_ARRAY,          IVec3(32, 32, 1),       IVec3(39, 41, 1),       4,              false },
1610                 { VK_IMAGE_VIEW_TYPE_2D_ARRAY,          IVec3(19, 27, 1),       IVec3(32, 32, 1),       4,              false },
1611
1612                 { VK_IMAGE_VIEW_TYPE_CUBE,                      IVec3(32, 32, 1),       IVec3(64, 64, 1),       6,              false },
1613                 { VK_IMAGE_VIEW_TYPE_CUBE,                      IVec3(32, 32, 1),       IVec3(48, 48, 1),       6,              false },
1614                 { VK_IMAGE_VIEW_TYPE_CUBE,                      IVec3(32, 32, 1),       IVec3(39, 41, 1),       6,              false },
1615                 { VK_IMAGE_VIEW_TYPE_CUBE,                      IVec3(19, 27, 1),       IVec3(32, 32, 1),       6,              false },
1616
1617                 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,        IVec3(32, 32, 1),       IVec3(64, 64, 1),       6*2,    false },
1618                 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,        IVec3(32, 32, 1),       IVec3(48, 48, 1),       6*2,    false },
1619                 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,        IVec3(32, 32, 1),       IVec3(39, 41, 1),       6*2,    false },
1620                 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,        IVec3(19, 27, 1),       IVec3(32, 32, 1),       6*2,    false },
1621
1622                 // Multi-sample test cases
1623                 { VK_IMAGE_VIEW_TYPE_2D,                        IVec3(32, 32, 1),       IVec3(64, 64, 1),       1,              true },
1624                 { VK_IMAGE_VIEW_TYPE_2D,                        IVec3(32, 32, 1),       IVec3(48, 48, 1),       1,              true },
1625                 { VK_IMAGE_VIEW_TYPE_2D,                        IVec3(32, 32, 1),       IVec3(39, 41, 1),       1,              true },
1626                 { VK_IMAGE_VIEW_TYPE_2D,                        IVec3(19, 27, 1),       IVec3(32, 32, 1),       1,              true },
1627
1628                 { VK_IMAGE_VIEW_TYPE_2D_ARRAY,          IVec3(32, 32, 1),       IVec3(64, 64, 1),       4,              true },
1629                 { VK_IMAGE_VIEW_TYPE_2D_ARRAY,          IVec3(32, 32, 1),       IVec3(48, 48, 1),       4,              true },
1630                 { VK_IMAGE_VIEW_TYPE_2D_ARRAY,          IVec3(32, 32, 1),       IVec3(39, 41, 1),       4,              true },
1631                 { VK_IMAGE_VIEW_TYPE_2D_ARRAY,          IVec3(19, 27, 1),       IVec3(32, 32, 1),       4,              true },
1632         };
1633
1634         for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(caseDef); ++sizeNdx)
1635                 addFunctionCaseWithPrograms(group, getTestCaseString(caseDef[sizeNdx]).c_str(), "", initColorPrograms, test, caseDef[sizeNdx]);
1636
1637         // Add tests for the case where there are no color attachments but the
1638         // fragment shader writes to an image via imageStore().
1639         addFunctionCaseWithPrograms(group, "no_attachments", "", initImagePrograms, testNoAtt, false);
1640         addFunctionCaseWithPrograms(group, "no_attachments_ms", "", initImagePrograms, testNoAtt, true);
1641
1642         const CaseDef   differentAttachmentSizesCaseDef[]       =
1643         {
1644                 // Single-sample test cases
1645                 { VK_IMAGE_VIEW_TYPE_1D,        IVec3(32, 1, 1),        IVec3(64, 1, 1),        1,      false },
1646                 { VK_IMAGE_VIEW_TYPE_1D,        IVec3(32, 1, 1),        IVec3(48, 1, 1),        1,      false },
1647                 { VK_IMAGE_VIEW_TYPE_1D,        IVec3(32, 1, 1),        IVec3(39, 1, 1),        1,      false },
1648                 { VK_IMAGE_VIEW_TYPE_1D,        IVec3(19, 1, 1),        IVec3(32, 1, 1),        1,      false },
1649
1650                 { VK_IMAGE_VIEW_TYPE_2D,        IVec3(32, 32, 1),       IVec3(64, 64, 1),       1,      false },
1651                 { VK_IMAGE_VIEW_TYPE_2D,        IVec3(32, 32, 1),       IVec3(48, 48, 1),       1,      false },
1652                 { VK_IMAGE_VIEW_TYPE_2D,        IVec3(32, 32, 1),       IVec3(39, 41, 1),       1,      false },
1653                 { VK_IMAGE_VIEW_TYPE_2D,        IVec3(19, 27, 1),       IVec3(32, 32, 1),       1,      false },
1654
1655                 // Multi-sample test cases
1656                 { VK_IMAGE_VIEW_TYPE_2D,        IVec3(32, 32, 1),       IVec3(64, 64, 1),       1,      true },
1657                 { VK_IMAGE_VIEW_TYPE_2D,        IVec3(32, 32, 1),       IVec3(48, 48, 1),       1,      true },
1658                 { VK_IMAGE_VIEW_TYPE_2D,        IVec3(32, 32, 1),       IVec3(39, 41, 1),       1,      true },
1659                 { VK_IMAGE_VIEW_TYPE_2D,        IVec3(19, 27, 1),       IVec3(32, 32, 1),       1,      true }
1660         };
1661
1662         for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(differentAttachmentSizesCaseDef); ++sizeNdx)
1663                 addFunctionCaseWithPrograms(group, (std::string("diff_attachments_") + getTestCaseString(differentAttachmentSizesCaseDef[sizeNdx])).c_str(), "", initDifferentAttachmentSizesPrograms, testDifferentAttachmentSizes, differentAttachmentSizesCaseDef[sizeNdx]);
1664 }
1665
1666 } // anonymous ns
1667
1668 tcu::TestCaseGroup* createFramebufferAttachmentTests (tcu::TestContext& testCtx)
1669 {
1670         return createTestGroup(testCtx, "framebuffer_attachment", "Framebuffer attachment tests", addAttachmentTestCasesWithFunctions);
1671 }
1672
1673 } // pipeline
1674 } // vkt