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