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