Fix issues in pipeline.timestamp.transfer_tests am: 0f672f2a20
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / image / vktImageMultisampleLoadStoreTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  * Copyright (c) 2016 The Android Open Source Project
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Multisampled image load/store Tests
23  *//*--------------------------------------------------------------------*/
24
25 #include "vktImageMultisampleLoadStoreTests.hpp"
26 #include "vktTestCaseUtil.hpp"
27 #include "vktImageTestsUtil.hpp"
28 #include "vktImageLoadStoreUtil.hpp"
29 #include "vktImageTexture.hpp"
30
31 #include "vkDefs.hpp"
32 #include "vkRef.hpp"
33 #include "vkRefUtil.hpp"
34 #include "vkPlatform.hpp"
35 #include "vkPrograms.hpp"
36 #include "vkMemUtil.hpp"
37 #include "vkBuilderUtil.hpp"
38 #include "vkQueryUtil.hpp"
39 #include "vkImageUtil.hpp"
40
41 #include "deUniquePtr.hpp"
42
43 #include "tcuTextureUtil.hpp"
44 #include "tcuTestLog.hpp"
45
46 #include <string>
47 #include <vector>
48
49 namespace vkt
50 {
51 namespace image
52 {
53 namespace
54 {
55 using namespace vk;
56 using de::MovePtr;
57 using de::UniquePtr;
58 using tcu::IVec3;
59
60 static const VkFormat CHECKSUM_IMAGE_FORMAT = VK_FORMAT_R32_SINT;
61
62 struct CaseDef
63 {
64         Texture                                 texture;
65         VkFormat                                format;
66         VkSampleCountFlagBits   numSamples;
67         bool                                    singleLayerBind;
68 };
69
70 //  Multisampled storage image test.
71 //
72 //  Pass 1: Write a slightly different color pattern per-sample to the whole image.
73 //  Pass 2: Read samples of the same image and check if color values are in the expected range.
74 //          Write back results as a checksum image and verify them on the host.
75 //  Each checksum image pixel should contain an integer equal to the number of samples.
76
77 void initPrograms (SourceCollections& programCollection, const  CaseDef caseDef)
78 {
79         const int                       dimension                       = (caseDef.singleLayerBind ? caseDef.texture.layerDimension() : caseDef.texture.dimension());
80         const std::string       texelCoordStr           = (dimension == 1 ? "gx" : dimension == 2 ? "ivec2(gx, gy)" : dimension == 3 ? "ivec3(gx, gy, gz)" : "");
81
82         const ImageType         usedImageType           = (caseDef.singleLayerBind ? getImageTypeForSingleLayer(caseDef.texture.type()) : caseDef.texture.type());
83         const std::string       formatQualifierStr      = getShaderImageFormatQualifier(mapVkFormat(caseDef.format));
84         const std::string       msImageTypeStr          = getShaderImageType(mapVkFormat(caseDef.format), usedImageType, (caseDef.texture.numSamples() > 1));
85
86         const std::string       xMax                            = de::toString(caseDef.texture.size().x() - 1);
87         const std::string       yMax                            = de::toString(caseDef.texture.size().y() - 1);
88         const std::string       signednessPrefix        = isUintFormat(caseDef.format) ? "u" : isIntFormat(caseDef.format) ? "i" : "";
89         const std::string       gvec4Expr                       = signednessPrefix + "vec4";
90         const int                       numColorComponents      = tcu::getNumUsedChannels(mapVkFormat(caseDef.format).order);
91
92         const float                     storeColorScale         = computeStoreColorScale(caseDef.format, caseDef.texture.size());
93         const float                     storeColorBias          = computeStoreColorBias(caseDef.format);
94         DE_ASSERT(colorScaleAndBiasAreValid(caseDef.format, storeColorScale, storeColorBias));
95
96         const std::string       colorScaleExpr          = (storeColorScale == 1.0f ? "" : "*" + de::toString(storeColorScale))
97                                                                                         + (storeColorBias == 0.0f ? "" : " + float(" + de::toString(storeColorBias) + ")");
98         const std::string       colorExpr                       =
99                 gvec4Expr + "("
100                 +                           "gx^gy^gz^(sampleNdx >> 5)^(sampleNdx & 31), "              // we "split" sampleNdx to keep this value in [0, 31] range for numSamples = 64 case
101                 + (numColorComponents > 1 ? "(" + xMax + "-gx)^gy^gz, "              : "0, ")
102                 + (numColorComponents > 2 ? "gx^(" + yMax + "-gy)^gz, "              : "0, ")
103                 + (numColorComponents > 3 ? "(" + xMax + "-gx)^(" + yMax + "-gy)^gz" : "1")
104                 + ")" + colorScaleExpr;
105
106         // Store shader
107         {
108                 std::ostringstream src;
109                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
110                         << "\n"
111                         << "layout(local_size_x = 1) in;\n"
112                         << "layout(set = 0, binding = 1, " << formatQualifierStr << ") writeonly uniform " << msImageTypeStr << " u_msImage;\n";
113
114                 if (caseDef.singleLayerBind)
115                         src << "layout(set = 0, binding = 0) readonly uniform Constants {\n"
116                                 << "    int u_layerNdx;\n"
117                                 << "};\n";
118
119                 src << "\n"
120                         << "void main (void)\n"
121                         << "{\n"
122                         << "    int gx = int(gl_GlobalInvocationID.x);\n"
123                         << "    int gy = int(gl_GlobalInvocationID.y);\n"
124                         << "    int gz = " << (caseDef.singleLayerBind ? "u_layerNdx" : "int(gl_GlobalInvocationID.z)") << ";\n"
125                         << "\n"
126                         << "    for (int sampleNdx = 0; sampleNdx < " << caseDef.texture.numSamples() <<"; ++sampleNdx) {\n"
127                         << "        imageStore(u_msImage, " << texelCoordStr << ", sampleNdx, " << colorExpr << ");\n"
128                         << "    }\n"
129                         << "}\n";
130
131                 programCollection.glslSources.add("comp_store") << glu::ComputeSource(src.str());
132         }
133
134         // Load shader
135         {
136                 const tcu::TextureFormat        checksumFormat                  = mapVkFormat(CHECKSUM_IMAGE_FORMAT);
137                 const std::string                       checksumImageTypeStr    = getShaderImageType(checksumFormat, usedImageType);
138                 const bool                                      useExactCompare                 = isIntegerFormat(caseDef.format);
139
140                 std::ostringstream src;
141                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
142                         << "\n"
143                         << "layout(local_size_x = 1) in;\n"
144                         << "layout(set = 0, binding = 1, " << formatQualifierStr << ") readonly  uniform " << msImageTypeStr << " u_msImage;\n"
145                         << "layout(set = 0, binding = 2, " << getShaderImageFormatQualifier(checksumFormat) << ") writeonly uniform " << checksumImageTypeStr << " u_checksumImage;\n";
146
147                 if (caseDef.singleLayerBind)
148                         src << "layout(set = 0, binding = 0) readonly uniform Constants {\n"
149                                 << "    int u_layerNdx;\n"
150                                 << "};\n";
151
152                 src << "\n"
153                         << "void main (void)\n"
154                         << "{\n"
155                         << "    int gx = int(gl_GlobalInvocationID.x);\n"
156                         << "    int gy = int(gl_GlobalInvocationID.y);\n"
157                         << "    int gz = " << (caseDef.singleLayerBind ? "u_layerNdx" : "int(gl_GlobalInvocationID.z)") << ";\n"
158                         << "\n"
159                         << "    int checksum = 0;\n"
160                         << "    for (int sampleNdx = 0; sampleNdx < " << caseDef.texture.numSamples() <<"; ++sampleNdx) {\n"
161                         << "        " << gvec4Expr << " color = imageLoad(u_msImage, " << texelCoordStr << ", sampleNdx);\n";
162
163                 if (useExactCompare)
164                         src << "        if (color == " << colorExpr << ")\n"
165                                 << "            ++checksum;\n";
166                 else
167                         src << "        " << gvec4Expr << " diff  = abs(abs(color) - abs(" << colorExpr << "));\n"
168                                 << "        if (all(lessThan(diff, " << gvec4Expr << "(0.02))))\n"
169                                 << "            ++checksum;\n";
170
171                 src << "    }\n"
172                         << "\n"
173                         << "    imageStore(u_checksumImage, " << texelCoordStr << ", ivec4(checksum));\n"
174                         << "}\n";
175
176                 programCollection.glslSources.add("comp_load") << glu::ComputeSource(src.str());
177         }
178 }
179
180 void checkRequirements (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const CaseDef& caseDef)
181 {
182         VkPhysicalDeviceFeatures        features;
183         vki.getPhysicalDeviceFeatures(physDevice, &features);
184
185         if (!features.shaderStorageImageMultisample)
186                 TCU_THROW(NotSupportedError, "Multisampled storage images are not supported");
187
188         VkImageFormatProperties         imageFormatProperties;
189         const VkResult                          imageFormatResult               = vki.getPhysicalDeviceImageFormatProperties(
190                 physDevice, caseDef.format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_STORAGE_BIT, (VkImageCreateFlags)0, &imageFormatProperties);
191
192         if (imageFormatResult == VK_ERROR_FORMAT_NOT_SUPPORTED)
193                 TCU_THROW(NotSupportedError, "Format is not supported");
194
195         if ((imageFormatProperties.sampleCounts & caseDef.numSamples) != caseDef.numSamples)
196                 TCU_THROW(NotSupportedError, "Requested sample count is not supported");
197 }
198
199 //! Helper function to deal with per-layer resources.
200 void insertImageViews (const DeviceInterface& vk, const VkDevice device, const CaseDef& caseDef, const VkFormat format, const VkImage image, std::vector<SharedVkImageView>* const pOutImageViews)
201 {
202         if (caseDef.singleLayerBind)
203         {
204                 pOutImageViews->clear();
205                 pOutImageViews->resize(caseDef.texture.numLayers());
206                 for (int layerNdx = 0; layerNdx < caseDef.texture.numLayers(); ++layerNdx)
207                 {
208                         (*pOutImageViews)[layerNdx] = makeVkSharedPtr(makeImageView(
209                                 vk, device, image, mapImageViewType(getImageTypeForSingleLayer(caseDef.texture.type())), format,
210                                 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, layerNdx, 1u)));
211                 }
212         }
213         else // bind all layers at once
214         {
215                 pOutImageViews->clear();
216                 pOutImageViews->resize(1);
217                 (*pOutImageViews)[0] = makeVkSharedPtr(makeImageView(
218                         vk, device, image, mapImageViewType(caseDef.texture.type()), format,
219                         makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, caseDef.texture.numLayers())));
220         }
221 }
222
223 //! Helper function to deal with per-layer resources.
224 void insertDescriptorSets (const DeviceInterface& vk, const VkDevice device, const CaseDef& caseDef, const VkDescriptorPool descriptorPool, const VkDescriptorSetLayout descriptorSetLayout, std::vector<SharedVkDescriptorSet>* const pOutDescriptorSets)
225 {
226         if (caseDef.singleLayerBind)
227         {
228                 pOutDescriptorSets->clear();
229                 pOutDescriptorSets->resize(caseDef.texture.numLayers());
230                 for (int layerNdx = 0; layerNdx < caseDef.texture.numLayers(); ++layerNdx)
231                         (*pOutDescriptorSets)[layerNdx] = makeVkSharedPtr(makeDescriptorSet(vk, device, descriptorPool, descriptorSetLayout));
232         }
233         else // bind all layers at once
234         {
235                 pOutDescriptorSets->clear();
236                 pOutDescriptorSets->resize(1);
237                 (*pOutDescriptorSets)[0] = makeVkSharedPtr(makeDescriptorSet(vk, device, descriptorPool, descriptorSetLayout));
238         }
239 }
240
241 tcu::TestStatus test (Context& context, const CaseDef caseDef)
242 {
243         const InstanceInterface&        vki                                     = context.getInstanceInterface();
244         const VkPhysicalDevice          physDevice                      = context.getPhysicalDevice();
245         const DeviceInterface&          vk                                      = context.getDeviceInterface();
246         const VkDevice                          device                          = context.getDevice();
247         const VkQueue                           queue                           = context.getUniversalQueue();
248         const deUint32                          queueFamilyIndex        = context.getUniversalQueueFamilyIndex();
249         Allocator&                                      allocator                       = context.getDefaultAllocator();
250
251         checkRequirements(vki, physDevice, caseDef);
252
253         // Images
254
255         const UniquePtr<Image> msImage(new Image(
256                 vk, device, allocator, makeImageCreateInfo(caseDef.texture, caseDef.format, VK_IMAGE_USAGE_STORAGE_BIT, 0u), MemoryRequirement::Any));
257
258         const UniquePtr<Image> checksumImage(new Image(
259                 vk, device, allocator,
260                 makeImageCreateInfo(Texture(caseDef.texture, 1), CHECKSUM_IMAGE_FORMAT, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0u),
261                 MemoryRequirement::Any));
262
263         // Buffer used to pass constants to the shader.
264
265         const int                       numLayers                                       = caseDef.texture.numLayers();
266         const VkDeviceSize      bufferChunkSize                         = getOptimalUniformBufferChunkSize(vki, physDevice, sizeof(deInt32));
267         const VkDeviceSize      constantsBufferSizeBytes        = numLayers * bufferChunkSize;
268         UniquePtr<Buffer>       constantsBuffer                         (new Buffer(vk, device, allocator, makeBufferCreateInfo(constantsBufferSizeBytes, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT),
269                                                                                                          MemoryRequirement::HostVisible));
270
271         {
272                 const Allocation&       alloc   = constantsBuffer->getAllocation();
273                 deUint8* const          basePtr = static_cast<deUint8*>(alloc.getHostPtr());
274
275                 deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(constantsBufferSizeBytes));
276
277                 for (int layerNdx = 0; layerNdx < numLayers; ++layerNdx)
278                 {
279                         deInt32* const valuePtr = reinterpret_cast<deInt32*>(basePtr + layerNdx * bufferChunkSize);
280                         *valuePtr = layerNdx;
281                 }
282
283                 flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), constantsBufferSizeBytes);
284         }
285
286         const VkDeviceSize      resultBufferSizeBytes   = getImageSizeBytes(caseDef.texture.size(), CHECKSUM_IMAGE_FORMAT);
287         UniquePtr<Buffer>       resultBuffer                    (new Buffer(vk, device, allocator, makeBufferCreateInfo(resultBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT),
288                                                                                                  MemoryRequirement::HostVisible));
289
290         {
291                 const Allocation& alloc = resultBuffer->getAllocation();
292                 deMemset(alloc.getHostPtr(), 0, static_cast<size_t>(resultBufferSizeBytes));
293                 flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), resultBufferSizeBytes);
294         }
295
296         // Descriptors
297
298         Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
299                 .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
300                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
301                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
302                 .build(vk, device));
303
304         Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
305                 .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, numLayers)
306                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
307                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, numLayers)
308                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, numLayers));
309
310         std::vector<SharedVkDescriptorSet>      allDescriptorSets;
311         std::vector<SharedVkImageView>          allMultisampledImageViews;
312         std::vector<SharedVkImageView>          allChecksumImageViews;
313
314         insertDescriptorSets(vk, device, caseDef, *descriptorPool, *descriptorSetLayout, &allDescriptorSets);
315         insertImageViews        (vk, device, caseDef, caseDef.format, **msImage, &allMultisampledImageViews);
316         insertImageViews        (vk, device, caseDef, CHECKSUM_IMAGE_FORMAT, **checksumImage, &allChecksumImageViews);
317
318         // Prepare commands
319
320         const Unique<VkPipelineLayout>  pipelineLayout  (makePipelineLayout(vk, device, *descriptorSetLayout));
321         const Unique<VkCommandPool>             cmdPool                 (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
322         const Unique<VkCommandBuffer>   cmdBuffer               (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
323
324         const tcu::IVec3                                workSize                                = (caseDef.singleLayerBind ? caseDef.texture.layerSize() : caseDef.texture.size());
325         const int                                               loopNumLayers                   = (caseDef.singleLayerBind ? numLayers : 1);
326         const VkImageSubresourceRange   subresourceAllLayers    = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, caseDef.texture.numLayers());
327
328         // Pass 1: Write MS image
329         {
330                 const Unique<VkShaderModule>    shaderModule    (createShaderModule     (vk, device, context.getBinaryCollection().get("comp_store"), 0));
331                 const Unique<VkPipeline>                pipeline                (makeComputePipeline(vk, device, *pipelineLayout, *shaderModule));
332
333                 beginCommandBuffer(vk, *cmdBuffer);
334                 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
335
336                 {
337                         const VkImageMemoryBarrier barriers[] =
338                         {
339                                 makeImageMemoryBarrier((VkAccessFlags)0, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, **msImage, subresourceAllLayers),
340                                 makeImageMemoryBarrier((VkAccessFlags)0, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, **checksumImage, subresourceAllLayers),
341                         };
342
343                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0,
344                                 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
345                 }
346
347                 for (int layerNdx = 0; layerNdx < loopNumLayers; ++layerNdx)
348                 {
349                         const VkDescriptorSet                   descriptorSet                                   = **allDescriptorSets[layerNdx];
350                         const VkDescriptorImageInfo             descriptorMultiImageInfo                = makeDescriptorImageInfo(DE_NULL, **allMultisampledImageViews[layerNdx], VK_IMAGE_LAYOUT_GENERAL);
351                         const VkDescriptorBufferInfo    descriptorConstantsBufferInfo   = makeDescriptorBufferInfo(constantsBuffer->get(), layerNdx*bufferChunkSize, bufferChunkSize);
352
353                         DescriptorSetUpdateBuilder()
354                                 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descriptorConstantsBufferInfo)
355                                 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorMultiImageInfo)
356                                 .update(vk, device);
357
358                         vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
359                         vk.cmdDispatch(*cmdBuffer, workSize.x(), workSize.y(), workSize.z());
360                 }
361
362                 endCommandBuffer(vk, *cmdBuffer);
363                 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
364         }
365
366         // Pass 2: "Resolve" MS image in compute shader
367         {
368                 const Unique<VkShaderModule>    shaderModule    (createShaderModule     (vk, device, context.getBinaryCollection().get("comp_load"), 0));
369                 const Unique<VkPipeline>                pipeline                (makeComputePipeline(vk, device, *pipelineLayout, *shaderModule));
370
371                 beginCommandBuffer(vk, *cmdBuffer);
372                 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
373
374                 {
375                         const VkImageMemoryBarrier barriers[] =
376                         {
377                                 makeImageMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL, **msImage, subresourceAllLayers),
378                         };
379
380                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0,
381                                 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
382                 }
383
384                 for (int layerNdx = 0; layerNdx < loopNumLayers; ++layerNdx)
385                 {
386                         const VkDescriptorSet                   descriptorSet                                   = **allDescriptorSets[layerNdx];
387                         const VkDescriptorImageInfo             descriptorMultiImageInfo                = makeDescriptorImageInfo(DE_NULL, **allMultisampledImageViews[layerNdx], VK_IMAGE_LAYOUT_GENERAL);
388                         const VkDescriptorImageInfo             descriptorChecksumImageInfo             = makeDescriptorImageInfo(DE_NULL, **allChecksumImageViews[layerNdx], VK_IMAGE_LAYOUT_GENERAL);
389                         const VkDescriptorBufferInfo    descriptorConstantsBufferInfo   = makeDescriptorBufferInfo(constantsBuffer->get(), layerNdx*bufferChunkSize, bufferChunkSize);
390
391                         DescriptorSetUpdateBuilder()
392                                 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descriptorConstantsBufferInfo)
393                                 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorMultiImageInfo)
394                                 .writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(2u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorChecksumImageInfo)
395                                 .update(vk, device);
396
397                         vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
398                         vk.cmdDispatch(*cmdBuffer, workSize.x(), workSize.y(), workSize.z());
399                 }
400
401                 endCommandBuffer(vk, *cmdBuffer);
402                 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
403         }
404
405         // Retrieve result
406         {
407                 beginCommandBuffer(vk, *cmdBuffer);
408
409                 {
410                         const VkImageMemoryBarrier barriers[] =
411                         {
412                                 makeImageMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **checksumImage, subresourceAllLayers),
413                         };
414                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0,
415                                 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
416                 }
417                 {
418                         const VkBufferImageCopy copyRegion = makeBufferImageCopy(makeExtent3D(caseDef.texture.layerSize()), caseDef.texture.numLayers());
419                         vk.cmdCopyImageToBuffer(*cmdBuffer, **checksumImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **resultBuffer, 1u, &copyRegion);
420                 }
421                 {
422                         const VkBufferMemoryBarrier barriers[] =
423                         {
424                                 makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, **resultBuffer, 0ull, resultBufferSizeBytes),
425                         };
426                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0,
427                                 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers, 0u, DE_NULL);
428                 }
429
430                 endCommandBuffer(vk, *cmdBuffer);
431                 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
432         }
433
434         // Verify
435         {
436                 const Allocation& alloc = resultBuffer->getAllocation();
437                 invalidateMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), resultBufferSizeBytes);
438
439                 const IVec3             imageSize                       = caseDef.texture.size();
440                 const deInt32*  pDataPtr                        = static_cast<deInt32*>(alloc.getHostPtr());
441                 const deInt32   expectedChecksum        = caseDef.texture.numSamples();
442
443                 for (int layer = 0; layer < imageSize.z(); ++layer)
444                 for (int y = 0; y < imageSize.y(); ++y)
445                 for (int x = 0; x < imageSize.x(); ++x)
446                 {
447                         if (*pDataPtr != expectedChecksum)
448                         {
449                                 context.getTestContext().getLog()
450                                         << tcu::TestLog::Message << "Some sample colors were incorrect at (x, y, layer) = (" << x << ", " << y << ", " << layer << ")"  << tcu::TestLog::EndMessage
451                                         << tcu::TestLog::Message << "Checksum value is " << *pDataPtr << " but expected " << expectedChecksum << tcu::TestLog::EndMessage;
452
453                                 return tcu::TestStatus::fail("Some sample colors were incorrect");
454                         }
455                         ++pDataPtr;
456                 }
457
458                 return tcu::TestStatus::pass("OK");
459         }
460 }
461
462 } // anonymous ns
463
464 tcu::TestCaseGroup* createImageMultisampleLoadStoreTests (tcu::TestContext& testCtx)
465 {
466         const Texture textures[] =
467         {
468                 // \note Shader code is tweaked to work with image size of 32, take a look if this needs to be modified.
469                 Texture(IMAGE_TYPE_2D,                  tcu::IVec3(32,  32,     1),             1),
470                 Texture(IMAGE_TYPE_2D_ARRAY,    tcu::IVec3(32,  32,     1),             4),
471         };
472
473         static const VkFormat formats[] =
474         {
475                 VK_FORMAT_R32G32B32A32_SFLOAT,
476                 VK_FORMAT_R16G16B16A16_SFLOAT,
477                 VK_FORMAT_R32_SFLOAT,
478
479                 VK_FORMAT_R32G32B32A32_UINT,
480                 VK_FORMAT_R16G16B16A16_UINT,
481                 VK_FORMAT_R8G8B8A8_UINT,
482                 VK_FORMAT_R32_UINT,
483
484                 VK_FORMAT_R32G32B32A32_SINT,
485                 VK_FORMAT_R16G16B16A16_SINT,
486                 VK_FORMAT_R8G8B8A8_SINT,
487                 VK_FORMAT_R32_SINT,
488
489                 VK_FORMAT_R8G8B8A8_UNORM,
490
491                 VK_FORMAT_R8G8B8A8_SNORM,
492         };
493
494         static const VkSampleCountFlagBits samples[] =
495         {
496                 VK_SAMPLE_COUNT_2_BIT,
497                 VK_SAMPLE_COUNT_4_BIT,
498                 VK_SAMPLE_COUNT_8_BIT,
499                 VK_SAMPLE_COUNT_16_BIT,
500                 VK_SAMPLE_COUNT_32_BIT,
501                 VK_SAMPLE_COUNT_64_BIT,
502         };
503
504         MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "load_store_multisample", "Multisampled image store and load"));
505
506         for (int baseTextureNdx = 0; baseTextureNdx < DE_LENGTH_OF_ARRAY(textures); ++baseTextureNdx)
507         {
508                 const Texture&                          baseTexture                     = textures[baseTextureNdx];
509                 MovePtr<tcu::TestCaseGroup>     imageViewGroup          (new tcu::TestCaseGroup(testCtx, getImageTypeName(baseTexture.type()).c_str(), ""));
510                 const int                                       numLayerBindModes       = (baseTexture.numLayers() == 1 ? 1 : 2);
511
512                 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx)
513                 for (int layerBindMode = 0; layerBindMode < numLayerBindModes; ++layerBindMode)
514                 {
515                         const bool                                      singleLayerBind = (layerBindMode != 0);
516                         const std::string                       formatGroupName = getFormatShortString(formats[formatNdx]) + (singleLayerBind ? "_single_layer" : "");
517                         MovePtr<tcu::TestCaseGroup>     formatGroup             (new tcu::TestCaseGroup(testCtx, formatGroupName.c_str(), ""));
518
519                         for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); ++samplesNdx)
520                         {
521                                 const std::string       samplesCaseName = "samples_" + de::toString(samples[samplesNdx]);
522
523                                 const CaseDef           caseDef =
524                                 {
525                                         Texture(baseTexture, samples[samplesNdx]),
526                                         formats[formatNdx],
527                                         samples[samplesNdx],
528                                         singleLayerBind,
529                                 };
530
531                                 addFunctionCaseWithPrograms(formatGroup.get(), samplesCaseName, "", initPrograms, test, caseDef);
532                         }
533                         imageViewGroup->addChild(formatGroup.release());
534                 }
535                 testGroup->addChild(imageViewGroup.release());
536         }
537
538         return testGroup.release();
539 }
540
541 } // image
542 } // vkt