Merge branch 'jekstrand_renderpass_transfer_bit_fix' into 'master'
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / image / vktImageQualifiersTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 Mobica Ltd.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and/or associated documentation files (the
9  * "Materials"), to deal in the Materials without restriction, including
10  * without limitation the rights to use, copy, modify, merge, publish,
11  * distribute, sublicense, and/or sell copies of the Materials, and to
12  * permit persons to whom the Materials are furnished to do so, subject to
13  * the following conditions:
14  *
15  * The above copyright notice(s) and this permission notice shall be included
16  * in all copies or substantial portions of the Materials.
17  *
18  * The Materials are Confidential Information as defined by the
19  * Khronos Membership Agreement until designated non-confidential by Khronos,
20  * at which point this condition clause shall be removed.
21  *
22  * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
26  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28  * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
29  *
30  *//*!
31  * \file
32  * \brief Memory qualifiers tests
33  *//*--------------------------------------------------------------------*/
34
35 #include "vktImageQualifiersTests.hpp"
36 #include "vktImageLoadStoreTests.hpp"
37 #include "vktImageTestsUtil.hpp"
38
39 #include "vkDefs.hpp"
40 #include "vkImageUtil.hpp"
41 #include "vkRef.hpp"
42 #include "vkRefUtil.hpp"
43 #include "vktTestCase.hpp"
44 #include "vktTestCaseUtil.hpp"
45 #include "vkPlatform.hpp"
46 #include "vkPrograms.hpp"
47 #include "vkMemUtil.hpp"
48 #include "vkBuilderUtil.hpp"
49 #include "vkQueryUtil.hpp"
50 #include "vkTypeUtil.hpp"
51
52 #include "deDefs.hpp"
53 #include "deStringUtil.hpp"
54 #include "deUniquePtr.hpp"
55
56 #include "tcuImageCompare.hpp"
57 #include "tcuTexture.hpp"
58 #include "tcuTextureUtil.hpp"
59 #include "tcuVectorType.hpp"
60
61 using namespace vk;
62
63 namespace vkt
64 {
65 namespace image
66 {
67 namespace
68 {
69
70 static const tcu::UVec3         g_localWorkGroupSizeBase        = tcu::UVec3(8, 8, 2);
71 static const deInt32            g_ShaderReadOffsetsX[4]         = { 1, 4, 7, 10 };
72 static const deInt32            g_ShaderReadOffsetsY[4]         = { 2, 5, 8, 11 };
73 static const deInt32            g_ShaderReadOffsetsZ[4]         = { 3, 6, 9, 12 };
74 static const char* const        g_ShaderReadOffsetsXStr         = "int[]( 1, 4, 7, 10 )";
75 static const char* const        g_ShaderReadOffsetsYStr         = "int[]( 2, 5, 8, 11 )";
76 static const char* const        g_ShaderReadOffsetsZStr         = "int[]( 3, 6, 9, 12 )";
77
78 const tcu::UVec3 getComputeGridSize (const ImageType imageType, const tcu::UVec4& imageSize)
79 {
80         switch (imageType)
81         {
82                 case IMAGE_TYPE_1D:
83                 case IMAGE_TYPE_2D:
84                 case IMAGE_TYPE_2D_ARRAY:
85                 case IMAGE_TYPE_3D:
86                 case IMAGE_TYPE_CUBE:
87                 case IMAGE_TYPE_CUBE_ARRAY:
88                 case IMAGE_TYPE_BUFFER:
89                         return tcu::UVec3(imageSize.x(), imageSize.y(), imageSize.z() * imageSize.w());
90
91                 case IMAGE_TYPE_1D_ARRAY:
92                         return tcu::UVec3(imageSize.x(), imageSize.w(), 1);
93
94                 default:
95                         DE_FATAL("Unknown image type");
96                         return tcu::UVec3(1, 1, 1);
97         }
98 }
99
100 const tcu::UVec3 getLocalWorkGroupSize (const ImageType imageType, const tcu::UVec4& imageSize)
101 {
102         const tcu::UVec3 computeGridSize        = getComputeGridSize(imageType, imageSize);
103
104         const tcu::UVec3 localWorkGroupSize = tcu::UVec3(de::min(g_localWorkGroupSizeBase.x(), computeGridSize.x()),
105                                                                                                          de::min(g_localWorkGroupSizeBase.y(), computeGridSize.y()),
106                                                                                                          de::min(g_localWorkGroupSizeBase.z(), computeGridSize.z()));
107         return localWorkGroupSize;
108 }
109
110 const tcu::UVec3 getNumWorkGroups (const ImageType imageType, const tcu::UVec4& imageSize)
111 {
112         const tcu::UVec3 computeGridSize        = getComputeGridSize(imageType, imageSize);
113         const tcu::UVec3 localWorkGroupSize = getLocalWorkGroupSize(imageType, imageSize);
114
115         return computeGridSize / localWorkGroupSize;
116 }
117
118 tcu::ConstPixelBufferAccess getLayerOrSlice (const ImageType                                    imageType,
119                                                                                          const tcu::ConstPixelBufferAccess&     access,
120                                                                                          const deUint32                                         layer)
121 {
122         switch (imageType)
123         {
124                 case IMAGE_TYPE_1D:
125                 case IMAGE_TYPE_2D:
126                 case IMAGE_TYPE_BUFFER:
127                         DE_ASSERT(layer == 0);
128                         return access;
129
130                 case IMAGE_TYPE_1D_ARRAY:
131                         return tcu::getSubregion(access, 0, layer, access.getWidth(), 1);
132
133                 case IMAGE_TYPE_2D_ARRAY:
134                 case IMAGE_TYPE_3D:
135                 case IMAGE_TYPE_CUBE:
136                 case IMAGE_TYPE_CUBE_ARRAY:
137                         return tcu::getSubregion(access, 0, 0, layer, access.getWidth(), access.getHeight(), 1);
138
139                 default:
140                         DE_FATAL("Unknown image type");
141                         return tcu::ConstPixelBufferAccess();
142         }
143 }
144
145 bool comparePixelBuffers (tcu::TestContext&                                             testCtx,
146                                                   const ImageType                                               imageType,
147                                                   const tcu::UVec4&                                             imageSize,
148                                                   const tcu::TextureFormat&                             format,
149                                                   const tcu::ConstPixelBufferAccess&    reference,
150                                                   const tcu::ConstPixelBufferAccess&    result)
151 {
152         DE_ASSERT(reference.getFormat() == result.getFormat());
153         DE_ASSERT(reference.getSize() == result.getSize());
154
155         const bool               intFormat                      = isIntFormat(mapTextureFormat(format)) || isUintFormat(mapTextureFormat(format));
156         deUint32                 passedLayers           = 0;
157
158         for (deUint32 layerNdx = 0; layerNdx < imageSize.z() * imageSize.w(); ++layerNdx)
159         {
160                 const std::string comparisonName = "Comparison" + de::toString(layerNdx);
161
162                 std::string comparisonDesc = "Image Comparison, ";
163                 switch (imageType)
164                 {
165                         case IMAGE_TYPE_3D:
166                                 comparisonDesc = comparisonDesc + "slice " + de::toString(layerNdx);
167                                 break;
168
169                         case IMAGE_TYPE_CUBE:
170                         case IMAGE_TYPE_CUBE_ARRAY:
171                                 comparisonDesc = comparisonDesc + "face " + de::toString(layerNdx % 6) + ", cube " + de::toString(layerNdx / 6);
172                                 break;
173
174                         default:
175                                 comparisonDesc = comparisonDesc + "layer " + de::toString(layerNdx);
176                                 break;
177                 }
178
179                 const tcu::ConstPixelBufferAccess refLayer              = getLayerOrSlice(imageType, reference, layerNdx);
180                 const tcu::ConstPixelBufferAccess resultLayer   = getLayerOrSlice(imageType, result, layerNdx);
181
182                 bool ok = false;
183                 if (intFormat)
184                         ok = tcu::intThresholdCompare(testCtx.getLog(), comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer, tcu::UVec4(0), tcu::COMPARE_LOG_RESULT);
185                 else
186                         ok = tcu::floatThresholdCompare(testCtx.getLog(), comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer, tcu::Vec4(0.01f), tcu::COMPARE_LOG_RESULT);
187
188                 if (ok)
189                         ++passedLayers;
190         }
191
192         return passedLayers == (imageSize.z() * imageSize.w());
193 }
194
195 const std::string getCoordStr (const ImageType          imageType,
196                                                            const std::string&   x,
197                                                            const std::string&   y,
198                                                            const std::string&   z)
199 {
200         switch (imageType)
201         {
202                 case IMAGE_TYPE_1D:
203                 case IMAGE_TYPE_BUFFER:
204                         return x;
205
206                 case IMAGE_TYPE_1D_ARRAY:
207                 case IMAGE_TYPE_2D:
208                         return "ivec2(" + x + "," + y + ")";
209
210                 case IMAGE_TYPE_2D_ARRAY:
211                 case IMAGE_TYPE_3D:
212                 case IMAGE_TYPE_CUBE:
213                 case IMAGE_TYPE_CUBE_ARRAY:
214                         return "ivec3(" + x + "," + y + "," + z + ")";
215
216                 default:
217                         DE_ASSERT(false);
218                         return "";
219         }
220 }
221
222 class MemoryQualifierTestCase : public vkt::TestCase
223 {
224 public:
225
226         enum Qualifier
227         {
228                 QUALIFIER_COHERENT = 0,
229                 QUALIFIER_VOLATILE,
230                 QUALIFIER_RESTRICT,
231                 QUALIFIER_LAST
232         };
233
234                                                                 MemoryQualifierTestCase         (tcu::TestContext&                      testCtx,
235                                                                                                                          const std::string&                     name,
236                                                                                                                          const std::string&                     description,
237                                                                                                                          const Qualifier                        qualifier,
238                                                                                                                          const ImageType                        imageType,
239                                                                                                                          const tcu::UVec4&                      imageSize,
240                                                                                                                          const tcu::TextureFormat&      format,
241                                                                                                                          const glu::GLSLVersion         glslVersion);
242
243         virtual                                         ~MemoryQualifierTestCase        (void) {}
244
245         virtual void                            initPrograms                            (SourceCollections&                     programCollection) const;
246         virtual TestInstance*           createInstance                          (Context&                                       context) const;
247
248 protected:
249
250         const Qualifier                         m_qualifier;
251         const ImageType                         m_imageType;
252         const tcu::UVec4                        m_imageSize;
253         const tcu::TextureFormat        m_format;
254         const glu::GLSLVersion          m_glslVersion;
255 };
256
257 MemoryQualifierTestCase::MemoryQualifierTestCase (tcu::TestContext&                     testCtx,
258                                                                                                   const std::string&            name,
259                                                                                                   const std::string&            description,
260                                                                                                   const Qualifier                       qualifier,
261                                                                                                   const ImageType                       imageType,
262                                                                                                   const tcu::UVec4&                     imageSize,
263                                                                                                   const tcu::TextureFormat&     format,
264                                                                                                   const glu::GLSLVersion        glslVersion)
265         : vkt::TestCase(testCtx, name, description)
266         , m_qualifier(qualifier)
267         , m_imageType(imageType)
268         , m_imageSize(imageSize)
269         , m_format(format)
270         , m_glslVersion(glslVersion)
271 {
272 }
273
274 void MemoryQualifierTestCase::initPrograms (SourceCollections& programCollection) const
275 {
276         const char* const       versionDecl                     = glu::getGLSLVersionDeclaration(m_glslVersion);
277
278         const char* const       qualifierName           = m_qualifier == QUALIFIER_COHERENT ? "coherent"
279                                                                                         : m_qualifier == QUALIFIER_VOLATILE ? "volatile"
280                                                                                         : DE_NULL;
281
282         const bool                      uintFormat                      = isUintFormat(mapTextureFormat(m_format));
283         const bool                      intFormat                       = isIntFormat(mapTextureFormat(m_format));
284         const std::string       colorVecTypeName        = std::string(uintFormat ? "u"  : intFormat ? "i" : "") + "vec4";
285         const std::string       colorScalarTypeName = std::string(uintFormat ? "uint" : intFormat ? "int" : "float");
286         const std::string       invocationCoord         = getCoordStr(m_imageType, "gx", "gy", "gz");
287         const std::string       shaderImageFormat       = getShaderImageFormatQualifier(m_format);
288         const std::string       shaderImageType         = getShaderImageType(m_format, m_imageType);
289
290         const tcu::UVec3        localWorkGroupSize      = getLocalWorkGroupSize(m_imageType, m_imageSize);
291         const std::string       localSizeX                      = de::toString(localWorkGroupSize.x());
292         const std::string       localSizeY                      = de::toString(localWorkGroupSize.y());
293         const std::string       localSizeZ                      = de::toString(localWorkGroupSize.z());
294
295         std::ostringstream      programBuffer;
296
297         programBuffer
298                 << versionDecl << "\n"
299                 << "\n"
300                 << "precision highp " << shaderImageType << ";\n"
301                 << "\n"
302                 << "layout (local_size_x = " << localSizeX << ", local_size_y = " << localSizeY << ", local_size_z = " + localSizeZ << ") in;\n"
303                 << "layout (" << shaderImageFormat << ", binding=0) " << qualifierName << " uniform " << shaderImageType << " u_image;\n"
304                 << "void main (void)\n"
305                 << "{\n"
306                 << "    int gx = int(gl_GlobalInvocationID.x);\n"
307                 << "    int gy = int(gl_GlobalInvocationID.y);\n"
308                 << "    int gz = int(gl_GlobalInvocationID.z);\n"
309                 << "    imageStore(u_image, " << invocationCoord << ", " << colorVecTypeName << "(gx^gy^gz));\n"
310                 << "\n"
311                 << "    memoryBarrier();\n"
312                 << "    barrier();\n"
313                 << "\n"
314                 << "    " << colorScalarTypeName << " sum = " << colorScalarTypeName << "(0);\n"
315                 << "    int groupBaseX = gx/" << localSizeX << "*" << localSizeX << ";\n"
316                 << "    int groupBaseY = gy/" << localSizeY << "*" << localSizeY << ";\n"
317                 << "    int groupBaseZ = gz/" << localSizeZ << "*" << localSizeZ << ";\n"
318                 << "    int xOffsets[] = " << g_ShaderReadOffsetsXStr << ";\n"
319                 << "    int yOffsets[] = " << g_ShaderReadOffsetsYStr << ";\n"
320                 << "    int zOffsets[] = " << g_ShaderReadOffsetsZStr << ";\n"
321                 << "    for (int i = 0; i < " << de::toString(DE_LENGTH_OF_ARRAY(g_ShaderReadOffsetsX)) << "; i++)\n"
322                 << "    {\n"
323                 << "            int readX = groupBaseX + (gx + xOffsets[i]) % " + localSizeX + ";\n"
324                 << "            int readY = groupBaseY + (gy + yOffsets[i]) % " + localSizeY + ";\n"
325                 << "            int readZ = groupBaseZ + (gz + zOffsets[i]) % " + localSizeZ + ";\n"
326                 << "            sum += imageLoad(u_image, " << getCoordStr(m_imageType, "readX", "readY", "readZ") << ").x;\n"
327                 << "    }\n"
328                 << "\n"
329                 << "    memoryBarrier();\n"
330                 << "    barrier();\n"
331                 << "\n"
332                 << "    imageStore(u_image, " + invocationCoord + ", " + colorVecTypeName + "(sum));\n"
333                 << "}\n";
334
335         programCollection.glslSources.add(m_name) << glu::ComputeSource(programBuffer.str());
336 }
337
338 class MemoryQualifierInstanceBase : public vkt::TestInstance
339 {
340 public:
341                                                                         MemoryQualifierInstanceBase             (Context&                                       context,
342                                                                                                                                          const std::string&                     name,
343                                                                                                                                          const ImageType                        imageType,
344                                                                                                                                          const tcu::UVec4&                      imageSize,
345                                                                                                                                          const tcu::TextureFormat&      format);
346
347         virtual                                                 ~MemoryQualifierInstanceBase    (void) {};
348
349         virtual tcu::TestStatus                 iterate                                                 (void);
350
351         virtual void                                    prepareResources                                (const VkDeviceSize                     bufferSizeInBytes) = 0;
352
353         virtual void                                    prepareDescriptors                              (void) = 0;
354
355         virtual void                                    commandsBeforeCompute                   (const VkCommandBuffer          cmdBuffer,
356                                                                                                                                          const VkDeviceSize                     bufferSizeInBytes) const = 0;
357
358         virtual void                                    commandsAfterCompute                    (const VkCommandBuffer          cmdBuffer,
359                                                                                                                                          const VkDeviceSize                     bufferSizeInBytes) const = 0;
360 protected:
361
362         tcu::TextureLevel                               generateReferenceImage                  (void) const;
363
364         const std::string                               m_name;
365         const ImageType                                 m_imageType;
366         const tcu::UVec4                                m_imageSize;
367         const tcu::TextureFormat                m_format;
368
369         de::MovePtr<Buffer>                             m_buffer;
370         Move<VkDescriptorPool>                  m_descriptorPool;
371         Move<VkDescriptorSetLayout>             m_descriptorSetLayout;
372         Move<VkDescriptorSet>                   m_descriptorSet;
373 };
374
375 MemoryQualifierInstanceBase::MemoryQualifierInstanceBase (Context&                                      context,
376                                                                                                                   const std::string&            name,
377                                                                                                                   const ImageType                       imageType,
378                                                                                                                   const tcu::UVec4&                     imageSize,
379                                                                                                                   const tcu::TextureFormat&     format)
380         : vkt::TestInstance(context)
381         , m_name(name)
382         , m_imageType(imageType)
383         , m_imageSize(imageSize)
384         , m_format(format)
385 {
386 }
387
388 tcu::TestStatus MemoryQualifierInstanceBase::iterate (void)
389 {
390         const VkDevice                  device                          = m_context.getDevice();
391         const DeviceInterface&  deviceInterface         = m_context.getDeviceInterface();
392         const VkQueue                   queue                           = m_context.getUniversalQueue();
393         const deUint32                  queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
394
395         const VkDeviceSize      bufferSizeInBytes = m_imageSize.x() * m_imageSize.y() * m_imageSize.z() * m_imageSize.w() * tcu::getPixelSize(m_format);
396
397         // Prepare resources for the test
398         prepareResources(bufferSizeInBytes);
399
400         // Prepare descriptor sets
401         prepareDescriptors();
402
403         // Create compute shader
404         const vk::Unique<VkShaderModule> shaderModule(createShaderModule(deviceInterface, device, m_context.getBinaryCollection().get(m_name), 0u));
405
406         // Create compute pipeline
407         const vk::Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(deviceInterface, device, *m_descriptorSetLayout));
408         const vk::Unique<VkPipeline> pipeline(makeComputePipeline(deviceInterface, device, *pipelineLayout, *shaderModule));
409
410         // Create command buffer
411         const Unique<VkCommandPool> cmdPool(makeCommandPool(deviceInterface, device, queueFamilyIndex));
412         const Unique<VkCommandBuffer> cmdBuffer(makeCommandBuffer(deviceInterface, device, *cmdPool));
413
414         // Start recording commands
415         beginCommandBuffer(deviceInterface, *cmdBuffer);
416
417         deviceInterface.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
418         deviceInterface.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
419
420         commandsBeforeCompute(*cmdBuffer, bufferSizeInBytes);
421
422         const tcu::UVec3 numGroups = getNumWorkGroups(m_imageType, m_imageSize);
423         deviceInterface.cmdDispatch(*cmdBuffer, numGroups.x(), numGroups.y(), numGroups.z());
424
425         commandsAfterCompute(*cmdBuffer, bufferSizeInBytes);
426
427         endCommandBuffer(deviceInterface, *cmdBuffer);
428
429         // Submit and wait for completion
430         submitCommandsAndWait(deviceInterface, device, queue, *cmdBuffer);
431
432         // Retrieve data from buffer to host memory
433         const Allocation& allocation = m_buffer->getAllocation();
434         invalidateMappedMemoryRange(deviceInterface, device, allocation.getMemory(), allocation.getOffset(), bufferSizeInBytes);
435
436         const tcu::UVec3 computeGridSize = getComputeGridSize(m_imageType, m_imageSize);
437         tcu::ConstPixelBufferAccess resultPixelBuffer(m_format, computeGridSize.x(), computeGridSize.y(), computeGridSize.z(), allocation.getHostPtr());
438
439         // Create a reference image
440         tcu::TextureLevel referenceImage = generateReferenceImage();
441         tcu::ConstPixelBufferAccess referencePixelBuffer = referenceImage.getAccess();
442
443         // Validate the result
444         if (comparePixelBuffers(m_context.getTestContext(), m_imageType, m_imageSize, m_format, referencePixelBuffer, resultPixelBuffer))
445                 return tcu::TestStatus::pass("Passed");
446         else
447                 return tcu::TestStatus::fail("Image comparison failed");
448 }
449
450 tcu::TextureLevel MemoryQualifierInstanceBase::generateReferenceImage (void) const
451 {
452         // Generate a reference image data using the storage format
453         const tcu::UVec3 computeGridSize = getComputeGridSize(m_imageType, m_imageSize);
454
455         tcu::TextureLevel base(m_format, computeGridSize.x(), computeGridSize.y(), computeGridSize.z());
456         tcu::PixelBufferAccess baseAccess = base.getAccess();
457
458         tcu::TextureLevel reference(m_format, computeGridSize.x(), computeGridSize.y(), computeGridSize.z());
459         tcu::PixelBufferAccess referenceAccess = reference.getAccess();
460
461         for (deInt32 z = 0; z < baseAccess.getDepth(); ++z)
462                 for (deInt32 y = 0; y < baseAccess.getHeight(); ++y)
463                         for (deInt32 x = 0; x < baseAccess.getWidth(); ++x)
464                         {
465                                 baseAccess.setPixel(tcu::IVec4(x^y^z), x, y, z);
466                         }
467
468         const tcu::UVec3 localWorkGroupSize = getLocalWorkGroupSize(m_imageType, m_imageSize);
469
470         for (deInt32 z = 0; z < referenceAccess.getDepth(); ++z)
471                 for (deInt32 y = 0; y < referenceAccess.getHeight(); ++y)
472                         for (deInt32 x = 0; x < referenceAccess.getWidth(); ++x)
473                         {
474                                 const deInt32   groupBaseX      = x / localWorkGroupSize.x() * localWorkGroupSize.x();
475                                 const deInt32   groupBaseY      = y / localWorkGroupSize.y() * localWorkGroupSize.y();
476                                 const deInt32   groupBaseZ      = z / localWorkGroupSize.z() * localWorkGroupSize.z();
477                                 deInt32                 sum                     = 0;
478
479                                 for (deInt32 i = 0; i < DE_LENGTH_OF_ARRAY(g_ShaderReadOffsetsX); i++)
480                                 {
481                                         sum += baseAccess.getPixelInt(
482                                                 groupBaseX + (x + g_ShaderReadOffsetsX[i]) % localWorkGroupSize.x(),
483                                                 groupBaseY + (y + g_ShaderReadOffsetsY[i]) % localWorkGroupSize.y(),
484                                                 groupBaseZ + (z + g_ShaderReadOffsetsZ[i]) % localWorkGroupSize.z()).x();
485                                 }
486
487                                 referenceAccess.setPixel(tcu::IVec4(sum), x, y, z);
488                         }
489
490         return reference;
491 }
492
493 class MemoryQualifierInstanceImage : public MemoryQualifierInstanceBase
494 {
495 public:
496                                                 MemoryQualifierInstanceImage    (Context&                                       context,
497                                                                                                                  const std::string&                     name,
498                                                                                                                  const ImageType                        imageType,
499                                                                                                                  const tcu::UVec4&                      imageSize,
500                                                                                                                  const tcu::TextureFormat&      format)
501                                                         : MemoryQualifierInstanceBase(context, name, imageType, imageSize, format) {}
502
503         virtual                         ~MemoryQualifierInstanceImage   (void) {};
504
505         virtual void            prepareResources                                (const VkDeviceSize                     bufferSizeInBytes);
506
507         virtual void            prepareDescriptors                              (void);
508
509         virtual void            commandsBeforeCompute                   (const VkCommandBuffer          cmdBuffer,
510                                                                                                                  const VkDeviceSize                     bufferSizeInBytes) const;
511
512         virtual void            commandsAfterCompute                    (const VkCommandBuffer          cmdBuffer,
513                                                                                                                  const VkDeviceSize                     bufferSizeInBytes) const;
514 protected:
515
516         de::MovePtr<Image>      m_image;
517         Move<VkImageView>       m_imageView;
518 };
519
520 void MemoryQualifierInstanceImage::prepareResources (const VkDeviceSize bufferSizeInBytes)
521 {
522         const VkDevice                  device                  = m_context.getDevice();
523         const DeviceInterface&  deviceInterface = m_context.getDeviceInterface();
524         Allocator&                              allocator               = m_context.getDefaultAllocator();
525
526         // Create image
527         const VkImageCreateInfo imageCreateInfo =
528         {
529                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                                                    // VkStructureType                      sType;
530                 DE_NULL,                                                                                                                                // const void*                          pNext;
531                 m_imageType == IMAGE_TYPE_CUBE ||
532                 m_imageType     == IMAGE_TYPE_CUBE_ARRAY
533                 ? (VkImageCreateFlags)VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0u,                 // VkImageCreateFlags           flags;
534                 mapImageType(m_imageType),                                                                                              // VkImageType                          imageType;
535                 mapTextureFormat(m_format),                                                                                             // VkFormat                                     format;
536                 vk::makeExtent3D(m_imageSize.x(), m_imageSize.y(), m_imageSize.z()),    // VkExtent3D                           extent;
537                 1u,                                                                                                                                             // deUint32                                     mipLevels;
538                 m_imageSize.w(),                                                                                                                // deUint32                                     arrayLayers;
539                 VK_SAMPLE_COUNT_1_BIT,                                                                                                  // VkSampleCountFlagBits        samples;
540                 VK_IMAGE_TILING_OPTIMAL,                                                                                                // VkImageTiling                        tiling;
541                 VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_STORAGE_BIT,                   // VkImageUsageFlags            usage;
542                 VK_SHARING_MODE_EXCLUSIVE,                                                                                              // VkSharingMode                        sharingMode;
543                 0u,                                                                                                                                             // deUint32                                     queueFamilyIndexCount;
544                 DE_NULL,                                                                                                                                // const deUint32*                      pQueueFamilyIndices;
545                 VK_IMAGE_LAYOUT_UNDEFINED,                                                                                              // VkImageLayout                        initialLayout;
546         };
547
548         m_image = de::MovePtr<Image>(new Image(deviceInterface, device, allocator, imageCreateInfo, MemoryRequirement::Any));
549
550         // Create imageView
551         const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_imageSize.w());
552         m_imageView = makeImageView(deviceInterface, device, m_image->get(), mapImageViewType(m_imageType), mapTextureFormat(m_format), subresourceRange);
553
554         // Create a buffer to store shader output (copied from image data)
555         const VkBufferCreateInfo        bufferCreateInfo = makeBufferCreateInfo(bufferSizeInBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
556         m_buffer = de::MovePtr<Buffer>(new Buffer(deviceInterface, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
557 }
558 void MemoryQualifierInstanceImage::prepareDescriptors (void)
559 {
560         const VkDevice                  device                  = m_context.getDevice();
561         const DeviceInterface&  deviceInterface = m_context.getDeviceInterface();
562
563         // Create descriptor pool
564         m_descriptorPool =
565                 DescriptorPoolBuilder()
566                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
567                 .build(deviceInterface, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
568
569         // Create descriptor set layout
570         m_descriptorSetLayout =
571                 DescriptorSetLayoutBuilder()
572                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
573                 .build(deviceInterface, device);
574
575         // Allocate descriptor set
576         m_descriptorSet = makeDescriptorSet(deviceInterface, device, *m_descriptorPool, *m_descriptorSetLayout);
577
578         // Set the bindings
579         const VkDescriptorImageInfo descriptorImageInfo = makeDescriptorImageInfo(DE_NULL, *m_imageView, VK_IMAGE_LAYOUT_GENERAL);
580
581         DescriptorSetUpdateBuilder()
582                 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
583                 .update(deviceInterface, device);
584 }
585
586 void MemoryQualifierInstanceImage::commandsBeforeCompute (const VkCommandBuffer cmdBuffer, const VkDeviceSize bufferSizeInBytes) const
587 {
588         DE_UNREF(bufferSizeInBytes);
589
590         const DeviceInterface&                  deviceInterface  = m_context.getDeviceInterface();
591         const VkImageSubresourceRange   subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_imageSize.w());
592
593         const VkImageMemoryBarrier imageLayoutBarrier
594                 = makeImageMemoryBarrier(0u,
595                                                                  VK_ACCESS_SHADER_READ_BIT,
596                                                                  VK_IMAGE_LAYOUT_UNDEFINED,
597                                                                  VK_IMAGE_LAYOUT_GENERAL,
598                                                                  m_image->get(),
599                                                                  subresourceRange);
600
601         deviceInterface.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &imageLayoutBarrier);
602 }
603
604 void MemoryQualifierInstanceImage::commandsAfterCompute (const VkCommandBuffer cmdBuffer, const VkDeviceSize    bufferSizeInBytes) const
605 {
606         const DeviceInterface&                  deviceInterface  = m_context.getDeviceInterface();
607         const VkImageSubresourceRange   subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_imageSize.w());
608
609         const VkImageMemoryBarrier imagePreCopyBarrier
610                 = makeImageMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT,
611                                                                  VK_ACCESS_TRANSFER_READ_BIT,
612                                                                  VK_IMAGE_LAYOUT_GENERAL,
613                                                                  VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
614                                                                  m_image->get(),
615                                                                  subresourceRange);
616
617         deviceInterface.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &imagePreCopyBarrier);
618
619         const VkBufferImageCopy copyParams = makeBufferImageCopy(vk::makeExtent3D(m_imageSize.x(), m_imageSize.y(), m_imageSize.z()), m_imageSize.w());
620         deviceInterface.cmdCopyImageToBuffer(cmdBuffer, m_image->get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_buffer->get(), 1u, &copyParams);
621
622         const VkBufferMemoryBarrier bufferPostCopyBarrier
623                 = makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT,
624                                                                   VK_ACCESS_HOST_READ_BIT,
625                                                                   m_buffer->get(),
626                                                                   0ull,
627                                                                   bufferSizeInBytes);
628
629         deviceInterface.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &bufferPostCopyBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
630 }
631
632 class MemoryQualifierInstanceBuffer : public MemoryQualifierInstanceBase
633 {
634 public:
635                                                 MemoryQualifierInstanceBuffer   (Context&                                       context,
636                                                                                                                  const std::string&                     name,
637                                                                                                                  const ImageType                        imageType,
638                                                                                                                  const tcu::UVec4&                      imageSize,
639                                                                                                                  const tcu::TextureFormat&      format)
640                                                         : MemoryQualifierInstanceBase(context, name, imageType, imageSize, format) {}
641
642         virtual                         ~MemoryQualifierInstanceBuffer  (void) {};
643
644         virtual void            prepareResources                                (const VkDeviceSize                     bufferSizeInBytes);
645
646         virtual void            prepareDescriptors                              (void);
647
648         virtual void            commandsBeforeCompute                   (const VkCommandBuffer,
649                                                                                                                  const VkDeviceSize) const {}
650
651         virtual void            commandsAfterCompute                    (const VkCommandBuffer          cmdBuffer,
652                                                                                                                  const VkDeviceSize                     bufferSizeInBytes) const;
653 protected:
654
655         Move<VkBufferView>      m_bufferView;
656 };
657
658 void MemoryQualifierInstanceBuffer::prepareResources (const VkDeviceSize bufferSizeInBytes)
659 {
660         const VkDevice                  device                  = m_context.getDevice();
661         const DeviceInterface&  deviceInterface = m_context.getDeviceInterface();
662         Allocator&                              allocator               = m_context.getDefaultAllocator();
663
664         // Create a buffer to store shader output
665         const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSizeInBytes, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT);
666         m_buffer = de::MovePtr<Buffer>(new Buffer(deviceInterface, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
667
668         m_bufferView = makeBufferView(deviceInterface, device, m_buffer->get(), mapTextureFormat(m_format), 0ull, bufferSizeInBytes);
669 }
670
671 void MemoryQualifierInstanceBuffer::prepareDescriptors (void)
672 {
673         const VkDevice                  device                  = m_context.getDevice();
674         const DeviceInterface&  deviceInterface = m_context.getDeviceInterface();
675
676         // Create descriptor pool
677         m_descriptorPool =
678                 DescriptorPoolBuilder()
679                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
680                 .build(deviceInterface, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
681
682         // Create descriptor set layout
683         m_descriptorSetLayout =
684                 DescriptorSetLayoutBuilder()
685                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
686                 .build(deviceInterface, device);
687
688         // Allocate descriptor set
689         m_descriptorSet = makeDescriptorSet(deviceInterface, device, *m_descriptorPool, *m_descriptorSetLayout);
690
691         // Set the bindings
692         DescriptorSetUpdateBuilder()
693                 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &m_bufferView.get())
694                 .update(deviceInterface, device);
695 }
696
697 void MemoryQualifierInstanceBuffer::commandsAfterCompute (const VkCommandBuffer cmdBuffer, const VkDeviceSize bufferSizeInBytes) const
698 {
699         const DeviceInterface&  deviceInterface = m_context.getDeviceInterface();
700
701         const VkBufferMemoryBarrier shaderWriteBarrier
702                 = makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT,
703                                                                   VK_ACCESS_HOST_READ_BIT,
704                                                                   m_buffer->get(),
705                                                                   0ull,
706                                                                   bufferSizeInBytes);
707
708         deviceInterface.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &shaderWriteBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
709 }
710
711 TestInstance* MemoryQualifierTestCase::createInstance (Context& context) const
712 {
713         if ( m_imageType == IMAGE_TYPE_BUFFER )
714                 return new MemoryQualifierInstanceBuffer(context, m_name, m_imageType, m_imageSize, m_format);
715         else
716                 return new MemoryQualifierInstanceImage(context, m_name, m_imageType, m_imageSize, m_format);
717 }
718
719 } // anonymous ns
720
721 tcu::TestCaseGroup* createImageQualifiersTests (tcu::TestContext& testCtx)
722 {
723         de::MovePtr<tcu::TestCaseGroup> imageQualifiersTests(new tcu::TestCaseGroup(testCtx, "qualifiers", "Coherent, volatile and restrict"));
724
725         struct ImageParameters
726         {
727                 ImageType       imageType;
728                 tcu::UVec4      imageSize;
729         };
730
731         static const ImageParameters imageParametersArray[] =
732         {
733                 { IMAGE_TYPE_1D,                        tcu::UVec4(64, 1,  1, 1)        },
734                 { IMAGE_TYPE_1D_ARRAY,          tcu::UVec4(64, 1,  1, 8)        },
735                 { IMAGE_TYPE_2D,                        tcu::UVec4(64, 64, 1, 1)        },
736                 { IMAGE_TYPE_2D_ARRAY,          tcu::UVec4(64, 64, 1, 8)        },
737                 { IMAGE_TYPE_3D,                        tcu::UVec4(64, 64, 8, 1)        },
738                 { IMAGE_TYPE_CUBE,                      tcu::UVec4(64, 64, 1, 6)        },
739                 { IMAGE_TYPE_CUBE_ARRAY,        tcu::UVec4(64, 64, 1, 6*8)      },
740                 { IMAGE_TYPE_BUFFER,            tcu::UVec4(64, 1,  1, 1)        }
741         };
742
743         static const tcu::TextureFormat formats[] =
744         {
745                 tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT),
746                 tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::UNSIGNED_INT32),
747                 tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::SIGNED_INT32),
748         };
749
750         for (deUint32 qualifierI = 0; qualifierI < MemoryQualifierTestCase::QUALIFIER_LAST; ++qualifierI)
751         {
752                 const MemoryQualifierTestCase::Qualifier        memoryQualifier         = (MemoryQualifierTestCase::Qualifier)qualifierI;
753                 const char* const                                                       memoryQualifierName =
754                         memoryQualifier == MemoryQualifierTestCase::QUALIFIER_COHERENT ? "coherent" :
755                         memoryQualifier == MemoryQualifierTestCase::QUALIFIER_VOLATILE ? "volatile" :
756                         memoryQualifier == MemoryQualifierTestCase::QUALIFIER_RESTRICT ? "restrict" :
757                         DE_NULL;
758
759                 de::MovePtr<tcu::TestCaseGroup> qualifierGroup(new tcu::TestCaseGroup(testCtx, memoryQualifierName, ""));
760
761                 for (deInt32 imageTypeNdx = 0; imageTypeNdx < DE_LENGTH_OF_ARRAY(imageParametersArray); imageTypeNdx++)
762                 {
763                         const ImageType         imageType = imageParametersArray[imageTypeNdx].imageType;
764                         const tcu::UVec4        imageSize = imageParametersArray[imageTypeNdx].imageSize;
765
766                         if (memoryQualifier == MemoryQualifierTestCase::QUALIFIER_RESTRICT)
767                         {
768                                 de::MovePtr<TestCase> restrictCase = createImageQualifierRestrictCase(testCtx, imageType, getImageTypeName(imageType));
769                                 qualifierGroup->addChild(restrictCase.release());
770                         }
771                         else
772                         {
773                                 for (deInt32 formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
774                                 {
775                                         const tcu::TextureFormat&       format          = formats[formatNdx];
776                                         const std::string                       formatName      = getShaderImageFormatQualifier(formats[formatNdx]);
777
778                                         qualifierGroup->addChild(
779                                                 new MemoryQualifierTestCase(testCtx, getImageTypeName(imageType) + std::string("_") + formatName,
780                                                 "", memoryQualifier, imageType, imageSize, format, glu::GLSL_VERSION_440));
781                                 }
782                         }
783                 }
784
785                 imageQualifiersTests->addChild(qualifierGroup.release());
786         }
787
788         return imageQualifiersTests.release();
789 }
790
791 } // image
792 } // vkt