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