Merge vk-gl-cts/vulkan-cts-1.2.2 into vk-gl-cts/vulkan-cts-1.2.3
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / protected_memory / vktProtectedMemStorageBufferTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2017 The Khronos Group Inc.
6  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
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 Protected memory storage buffer tests
23  *//*--------------------------------------------------------------------*/
24
25 #include "vktProtectedMemStorageBufferTests.hpp"
26
27 #include "deRandom.hpp"
28 #include "deStringUtil.hpp"
29 #include "tcuTestLog.hpp"
30 #include "tcuVector.hpp"
31 #include "tcuStringTemplate.hpp"
32
33 #include "vkPrograms.hpp"
34 #include "vktTestCase.hpp"
35 #include "vktTestGroupUtil.hpp"
36 #include "vkTypeUtil.hpp"
37 #include "vkBuilderUtil.hpp"
38 #include "vkCmdUtil.hpp"
39
40 #include "vktProtectedMemBufferValidator.hpp"
41 #include "vktProtectedMemUtils.hpp"
42 #include "vktProtectedMemContext.hpp"
43
44 namespace vkt
45 {
46 namespace ProtectedMem
47 {
48
49 namespace
50 {
51
52 enum {
53         RENDER_HEIGHT   = 128,
54         RENDER_WIDTH    = 128,
55 };
56
57 enum {
58         RANDOM_TEST_COUNT       = 10,
59 };
60
61 enum SSBOTestType {
62         SSBO_READ,
63         SSBO_WRITE,
64         SSBO_ATOMIC
65 };
66
67 enum SSBOAtomicType {
68         ATOMIC_ADD,
69         ATOMIC_MIN,
70         ATOMIC_MAX,
71         ATOMIC_AND,
72         ATOMIC_OR,
73         ATOMIC_XOR,
74         ATOMIC_EXCHANGE,
75         ATOMIC_COMPSWAP
76 };
77
78
79 const char* getSSBOTestDescription (SSBOTestType type)
80 {
81         switch (type) {
82                 case SSBO_READ:         return "Test for read storage buffer on protected memory.";
83                 case SSBO_WRITE:        return "Test for write storage buffer on protected memory.";
84                 case SSBO_ATOMIC:       return "Test for atomic storage buffer on protected memory.";
85                 default: DE_FATAL("Invalid SSBO test type"); return "";
86         }
87 }
88
89 const char* getSSBOTypeString (SSBOTestType type)
90 {
91         switch (type) {
92                 case SSBO_READ:         return "read";
93                 case SSBO_WRITE:        return "write";
94                 case SSBO_ATOMIC:       return "atomic";
95                 default: DE_FATAL("Invalid SSBO test type"); return "";
96         }
97 }
98
99 const char* getSSBOAtomicTypeString (SSBOAtomicType type)
100 {
101         switch (type)
102         {
103                 case ATOMIC_ADD:                return "add";
104                 case ATOMIC_MIN:                return "min";
105                 case ATOMIC_MAX:                return "max";
106                 case ATOMIC_AND:                return "and";
107                 case ATOMIC_OR:                 return "or";
108                 case ATOMIC_XOR:                return "xor";
109                 case ATOMIC_EXCHANGE:   return "exchange";
110                 case ATOMIC_COMPSWAP:   return "compswap";
111                 default: DE_FATAL("Invalid SSBO atomic operation type"); return "";
112         }
113 }
114
115 void static addBufferCopyCmd (const vk::DeviceInterface&        vk,
116                                                           vk::VkCommandBuffer                   cmdBuffer,
117                                                           deUint32                                              queueFamilyIndex,
118                                                           vk::VkBuffer                                  srcBuffer,
119                                                           vk::VkBuffer                                  dstBuffer,
120                                                           deUint32                                              copySize)
121 {
122         const vk::VkBufferMemoryBarrier         dstWriteStartBarrier    =
123         {
124                 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,            // VkStructureType              sType
125                 DE_NULL,                                                                                        // const void*                  pNext
126                 0,                                                                                                      // VkAccessFlags                srcAccessMask
127                 vk::VK_ACCESS_SHADER_WRITE_BIT,                                         // VkAccessFlags                dstAccessMask
128                 queueFamilyIndex,                                                                       // uint32_t                             srcQueueFamilyIndex
129                 queueFamilyIndex,                                                                       // uint32_t                             dstQueueFamilyIndex
130                 dstBuffer,                                                                                      // VkBuffer                             buffer
131                 0u,                                                                                                     // VkDeviceSize                 offset
132                 VK_WHOLE_SIZE,                                                                          // VkDeviceSize                 size
133         };
134
135         vk.cmdPipelineBarrier(cmdBuffer,
136                                                   vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,        // srcStageMask
137                                                   vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,      // dstStageMask
138                                                   (vk::VkDependencyFlags)0,
139                                                   0, (const vk::VkMemoryBarrier*)DE_NULL,
140                                                   1, &dstWriteStartBarrier,
141                                                   0, (const vk::VkImageMemoryBarrier*)DE_NULL);
142
143         const vk::VkBufferCopy                          copyRegion                              =
144         {
145                 0,                                      // VkDeviceSize srcOffset
146                 0,                                      // VkDeviceSize dstOffset
147                 copySize                        // VkDeviceSize size
148         };
149         vk.cmdCopyBuffer(cmdBuffer, srcBuffer, dstBuffer, 1, &copyRegion);
150
151         const vk::VkBufferMemoryBarrier         dstWriteEndBarrier              =
152         {
153                 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,            // VkStructureType              sType
154                 DE_NULL,                                                                                        // const void*                  pNext
155                 vk::VK_ACCESS_SHADER_WRITE_BIT,                                         // VkAccessFlags                srcAccessMask
156                 vk::VK_ACCESS_SHADER_READ_BIT,                                          // VkAccessFlags                dstAccessMask
157                 queueFamilyIndex,                                                                       // uint32_t                             srcQueueFamilyIndex
158                 queueFamilyIndex,                                                                       // uint32_t                             dstQueueFamilyIndex
159                 dstBuffer,                                                                                      // VkBuffer                             buffer
160                 0u,                                                                                                     // VkDeviceSize                 offset
161                 VK_WHOLE_SIZE,                                                                          // VkDeviceSize                 size
162         };
163         vk.cmdPipelineBarrier(cmdBuffer,
164                                                   vk::VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,              // srcStageMask
165                                                   vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,    // dstStageMask
166                                                   (vk::VkDependencyFlags)0,
167                                                   0, (const vk::VkMemoryBarrier*)DE_NULL,
168                                                   1, &dstWriteEndBarrier,
169                                                   0, (const vk::VkImageMemoryBarrier*)DE_NULL);
170
171 }
172
173 template<typename T>
174 class StorageBufferTestInstance : public ProtectedTestInstance
175 {
176 public:
177                                                                 StorageBufferTestInstance       (Context&                                       ctx,
178                                                                                                                          const SSBOTestType                     testType,
179                                                                                                                          const glu::ShaderType          shaderType,
180                                                                                                                          const tcu::UVec4                       testInput,
181                                                                                                                          const BufferValidator<T>&      validator);
182         virtual tcu::TestStatus         iterate                                         (void);
183
184 private:
185         tcu::TestStatus                         executeFragmentTest                     (void);
186         tcu::TestStatus                         executeComputeTest                      (void);
187
188         const SSBOTestType                      m_testType;
189         const glu::ShaderType           m_shaderType;
190         const tcu::UVec4                        m_testInput;
191         const BufferValidator<T>&       m_validator;
192         const vk::VkFormat                      m_imageFormat;
193 };
194
195 template<typename T>
196 class StorageBufferTestCase : public TestCase
197 {
198 public:
199                                                                 StorageBufferTestCase   (tcu::TestContext&                      testctx,
200                                                                                                                  const SSBOTestType                     testType,
201                                                                                                                  const glu::ShaderType          shaderType,
202                                                                                                                  const char*                            name,
203                                                                                                                  const tcu::UVec4                       testInput,
204                                                                                                                  ValidationDataStorage<T>       validationData,
205                                                                                                                  vk::VkFormat                           format,
206                                                                                                                  const std::string&                     extraShader = "")
207                                                                         : TestCase              (testctx, name, getSSBOTestDescription(testType))
208                                                                         , m_testType    (testType)
209                                                                         , m_shaderType  (shaderType)
210                                                                         , m_testInput   (testInput)
211                                                                         , m_validator   (validationData, format)
212                                                                         , m_extraShader (extraShader)
213                                                                 {
214                                                                 }
215         virtual TestInstance*           createInstance                  (Context& ctx) const
216                                                                 {
217                                                                         return new StorageBufferTestInstance<T>(ctx, m_testType, m_shaderType, m_testInput, m_validator);
218                                                                 }
219         virtual void                            initPrograms                    (vk::SourceCollections& programCollection) const;
220         virtual void                            checkSupport                    (Context& context) const
221                                                                 {
222                                                                         checkProtectedQueueSupport(context);
223                                                                 }
224
225         virtual                                         ~StorageBufferTestCase  (void) {}
226
227 private:
228         const SSBOTestType                      m_testType;
229         const glu::ShaderType           m_shaderType;
230         const tcu::UVec4                        m_testInput;
231         const BufferValidator<T>        m_validator;
232         const std::string                       m_extraShader;
233 };
234
235 template<typename T>
236 StorageBufferTestInstance<T>::StorageBufferTestInstance  (Context&                                      ctx,
237                                                                                                                   const SSBOTestType            testType,
238                                                                                                                   const glu::ShaderType         shaderType,
239                                                                                                                   const tcu::UVec4                      testInput,
240                                                                                                                   const BufferValidator<T>&     validator)
241         : ProtectedTestInstance (ctx)
242         , m_testType                    (testType)
243         , m_shaderType                  (shaderType)
244         , m_testInput                   (testInput)
245         , m_validator                   (validator)
246         , m_imageFormat                 (vk::VK_FORMAT_R8G8B8A8_UNORM)
247 {
248 }
249
250 template<typename T>
251 void StorageBufferTestCase<T>::initPrograms (vk::SourceCollections& programCollection) const
252 {
253         const char* vertexShader =
254                 "#version 450\n"
255                 "layout(location=0) out vec4 vIndex;\n"
256                 "void main() {\n"
257                 "    vec2 pos[4] = vec2[4]( vec2(-0.7, 0.7), vec2(0.7, 0.7), vec2(0.0, -0.7), vec2(-0.7, -0.7) );\n"
258                 "    vIndex = vec4(gl_VertexIndex);\n"
259                 "    gl_PointSize = 1.0;\n"
260                 "    gl_Position = vec4(pos[gl_VertexIndex], 0.0, 1.0);\n"
261                 "}";
262
263         //  set = 0, location = 0 -> buffer ProtectedTestBuffer (uvec4)
264         //  set = 0, location = 2 -> buffer ProtectedTestBufferSource (uvec4)
265         const char* readShaderTemplateStr =
266                 "#version 450\n"
267                 "${INPUT_DECLARATION}\n"
268                 "\n"
269                 "layout(set=0, binding=0, std140) buffer ProtectedTestBuffer\n"
270                 "{\n"
271                 "    highp uvec4 protectedTestResultBuffer;\n"
272                 "};\n"
273                 "\n"
274                 "layout(set=0, binding=2, std140) buffer ProtectedTestBufferSource\n"
275                 "{\n"
276                 "    highp uvec4 protectedTestBufferSource;\n"
277                 "};\n"
278                 "\n"
279                 "void main (void)\n"
280                 "{\n"
281                 "    protectedTestResultBuffer = protectedTestBufferSource;\n"
282                 "    ${FRAGMENT_OUTPUT}\n"
283                 "}\n";
284
285         //  set = 0, location = 0 -> buffer ProtectedTestBuffer (uvec4)
286         //  set = 0, location = 1 -> uniform Data (uvec4)
287         const char* writeShaderTemplateStr =
288                 "#version 450\n"
289                 "${INPUT_DECLARATION}\n"
290                 "\n"
291                 "layout(set=0, binding=0, std140) buffer ProtectedTestBuffer\n"
292                 "{\n"
293                 "    highp uvec4 protectedTestResultBuffer;\n"
294                 "};\n"
295                 "\n"
296                 "layout(set=0, binding=1, std140) uniform Data\n"
297                 "{\n"
298                 "    highp uvec4 testInput;\n"
299                 "};\n"
300                 "\n"
301                 "void main (void)\n"
302                 "{\n"
303                 "    protectedTestResultBuffer = testInput;\n"
304                 "    ${FRAGMENT_OUTPUT}\n"
305                 "}\n";
306
307         //  set = 0, location = 0 -> buffer ProtectedTestBuffer (uint [4])
308         const char* atomicTestShaderTemplateStr =
309                 "#version 450\n"
310                 "${INPUT_DECLARATION}\n"
311                 "\n"
312                 "layout(set=0, binding=0, std430) buffer ProtectedTestBuffer\n"
313                 "{\n"
314                 "    highp uint protectedTestResultBuffer[4];\n"
315                 "};\n"
316                 "\n"
317                 "void main (void)\n"
318                 "{\n"
319                 "    uint i = uint(${INVOCATION_ID});\n"
320                 "    ${ATOMIC_FUNCTION_CALL}\n"
321                 "    ${FRAGMENT_OUTPUT}\n"
322                 "}\n";
323
324         const char*                                                     shaderTemplateStr;
325         std::map<std::string, std::string>      shaderParam;
326         switch (m_testType) {
327                 case SSBO_READ:         shaderTemplateStr = readShaderTemplateStr; break;
328                 case SSBO_WRITE:        shaderTemplateStr = writeShaderTemplateStr; break;
329                 case SSBO_ATOMIC:       {
330                         shaderTemplateStr = atomicTestShaderTemplateStr;
331                         shaderParam["ATOMIC_FUNCTION_CALL"] = m_extraShader;
332                         break;
333                 }
334                 default: DE_FATAL("Incorrect SSBO test type"); return;
335         }
336
337         if (m_shaderType == glu::SHADERTYPE_FRAGMENT)
338         {
339                 shaderParam["INPUT_DECLARATION"]                = "layout(location=0) out mediump vec4 o_color;\n"
340                                                                                                   "layout(location=0) in vec4 vIndex;\n";
341                 shaderParam["FRAGMENT_OUTPUT"]                  = "o_color = vec4( 0.0, 0.4, 1.0, 1.0 );\n";
342                 shaderParam["INVOCATION_ID"]                    = "vIndex.x";
343
344                 programCollection.glslSources.add("vert") << glu::VertexSource(vertexShader);
345                 programCollection.glslSources.add("TestShader") << glu::FragmentSource(tcu::StringTemplate(shaderTemplateStr).specialize(shaderParam));
346         }
347         else if (m_shaderType == glu::SHADERTYPE_COMPUTE)
348         {
349                 shaderParam["INPUT_DECLARATION"]                = "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n";
350                 shaderParam["FRAGMENT_OUTPUT"]                  = "";
351                 shaderParam["INVOCATION_ID"]                    = "gl_GlobalInvocationID.x";
352                 programCollection.glslSources.add("TestShader") << glu::ComputeSource(tcu::StringTemplate(shaderTemplateStr).specialize(shaderParam));
353         }
354         else
355                 DE_FATAL("Incorrect shader type");
356
357         m_validator.initPrograms(programCollection);
358 }
359
360 template<typename T>
361 tcu::TestStatus StorageBufferTestInstance<T>::executeFragmentTest(void)
362 {
363         ProtectedContext&                                               ctx                                     (m_protectedContext);
364         const vk::DeviceInterface&                              vk                                      = ctx.getDeviceInterface();
365         const vk::VkDevice                                              device                          = ctx.getDevice();
366         const vk::VkQueue                                               queue                           = ctx.getQueue();
367         const deUint32                                                  queueFamilyIndex        = ctx.getQueueFamilyIndex();
368
369         const deUint32                                                  testUniformSize         = sizeof(m_testInput);
370         de::UniquePtr<vk::BufferWithMemory>             testUniform                     (makeBuffer(ctx,
371                                                                                                                                                 PROTECTION_DISABLED,
372                                                                                                                                                 queueFamilyIndex,
373                                                                                                                                                 testUniformSize,
374                                                                                                                                                 vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
375                                                                                                                                                  | vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
376                                                                                                                                                 vk::MemoryRequirement::HostVisible));
377
378         // Set the test input uniform data
379         {
380                 deMemcpy(testUniform->getAllocation().getHostPtr(), &m_testInput, testUniformSize);
381                 vk::flushAlloc(vk, device, testUniform->getAllocation());
382         }
383         const deUint32                                                  testBufferSize          = sizeof(ValidationDataStorage<T>);
384         de::MovePtr<vk::BufferWithMemory>               testBuffer                      (makeBuffer(ctx,
385                                                                                                                                                         PROTECTION_ENABLED,
386                                                                                                                                                         queueFamilyIndex,
387                                                                                                                                                         testBufferSize,
388                                                                                                                                                         vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
389                                                                                                                                                          | vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT,
390                                                                                                                                                         vk::MemoryRequirement::Protected));
391     de::MovePtr<vk::BufferWithMemory>           testBufferSource                        (makeBuffer(ctx,
392                                                                                                                                                         PROTECTION_ENABLED,
393                                                                                                                                                         queueFamilyIndex,
394                                                                                                                                                         testBufferSize,
395                                                                                                                                                         vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
396                                                                                                                                                          | vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT,
397                                                                                                                                                         vk::MemoryRequirement::Protected));
398
399         vk::Move<vk::VkShaderModule>                    vertexShader            (vk::createShaderModule(vk, device, ctx.getBinaryCollection().get("vert"), 0));
400         vk::Unique<vk::VkShaderModule>                  testShader                      (vk::createShaderModule(vk, device, ctx.getBinaryCollection().get("TestShader"), 0));
401
402         // Create descriptors
403         vk::Unique<vk::VkDescriptorSetLayout>   descriptorSetLayout(vk::DescriptorSetLayoutBuilder()
404                 .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_ALL)
405                 .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, vk::VK_SHADER_STAGE_ALL)
406                 .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_ALL)
407                 .build(vk, device));
408         vk::Unique<vk::VkDescriptorPool>                descriptorPool(vk::DescriptorPoolBuilder()
409                 .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u)
410                 .addType(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u)
411                 .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u)
412                 .build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
413         vk::Unique<vk::VkDescriptorSet>                 descriptorSet           (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
414
415         // Update descriptor set information
416         {
417                 vk::VkDescriptorBufferInfo      descTestBuffer                  = makeDescriptorBufferInfo(**testBuffer, 0, testBufferSize);
418                 vk::VkDescriptorBufferInfo      descTestUniform                 = makeDescriptorBufferInfo(**testUniform, 0, testUniformSize);
419                 vk::VkDescriptorBufferInfo      descTestBufferSource    = makeDescriptorBufferInfo(**testBufferSource, 0, testBufferSize);
420
421                 vk::DescriptorSetUpdateBuilder()
422                         .writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descTestBuffer)
423                         .writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descTestUniform)
424                         .writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descTestBufferSource)
425                         .update(vk, device);
426         }
427
428         // Create output image
429         de::MovePtr<vk::ImageWithMemory>                colorImage                      (createImage2D(ctx, PROTECTION_ENABLED, queueFamilyIndex,
430                                                                                                                                                            RENDER_WIDTH, RENDER_HEIGHT,
431                                                                                                                                                            m_imageFormat,
432                                                                                                                                                            vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|vk::VK_IMAGE_USAGE_SAMPLED_BIT));
433         vk::Unique<vk::VkImageView>                             colorImageView          (createImageView(ctx, **colorImage, m_imageFormat));
434         vk::Unique<vk::VkRenderPass>                    renderPass                      (createRenderPass(ctx, m_imageFormat));
435         vk::Unique<vk::VkFramebuffer>                   framebuffer                     (createFramebuffer(ctx, RENDER_WIDTH, RENDER_HEIGHT, *renderPass, *colorImageView));
436
437         // Build pipeline
438         vk::Unique<vk::VkPipelineLayout>                pipelineLayout          (makePipelineLayout(vk, device, *descriptorSetLayout));
439         vk::Unique<vk::VkCommandPool>                   cmdPool                         (makeCommandPool(vk, device, PROTECTION_ENABLED, queueFamilyIndex));
440         vk::Unique<vk::VkCommandBuffer>                 cmdBuffer                       (vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
441
442         // Create pipeline
443         vk::Unique<vk::VkPipeline>                              graphicsPipeline        (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass,
444                                                                                                                                                                           *vertexShader, *testShader,
445                                                                                                                                                                           std::vector<vk::VkVertexInputBindingDescription>(),
446                                                                                                                                                                           std::vector<vk::VkVertexInputAttributeDescription>(),
447                                                                                                                                                                           tcu::UVec2(RENDER_WIDTH, RENDER_HEIGHT),
448                                                                                                                                                                           vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST));
449
450         beginCommandBuffer(vk, *cmdBuffer);
451
452         if (m_testType == SSBO_READ || m_testType == SSBO_ATOMIC)
453         {
454                 vk::VkBuffer targetBuffer = (m_testType == SSBO_ATOMIC) ? **testBuffer : **testBufferSource;
455                 addBufferCopyCmd(vk, *cmdBuffer, queueFamilyIndex, **testUniform, targetBuffer, testUniformSize);
456         }
457
458         // Start image barrier
459         {
460                 const vk::VkImageMemoryBarrier  startImgBarrier         =
461                 {
462                         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                     // sType
463                         DE_NULL,                                                                                        // pNext
464                         0,                                                                                                      // srcAccessMask
465                         vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                       // dstAccessMask
466                         vk::VK_IMAGE_LAYOUT_UNDEFINED,                                          // oldLayout
467                         vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,           // newLayout
468                         queueFamilyIndex,                                                                       // srcQueueFamilyIndex
469                         queueFamilyIndex,                                                                       // dstQueueFamilyIndex
470                         **colorImage,                                                                           // image
471                         {
472                                 vk::VK_IMAGE_ASPECT_COLOR_BIT,                                  // aspectMask
473                                 0u,                                                                                             // baseMipLevel
474                                 1u,                                                                                             // mipLevels
475                                 0u,                                                                                             // baseArraySlice
476                                 1u,                                                                                             // subresourceRange
477                         }
478                 };
479
480                 vk.cmdPipelineBarrier(*cmdBuffer,
481                                                           vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,                                // srcStageMask
482                                                           vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,    // dstStageMask
483                                                           (vk::VkDependencyFlags)0,
484                                                           0, (const vk::VkMemoryBarrier*)DE_NULL,
485                                                           0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
486                                                           1, &startImgBarrier);
487         }
488
489         beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, vk::makeRect2D(0, 0, RENDER_WIDTH, RENDER_HEIGHT), tcu::Vec4(0.125f, 0.25f, 0.5f, 1.0f));
490         vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
491         vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &*descriptorSet, 0u, DE_NULL);
492
493         vk.cmdDraw(*cmdBuffer, 4u, 1u, 0u, 0u);
494         endRenderPass(vk, *cmdBuffer);
495
496         {
497                 const vk::VkImageMemoryBarrier  endImgBarrier           =
498                 {
499                         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                     // sType
500                         DE_NULL,                                                                                        // pNext
501                         vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                       // srcAccessMask
502                         vk::VK_ACCESS_SHADER_READ_BIT,                                          // dstAccessMask
503                         vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,           // oldLayout
504                         vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,           // newLayout
505                         queueFamilyIndex,                                                                       // srcQueueFamilyIndex
506                         queueFamilyIndex,                                                                       // dstQueueFamilyIndex
507                         **colorImage,                                                                           // image
508                         {
509                                 vk::VK_IMAGE_ASPECT_COLOR_BIT,                                  // aspectMask
510                                 0u,                                                                                             // baseMipLevel
511                                 1u,                                                                                             // mipLevels
512                                 0u,                                                                                             // baseArraySlice
513                                 1u,                                                                                             // subresourceRange
514                         }
515                 };
516                 vk.cmdPipelineBarrier(*cmdBuffer,
517                                                           vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,    // srcStageMask
518                                                           vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,                               // dstStageMask
519                                                           (vk::VkDependencyFlags)0,
520                                                           0, (const vk::VkMemoryBarrier*)DE_NULL,
521                                                           0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
522                                                           1, &endImgBarrier);
523         }
524
525         endCommandBuffer(vk, *cmdBuffer);
526
527         // Execute Draw
528         {
529                 const vk::Unique<vk::VkFence> fence (vk::createFence(vk, device));
530                 VK_CHECK(vk.resetFences(device, 1, &fence.get()));
531                 VK_CHECK(queueSubmit(ctx, PROTECTION_ENABLED, queue, *cmdBuffer, *fence, ~0ull));
532         }
533
534         // Log inputs
535         ctx.getTestContext().getLog()
536                         << tcu::TestLog::Message << "Input values: \n"
537                         << "1: " << m_testInput << "\n"
538                         << tcu::TestLog::EndMessage;
539
540         // Validate buffer
541         if (m_validator.validateBuffer(ctx, **testBuffer))
542                 return tcu::TestStatus::pass("Everything went OK");
543         else
544                 return tcu::TestStatus::fail("Something went really wrong");
545 }
546
547 template<typename T>
548 tcu::TestStatus StorageBufferTestInstance<T>::executeComputeTest(void)
549 {
550         ProtectedContext&                                               ctx                                     (m_protectedContext);
551         const vk::DeviceInterface&                              vk                                      = ctx.getDeviceInterface();
552         const vk::VkDevice                                              device                          = ctx.getDevice();
553         const vk::VkQueue                                               queue                           = ctx.getQueue();
554         const deUint32                                                  queueFamilyIndex        = ctx.getQueueFamilyIndex();
555
556         const deUint32                                                  testUniformSize         = sizeof(m_testInput);
557         de::UniquePtr<vk::BufferWithMemory>             testUniform                     (makeBuffer(ctx,
558                                                                                                                                                 PROTECTION_DISABLED,
559                                                                                                                                                 queueFamilyIndex,
560                                                                                                                                                 testUniformSize,
561                                                                                                                                                 vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
562                                                                                                                                                  | vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
563                                                                                                                                                 vk::MemoryRequirement::HostVisible));
564
565         // Set the test input uniform data
566         {
567                 deMemcpy(testUniform->getAllocation().getHostPtr(), &m_testInput, testUniformSize);
568                 vk::flushAlloc(vk, device, testUniform->getAllocation());
569         }
570
571         const deUint32                                                  testBufferSize          = sizeof(ValidationDataStorage<T>);
572         de::MovePtr<vk::BufferWithMemory>               testBuffer                      (makeBuffer(ctx,
573                                                                                                                                                         PROTECTION_ENABLED,
574                                                                                                                                                         queueFamilyIndex,
575                                                                                                                                                         testBufferSize,
576                                                                                                                                                         vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
577                                                                                                                                                          | vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT,
578                                                                                                                                                         vk::MemoryRequirement::Protected));
579         de::MovePtr<vk::BufferWithMemory>               testBufferSource        (makeBuffer(ctx,
580                                                                                                                                                         PROTECTION_ENABLED,
581                                                                                                                                                         queueFamilyIndex,
582                                                                                                                                                         testBufferSize,
583                                                                                                                                                         vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
584                                                                                                                                                          | vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT,
585                                                                                                                                                         vk::MemoryRequirement::Protected));
586
587         vk::Unique<vk::VkShaderModule>                  testShader                      (vk::createShaderModule(vk, device, ctx.getBinaryCollection().get("TestShader"), 0));
588
589         // Create descriptors
590         vk::Unique<vk::VkDescriptorSetLayout>   descriptorSetLayout(vk::DescriptorSetLayoutBuilder()
591                 .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT)
592                 .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT)
593                 .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT)
594                 .build(vk, device));
595         vk::Unique<vk::VkDescriptorPool>                descriptorPool(vk::DescriptorPoolBuilder()
596                 .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u)
597                 .addType(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u)
598                 .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u)
599                 .build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
600         vk::Unique<vk::VkDescriptorSet>                 descriptorSet           (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
601
602         // Update descriptor set information
603         {
604                 vk::VkDescriptorBufferInfo      descTestBuffer                  = makeDescriptorBufferInfo(**testBuffer, 0, testBufferSize);
605                 vk::VkDescriptorBufferInfo      descTestUniform                 = makeDescriptorBufferInfo(**testUniform, 0, testUniformSize);
606                 vk::VkDescriptorBufferInfo      descTestBufferSource    = makeDescriptorBufferInfo(**testBufferSource, 0, testBufferSize);
607
608                 vk::DescriptorSetUpdateBuilder()
609                         .writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descTestBuffer)
610                         .writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descTestUniform)
611                         .writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descTestBufferSource)
612                         .update(vk, device);
613         }
614
615
616         // Build and execute test
617         {
618                 const vk::Unique<vk::VkFence>           fence                           (vk::createFence(vk, device));
619                 vk::Unique<vk::VkPipelineLayout>        pipelineLayout          (makePipelineLayout(vk, device, *descriptorSetLayout));
620                 vk::Unique<vk::VkPipeline>                      SSBOPipeline            (makeComputePipeline(vk, device, *pipelineLayout, *testShader, DE_NULL));
621                 vk::Unique<vk::VkCommandPool>           cmdPool                         (makeCommandPool(vk, device, PROTECTION_ENABLED, queueFamilyIndex));
622                 vk::Unique<vk::VkCommandBuffer>         cmdBuffer                       (vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
623                 deUint32                                                        dispatchCount           = (m_testType == SSBO_ATOMIC) ? 4u : 1u;
624
625                 beginCommandBuffer(vk, *cmdBuffer);
626
627                 if (m_testType == SSBO_READ || m_testType == SSBO_ATOMIC)
628                 {
629                         vk::VkBuffer targetBuffer = (m_testType == SSBO_ATOMIC) ? **testBuffer : **testBufferSource;
630                         addBufferCopyCmd(vk, *cmdBuffer, queueFamilyIndex, **testUniform, targetBuffer, testUniformSize);
631                 }
632
633                 vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *SSBOPipeline);
634                 vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &*descriptorSet, 0u, DE_NULL);
635
636                 vk.cmdDispatch(*cmdBuffer, dispatchCount, 1u, 1u);
637
638                 endCommandBuffer(vk, *cmdBuffer);
639                 VK_CHECK(queueSubmit(ctx, PROTECTION_ENABLED, queue, *cmdBuffer, *fence, ~0ull));
640         }
641
642         ctx.getTestContext().getLog()
643                         << tcu::TestLog::Message << "Input values: \n"
644                         << "1: " << m_testInput << "\n"
645                         << tcu::TestLog::EndMessage;
646
647         // Validate buffer
648         if (m_validator.validateBuffer(ctx, **testBuffer))
649                 return tcu::TestStatus::pass("Everything went OK");
650         else
651                 return tcu::TestStatus::fail("Something went really wrong");
652 }
653
654 template<typename T>
655 tcu::TestStatus StorageBufferTestInstance<T>::iterate(void)
656 {
657         switch (m_shaderType)
658         {
659                 case glu::SHADERTYPE_FRAGMENT:  return executeFragmentTest();
660                 case glu::SHADERTYPE_COMPUTE:   return executeComputeTest();
661                 default:
662                         DE_FATAL("Incorrect shader type"); return tcu::TestStatus::fail("");
663         }
664 }
665
666 tcu::TestCaseGroup* createSpecifiedStorageBufferTests (tcu::TestContext&                                                testCtx,
667                                                                                                            const std::string                                            groupName,
668                                                                                                            SSBOTestType                                                         testType,
669                                                                                                            const glu::ShaderType                                        shaderType,
670                                                                                                            const ValidationDataStorage<tcu::UVec4>      testData[],
671                                                                                                            size_t                                                                       testCount)
672 {
673         const std::string                               testTypeStr             = getSSBOTypeString(testType);
674         const std::string                               description             = "Storage buffer " + testTypeStr + " tests";
675         de::MovePtr<tcu::TestCaseGroup> testGroup               (new tcu::TestCaseGroup(testCtx, groupName.c_str(), description.c_str()));
676
677         for (size_t ndx = 0; ndx < testCount; ++ndx)
678         {
679                 const std::string name = testTypeStr + "_" + de::toString(ndx + 1);
680                 testGroup->addChild(new StorageBufferTestCase<tcu::UVec4>(testCtx, testType, shaderType, name.c_str(), testData[ndx].values, testData[ndx], vk::VK_FORMAT_R32G32B32A32_UINT));
681         }
682
683         return testGroup.release();
684 }
685
686 tcu::TestCaseGroup* createRandomizedBufferTests (tcu::TestContext& testCtx, SSBOTestType testType, const glu::ShaderType shaderType, size_t testCount)
687 {
688         de::Random                                                                                      rnd                             (testCtx.getCommandLine().getBaseSeed());
689         std::vector<ValidationDataStorage<tcu::UVec4> >         testData;
690         testData.resize(testCount);
691
692         for (size_t ndx = 0; ndx < testCount; ++ndx)
693                 for (deUint32 compIdx = 0; compIdx < 4; ++compIdx)
694                         testData[ndx].values[compIdx] = rnd.getUint32();
695
696         return createSpecifiedStorageBufferTests(testCtx, "random", testType, shaderType, testData.data(), testData.size());
697 }
698
699 tcu::TestCaseGroup* createRWStorageBufferTests (tcu::TestContext&                                                       testCtx,
700                                                                                                 const std::string                                                       groupName,
701                                                                                                 const std::string                                                       groupDescription,
702                                                                                                 SSBOTestType                                                            testType,
703                                                                                                 const ValidationDataStorage<tcu::UVec4>         testData[],
704                                                                                                 size_t                                                                          testCount)
705 {
706         de::MovePtr<tcu::TestCaseGroup> ssboRWTestGroup (new tcu::TestCaseGroup(testCtx, groupName.c_str(), groupDescription.c_str()));
707
708         glu::ShaderType                                 shaderTypes[] = {
709                 glu::SHADERTYPE_FRAGMENT,
710                 glu::SHADERTYPE_COMPUTE
711         };
712
713         for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(shaderTypes); ++shaderNdx)
714         {
715                 const glu::ShaderType                           shaderType                      = shaderTypes[shaderNdx];
716                 const std::string                                       shaderName                      = glu::getShaderTypeName(shaderType);
717                 const std::string                                       shaderGroupDesc         = "Storage buffer tests for shader type: " + shaderName;
718                 de::MovePtr<tcu::TestCaseGroup>         testShaderGroup         (new tcu::TestCaseGroup(testCtx, shaderName.c_str(), shaderGroupDesc.c_str()));
719
720                 testShaderGroup->addChild(createSpecifiedStorageBufferTests(testCtx, "static", testType, shaderType, testData, testCount));
721                 testShaderGroup->addChild(createRandomizedBufferTests(testCtx, testType, shaderType, RANDOM_TEST_COUNT));
722                 ssboRWTestGroup->addChild(testShaderGroup.release());
723         }
724
725         return ssboRWTestGroup.release();
726 }
727
728 void calculateAtomicOpData (SSBOAtomicType              type,
729                                                         const tcu::UVec4&       inputValue,
730                                                         const deUint32          atomicArg,
731                                                         std::string&            atomicCall,
732                                                         tcu::UVec4&                     refValue,
733                                                         const deUint32          swapNdx = 0)
734 {
735         switch (type)
736         {
737                 case ATOMIC_ADD:
738                 {
739                         refValue        = inputValue + tcu::UVec4(atomicArg);
740                         atomicCall      = "atomicAdd(protectedTestResultBuffer[i], " + de::toString(atomicArg) + "u);";
741                         break;
742                 }
743                 case ATOMIC_MIN:
744                 {
745                         refValue        = tcu::UVec4(std::min(inputValue.x(), atomicArg), std::min(inputValue.y(), atomicArg), std::min(inputValue.z(), atomicArg), std::min(inputValue.w(), atomicArg));
746                         atomicCall      = "atomicMin(protectedTestResultBuffer[i], " + de::toString(atomicArg) + "u);";
747                         break;
748                 }
749                 case ATOMIC_MAX:
750                 {
751                         refValue        = tcu::UVec4(std::max(inputValue.x(), atomicArg), std::max(inputValue.y(), atomicArg), std::max(inputValue.z(), atomicArg), std::max(inputValue.w(), atomicArg));
752                         atomicCall      = "atomicMax(protectedTestResultBuffer[i], " + de::toString(atomicArg) + "u);";
753                         break;
754                 }
755                 case ATOMIC_AND:
756                 {
757                         refValue        = tcu::UVec4(inputValue.x() & atomicArg, inputValue.y() & atomicArg, inputValue.z() & atomicArg, inputValue.w() & atomicArg);
758                         atomicCall      = "atomicAnd(protectedTestResultBuffer[i], " + de::toString(atomicArg) + "u);";
759                         break;
760                 }
761                 case ATOMIC_OR:
762                 {
763                         refValue        = tcu::UVec4(inputValue.x() | atomicArg, inputValue.y() | atomicArg, inputValue.z() | atomicArg, inputValue.w() | atomicArg);
764                         atomicCall      = "atomicOr(protectedTestResultBuffer[i], " + de::toString(atomicArg) + "u);";
765                         break;
766                 }
767                 case ATOMIC_XOR:
768                 {
769                         refValue        = tcu::UVec4(inputValue.x() ^ atomicArg, inputValue.y() ^ atomicArg, inputValue.z() ^ atomicArg, inputValue.w() ^ atomicArg);
770                         atomicCall      = "atomicXor(protectedTestResultBuffer[i], " + de::toString(atomicArg) + "u);";
771                         break;
772                 }
773                 case ATOMIC_EXCHANGE:
774                 {
775                         refValue        = tcu::UVec4(atomicArg);
776                         atomicCall      = "atomicExchange(protectedTestResultBuffer[i], " + de::toString(atomicArg) + "u);";
777                         break;
778                 }
779                 case ATOMIC_COMPSWAP:
780                 {
781                         int                     selectedNdx             = swapNdx % 4;
782                         deUint32        selectedChange  = inputValue[selectedNdx];
783
784                         refValue                                = inputValue;
785                         refValue[selectedNdx]   = atomicArg;
786                         atomicCall                              = "atomicCompSwap(protectedTestResultBuffer[i], " + de::toString(selectedChange) + "u, " + de::toString(atomicArg) + "u);";
787                         break;
788                 }
789                 default: DE_FATAL("Incorrect atomic function type"); break;
790         }
791
792 }
793
794 } // anonymous
795
796 tcu::TestCaseGroup* createReadStorageBufferTests (tcu::TestContext& testCtx)
797 {
798         const ValidationDataStorage<tcu::UVec4> testData[] = {
799                 { tcu::UVec4(0u, 0u, 0u, 0u) }, { tcu::UVec4(1u, 0u, 0u, 0u) },
800                 { tcu::UVec4(0u, 1u, 0u, 0u) }, { tcu::UVec4(0u, 0u, 1u, 0u) },
801                 { tcu::UVec4(0u, 0u, 0u, 1u) }, { tcu::UVec4(1u, 1u, 1u, 1u) }
802         };
803
804         return createRWStorageBufferTests(testCtx, "ssbo_read", "Storage Buffer Read Tests", SSBO_READ, testData, DE_LENGTH_OF_ARRAY(testData));
805 }
806
807 tcu::TestCaseGroup* createWriteStorageBufferTests (tcu::TestContext& testCtx)
808 {
809         const ValidationDataStorage<tcu::UVec4> testData[] = {
810                 { tcu::UVec4(0u, 0u, 0u, 0u) }, { tcu::UVec4(1u, 0u, 0u, 0u) },
811                 { tcu::UVec4(0u, 1u, 0u, 0u) }, { tcu::UVec4(0u, 0u, 1u, 0u) },
812                 { tcu::UVec4(0u, 0u, 0u, 1u) }, { tcu::UVec4(1u, 1u, 1u, 1u) }
813         };
814
815         return createRWStorageBufferTests(testCtx, "ssbo_write", "Storage Buffer Write Tests", SSBO_WRITE, testData, DE_LENGTH_OF_ARRAY(testData));
816 }
817
818 tcu::TestCaseGroup* createAtomicStorageBufferTests (tcu::TestContext& testctx)
819 {
820         struct {
821                 const tcu::UVec4        input;
822                 const deUint32          atomicArg;
823                 const deUint32          swapNdx;
824         }                                                               testData[]      = {
825                 { tcu::UVec4(0u,                1u,                     2u,                     3u),            10u,    0u      },
826                 { tcu::UVec4(10u,               20u,            30u,            40u),           3u,             2u      },
827                 { tcu::UVec4(800u,              400u,           230u,           999u),          50u,    3u      },
828                 { tcu::UVec4(100800u,   233400u,        22230u,         77999u),        800u,   1u      },
829         };
830
831         SSBOAtomicType                                  testTypes[]     = {
832                 ATOMIC_ADD,
833                 ATOMIC_MIN,
834                 ATOMIC_MAX,
835                 ATOMIC_AND,
836                 ATOMIC_OR,
837                 ATOMIC_XOR,
838                 ATOMIC_EXCHANGE,
839                 ATOMIC_COMPSWAP
840         };
841
842         glu::ShaderType                                 shaderTypes[] = {
843                 glu::SHADERTYPE_FRAGMENT,
844                 glu::SHADERTYPE_COMPUTE
845         };
846
847         de::Random                                              rnd                             (testctx.getCommandLine().getBaseSeed());
848         de::MovePtr<tcu::TestCaseGroup> ssboAtomicTests (new tcu::TestCaseGroup(testctx, "ssbo_atomic", "Storage Buffer Atomic Tests"));
849
850         for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(shaderTypes); ++shaderNdx)
851         {
852                 const glu::ShaderType                           shaderType                      = shaderTypes[shaderNdx];
853                 const std::string                                       shaderName                      = glu::getShaderTypeName(shaderType);
854                 const std::string                                       shaderDesc                      = "Storage Buffer Atomic Tests for shader type: " + shaderName;
855                 de::MovePtr<tcu::TestCaseGroup>         atomicShaderGroup       (new tcu::TestCaseGroup(testctx, shaderName.c_str(), shaderDesc.c_str()));
856
857                 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(testTypes); ++typeNdx)
858                 {
859                         SSBOAtomicType                                  atomicType              = testTypes[typeNdx];
860                         const std::string                               atomicTypeStr   = getSSBOAtomicTypeString(atomicType);
861                         const std::string                               atomicDesc              = "Storage Buffer Atomic Tests: " + atomicTypeStr;
862
863                         de::MovePtr<tcu::TestCaseGroup> staticTests             (new tcu::TestCaseGroup(testctx, "static", (atomicDesc + " with static input").c_str()));
864                         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(testData); ++ndx)
865                         {
866                                 const std::string       name            = "atomic_" + atomicTypeStr + "_" + de::toString(ndx + 1);
867                                 const tcu::UVec4&       inputValue      = testData[ndx].input;
868                                 const deUint32&         atomicArg       = testData[ndx].atomicArg;
869                                 std::string                     atomicCall;
870                                 tcu::UVec4                      refValue;
871
872                                 calculateAtomicOpData(atomicType, inputValue, atomicArg, atomicCall, refValue, testData[ndx].swapNdx);
873
874                                 ValidationDataStorage<tcu::UVec4>       validationData  = { refValue };
875                                 staticTests->addChild(new StorageBufferTestCase<tcu::UVec4>(testctx, SSBO_ATOMIC, shaderType, name.c_str(), inputValue, validationData, vk::VK_FORMAT_R32G32B32A32_UINT, atomicCall));
876                         }
877
878                         de::MovePtr<tcu::TestCaseGroup> randomTests             (new tcu::TestCaseGroup(testctx, "random", (atomicDesc + " with random input").c_str()));
879                         for (int ndx = 0; ndx < RANDOM_TEST_COUNT; ndx++)
880                         {
881                                 const std::string                                       name                    = "atomic_" + atomicTypeStr + "_" + de::toString(ndx + 1);
882                                 deUint32                                                        atomicArg               = rnd.getUint16();
883                                 tcu::UVec4                                                      inputValue;
884                                 tcu::UVec4                                                      refValue;
885                                 std::string                                                     atomicCall;
886
887                                 for (int i = 0; i < 4; i++)
888                                         inputValue[i] = rnd.getUint16();
889
890                                 calculateAtomicOpData(atomicType, inputValue, atomicArg, atomicCall, refValue, ndx);
891
892                                 ValidationDataStorage<tcu::UVec4>       validationData  = { refValue };
893                                 randomTests->addChild(new StorageBufferTestCase<tcu::UVec4>(testctx, SSBO_ATOMIC, shaderType, name.c_str(), inputValue, validationData, vk::VK_FORMAT_R32G32B32A32_UINT, atomicCall));
894
895                         }
896
897                         de::MovePtr<tcu::TestCaseGroup> atomicTests             (new tcu::TestCaseGroup(testctx, atomicTypeStr.c_str(), atomicDesc.c_str()));
898                         atomicTests->addChild(staticTests.release());
899                         atomicTests->addChild(randomTests.release());
900                         atomicShaderGroup->addChild(atomicTests.release());
901                 }
902                 ssboAtomicTests->addChild(atomicShaderGroup.release());
903         }
904
905         return ssboAtomicTests.release();
906 }
907
908 } // ProtectedMem
909 } // vkt