Merge vk-gl-cts/vulkan-cts-1.1.6 into vk-gl-cts/master
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / pipeline / vktPipelineMultisampleShaderFragmentMaskTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2019 Advanced Micro Devices, Inc.
6  * Copyright (c) 2019 The Khronos Group Inc.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Tests for VK_AMD_shader_fragment_mask
23  *//*--------------------------------------------------------------------*/
24
25 #include "vktPipelineMultisampleShaderFragmentMaskTests.hpp"
26 #include "vktPipelineMakeUtil.hpp"
27 #include "vktTestCase.hpp"
28 #include "vktTestCaseUtil.hpp"
29 #include "vktTestGroupUtil.hpp"
30
31 #include "vkCmdUtil.hpp"
32 #include "vkObjUtil.hpp"
33 #include "vkPlatform.hpp"
34 #include "vkMemUtil.hpp"
35 #include "vkQueryUtil.hpp"
36 #include "vkTypeUtil.hpp"
37 #include "vkRefUtil.hpp"
38 #include "vkBuilderUtil.hpp"
39 #include "vkPrograms.hpp"
40 #include "vkImageUtil.hpp"
41
42 #include "deUniquePtr.hpp"
43 #include "deSharedPtr.hpp"
44 #include "deRandom.hpp"
45
46 #include "tcuVector.hpp"
47 #include "tcuTestLog.hpp"
48 #include "tcuImageCompare.hpp"
49 #include "tcuTestLog.hpp"
50 #include "tcuTextureUtil.hpp"
51
52 #include <string>
53 #include <vector>
54
55 namespace vkt
56 {
57 namespace pipeline
58 {
59 namespace
60 {
61 using namespace vk;
62 using de::UniquePtr;
63 using de::MovePtr;
64 using de::SharedPtr;
65 using tcu::UVec2;
66 using tcu::UVec4;
67 using tcu::Vec2;
68 using tcu::Vec4;
69
70 typedef SharedPtr<Unique<VkImageView> >         ImageViewSp;
71 typedef SharedPtr<Unique<VkPipeline> >          PipelineSp;
72
73 struct PositionColor
74 {
75         tcu::Vec4               position;
76         VkClearColorValue       color;
77
78         PositionColor (const tcu::Vec4& pos, const tcu::UVec4& col) : position(pos)
79     {
80         deMemcpy(color.uint32, col.getPtr(), sizeof(color.uint32));
81     }
82
83         PositionColor (const tcu::Vec4& pos, const tcu::Vec4&  col) : position(pos)
84     {
85         deMemcpy(color.float32, col.getPtr(), sizeof(color.float32));
86     }
87
88         PositionColor (const PositionColor& rhs)
89                 : position      (rhs.position)
90         , color     (rhs.color)
91         {
92         }
93 };
94
95 //! Make a dummy sampler.
96 Move<VkSampler> makeSampler (const DeviceInterface& vk, const VkDevice device)
97 {
98         const VkSamplerCreateInfo samplerParams =
99         {
100                 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,                  // VkStructureType         sType;
101                 DE_NULL,                                                                                // const void*             pNext;
102                 (VkSamplerCreateFlags)0,                                                // VkSamplerCreateFlags    flags;
103                 VK_FILTER_NEAREST,                                                              // VkFilter                magFilter;
104                 VK_FILTER_NEAREST,                                                              // VkFilter                minFilter;
105                 VK_SAMPLER_MIPMAP_MODE_NEAREST,                                 // VkSamplerMipmapMode     mipmapMode;
106                 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,                  // VkSamplerAddressMode    addressModeU;
107                 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,                  // VkSamplerAddressMode    addressModeV;
108                 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,                  // VkSamplerAddressMode    addressModeW;
109                 0.0f,                                                                                   // float                   mipLodBias;
110                 VK_FALSE,                                                                               // VkBool32                anisotropyEnable;
111                 1.0f,                                                                                   // float                   maxAnisotropy;
112                 VK_FALSE,                                                                               // VkBool32                compareEnable;
113                 VK_COMPARE_OP_ALWAYS,                                                   // VkCompareOp             compareOp;
114                 0.0f,                                                                                   // float                   minLod;
115                 0.0f,                                                                                   // float                   maxLod;
116                 VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,                // VkBorderColor           borderColor;
117                 VK_FALSE,                                                                               // VkBool32                unnormalizedCoordinates;
118         };
119         return createSampler(vk, device, &samplerParams);
120 }
121
122 Move<VkImage> makeImage (const DeviceInterface&                 vk,
123                                                  const VkDevice                                 device,
124                                                  const VkFormat                                 format,
125                                                  const UVec2&                                   size,
126                                                  const deUint32                                 layers,
127                                                  const VkSampleCountFlagBits    samples,
128                                                  const VkImageUsageFlags                usage)
129 {
130         const VkImageCreateInfo imageParams =
131         {
132                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                    // VkStructureType                      sType;
133                 DE_NULL,                                                                                // const void*                          pNext;
134                 (VkImageCreateFlags)0,                                                  // VkImageCreateFlags           flags;
135                 VK_IMAGE_TYPE_2D,                                                               // VkImageType                          imageType;
136                 format,                                                                                 // VkFormat                                     format;
137                 makeExtent3D(size.x(), size.y(), 1),                    // VkExtent3D                           extent;
138                 1u,                                                                                             // deUint32                                     mipLevels;
139                 layers,                                                                                 // deUint32                                     arrayLayers;
140                 samples,                                                                                // VkSampleCountFlagBits        samples;
141                 VK_IMAGE_TILING_OPTIMAL,                                                // VkImageTiling                        tiling;
142                 usage,                                                                                  // VkImageUsageFlags            usage;
143                 VK_SHARING_MODE_EXCLUSIVE,                                              // VkSharingMode                        sharingMode;
144                 0u,                                                                                             // deUint32                                     queueFamilyIndexCount;
145                 DE_NULL,                                                                                // const deUint32*                      pQueueFamilyIndices;
146                 VK_IMAGE_LAYOUT_UNDEFINED,                                              // VkImageLayout                        initialLayout;
147         };
148         return createImage(vk, device, &imageParams);
149 }
150
151 //! Create a test-specific MSAA pipeline
152 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&                                   vk,
153                                                                            const VkDevice                                                       device,
154                                                                            const VkPipelineLayout                                       pipelineLayout,
155                                                                            const VkRenderPass                                           renderPass,
156                                                                            const VkShaderModule                                         vertexModule,
157                                                                            const VkShaderModule                                         fragmentModule,
158                                                                            const bool                                                           useVertexInput,
159                                                                            const VkFormat                                                       vertexAttribColorFormat,
160                                                                            const bool                                                           useColorAttachment,
161                                                                            const deUint32                                                       subpassNdx,
162                                                                            const UVec2&                                                         renderSize,
163                                                                            const VkSampleCountFlagBits                          numSamples)
164 {
165         std::vector<VkVertexInputBindingDescription>    vertexInputBindingDescriptions;
166         std::vector<VkVertexInputAttributeDescription>  vertexInputAttributeDescriptions;
167
168         // Vertex attributes: position and color
169         if (useVertexInput)
170         {
171                 vertexInputBindingDescriptions.push_back  (makeVertexInputBindingDescription  (0u, sizeof(PositionColor), VK_VERTEX_INPUT_RATE_VERTEX));
172                 vertexInputAttributeDescriptions.push_back(makeVertexInputAttributeDescription(0u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, 0u));
173                 vertexInputAttributeDescriptions.push_back(makeVertexInputAttributeDescription(1u, 0u, vertexAttribColorFormat, sizeof(Vec4)));
174         }
175
176         const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
177         {
178                 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,              // VkStructureType                                                      sType;
179                 DE_NULL,                                                                                                                // const void*                                                          pNext;
180                 (VkPipelineVertexInputStateCreateFlags)0,                                               // VkPipelineVertexInputStateCreateFlags        flags;
181                 static_cast<deUint32>(vertexInputBindingDescriptions.size()),   // uint32_t                                                                     vertexBindingDescriptionCount;
182                 dataOrNullPtr(vertexInputBindingDescriptions),                                  // const VkVertexInputBindingDescription*       pVertexBindingDescriptions;
183                 static_cast<deUint32>(vertexInputAttributeDescriptions.size()), // uint32_t                                                                     vertexAttributeDescriptionCount;
184                 dataOrNullPtr(vertexInputAttributeDescriptions),                                // const VkVertexInputAttributeDescription*     pVertexAttributeDescriptions;
185         };
186
187         const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
188         {
189                 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,    // VkStructureType                                                      sType;
190                 DE_NULL,                                                                                                                // const void*                                                          pNext;
191                 (VkPipelineInputAssemblyStateCreateFlags)0,                                             // VkPipelineInputAssemblyStateCreateFlags      flags;
192                 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,                                                    // VkPrimitiveTopology                                          topology;
193                 VK_FALSE,                                                                                                               // VkBool32                                                                     primitiveRestartEnable;
194         };
195
196         const VkViewport viewport =
197         {
198                 0.0f, 0.0f,                                                                                                                                     // x, y
199                 static_cast<float>(renderSize.x()), static_cast<float>(renderSize.y()),         // widht, height
200                 0.0f, 1.0f                                                                                                                                      // minDepth, maxDepth
201         };
202
203         const VkRect2D scissor =
204         {
205                 makeOffset2D(0, 0),
206                 makeExtent2D(renderSize.x(), renderSize.y()),
207         };
208
209         const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
210         {
211                 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,                  // VkStructureType                                              sType;
212                 DE_NULL,                                                                                                                // const void*                                                  pNext;
213                 (VkPipelineViewportStateCreateFlags)0,                                                  // VkPipelineViewportStateCreateFlags   flags;
214                 1u,                                                                                                                             // uint32_t                                                             viewportCount;
215                 &viewport,                                                                                                              // const VkViewport*                                    pViewports;
216                 1u,                                                                                                                             // uint32_t                                                             scissorCount;
217                 &scissor,                                                                                                               // const VkRect2D*                                              pScissors;
218         };
219
220         const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
221         {
222                 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,     // VkStructureType                                                      sType;
223                 DE_NULL,                                                                                                        // const void*                                                          pNext;
224                 (VkPipelineRasterizationStateCreateFlags)0,                                     // VkPipelineRasterizationStateCreateFlags      flags;
225                 VK_FALSE,                                                                                                       // VkBool32                                                                     depthClampEnable;
226                 VK_FALSE,                                                                                                       // VkBool32                                                                     rasterizerDiscardEnable;
227                 VK_POLYGON_MODE_FILL,                                                                           // VkPolygonMode                                                        polygonMode;
228                 VK_CULL_MODE_NONE,                                                                                      // VkCullModeFlags                                                      cullMode;
229                 VK_FRONT_FACE_COUNTER_CLOCKWISE,                                                        // VkFrontFace                                                          frontFace;
230                 VK_FALSE,                                                                                                       // VkBool32                                                                     depthBiasEnable;
231                 0.0f,                                                                                                           // float                                                                        depthBiasConstantFactor;
232                 0.0f,                                                                                                           // float                                                                        depthBiasClamp;
233                 0.0f,                                                                                                           // float                                                                        depthBiasSlopeFactor;
234                 1.0f,                                                                                                           // float                                                                        lineWidth;
235         };
236
237         const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
238         {
239                 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,       // VkStructureType                                                      sType;
240                 DE_NULL,                                                                                                        // const void*                                                          pNext;
241                 (VkPipelineMultisampleStateCreateFlags)0,                                       // VkPipelineMultisampleStateCreateFlags        flags;
242                 numSamples,                                                                                                     // VkSampleCountFlagBits                                        rasterizationSamples;
243                 VK_FALSE,                                                                                                       // VkBool32                                                                     sampleShadingEnable;
244                 1.0f,                                                                                                           // float                                                                        minSampleShading;
245                 DE_NULL,                                                                                                        // const VkSampleMask*                                          pSampleMask;
246                 VK_FALSE,                                                                                                       // VkBool32                                                                     alphaToCoverageEnable;
247                 VK_FALSE                                                                                                        // VkBool32                                                                     alphaToOneEnable;
248         };
249
250         VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
251         {
252                 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,     // VkStructureType                                                      sType;
253                 DE_NULL,                                                                                                        // const void*                                                          pNext;
254                 (VkPipelineDepthStencilStateCreateFlags)0,                                      // VkPipelineDepthStencilStateCreateFlags       flags;
255                 VK_FALSE,                                                                                                       // VkBool32                                                                     depthTestEnable;
256                 VK_TRUE,                                                                                                        // VkBool32                                                                     depthWriteEnable;
257                 VK_COMPARE_OP_ALWAYS,                                                                           // VkCompareOp                                                          depthCompareOp;
258                 VK_FALSE,                                                                                                       // VkBool32                                                                     depthBoundsTestEnable;
259                 VK_FALSE,                                                                                                       // VkBool32                                                                     stencilTestEnable;
260                 VkStencilOpState(),                                                                                     // VkStencilOpState                                                     front;
261                 VkStencilOpState(),                                                                                     // VkStencilOpState                                                     back;
262                 0.0f,                                                                                                           // float                                                                        minDepthBounds;
263                 1.0f,                                                                                                           // float                                                                        maxDepthBounds;
264         };
265
266         const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
267         const VkPipelineColorBlendAttachmentState defaultBlendAttachmentState =
268         {
269                 VK_FALSE,                               // VkBool32                                     blendEnable;
270                 VK_BLEND_FACTOR_ONE,    // VkBlendFactor                        srcColorBlendFactor;
271                 VK_BLEND_FACTOR_ZERO,   // VkBlendFactor                        dstColorBlendFactor;
272                 VK_BLEND_OP_ADD,                // VkBlendOp                            colorBlendOp;
273                 VK_BLEND_FACTOR_ONE,    // VkBlendFactor                        srcAlphaBlendFactor;
274                 VK_BLEND_FACTOR_ZERO,   // VkBlendFactor                        dstAlphaBlendFactor;
275                 VK_BLEND_OP_ADD,                // VkBlendOp                            alphaBlendOp;
276                 colorComponentsAll,             // VkColorComponentFlags        colorWriteMask;
277         };
278
279         const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
280         {
281                 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,       // VkStructureType                                                              sType;
282                 DE_NULL,                                                                                                        // const void*                                                                  pNext;
283                 (VkPipelineColorBlendStateCreateFlags)0,                                        // VkPipelineColorBlendStateCreateFlags                 flags;
284                 VK_FALSE,                                                                                                       // VkBool32                                                                             logicOpEnable;
285                 VK_LOGIC_OP_COPY,                                                                                       // VkLogicOp                                                                    logicOp;
286                 (useColorAttachment ? 1u : 0u),                                                         // deUint32                                                                             attachmentCount;
287                 &defaultBlendAttachmentState,                                                           // const VkPipelineColorBlendAttachmentState*   pAttachments;
288                 { 0.0f, 0.0f, 0.0f, 0.0f },                                                                     // float                                                                                blendConstants[4];
289         };
290
291         const VkPipelineShaderStageCreateInfo pShaderStages[] =
292         {
293                 {
294                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    // VkStructureType                                              sType;
295                         DE_NULL,                                                                                                // const void*                                                  pNext;
296                         (VkPipelineShaderStageCreateFlags)0,                                    // VkPipelineShaderStageCreateFlags             flags;
297                         VK_SHADER_STAGE_VERTEX_BIT,                                                             // VkShaderStageFlagBits                                stage;
298                         vertexModule,                                                                                   // VkShaderModule                                               module;
299                         "main",                                                                                                 // const char*                                                  pName;
300                         DE_NULL,                                                                                                // const VkSpecializationInfo*                  pSpecializationInfo;
301                 },
302                 {
303                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    // VkStructureType                                              sType;
304                         DE_NULL,                                                                                                // const void*                                                  pNext;
305                         (VkPipelineShaderStageCreateFlags)0,                                    // VkPipelineShaderStageCreateFlags             flags;
306                         VK_SHADER_STAGE_FRAGMENT_BIT,                                                   // VkShaderStageFlagBits                                stage;
307                         fragmentModule,                                                                                 // VkShaderModule                                               module;
308                         "main",                                                                                                 // const char*                                                  pName;
309                         DE_NULL,                                                                                                // const VkSpecializationInfo*                  pSpecializationInfo;
310                 }
311         };
312
313         const VkGraphicsPipelineCreateInfo      graphicsPipelineInfo =
314         {
315                 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,        // VkStructureType                                                                      sType;
316                 DE_NULL,                                                                                        // const void*                                                                          pNext;
317                 (VkPipelineCreateFlags)0,                                                       // VkPipelineCreateFlags                                                        flags;
318                 DE_LENGTH_OF_ARRAY(pShaderStages),                                      // deUint32                                                                                     stageCount;
319                 pShaderStages,                                                                          // const VkPipelineShaderStageCreateInfo*                       pStages;
320                 &vertexInputStateInfo,                                                          // const VkPipelineVertexInputStateCreateInfo*          pVertexInputState;
321                 &pipelineInputAssemblyStateInfo,                                        // const VkPipelineInputAssemblyStateCreateInfo*        pInputAssemblyState;
322                 DE_NULL,                                                                                        // const VkPipelineTessellationStateCreateInfo*         pTessellationState;
323                 &pipelineViewportStateInfo,                                                     // const VkPipelineViewportStateCreateInfo*                     pViewportState;
324                 &pipelineRasterizationStateInfo,                                        // const VkPipelineRasterizationStateCreateInfo*        pRasterizationState;
325                 &pipelineMultisampleStateInfo,                                          // const VkPipelineMultisampleStateCreateInfo*          pMultisampleState;
326                 &pipelineDepthStencilStateInfo,                                         // const VkPipelineDepthStencilStateCreateInfo*         pDepthStencilState;
327                 &pipelineColorBlendStateInfo,                                           // const VkPipelineColorBlendStateCreateInfo*           pColorBlendState;
328                 DE_NULL,                                                                                        // const VkPipelineDynamicStateCreateInfo*                      pDynamicState;
329                 pipelineLayout,                                                                         // VkPipelineLayout                                                                     layout;
330                 renderPass,                                                                                     // VkRenderPass                                                                         renderPass;
331                 subpassNdx,                                                                                     // deUint32                                                                                     subpass;
332                 DE_NULL,                                                                                        // VkPipeline                                                                           basePipelineHandle;
333                 -1,                                                                                                     // deInt32                                                                                      basePipelineIndex;
334         };
335
336         return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
337 }
338
339 std::vector<PositionColor> genShapes (const VkFormat colorFormat)
340 {
341         std::vector<PositionColor> vertices;
342
343         if (colorFormat == VK_FORMAT_R8G8B8A8_UNORM)
344         {
345                 vertices.push_back(PositionColor(Vec4( 0.0f,  -0.75f, 0.0f, 1.0f), Vec4(0.5f, 0.5f, 0.5f, 1.0f)));
346                 vertices.push_back(PositionColor(Vec4(-0.75f,  0.75f, 0.0f, 1.0f), Vec4(1.0f, 0.5f, 0.5f, 1.0f)));
347                 vertices.push_back(PositionColor(Vec4( 0.75f,  0.65f, 0.0f, 1.0f), Vec4(0.0f, 0.5f, 1.0f, 1.0f)));
348         }
349         else
350         {
351                 vertices.push_back(PositionColor(Vec4( 0.0f,  -0.75f, 0.0f, 1.0f), UVec4(0xabcdu, 0u, 0u, 0u)));
352                 vertices.push_back(PositionColor(Vec4(-0.75f,  0.75f, 0.0f, 1.0f), UVec4(0xbcdeu, 0u, 0u, 0u)));
353                 vertices.push_back(PositionColor(Vec4( 0.75f,  0.65f, 0.0f, 1.0f), UVec4(0xcdefu, 0u, 0u, 0u)));
354         }
355
356         return vertices;
357 }
358
359 //! Map color image format to a convenient format used in vertex attributes
360 VkFormat getVertexInputColorFormat (const VkFormat colorImageFormat)
361 {
362         switch (tcu::getTextureChannelClass(mapVkFormat(colorImageFormat).type))
363         {
364                 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
365                 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
366                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
367                         return VK_FORMAT_R32G32B32A32_SFLOAT;
368
369                 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
370                         return VK_FORMAT_R32G32B32A32_SINT;
371
372                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
373                         return VK_FORMAT_R32G32B32A32_UINT;
374
375                 default:
376                         DE_ASSERT(0);
377                         return VK_FORMAT_UNDEFINED;
378         }
379 }
380
381 enum SampleSource
382 {
383         SAMPLE_SOURCE_IMAGE,                    //!< texel fetch from an image
384         SAMPLE_SOURCE_SUBPASS_INPUT,    //!< texel fetch from an input attachment
385 };
386
387 //! The parameters that define a test case
388 struct TestParams
389 {
390         UVec2                                   renderSize;
391         deUint32                                numLayers;                      //!< 1 or N for layered image
392         SampleSource                    sampleSource;           //!< source of texel fetch
393         VkSampleCountFlagBits   numColorSamples;
394         VkFormat                                colorFormat;            //!< Color attachment format
395
396         TestParams (void)
397                 : numLayers                     ()
398                 , numColorSamples       ()
399                 , colorFormat           ()
400         {
401         }
402 };
403
404 void checkRequirements (Context& context, TestParams params)
405 {
406         context.requireDeviceFunctionality("VK_AMD_shader_fragment_mask");
407
408         // In the subpass input case we have to store fetch results into a buffer for subsequent verification in a compute shader.
409         const bool requireFragmentStores = (params.sampleSource == SAMPLE_SOURCE_SUBPASS_INPUT);
410
411         const VkPhysicalDeviceLimits& limits = context.getDeviceProperties().limits;
412
413         if ((limits.framebufferColorSampleCounts & params.numColorSamples) == 0u)
414                 TCU_THROW(NotSupportedError, "framebufferColorSampleCounts: sample count not supported");
415
416         if ((isIntFormat(params.colorFormat) || isUintFormat(params.colorFormat)))
417         {
418                 if ((limits.sampledImageIntegerSampleCounts & params.numColorSamples) == 0u)
419                         TCU_THROW(NotSupportedError, "sampledImageIntegerSampleCounts: sample count not supported");
420         }
421         else
422         {
423                 if ((limits.sampledImageColorSampleCounts & params.numColorSamples) == 0u)
424                         TCU_THROW(NotSupportedError, "sampledImageColorSampleCounts: sample count not supported");
425         }
426
427         if (requireFragmentStores)
428         {
429                 if (!context.getDeviceFeatures().fragmentStoresAndAtomics)
430                         TCU_THROW(NotSupportedError, "fragmentStoresAndAtomics: feature not supported");
431         }
432 }
433
434 //! Common data used by the test
435 struct WorkingData
436 {
437         deUint32                                                numVertices;                            //!< Number of vertices defined in the vertex buffer
438         Move<VkBuffer>                                  vertexBuffer;
439         MovePtr<Allocation>                             vertexBufferAlloc;
440         Move<VkImage>                                   colorImage;                                     //!< Color image
441         MovePtr<Allocation>                             colorImageAlloc;
442         Move<VkImageView>                               colorImageView;                         //!< Color image view spanning all layers
443         Move<VkBuffer>                                  colorBuffer;                            //!< Buffer used to copy image data
444         MovePtr<Allocation>                             colorBufferAlloc;
445         VkDeviceSize                                    colorBufferSize;
446         Move<VkSampler>                                 defaultSampler;                         //!< Dummy sampler, we are using texel fetches
447
448         WorkingData (void)
449                 : numVertices           ()
450                 , colorBufferSize       ()
451         {
452         }
453 };
454
455 void initPrograms (SourceCollections& programCollection, const TestParams params)
456 {
457         std::string     colorType;                                      //!< color pixel type used by image functions
458         std::string     colorBufferType;                        //!< packed pixel type as stored in a ssbo
459         std::string colorBufferPack;                    //!< a cast or a function call when writing back color format to the ssbo
460         std::string     colorFragInQualifier;           //!< fragment shader color input qualifier
461         std::string samplerPrefix;                              //!< u, i, or empty
462
463         switch (params.colorFormat)
464         {
465                 case VK_FORMAT_R8G8B8A8_UNORM:
466                         colorType                               = "vec4";
467                         colorBufferType                 = "uint";
468                         colorBufferPack                 = "packUnorm4x8";
469                         break;
470
471                 case VK_FORMAT_R32_UINT:
472                         colorType                               = "uint";
473                         colorBufferType                 = "uint";
474                         colorBufferPack                 = colorBufferType;
475                         colorFragInQualifier    = "flat";
476                         samplerPrefix                   = "u";
477                         break;
478
479                 case VK_FORMAT_R32_SINT:
480                         colorType                               = "int";
481                         colorBufferType                 = "int";
482                         colorBufferPack                 = colorBufferType;
483                         colorFragInQualifier    = "flat";
484                         samplerPrefix                   = "i";
485                         break;
486
487                 default:
488                         DE_FATAL("initPrograms not handled for this color format");
489                         break;
490         }
491
492         // Vertex shader - position and color
493         {
494                 std::ostringstream src;
495                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
496                         << "\n"
497                         << "layout(location = 0) in  vec4 in_position;\n"
498                         << "layout(location = 1) in  " << colorType << " in_color;\n"
499                         << "layout(location = 0) out " << colorType << " o_color;\n"
500                         << "\n"
501                         << "out gl_PerVertex {\n"
502                         << "    vec4 gl_Position;\n"
503                         << "};\n"
504                         << "\n"
505                         << "void main(void)\n"
506                         << "{\n"
507                         // Introduce a variance in geometry per instance index which maps to the image layer
508                         << "    float a   = 0.25 * float(gl_InstanceIndex);\n"
509                         << "    mat3 rm   = mat3( cos(a), sin(a), 0.0,\n"
510                         << "                     -sin(a), cos(a), 0.0,\n"
511                         << "                         0.0,    0.0, 1.0);\n"
512                         << "    vec2 rpos = (rm * vec3(in_position.xy, 1.0)).xy;\n"
513                         << "\n"
514                         << "    gl_Position = vec4(rpos, in_position.zw);\n"
515                         << "    o_color     = in_color;\n"
516                         << "}\n";
517
518                 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
519         }
520
521         // Vertex shader - no vertex data, fill viewport with one primitive
522         {
523                 std::ostringstream src;
524                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
525                         << "\n"
526                         << "out gl_PerVertex {\n"
527                         << "    vec4 gl_Position;\n"
528                         << "};\n"
529                         << "\n"
530                         << "void main(void)\n"
531                         << "{\n"
532                         // Specify an oversized triangle covering the whole viewport.
533                         << "    switch (gl_VertexIndex)\n"
534                         << "    {\n"
535                         << "        case 0:\n"
536                         << "            gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
537                         << "            break;\n"
538                         << "        case 1:\n"
539                         << "            gl_Position = vec4(-1.0,  3.0, 0.0, 1.0);\n"
540                         << "            break;\n"
541                         << "        case 2:\n"
542                         << "            gl_Position = vec4( 3.0, -1.0, 0.0, 1.0);\n"
543                         << "            break;\n"
544                         << "    }\n"
545                         << "}\n";
546
547                 programCollection.glslSources.add("vert_full") << glu::VertexSource(src.str());
548         }
549
550         // Fragment shader - output color from VS
551         {
552                 std::ostringstream src;
553                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
554                         << "\n"
555                         << "layout(location = 0) in " << colorFragInQualifier << " " << colorType << " in_color;\n"
556                         << "layout(location = 0) out " << colorType << " o_color;\n"
557                         << "\n"
558                         << "void main(void)\n"
559                         << "{\n"
560                         << "    o_color = in_color;\n"
561                         << "}\n";
562
563                 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
564         }
565
566         // Fragment shader - FMASK fetch from an input attachment
567         if (params.sampleSource == SAMPLE_SOURCE_SUBPASS_INPUT)
568         {
569                 std::ostringstream src;
570                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
571                         << "#extension GL_AMD_shader_fragment_mask : enable\n"
572                         << "\n"
573                         << "layout(set = 0, binding = 0) uniform " << samplerPrefix << "sampler2DMS" << (params.numLayers > 1 ? "Array" : "") << " u_image;\n"
574                         << "layout(set = 0, binding = 1, std430) writeonly buffer ColorOutput {\n"
575                         << "    " << colorBufferType << " color[];\n"
576                         << "} sb_out;\n"
577                         << "layout(input_attachment_index = " << params.numLayers << ", set = 0, binding = 2) uniform " << samplerPrefix << "subpassInputMS" << " input_attach;\n"
578                         << "\n"
579                         << "void main(void)\n"
580                         << "{\n"
581                         << "    ivec2 p            = ivec2(gl_FragCoord.xy);\n"
582                         << "    int   width        = " << params.renderSize.x() << ";\n"
583                         << "    int   numSamples   = " << static_cast<deUint32>(params.numColorSamples) << ";\n"
584                         << "    int   colorOutNdx  = numSamples * (p.x + width * p.y);\n"
585                         << "\n"
586                         << "    uint mask = fragmentMaskFetchAMD(input_attach);\n"
587                         << "    for (int sampleNdx = 0; sampleNdx < numSamples; ++sampleNdx)\n"
588                         << "    {\n"
589                         << "        int fragNdx = int((mask >> (4 * sampleNdx)) & 0xf);\n"
590                         << "        " << samplerPrefix << "vec4 color = fragmentFetchAMD(input_attach, fragNdx);\n"
591                         << "        sb_out.color[colorOutNdx + sampleNdx] = " << colorBufferPack << "(color);\n"
592                         << "    }\n"
593                         << "}\n";
594
595                 programCollection.glslSources.add("frag_fmask_fetch") << glu::FragmentSource(src.str());
596         }
597
598         // Generate compute shaders
599         const struct ComputeShaderParams
600         {
601                 const char*             name;
602                 bool                    isFmaskFetch;
603                 bool                    enabled;
604         } computeShaders[] =
605         {
606                 // name                                 // FMASK?       // enabled?
607                 { "comp_fetch",                 false,          true,                                                                                                   },
608                 { "comp_fmask_fetch",   true,           (params.sampleSource != SAMPLE_SOURCE_SUBPASS_INPUT)    },
609         };
610
611         for (const ComputeShaderParams* pShaderParams = computeShaders; pShaderParams != DE_ARRAY_END(computeShaders); ++pShaderParams)
612         if (pShaderParams->enabled)
613         {
614                 const std::string samplingPos = (params.numLayers == 1 ? "ivec2(gl_WorkGroupID.xy)"
615                                                                                                                            : "ivec3(gl_WorkGroupID)");
616                 std::ostringstream src;
617                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
618                         << (pShaderParams->isFmaskFetch ? "#extension GL_AMD_shader_fragment_mask : enable\n" : "")
619                         << "#define NUM_SAMPLES " << static_cast<deUint32>(params.numColorSamples) << "\n"
620                         << "\n"
621                         << "layout(local_size_x = NUM_SAMPLES) in;\n"   // one work group per pixel, each sample gets a local invocation
622                         << "\n"
623                         << "layout(set = 0, binding = 0) uniform " << samplerPrefix << "sampler2DMS" << (params.numLayers > 1 ? "Array" : "") << " u_image;\n"
624                         << "layout(set = 0, binding = 1, std430) writeonly buffer ColorOutput {\n"
625                         << "    " << colorBufferType << " color[];\n"
626                         << "} sb_out;\n"
627                         << "\n"
628                         << "void main(void)\n"
629                         << "{\n"
630                         << "    int sampleNdx   = int(gl_LocalInvocationID.x);\n"
631                         << "    int colorOutNdx = NUM_SAMPLES * int(gl_WorkGroupID.x +\n"
632                         << "                                        gl_WorkGroupID.y * gl_NumWorkGroups.x +\n"
633                         << "                                        gl_WorkGroupID.z * gl_NumWorkGroups.x * gl_NumWorkGroups.y);\n"
634                         << "\n";
635                 if (pShaderParams->isFmaskFetch)
636                 {
637                         src << "    uint  mask    = fragmentMaskFetchAMD(u_image, " << samplingPos << ");\n"
638                                 << "    int   fragNdx = int((mask >> (4 * sampleNdx)) & 0xf);\n"
639                                 << "    " << samplerPrefix << "vec4 color = fragmentFetchAMD(u_image, " << samplingPos << ", fragNdx);\n"
640                                 << "    sb_out.color[colorOutNdx + sampleNdx] = " << colorBufferPack << "(color);\n";
641                 }
642                 else
643                 {
644                         src << "    " << samplerPrefix << "vec4 color = texelFetch(u_image, " << samplingPos << ", sampleNdx);\n"
645                                 << "    sb_out.color[colorOutNdx + sampleNdx] = " << colorBufferPack << "(color);\n";
646                 }
647                 src << "}\n";
648
649                 programCollection.glslSources.add(pShaderParams->name) << glu::ComputeSource(src.str());
650         }
651 }
652
653 std::vector<VkClearValue> genClearValues (const VkFormat format, const deUint32 count)
654 {
655         std::vector<VkClearValue>       clearValues;
656         de::Random                                      rng (332);
657
658         switch (format)
659         {
660                 case VK_FORMAT_R8G8B8A8_UNORM:
661                         for (deUint32 i = 0u; i < count; ++i)
662                                 clearValues.push_back(makeClearValueColorF32(rng.getFloat(), rng.getFloat(), rng.getFloat(), 1.0f));
663                         break;
664
665                 case VK_FORMAT_R32_UINT:
666                 case VK_FORMAT_R32_SINT:
667                         for (deUint32 i = 0u; i < count; ++i)
668                                 clearValues.push_back(makeClearValueColorU32(rng.getUint32(), 0u, 0u, 0u));
669                         break;
670
671                 default:
672                         DE_FATAL("Clear color not defined for this format");
673                         break;
674         }
675
676         return clearValues;
677 }
678
679 //! For subpass load case draw and fetch must happen within the same render pass.
680 void drawAndSampleInputAttachment (Context& context, const TestParams& params, WorkingData& wd)
681 {
682         DE_ASSERT(params.numLayers == 1u);      // subpass load with single-layer image
683
684         const DeviceInterface&  vk              = context.getDeviceInterface();
685         const VkDevice                  device  = context.getDevice();
686
687         Move<VkRenderPass>              renderPass;
688         Move<VkFramebuffer>             framebuffer;
689
690         // Create descriptor set
691         const Unique<VkDescriptorSetLayout> descriptorSetLayout (DescriptorSetLayoutBuilder()
692                 .addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,     VK_SHADER_STAGE_FRAGMENT_BIT, &wd.defaultSampler.get())
693                 .addSingleBinding               (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,                     VK_SHADER_STAGE_FRAGMENT_BIT)
694                 .addSingleBinding               (VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,           VK_SHADER_STAGE_FRAGMENT_BIT)
695                 .build(vk, device));
696
697         const Unique<VkDescriptorPool> descriptorPool (DescriptorPoolBuilder()
698                 .addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
699                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
700                 .addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)
701                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
702
703         const Unique<VkDescriptorSet> descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
704
705         {
706                 const VkDescriptorImageInfo             colorImageInfo  = makeDescriptorImageInfo(DE_NULL, *wd.colorImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
707                 const VkDescriptorBufferInfo    bufferInfo              = makeDescriptorBufferInfo(*wd.colorBuffer, 0u, wd.colorBufferSize);
708
709                 DescriptorSetUpdateBuilder      builder;
710
711                 builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &colorImageInfo);
712                 builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,                &bufferInfo);
713
714                 if (params.sampleSource == SAMPLE_SOURCE_SUBPASS_INPUT)
715                         builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(2u), VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &colorImageInfo);
716
717                 builder.update(vk, device);
718         }
719
720         // Create a render pass and a framebuffer
721         {
722                 std::vector<VkSubpassDescription>               subpasses;
723                 std::vector<VkSubpassDependency>                subpassDependencies;
724                 std::vector<VkImageView>                                attachments;
725                 std::vector<VkAttachmentDescription>    attachmentDescriptions;
726                 std::vector<VkAttachmentReference>              attachmentReferences;
727
728                 // Reserve capacity to avoid invalidating pointers to elements
729                 attachmentReferences.reserve(2);        // color image + input attachment
730
731                 // Create a MS draw subpass
732                 {
733                         attachments.push_back(*wd.colorImageView);
734
735                         attachmentDescriptions.push_back(makeAttachmentDescription(
736                                 (VkAttachmentDescriptionFlags)0,                                                                // VkAttachmentDescriptionFlags         flags;
737                                 params.colorFormat,                                                                                             // VkFormat                                                     format;
738                                 params.numColorSamples,                                                                                 // VkSampleCountFlagBits                        samples;
739                                 VK_ATTACHMENT_LOAD_OP_CLEAR,                                                                    // VkAttachmentLoadOp                           loadOp;
740                                 VK_ATTACHMENT_STORE_OP_STORE,                                                                   // VkAttachmentStoreOp                          storeOp;
741                                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,                                                                // VkAttachmentLoadOp                           stencilLoadOp;
742                                 VK_ATTACHMENT_STORE_OP_DONT_CARE,                                                               // VkAttachmentStoreOp                          stencilStoreOp;
743                                 VK_IMAGE_LAYOUT_UNDEFINED,                                                                              // VkImageLayout                                        initialLayout;
744                                 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL                                                // VkImageLayout                                        finalLayout;
745                         ));
746
747                         attachmentReferences.push_back(makeAttachmentReference(static_cast<deUint32>(attachmentReferences.size()),      VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
748                         const VkAttachmentReference* colorRef = &attachmentReferences.back();
749
750                         const VkSubpassDescription subpassDescription =
751                         {
752                                 (VkSubpassDescriptionFlags)0,                                           // VkSubpassDescriptionFlags       flags;
753                                 VK_PIPELINE_BIND_POINT_GRAPHICS,                                        // VkPipelineBindPoint             pipelineBindPoint;
754                                 0u,                                                                                                     // uint32_t                        inputAttachmentCount;
755                                 DE_NULL,                                                                                        // const VkAttachmentReference*    pInputAttachments;
756                                 1u,                                                                                                     // uint32_t                        colorAttachmentCount;
757                                 colorRef,                                                                                       // const VkAttachmentReference*    pColorAttachments;
758                                 DE_NULL,                                                                                        // const VkAttachmentReference*    pResolveAttachments;
759                                 DE_NULL,                                                                                        // const VkAttachmentReference*    pDepthStencilAttachment;
760                                 0u,                                                                                                     // uint32_t                        preserveAttachmentCount;
761                                 DE_NULL,                                                                                        // const uint32_t*                 pPreserveAttachments;
762                         };
763
764                         subpasses.push_back(subpassDescription);
765                 }
766
767                 // Create a sampling subpass
768                 {
769                         attachmentReferences.push_back(makeAttachmentReference(0u, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL));
770                         const VkAttachmentReference* inputRef = &attachmentReferences.back();
771
772                         // No color attachment, side effects only
773                         VkSubpassDescription subpassDescription =
774                         {
775                                 (VkSubpassDescriptionFlags)0,                                           // VkSubpassDescriptionFlags       flags;
776                                 VK_PIPELINE_BIND_POINT_GRAPHICS,                                        // VkPipelineBindPoint             pipelineBindPoint;
777                                 1u,                                                                                                     // uint32_t                        inputAttachmentCount;
778                                 inputRef,                                                                                       // const VkAttachmentReference*    pInputAttachments;
779                                 0u,                                                                                                     // uint32_t                        colorAttachmentCount;
780                                 DE_NULL,                                                                                        // const VkAttachmentReference*    pColorAttachments;
781                                 DE_NULL,                                                                                        // const VkAttachmentReference*    pResolveAttachments;
782                                 DE_NULL,                                                                                        // const VkAttachmentReference*    pDepthStencilAttachment;
783                                 0u,                                                                                                     // uint32_t                        preserveAttachmentCount;
784                                 DE_NULL,                                                                                        // const uint32_t*                 pPreserveAttachments;
785                         };
786
787                         subpasses.push_back(subpassDescription);
788                 }
789
790                 // Serialize the subpasses
791                 {
792                         const VkAccessFlags     dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
793                                                                                           | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT
794                                                                                           | VK_ACCESS_SHADER_WRITE_BIT;
795                         const VkSubpassDependency       dependency      =
796                         {
797                                 0u,                                                                                                                                                                                     // uint32_t                srcSubpass;
798                                 1u,                                                                                                                                                                                     // uint32_t                dstSubpass;
799                                 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,          // VkPipelineStageFlags    srcStageMask;
800                                 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,                                                                                                          // VkPipelineStageFlags    dstStageMask;
801                                 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                                                                                                           // VkAccessFlags           srcAccessMask;
802                                 dstAccessMask,                                                                                                                                                          // VkAccessFlags           dstAccessMask;
803                                 VK_DEPENDENCY_BY_REGION_BIT,                                                                                                                            // VkDependencyFlags       dependencyFlags;
804                         };
805                         subpassDependencies.push_back(dependency);
806                 }
807
808                 VkRenderPassCreateInfo renderPassInfo =
809                 {
810                         VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,                              // VkStructureType                                      sType;
811                         DE_NULL,                                                                                                // const void*                                          pNext;
812                         (VkRenderPassCreateFlags)0,                                                             // VkRenderPassCreateFlags                      flags;
813                         static_cast<deUint32>(attachmentDescriptions.size()),   // deUint32                                                     attachmentCount;
814                         dataOrNullPtr(attachmentDescriptions),                                  // const VkAttachmentDescription*       pAttachments;
815                         static_cast<deUint32>(subpasses.size()),                                // deUint32                                                     subpassCount;
816                         dataOrNullPtr(subpasses),                                                               // const VkSubpassDescription*          pSubpasses;
817                         static_cast<deUint32>(subpassDependencies.size()),              // deUint32                                                     dependencyCount;
818                         dataOrNullPtr(subpassDependencies),                                             // const VkSubpassDependency*           pDependencies;
819                 };
820
821                 renderPass  = createRenderPass(vk, device, &renderPassInfo);
822                 framebuffer = makeFramebuffer (vk, device, *renderPass, static_cast<deUint32>(attachments.size()), dataOrNullPtr(attachments), params.renderSize.x(), params.renderSize.y());
823         }
824
825         const Unique<VkShaderModule>    vertexModuleDraw        (createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u));
826         const Unique<VkShaderModule>    fragmentModuleDraw      (createShaderModule(vk, device, context.getBinaryCollection().get("frag"), 0u));
827
828         // Create pipelines for MS draw
829         const Unique<VkPipelineLayout>  pipelineLayout          (makePipelineLayout(vk, device, *descriptorSetLayout));
830         const Unique<VkPipeline>                pipelineDraw            (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModuleDraw, *fragmentModuleDraw,
831                                                                                                                                                           true/*use vertex attribs*/, getVertexInputColorFormat(params.colorFormat), true/*use color attach*/, 0u/*subpass*/,
832                                                                                                                                                           params.renderSize, params.numColorSamples));
833
834         // Sampling pass is single-sampled, output to storage buffer
835         const Unique<VkShaderModule>    vertexModuleSample              (createShaderModule(vk, device, context.getBinaryCollection().get("vert_full"), 0u));
836         const Unique<VkShaderModule>    fragmentModuleSample    (createShaderModule(vk, device, context.getBinaryCollection().get("frag_fmask_fetch"), 0u));
837
838         // Sampling pipeline
839         const Unique<VkPipeline>                pipelineSample          (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModuleSample, *fragmentModuleSample,
840                                                                                                                                                           false/*use vertex attribs*/, VK_FORMAT_UNDEFINED, false/*no color output*/, 1u/*subpass*/,
841                                                                                                                                                           params.renderSize, VK_SAMPLE_COUNT_1_BIT));
842
843         const Unique<VkCommandPool>             cmdPool         (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, context.getUniversalQueueFamilyIndex()));
844         const Unique<VkCommandBuffer>   cmdBuffer       (makeCommandBuffer(vk, device, *cmdPool));
845
846         beginCommandBuffer(vk, *cmdBuffer);
847
848         {
849                 // Generate clear values
850                 std::vector<VkClearValue> clearValues = genClearValues(params.colorFormat, params.numLayers);
851
852                 const VkRect2D renderArea =
853                 {
854                         { 0u, 0u },
855                         { params.renderSize.x(), params.renderSize.y() }
856                 };
857
858                 const VkRenderPassBeginInfo renderPassBeginInfo =
859                 {
860                         VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,                       // VkStructureType         sType;
861                         DE_NULL,                                                                                        // const void*             pNext;
862                         *renderPass,                                                                            // VkRenderPass            renderPass;
863                         *framebuffer,                                                                           // VkFramebuffer           framebuffer;
864                         renderArea,                                                                                     // VkRect2D                renderArea;
865                         static_cast<deUint32>(clearValues.size()),                      // uint32_t                clearValueCount;
866                         dataOrNullPtr(clearValues),                                                     // const VkClearValue*     pClearValues;
867                 };
868                 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
869         }
870
871         vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
872
873         {
874                 const VkDeviceSize vertexBufferOffset = 0ull;
875                 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &wd.vertexBuffer.get(), &vertexBufferOffset);
876         }
877
878         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineDraw);
879         vk.cmdDraw(*cmdBuffer, wd.numVertices, 1u, 0u, 0u);
880
881         vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
882
883         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineSample);
884         vk.cmdDraw(*cmdBuffer, 3u, 1u, 0u, 0u); // fill the framebuffer, geometry defined in the VS
885
886         vk.cmdEndRenderPass(*cmdBuffer);
887
888         // Buffer write barrier
889         {
890                 const VkBufferMemoryBarrier barrier =
891                 {
892                         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,                // VkStructureType    sType;
893                         DE_NULL,                                                                                // const void*        pNext;
894                         VK_ACCESS_SHADER_WRITE_BIT,                                             // VkAccessFlags      srcAccessMask;
895                         VK_ACCESS_HOST_READ_BIT,                                                // VkAccessFlags      dstAccessMask;
896                         VK_QUEUE_FAMILY_IGNORED,                                                // uint32_t           srcQueueFamilyIndex;
897                         VK_QUEUE_FAMILY_IGNORED,                                                // uint32_t           dstQueueFamilyIndex;
898                         *wd.colorBuffer,                                                                // VkBuffer           buffer;
899                         0ull,                                                                                   // VkDeviceSize       offset;
900                         VK_WHOLE_SIZE,                                                                  // VkDeviceSize       size;
901                 };
902
903                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0u, DE_NULL, 1u, &barrier, DE_NULL, 0u);
904         }
905
906         VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
907         submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer);
908
909         invalidateMappedMemoryRange(vk, device, wd.colorBufferAlloc->getMemory(), wd.colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
910 }
911
912 //! Only draw a multisampled image
913 void draw (Context& context, const TestParams& params, WorkingData& wd)
914 {
915         const DeviceInterface&  vk              = context.getDeviceInterface();
916         const VkDevice                  device  = context.getDevice();
917
918         std::vector<ImageViewSp>        imageViews;
919         Move<VkRenderPass>                      renderPass;
920         Move<VkFramebuffer>                     framebuffer;
921
922         // Create color attachments
923         for (deUint32 layerNdx = 0u; layerNdx < params.numLayers; ++layerNdx)
924         {
925                 imageViews.push_back(ImageViewSp(new Unique<VkImageView>(
926                         makeImageView(vk, device, *wd.colorImage, VK_IMAGE_VIEW_TYPE_2D, params.colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, layerNdx, 1u)))));
927         }
928
929         // Create a render pass and a framebuffer
930         {
931                 std::vector<VkSubpassDescription>               subpasses;
932                 std::vector<VkImageView>                                attachments;
933                 std::vector<VkAttachmentDescription>    attachmentDescriptions;
934                 std::vector<VkAttachmentReference>              attachmentReferences;
935
936                 // Reserve capacity to avoid invalidating pointers to elements
937                 attachmentReferences.reserve(params.numLayers);
938
939                 // Create MS draw subpasses
940                 for (deUint32 layerNdx = 0u; layerNdx < params.numLayers; ++layerNdx)
941                 {
942                         attachments.push_back(**imageViews[layerNdx]);
943
944                         attachmentDescriptions.push_back(makeAttachmentDescription(
945                                 (VkAttachmentDescriptionFlags)0,                                                                // VkAttachmentDescriptionFlags         flags;
946                                 params.colorFormat,                                                                                             // VkFormat                                                     format;
947                                 params.numColorSamples,                                                                                 // VkSampleCountFlagBits                        samples;
948                                 VK_ATTACHMENT_LOAD_OP_CLEAR,                                                                    // VkAttachmentLoadOp                           loadOp;
949                                 VK_ATTACHMENT_STORE_OP_STORE,                                                                   // VkAttachmentStoreOp                          storeOp;
950                                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,                                                                // VkAttachmentLoadOp                           stencilLoadOp;
951                                 VK_ATTACHMENT_STORE_OP_DONT_CARE,                                                               // VkAttachmentStoreOp                          stencilStoreOp;
952                                 VK_IMAGE_LAYOUT_UNDEFINED,                                                                              // VkImageLayout                                        initialLayout;
953                                 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL                                                // VkImageLayout                                        finalLayout;
954                         ));
955
956                         attachmentReferences.push_back(makeAttachmentReference(static_cast<deUint32>(attachmentReferences.size()),      VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
957                         const VkAttachmentReference* colorRef = &attachmentReferences.back();
958
959                         const VkSubpassDescription subpassDescription =
960                         {
961                                 (VkSubpassDescriptionFlags)0,                                           // VkSubpassDescriptionFlags       flags;
962                                 VK_PIPELINE_BIND_POINT_GRAPHICS,                                        // VkPipelineBindPoint             pipelineBindPoint;
963                                 0u,                                                                                                     // uint32_t                        inputAttachmentCount;
964                                 DE_NULL,                                                                                        // const VkAttachmentReference*    pInputAttachments;
965                                 1u,                                                                                                     // uint32_t                        colorAttachmentCount;
966                                 colorRef,                                                                                       // const VkAttachmentReference*    pColorAttachments;
967                                 DE_NULL,                                                                                        // const VkAttachmentReference*    pResolveAttachments;
968                                 DE_NULL,                                                                                        // const VkAttachmentReference*    pDepthStencilAttachment;
969                                 0u,                                                                                                     // uint32_t                        preserveAttachmentCount;
970                                 DE_NULL,                                                                                        // const uint32_t*                 pPreserveAttachments;
971                         };
972
973                         subpasses.push_back(subpassDescription);
974                 }
975
976                 // All MS image drawing subpasses are independent
977                 VkRenderPassCreateInfo renderPassInfo =
978                 {
979                         VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,                              // VkStructureType                                      sType;
980                         DE_NULL,                                                                                                // const void*                                          pNext;
981                         (VkRenderPassCreateFlags)0,                                                             // VkRenderPassCreateFlags                      flags;
982                         static_cast<deUint32>(attachmentDescriptions.size()),   // deUint32                                                     attachmentCount;
983                         dataOrNullPtr(attachmentDescriptions),                                  // const VkAttachmentDescription*       pAttachments;
984                         static_cast<deUint32>(subpasses.size()),                                // deUint32                                                     subpassCount;
985                         dataOrNullPtr(subpasses),                                                               // const VkSubpassDescription*          pSubpasses;
986                         0u,                                                                                                             // deUint32                                                     dependencyCount;
987                         DE_NULL,                                                                                                // const VkSubpassDependency*           pDependencies;
988                 };
989
990                 renderPass  = createRenderPass(vk, device, &renderPassInfo);
991                 framebuffer = makeFramebuffer (vk, device, *renderPass, static_cast<deUint32>(attachments.size()), dataOrNullPtr(attachments), params.renderSize.x(), params.renderSize.y());
992         }
993
994         std::vector<PipelineSp>                 pipelines;
995         const Unique<VkPipelineLayout>  pipelineLayout          (makePipelineLayout(vk, device));
996         const Unique<VkShaderModule>    vertexModuleDraw        (createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u));
997         const Unique<VkShaderModule>    fragmentModuleDraw      (createShaderModule(vk, device, context.getBinaryCollection().get("frag"), 0u));
998
999         // Create pipelines for MS draw
1000         for (deUint32 layerNdx = 0u; layerNdx < params.numLayers; ++layerNdx)
1001         {
1002                 pipelines.push_back(PipelineSp(new Unique<VkPipeline>(
1003                         makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModuleDraw, *fragmentModuleDraw,
1004                                                                  true /*use vertex attribs*/, getVertexInputColorFormat(params.colorFormat), true/*use color attachment*/, layerNdx /*subpass*/,
1005                                                                  params.renderSize, params.numColorSamples))));
1006         }
1007
1008         const Unique<VkCommandPool>             cmdPool         (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, context.getUniversalQueueFamilyIndex()));
1009         const Unique<VkCommandBuffer>   cmdBuffer       (makeCommandBuffer(vk, device, *cmdPool));
1010
1011         beginCommandBuffer(vk, *cmdBuffer);
1012
1013         {
1014                 // Generate clear values
1015                 std::vector<VkClearValue> clearValues = genClearValues(params.colorFormat, params.numLayers);
1016
1017                 const VkRect2D renderArea =
1018                 {
1019                         { 0u, 0u },
1020                         { params.renderSize.x(), params.renderSize.y() }
1021                 };
1022
1023                 const VkRenderPassBeginInfo renderPassBeginInfo =
1024                 {
1025                         VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,                       // VkStructureType         sType;
1026                         DE_NULL,                                                                                        // const void*             pNext;
1027                         *renderPass,                                                                            // VkRenderPass            renderPass;
1028                         *framebuffer,                                                                           // VkFramebuffer           framebuffer;
1029                         renderArea,                                                                                     // VkRect2D                renderArea;
1030                         static_cast<deUint32>(clearValues.size()),                      // uint32_t                clearValueCount;
1031                         dataOrNullPtr(clearValues),                                                     // const VkClearValue*     pClearValues;
1032                 };
1033                 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1034         }
1035
1036         {
1037                 const VkDeviceSize vertexBufferOffset = 0ull;
1038                 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &wd.vertexBuffer.get(), &vertexBufferOffset);
1039         }
1040
1041         for (deUint32 layerNdx = 0u; layerNdx < params.numLayers; ++layerNdx)
1042         {
1043                 if (layerNdx != 0u)
1044                         vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
1045
1046                 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[layerNdx]);
1047                 vk.cmdDraw(*cmdBuffer, wd.numVertices, 1u, 0u, layerNdx);       // pass instance index to slightly change geometry per layer
1048         }
1049
1050         vk.cmdEndRenderPass(*cmdBuffer);
1051
1052         VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1053         submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer);
1054 }
1055
1056 //! Sample from an image in a compute shader, storing the result in a color buffer
1057 void dispatchSampleImage (Context& context, const TestParams& params, WorkingData& wd, const std::string& shaderName)
1058 {
1059         const DeviceInterface&  vk              = context.getDeviceInterface();
1060         const VkDevice                  device  = context.getDevice();
1061
1062         // Create descriptor set
1063
1064         const Unique<VkDescriptorSetLayout> descriptorSetLayout(
1065                 DescriptorSetLayoutBuilder()
1066                 .addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,     VK_SHADER_STAGE_COMPUTE_BIT, &wd.defaultSampler.get())
1067                 .addSingleBinding               (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,                     VK_SHADER_STAGE_COMPUTE_BIT)
1068                 .build(vk, device));
1069
1070         const Unique<VkDescriptorPool> descriptorPool(
1071                 DescriptorPoolBuilder()
1072                 .addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
1073                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
1074                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
1075
1076         const Unique<VkDescriptorSet> descriptorSet(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
1077
1078         {
1079                 const VkDescriptorImageInfo             colorImageInfo          = makeDescriptorImageInfo(DE_NULL, *wd.colorImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1080                 const VkDescriptorBufferInfo    resultBufferInfo        = makeDescriptorBufferInfo(*wd.colorBuffer, 0ull, wd.colorBufferSize);
1081
1082                 DescriptorSetUpdateBuilder      builder;
1083
1084                 builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &colorImageInfo);
1085                 builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,                 &resultBufferInfo);
1086
1087                 builder.update(vk, device);
1088         }
1089
1090         // Pipeline
1091
1092         const Unique<VkShaderModule>    shaderModule    (createShaderModule(vk, device, context.getBinaryCollection().get(shaderName), 0u));
1093         const Unique<VkPipelineLayout>  pipelineLayout  (makePipelineLayout(vk, device, *descriptorSetLayout));
1094         const Unique<VkPipeline>                pipeline                (makeComputePipeline(vk, device, *pipelineLayout, *shaderModule, DE_NULL));
1095
1096         const Unique<VkCommandPool>             cmdPool         (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, context.getUniversalQueueFamilyIndex()));
1097         const Unique<VkCommandBuffer>   cmdBuffer       (makeCommandBuffer(vk, device, *cmdPool));
1098
1099         beginCommandBuffer(vk, *cmdBuffer);
1100
1101         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
1102         vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
1103
1104         vk.cmdDispatch(*cmdBuffer, params.renderSize.x(), params.renderSize.y(), params.numLayers);
1105
1106         {
1107                 const VkBufferMemoryBarrier barrier =
1108                 {
1109                         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,                // VkStructureType    sType;
1110                         DE_NULL,                                                                                // const void*        pNext;
1111                         VK_ACCESS_SHADER_WRITE_BIT,                                             // VkAccessFlags      srcAccessMask;
1112                         VK_ACCESS_HOST_READ_BIT,                                                // VkAccessFlags      dstAccessMask;
1113                         VK_QUEUE_FAMILY_IGNORED,                                                // uint32_t           srcQueueFamilyIndex;
1114                         VK_QUEUE_FAMILY_IGNORED,                                                // uint32_t           dstQueueFamilyIndex;
1115                         *wd.colorBuffer,                                                                // VkBuffer           buffer;
1116                         0ull,                                                                                   // VkDeviceSize       offset;
1117                         VK_WHOLE_SIZE,                                                                  // VkDeviceSize       size;
1118                 };
1119
1120                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0,
1121                         (const VkMemoryBarrier*)DE_NULL, 1u, &barrier, 0u, (const VkImageMemoryBarrier*)DE_NULL);
1122         }
1123
1124         VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
1125         submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer);
1126
1127         invalidateMappedMemoryRange(vk, device, wd.colorBufferAlloc->getMemory(), wd.colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1128 }
1129
1130 //! Get a single-sampled image access from a multisampled color buffer with samples packed per pixel
1131 tcu::ConstPixelBufferAccess getSingleSampledAccess (const void* const imageData, const TestParams& params, const deUint32 sampleNdx, const deUint32 layerNdx)
1132 {
1133         const deUint32          numSamples      = static_cast<deUint32>(params.numColorSamples);
1134         const deUint32          pixelSize       = tcu::getPixelSize(mapVkFormat(params.colorFormat));
1135         const deUint32          rowSize         = pixelSize * params.renderSize.x();
1136         const deUint32          layerSize       = rowSize * params.renderSize.y();
1137         const deUint8*          src                     = static_cast<const deUint8*>(imageData)
1138                                                                         + (layerNdx * numSamples * layerSize)
1139                                                                         + (sampleNdx * pixelSize);
1140         const tcu::IVec3        size            (params.renderSize.x(), params.renderSize.y(), 1);
1141         const tcu::IVec3        pitch           (numSamples * pixelSize,
1142                                                                          numSamples * rowSize,
1143                                                                          numSamples * layerSize);
1144         return tcu::ConstPixelBufferAccess(mapVkFormat(params.colorFormat), size, pitch, src);
1145 }
1146
1147 tcu::TestStatus test (Context& context, const TestParams params)
1148 {
1149         WorkingData                             wd;
1150         const DeviceInterface&  vk                = context.getDeviceInterface();
1151         const VkDevice                  device    = context.getDevice();
1152         MovePtr<Allocator>              allocator = MovePtr<Allocator>(new SimpleAllocator(vk, device, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice())));
1153
1154         // Initialize resources
1155         {
1156                 const VkImageUsageFlags msImageUsage    = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
1157                                                                                                 | VK_IMAGE_USAGE_SAMPLED_BIT
1158                                                                                                 | (params.sampleSource == SAMPLE_SOURCE_SUBPASS_INPUT ? VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT : (VkImageUsageFlagBits)0);
1159                 wd.colorImage           = makeImage(vk, device, params.colorFormat, params.renderSize, params.numLayers, params.numColorSamples, msImageUsage);
1160                 wd.colorImageAlloc      = bindImage(vk, device, *allocator, *wd.colorImage, MemoryRequirement::Any);
1161                 wd.colorImageView       = makeImageView(vk, device, *wd.colorImage, (params.numLayers == 1u ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_2D_ARRAY), params.colorFormat,
1162                                                                                         makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, params.numLayers));
1163
1164                 wd.defaultSampler       = makeSampler(vk, device);
1165
1166                 // Color buffer is meant to hold data for all layers and all samples of the image.
1167                 // Data is tightly packed layer by layer, for each pixel all samples are laid out together starting with sample 0.
1168                 // E.g.: pixel(0,0)sample(0)sample(1), pixel(1,0)sample(0)sample(1), ...
1169                 wd.colorBufferSize      = static_cast<VkDeviceSize>(tcu::getPixelSize(mapVkFormat(params.colorFormat))
1170                                                                                                                 * params.renderSize.x() * params.renderSize.y() * params.numLayers * static_cast<deUint32>(params.numColorSamples));
1171                 wd.colorBuffer          = makeBuffer(vk, device, wd.colorBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1172                 wd.colorBufferAlloc     = bindBuffer(vk, device, *allocator, *wd.colorBuffer, MemoryRequirement::HostVisible);
1173
1174                 deMemset(wd.colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(wd.colorBufferSize));
1175                 flushMappedMemoryRange(vk, device, wd.colorBufferAlloc->getMemory(), wd.colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1176
1177                 const std::vector<PositionColor>        vertices                        = genShapes(params.colorFormat);
1178                 const VkDeviceSize                                      vertexBufferSize        = static_cast<VkDeviceSize>(sizeof(vertices[0]) * vertices.size());
1179
1180                 wd.numVertices                  = static_cast<deUint32>(vertices.size());
1181                 wd.vertexBuffer                 = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1182                 wd.vertexBufferAlloc    = bindBuffer(vk, device, *allocator, *wd.vertexBuffer, MemoryRequirement::HostVisible);
1183
1184                 deMemcpy(wd.vertexBufferAlloc->getHostPtr(), dataOrNullPtr(vertices), static_cast<std::size_t>(vertexBufferSize));
1185                 flushMappedMemoryRange(vk, device, wd.vertexBufferAlloc->getMemory(), wd.vertexBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1186         }
1187
1188         if (params.sampleSource == SAMPLE_SOURCE_SUBPASS_INPUT)
1189         {
1190                 // Create a multisample image and sample from it
1191                 drawAndSampleInputAttachment (context, params, wd);
1192         }
1193         else
1194         {
1195                 // Draw the image, then sample from it in a CS
1196                 draw                            (context, params, wd);
1197                 dispatchSampleImage (context, params, wd, "comp_fmask_fetch");
1198         }
1199
1200         // Copy the result
1201         std::vector<deUint8> fmaskFetchColorBuffer (static_cast<deUint32>(wd.colorBufferSize));
1202         deMemcpy(&fmaskFetchColorBuffer[0], wd.colorBufferAlloc->getHostPtr(), static_cast<std::size_t>(wd.colorBufferSize));
1203
1204         // Clear the color buffer, just to be sure we're getting the new data
1205         deMemset(wd.colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(wd.colorBufferSize));
1206         flushMappedMemoryRange(vk, device, wd.colorBufferAlloc->getMemory(), wd.colorBufferAlloc->getOffset(), VK_WHOLE_SIZE);
1207
1208         // Sample image using the standard texel fetch
1209         dispatchSampleImage (context, params, wd, "comp_fetch");
1210
1211         // Verify the images
1212         {
1213                 const void* const fmaskResult    = dataOrNullPtr(fmaskFetchColorBuffer);
1214                 const void* const expectedResult = wd.colorBufferAlloc->getHostPtr();
1215
1216                 DE_ASSERT(!isFloatFormat(params.colorFormat));  // we're using int compare
1217
1218                 // Mismatch, do image compare to pinpoint the failure
1219                 for (deUint32 layerNdx  = 0u; layerNdx  < params.numLayers;                                                              ++layerNdx)
1220                 for (deUint32 sampleNdx = 0u; sampleNdx < static_cast<deUint32>(params.numColorSamples); ++sampleNdx)
1221                 {
1222                         const std::string                                       imageName       = "layer_" + de::toString(layerNdx) + "_sample_" + de::toString(sampleNdx);
1223                         const std::string                                       imageDesc       = "Layer " + de::toString(layerNdx) + " Sample " + de::toString(sampleNdx);
1224                         const tcu::ConstPixelBufferAccess       expected        = getSingleSampledAccess(expectedResult, params, sampleNdx, layerNdx);
1225                         const tcu::ConstPixelBufferAccess       actual          = getSingleSampledAccess(fmaskResult,    params, sampleNdx, layerNdx);
1226                         const UVec4                                                     threshold       (0);    // should match exactly
1227
1228                         const bool ok = tcu::intThresholdCompare(context.getTestContext().getLog(), imageName.c_str(), imageDesc.c_str(),
1229                                                                                                          expected, actual, threshold, tcu::COMPARE_LOG_RESULT);
1230
1231                         if (!ok)
1232                                 return tcu::TestStatus::fail("Some texels were incorrect");
1233                 }
1234         }
1235
1236         return tcu::TestStatus::pass("Pass");
1237 }
1238
1239 std::string getFormatShortString (const VkFormat format)
1240 {
1241         std::string s(de::toLower(getFormatName(format)));
1242         return s.substr(10);
1243 }
1244
1245 void createShaderFragmentMaskTestsInGroup (tcu::TestCaseGroup* rootGroup)
1246 {
1247         // Per spec, the following formats must support color attachment and sampled image
1248         const VkFormat colorFormats[] =
1249         {
1250                 VK_FORMAT_R8G8B8A8_UNORM,
1251                 VK_FORMAT_R32_UINT,
1252                 VK_FORMAT_R32_SINT,
1253         };
1254
1255         const VkSampleCountFlagBits     sampleCounts[] =
1256         {
1257                 VK_SAMPLE_COUNT_2_BIT,
1258                 VK_SAMPLE_COUNT_4_BIT,
1259                 VK_SAMPLE_COUNT_8_BIT,
1260                 VK_SAMPLE_COUNT_16_BIT,
1261         };
1262
1263         const struct SourceCase
1264         {
1265                 const char*                     name;
1266                 deUint32                        numLayers;
1267                 SampleSource            sampleSource;
1268         } sourceCases[] =
1269         {
1270                 { "image_2d",           1u,     SAMPLE_SOURCE_IMAGE                     },
1271                 { "image_2d_array",     3u,     SAMPLE_SOURCE_IMAGE                     },
1272                 { "subpass_input",      1u,     SAMPLE_SOURCE_SUBPASS_INPUT     },
1273         };
1274
1275         // Test 1: Compare fragments fetched via FMASK and an ordinary texel fetch
1276         {
1277                 for (const VkSampleCountFlagBits* pSampleCount = sampleCounts; pSampleCount != DE_ARRAY_END(sampleCounts); ++pSampleCount)
1278                 {
1279                         MovePtr<tcu::TestCaseGroup> sampleCountGroup (new tcu::TestCaseGroup(rootGroup->getTestContext(), ("samples_" + de::toString(*pSampleCount)).c_str(), ""));
1280                         for (const SourceCase* pSourceCase = sourceCases; pSourceCase != DE_ARRAY_END(sourceCases); ++pSourceCase)
1281                         {
1282                                 MovePtr<tcu::TestCaseGroup> sourceGroup (new tcu::TestCaseGroup(rootGroup->getTestContext(), pSourceCase->name, ""));
1283                                 for (const VkFormat* pColorFormat = colorFormats; pColorFormat != DE_ARRAY_END(colorFormats); ++pColorFormat)
1284                                 {
1285                                         TestParams params;
1286                                         params.renderSize               = UVec2(32, 32);
1287                                         params.colorFormat              = *pColorFormat;
1288                                         params.numColorSamples  = *pSampleCount;
1289                                         params.numLayers                = pSourceCase->numLayers;
1290                                         params.sampleSource             = pSourceCase->sampleSource;
1291
1292                                         addFunctionCaseWithPrograms(sourceGroup.get(), getFormatShortString(*pColorFormat), "", checkRequirements, initPrograms, test, params);
1293                                 }
1294                                 sampleCountGroup->addChild(sourceGroup.release());
1295                         }
1296                         rootGroup->addChild(sampleCountGroup.release());
1297                 }
1298         }
1299 }
1300
1301 } // anonymous ns
1302
1303 tcu::TestCaseGroup* createMultisampleShaderFragmentMaskTests (tcu::TestContext& testCtx)
1304 {
1305         return createTestGroup(testCtx, "shader_fragment_mask", "Access raw texel values in a compressed MSAA surface", createShaderFragmentMaskTestsInGroup);
1306 }
1307
1308 } // pipeline
1309 } // vkt