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