Merge "Merge "Try to determine renderable format in lifetime tests am: c0a5dc217f...
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / pipeline / vktPipelineMultisampleImageTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 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
21  * \brief Multisample image Tests
22  *//*--------------------------------------------------------------------*/
23
24 #include "vktPipelineMultisampleImageTests.hpp"
25 #include "vktPipelineMakeUtil.hpp"
26 #include "vktTestCase.hpp"
27 #include "vktTestCaseUtil.hpp"
28 #include "vktPipelineVertexUtil.hpp"
29 #include "vktTestGroupUtil.hpp"
30
31 #include "vkMemUtil.hpp"
32 #include "vkQueryUtil.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkRefUtil.hpp"
35 #include "vkBuilderUtil.hpp"
36 #include "vkPrograms.hpp"
37 #include "vkImageUtil.hpp"
38
39 #include "tcuTextureUtil.hpp"
40 #include "tcuTestLog.hpp"
41
42 #include "deUniquePtr.hpp"
43 #include "deSharedPtr.hpp"
44
45 #include <string>
46
47 namespace vkt
48 {
49 namespace pipeline
50 {
51 namespace
52 {
53 using namespace vk;
54 using de::UniquePtr;
55 using de::MovePtr;
56 using de::SharedPtr;
57 using tcu::IVec2;
58 using tcu::Vec4;
59
60 typedef SharedPtr<Unique<VkImageView> > ImageViewSp;
61 typedef SharedPtr<Unique<VkPipeline> >  PipelineSp;
62
63 //! Test case parameters
64 struct CaseDef
65 {
66         IVec2                                   renderSize;
67         int                                             numLayers;
68         VkFormat                                colorFormat;
69         VkSampleCountFlagBits   numSamples;
70 };
71
72 template<typename T>
73 inline SharedPtr<Unique<T> > makeSharedPtr (Move<T> move)
74 {
75         return SharedPtr<Unique<T> >(new Unique<T>(move));
76 }
77
78 template<typename T>
79 inline VkDeviceSize sizeInBytes(const std::vector<T>& vec)
80 {
81         return vec.size() * sizeof(vec[0]);
82 }
83
84 //! Create a vector of derived pipelines, each with an increasing subpass index
85 std::vector<PipelineSp> makeGraphicsPipelines (const DeviceInterface&           vk,
86                                                                                            const VkDevice                               device,
87                                                                                            const deUint32                               numSubpasses,
88                                                                                            const VkPipelineLayout               pipelineLayout,
89                                                                                            const VkRenderPass                   renderPass,
90                                                                                            const VkShaderModule                 vertexModule,
91                                                                                            const VkShaderModule                 fragmentModule,
92                                                                                            const IVec2                                  renderSize,
93                                                                                            const VkSampleCountFlagBits  numSamples,
94                                                                                            const VkPrimitiveTopology    topology)
95 {
96         const VkVertexInputBindingDescription vertexInputBindingDescription =
97         {
98                 0u,                                                             // uint32_t                             binding;
99                 sizeof(Vertex4RGBA),                    // uint32_t                             stride;
100                 VK_VERTEX_INPUT_RATE_VERTEX,    // VkVertexInputRate    inputRate;
101         };
102
103         const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
104         {
105                 {
106                         0u,                                                                     // uint32_t                     location;
107                         0u,                                                                     // uint32_t                     binding;
108                         VK_FORMAT_R32G32B32A32_SFLOAT,          // VkFormat                     format;
109                         0u,                                                                     // uint32_t                     offset;
110                 },
111                 {
112                         1u,                                                                     // uint32_t                     location;
113                         0u,                                                                     // uint32_t                     binding;
114                         VK_FORMAT_R32G32B32A32_SFLOAT,          // VkFormat                     format;
115                         sizeof(Vec4),                                           // uint32_t                     offset;
116                 },
117         };
118
119         const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
120         {
121                 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,              // VkStructureType                             sType;
122                 DE_NULL,                                                                                                                // const void*                                 pNext;
123                 (VkPipelineVertexInputStateCreateFlags)0,                                               // VkPipelineVertexInputStateCreateFlags       flags;
124                 1u,                                                                                                                             // uint32_t                                    vertexBindingDescriptionCount;
125                 &vertexInputBindingDescription,                                                                 // const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
126                 DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions),                   // uint32_t                                    vertexAttributeDescriptionCount;
127                 vertexInputAttributeDescriptions,                                                               // const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
128         };
129
130         const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
131         {
132                 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,    // VkStructureType                             sType;
133                 DE_NULL,                                                                                                                // const void*                                 pNext;
134                 (VkPipelineInputAssemblyStateCreateFlags)0,                                             // VkPipelineInputAssemblyStateCreateFlags     flags;
135                 topology,                                                                                                               // VkPrimitiveTopology                         topology;
136                 VK_FALSE,                                                                                                               // VkBool32                                    primitiveRestartEnable;
137         };
138
139         const VkViewport viewport = makeViewport(
140                 0.0f, 0.0f,
141                 static_cast<float>(renderSize.x()), static_cast<float>(renderSize.y()),
142                 0.0f, 1.0f);
143
144         const VkRect2D scissor = {
145                 makeOffset2D(0, 0),
146                 makeExtent2D(renderSize.x(), renderSize.y()),
147         };
148
149         const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
150         {
151                 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,                  // VkStructureType                             sType;
152                 DE_NULL,                                                                                                                // const void*                                 pNext;
153                 (VkPipelineViewportStateCreateFlags)0,                                                  // VkPipelineViewportStateCreateFlags          flags;
154                 1u,                                                                                                                             // uint32_t                                    viewportCount;
155                 &viewport,                                                                                                              // const VkViewport*                           pViewports;
156                 1u,                                                                                                                             // uint32_t                                    scissorCount;
157                 &scissor,                                                                                                               // const VkRect2D*                             pScissors;
158         };
159
160         const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
161         {
162                 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,             // VkStructureType                          sType;
163                 DE_NULL,                                                                                                                // const void*                              pNext;
164                 (VkPipelineRasterizationStateCreateFlags)0,                                             // VkPipelineRasterizationStateCreateFlags  flags;
165                 VK_FALSE,                                                                                                               // VkBool32                                 depthClampEnable;
166                 VK_FALSE,                                                                                                               // VkBool32                                 rasterizerDiscardEnable;
167                 VK_POLYGON_MODE_FILL,                                                                                   // VkPolygonMode                                                        polygonMode;
168                 VK_CULL_MODE_NONE,                                                                                              // VkCullModeFlags                                                      cullMode;
169                 VK_FRONT_FACE_COUNTER_CLOCKWISE,                                                                // VkFrontFace                                                          frontFace;
170                 VK_FALSE,                                                                                                               // VkBool32                                                                     depthBiasEnable;
171                 0.0f,                                                                                                                   // float                                                                        depthBiasConstantFactor;
172                 0.0f,                                                                                                                   // float                                                                        depthBiasClamp;
173                 0.0f,                                                                                                                   // float                                                                        depthBiasSlopeFactor;
174                 1.0f,                                                                                                                   // float                                                                        lineWidth;
175         };
176
177         const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
178         {
179                 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,               // VkStructureType                                                      sType;
180                 DE_NULL,                                                                                                                // const void*                                                          pNext;
181                 (VkPipelineMultisampleStateCreateFlags)0,                                               // VkPipelineMultisampleStateCreateFlags        flags;
182                 numSamples,                                                                                                             // VkSampleCountFlagBits                                        rasterizationSamples;
183                 VK_FALSE,                                                                                                               // VkBool32                                                                     sampleShadingEnable;
184                 0.0f,                                                                                                                   // float                                                                        minSampleShading;
185                 DE_NULL,                                                                                                                // const VkSampleMask*                                          pSampleMask;
186                 VK_FALSE,                                                                                                               // VkBool32                                                                     alphaToCoverageEnable;
187                 VK_FALSE                                                                                                                // VkBool32                                                                     alphaToOneEnable;
188         };
189
190         const VkStencilOpState stencilOpState = makeStencilOpState(
191                 VK_STENCIL_OP_KEEP,                             // stencil fail
192                 VK_STENCIL_OP_KEEP,                             // depth & stencil pass
193                 VK_STENCIL_OP_KEEP,                             // depth only fail
194                 VK_COMPARE_OP_ALWAYS,                   // compare op
195                 0u,                                                             // compare mask
196                 0u,                                                             // write mask
197                 0u);                                                    // reference
198
199         VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
200         {
201                 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,             // VkStructureType                                                      sType;
202                 DE_NULL,                                                                                                                // const void*                                                          pNext;
203                 (VkPipelineDepthStencilStateCreateFlags)0,                                              // VkPipelineDepthStencilStateCreateFlags       flags;
204                 VK_FALSE,                                                                                                               // VkBool32                                                                     depthTestEnable;
205                 VK_FALSE,                                                                                                               // VkBool32                                                                     depthWriteEnable;
206                 VK_COMPARE_OP_LESS,                                                                                             // VkCompareOp                                                          depthCompareOp;
207                 VK_FALSE,                                                                                                               // VkBool32                                                                     depthBoundsTestEnable;
208                 VK_FALSE,                                                                                                               // VkBool32                                                                     stencilTestEnable;
209                 stencilOpState,                                                                                                 // VkStencilOpState                                                     front;
210                 stencilOpState,                                                                                                 // VkStencilOpState                                                     back;
211                 0.0f,                                                                                                                   // float                                                                        minDepthBounds;
212                 1.0f,                                                                                                                   // float                                                                        maxDepthBounds;
213         };
214
215         const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
216         // Number of blend attachments must equal the number of color attachments during any subpass.
217         const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
218         {
219                 VK_FALSE,                                               // VkBool32                                     blendEnable;
220                 VK_BLEND_FACTOR_ONE,                    // VkBlendFactor                        srcColorBlendFactor;
221                 VK_BLEND_FACTOR_ZERO,                   // VkBlendFactor                        dstColorBlendFactor;
222                 VK_BLEND_OP_ADD,                                // VkBlendOp                            colorBlendOp;
223                 VK_BLEND_FACTOR_ONE,                    // VkBlendFactor                        srcAlphaBlendFactor;
224                 VK_BLEND_FACTOR_ZERO,                   // VkBlendFactor                        dstAlphaBlendFactor;
225                 VK_BLEND_OP_ADD,                                // VkBlendOp                            alphaBlendOp;
226                 colorComponentsAll,                             // VkColorComponentFlags        colorWriteMask;
227         };
228
229         const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
230         {
231                 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,               // VkStructureType                                                              sType;
232                 DE_NULL,                                                                                                                // const void*                                                                  pNext;
233                 (VkPipelineColorBlendStateCreateFlags)0,                                                // VkPipelineColorBlendStateCreateFlags                 flags;
234                 VK_FALSE,                                                                                                               // VkBool32                                                                             logicOpEnable;
235                 VK_LOGIC_OP_COPY,                                                                                               // VkLogicOp                                                                    logicOp;
236                 1u,                                                                                                                             // deUint32                                                                             attachmentCount;
237                 &pipelineColorBlendAttachmentState,                                                             // const VkPipelineColorBlendAttachmentState*   pAttachments;
238                 { 0.0f, 0.0f, 0.0f, 0.0f },                                                                             // float                                                                                blendConstants[4];
239         };
240
241         const VkPipelineShaderStageCreateInfo pShaderStages[] =
242         {
243                 {
244                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,            // VkStructureType                                              sType;
245                         DE_NULL,                                                                                                        // const void*                                                  pNext;
246                         (VkPipelineShaderStageCreateFlags)0,                                            // VkPipelineShaderStageCreateFlags             flags;
247                         VK_SHADER_STAGE_VERTEX_BIT,                                                                     // VkShaderStageFlagBits                                stage;
248                         vertexModule,                                                                                           // VkShaderModule                                               module;
249                         "main",                                                                                                         // const char*                                                  pName;
250                         DE_NULL,                                                                                                        // const VkSpecializationInfo*                  pSpecializationInfo;
251                 },
252                 {
253                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,            // VkStructureType                                              sType;
254                         DE_NULL,                                                                                                        // const void*                                                  pNext;
255                         (VkPipelineShaderStageCreateFlags)0,                                            // VkPipelineShaderStageCreateFlags             flags;
256                         VK_SHADER_STAGE_FRAGMENT_BIT,                                                           // VkShaderStageFlagBits                                stage;
257                         fragmentModule,                                                                                         // VkShaderModule                                               module;
258                         "main",                                                                                                         // const char*                                                  pName;
259                         DE_NULL,                                                                                                        // const VkSpecializationInfo*                  pSpecializationInfo;
260                 }
261         };
262
263         DE_ASSERT(numSubpasses > 0u);
264
265         std::vector<VkGraphicsPipelineCreateInfo>       graphicsPipelineInfos   (0);
266         std::vector<VkPipeline>                                         rawPipelines                    (numSubpasses, DE_NULL);
267
268         {
269                 const VkPipelineCreateFlags firstPipelineFlags = (numSubpasses > 1u ? VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT
270                                                                                                                                                         : (VkPipelineCreateFlagBits)0);
271
272                 VkGraphicsPipelineCreateInfo createInfo =
273                 {
274                         VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,        // VkStructureType                                                                      sType;
275                         DE_NULL,                                                                                        // const void*                                                                          pNext;
276                         firstPipelineFlags,                                                                     // VkPipelineCreateFlags                                                        flags;
277                         DE_LENGTH_OF_ARRAY(pShaderStages),                                      // deUint32                                                                                     stageCount;
278                         pShaderStages,                                                                          // const VkPipelineShaderStageCreateInfo*                       pStages;
279                         &vertexInputStateInfo,                                                          // const VkPipelineVertexInputStateCreateInfo*          pVertexInputState;
280                         &pipelineInputAssemblyStateInfo,                                        // const VkPipelineInputAssemblyStateCreateInfo*        pInputAssemblyState;
281                         DE_NULL,                                                                                        // const VkPipelineTessellationStateCreateInfo*         pTessellationState;
282                         &pipelineViewportStateInfo,                                                     // const VkPipelineViewportStateCreateInfo*                     pViewportState;
283                         &pipelineRasterizationStateInfo,                                        // const VkPipelineRasterizationStateCreateInfo*        pRasterizationState;
284                         &pipelineMultisampleStateInfo,                                          // const VkPipelineMultisampleStateCreateInfo*          pMultisampleState;
285                         &pipelineDepthStencilStateInfo,                                         // const VkPipelineDepthStencilStateCreateInfo*         pDepthStencilState;
286                         &pipelineColorBlendStateInfo,                                           // const VkPipelineColorBlendStateCreateInfo*           pColorBlendState;
287                         DE_NULL,                                                                                        // const VkPipelineDynamicStateCreateInfo*                      pDynamicState;
288                         pipelineLayout,                                                                         // VkPipelineLayout                                                                     layout;
289                         renderPass,                                                                                     // VkRenderPass                                                                         renderPass;
290                         0u,                                                                                                     // deUint32                                                                                     subpass;
291                         DE_NULL,                                                                                        // VkPipeline                                                                           basePipelineHandle;
292                         -1,                                                                                                     // deInt32                                                                                      basePipelineIndex;
293                 };
294
295                 graphicsPipelineInfos.push_back(createInfo);
296
297                 createInfo.flags                                = VK_PIPELINE_CREATE_DERIVATIVE_BIT;
298                 createInfo.basePipelineIndex    = 0;
299
300                 for (deUint32 subpassNdx = 1u; subpassNdx < numSubpasses; ++subpassNdx)
301                 {
302                         createInfo.subpass = subpassNdx;
303                         graphicsPipelineInfos.push_back(createInfo);
304                 }
305         }
306
307         VK_CHECK(vk.createGraphicsPipelines(device, DE_NULL, static_cast<deUint32>(graphicsPipelineInfos.size()), &graphicsPipelineInfos[0], DE_NULL, &rawPipelines[0]));
308
309         std::vector<PipelineSp> pipelines;
310
311         for (std::vector<VkPipeline>::const_iterator it = rawPipelines.begin(); it != rawPipelines.end(); ++it)
312                 pipelines.push_back(makeSharedPtr(Move<VkPipeline>(check<VkPipeline>(*it), Deleter<VkPipeline>(vk, device, DE_NULL))));
313
314         return pipelines;
315 }
316
317 //! Make a render pass with one subpass per color attachment and one attachment per image layer.
318 Move<VkRenderPass> makeMultisampleRenderPass (const DeviceInterface&            vk,
319                                                                                           const VkDevice                                device,
320                                                                                           const VkFormat                                colorFormat,
321                                                                                           const VkSampleCountFlagBits   numSamples,
322                                                                                           const deUint32                                numLayers)
323 {
324         const VkAttachmentDescription colorAttachmentDescription =
325         {
326                 (VkAttachmentDescriptionFlags)0,                                        // VkAttachmentDescriptionFlags         flags;
327                 colorFormat,                                                                            // VkFormat                                                     format;
328                 numSamples,                                                                                     // VkSampleCountFlagBits                        samples;
329                 VK_ATTACHMENT_LOAD_OP_CLEAR,                                            // VkAttachmentLoadOp                           loadOp;
330                 VK_ATTACHMENT_STORE_OP_STORE,                                           // VkAttachmentStoreOp                          storeOp;
331                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,                                        // VkAttachmentLoadOp                           stencilLoadOp;
332                 VK_ATTACHMENT_STORE_OP_DONT_CARE,                                       // VkAttachmentStoreOp                          stencilStoreOp;
333                 VK_IMAGE_LAYOUT_UNDEFINED,                                                      // VkImageLayout                                        initialLayout;
334                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                       // VkImageLayout                                        finalLayout;
335         };
336         const std::vector<VkAttachmentDescription> attachmentDescriptions(numLayers, colorAttachmentDescription);
337
338         // Create a subpass for each attachment (each attachement is a layer of an arrayed image).
339
340         std::vector<VkAttachmentReference>      colorAttachmentReferences(numLayers);
341         std::vector<VkSubpassDescription>       subpasses;
342
343         for (deUint32 i = 0; i < numLayers; ++i)
344         {
345                 const VkAttachmentReference attachmentRef =
346                 {
347                         i,                                                                                              // deUint32                     attachment;
348                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL                // VkImageLayout        layout;
349                 };
350                 colorAttachmentReferences[i] = attachmentRef;
351
352                 const VkSubpassDescription subpassDescription =
353                 {
354                         (VkSubpassDescriptionFlags)0,                                   // VkSubpassDescriptionFlags            flags;
355                         VK_PIPELINE_BIND_POINT_GRAPHICS,                                // VkPipelineBindPoint                          pipelineBindPoint;
356                         0u,                                                                                             // deUint32                                                     inputAttachmentCount;
357                         DE_NULL,                                                                                // const VkAttachmentReference*         pInputAttachments;
358                         1u,                                                                                             // deUint32                                                     colorAttachmentCount;
359                         &colorAttachmentReferences[i],                                  // const VkAttachmentReference*         pColorAttachments;
360                         DE_NULL,                                                                                // const VkAttachmentReference*         pResolveAttachments;
361                         DE_NULL,                                                                                // const VkAttachmentReference*         pDepthStencilAttachment;
362                         0u,                                                                                             // deUint32                                                     preserveAttachmentCount;
363                         DE_NULL                                                                                 // const deUint32*                                      pPreserveAttachments;
364                 };
365                 subpasses.push_back(subpassDescription);
366         }
367
368         const VkRenderPassCreateInfo renderPassInfo =
369         {
370                 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,                              // VkStructureType                                      sType;
371                 DE_NULL,                                                                                                // const void*                                          pNext;
372                 (VkRenderPassCreateFlags)0,                                                             // VkRenderPassCreateFlags                      flags;
373                 static_cast<deUint32>(attachmentDescriptions.size()),   // deUint32                                                     attachmentCount;
374                 &attachmentDescriptions[0],                                                             // const VkAttachmentDescription*       pAttachments;
375                 static_cast<deUint32>(subpasses.size()),                                // deUint32                                                     subpassCount;
376                 &subpasses[0],                                                                                  // const VkSubpassDescription*          pSubpasses;
377                 0u,                                                                                                             // deUint32                                                     dependencyCount;
378                 DE_NULL                                                                                                 // const VkSubpassDependency*           pDependencies;
379         };
380
381         return createRenderPass(vk, device, &renderPassInfo);
382 }
383
384 //! A single-attachment, single-subpass render pass.
385 Move<VkRenderPass> makeSimpleRenderPass (const DeviceInterface& vk,
386                                                                              const VkDevice                     device,
387                                                                                  const VkFormat                 colorFormat)
388 {
389         const VkAttachmentDescription colorAttachmentDescription =
390         {
391                 (VkAttachmentDescriptionFlags)0,                                        // VkAttachmentDescriptionFlags         flags;
392                 colorFormat,                                                                            // VkFormat                                                     format;
393                 VK_SAMPLE_COUNT_1_BIT,                                                          // VkSampleCountFlagBits                        samples;
394                 VK_ATTACHMENT_LOAD_OP_CLEAR,                                            // VkAttachmentLoadOp                           loadOp;
395                 VK_ATTACHMENT_STORE_OP_STORE,                                           // VkAttachmentStoreOp                          storeOp;
396                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,                                        // VkAttachmentLoadOp                           stencilLoadOp;
397                 VK_ATTACHMENT_STORE_OP_DONT_CARE,                                       // VkAttachmentStoreOp                          stencilStoreOp;
398                 VK_IMAGE_LAYOUT_UNDEFINED,                                                      // VkImageLayout                                        initialLayout;
399                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                       // VkImageLayout                                        finalLayout;
400         };
401
402         const VkAttachmentReference colorAttachmentRef =
403         {
404                 0u,                                                                                                     // deUint32                     attachment;
405                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL                        // VkImageLayout        layout;
406         };
407
408         const VkSubpassDescription subpassDescription =
409         {
410                 (VkSubpassDescriptionFlags)0,                                           // VkSubpassDescriptionFlags            flags;
411                 VK_PIPELINE_BIND_POINT_GRAPHICS,                                        // VkPipelineBindPoint                          pipelineBindPoint;
412                 0u,                                                                                                     // deUint32                                                     inputAttachmentCount;
413                 DE_NULL,                                                                                        // const VkAttachmentReference*         pInputAttachments;
414                 1u,                                                                                                     // deUint32                                                     colorAttachmentCount;
415                 &colorAttachmentRef,                                                            // const VkAttachmentReference*         pColorAttachments;
416                 DE_NULL,                                                                                        // const VkAttachmentReference*         pResolveAttachments;
417                 DE_NULL,                                                                                        // const VkAttachmentReference*         pDepthStencilAttachment;
418                 0u,                                                                                                     // deUint32                                                     preserveAttachmentCount;
419                 DE_NULL                                                                                         // const deUint32*                                      pPreserveAttachments;
420         };
421
422         const VkRenderPassCreateInfo renderPassInfo =
423         {
424                 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,                      // VkStructureType                                      sType;
425                 DE_NULL,                                                                                        // const void*                                          pNext;
426                 (VkRenderPassCreateFlags)0,                                                     // VkRenderPassCreateFlags                      flags;
427                 1u,                                                                                                     // deUint32                                                     attachmentCount;
428                 &colorAttachmentDescription,                                            // const VkAttachmentDescription*       pAttachments;
429                 1u,                                                                                                     // deUint32                                                     subpassCount;
430                 &subpassDescription,                                                            // const VkSubpassDescription*          pSubpasses;
431                 0u,                                                                                                     // deUint32                                                     dependencyCount;
432                 DE_NULL                                                                                         // const VkSubpassDependency*           pDependencies;
433         };
434
435         return createRenderPass(vk, device, &renderPassInfo);
436 }
437
438 Move<VkImage> makeImage (const DeviceInterface& vk, const VkDevice device, const VkFormat format, const IVec2& size, const deUint32 numLayers, const VkSampleCountFlagBits samples, const VkImageUsageFlags usage)
439 {
440         const VkImageCreateInfo imageParams =
441         {
442                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                    // VkStructureType                      sType;
443                 DE_NULL,                                                                                // const void*                          pNext;
444                 (VkImageCreateFlags)0,                                                  // VkImageCreateFlags           flags;
445                 VK_IMAGE_TYPE_2D,                                                               // VkImageType                          imageType;
446                 format,                                                                                 // VkFormat                                     format;
447                 makeExtent3D(size.x(), size.y(), 1),                    // VkExtent3D                           extent;
448                 1u,                                                                                             // deUint32                                     mipLevels;
449                 numLayers,                                                                              // deUint32                                     arrayLayers;
450                 samples,                                                                                // VkSampleCountFlagBits        samples;
451                 VK_IMAGE_TILING_OPTIMAL,                                                // VkImageTiling                        tiling;
452                 usage,                                                                                  // VkImageUsageFlags            usage;
453                 VK_SHARING_MODE_EXCLUSIVE,                                              // VkSharingMode                        sharingMode;
454                 0u,                                                                                             // deUint32                                     queueFamilyIndexCount;
455                 DE_NULL,                                                                                // const deUint32*                      pQueueFamilyIndices;
456                 VK_IMAGE_LAYOUT_UNDEFINED,                                              // VkImageLayout                        initialLayout;
457         };
458         return createImage(vk, device, &imageParams);
459 }
460
461 //! Make a simplest sampler.
462 Move<VkSampler> makeSampler (const DeviceInterface& vk, const VkDevice device)
463 {
464         const VkSamplerCreateInfo samplerParams =
465         {
466                 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,                  // VkStructureType         sType;
467                 DE_NULL,                                                                                // const void*             pNext;
468                 (VkSamplerCreateFlags)0,                                                // VkSamplerCreateFlags    flags;
469                 VK_FILTER_NEAREST,                                                              // VkFilter                magFilter;
470                 VK_FILTER_NEAREST,                                                              // VkFilter                minFilter;
471                 VK_SAMPLER_MIPMAP_MODE_NEAREST,                                 // VkSamplerMipmapMode     mipmapMode;
472                 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,                  // VkSamplerAddressMode    addressModeU;
473                 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,                  // VkSamplerAddressMode    addressModeV;
474                 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,                  // VkSamplerAddressMode    addressModeW;
475                 0.0f,                                                                                   // float                   mipLodBias;
476                 VK_FALSE,                                                                               // VkBool32                anisotropyEnable;
477                 1.0f,                                                                                   // float                   maxAnisotropy;
478                 VK_FALSE,                                                                               // VkBool32                compareEnable;
479                 VK_COMPARE_OP_ALWAYS,                                                   // VkCompareOp             compareOp;
480                 0.0f,                                                                                   // float                   minLod;
481                 0.0f,                                                                                   // float                   maxLod;
482                 VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,                // VkBorderColor           borderColor;
483                 VK_FALSE,                                                                               // VkBool32                unnormalizedCoordinates;
484         };
485         return createSampler(vk, device, &samplerParams);
486 }
487
488 inline Move<VkBuffer> makeBuffer (const DeviceInterface& vk, const VkDevice device, const VkDeviceSize bufferSize, const VkBufferUsageFlags usage)
489 {
490         const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSize, usage);
491         return createBuffer(vk, device, &bufferCreateInfo);
492 }
493
494 inline VkImageSubresourceRange makeColorSubresourceRange (const int baseArrayLayer, const int layerCount)
495 {
496         return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, static_cast<deUint32>(baseArrayLayer), static_cast<deUint32>(layerCount));
497 }
498
499 inline VkImageSubresourceLayers makeColorSubresourceLayers (const int baseArrayLayer, const int layerCount)
500 {
501         return makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, static_cast<deUint32>(baseArrayLayer), static_cast<deUint32>(layerCount));
502 }
503
504 void checkImageFormatRequirements (const InstanceInterface&             vki,
505                                                                    const VkPhysicalDevice               physDevice,
506                                                                    const VkSampleCountFlagBits  sampleCount,
507                                                                    const VkFormat                               format,
508                                                                    const VkImageUsageFlags              usage)
509 {
510         VkPhysicalDeviceFeatures        features;
511         vki.getPhysicalDeviceFeatures(physDevice, &features);
512
513         if (((usage & VK_IMAGE_USAGE_STORAGE_BIT) != 0) && !features.shaderStorageImageMultisample)
514                 TCU_THROW(NotSupportedError, "Multisampled storage images are not supported");
515
516         VkImageFormatProperties         imageFormatProperties;
517         const VkResult                          imageFormatResult               = vki.getPhysicalDeviceImageFormatProperties(
518                 physDevice, format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, usage, (VkImageCreateFlags)0, &imageFormatProperties);
519
520         if (imageFormatResult == VK_ERROR_FORMAT_NOT_SUPPORTED)
521                 TCU_THROW(NotSupportedError, "Image format is not supported");
522
523         if ((imageFormatProperties.sampleCounts & sampleCount) != sampleCount)
524                 TCU_THROW(NotSupportedError, "Requested sample count is not supported");
525 }
526
527 void zeroBuffer (const DeviceInterface& vk, const VkDevice device, const Allocation& alloc, const VkDeviceSize bufferSize)
528 {
529         deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(bufferSize));
530         flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), bufferSize);
531 }
532
533 //! The default foreground color.
534 inline Vec4 getPrimitiveColor (void)
535 {
536         return Vec4(1.0f, 0.0f, 0.0f, 1.0f);
537 }
538
539 //! Get a reference clear value based on color format.
540 VkClearValue getClearValue (const VkFormat format)
541 {
542         if (isUintFormat(format) || isIntFormat(format))
543                 return makeClearValueColorU32(16, 32, 64, 96);
544         else
545                 return makeClearValueColorF32(0.0f, 0.0f, 1.0f, 1.0f);
546 }
547
548 std::string getColorFormatStr (const int numComponents, const bool isUint, const bool isSint)
549 {
550         std::ostringstream str;
551         if (numComponents == 1)
552                 str << (isUint ? "uint" : isSint ? "int" : "float");
553         else
554                 str << (isUint ? "u" : isSint ? "i" : "") << "vec" << numComponents;
555
556         return str.str();
557 }
558
559 std::string getSamplerTypeStr (const int numLayers, const bool isUint, const bool isSint)
560 {
561         std::ostringstream str;
562         str << (isUint ? "u" : isSint ? "i" : "") << "sampler2DMS" << (numLayers > 1 ? "Array" : "");
563         return str.str();
564 }
565
566 //! Generate a gvec4 color literal.
567 template<typename T>
568 std::string getColorStr (const T* data, int numComponents, const bool isUint, const bool isSint)
569 {
570         const int maxIndex = 3;  // 4 components max
571
572         std::ostringstream str;
573         str << (isUint ? "u" : isSint ? "i" : "") << "vec4(";
574
575         for (int i = 0; i < numComponents; ++i)
576         {
577                 str << data[i]
578                         << (i < maxIndex ? ", " : "");
579         }
580
581         for (int i = numComponents; i < maxIndex + 1; ++i)
582         {
583                 str << (i == maxIndex ? 1 : 0)
584                         << (i <  maxIndex ? ", " : "");
585         }
586
587         str << ")";
588         return str.str();
589 }
590
591 //! Clear color literal value used by the sampling shader.
592 std::string getReferenceClearColorStr (const VkFormat format, const int numComponents, const bool isUint, const bool isSint)
593 {
594         const VkClearColorValue clearColor = getClearValue(format).color;
595         if (isUint)
596                 return getColorStr(clearColor.uint32, numComponents, isUint, isSint);
597         else if (isSint)
598                 return getColorStr(clearColor.int32, numComponents, isUint, isSint);
599         else
600                 return getColorStr(clearColor.float32, numComponents, isUint, isSint);
601 }
602
603 //! Primitive color literal value used by the sampling shader.
604 std::string getReferencePrimitiveColorStr (int numComponents, const bool isUint, const bool isSint)
605 {
606         const Vec4 color = getPrimitiveColor();
607         return getColorStr(color.getPtr(), numComponents, isUint, isSint);
608 }
609
610 inline int getNumSamples (const VkSampleCountFlagBits samples)
611 {
612         return static_cast<int>(samples);       // enum bitmask actually matches the number of samples
613 }
614
615 //! A flat-colored shape with sharp angles to make antialiasing visible.
616 std::vector<Vertex4RGBA> genTriangleVertices (void)
617 {
618         static const Vertex4RGBA data[] =
619         {
620                 {
621                         Vec4(-1.0f, 0.0f, 0.0f, 1.0f),
622                         getPrimitiveColor(),
623                 },
624                 {
625                         Vec4(0.8f, 0.2f, 0.0f, 1.0f),
626                         getPrimitiveColor(),
627                 },
628                 {
629                         Vec4(0.8f, -0.2f, 0.0f, 1.0f),
630                         getPrimitiveColor(),
631                 },
632         };
633         return std::vector<Vertex4RGBA>(data, data + DE_LENGTH_OF_ARRAY(data));
634 }
635
636 //! A full-viewport quad. Use with TRIANGLE_STRIP topology.
637 std::vector<Vertex4RGBA> genFullQuadVertices (void)
638 {
639         static const Vertex4RGBA data[] =
640         {
641                 {
642                         Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
643                         Vec4(), // unused
644                 },
645                 {
646                         Vec4(-1.0f, 1.0f, 0.0f, 1.0f),
647                         Vec4(), // unused
648                 },
649                 {
650                         Vec4(1.0f, -1.0f, 0.0f, 1.0f),
651                         Vec4(), // unused
652                 },
653                 {
654                         Vec4(1.0f, 1.0f, 0.0f, 1.0f),
655                         Vec4(), // unused
656                 },
657         };
658         return std::vector<Vertex4RGBA>(data, data + DE_LENGTH_OF_ARRAY(data));
659 }
660
661 std::string getShaderImageFormatQualifier (const tcu::TextureFormat& format)
662 {
663         const char* orderPart;
664         const char* typePart;
665
666         switch (format.order)
667         {
668                 case tcu::TextureFormat::R:             orderPart = "r";        break;
669                 case tcu::TextureFormat::RG:    orderPart = "rg";       break;
670                 case tcu::TextureFormat::RGB:   orderPart = "rgb";      break;
671                 case tcu::TextureFormat::RGBA:  orderPart = "rgba";     break;
672
673                 default:
674                         DE_ASSERT(false);
675                         orderPart = DE_NULL;
676         }
677
678         switch (format.type)
679         {
680                 case tcu::TextureFormat::FLOAT:                         typePart = "32f";               break;
681                 case tcu::TextureFormat::HALF_FLOAT:            typePart = "16f";               break;
682
683                 case tcu::TextureFormat::UNSIGNED_INT32:        typePart = "32ui";              break;
684                 case tcu::TextureFormat::UNSIGNED_INT16:        typePart = "16ui";              break;
685                 case tcu::TextureFormat::UNSIGNED_INT8:         typePart = "8ui";               break;
686
687                 case tcu::TextureFormat::SIGNED_INT32:          typePart = "32i";               break;
688                 case tcu::TextureFormat::SIGNED_INT16:          typePart = "16i";               break;
689                 case tcu::TextureFormat::SIGNED_INT8:           typePart = "8i";                break;
690
691                 case tcu::TextureFormat::UNORM_INT16:           typePart = "16";                break;
692                 case tcu::TextureFormat::UNORM_INT8:            typePart = "8";                 break;
693
694                 case tcu::TextureFormat::SNORM_INT16:           typePart = "16_snorm";  break;
695                 case tcu::TextureFormat::SNORM_INT8:            typePart = "8_snorm";   break;
696
697                 default:
698                         DE_ASSERT(false);
699                         typePart = DE_NULL;
700         }
701
702         return std::string() + orderPart + typePart;
703 }
704
705 std::string getShaderMultisampledImageType (const tcu::TextureFormat& format, const int numLayers)
706 {
707         const std::string formatPart = tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER ? "u" :
708                                                                    tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER   ? "i" : "";
709
710         std::ostringstream str;
711         str << formatPart << "image2DMS" << (numLayers > 1 ? "Array" : "");
712
713         return str.str();
714 }
715
716 void addSimpleVertexAndFragmentPrograms (SourceCollections& programCollection, const CaseDef caseDef)
717 {
718         const int       numComponents   = tcu::getNumUsedChannels(mapVkFormat(caseDef.colorFormat).order);
719         const bool      isUint                  = isUintFormat(caseDef.colorFormat);
720         const bool      isSint                  = isIntFormat(caseDef.colorFormat);
721
722         // Vertex shader
723         {
724                 std::ostringstream src;
725                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
726                         << "\n"
727                         << "layout(location = 0) in  vec4 in_position;\n"
728                         << "layout(location = 1) in  vec4 in_color;\n"
729                         << "layout(location = 0) out vec4 o_color;\n"
730                         << "\n"
731                         << "out gl_PerVertex {\n"
732                         << "    vec4 gl_Position;\n"
733                         << "};\n"
734                         << "\n"
735                         << "void main(void)\n"
736                         << "{\n"
737                         << "    gl_Position = in_position;\n"
738                         << "    o_color     = in_color;\n"
739                         << "}\n";
740
741                 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
742         }
743
744         // Fragment shader
745         {
746                 const std::string colorFormat = getColorFormatStr(numComponents, isUint, isSint);
747
748                 std::ostringstream src;
749                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
750                         << "\n"
751                         << "layout(location = 0) in  vec4 in_color;\n"
752                         << "layout(location = 0) out " << colorFormat << " o_color;\n"
753                         << "\n"
754                         << "void main(void)\n"
755                         << "{\n"
756                         << "    o_color = " << colorFormat << "("               // float color will be converted to int/uint here if needed
757                         << (numComponents == 1 ? "in_color.r"   :
758                                 numComponents == 2 ? "in_color.rg"  :
759                                 numComponents == 3 ? "in_color.rgb" : "in_color") << ");\n"
760                         << "}\n";
761
762                 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
763         }
764 }
765
766 //! Synchronously render to a multisampled color image.
767 void renderMultisampledImage (Context& context, const CaseDef& caseDef, const VkImage colorImage)
768 {
769         const DeviceInterface&                  vk                                      = context.getDeviceInterface();
770         const VkDevice                                  device                          = context.getDevice();
771         const VkQueue                                   queue                           = context.getUniversalQueue();
772         const deUint32                                  queueFamilyIndex        = context.getUniversalQueueFamilyIndex();
773         Allocator&                                              allocator                       = context.getDefaultAllocator();
774
775         const Unique<VkCommandPool>             cmdPool                         (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
776         const Unique<VkCommandBuffer>   cmdBuffer                       (makeCommandBuffer(vk, device, *cmdPool));
777
778         const VkRect2D renderArea = {
779                 makeOffset2D(0, 0),
780                 makeExtent2D(caseDef.renderSize.x(), caseDef.renderSize.y()),
781         };
782
783         {
784                 // Create an image view (attachment) for each layer of the image
785                 std::vector<ImageViewSp>        colorAttachments;
786                 std::vector<VkImageView>        attachmentHandles;
787                 for (int i = 0; i < caseDef.numLayers; ++i)
788                 {
789                         colorAttachments.push_back(makeSharedPtr(makeImageView(
790                                 vk, device, colorImage, VK_IMAGE_VIEW_TYPE_2D, caseDef.colorFormat, makeColorSubresourceRange(i, 1))));
791                         attachmentHandles.push_back(**colorAttachments.back());
792                 }
793
794                 // Vertex buffer
795                 const std::vector<Vertex4RGBA>  vertices                        = genTriangleVertices();
796                 const VkDeviceSize                              vertexBufferSize        = sizeInBytes(vertices);
797                 const Unique<VkBuffer>                  vertexBuffer            (makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
798                 const UniquePtr<Allocation>             vertexBufferAlloc       (bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
799
800                 {
801                         deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
802                         flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSize);
803                 }
804
805                 const Unique<VkShaderModule>    vertexModule    (createShaderModule                     (vk, device, context.getBinaryCollection().get("vert"), 0u));
806                 const Unique<VkShaderModule>    fragmentModule  (createShaderModule                     (vk, device, context.getBinaryCollection().get("frag"), 0u));
807                 const Unique<VkRenderPass>              renderPass              (makeMultisampleRenderPass      (vk, device, caseDef.colorFormat, caseDef.numSamples, caseDef.numLayers));
808                 const Unique<VkFramebuffer>             framebuffer             (makeFramebuffer                        (vk, device, *renderPass, caseDef.numLayers, &attachmentHandles[0],
809                                                                                                                                                                          static_cast<deUint32>(caseDef.renderSize.x()),  static_cast<deUint32>(caseDef.renderSize.y())));
810                 const Unique<VkPipelineLayout>  pipelineLayout  (makePipelineLayout                     (vk, device));
811                 const std::vector<PipelineSp>   pipelines               (makeGraphicsPipelines          (vk, device, caseDef.numLayers, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule,
812                                                                                                                                                                          caseDef.renderSize, caseDef.numSamples, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST));
813
814                 beginCommandBuffer(vk, *cmdBuffer);
815
816                 const std::vector<VkClearValue> clearValues(caseDef.numLayers, getClearValue(caseDef.colorFormat));
817
818                 const VkRenderPassBeginInfo renderPassBeginInfo = {
819                         VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,               // VkStructureType         sType;
820                         DE_NULL,                                                                                // const void*             pNext;
821                         *renderPass,                                                                    // VkRenderPass            renderPass;
822                         *framebuffer,                                                                   // VkFramebuffer           framebuffer;
823                         renderArea,                                                                             // VkRect2D                renderArea;
824                         static_cast<deUint32>(clearValues.size()),              // uint32_t                clearValueCount;
825                         &clearValues[0],                                                                // const VkClearValue*     pClearValues;
826                 };
827                 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
828
829                 {
830                         const VkDeviceSize vertexBufferOffset = 0ull;
831                         vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
832                 }
833
834                 for (int layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx)
835                 {
836                         if (layerNdx != 0)
837                                 vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
838
839                         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[layerNdx]);
840
841                         vk.cmdDraw(*cmdBuffer, static_cast<deUint32>(vertices.size()), 1u, 0u, 0u);
842                 }
843
844                 vk.cmdEndRenderPass(*cmdBuffer);
845
846                 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
847                 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
848         }
849 }
850
851 namespace SampledImage
852 {
853
854 void initPrograms (SourceCollections& programCollection, const CaseDef caseDef)
855 {
856         // Pass 1: Render to texture
857
858         addSimpleVertexAndFragmentPrograms(programCollection, caseDef);
859
860         // Pass 2: Sample texture
861
862         // Vertex shader
863         {
864                 std::ostringstream src;
865                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
866                         << "\n"
867                         << "layout(location = 0) in  vec4  in_position;\n"
868                         << "\n"
869                         << "out gl_PerVertex {\n"
870                         << "    vec4 gl_Position;\n"
871                         << "};\n"
872                         << "\n"
873                         << "void main(void)\n"
874                         << "{\n"
875                         << "    gl_Position = in_position;\n"
876                         << "}\n";
877
878                 programCollection.glslSources.add("sample_vert") << glu::VertexSource(src.str());
879         }
880
881         // Fragment shader
882         {
883                 const int                       numComponents           = tcu::getNumUsedChannels(mapVkFormat(caseDef.colorFormat).order);
884                 const bool                      isUint                          = isUintFormat(caseDef.colorFormat);
885                 const bool                      isSint                          = isIntFormat(caseDef.colorFormat);
886                 const std::string       texelFormatStr          = (isUint ? "uvec4" : isSint ? "ivec4" : "vec4");
887                 const std::string       refClearColor           = getReferenceClearColorStr(caseDef.colorFormat, numComponents, isUint, isSint);
888                 const std::string       refPrimitiveColor       = getReferencePrimitiveColorStr(numComponents, isUint, isSint);
889                 const std::string       samplerTypeStr          = getSamplerTypeStr(caseDef.numLayers, isUint, isSint);
890
891                 std::ostringstream src;
892                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
893                         << "\n"
894                         << "layout(location = 0) out int o_status;\n"
895                         << "\n"
896                         << "layout(set = 0, binding = 0) uniform " << samplerTypeStr << " colorTexture;\n"
897                         << "\n"
898                         << "void main(void)\n"
899                         << "{\n"
900                         << "    int checksum = 0;\n"
901                         << "\n";
902
903                 if (caseDef.numLayers == 1)
904                         src << "    for (int sampleNdx = 0; sampleNdx < " << caseDef.numSamples << "; ++sampleNdx) {\n"
905                                 << "        " << texelFormatStr << " color = texelFetch(colorTexture, ivec2(gl_FragCoord.xy), sampleNdx);\n"
906                                 << "        if (color == " << refClearColor << " || color == " << refPrimitiveColor << ")\n"
907                                 << "            ++checksum;\n"
908                                 << "    }\n";
909                 else
910                         src << "    for (int layerNdx = 0; layerNdx < " << caseDef.numLayers << "; ++layerNdx)\n"
911                                 << "    for (int sampleNdx = 0; sampleNdx < " << caseDef.numSamples << "; ++sampleNdx) {\n"
912                                 << "        " << texelFormatStr << " color = texelFetch(colorTexture, ivec3(gl_FragCoord.xy, layerNdx), sampleNdx);\n"
913                                 << "        if (color == " << refClearColor << " || color == " << refPrimitiveColor << ")\n"
914                                 << "            ++checksum;\n"
915                                 << "    }\n";
916
917                 src << "\n"
918                         << "    o_status = checksum;\n"
919                         << "}\n";
920
921                 programCollection.glslSources.add("sample_frag") << glu::FragmentSource(src.str());
922         }
923 }
924
925 tcu::TestStatus test (Context& context, const CaseDef caseDef)
926 {
927         const DeviceInterface&          vk                                      = context.getDeviceInterface();
928         const InstanceInterface&        vki                                     = context.getInstanceInterface();
929         const VkDevice                          device                          = context.getDevice();
930         const VkPhysicalDevice          physDevice                      = context.getPhysicalDevice();
931         const VkQueue                           queue                           = context.getUniversalQueue();
932         const deUint32                          queueFamilyIndex        = context.getUniversalQueueFamilyIndex();
933         Allocator&                                      allocator                       = context.getDefaultAllocator();
934
935         const VkImageUsageFlags         colorImageUsage         = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
936
937         checkImageFormatRequirements(vki, physDevice, caseDef.numSamples, caseDef.colorFormat, colorImageUsage);
938
939         {
940                 tcu::TestLog& log = context.getTestContext().getLog();
941                 log << tcu::LogSection("Description", "")
942                         << tcu::TestLog::Message << "Rendering to a multisampled image. Expecting all samples to be either a clear color or a primitive color." << tcu::TestLog::EndMessage
943                         << tcu::TestLog::Message << "Sampling from the texture with texelFetch (OpImageFetch)." << tcu::TestLog::EndMessage
944                         << tcu::TestLog::EndSection;
945         }
946
947         // Multisampled color image
948         const Unique<VkImage>                   colorImage              (makeImage(vk, device, caseDef.colorFormat, caseDef.renderSize, caseDef.numLayers, caseDef.numSamples, colorImageUsage));
949         const UniquePtr<Allocation>             colorImageAlloc (bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
950
951         const Unique<VkCommandPool>             cmdPool                 (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
952         const Unique<VkCommandBuffer>   cmdBuffer               (makeCommandBuffer(vk, device, *cmdPool));
953
954         const VkRect2D renderArea = {
955                 makeOffset2D(0, 0),
956                 makeExtent2D(caseDef.renderSize.x(), caseDef.renderSize.y()),
957         };
958
959         // Step 1: Render to texture
960         {
961                 renderMultisampledImage(context, caseDef, *colorImage);
962         }
963
964         // Step 2: Sample texture
965         {
966                 // Color image view
967                 const VkImageViewType                   colorImageViewType      = (caseDef.numLayers == 1 ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_2D_ARRAY);
968                 const Unique<VkImageView>               colorImageView          (makeImageView(vk, device, *colorImage, colorImageViewType, caseDef.colorFormat, makeColorSubresourceRange(0, caseDef.numLayers)));
969                 const Unique<VkSampler>                 colorSampler            (makeSampler(vk, device));
970
971                 // Checksum image
972                 const VkFormat                                  checksumFormat          = VK_FORMAT_R32_SINT;
973                 const Unique<VkImage>                   checksumImage           (makeImage(vk, device, checksumFormat, caseDef.renderSize, 1u, VK_SAMPLE_COUNT_1_BIT,
974                                                                                                                                            VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
975                 const UniquePtr<Allocation>             checksumImageAlloc      (bindImage(vk, device, allocator, *checksumImage, MemoryRequirement::Any));
976                 const Unique<VkImageView>               checksumImageView       (makeImageView(vk, device, *checksumImage, VK_IMAGE_VIEW_TYPE_2D, checksumFormat, makeColorSubresourceRange(0, 1)));
977
978                 // Checksum buffer (for host reading)
979                 const VkDeviceSize                              checksumBufferSize      = caseDef.renderSize.x() * caseDef.renderSize.y() * tcu::getPixelSize(mapVkFormat(checksumFormat));
980                 const Unique<VkBuffer>                  checksumBuffer          (makeBuffer(vk, device, checksumBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
981                 const UniquePtr<Allocation>             checksumBufferAlloc     (bindBuffer(vk, device, allocator, *checksumBuffer, MemoryRequirement::HostVisible));
982
983                 zeroBuffer(vk, device, *checksumBufferAlloc, checksumBufferSize);
984
985                 // Vertex buffer
986                 const std::vector<Vertex4RGBA>  vertices                        = genFullQuadVertices();
987                 const VkDeviceSize                              vertexBufferSize        = sizeInBytes(vertices);
988                 const Unique<VkBuffer>                  vertexBuffer            (makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
989                 const UniquePtr<Allocation>             vertexBufferAlloc       (bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
990
991                 {
992                         deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
993                         flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSize);
994                 }
995
996                 // Descriptors
997                 // \note OpImageFetch doesn't use a sampler, but in GLSL texelFetch needs a sampler2D which translates to a combined image sampler in Vulkan.
998
999                 const Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
1000                         .addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, &colorSampler.get())
1001                         .build(vk, device));
1002
1003                 const Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
1004                         .addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
1005                         .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
1006
1007                 const Unique<VkDescriptorSet>   descriptorSet           (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
1008                 const VkDescriptorImageInfo             imageDescriptorInfo     = makeDescriptorImageInfo(DE_NULL, *colorImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1009
1010                 DescriptorSetUpdateBuilder()
1011                         .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageDescriptorInfo)
1012                         .update(vk, device);
1013
1014                 const Unique<VkShaderModule>    vertexModule    (createShaderModule             (vk, device, context.getBinaryCollection().get("sample_vert"), 0u));
1015                 const Unique<VkShaderModule>    fragmentModule  (createShaderModule             (vk, device, context.getBinaryCollection().get("sample_frag"), 0u));
1016                 const Unique<VkRenderPass>              renderPass              (makeSimpleRenderPass   (vk, device, checksumFormat));
1017                 const Unique<VkFramebuffer>             framebuffer             (makeFramebuffer                (vk, device, *renderPass, 1u, &checksumImageView.get(),
1018                                                                                                                                                                  static_cast<deUint32>(caseDef.renderSize.x()),  static_cast<deUint32>(caseDef.renderSize.y())));
1019                 const Unique<VkPipelineLayout>  pipelineLayout  (makePipelineLayout             (vk, device, *descriptorSetLayout));
1020                 const std::vector<PipelineSp>   pipelines               (makeGraphicsPipelines  (vk, device, 1u, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule,
1021                                                                                                                                                                  caseDef.renderSize, VK_SAMPLE_COUNT_1_BIT, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP));
1022
1023                 beginCommandBuffer(vk, *cmdBuffer);
1024
1025                 // Prepare for sampling in the fragment shader
1026                 {
1027                         const VkImageMemoryBarrier barriers[] =
1028                         {
1029                                 {
1030                                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                                         // VkStructureType                      sType;
1031                                         DE_NULL,                                                                                                        // const void*                          pNext;
1032                                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                                           // VkAccessFlags                        outputMask;
1033                                         VK_ACCESS_SHADER_READ_BIT,                                                                      // VkAccessFlags                        inputMask;
1034                                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                                       // VkImageLayout                        oldLayout;
1035                                         VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,                                       // VkImageLayout                        newLayout;
1036                                         VK_QUEUE_FAMILY_IGNORED,                                                                        // deUint32                                     srcQueueFamilyIndex;
1037                                         VK_QUEUE_FAMILY_IGNORED,                                                                        // deUint32                                     destQueueFamilyIndex;
1038                                         *colorImage,                                                                                            // VkImage                                      image;
1039                                         makeColorSubresourceRange(0, caseDef.numLayers),                        // VkImageSubresourceRange      subresourceRange;
1040                                 },
1041                         };
1042
1043                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u,
1044                                 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
1045                 }
1046
1047                 const VkClearValue clearValue = makeClearValueColorU32(0u, 0u, 0u, 0u);
1048
1049                 const VkRenderPassBeginInfo renderPassBeginInfo = {
1050                         VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,                                                       // VkStructureType         sType;
1051                         DE_NULL,                                                                                                                        // const void*             pNext;
1052                         *renderPass,                                                                                                            // VkRenderPass            renderPass;
1053                         *framebuffer,                                                                                                           // VkFramebuffer           framebuffer;
1054                         renderArea,                                                                                                                     // VkRect2D                renderArea;
1055                         1u,                                                                                                                                     // uint32_t                clearValueCount;
1056                         &clearValue,                                                                                                            // const VkClearValue*     pClearValues;
1057                 };
1058                 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1059
1060                 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines.back());
1061                 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
1062                 {
1063                         const VkDeviceSize vertexBufferOffset = 0ull;
1064                         vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1065                 }
1066
1067                 vk.cmdDraw(*cmdBuffer, static_cast<deUint32>(vertices.size()), 1u, 0u, 0u);
1068                 vk.cmdEndRenderPass(*cmdBuffer);
1069
1070                 // Prepare checksum image for copy
1071                 {
1072                         const VkImageMemoryBarrier barriers[] =
1073                         {
1074                                 {
1075                                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                                         // VkStructureType                      sType;
1076                                         DE_NULL,                                                                                                        // const void*                          pNext;
1077                                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                                           // VkAccessFlags                        outputMask;
1078                                         VK_ACCESS_TRANSFER_READ_BIT,                                                            // VkAccessFlags                        inputMask;
1079                                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                                       // VkImageLayout                        oldLayout;
1080                                         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,                                           // VkImageLayout                        newLayout;
1081                                         VK_QUEUE_FAMILY_IGNORED,                                                                        // deUint32                                     srcQueueFamilyIndex;
1082                                         VK_QUEUE_FAMILY_IGNORED,                                                                        // deUint32                                     destQueueFamilyIndex;
1083                                         *checksumImage,                                                                                         // VkImage                                      image;
1084                                         makeColorSubresourceRange(0, 1),                                                        // VkImageSubresourceRange      subresourceRange;
1085                                 },
1086                         };
1087
1088                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1089                                 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
1090                 }
1091                 // Checksum image -> host buffer
1092                 {
1093                         const VkBufferImageCopy region =
1094                         {
1095                                 0ull,                                                                                                                                           // VkDeviceSize                bufferOffset;
1096                                 0u,                                                                                                                                                     // uint32_t                    bufferRowLength;
1097                                 0u,                                                                                                                                                     // uint32_t                    bufferImageHeight;
1098                                 makeColorSubresourceLayers(0, 1),                                                                                       // VkImageSubresourceLayers    imageSubresource;
1099                                 makeOffset3D(0, 0, 0),                                                                                                          // VkOffset3D                  imageOffset;
1100                                 makeExtent3D(caseDef.renderSize.x(), caseDef.renderSize.y(), 1u),                       // VkExtent3D                  imageExtent;
1101                         };
1102
1103                         vk.cmdCopyImageToBuffer(*cmdBuffer, *checksumImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *checksumBuffer, 1u, &region);
1104                 }
1105                 // Buffer write barrier
1106                 {
1107                         const VkBufferMemoryBarrier barriers[] =
1108                         {
1109                                 {
1110                                         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,                // VkStructureType    sType;
1111                                         DE_NULL,                                                                                // const void*        pNext;
1112                                         VK_ACCESS_TRANSFER_WRITE_BIT,                                   // VkAccessFlags      srcAccessMask;
1113                                         VK_ACCESS_HOST_READ_BIT,                                                // VkAccessFlags      dstAccessMask;
1114                                         VK_QUEUE_FAMILY_IGNORED,                                                // uint32_t           srcQueueFamilyIndex;
1115                                         VK_QUEUE_FAMILY_IGNORED,                                                // uint32_t           dstQueueFamilyIndex;
1116                                         *checksumBuffer,                                                                // VkBuffer           buffer;
1117                                         0ull,                                                                                   // VkDeviceSize       offset;
1118                                         checksumBufferSize,                                                             // VkDeviceSize       size;
1119                                 },
1120                         };
1121
1122                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
1123                                 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers, DE_NULL, 0u);
1124                 }
1125
1126                 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1127                 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1128
1129                 // Verify result
1130
1131                 {
1132                         invalidateMappedMemoryRange(vk, device, checksumBufferAlloc->getMemory(), 0ull, checksumBufferSize);
1133
1134                         const tcu::ConstPixelBufferAccess access(mapVkFormat(checksumFormat), caseDef.renderSize.x(), caseDef.renderSize.y(), 1, checksumBufferAlloc->getHostPtr());
1135                         const int numExpectedChecksum = getNumSamples(caseDef.numSamples) * caseDef.numLayers;
1136
1137                         for (int y = 0; y < caseDef.renderSize.y(); ++y)
1138                         for (int x = 0; x < caseDef.renderSize.x(); ++x)
1139                         {
1140                                 if (access.getPixelInt(x, y).x() != numExpectedChecksum)
1141                                         return tcu::TestStatus::fail("Some samples have incorrect color");
1142                         }
1143                 }
1144         }
1145
1146         return tcu::TestStatus::pass("OK");
1147 }
1148
1149 } // SampledImage ns
1150
1151 namespace StorageImage
1152 {
1153
1154 void initPrograms (SourceCollections& programCollection, const CaseDef caseDef)
1155 {
1156         // Vertex & fragment
1157
1158         addSimpleVertexAndFragmentPrograms(programCollection, caseDef);
1159
1160         // Compute
1161         {
1162                 const std::string       imageTypeStr            = getShaderMultisampledImageType(mapVkFormat(caseDef.colorFormat), caseDef.numLayers);
1163                 const std::string       formatQualifierStr      = getShaderImageFormatQualifier(mapVkFormat(caseDef.colorFormat));
1164                 const std::string       signednessPrefix        = isUintFormat(caseDef.colorFormat) ? "u" : isIntFormat(caseDef.colorFormat) ? "i" : "";
1165                 const std::string       gvec4Expr                       = signednessPrefix + "vec4";
1166                 const std::string       texelCoordStr           = (caseDef.numLayers == 1 ? "ivec2(gx, gy)" : "ivec3(gx, gy, gz)");
1167
1168                 std::ostringstream src;
1169                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1170                         << "layout(local_size_x = 1) in;\n"
1171                         << "layout(set = 0, binding = 0, " << formatQualifierStr << ") uniform " << imageTypeStr << " u_msImage;\n"
1172                         << "\n"
1173                         << "void main(void)\n"
1174                         << "{\n"
1175                         << "    int gx = int(gl_GlobalInvocationID.x);\n"
1176                         << "    int gy = int(gl_GlobalInvocationID.y);\n"
1177                         << "    int gz = int(gl_GlobalInvocationID.z);\n"
1178                         << "\n"
1179                         << "    " << gvec4Expr << " prevColor = imageLoad(u_msImage, " << texelCoordStr << ", 0);\n"
1180                         << "    for (int sampleNdx = 1; sampleNdx < " << caseDef.numSamples << "; ++sampleNdx) {\n"
1181                         << "        " << gvec4Expr << " color = imageLoad(u_msImage, " << texelCoordStr << ", sampleNdx);\n"
1182                         << "        imageStore(u_msImage, " << texelCoordStr <<", sampleNdx, prevColor);\n"
1183                         << "        prevColor = color;\n"
1184                         << "    }\n"
1185                         << "    imageStore(u_msImage, " << texelCoordStr <<", 0, prevColor);\n"
1186                         << "}\n";
1187
1188                 programCollection.glslSources.add("comp") << glu::ComputeSource(src.str());
1189         }
1190 }
1191
1192 //! Render a MS image, resolve it, and copy result to resolveBuffer.
1193 void renderAndResolve (Context& context, const CaseDef& caseDef, const VkBuffer resolveBuffer, const bool useComputePass)
1194 {
1195         const DeviceInterface&          vk                                      = context.getDeviceInterface();
1196         const VkDevice                          device                          = context.getDevice();
1197         const VkQueue                           queue                           = context.getUniversalQueue();
1198         const deUint32                          queueFamilyIndex        = context.getUniversalQueueFamilyIndex();
1199         Allocator&                                      allocator                       = context.getDefaultAllocator();
1200
1201         // Multisampled color image
1202         const Unique<VkImage>                   colorImage                      (makeImage(vk, device, caseDef.colorFormat, caseDef.renderSize, caseDef.numLayers, caseDef.numSamples,
1203                                                                                                                                    VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT));
1204         const UniquePtr<Allocation>             colorImageAlloc         (bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
1205
1206         const Unique<VkImage>                   resolveImage            (makeImage(vk, device, caseDef.colorFormat, caseDef.renderSize, caseDef.numLayers, VK_SAMPLE_COUNT_1_BIT,
1207                                                                                                                                    VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT));
1208         const UniquePtr<Allocation>             resolveImageAlloc       (bindImage(vk, device, allocator, *resolveImage, MemoryRequirement::Any));
1209
1210         const Unique<VkCommandPool>             cmdPool                         (createCommandPool  (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1211         const Unique<VkCommandBuffer>   cmdBuffer                       (makeCommandBuffer(vk, device, *cmdPool));
1212
1213         // Working image barrier, we change it based on which rendering stages were executed so far.
1214         VkImageMemoryBarrier colorImageBarrier =
1215         {
1216                 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                                         // VkStructureType                      sType;
1217                 DE_NULL,                                                                                                        // const void*                          pNext;
1218                 (VkAccessFlags)0,                                                                                       // VkAccessFlags                        outputMask;
1219                 (VkAccessFlags)0,                                                                                       // VkAccessFlags                        inputMask;
1220                 VK_IMAGE_LAYOUT_UNDEFINED,                                                                      // VkImageLayout                        oldLayout;
1221                 VK_IMAGE_LAYOUT_UNDEFINED,                                                                      // VkImageLayout                        newLayout;
1222                 VK_QUEUE_FAMILY_IGNORED,                                                                        // deUint32                                     srcQueueFamilyIndex;
1223                 VK_QUEUE_FAMILY_IGNORED,                                                                        // deUint32                                     destQueueFamilyIndex;
1224                 *colorImage,                                                                                            // VkImage                                      image;
1225                 makeColorSubresourceRange(0, caseDef.numLayers),                        // VkImageSubresourceRange      subresourceRange;
1226         };
1227
1228         // Pass 1: Render an image
1229         {
1230                 renderMultisampledImage(context, caseDef, *colorImage);
1231
1232                 colorImageBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1233                 colorImageBarrier.oldLayout             = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1234         }
1235
1236         // Pass 2: Compute shader
1237         if (useComputePass)
1238         {
1239                 // Descriptors
1240
1241                 Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
1242                         .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
1243                         .build(vk, device));
1244
1245                 Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
1246                         .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1u)
1247                         .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
1248
1249                 const Unique<VkImageView>               colorImageView          (makeImageView(vk, device, *colorImage,
1250                                                                                                                                                         (caseDef.numLayers == 1 ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_2D_ARRAY),
1251                                                                                                                                                         caseDef.colorFormat, makeColorSubresourceRange(0, caseDef.numLayers)));
1252                 const Unique<VkDescriptorSet>   descriptorSet           (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
1253                 const VkDescriptorImageInfo             descriptorImageInfo     = makeDescriptorImageInfo(DE_NULL, *colorImageView, VK_IMAGE_LAYOUT_GENERAL);
1254
1255                 DescriptorSetUpdateBuilder()
1256                         .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
1257                         .update(vk, device);
1258
1259                 const Unique<VkPipelineLayout>  pipelineLayout  (makePipelineLayout     (vk, device, *descriptorSetLayout));
1260                 const Unique<VkShaderModule>    shaderModule    (createShaderModule     (vk, device, context.getBinaryCollection().get("comp"), 0));
1261                 const Unique<VkPipeline>                pipeline                (makeComputePipeline(vk, device, *pipelineLayout, *shaderModule, DE_NULL));
1262
1263                 beginCommandBuffer(vk, *cmdBuffer);
1264
1265                 // Image layout for load/stores
1266                 {
1267                         colorImageBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
1268                         colorImageBarrier.newLayout             = VK_IMAGE_LAYOUT_GENERAL;
1269
1270                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u,
1271                                 0u, DE_NULL, 0u, DE_NULL, 1u, &colorImageBarrier);
1272
1273                         colorImageBarrier.srcAccessMask = colorImageBarrier.dstAccessMask;
1274                         colorImageBarrier.oldLayout             = colorImageBarrier.newLayout;
1275                 }
1276                 // Dispatch
1277                 {
1278                         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
1279                         vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
1280                         vk.cmdDispatch(*cmdBuffer, caseDef.renderSize.x(), caseDef.renderSize.y(), caseDef.numLayers);
1281                 }
1282
1283                 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1284                 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1285         }
1286
1287         // Resolve and verify the image
1288         {
1289                 beginCommandBuffer(vk, *cmdBuffer);
1290
1291                 // Prepare for resolve
1292                 {
1293                         colorImageBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1294                         colorImageBarrier.newLayout             = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
1295
1296                         const VkImageMemoryBarrier barriers[] =
1297                         {
1298                                 colorImageBarrier,
1299                                 {
1300                                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                                         // VkStructureType                      sType;
1301                                         DE_NULL,                                                                                                        // const void*                          pNext;
1302                                         (VkAccessFlags)0,                                                                                       // VkAccessFlags                        outputMask;
1303                                         VK_ACCESS_TRANSFER_WRITE_BIT,                                                           // VkAccessFlags                        inputMask;
1304                                         VK_IMAGE_LAYOUT_UNDEFINED,                                                                      // VkImageLayout                        oldLayout;
1305                                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,                                           // VkImageLayout                        newLayout;
1306                                         VK_QUEUE_FAMILY_IGNORED,                                                                        // deUint32                                     srcQueueFamilyIndex;
1307                                         VK_QUEUE_FAMILY_IGNORED,                                                                        // deUint32                                     destQueueFamilyIndex;
1308                                         *resolveImage,                                                                                          // VkImage                                      image;
1309                                         makeColorSubresourceRange(0, caseDef.numLayers),                        // VkImageSubresourceRange      subresourceRange;
1310                                 },
1311                         };
1312
1313                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1314                                 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
1315
1316                         colorImageBarrier.srcAccessMask = colorImageBarrier.dstAccessMask;
1317                         colorImageBarrier.oldLayout             = colorImageBarrier.newLayout;
1318                 }
1319                 // Resolve the image
1320                 {
1321                         const VkImageResolve resolveRegion =
1322                         {
1323                                 makeColorSubresourceLayers(0, caseDef.numLayers),                                       // VkImageSubresourceLayers    srcSubresource;
1324                                 makeOffset3D(0, 0, 0),                                                                                          // VkOffset3D                  srcOffset;
1325                                 makeColorSubresourceLayers(0, caseDef.numLayers),                                       // VkImageSubresourceLayers    dstSubresource;
1326                                 makeOffset3D(0, 0, 0),                                                                                          // VkOffset3D                  dstOffset;
1327                                 makeExtent3D(caseDef.renderSize.x(), caseDef.renderSize.y(), 1u),       // VkExtent3D                  extent;
1328                         };
1329
1330                         vk.cmdResolveImage(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *resolveImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &resolveRegion);
1331                 }
1332                 // Prepare resolve image for copy
1333                 {
1334                         const VkImageMemoryBarrier barriers[] =
1335                         {
1336                                 {
1337                                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                                         // VkStructureType                      sType;
1338                                         DE_NULL,                                                                                                        // const void*                          pNext;
1339                                         VK_ACCESS_TRANSFER_WRITE_BIT,                                                           // VkAccessFlags                        outputMask;
1340                                         VK_ACCESS_TRANSFER_READ_BIT,                                                            // VkAccessFlags                        inputMask;
1341                                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,                                           // VkImageLayout                        oldLayout;
1342                                         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,                                           // VkImageLayout                        newLayout;
1343                                         VK_QUEUE_FAMILY_IGNORED,                                                                        // deUint32                                     srcQueueFamilyIndex;
1344                                         VK_QUEUE_FAMILY_IGNORED,                                                                        // deUint32                                     destQueueFamilyIndex;
1345                                         *resolveImage,                                                                                          // VkImage                                      image;
1346                                         makeColorSubresourceRange(0, caseDef.numLayers),                        // VkImageSubresourceRange      subresourceRange;
1347                                 },
1348                         };
1349
1350                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1351                                 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
1352                 }
1353                 // Copy resolved image to host-readable buffer
1354                 {
1355                         const VkBufferImageCopy copyRegion =
1356                         {
1357                                 0ull,                                                                                                                           // VkDeviceSize                bufferOffset;
1358                                 0u,                                                                                                                                     // uint32_t                    bufferRowLength;
1359                                 0u,                                                                                                                                     // uint32_t                    bufferImageHeight;
1360                                 makeColorSubresourceLayers(0, caseDef.numLayers),                                       // VkImageSubresourceLayers    imageSubresource;
1361                                 makeOffset3D(0, 0, 0),                                                                                          // VkOffset3D                  imageOffset;
1362                                 makeExtent3D(caseDef.renderSize.x(), caseDef.renderSize.y(), 1u),       // VkExtent3D                  imageExtent;
1363                         };
1364
1365                         vk.cmdCopyImageToBuffer(*cmdBuffer, *resolveImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, resolveBuffer, 1u, &copyRegion);
1366                 }
1367
1368                 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1369                 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1370         }
1371 }
1372
1373 //! Exact image compare, but allow for some error when color format is integer.
1374 bool compareImages (tcu::TestLog& log, const CaseDef& caseDef, const tcu::ConstPixelBufferAccess layeredReferenceImage, const tcu::ConstPixelBufferAccess layeredActualImage)
1375 {
1376         DE_ASSERT(caseDef.numSamples > 1);
1377
1378         const Vec4      goodColor                       = Vec4(0.0f, 1.0f, 0.0f, 1.0f);
1379         const Vec4      badColor                        = Vec4(1.0f, 0.0f, 0.0f, 1.0f);
1380         const bool      isAnyIntFormat          = isIntFormat(caseDef.colorFormat) || isUintFormat(caseDef.colorFormat);
1381
1382         // There should be no mismatched pixels for non-integer formats. Otherwise we may get a wrong color in a location where sample coverage isn't exactly 0 or 1.
1383         const int       badPixelTolerance       = (isAnyIntFormat ? 2 * caseDef.renderSize.x() : 0);
1384         int                     goodLayers                      = 0;
1385
1386         for (int layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx)
1387         {
1388                 const tcu::ConstPixelBufferAccess       referenceImage  = tcu::getSubregion(layeredReferenceImage, 0, 0, layerNdx, caseDef.renderSize.x(), caseDef.renderSize.y(), 1);
1389                 const tcu::ConstPixelBufferAccess       actualImage             = tcu::getSubregion(layeredActualImage, 0, 0, layerNdx, caseDef.renderSize.x(), caseDef.renderSize.y(), 1);
1390                 const std::string                                       imageName               = "color layer " + de::toString(layerNdx);
1391
1392                 tcu::TextureLevel               errorMaskStorage        (tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), caseDef.renderSize.x(), caseDef.renderSize.y());
1393                 tcu::PixelBufferAccess  errorMask                       = errorMaskStorage.getAccess();
1394                 int                                             numBadPixels            = 0;
1395
1396                 for (int y = 0; y < caseDef.renderSize.y(); ++y)
1397                 for (int x = 0; x < caseDef.renderSize.x(); ++x)
1398                 {
1399                         if (isAnyIntFormat && (referenceImage.getPixelInt(x, y) == actualImage.getPixelInt(x, y)))
1400                                 errorMask.setPixel(goodColor, x, y);
1401                         else if (referenceImage.getPixel(x, y) == actualImage.getPixel(x, y))
1402                                 errorMask.setPixel(goodColor, x, y);
1403                         else
1404                         {
1405                                 ++numBadPixels;
1406                                 errorMask.setPixel(badColor, x, y);
1407                         }
1408                 }
1409
1410                 if (numBadPixels <= badPixelTolerance)
1411                 {
1412                         ++goodLayers;
1413
1414                         log << tcu::TestLog::ImageSet(imageName, imageName)
1415                                 << tcu::TestLog::Image("Result",        "Result",               actualImage)
1416                                 << tcu::TestLog::EndImageSet;
1417                 }
1418                 else
1419                 {
1420                         log << tcu::TestLog::ImageSet(imageName, imageName)
1421                                 << tcu::TestLog::Image("Result",        "Result",               actualImage)
1422                                 << tcu::TestLog::Image("Reference",     "Reference",    referenceImage)
1423                                 << tcu::TestLog::Image("ErrorMask",     "Error mask",   errorMask)
1424                                 << tcu::TestLog::EndImageSet;
1425                 }
1426         }
1427
1428         if (goodLayers == caseDef.numLayers)
1429         {
1430                 log << tcu::TestLog::Message << "All rendered images are correct." << tcu::TestLog::EndMessage;
1431                 return true;
1432         }
1433         else
1434         {
1435                 log << tcu::TestLog::Message << "FAILED: Some rendered images were incorrect." << tcu::TestLog::EndMessage;
1436                 return false;
1437         }
1438 }
1439
1440 tcu::TestStatus test (Context& context, const CaseDef caseDef)
1441 {
1442         const DeviceInterface&          vk                                      = context.getDeviceInterface();
1443         const InstanceInterface&        vki                                     = context.getInstanceInterface();
1444         const VkDevice                          device                          = context.getDevice();
1445         const VkPhysicalDevice          physDevice                      = context.getPhysicalDevice();
1446         Allocator&                                      allocator                       = context.getDefaultAllocator();
1447
1448         checkImageFormatRequirements(vki, physDevice, caseDef.numSamples, caseDef.colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT);
1449
1450         {
1451                 tcu::TestLog& log = context.getTestContext().getLog();
1452                 log << tcu::LogSection("Description", "")
1453                         << tcu::TestLog::Message << "Rendering to a multisampled image. Image will be processed with a compute shader using OpImageRead and OpImageWrite." << tcu::TestLog::EndMessage
1454                         << tcu::TestLog::Message << "Expecting the processed image to be roughly the same as the input image (deviation may occur for integer formats)." << tcu::TestLog::EndMessage
1455                         << tcu::TestLog::EndSection;
1456         }
1457
1458         // Host-readable buffer
1459         const VkDeviceSize                              resolveBufferSize                       = caseDef.renderSize.x() * caseDef.renderSize.y() * caseDef.numLayers * tcu::getPixelSize(mapVkFormat(caseDef.colorFormat));
1460         const Unique<VkBuffer>                  resolveImageOneBuffer           (makeBuffer(vk, device, resolveBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1461         const UniquePtr<Allocation>             resolveImageOneBufferAlloc      (bindBuffer(vk, device, allocator, *resolveImageOneBuffer, MemoryRequirement::HostVisible));
1462         const Unique<VkBuffer>                  resolveImageTwoBuffer           (makeBuffer(vk, device, resolveBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1463         const UniquePtr<Allocation>             resolveImageTwoBufferAlloc      (bindBuffer(vk, device, allocator, *resolveImageTwoBuffer, MemoryRequirement::HostVisible));
1464
1465         zeroBuffer(vk, device, *resolveImageOneBufferAlloc, resolveBufferSize);
1466         zeroBuffer(vk, device, *resolveImageTwoBufferAlloc, resolveBufferSize);
1467
1468         // Render: repeat the same rendering twice to avoid non-essential API calls and layout transitions (e.g. copy).
1469         {
1470                 renderAndResolve(context, caseDef, *resolveImageOneBuffer, false);      // Pass 1: render a basic multisampled image
1471                 renderAndResolve(context, caseDef, *resolveImageTwoBuffer, true);       // Pass 2: the same but altered with a compute shader
1472         }
1473
1474         // Verify
1475         {
1476                 invalidateMappedMemoryRange(vk, device, resolveImageOneBufferAlloc->getMemory(), resolveImageOneBufferAlloc->getOffset(), resolveBufferSize);
1477                 invalidateMappedMemoryRange(vk, device, resolveImageTwoBufferAlloc->getMemory(), resolveImageTwoBufferAlloc->getOffset(), resolveBufferSize);
1478
1479                 const tcu::PixelBufferAccess            layeredImageOne (mapVkFormat(caseDef.colorFormat), caseDef.renderSize.x(), caseDef.renderSize.y(), caseDef.numLayers, resolveImageOneBufferAlloc->getHostPtr());
1480                 const tcu::ConstPixelBufferAccess       layeredImageTwo (mapVkFormat(caseDef.colorFormat), caseDef.renderSize.x(), caseDef.renderSize.y(), caseDef.numLayers, resolveImageTwoBufferAlloc->getHostPtr());
1481
1482                 // Check all layers
1483                 if (!compareImages(context.getTestContext().getLog(), caseDef, layeredImageOne, layeredImageTwo))
1484                         return tcu::TestStatus::fail("Rendered images are not correct");
1485         }
1486
1487         return tcu::TestStatus::pass("OK");
1488 }
1489
1490 } // StorageImage ns
1491
1492 std::string getSizeLayerString (const IVec2& size, const int numLayers)
1493 {
1494         std::ostringstream str;
1495         str << size.x() << "x" << size.y() << "_" << numLayers;
1496         return str.str();
1497 }
1498
1499 std::string getFormatString (const VkFormat format)
1500 {
1501         std::string name(getFormatName(format));
1502         return de::toLower(name.substr(10));
1503 }
1504
1505 void addTestCasesWithFunctions (tcu::TestCaseGroup*                                             group,
1506                                                                 FunctionPrograms1<CaseDef>::Function    initPrograms,
1507                                                                 FunctionInstance1<CaseDef>::Function    testFunc)
1508 {
1509         const IVec2 size[] =
1510         {
1511                 IVec2(64, 64),
1512                 IVec2(79, 31),
1513         };
1514         const int numLayers[] =
1515         {
1516                 1, 4
1517         };
1518         const VkSampleCountFlagBits samples[] =
1519         {
1520                 VK_SAMPLE_COUNT_2_BIT,
1521                 VK_SAMPLE_COUNT_4_BIT,
1522                 VK_SAMPLE_COUNT_8_BIT,
1523                 VK_SAMPLE_COUNT_16_BIT,
1524                 VK_SAMPLE_COUNT_32_BIT,
1525                 VK_SAMPLE_COUNT_64_BIT,
1526         };
1527         const VkFormat format[] =
1528         {
1529                 VK_FORMAT_R8G8B8A8_UNORM,
1530                 VK_FORMAT_R32_UINT,
1531                 VK_FORMAT_R16G16_SINT,
1532                 VK_FORMAT_R32G32B32A32_SFLOAT,
1533         };
1534
1535         for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(size); ++sizeNdx)
1536         for (int layerNdx = 0; layerNdx < DE_LENGTH_OF_ARRAY(numLayers); ++layerNdx)
1537         {
1538                 MovePtr<tcu::TestCaseGroup>     sizeLayerGroup(new tcu::TestCaseGroup(group->getTestContext(), getSizeLayerString(size[sizeNdx], numLayers[layerNdx]).c_str(), ""));
1539                 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(format); ++formatNdx)
1540                 {
1541                         MovePtr<tcu::TestCaseGroup>     formatGroup(new tcu::TestCaseGroup(group->getTestContext(), getFormatString(format[formatNdx]).c_str(), ""));
1542                         for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); ++samplesNdx)
1543                         {
1544                                 std::ostringstream caseName;
1545                                 caseName << "samples_" << getNumSamples(samples[samplesNdx]);
1546
1547                                 const CaseDef caseDef =
1548                                 {
1549                                         size[sizeNdx],                  // IVec2                                        renderSize;
1550                                         numLayers[layerNdx],    // int                                          numLayers;
1551                                         format[formatNdx],              // VkFormat                                     colorFormat;
1552                                         samples[samplesNdx],    // VkSampleCountFlagBits        numSamples;
1553                                 };
1554
1555                                 addFunctionCaseWithPrograms(formatGroup.get(), caseName.str(), "", initPrograms, testFunc, caseDef);
1556                         }
1557                         sizeLayerGroup->addChild(formatGroup.release());
1558                 }
1559                 group->addChild(sizeLayerGroup.release());
1560         }
1561 }
1562
1563 void createSampledImageTestsInGroup (tcu::TestCaseGroup* group)
1564 {
1565         addTestCasesWithFunctions(group, SampledImage::initPrograms, SampledImage::test);
1566 }
1567
1568 void createStorageImageTestsInGroup (tcu::TestCaseGroup* group)
1569 {
1570         addTestCasesWithFunctions(group, StorageImage::initPrograms, StorageImage::test);
1571 }
1572
1573 } // anonymous ns
1574
1575 //! Render to a multisampled image and sample from it in a fragment shader.
1576 tcu::TestCaseGroup* createMultisampleSampledImageTests (tcu::TestContext& testCtx)
1577 {
1578         return createTestGroup(testCtx, "sampled_image", "Multisampled image direct sample access", createSampledImageTestsInGroup);
1579 }
1580
1581 //! Render to a multisampled image and access it with load/stores in a compute shader.
1582 tcu::TestCaseGroup* createMultisampleStorageImageTests (tcu::TestContext& testCtx)
1583 {
1584         return createTestGroup(testCtx, "storage_image", "Multisampled image draw and read/write in compute shader", createStorageImageTestsInGroup);
1585 }
1586
1587 } // pipeline
1588 } // vkt