Merge remote-tracking branch 'khronos/master' into deqp-dev
[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                 testData[ndx].values = tcu::UVec4(rnd.getUint32(), rnd.getUint32(), rnd.getUint32(), rnd.getUint32());
698
699         return createSpecifiedStorageBufferTests(testCtx, "random", testType, shaderType, testData.data(), testData.size());
700 }
701
702 tcu::TestCaseGroup* createRWStorageBufferTests (tcu::TestContext&                                                       testCtx,
703                                                                                                 const std::string                                                       groupName,
704                                                                                                 const std::string                                                       groupDescription,
705                                                                                                 SSBOTestType                                                            testType,
706                                                                                                 const ValidationDataStorage<tcu::UVec4>         testData[],
707                                                                                                 size_t                                                                          testCount)
708 {
709         de::MovePtr<tcu::TestCaseGroup> ssboRWTestGroup (new tcu::TestCaseGroup(testCtx, groupName.c_str(), groupDescription.c_str()));
710
711         glu::ShaderType                                 shaderTypes[] = {
712                 glu::SHADERTYPE_FRAGMENT,
713                 glu::SHADERTYPE_COMPUTE
714         };
715
716         for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(shaderTypes); ++shaderNdx)
717         {
718                 const glu::ShaderType                           shaderType                      = shaderTypes[shaderNdx];
719                 const std::string                                       shaderName                      = getShaderTypeString(shaderType);
720                 const std::string                                       shaderGroupDesc         = "Storage buffer tests for shader type: " + shaderName;
721                 de::MovePtr<tcu::TestCaseGroup>         testShaderGroup         (new tcu::TestCaseGroup(testCtx, shaderName.c_str(), shaderGroupDesc.c_str()));
722
723                 testShaderGroup->addChild(createSpecifiedStorageBufferTests(testCtx, "static", testType, shaderType, testData, testCount));
724                 testShaderGroup->addChild(createRandomizedBufferTests(testCtx, testType, shaderType, RANDOM_TEST_COUNT));
725                 ssboRWTestGroup->addChild(testShaderGroup.release());
726         }
727
728         return ssboRWTestGroup.release();
729 }
730
731 void calculateAtomicOpData (SSBOAtomicType              type,
732                                                         const tcu::UVec4&       inputValue,
733                                                         const deUint32          atomicArg,
734                                                         std::string&            atomicCall,
735                                                         tcu::UVec4&                     refValue,
736                                                         const deUint32          swapNdx = 0)
737 {
738         switch (type)
739         {
740                 case ATOMIC_ADD:
741                 {
742                         refValue        = inputValue + tcu::UVec4(atomicArg);
743                         atomicCall      = "atomicAdd(protectedTestResultBuffer[i], " + de::toString(atomicArg) + "u);";
744                         break;
745                 }
746                 case ATOMIC_MIN:
747                 {
748                         refValue        = tcu::UVec4(std::min(inputValue.x(), atomicArg), std::min(inputValue.y(), atomicArg), std::min(inputValue.z(), atomicArg), std::min(inputValue.w(), atomicArg));
749                         atomicCall      = "atomicMin(protectedTestResultBuffer[i], " + de::toString(atomicArg) + "u);";
750                         break;
751                 }
752                 case ATOMIC_MAX:
753                 {
754                         refValue        = tcu::UVec4(std::max(inputValue.x(), atomicArg), std::max(inputValue.y(), atomicArg), std::max(inputValue.z(), atomicArg), std::max(inputValue.w(), atomicArg));
755                         atomicCall      = "atomicMax(protectedTestResultBuffer[i], " + de::toString(atomicArg) + "u);";
756                         break;
757                 }
758                 case ATOMIC_AND:
759                 {
760                         refValue        = tcu::UVec4(inputValue.x() & atomicArg, inputValue.y() & atomicArg, inputValue.z() & atomicArg, inputValue.w() & atomicArg);
761                         atomicCall      = "atomicAnd(protectedTestResultBuffer[i], " + de::toString(atomicArg) + "u);";
762                         break;
763                 }
764                 case ATOMIC_OR:
765                 {
766                         refValue        = tcu::UVec4(inputValue.x() | atomicArg, inputValue.y() | atomicArg, inputValue.z() | atomicArg, inputValue.w() | atomicArg);
767                         atomicCall      = "atomicOr(protectedTestResultBuffer[i], " + de::toString(atomicArg) + "u);";
768                         break;
769                 }
770                 case ATOMIC_XOR:
771                 {
772                         refValue        = tcu::UVec4(inputValue.x() ^ atomicArg, inputValue.y() ^ atomicArg, inputValue.z() ^ atomicArg, inputValue.w() ^ atomicArg);
773                         atomicCall      = "atomicXor(protectedTestResultBuffer[i], " + de::toString(atomicArg) + "u);";
774                         break;
775                 }
776                 case ATOMIC_EXCHANGE:
777                 {
778                         refValue        = tcu::UVec4(atomicArg);
779                         atomicCall      = "atomicExchange(protectedTestResultBuffer[i], " + de::toString(atomicArg) + "u);";
780                         break;
781                 }
782                 case ATOMIC_COMPSWAP:
783                 {
784                         int                     selectedNdx             = swapNdx % 4;
785                         deUint32        selectedChange  = inputValue[selectedNdx];
786
787                         refValue                                = inputValue;
788                         refValue[selectedNdx]   = atomicArg;
789                         atomicCall                              = "atomicCompSwap(protectedTestResultBuffer[i], " + de::toString(selectedChange) + "u, " + de::toString(atomicArg) + "u);";
790                         break;
791                 }
792                 default: DE_FATAL("Incorrect atomic function type"); break;
793         }
794
795 }
796
797 } // anonymous
798
799 tcu::TestCaseGroup* createReadStorageBufferTests (tcu::TestContext& testCtx)
800 {
801         const ValidationDataStorage<tcu::UVec4> testData[] = {
802                 { tcu::UVec4(0u, 0u, 0u, 0u) }, { tcu::UVec4(1u, 0u, 0u, 0u) },
803                 { tcu::UVec4(0u, 1u, 0u, 0u) }, { tcu::UVec4(0u, 0u, 1u, 0u) },
804                 { tcu::UVec4(0u, 0u, 0u, 1u) }, { tcu::UVec4(1u, 1u, 1u, 1u) }
805         };
806
807         return createRWStorageBufferTests(testCtx, "ssbo_read", "Storage Buffer Read Tests", SSBO_READ, testData, DE_LENGTH_OF_ARRAY(testData));
808 }
809
810 tcu::TestCaseGroup* createWriteStorageBufferTests (tcu::TestContext& testCtx)
811 {
812         const ValidationDataStorage<tcu::UVec4> testData[] = {
813                 { tcu::UVec4(0u, 0u, 0u, 0u) }, { tcu::UVec4(1u, 0u, 0u, 0u) },
814                 { tcu::UVec4(0u, 1u, 0u, 0u) }, { tcu::UVec4(0u, 0u, 1u, 0u) },
815                 { tcu::UVec4(0u, 0u, 0u, 1u) }, { tcu::UVec4(1u, 1u, 1u, 1u) }
816         };
817
818         return createRWStorageBufferTests(testCtx, "ssbo_write", "Storage Buffer Write Tests", SSBO_WRITE, testData, DE_LENGTH_OF_ARRAY(testData));
819 }
820
821 tcu::TestCaseGroup* createAtomicStorageBufferTests (tcu::TestContext& testctx)
822 {
823         struct {
824                 const tcu::UVec4        input;
825                 const deUint32          atomicArg;
826                 const deUint32          swapNdx;
827         }                                                               testData[]      = {
828                 { tcu::UVec4(0u,                1u,                     2u,                     3u),            10u,    0u      },
829                 { tcu::UVec4(10u,               20u,            30u,            40u),           3u,             2u      },
830                 { tcu::UVec4(800u,              400u,           230u,           999u),          50u,    3u      },
831                 { tcu::UVec4(100800u,   233400u,        22230u,         77999u),        800u,   1u      },
832         };
833
834         SSBOAtomicType                                  testTypes[]     = {
835                 ATOMIC_ADD,
836                 ATOMIC_MIN,
837                 ATOMIC_MAX,
838                 ATOMIC_AND,
839                 ATOMIC_OR,
840                 ATOMIC_XOR,
841                 ATOMIC_EXCHANGE,
842                 ATOMIC_COMPSWAP
843         };
844
845         glu::ShaderType                                 shaderTypes[] = {
846                 glu::SHADERTYPE_FRAGMENT,
847                 glu::SHADERTYPE_COMPUTE
848         };
849
850         de::Random                                              rnd                             (testctx.getCommandLine().getBaseSeed());
851         de::MovePtr<tcu::TestCaseGroup> ssboAtomicTests (new tcu::TestCaseGroup(testctx, "ssbo_atomic", "Storage Buffer Atomic Tests"));
852
853         for (int shaderNdx = 0; shaderNdx < DE_LENGTH_OF_ARRAY(shaderTypes); ++shaderNdx)
854         {
855                 const glu::ShaderType                           shaderType                      = shaderTypes[shaderNdx];
856                 const std::string                                       shaderName                      = getShaderTypeString(shaderType);
857                 const std::string                                       shaderDesc                      = "Storage Buffer Atomic Tests for shader type: " + shaderName;
858                 de::MovePtr<tcu::TestCaseGroup>         atomicShaderGroup       (new tcu::TestCaseGroup(testctx, shaderName.c_str(), shaderDesc.c_str()));
859
860                 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(testTypes); ++typeNdx)
861                 {
862                         SSBOAtomicType                                  atomicType              = testTypes[typeNdx];
863                         const std::string                               atomicTypeStr   = getSSBOAtomicTypeString(atomicType);
864                         const std::string                               atomicDesc              = "Storage Buffer Atomic Tests: " + atomicTypeStr;
865
866                         de::MovePtr<tcu::TestCaseGroup> staticTests             (new tcu::TestCaseGroup(testctx, "static", (atomicDesc + " with static input").c_str()));
867                         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(testData); ++ndx)
868                         {
869                                 const std::string       name            = "atomic_" + atomicTypeStr + "_" + de::toString(ndx + 1);
870                                 const tcu::UVec4&       inputValue      = testData[ndx].input;
871                                 const deUint32&         atomicArg       = testData[ndx].atomicArg;
872                                 std::string                     atomicCall;
873                                 tcu::UVec4                      refValue;
874
875                                 calculateAtomicOpData(atomicType, inputValue, atomicArg, atomicCall, refValue, testData[ndx].swapNdx);
876
877                                 ValidationDataStorage<tcu::UVec4>       validationData  = { refValue };
878                                 staticTests->addChild(new StorageBufferTestCase<tcu::UVec4>(testctx, SSBO_ATOMIC, shaderType, name.c_str(), inputValue, validationData, atomicCall));
879                         }
880
881                         de::MovePtr<tcu::TestCaseGroup> randomTests             (new tcu::TestCaseGroup(testctx, "random", (atomicDesc + " with random input").c_str()));
882                         for (int ndx = 0; ndx < RANDOM_TEST_COUNT; ndx++)
883                         {
884                                 const std::string                                       name                    = "atomic_" + atomicTypeStr + "_" + de::toString(ndx + 1);
885                                 deUint32                                                        atomicArg               = rnd.getUint16();
886                                 tcu::UVec4                                                      inputValue;
887                                 tcu::UVec4                                                      refValue;
888                                 std::string                                                     atomicCall;
889
890                                 for (int i = 0; i < 4; i++)
891                                         inputValue[i] = rnd.getUint16();
892
893                                 calculateAtomicOpData(atomicType, inputValue, atomicArg, atomicCall, refValue, ndx);
894
895                                 ValidationDataStorage<tcu::UVec4>       validationData  = { refValue };
896                                 randomTests->addChild(new StorageBufferTestCase<tcu::UVec4>(testctx, SSBO_ATOMIC, shaderType, name.c_str(), inputValue, validationData, atomicCall));
897
898                         }
899
900                         de::MovePtr<tcu::TestCaseGroup> atomicTests             (new tcu::TestCaseGroup(testctx, atomicTypeStr.c_str(), atomicDesc.c_str()));
901                         atomicTests->addChild(staticTests.release());
902                         atomicTests->addChild(randomTests.release());
903                         atomicShaderGroup->addChild(atomicTests.release());
904                 }
905                 ssboAtomicTests->addChild(atomicShaderGroup.release());
906         }
907
908         return ssboAtomicTests.release();
909 }
910
911 } // ProtectedMem
912 } // vkt