Fix tests in dEQP-EGL.functional.robustness* am: fd0b6eda1c am: d3ac80fae5 am: 54c4090dfe
[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 bool                                   hasAttachments,
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         const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
331         {
332                 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,       // VkStructureType                                                              sType;
333                 DE_NULL,                                                                                                        // const void*                                                                  pNext;
334                 (VkPipelineColorBlendStateCreateFlags)0,                                        // VkPipelineColorBlendStateCreateFlags                 flags;
335                 VK_FALSE,                                                                                                       // VkBool32                                                                             logicOpEnable;
336                 VK_LOGIC_OP_COPY,                                                                                       // VkLogicOp                                                                    logicOp;
337                 hasAttachments ? 1u : 0u,                                                                       // deUint32                                                                             attachmentCount;
338                 &pipelineColorBlendAttachmentState,                                                     // const VkPipelineColorBlendAttachmentState*   pAttachments;
339                 { 0.0f, 0.0f, 0.0f, 0.0f },                                                                     // float                                                                                blendConstants[4];
340         };
341
342         const VkPipelineShaderStageCreateInfo pShaderStages[] =
343         {
344                 {
345                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    // VkStructureType                                              sType;
346                         DE_NULL,                                                                                                // const void*                                                  pNext;
347                         (VkPipelineShaderStageCreateFlags)0,                                    // VkPipelineShaderStageCreateFlags             flags;
348                         VK_SHADER_STAGE_VERTEX_BIT,                                                             // VkShaderStageFlagBits                                stage;
349                         vertexModule,                                                                                   // VkShaderModule                                               module;
350                         "main",                                                                                                 // const char*                                                  pName;
351                         DE_NULL,                                                                                                // const VkSpecializationInfo*                  pSpecializationInfo;
352                 },
353                 {
354                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    // VkStructureType                                              sType;
355                         DE_NULL,                                                                                                // const void*                                                  pNext;
356                         (VkPipelineShaderStageCreateFlags)0,                                    // VkPipelineShaderStageCreateFlags             flags;
357                         VK_SHADER_STAGE_FRAGMENT_BIT,                                                   // VkShaderStageFlagBits                                stage;
358                         fragmentModule,                                                                                 // VkShaderModule                                               module;
359                         "main",                                                                                                 // const char*                                                  pName;
360                         DE_NULL,                                                                                                // const VkSpecializationInfo*                  pSpecializationInfo;
361                 }
362         };
363
364         const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
365         {
366                 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,        // VkStructureType                                                                      sType;
367                 DE_NULL,                                                                                        // const void*                                                                          pNext;
368                 (VkPipelineCreateFlags)0,                                                       // VkPipelineCreateFlags                                                        flags;
369                 DE_LENGTH_OF_ARRAY(pShaderStages),                                      // deUint32                                                                                     stageCount;
370                 pShaderStages,                                                                          // const VkPipelineShaderStageCreateInfo*                       pStages;
371                 &vertexInputStateInfo,                                                          // const VkPipelineVertexInputStateCreateInfo*          pVertexInputState;
372                 &pipelineInputAssemblyStateInfo,                                        // const VkPipelineInputAssemblyStateCreateInfo*        pInputAssemblyState;
373                 DE_NULL,                                                                                        // const VkPipelineTessellationStateCreateInfo*         pTessellationState;
374                 &pipelineViewportStateInfo,                                                     // const VkPipelineViewportStateCreateInfo*                     pViewportState;
375                 &pipelineRasterizationStateInfo,                                        // const VkPipelineRasterizationStateCreateInfo*        pRasterizationState;
376                 &pipelineMultisampleStateInfo,                                          // const VkPipelineMultisampleStateCreateInfo*          pMultisampleState;
377                 &pipelineDepthStencilStateInfo,                                         // const VkPipelineDepthStencilStateCreateInfo*         pDepthStencilState;
378                 &pipelineColorBlendStateInfo,                                           // const VkPipelineColorBlendStateCreateInfo*           pColorBlendState;
379                 DE_NULL,                                                                                        // const VkPipelineDynamicStateCreateInfo*                      pDynamicState;
380                 pipelineLayout,                                                                         // VkPipelineLayout                                                                     layout;
381                 renderPass,                                                                                     // VkRenderPass                                                                         renderPass;
382                 subpass,                                                                                        // deUint32                                                                                     subpass;
383                 DE_NULL,                                                                                        // VkPipeline                                                                           basePipelineHandle;
384                 0,                                                                                                      // deInt32                                                                                      basePipelineIndex;
385         };
386
387         return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
388 }
389
390 Move<VkImage> makeImage (const DeviceInterface&         vk,
391                                                  const VkDevice                         device,
392                                                  const VkImageCreateFlags       flags,
393                                                  const VkImageType                      imageType,
394                                                  const VkFormat                         format,
395                                                  const IVec3&                           size,
396                                                  const deUint32                         numLayers,
397                                                  const VkImageUsageFlags        usage,
398                                                  const bool                                     multisample)
399 {
400         const VkImageCreateInfo imageParams =
401         {
402                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                                    // VkStructureType                      sType;
403                 DE_NULL,                                                                                                                // const void*                          pNext;
404                 flags,                                                                                                                  // VkImageCreateFlags           flags;
405                 imageType,                                                                                                              // VkImageType                          imageType;
406                 format,                                                                                                                 // VkFormat                                     format;
407                 makeExtent3D(size),                                                                                             // VkExtent3D                           extent;
408                 1u,                                                                                                                             // deUint32                                     mipLevels;
409                 numLayers,                                                                                                              // deUint32                                     arrayLayers;
410                 multisample ? VK_SAMPLE_COUNT_4_BIT : VK_SAMPLE_COUNT_1_BIT,    // VkSampleCountFlagBits        samples;
411                 VK_IMAGE_TILING_OPTIMAL,                                                                                // VkImageTiling                        tiling;
412                 usage,                                                                                                                  // VkImageUsageFlags            usage;
413                 VK_SHARING_MODE_EXCLUSIVE,                                                                              // VkSharingMode                        sharingMode;
414                 0u,                                                                                                                             // deUint32                                     queueFamilyIndexCount;
415                 DE_NULL,                                                                                                                // const deUint32*                      pQueueFamilyIndices;
416                 VK_IMAGE_LAYOUT_UNDEFINED,                                                                              // VkImageLayout                        initialLayout;
417         };
418
419         return createImage(vk, device, &imageParams);
420 }
421
422 vector<tcu::Vec4> genFullQuadVertices (const int subpassCount)
423 {
424         vector<tcu::Vec4>       vectorData;
425         for (int subpassNdx = 0; subpassNdx < subpassCount; ++subpassNdx)
426         {
427                 vectorData.push_back(Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
428                 vectorData.push_back(Vec4(-1.0f,  1.0f, 0.0f, 1.0f));
429                 vectorData.push_back(Vec4(1.0f, -1.0f, 0.0f, 1.0f));
430                 vectorData.push_back(Vec4(1.0f,  1.0f, 0.0f, 1.0f));
431         }
432         return vectorData;
433 }
434
435 void initColorPrograms (SourceCollections& programCollection, const CaseDef caseDef)
436 {
437         (void)caseDef;
438
439         // Vertex shader
440         {
441                 std::ostringstream src;
442                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
443                         << "\n"
444                         << "layout(location = 0) in vec4 in_position;\n"
445                         << "\n"
446                         << "out gl_PerVertex {\n"
447                         << "    vec4 gl_Position;\n"
448                         << "};\n"
449                         << "\n"
450                         << "void main(void)\n"
451                         << "{\n"
452                         << "    gl_Position     = in_position;\n"
453                         << "}\n";
454
455                 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
456         }
457
458         // Fragment shader
459         {
460                 std::ostringstream src;
461                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
462                         << "\n"
463                         << "layout(location = 0) out vec4 o_color;\n"
464                         << "\n"
465                         << "void main(void)\n"
466                         << "{\n"
467                         << "    o_color = vec4(1.0, 0.5, 0.25, 1.0);\n"
468                         << "}\n";
469
470                 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
471         }
472 }
473
474 tcu::PixelBufferAccess getExpectedData (tcu::TextureLevel& textureLevel, const CaseDef& caseDef)
475 {
476         const tcu::PixelBufferAccess    expectedImage   (textureLevel);
477         const int                                               renderDepth             = deMax32(caseDef.renderSize.z(), caseDef.numLayers);
478
479         for (int z = 0; z < expectedImage.getDepth(); ++z)
480         {
481                 for (int y = 0; y < expectedImage.getHeight(); ++y)
482                 {
483                         for (int x = 0; x < expectedImage.getWidth(); ++x)
484                         {
485                                 if (x < caseDef.renderSize.x() && y < caseDef.renderSize.y() && z < renderDepth)
486                                         expectedImage.setPixel(tcu::Vec4(1.0, 0.5, 0.25, 1.0), x, y, z);
487                                 else
488                                         expectedImage.setPixel(tcu::Vec4(0.0, 0.0, 0.0, 1.0), x, y, z);
489                         }
490                 }
491         }
492         return expectedImage;
493 }
494
495 inline Move<VkBuffer> makeBuffer (const DeviceInterface& vk, const VkDevice device, const VkDeviceSize bufferSize, const VkBufferUsageFlags usage)
496 {
497         const VkBufferCreateInfo        bufferCreateInfo        = makeBufferCreateInfo(bufferSize, usage);
498         return createBuffer(vk, device, &bufferCreateInfo);
499 }
500
501 inline VkImageSubresourceRange makeColorSubresourceRange (const deUint32 baseArrayLayer, const deUint32 layerCount)
502 {
503         return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, baseArrayLayer, layerCount);
504 }
505
506 // Tests rendering to a a framebuffer with color attachments larger than the
507 // framebuffer dimensions and verifies that rendering does not affect the areas
508 // of the attachment outside the framebuffer dimensions. Tests both single-sample
509 // and multi-sample configurations.
510 tcu::TestStatus test (Context& context, const CaseDef caseDef)
511 {
512         const DeviceInterface&                  vk                                      = context.getDeviceInterface();
513         const VkDevice                                  device                          = context.getDevice();
514         const VkQueue                                   queue                           = context.getUniversalQueue();
515         const deUint32                                  queueFamilyIndex        = context.getUniversalQueueFamilyIndex();
516         Allocator&                                              allocator                       = context.getDefaultAllocator();
517
518         // Color image for rendering in single-sample tests or resolve target for multi-sample tests
519         Move<VkImage>                                   colorImage;
520         MovePtr<Allocation>                             colorImageAlloc;
521
522         // For multisampled tests, this is the rendering target
523         Move<VkImage>                                   msColorImage;
524         MovePtr<Allocation>                             msColorImageAlloc;
525
526         // Host memory buffer where we will copy the rendered image for verification
527         const deUint32                                  att_size_x                      = caseDef.attachmentSize.x();
528         const deUint32                                  att_size_y                      = caseDef.attachmentSize.y();
529         const deUint32                                  att_size_z                      = caseDef.attachmentSize.z();
530         const VkDeviceSize                              colorBufferSize         = att_size_x * att_size_y * att_size_z * caseDef.numLayers * tcu::getPixelSize(mapVkFormat(COLOR_FORMAT));
531         const Unique<VkBuffer>                  colorBuffer                     (makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
532         const UniquePtr<Allocation>             colorBufferAlloc        (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
533
534         Move<VkBuffer>                                  vertexBuffer;
535         MovePtr<Allocation>                             vertexBufferAlloc;
536
537         vector<SharedPtrVkImageView>    colorAttachments;
538         vector<VkImageView>                             attachmentHandles;
539
540         const Unique<VkPipelineLayout>  pipelineLayout          (makePipelineLayout(vk, device));
541         vector<SharedPtrVkPipeline>             pipeline;
542         const Unique<VkRenderPass>              renderPass                      (makeRenderPass(vk, device, COLOR_FORMAT, caseDef.numLayers, caseDef.multisample));
543         Move<VkFramebuffer>                             framebuffer;
544
545         const Unique<VkShaderModule>    vertexModule            (createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u));
546         const Unique<VkShaderModule>    fragmentModule          (createShaderModule(vk, device, context.getBinaryCollection().get("frag"), 0u));
547
548         const Unique<VkCommandPool>             cmdPool                         (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
549         const Unique<VkCommandBuffer>   cmdBuffer                       (makeCommandBuffer(vk, device, *cmdPool));
550
551         const VkImageViewType                   imageViewType           = caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE || caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY
552                 ? VK_IMAGE_VIEW_TYPE_2D : caseDef.imageType;
553
554         // create vertexBuffer
555         {
556                 const vector<tcu::Vec4> vertices                        = genFullQuadVertices(caseDef.numLayers);
557                 const VkDeviceSize              vertexBufferSize        = sizeInBytes(vertices);
558
559                 vertexBuffer            = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
560                 vertexBufferAlloc       = bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
561
562                 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
563                 flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSize);
564         }
565
566         // create colorImage (and msColorImage) using the configured attachmentsize
567         {
568                 const VkImageUsageFlags colorImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
569
570                 colorImage              = makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType), COLOR_FORMAT,
571                         caseDef.attachmentSize, caseDef.numLayers, colorImageUsage, false);
572                 colorImageAlloc = bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any);
573
574                 if (caseDef.multisample)
575                 {
576                         const VkImageUsageFlags msImageUsage    = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
577
578                         msColorImage            = makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType), COLOR_FORMAT,
579                                 caseDef.attachmentSize, caseDef.numLayers, msImageUsage, true);
580                         msColorImageAlloc       = bindImage(vk, device, allocator, *msColorImage, MemoryRequirement::Any);
581                 }
582         }
583
584         // create attachmentHandles and pipelines (one for each layer). We use the renderSize for viewport and scissor
585         for (deUint32 layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx)
586         {
587                 colorAttachments.push_back(makeSharedPtr(makeImageView(vk, device, ! caseDef.multisample ? *colorImage : *msColorImage,
588                         imageViewType, COLOR_FORMAT, makeColorSubresourceRange(layerNdx, 1))));
589                 attachmentHandles.push_back(**colorAttachments.back());
590
591                 pipeline.push_back(makeSharedPtr(makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule,
592                         caseDef.renderSize, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, layerNdx, true, caseDef.multisample)));
593         }
594
595         // create framebuffer
596         framebuffer = makeFramebuffer(vk, device, *renderPass, caseDef.numLayers, &attachmentHandles[0],
597                 static_cast<deUint32>(caseDef.renderSize.x()), static_cast<deUint32>(caseDef.renderSize.y()));
598
599         // record command buffer
600         beginCommandBuffer(vk, *cmdBuffer);
601         {
602                 // Clear the entire image attachment to black
603                 {
604                         const VkImageMemoryBarrier      imageLayoutBarriers[]   =
605                         {
606                                 {
607                                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                         // VkStructureType                      sType;
608                                         DE_NULL,                                                                                        // const void*                          pNext;
609                                         0u,                                                                                                     // VkAccessFlags                        srcAccessMask;
610                                         VK_ACCESS_TRANSFER_WRITE_BIT,                                           // VkAccessFlags                        dstAccessMask;
611                                         VK_IMAGE_LAYOUT_UNDEFINED,                                                      // VkImageLayout                        oldLayout;
612                                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,                           // VkImageLayout                        newLayout;
613                                         VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     srcQueueFamilyIndex;
614                                         VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     destQueueFamilyIndex;
615                                         caseDef.multisample ? *msColorImage : *colorImage,      // VkImage                                      image;
616                                         makeColorSubresourceRange(0, caseDef.numLayers)         // VkImageSubresourceRange      subresourceRange;
617                                 },
618                         };
619
620                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0u,
621                                 0u, DE_NULL, 0u, DE_NULL, 1u, imageLayoutBarriers);
622
623                         const VkImageSubresourceRange   ranges          = makeColorSubresourceRange(0, caseDef.numLayers);
624                         const VkClearColorValue                 clearColor      =
625                 {
626                 {0.0f, 0.0f, 0.0f, 1.0f}
627                         };
628                         vk.cmdClearColorImage(*cmdBuffer, caseDef.multisample ? *msColorImage : *colorImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor, 1u, &ranges);
629
630                         const VkImageMemoryBarrier      imageClearBarriers[]    =
631                         {
632                                 {
633                                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                         // VkStructureType                      sType;
634                                         DE_NULL,                                                                                        // const void*                          pNext;
635                                         VK_ACCESS_TRANSFER_WRITE_BIT,                                           // VkAccessFlags                        srcAccessMask;
636                                         VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,                            // VkAccessFlags                        dstAccessMask;
637                                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,                           // VkImageLayout                        oldLayout;
638                                         VK_IMAGE_LAYOUT_GENERAL,                                                        // VkImageLayout                        newLayout;
639                                         VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     srcQueueFamilyIndex;
640                                         VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     destQueueFamilyIndex;
641                                         caseDef.multisample ? *msColorImage : *colorImage,      // VkImage                                      image;
642                                         makeColorSubresourceRange(0, caseDef.numLayers)         // VkImageSubresourceRange      subresourceRange;
643                                 },
644                         };
645
646                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u,
647                                 0u, DE_NULL, 0u, DE_NULL, 1u, imageClearBarriers);
648                 }
649
650                 // Render pass: this should render only to the area defined by renderSize (smaller than the size of the attachment)
651                 {
652                         const VkRect2D                          renderArea                      =
653                         {
654                                 makeOffset2D(0, 0),
655                                 makeExtent2D(caseDef.renderSize.x(), caseDef.renderSize.y()),
656                         };
657                         const VkRenderPassBeginInfo renderPassBeginInfo =
658                         {
659                                 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,       // VkStructureType         sType;
660                                 DE_NULL,                                                                        // const void*             pNext;
661                                 *renderPass,                                                            // VkRenderPass            renderPass;
662                                 *framebuffer,                                                           // VkFramebuffer           framebuffer;
663                                 renderArea,                                                                     // VkRect2D                renderArea;
664                                 0,                                                                                      // uint32_t                clearValueCount;
665                                 DE_NULL,                                                                        // const VkClearValue*     pClearValues;
666                         };
667                         const VkDeviceSize                      vertexBufferOffset      = 0ull;
668
669                         vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
670                         {
671                                 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
672                                 for (deUint32 layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx)
673                                 {
674                                         if (layerNdx != 0)
675                                                 vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
676
677                                         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipeline[layerNdx]);
678                                         vk.cmdDraw(*cmdBuffer, 4u, 1u, layerNdx*4u, 0u);
679                                 }
680                         }
681                         vk.cmdEndRenderPass(*cmdBuffer);
682                 }
683
684                 // If we are using a multi-sampled render target (msColorImage), resolve it now (to colorImage)
685                 if (caseDef.multisample)
686                 {
687                         // Transition msColorImage (from layout COLOR_ATTACHMENT_OPTIMAL) and colorImage (from layout UNDEFINED) to layout GENERAL before resolving
688                         const VkImageMemoryBarrier      imageBarriers[] =
689                         {
690                                 {
691                                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                 // VkStructureType                      sType;
692                                         DE_NULL,                                                                                // const void*                          pNext;
693                                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                   // VkAccessFlags                        srcAccessMask;
694                                         VK_ACCESS_TRANSFER_READ_BIT,                                    // VkAccessFlags                        dstAccessMask;
695                                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,               // VkImageLayout                        oldLayout;
696                                         VK_IMAGE_LAYOUT_GENERAL,                                                // VkImageLayout                        newLayout;
697                                         VK_QUEUE_FAMILY_IGNORED,                                                // deUint32                                     srcQueueFamilyIndex;
698                                         VK_QUEUE_FAMILY_IGNORED,                                                // deUint32                                     destQueueFamilyIndex;
699                                         *msColorImage,                                                                  // VkImage                                      image;
700                                         makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange      subresourceRange;
701                                 },
702                                 {
703                                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                 // VkStructureType                      sType;
704                                         DE_NULL,                                                                                // const void*                          pNext;
705                                         (VkAccessFlags)0,                                                               // VkAccessFlags                        srcAccessMask;
706                                         VK_ACCESS_TRANSFER_WRITE_BIT,                                   // VkAccessFlags                        dstAccessMask;
707                                         VK_IMAGE_LAYOUT_UNDEFINED,                                              // VkImageLayout                        oldLayout;
708                                         VK_IMAGE_LAYOUT_GENERAL,                                                // VkImageLayout                        newLayout;
709                                         VK_QUEUE_FAMILY_IGNORED,                                                // deUint32                                     srcQueueFamilyIndex;
710                                         VK_QUEUE_FAMILY_IGNORED,                                                // deUint32                                     destQueueFamilyIndex;
711                                         *colorImage,                                                                    // VkImage                                      image;
712                                         makeColorSubresourceRange(0, caseDef.numLayers) // VkImageSubresourceRange      subresourceRange;
713                                 }
714                         };
715
716                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0u,
717                                 0u, DE_NULL, 0u, DE_NULL, 2u, imageBarriers);
718
719                         const VkImageResolve    region  =
720                         {
721                                 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, caseDef.numLayers), // VkImageSubresourceLayers    srcSubresource;
722                                 makeOffset3D(0, 0, 0),                                                                                                                  // VkOffset3D                  srcOffset;
723                                 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, caseDef.numLayers), // VkImageSubresourceLayers    dstSubresource;
724                                 makeOffset3D(0, 0, 0),                                                                                                                  // VkOffset3D                  dstOffset;
725                                 makeExtent3D(caseDef.attachmentSize)                                                                                    // VkExtent3D                  extent;
726                         };
727
728                         vk.cmdResolveImage(*cmdBuffer, *msColorImage, VK_IMAGE_LAYOUT_GENERAL, *colorImage, VK_IMAGE_LAYOUT_GENERAL, 1, &region);
729                 }
730
731                 // copy colorImage to host visible colorBuffer
732                 {
733                         const VkImageMemoryBarrier      imageBarriers[]         =
734                         {
735                                 {
736                                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                                                                                                         // VkStructureType                      sType;
737                                         DE_NULL,                                                                                                                                                                        // const void*                          pNext;
738                                         (vk::VkAccessFlags)(caseDef.multisample ? VK_ACCESS_TRANSFER_WRITE_BIT : VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
739                                         VK_ACCESS_TRANSFER_READ_BIT,                                                                                                                            // VkAccessFlags                        dstAccessMask;
740                                         caseDef.multisample ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,       // VkImageLayout                        oldLayout;
741                                         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,                                                                                                           // VkImageLayout                        newLayout;
742                                         VK_QUEUE_FAMILY_IGNORED,                                                                                                                                        // deUint32                                     srcQueueFamilyIndex;
743                                         VK_QUEUE_FAMILY_IGNORED,                                                                                                                                        // deUint32                                     destQueueFamilyIndex;
744                                         *colorImage,                                                                                                                                                            // VkImage                                      image;
745                                         makeColorSubresourceRange(0, caseDef.numLayers)                                                                                         // VkImageSubresourceRange      subresourceRange;
746                                 }
747                         };
748
749                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
750                                 0u, DE_NULL, 0u, DE_NULL, 1u, imageBarriers);
751
752                         const VkBufferImageCopy         region                          =
753                         {
754                                 0ull,                                                                                                                                                           // VkDeviceSize                bufferOffset;
755                                 0u,                                                                                                                                                                     // uint32_t                    bufferRowLength;
756                                 0u,                                                                                                                                                                     // uint32_t                    bufferImageHeight;
757                                 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, caseDef.numLayers),       // VkImageSubresourceLayers    imageSubresource;
758                                 makeOffset3D(0, 0, 0),                                                                                                                          // VkOffset3D                  imageOffset;
759                                 makeExtent3D(caseDef.attachmentSize),                                                                                           // VkExtent3D                  imageExtent;
760                         };
761
762                         vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, &region);
763
764                         const VkBufferMemoryBarrier     bufferBarriers[]        =
765                         {
766                                 {
767                                         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,        // VkStructureType    sType;
768                                         DE_NULL,                                                                        // const void*        pNext;
769                                         VK_ACCESS_TRANSFER_WRITE_BIT,                           // VkAccessFlags      srcAccessMask;
770                                         VK_ACCESS_HOST_READ_BIT,                                        // VkAccessFlags      dstAccessMask;
771                                         VK_QUEUE_FAMILY_IGNORED,                                        // uint32_t           srcQueueFamilyIndex;
772                                         VK_QUEUE_FAMILY_IGNORED,                                        // uint32_t           dstQueueFamilyIndex;
773                                         *colorBuffer,                                                           // VkBuffer           buffer;
774                                         0ull,                                                                           // VkDeviceSize       offset;
775                                         VK_WHOLE_SIZE,                                                          // VkDeviceSize       size;
776                                 },
777                         };
778
779                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
780                                 0u, DE_NULL, DE_LENGTH_OF_ARRAY(bufferBarriers), bufferBarriers, 0u, DE_NULL);
781                 }
782         } // beginCommandBuffer
783
784         VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
785         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
786
787         // Verify results
788         {
789                 invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
790                 const tcu::TextureFormat                        format                  = mapVkFormat(COLOR_FORMAT);
791                 const int                                                       depth                   = deMax32(caseDef.attachmentSize.z(), caseDef.numLayers);
792                 tcu::TextureLevel                                       textureLevel    (format, caseDef.attachmentSize.x(), caseDef.attachmentSize.y(), depth);
793                 const tcu::PixelBufferAccess            expectedImage   = getExpectedData(textureLevel, caseDef);
794                 const tcu::ConstPixelBufferAccess       resultImage             (format, caseDef.attachmentSize.x(), caseDef.attachmentSize.y(), depth, colorBufferAlloc->getHostPtr());
795
796                 if (!tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT))
797                         return tcu::TestStatus::fail("Fail");
798         }
799
800         return tcu::TestStatus::pass("Pass");
801 }
802
803 void initImagePrograms (SourceCollections& programCollection, const bool multisample)
804 {
805         // Vertex shader
806         {
807                 std::ostringstream src;
808                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
809                         << "\n"
810                         << "layout(location = 0) in vec4 in_position;\n"
811                         << "\n"
812                         << "out gl_PerVertex {\n"
813                         << "    vec4 gl_Position;\n"
814                         << "};\n"
815                         << "\n"
816                         << "void main(void)\n"
817                         << "{\n"
818                         << "    gl_Position     = in_position;\n"
819                         << "}\n";
820
821                 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
822         }
823
824         // Fragment shader
825         {
826                 std::ostringstream src;
827                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
828                         << "\n"
829                         << "layout(binding = 0, rgba8) writeonly uniform image2D image;\n"
830                         << "\n"
831                         << "void main(void)\n"
832                         << "{\n";
833                         if (!multisample)
834                                 src << "    imageStore(image, ivec2(gl_PrimitiveID % 4, 0), vec4(1.0, 0.5, 0.25, 1.0));\n";
835                         else
836                                 src << "    imageStore(image, ivec2(gl_PrimitiveID % 4, gl_SampleID % 4), vec4(1.0, 0.5, 0.25, 1.0));\n";
837                         src << "}\n";
838
839                 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
840         }
841 }
842
843 //! Make a render pass with no attachments
844 Move<VkRenderPass> makeRenderPassNoAtt (const DeviceInterface& vk, const VkDevice device)
845 {
846         // Create a single subpass with no attachment references
847         vector<VkSubpassDescription>    subpasses;
848
849         const VkSubpassDescription              subpassDescription      =
850         {
851                 (VkSubpassDescriptionFlags)0,           // VkSubpassDescriptionFlags            flags;
852                 VK_PIPELINE_BIND_POINT_GRAPHICS,        // VkPipelineBindPoint                          pipelineBindPoint;
853                 0u,                                                                     // deUint32                                                     inputAttachmentCount;
854                 DE_NULL,                                                        // const VkAttachmentReference*         pInputAttachments;
855                 0u,                                                                     // deUint32                                                     colorAttachmentCount;
856                 DE_NULL,                                                        // const VkAttachmentReference*         pColorAttachments;
857                 DE_NULL,                                                        // const VkAttachmentReference*         pResolveAttachments;
858                 DE_NULL,                                                        // const VkAttachmentReference*         pDepthStencilAttachment;
859                 0u,                                                                     // deUint32                                                     preserveAttachmentCount;
860                 DE_NULL                                                         // const deUint32*                                      pPreserveAttachments;
861         };
862         subpasses.push_back(subpassDescription);
863
864         const VkRenderPassCreateInfo    renderPassInfo  =
865         {
866                 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,      // VkStructureType                                      sType;
867                 DE_NULL,                                                                        // const void*                                          pNext;
868                 (VkRenderPassCreateFlags)0,                                     // VkRenderPassCreateFlags                      flags;
869                 0,                                                                                      // deUint32                                                     attachmentCount;
870                 DE_NULL,                                                                        // const VkAttachmentDescription*       pAttachments;
871                 1,                                                                                      // deUint32                                                     subpassCount;
872                 &subpasses[0],                                                          // const VkSubpassDescription*          pSubpasses;
873                 0u,                                                                                     // deUint32                                                     dependencyCount;
874                 DE_NULL                                                                         // const VkSubpassDependency*           pDependencies;
875         };
876
877         return createRenderPass(vk, device, &renderPassInfo);
878 }
879
880 tcu::PixelBufferAccess getExpectedDataNoAtt (tcu::TextureLevel& textureLevel)
881 {
882         const tcu::PixelBufferAccess    expectedImage   (textureLevel);
883         for (int z = 0; z < expectedImage.getDepth(); ++z)
884         {
885                 for (int y = 0; y < expectedImage.getHeight(); ++y)
886                 {
887                         for (int x = 0; x < expectedImage.getWidth(); ++x)
888                         {
889                                 expectedImage.setPixel(tcu::Vec4(1.0, 0.5, 0.25, 1.0), x, y, z);
890                         }
891                 }
892         }
893         return expectedImage;
894 }
895
896 vector<tcu::Vec4> genPointVertices (void)
897 {
898         vector<tcu::Vec4>       vectorData;
899         vectorData.push_back(Vec4(-0.25f, -0.25f, 0, 1));
900         vectorData.push_back(Vec4(-0.25f,  0.25f, 0, 1));
901         vectorData.push_back(Vec4(0.25f, -0.25f, 0, 1));
902         vectorData.push_back(Vec4(0.25f,  0.25f, 0, 1));
903         return vectorData;
904 }
905
906 // Tests rendering to a framebuffer without color attachments, checking that
907 // the fragment shader is run even in the absence of color output. In this case
908 // we render 4 point primitives and we make the fragment shader write to a
909 // different pixel of an image via an imageStore command. For the single-sampled
910 // configuration we use a 4x1 image to record the output and for the
911 // multi-sampled case we use a 4x4 image to record all 16 samples produced by
912 // 4-sample multi-sampling
913 tcu::TestStatus testNoAtt (Context& context, const bool multisample)
914 {
915         const VkPhysicalDeviceFeatures          features                                = context.getDeviceFeatures();
916         if (!features.fragmentStoresAndAtomics)
917                 throw tcu::NotSupportedError("fragmentStoresAndAtomics feature not supported");
918         if (!features.geometryShader && !features.tessellationShader) // Shader uses gl_PrimitiveID
919                 throw tcu::NotSupportedError("geometryShader or tessellationShader feature not supported");
920         if (multisample && !features.sampleRateShading) // MS shader uses gl_SampleID
921                 throw tcu::NotSupportedError("sampleRateShading feature not supported");
922
923         const DeviceInterface&                          vk                                              = context.getDeviceInterface();
924         const VkDevice                                          device                                  = context.getDevice();
925         const VkQueue                                           queue                                   = context.getUniversalQueue();
926         const deUint32                                          queueFamilyIndex                = context.getUniversalQueueFamilyIndex();
927         Allocator&                                                      allocator                               = context.getDefaultAllocator();
928         const IVec3                                                     renderSize                              (32, 32, 1);
929
930         Move<VkBuffer>                                          vertexBuffer;
931         MovePtr<Allocation>                                     vertexBufferAlloc;
932
933         const Unique<VkShaderModule>            vertexModule                    (createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u));
934         const Unique<VkShaderModule>            fragmentModule                  (createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u));
935
936         // Create image where we will record the writes. For single-sampled cases this is a 4x1 image
937         // and for multi-sampled cases this is a 4x<num_samples> image.
938         const deUint8                                           numSamples                              = multisample ? 4 : 1;
939         const deUint8                                           imageWidth                              = 4;
940         const deUint8                                           imageHeight                             = numSamples;
941         const deUint8                                           imageDepth                              = 1;
942         const deUint8                                           imageLayers                             = 1;
943         const IVec3                                                     imageDim                                = IVec3(imageWidth, imageHeight, imageDepth);
944         const VkImageUsageFlags                         imageUsage                              = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_STORAGE_BIT;
945         const Move<VkImage>                                     image                                   = makeImage(vk, device, VkImageViewCreateFlags(0), VK_IMAGE_TYPE_2D, COLOR_FORMAT, imageDim, imageLayers, imageUsage, false);
946         const VkImageSubresourceRange           imageSubresourceRange   = makeColorSubresourceRange(0u, imageLayers);
947         const MovePtr<Allocation>                       imageAlloc                              = bindImage(vk, device, allocator, *image, MemoryRequirement::Any);
948         const Move<VkImageView>                         imageView                               = makeImageView(vk, device, *image, VK_IMAGE_VIEW_TYPE_2D, COLOR_FORMAT, imageSubresourceRange);
949
950         // Create a buffer where we will copy the image for verification
951         const VkDeviceSize                                      colorBufferSize         = imageWidth * imageHeight * imageDepth * numSamples * tcu::getPixelSize(mapVkFormat(COLOR_FORMAT));
952         const Unique<VkBuffer>                          colorBuffer                     (makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
953         const UniquePtr<Allocation>                     colorBufferAlloc        (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
954
955         // Create pipeline descriptor set for the image
956         const Move<VkDescriptorSetLayout>       descriptorSetLayout             = DescriptorSetLayoutBuilder()
957                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT)
958                 .build(vk, device);
959
960         const Move<VkDescriptorPool>            descriptorPool                  = DescriptorPoolBuilder()
961                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1)
962                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
963
964         const Move<VkDescriptorSet>                     descriptorSet                   = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
965         const VkDescriptorImageInfo                     descriptorImageInfo             = makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL);
966         DescriptorSetUpdateBuilder()
967                 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
968                 .update(vk, device);
969
970         const Unique<VkPipelineLayout>          pipelineLayout                  (makePipelineLayout (vk, device, *descriptorSetLayout));
971         vector<SharedPtrVkPipeline>                     pipeline;
972         const Unique<VkRenderPass>                      renderPass                              (makeRenderPassNoAtt (vk, device));
973         Move<VkFramebuffer>                                     framebuffer;
974
975         const Unique<VkCommandPool>                     cmdPool                                 (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
976         const Unique<VkCommandBuffer>           cmdBuffer                               (makeCommandBuffer (vk, device, *cmdPool));
977
978         // create vertexBuffer
979         {
980                 const vector<tcu::Vec4> vertices                        = genPointVertices();
981                 const VkDeviceSize              vertexBufferSize        = sizeInBytes(vertices);
982
983                 vertexBuffer            = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
984                 vertexBufferAlloc       = bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
985                 deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
986                 flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSize);
987         }
988
989         // Create render pass and pipeline
990         pipeline.push_back(makeSharedPtr(makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule,
991                 renderSize, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0, false, multisample)));
992         framebuffer = makeFramebuffer(vk, device, *renderPass, 0, DE_NULL, renderSize.x(), renderSize.y());
993
994         // Record command buffer
995         beginCommandBuffer(vk, *cmdBuffer);
996         {
997                 // shader image layout transition undefined -> general
998                 {
999                         const VkImageMemoryBarrier setImageLayoutBarrier = makeImageMemoryBarrier(
1000                                 0u, VK_ACCESS_SHADER_WRITE_BIT,
1001                                 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
1002                                 *image, imageSubresourceRange);
1003
1004                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0,
1005                                 0, DE_NULL, 0, DE_NULL, 1, &setImageLayoutBarrier);
1006                 }
1007
1008                 // Render pass
1009                 {
1010                         const VkRect2D renderArea =
1011                         {
1012                                 makeOffset2D(0, 0),
1013                                 makeExtent2D(renderSize.x(), renderSize.y()),
1014                         };
1015                         const VkRenderPassBeginInfo renderPassBeginInfo =
1016                         {
1017                                 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,       // VkStructureType         sType;
1018                                 DE_NULL,                                                                        // const void*             pNext;
1019                                 *renderPass,                                                            // VkRenderPass            renderPass;
1020                                 *framebuffer,                                                           // VkFramebuffer           framebuffer;
1021                                 renderArea,                                                                     // VkRect2D                renderArea;
1022                                 0,                                                                                      // uint32_t                clearValueCount;
1023                                 DE_NULL,                                                                        // const VkClearValue*     pClearValues;
1024                         };
1025                         const VkDeviceSize vertexBufferOffset = 0ull;
1026
1027                         vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1028
1029                         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipeline[0]);
1030                         vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1031                         vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
1032                         vk.cmdDraw(*cmdBuffer, 4u, 1u, 0u, 0u);
1033
1034                         vk.cmdEndRenderPass(*cmdBuffer);
1035                 }
1036
1037                 // copy image to host visible colorBuffer
1038                 {
1039                         const VkImageMemoryBarrier      imageBarriers[]         =
1040                         {
1041                                 {
1042                                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,         // VkStructureType                      sType;
1043                                         DE_NULL,                                                                        // const void*                          pNext;
1044                                         VK_ACCESS_SHADER_WRITE_BIT,                                     // VkAccessFlags                        srcAccessMask;
1045                                         VK_ACCESS_TRANSFER_READ_BIT,                            // VkAccessFlags                        dstAccessMask;
1046                                         VK_IMAGE_LAYOUT_GENERAL,                                        // VkImageLayout                        oldLayout;
1047                                         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,           // VkImageLayout                        newLayout;
1048                                         VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                                     srcQueueFamilyIndex;
1049                                         VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                                     destQueueFamilyIndex;
1050                                         *image,                                                                         // VkImage                                      image;
1051                                         makeColorSubresourceRange(0, 1)                         // VkImageSubresourceRange      subresourceRange;
1052                                 }
1053                         };
1054
1055                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1056                                 0u, DE_NULL, 0u, DE_NULL, 1u, imageBarriers);
1057
1058                         const VkBufferImageCopy         region                          =
1059                         {
1060                                 0ull,                                                                                                                           // VkDeviceSize                bufferOffset;
1061                                 0u,                                                                                                                                     // uint32_t                    bufferRowLength;
1062                                 0u,                                                                                                                                     // uint32_t                    bufferImageHeight;
1063                                 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1),       // VkImageSubresourceLayers    imageSubresource;
1064                                 makeOffset3D(0, 0, 0),                                                                                          // VkOffset3D                  imageOffset;
1065                                 makeExtent3D(IVec3(imageWidth, imageHeight, imageDepth)),                       // VkExtent3D                  imageExtent;
1066                         };
1067
1068                         vk.cmdCopyImageToBuffer(*cmdBuffer, *image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, &region);
1069
1070                         const VkBufferMemoryBarrier     bufferBarriers[]        =
1071                         {
1072                                 {
1073                                         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,        // VkStructureType    sType;
1074                                         DE_NULL,                                                                        // const void*        pNext;
1075                                         VK_ACCESS_TRANSFER_WRITE_BIT,                           // VkAccessFlags      srcAccessMask;
1076                                         VK_ACCESS_HOST_READ_BIT,                                        // VkAccessFlags      dstAccessMask;
1077                                         VK_QUEUE_FAMILY_IGNORED,                                        // uint32_t           srcQueueFamilyIndex;
1078                                         VK_QUEUE_FAMILY_IGNORED,                                        // uint32_t           dstQueueFamilyIndex;
1079                                         *colorBuffer,                                                           // VkBuffer           buffer;
1080                                         0ull,                                                                           // VkDeviceSize       offset;
1081                                         VK_WHOLE_SIZE,                                                          // VkDeviceSize       size;
1082                                 },
1083                         };
1084
1085                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
1086                                 0u, DE_NULL, DE_LENGTH_OF_ARRAY(bufferBarriers), bufferBarriers, 0u, DE_NULL);
1087                 }
1088         } // beginCommandBuffer
1089
1090         VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1091         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1092
1093         // Verify results
1094         {
1095                 invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1096                 const tcu::TextureFormat                        format                  = mapVkFormat(COLOR_FORMAT);
1097                 tcu::TextureLevel                                       textureLevel    (format, imageWidth, imageHeight, imageDepth);
1098                 const tcu::PixelBufferAccess            expectedImage   = getExpectedDataNoAtt(textureLevel);
1099                 const tcu::ConstPixelBufferAccess       resultImage             (format, imageWidth, imageHeight, imageDepth, colorBufferAlloc->getHostPtr());
1100
1101                 if (!tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT))
1102                         return tcu::TestStatus::fail("Fail");
1103         }
1104
1105         return tcu::TestStatus::pass("Pass");
1106 }
1107
1108 std::string getShortImageViewTypeName (const VkImageViewType imageViewType)
1109 {
1110         std::string     s       (getImageViewTypeName(imageViewType));
1111         return de::toLower(s.substr(19));
1112 }
1113
1114 std::string getSizeString (const CaseDef& caseDef)
1115 {
1116         std::ostringstream      str;
1117
1118                                                                                 str << caseDef.renderSize.x();
1119         if (caseDef.renderSize.y() > 1)         str << "x" << caseDef.renderSize.y();
1120         if (caseDef.renderSize.z() > 1)         str << "x" << caseDef.renderSize.z();
1121
1122                                                                                 str << "_" << caseDef.attachmentSize.x();
1123
1124         if (caseDef.attachmentSize.y() > 1)     str << "x" << caseDef.attachmentSize.y();
1125         if (caseDef.attachmentSize.z() > 1)     str << "x" << caseDef.attachmentSize.z();
1126         if (caseDef.numLayers > 1)                      str << "_" << caseDef.numLayers;
1127
1128         return str.str();
1129 }
1130
1131 std::string getTestCaseString (const CaseDef& caseDef)
1132 {
1133         std::ostringstream str;
1134
1135         str << getShortImageViewTypeName (caseDef.imageType).c_str();
1136         str << "_";
1137         str << getSizeString(caseDef);
1138
1139         if (caseDef.multisample)
1140                 str << "_ms";
1141
1142         return str.str();
1143 }
1144
1145 void addAttachmentTestCasesWithFunctions (tcu::TestCaseGroup* group)
1146 {
1147
1148         // Add test cases for attachment strictly sizes larger than the framebuffer
1149         const CaseDef   caseDef[]       =
1150         {
1151                 // Single-sample test cases
1152                 { VK_IMAGE_VIEW_TYPE_1D,                        IVec3(32, 1, 1),        IVec3(64, 1, 1),        1,              false },
1153                 { VK_IMAGE_VIEW_TYPE_1D,                        IVec3(32, 1, 1),        IVec3(48, 1, 1),        1,              false },
1154                 { VK_IMAGE_VIEW_TYPE_1D,                        IVec3(32, 1, 1),        IVec3(39, 1, 1),        1,              false },
1155                 { VK_IMAGE_VIEW_TYPE_1D,                        IVec3(19, 1, 1),        IVec3(32, 1, 1),        1,              false },
1156
1157                 { VK_IMAGE_VIEW_TYPE_1D_ARRAY,          IVec3(32, 1, 1),        IVec3(64, 1, 1),        4,              false },
1158                 { VK_IMAGE_VIEW_TYPE_1D_ARRAY,          IVec3(32, 1, 1),        IVec3(48, 1, 1),        4,              false },
1159                 { VK_IMAGE_VIEW_TYPE_1D_ARRAY,          IVec3(32, 1, 1),        IVec3(39, 1, 1),        4,              false },
1160                 { VK_IMAGE_VIEW_TYPE_1D_ARRAY,          IVec3(19, 1, 1),        IVec3(32, 1, 1),        4,              false },
1161
1162                 { VK_IMAGE_VIEW_TYPE_2D,                        IVec3(32, 32, 1),       IVec3(64, 64, 1),       1,              false },
1163                 { VK_IMAGE_VIEW_TYPE_2D,                        IVec3(32, 32, 1),       IVec3(48, 48, 1),       1,              false },
1164                 { VK_IMAGE_VIEW_TYPE_2D,                        IVec3(32, 32, 1),       IVec3(39, 41, 1),       1,              false },
1165                 { VK_IMAGE_VIEW_TYPE_2D,                        IVec3(19, 27, 1),       IVec3(32, 32, 1),       1,              false },
1166
1167                 { VK_IMAGE_VIEW_TYPE_2D_ARRAY,          IVec3(32, 32, 1),       IVec3(64, 64, 1),       4,              false },
1168                 { VK_IMAGE_VIEW_TYPE_2D_ARRAY,          IVec3(32, 32, 1),       IVec3(48, 48, 1),       4,              false },
1169                 { VK_IMAGE_VIEW_TYPE_2D_ARRAY,          IVec3(32, 32, 1),       IVec3(39, 41, 1),       4,              false },
1170                 { VK_IMAGE_VIEW_TYPE_2D_ARRAY,          IVec3(19, 27, 1),       IVec3(32, 32, 1),       4,              false },
1171
1172                 { VK_IMAGE_VIEW_TYPE_CUBE,                      IVec3(32, 32, 1),       IVec3(64, 64, 1),       6,              false },
1173                 { VK_IMAGE_VIEW_TYPE_CUBE,                      IVec3(32, 32, 1),       IVec3(48, 48, 1),       6,              false },
1174                 { VK_IMAGE_VIEW_TYPE_CUBE,                      IVec3(32, 32, 1),       IVec3(39, 41, 1),       6,              false },
1175                 { VK_IMAGE_VIEW_TYPE_CUBE,                      IVec3(19, 27, 1),       IVec3(32, 32, 1),       6,              false },
1176
1177                 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,        IVec3(32, 32, 1),       IVec3(64, 64, 1),       6*2,    false },
1178                 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,        IVec3(32, 32, 1),       IVec3(48, 48, 1),       6*2,    false },
1179                 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,        IVec3(32, 32, 1),       IVec3(39, 41, 1),       6*2,    false },
1180                 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,        IVec3(19, 27, 1),       IVec3(32, 32, 1),       6*2,    false },
1181
1182                 // Multi-sample test cases
1183                 { VK_IMAGE_VIEW_TYPE_2D,                        IVec3(32, 32, 1),       IVec3(64, 64, 1),       1,              true },
1184                 { VK_IMAGE_VIEW_TYPE_2D,                        IVec3(32, 32, 1),       IVec3(48, 48, 1),       1,              true },
1185                 { VK_IMAGE_VIEW_TYPE_2D,                        IVec3(32, 32, 1),       IVec3(39, 41, 1),       1,              true },
1186                 { VK_IMAGE_VIEW_TYPE_2D,                        IVec3(19, 27, 1),       IVec3(32, 32, 1),       1,              true },
1187
1188                 { VK_IMAGE_VIEW_TYPE_2D_ARRAY,          IVec3(32, 32, 1),       IVec3(64, 64, 1),       4,              true },
1189                 { VK_IMAGE_VIEW_TYPE_2D_ARRAY,          IVec3(32, 32, 1),       IVec3(48, 48, 1),       4,              true },
1190                 { VK_IMAGE_VIEW_TYPE_2D_ARRAY,          IVec3(32, 32, 1),       IVec3(39, 41, 1),       4,              true },
1191                 { VK_IMAGE_VIEW_TYPE_2D_ARRAY,          IVec3(19, 27, 1),       IVec3(32, 32, 1),       4,              true },
1192         };
1193
1194         for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(caseDef); ++sizeNdx)
1195                 addFunctionCaseWithPrograms(group, getTestCaseString(caseDef[sizeNdx]).c_str(), "", initColorPrograms, test, caseDef[sizeNdx]);
1196
1197         // Add tests for the case where there are no color attachments but the
1198         // fragment shader writes to an image via imageStore().
1199         addFunctionCaseWithPrograms(group, "no_attachments", "", initImagePrograms, testNoAtt, false);
1200         addFunctionCaseWithPrograms(group, "no_attachments_ms", "", initImagePrograms, testNoAtt, true);
1201 }
1202
1203 } // anonymous ns
1204
1205 tcu::TestCaseGroup* createFramebufferAttachmentTests (tcu::TestContext& testCtx)
1206 {
1207         return createTestGroup(testCtx, "framebuffer_attachment", "Framebuffer attachment tests", addAttachmentTestCasesWithFunctions);
1208 }
1209
1210 } // pipeline
1211 } // vkt