035d4cdc674185db331a012a77b01d3995e1d267
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / robustness / vktRobustnessBufferAccessTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  * Copyright (c) 2016 Imagination Technologies 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 Robust buffer access tests for uniform/storage buffers and
23  *        uniform/storage texel buffers.
24  *//*--------------------------------------------------------------------*/
25
26 #include "vktRobustnessBufferAccessTests.hpp"
27 #include "vktRobustnessUtil.hpp"
28 #include "vktTestCaseUtil.hpp"
29 #include "vkBuilderUtil.hpp"
30 #include "vkImageUtil.hpp"
31 #include "vkPrograms.hpp"
32 #include "vkQueryUtil.hpp"
33 #include "vkRef.hpp"
34 #include "vkRefUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "tcuTestLog.hpp"
37
38 #include <limits>
39 #include <sstream>
40
41 namespace vkt
42 {
43 namespace robustness
44 {
45
46 using namespace vk;
47
48 enum ShaderType
49 {
50         SHADER_TYPE_MATRIX_COPY,
51         SHADER_TYPE_VECTOR_COPY,
52         SHADER_TYPE_SCALAR_COPY,
53         SHADER_TYPE_TEXEL_COPY,
54
55         SHADER_TYPE_COUNT
56 };
57
58 enum BufferAccessType
59 {
60         BUFFER_ACCESS_TYPE_READ,
61         BUFFER_ACCESS_TYPE_READ_FROM_STORAGE,
62         BUFFER_ACCESS_TYPE_WRITE,
63 };
64
65 static VkDeviceSize min (VkDeviceSize a, VkDeviceSize b)
66 {
67         return (a < b) ? a : b;
68 }
69
70 class RobustBufferAccessTest : public vkt::TestCase
71 {
72 public:
73         static const deUint32           s_testArraySize;
74         static const deUint32           s_numberOfBytesAccessed;
75
76                                                                 RobustBufferAccessTest          (tcu::TestContext&              testContext,
77                                                                                                                          const std::string&             name,
78                                                                                                                          const std::string&             description,
79                                                                                                                          VkShaderStageFlags             shaderStage,
80                                                                                                                          ShaderType                             shaderType,
81                                                                                                                          VkFormat                               bufferFormat);
82
83         virtual                                         ~RobustBufferAccessTest         (void) {}
84
85 private:
86         static void                                     genBufferShaderAccess           (ShaderType                             shaderType,
87                                                                                                                          VkFormat                               bufferFormat,
88                                                                                                                          bool                                   readFromStorage,
89                                                                                                                          std::ostringstream&    bufferDefinition,
90                                                                                                                          std::ostringstream&    bufferUse);
91
92         static void                                     genTexelBufferShaderAccess      (VkFormat                               bufferFormat,
93                                                                                                                          std::ostringstream&    bufferDefinition,
94                                                                                                                          std::ostringstream&    bufferUse,
95                                                                                                                          bool                                   readFromStorage);
96
97 protected:
98         static void                                     initBufferAccessPrograms        (SourceCollections&             programCollection,
99                                                                                                                          VkShaderStageFlags             shaderStage,
100                                                                                                                          ShaderType                             shaderType,
101                                                                                                                          VkFormat                               bufferFormat,
102                                                                                                                          bool                                   readFromStorage);
103
104         const VkShaderStageFlags        m_shaderStage;
105         const ShaderType                        m_shaderType;
106         const VkFormat                          m_bufferFormat;
107 };
108
109 class RobustBufferReadTest : public RobustBufferAccessTest
110 {
111 public:
112                                                                 RobustBufferReadTest            (tcu::TestContext&              testContext,
113                                                                                                                          const std::string&             name,
114                                                                                                                          const std::string&             description,
115                                                                                                                          VkShaderStageFlags             shaderStage,
116                                                                                                                          ShaderType                             shaderType,
117                                                                                                                          VkFormat                               bufferFormat,
118                                                                                                                          VkDeviceSize                   readAccessRange,
119                                                                                                                          bool                                   readFromStorage,
120                                                                                                                          bool                                   accessOutOfBackingMemory);
121
122         virtual                                         ~RobustBufferReadTest           (void) {}
123
124         virtual void                            initPrograms                            (SourceCollections& programCollection) const;
125         virtual TestInstance*           createInstance                          (Context& context) const;
126
127 private:
128         const bool                                      m_readFromStorage;
129         const VkDeviceSize                      m_readAccessRange;
130         const bool                                      m_accessOutOfBackingMemory;
131 };
132
133 class RobustBufferWriteTest : public RobustBufferAccessTest
134 {
135 public:
136                                                                 RobustBufferWriteTest           (tcu::TestContext&              testContext,
137                                                                                                                          const std::string&             name,
138                                                                                                                          const std::string&             description,
139                                                                                                                          VkShaderStageFlags             shaderStage,
140                                                                                                                          ShaderType                             shaderType,
141                                                                                                                          VkFormat                               bufferFormat,
142                                                                                                                          VkDeviceSize                   writeAccessRange,
143                                                                                                                          bool                                   accessOutOfBackingMemory);
144
145         virtual                                         ~RobustBufferWriteTest          (void) {}
146
147         virtual void                            initPrograms                            (SourceCollections& programCollection) const;
148         virtual TestInstance*           createInstance                          (Context& context) const;
149
150 private:
151         const VkDeviceSize                      m_writeAccessRange;
152         const bool                                      m_accessOutOfBackingMemory;
153 };
154
155 class BufferAccessInstance : public vkt::TestInstance
156 {
157 public:
158                                                                         BufferAccessInstance                    (Context&                       context,
159                                                                                                                                          Move<VkDevice>         device,
160                                                                                                                                          ShaderType                     shaderType,
161                                                                                                                                          VkShaderStageFlags     shaderStage,
162                                                                                                                                          VkFormat                       bufferFormat,
163                                                                                                                                          BufferAccessType       bufferAccessType,
164                                                                                                                                          VkDeviceSize           inBufferAccessRange,
165                                                                                                                                          VkDeviceSize           outBufferAccessRange,
166                                                                                                                                          bool                           accessOutOfBackingMemory);
167
168         virtual                                                 ~BufferAccessInstance                   (void) {}
169
170         virtual tcu::TestStatus                 iterate                                                 (void);
171
172         virtual bool                                    verifyResult                                    (void);
173
174 private:
175         bool                                                    isExpectedValueFromInBuffer             (VkDeviceSize offsetInBytes, const void* valuePtr, VkDeviceSize valueSize);
176         bool                                                    isOutBufferValueUnchanged               (VkDeviceSize offsetInBytes, VkDeviceSize valueSize);
177
178 protected:
179         Move<VkDevice>                                  m_device;
180         de::MovePtr<TestEnvironment>    m_testEnvironment;
181
182         const ShaderType                                m_shaderType;
183         const VkShaderStageFlags                m_shaderStage;
184
185         const VkFormat                                  m_bufferFormat;
186         const BufferAccessType                  m_bufferAccessType;
187
188         const VkDeviceSize                              m_inBufferAccessRange;
189         Move<VkBuffer>                                  m_inBuffer;
190         de::MovePtr<Allocation>                 m_inBufferAlloc;
191         VkDeviceSize                                    m_inBufferAllocSize;
192         VkDeviceSize                                    m_inBufferMaxAccessRange;
193
194         const VkDeviceSize                              m_outBufferAccessRange;
195         Move<VkBuffer>                                  m_outBuffer;
196         de::MovePtr<Allocation>                 m_outBufferAlloc;
197         VkDeviceSize                                    m_outBufferAllocSize;
198         VkDeviceSize                                    m_outBufferMaxAccessRange;
199
200         Move<VkBuffer>                                  m_indicesBuffer;
201         de::MovePtr<Allocation>                 m_indicesBufferAlloc;
202
203         Move<VkDescriptorPool>                  m_descriptorPool;
204         Move<VkDescriptorSetLayout>             m_descriptorSetLayout;
205         Move<VkDescriptorSet>                   m_descriptorSet;
206
207         Move<VkFence>                                   m_fence;
208         VkQueue                                                 m_queue;
209
210         // Used when m_shaderStage == VK_SHADER_STAGE_VERTEX_BIT
211         Move<VkBuffer>                                  m_vertexBuffer;
212         de::MovePtr<Allocation>                 m_vertexBufferAlloc;
213
214         // Used when m_shaderType == SHADER_TYPE_TEXEL_COPY
215         Move<VkBufferView>                              m_inTexelBufferView;
216         Move<VkBufferView>                              m_outTexelBufferView;
217
218         const bool                                              m_accessOutOfBackingMemory;
219 };
220
221 class BufferReadInstance: public BufferAccessInstance
222 {
223 public:
224                                                                         BufferReadInstance                      (Context&                               context,
225                                                                                                                                  Move<VkDevice>                 device,
226                                                                                                                                  ShaderType                             shaderType,
227                                                                                                                                  VkShaderStageFlags             shaderStage,
228                                                                                                                                  VkFormat                               bufferFormat,
229                                                                                                                                  bool                                   readFromStorage,
230                                                                                                                                  VkDeviceSize                   inBufferAccessRange,
231                                                                                                                                  bool                                   accessOutOfBackingMemory);
232
233         virtual                                                 ~BufferReadInstance                     (void) {}
234
235 private:
236 };
237
238 class BufferWriteInstance: public BufferAccessInstance
239 {
240 public:
241                                                                         BufferWriteInstance                     (Context&                               context,
242                                                                                                                                  Move<VkDevice>                 device,
243                                                                                                                                  ShaderType                             shaderType,
244                                                                                                                                  VkShaderStageFlags             shaderStage,
245                                                                                                                                  VkFormat                               bufferFormat,
246                                                                                                                                  VkDeviceSize                   writeBufferAccessRange,
247                                                                                                                                  bool                                   accessOutOfBackingMemory);
248
249         virtual                                                 ~BufferWriteInstance            (void) {}
250 };
251
252 // RobustBufferAccessTest
253
254 const deUint32 RobustBufferAccessTest::s_testArraySize = 1024;
255 const deUint32 RobustBufferAccessTest::s_numberOfBytesAccessed  = (deUint32)(16 * sizeof(float)); // size of mat4
256
257 RobustBufferAccessTest::RobustBufferAccessTest (tcu::TestContext&               testContext,
258                                                                                                 const std::string&              name,
259                                                                                                 const std::string&              description,
260                                                                                                 VkShaderStageFlags              shaderStage,
261                                                                                                 ShaderType                              shaderType,
262                                                                                                 VkFormat                                bufferFormat)
263         : vkt::TestCase         (testContext, name, description)
264         , m_shaderStage         (shaderStage)
265         , m_shaderType          (shaderType)
266         , m_bufferFormat        (bufferFormat)
267 {
268         DE_ASSERT(m_shaderStage == VK_SHADER_STAGE_VERTEX_BIT || m_shaderStage == VK_SHADER_STAGE_FRAGMENT_BIT || m_shaderStage == VK_SHADER_STAGE_COMPUTE_BIT);
269 }
270
271 void RobustBufferAccessTest::genBufferShaderAccess (ShaderType                  shaderType,
272                                                                                                     VkFormat                    bufferFormat,
273                                                                                                     bool                                readFromStorage,
274                                                                                                     std::ostringstream& bufferDefinition,
275                                                                                                     std::ostringstream& bufferUse)
276 {
277         if (isFloatFormat(bufferFormat))
278         {
279                 bufferDefinition <<
280                         "layout(binding = 0, " << (readFromStorage ? "std430" : "std140") << ") " << (readFromStorage ? "buffer" : "uniform") << " InBuffer\n"
281                         "{\n"
282                         "       mat4 inMatrix[" << s_testArraySize << "];\n"
283                         "};\n\n";
284
285                 bufferDefinition <<
286                         "layout(binding = 1, std430) buffer OutBuffer\n"
287                         "{\n"
288                         "       mat4 outMatrix[" << s_testArraySize << "];\n"
289                         "};\n\n";
290
291                 bufferDefinition <<
292                         "layout(binding = 2, std140) uniform Indices\n"
293                         "{\n"
294                         "       int inIndex;\n"
295                         "       int outIndex;\n"
296                         "};\n\n";
297
298                 switch (shaderType)
299                 {
300                         case SHADER_TYPE_MATRIX_COPY:
301                                 bufferUse <<
302                                         "       mat4 tmp = inMatrix[inIndex];\n"
303                                         "       outMatrix[outIndex] = tmp;\n";
304                                 break;
305
306                         case SHADER_TYPE_VECTOR_COPY:
307                                 bufferUse <<
308                                         "       outMatrix[outIndex][0] = inMatrix[inIndex][0];\n"
309                                         "       outMatrix[outIndex][1] = inMatrix[inIndex][1];\n"
310                                         "       outMatrix[outIndex][2] = inMatrix[inIndex][2];\n"
311                                         "       outMatrix[outIndex][3] = inMatrix[inIndex][3];\n";
312                                 break;
313
314                         case SHADER_TYPE_SCALAR_COPY:
315                                 bufferUse <<
316                                         "       outMatrix[outIndex][0][0] = inMatrix[inIndex][0][0];\n"
317                                         "       outMatrix[outIndex][0][1] = inMatrix[inIndex][0][1];\n"
318                                         "       outMatrix[outIndex][0][2] = inMatrix[inIndex][0][2];\n"
319                                         "       outMatrix[outIndex][0][3] = inMatrix[inIndex][0][3];\n"
320
321                                         "       outMatrix[outIndex][1][0] = inMatrix[inIndex][1][0];\n"
322                                         "       outMatrix[outIndex][1][1] = inMatrix[inIndex][1][1];\n"
323                                         "       outMatrix[outIndex][1][2] = inMatrix[inIndex][1][2];\n"
324                                         "       outMatrix[outIndex][1][3] = inMatrix[inIndex][1][3];\n"
325
326                                         "       outMatrix[outIndex][2][0] = inMatrix[inIndex][2][0];\n"
327                                         "       outMatrix[outIndex][2][1] = inMatrix[inIndex][2][1];\n"
328                                         "       outMatrix[outIndex][2][2] = inMatrix[inIndex][2][2];\n"
329                                         "       outMatrix[outIndex][2][3] = inMatrix[inIndex][2][3];\n"
330
331                                         "       outMatrix[outIndex][3][0] = inMatrix[inIndex][3][0];\n"
332                                         "       outMatrix[outIndex][3][1] = inMatrix[inIndex][3][1];\n"
333                                         "       outMatrix[outIndex][3][2] = inMatrix[inIndex][3][2];\n"
334                                         "       outMatrix[outIndex][3][3] = inMatrix[inIndex][3][3];\n";
335                                 break;
336
337                         default:
338                                 DE_ASSERT(false);
339                 }
340         }
341         else
342         {
343                 std::string typePrefixStr;
344
345                 if (isUintFormat(bufferFormat))
346                 {
347                         typePrefixStr = "u";
348                 }
349                 else if (isIntFormat(bufferFormat))
350                 {
351                         typePrefixStr = "i";
352                 }
353                 else
354                 {
355                         DE_ASSERT(false);
356                 }
357
358                 bufferDefinition <<
359                         "layout(binding = 0, " << (readFromStorage ? "std430" : "std140") << ") " << (readFromStorage ? "buffer readonly" : "uniform") << " InBuffer\n"
360                         "{\n"
361                         "       " << typePrefixStr << "vec4 inVecs[" << s_testArraySize << "][4];\n"
362                         "};\n\n";
363
364                 bufferDefinition <<
365                         "layout(binding = 1, std430) buffer OutBuffer\n"
366                         "{\n"
367                         "       " << typePrefixStr << "vec4 outVecs[" << s_testArraySize << "][4];\n"
368                         "};\n\n";
369
370                 bufferDefinition <<
371                         "layout(binding = 2, std140) uniform Indices\n"
372                         "{\n"
373                         "       int inIndex;\n"
374                         "       int outIndex;\n"
375                         "};\n\n";
376
377                 switch (shaderType)
378                 {
379                         case SHADER_TYPE_MATRIX_COPY:
380                                 // Shader type not supported for integer types.
381                                 DE_ASSERT(false);
382                                 break;
383
384                         case SHADER_TYPE_VECTOR_COPY:
385                                 bufferUse <<
386                                         "       outVecs[outIndex][0] = inVecs[inIndex][0];\n"
387                                         "       outVecs[outIndex][1] = inVecs[inIndex][1];\n"
388                                         "       outVecs[outIndex][2] = inVecs[inIndex][2];\n"
389                                         "       outVecs[outIndex][3] = inVecs[inIndex][3];\n";
390                                 break;
391
392                         case SHADER_TYPE_SCALAR_COPY:
393                                 bufferUse <<
394                                         "       outVecs[outIndex][0][0] = inVecs[inIndex][0][0];\n"
395                                         "       outVecs[outIndex][0][1] = inVecs[inIndex][0][1];\n"
396                                         "       outVecs[outIndex][0][2] = inVecs[inIndex][0][2];\n"
397                                         "       outVecs[outIndex][0][3] = inVecs[inIndex][0][3];\n"
398
399                                         "       outVecs[outIndex][1][0] = inVecs[inIndex][1][0];\n"
400                                         "       outVecs[outIndex][1][1] = inVecs[inIndex][1][1];\n"
401                                         "       outVecs[outIndex][1][2] = inVecs[inIndex][1][2];\n"
402                                         "       outVecs[outIndex][1][3] = inVecs[inIndex][1][3];\n"
403
404                                         "       outVecs[outIndex][2][0] = inVecs[inIndex][2][0];\n"
405                                         "       outVecs[outIndex][2][1] = inVecs[inIndex][2][1];\n"
406                                         "       outVecs[outIndex][2][2] = inVecs[inIndex][2][2];\n"
407                                         "       outVecs[outIndex][2][3] = inVecs[inIndex][2][3];\n"
408
409                                         "       outVecs[outIndex][3][0] = inVecs[inIndex][3][0];\n"
410                                         "       outVecs[outIndex][3][1] = inVecs[inIndex][3][1];\n"
411                                         "       outVecs[outIndex][3][2] = inVecs[inIndex][3][2];\n"
412                                         "       outVecs[outIndex][3][3] = inVecs[inIndex][3][3];\n";
413                                 break;
414
415                         default:
416                                 DE_ASSERT(false);
417                 }
418         }
419 }
420
421 void RobustBufferAccessTest::genTexelBufferShaderAccess (VkFormat                               bufferFormat,
422                                                                                                                  std::ostringstream&    bufferDefinition,
423                                                                                                                  std::ostringstream&    bufferUse,
424                                                                                                                  bool                                   readFromStorage)
425 {
426         const char*             layoutTypeStr;
427         const char*             inTexelBufferTypeStr;
428         const char*             outTexelBufferTypeStr;
429         const deUint32  texelSize                               = mapVkFormat(bufferFormat).getPixelSize();
430
431         if (isFloatFormat(bufferFormat))
432         {
433                 layoutTypeStr                   = "rgba32f";
434                 inTexelBufferTypeStr    = readFromStorage ? "imageBuffer" : "samplerBuffer";
435                 outTexelBufferTypeStr   = "imageBuffer";
436         }
437         else if (isUintFormat(bufferFormat))
438         {
439                 layoutTypeStr                   = "rgba32ui";
440                 inTexelBufferTypeStr    = readFromStorage ? "uimageBuffer" : "usamplerBuffer";
441                 outTexelBufferTypeStr   = "uimageBuffer";
442         }
443         else if (isIntFormat(bufferFormat))
444         {
445                 layoutTypeStr                   = "rgba32i";
446                 inTexelBufferTypeStr    = readFromStorage ? "iimageBuffer" : "isamplerBuffer";
447                 outTexelBufferTypeStr   = "iimageBuffer";
448         }
449         else if (bufferFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
450         {
451                 layoutTypeStr                   = "rgb10_a2";
452                 inTexelBufferTypeStr    = readFromStorage ? "imageBuffer" : "samplerBuffer"; outTexelBufferTypeStr      = "imageBuffer";
453         }
454         else
455         {
456                 TCU_THROW(NotSupportedError, (std::string("Unsupported format: ") + getFormatName(bufferFormat)).c_str());
457         }
458
459         bufferDefinition << "layout(set = 0, binding = 0" << ((readFromStorage) ? (std::string(", ") + layoutTypeStr) : "") << ") uniform highp "
460                                          << ((readFromStorage) ? "readonly " : "") << inTexelBufferTypeStr << " inImage;\n";
461
462         bufferDefinition << "layout(set = 0, binding = 1, " << layoutTypeStr << ") uniform highp writeonly " << outTexelBufferTypeStr << " outImage;\n";
463
464         bufferDefinition <<
465                 "layout(binding = 2, std140) uniform Offsets\n"
466                 "{\n"
467                 "       int inOffset;\n"
468                 "       int outOffset;\n"
469                 "};\n\n";
470
471         bufferUse << "  for (int i = 0; i < " << (s_numberOfBytesAccessed / texelSize) << "; i++)\n"
472                           << "  {\n"
473                           << "          imageStore(outImage, outOffset + i, " << (readFromStorage ? "imageLoad" : "texelFetch") << "(inImage, inOffset + i));\n"
474                           << "  }\n";
475 }
476
477 void RobustBufferAccessTest::initBufferAccessPrograms (SourceCollections&       programCollection,
478                                                                                                            VkShaderStageFlags   shaderStage,
479                                                                                                            ShaderType                   shaderType,
480                                                                                                            VkFormat                             bufferFormat,
481                                                                                                            bool                                 readFromStorage)
482 {
483         std::ostringstream      bufferDefinition;
484         std::ostringstream      bufferUse;
485
486         if (shaderType != SHADER_TYPE_TEXEL_COPY)
487         {
488                 genBufferShaderAccess(shaderType, bufferFormat, readFromStorage, bufferDefinition, bufferUse);
489         }
490
491         if (shaderStage == VK_SHADER_STAGE_COMPUTE_BIT)
492         {
493                 std::ostringstream computeShaderSource;
494
495                 if (shaderType == SHADER_TYPE_TEXEL_COPY)
496                         genTexelBufferShaderAccess(bufferFormat, bufferDefinition, bufferUse, readFromStorage);
497
498                 computeShaderSource <<
499                         "#version 440\n"
500                         "#extension GL_EXT_texture_buffer : require\n"
501                         "precision highp float;\n"
502                         "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
503                         << bufferDefinition.str() <<
504                         "void main (void)\n"
505                         "{\n"
506                         << bufferUse.str() <<
507                         "}\n";
508
509                 programCollection.glslSources.add("compute") << glu::ComputeSource(computeShaderSource.str());
510         }
511         else
512         {
513                 std::ostringstream vertexShaderSource;
514                 std::ostringstream fragmentShaderSource;
515
516                 if (shaderStage == VK_SHADER_STAGE_VERTEX_BIT)
517                 {
518                         if (shaderType == SHADER_TYPE_TEXEL_COPY)
519                                 genTexelBufferShaderAccess(bufferFormat, bufferDefinition, bufferUse, readFromStorage);
520
521                         vertexShaderSource <<
522                                 "#version 440\n"
523                                 "#extension GL_EXT_texture_buffer : require\n"
524                                 "precision highp float;\n"
525                                 "layout(location = 0) in vec4 position;\n\n"
526                                 << bufferDefinition.str() << "\n"
527                                 "out gl_PerVertex {\n"
528                                 "       vec4 gl_Position;\n"
529                                 "};\n\n"
530                                 "void main (void)\n"
531                                 "{\n"
532                                 << bufferUse.str() <<
533                                 "       gl_Position = position;\n"
534                                 "}\n";
535                 }
536                 else
537                 {
538                         vertexShaderSource <<
539                                 "#version 440\n"
540                                 "precision highp float;\n"
541                                 "layout(location = 0) in vec4 position;\n\n"
542                                 "out gl_PerVertex {\n"
543                                 "       vec4 gl_Position;\n"
544                                 "};\n\n"
545                                 "void main (void)\n"
546                                 "{\n"
547                                 "       gl_Position = position;\n"
548                                 "}\n";
549                 }
550
551                 programCollection.glslSources.add("vertex") << glu::VertexSource(vertexShaderSource.str());
552
553                 if (shaderStage == VK_SHADER_STAGE_FRAGMENT_BIT)
554                 {
555                         if (shaderType == SHADER_TYPE_TEXEL_COPY)
556                                 genTexelBufferShaderAccess(bufferFormat, bufferDefinition, bufferUse, readFromStorage);
557
558                         fragmentShaderSource <<
559                                 "#version 440\n"
560                                 "#extension GL_EXT_texture_buffer : require\n"
561                                 "precision highp float;\n"
562                                 "layout(location = 0) out vec4 fragColor;\n"
563                                 << bufferDefinition.str() <<
564                                 "void main (void)\n"
565                                 "{\n"
566                                 << bufferUse.str() <<
567                                 "       fragColor = vec4(1.0);\n"
568                                 "}\n";
569                 }
570                 else
571                 {
572                         fragmentShaderSource <<
573                                 "#version 440\n"
574                                 "precision highp float;\n"
575                                 "layout(location = 0) out vec4 fragColor;\n\n"
576                                 "void main (void)\n"
577                                 "{\n"
578                                 "       fragColor = vec4(1.0);\n"
579                                 "}\n";
580                 }
581
582                 programCollection.glslSources.add("fragment") << glu::FragmentSource(fragmentShaderSource.str());
583         }
584 }
585
586 // RobustBufferReadTest
587
588 RobustBufferReadTest::RobustBufferReadTest (tcu::TestContext&   testContext,
589                                                                                         const std::string&      name,
590                                                                                         const std::string&      description,
591                                                                                         VkShaderStageFlags      shaderStage,
592                                                                                         ShaderType                      shaderType,
593                                                                                         VkFormat                        bufferFormat,
594                                                                                         VkDeviceSize            readAccessRange,
595                                                                                         bool                            readFromStorage,
596                                                                                         bool                            accessOutOfBackingMemory)
597         : RobustBufferAccessTest                (testContext, name, description, shaderStage, shaderType, bufferFormat)
598         , m_readFromStorage                             (readFromStorage)
599         , m_readAccessRange                             (readAccessRange)
600         , m_accessOutOfBackingMemory    (accessOutOfBackingMemory)
601 {
602 }
603
604 void RobustBufferReadTest::initPrograms (SourceCollections& programCollection) const
605 {
606         initBufferAccessPrograms(programCollection, m_shaderStage, m_shaderType, m_bufferFormat, m_readFromStorage);
607 }
608
609 TestInstance* RobustBufferReadTest::createInstance (Context& context) const
610 {
611         Move<VkDevice>  device                  = createRobustBufferAccessDevice(context);
612
613         return new BufferReadInstance(context, device, m_shaderType, m_shaderStage, m_bufferFormat, m_readFromStorage, m_readAccessRange, m_accessOutOfBackingMemory);
614 }
615
616 // RobustBufferWriteTest
617
618 RobustBufferWriteTest::RobustBufferWriteTest (tcu::TestContext&         testContext,
619                                                                                           const std::string&    name,
620                                                                                           const std::string&    description,
621                                                                                           VkShaderStageFlags    shaderStage,
622                                                                                           ShaderType                    shaderType,
623                                                                                           VkFormat                              bufferFormat,
624                                                                                           VkDeviceSize                  writeAccessRange,
625                                                                                           bool                                  accessOutOfBackingMemory)
626
627         : RobustBufferAccessTest                (testContext, name, description, shaderStage, shaderType, bufferFormat)
628         , m_writeAccessRange                    (writeAccessRange)
629         , m_accessOutOfBackingMemory    (accessOutOfBackingMemory)
630 {
631 }
632
633 void RobustBufferWriteTest::initPrograms (SourceCollections& programCollection) const
634 {
635         initBufferAccessPrograms(programCollection, m_shaderStage, m_shaderType, m_bufferFormat, false /* readFromStorage */);
636 }
637
638 TestInstance* RobustBufferWriteTest::createInstance (Context& context) const
639 {
640         Move<VkDevice>  device                  = createRobustBufferAccessDevice(context);
641
642         return new BufferWriteInstance(context, device, m_shaderType, m_shaderStage, m_bufferFormat, m_writeAccessRange, m_accessOutOfBackingMemory);
643 }
644
645 // BufferAccessInstance
646
647 BufferAccessInstance::BufferAccessInstance (Context&                    context,
648                                                                                         Move<VkDevice>          device,
649                                                                                         ShaderType                      shaderType,
650                                                                                         VkShaderStageFlags      shaderStage,
651                                                                                         VkFormat                        bufferFormat,
652                                                                                         BufferAccessType        bufferAccessType,
653                                                                                         VkDeviceSize            inBufferAccessRange,
654                                                                                         VkDeviceSize            outBufferAccessRange,
655                                                                                         bool                            accessOutOfBackingMemory)
656         : vkt::TestInstance                             (context)
657         , m_device                                              (device)
658         , m_shaderType                                  (shaderType)
659         , m_shaderStage                                 (shaderStage)
660         , m_bufferFormat                                (bufferFormat)
661         , m_bufferAccessType                    (bufferAccessType)
662         , m_inBufferAccessRange                 (inBufferAccessRange)
663         , m_outBufferAccessRange                (outBufferAccessRange)
664         , m_accessOutOfBackingMemory    (accessOutOfBackingMemory)
665 {
666         const DeviceInterface&          vk                                              = context.getDeviceInterface();
667         const deUint32                          queueFamilyIndex                = context.getUniversalQueueFamilyIndex();
668         const bool                                      isTexelAccess                   = !!(m_shaderType == SHADER_TYPE_TEXEL_COPY);
669         const bool                                      readFromStorage                 = !!(m_bufferAccessType == BUFFER_ACCESS_TYPE_READ_FROM_STORAGE);
670         SimpleAllocator                         memAlloc                                (vk, *m_device, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
671         tcu::TestLog&                           log                                             = m_context.getTestContext().getLog();
672
673         DE_ASSERT(RobustBufferAccessTest::s_numberOfBytesAccessed % sizeof(deUint32) == 0);
674         DE_ASSERT(inBufferAccessRange <= RobustBufferAccessTest::s_numberOfBytesAccessed);
675         DE_ASSERT(outBufferAccessRange <= RobustBufferAccessTest::s_numberOfBytesAccessed);
676
677         // Check storage support
678         if (shaderStage == VK_SHADER_STAGE_VERTEX_BIT)
679         {
680                 if (!context.getDeviceFeatures().vertexPipelineStoresAndAtomics)
681                 {
682                         TCU_THROW(NotSupportedError, "Stores not supported in vertex stage");
683                 }
684         }
685         else if (shaderStage == VK_SHADER_STAGE_FRAGMENT_BIT)
686         {
687                 if (!context.getDeviceFeatures().fragmentStoresAndAtomics)
688                 {
689                         TCU_THROW(NotSupportedError, "Stores not supported in fragment stage");
690                 }
691         }
692
693         // Check format support
694         {
695                 VkFormatFeatureFlags            requiredFormatFeatures  = 0;
696                 const VkFormatProperties        formatProperties                = getPhysicalDeviceFormatProperties(context.getInstanceInterface(), context.getPhysicalDevice(), m_bufferFormat);
697
698                 if (isTexelAccess)
699                 {
700                         requiredFormatFeatures  = VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT;
701                 }
702
703                 if ((formatProperties.bufferFeatures & requiredFormatFeatures) != requiredFormatFeatures)
704                 {
705                         TCU_THROW(NotSupportedError, (std::string("Format cannot be used in uniform and storage") + (isTexelAccess ? " texel" : "") + " buffers: "
706                                                                                   + getFormatName(m_bufferFormat)).c_str());
707                 }
708         }
709
710         // Create buffer to read data from
711         {
712                 VkBufferUsageFlags              inBufferUsageFlags;
713                 VkMemoryRequirements    inBufferMemoryReqs;
714
715                 if (isTexelAccess)
716                 {
717                         inBufferUsageFlags = readFromStorage ? VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT : VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
718                 }
719                 else
720                 {
721                         inBufferUsageFlags = readFromStorage ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
722                 }
723
724                 const VkBufferCreateInfo        inBufferParams =
725                 {
726                         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,           // VkStructureType              sType;
727                         DE_NULL,                                                                        // const void*                  pNext;
728                         0u,                                                                                     // VkBufferCreateFlags  flags;
729                         m_inBufferAccessRange,                                          // VkDeviceSize                 size;
730                         inBufferUsageFlags,                                                     // VkBufferUsageFlags   usage;
731                         VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                sharingMode;
732                         VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                             queueFamilyIndexCount;
733                         DE_NULL                                                                         // const deUint32*              pQueueFamilyIndices;
734                 };
735
736                 m_inBuffer                              = createBuffer(vk, *m_device, &inBufferParams);
737
738                 inBufferMemoryReqs              = getBufferMemoryRequirements(vk, *m_device, *m_inBuffer);
739                 m_inBufferAllocSize             = inBufferMemoryReqs.size;
740                 m_inBufferAlloc                 = memAlloc.allocate(inBufferMemoryReqs, MemoryRequirement::HostVisible);
741
742                 // Size of the most restrictive bound
743                 m_inBufferMaxAccessRange = min(m_inBufferAllocSize, min(inBufferParams.size, m_inBufferAccessRange));
744
745                 VK_CHECK(vk.bindBufferMemory(*m_device, *m_inBuffer, m_inBufferAlloc->getMemory(), m_inBufferAlloc->getOffset()));
746                 populateBufferWithTestValues(m_inBufferAlloc->getHostPtr(), m_inBufferAllocSize, m_bufferFormat);
747                 flushMappedMemoryRange(vk, *m_device, m_inBufferAlloc->getMemory(), m_inBufferAlloc->getOffset(), VK_WHOLE_SIZE);
748
749                 log << tcu::TestLog::Message << "inBufferAllocSize = " << m_inBufferAllocSize << tcu::TestLog::EndMessage;
750                 log << tcu::TestLog::Message << "inBufferMaxAccessRange = " << m_inBufferMaxAccessRange << tcu::TestLog::EndMessage;
751         }
752
753         // Create buffer to write data into
754         {
755                 VkMemoryRequirements            outBufferMemoryReqs;
756                 const VkBufferUsageFlags        outBufferUsageFlags     = (m_shaderType == SHADER_TYPE_TEXEL_COPY) ? VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT
757                                                                                                                                                                                                    : VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
758
759                 const VkBufferCreateInfo        outBufferParams         =
760                 {
761                         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,           // VkStructureType              sType;
762                         DE_NULL,                                                                        // const void*                  pNext;
763                         0u,                                                                                     // VkBufferCreateFlags  flags;
764                         m_outBufferAccessRange,                                         // VkDeviceSize                 size;
765                         outBufferUsageFlags,                                            // VkBufferUsageFlags   usage;
766                         VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                sharingMode;
767                         VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                             queueFamilyIndexCount;
768                         DE_NULL                                                                         // const deUint32*              pQueueFamilyIndices;
769                 };
770
771                 m_outBuffer                                     = createBuffer(vk, *m_device, &outBufferParams);
772
773                 outBufferMemoryReqs                     = getBufferMemoryRequirements(vk, *m_device, *m_outBuffer);
774                 m_outBufferAllocSize            = outBufferMemoryReqs.size;
775                 m_outBufferAlloc                        = memAlloc.allocate(outBufferMemoryReqs, MemoryRequirement::HostVisible);
776
777                 // If we are requesting access out of the memory that backs the buffer, make sure the test is able to do so.
778                 if (m_accessOutOfBackingMemory)
779                 {
780                         if (m_outBufferAllocSize >= ((RobustBufferAccessTest::s_testArraySize + 1) * RobustBufferAccessTest::s_numberOfBytesAccessed))
781                         {
782                                 TCU_THROW(NotSupportedError, "Cannot access beyond the end of the memory that backs the buffer");
783                         }
784                 }
785
786                 // Size of the most restrictive bound
787                 m_outBufferMaxAccessRange = min(m_outBufferAllocSize, min(outBufferParams.size, m_outBufferAccessRange));
788
789                 VK_CHECK(vk.bindBufferMemory(*m_device, *m_outBuffer, m_outBufferAlloc->getMemory(), m_outBufferAlloc->getOffset()));
790                 deMemset(m_outBufferAlloc->getHostPtr(), 0xFF, (size_t)m_outBufferAllocSize);
791                 flushMappedMemoryRange(vk, *m_device, m_outBufferAlloc->getMemory(), m_outBufferAlloc->getOffset(), VK_WHOLE_SIZE);
792
793                 log << tcu::TestLog::Message << "outBufferAllocSize = " << m_outBufferAllocSize << tcu::TestLog::EndMessage;
794                 log << tcu::TestLog::Message << "outBufferMaxAccessRange = " << m_outBufferMaxAccessRange << tcu::TestLog::EndMessage;
795         }
796
797         // Create buffer for indices/offsets
798         {
799                 struct IndicesBuffer
800                 {
801                         int32_t inIndex;
802                         int32_t outIndex;
803                 };
804
805                 IndicesBuffer indices = { 0, 0 };
806
807                 const VkBufferCreateInfo        indicesBufferParams                     =
808                 {
809                         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,           // VkStructureType              sType;
810                         DE_NULL,                                                                        // const void*                  pNext;
811                         0u,                                                                                     // VkBufferCreateFlags  flags;
812                         sizeof(IndicesBuffer),                                          // VkDeviceSize                 size;
813                         VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,                     // VkBufferUsageFlags   usage;
814                         VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                sharingMode;
815                         VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                             queueFamilyIndexCount;
816                         DE_NULL,                                                                        // const deUint32*              pQueueFamilyIndices;
817                 };
818
819                 m_indicesBuffer                         = createBuffer(vk, *m_device, &indicesBufferParams);
820                 m_indicesBufferAlloc            = memAlloc.allocate(getBufferMemoryRequirements(vk, *m_device, *m_indicesBuffer), MemoryRequirement::HostVisible);
821
822                 VK_CHECK(vk.bindBufferMemory(*m_device, *m_indicesBuffer, m_indicesBufferAlloc->getMemory(), m_indicesBufferAlloc->getOffset()));
823
824                 if (m_accessOutOfBackingMemory)
825                 {
826                         if (m_bufferAccessType == BUFFER_ACCESS_TYPE_WRITE)
827                         {
828                                 indices.outIndex = RobustBufferAccessTest::s_testArraySize - 1;
829                         }
830                         else
831                         {
832                                 indices.inIndex = RobustBufferAccessTest::s_testArraySize - 1;
833                         }
834                 }
835
836                 deMemcpy(m_indicesBufferAlloc->getHostPtr(), &indices, sizeof(IndicesBuffer));
837
838                 flushMappedMemoryRange(vk, *m_device, m_indicesBufferAlloc->getMemory(), m_indicesBufferAlloc->getOffset(), VK_WHOLE_SIZE);
839
840                 log << tcu::TestLog::Message << "inIndex = " << indices.inIndex << tcu::TestLog::EndMessage;
841                 log << tcu::TestLog::Message << "outIndex = " << indices.outIndex << tcu::TestLog::EndMessage;
842         }
843
844         // Create descriptor data
845         {
846                 VkDescriptorType        inBufferDescriptorType;
847                 VkDescriptorType        outBufferDescriptorType;
848
849                 if (isTexelAccess)
850                 {
851                         inBufferDescriptorType  = readFromStorage ? VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER : VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
852                         outBufferDescriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
853                 }
854                 else
855                 {
856                         inBufferDescriptorType  = readFromStorage ? VK_DESCRIPTOR_TYPE_STORAGE_BUFFER : VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
857                         outBufferDescriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
858                 }
859
860                 DescriptorPoolBuilder descriptorPoolBuilder;
861                 descriptorPoolBuilder.addType(inBufferDescriptorType, 1u);
862                 descriptorPoolBuilder.addType(outBufferDescriptorType, 1u);
863                 descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u);
864                 m_descriptorPool = descriptorPoolBuilder.build(vk, *m_device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
865
866                 DescriptorSetLayoutBuilder setLayoutBuilder;
867                 setLayoutBuilder.addSingleBinding(inBufferDescriptorType, VK_SHADER_STAGE_ALL);
868                 setLayoutBuilder.addSingleBinding(outBufferDescriptorType, VK_SHADER_STAGE_ALL);
869                 setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_ALL);
870                 m_descriptorSetLayout = setLayoutBuilder.build(vk, *m_device);
871
872                 const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo =
873                 {
874                         VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,         // VkStructureType                              sType;
875                         DE_NULL,                                                                                        // const void*                                  pNext;
876                         *m_descriptorPool,                                                                      // VkDescriptorPool                             descriptorPool;
877                         1u,                                                                                                     // deUint32                                             setLayoutCount;
878                         &m_descriptorSetLayout.get()                                            // const VkDescriptorSetLayout* pSetLayouts;
879                 };
880
881                 m_descriptorSet = allocateDescriptorSet(vk, *m_device, &descriptorSetAllocateInfo);
882
883                 DescriptorSetUpdateBuilder setUpdateBuilder;
884
885                 if (isTexelAccess)
886                 {
887                         const VkBufferViewCreateInfo inBufferViewCreateInfo =
888                         {
889                                 VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,              // VkStructureType                      sType;
890                                 DE_NULL,                                                                                // const void*                          pNext;
891                                 0u,                                                                                             // VkBufferViewCreateFlags      flags;
892                                 *m_inBuffer,                                                                    // VkBuffer                                     buffer;
893                                 m_bufferFormat,                                                                 // VkFormat                                     format;
894                                 0ull,                                                                                   // VkDeviceSize                         offset;
895                                 m_inBufferAccessRange                                                   // VkDeviceSize                         range;
896                         };
897                         m_inTexelBufferView     = createBufferView(vk, *m_device, &inBufferViewCreateInfo, DE_NULL);
898
899                         const VkBufferViewCreateInfo outBufferViewCreateInfo =
900                         {
901                                 VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,              // VkStructureType                      sType;
902                                 DE_NULL,                                                                                // const void*                          pNext;
903                                 0u,                                                                                             // VkBufferViewCreateFlags      flags;
904                                 *m_outBuffer,                                                                   // VkBuffer                                     buffer;
905                                 m_bufferFormat,                                                                 // VkFormat                                     format;
906                                 0ull,                                                                                   // VkDeviceSize                         offset;
907                                 m_outBufferAccessRange,                                                 // VkDeviceSize                         range;
908                         };
909                         m_outTexelBufferView    = createBufferView(vk, *m_device, &outBufferViewCreateInfo, DE_NULL);
910
911                         setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0), inBufferDescriptorType, &m_inTexelBufferView.get());
912                         setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1), outBufferDescriptorType, &m_outTexelBufferView.get());
913                 }
914                 else
915                 {
916                         const VkDescriptorBufferInfo inBufferDescriptorInfo             = makeDescriptorBufferInfo(*m_inBuffer, 0ull, m_inBufferAccessRange);
917                         const VkDescriptorBufferInfo outBufferDescriptorInfo    = makeDescriptorBufferInfo(*m_outBuffer, 0ull, m_outBufferAccessRange);
918
919                         setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0), inBufferDescriptorType, &inBufferDescriptorInfo);
920                         setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1), outBufferDescriptorType, &outBufferDescriptorInfo);
921                 }
922
923                 const VkDescriptorBufferInfo indicesBufferDescriptorInfo        = makeDescriptorBufferInfo(*m_indicesBuffer, 0ull, 8ull);
924                 setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(2), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &indicesBufferDescriptorInfo);
925
926                 setUpdateBuilder.update(vk, *m_device);
927         }
928
929         // Create fence
930         {
931                 const VkFenceCreateInfo fenceParams =
932                 {
933                         VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,    // VkStructureType              sType;
934                         DE_NULL,                                                                // const void*                  pNext;
935                         0u                                                                              // VkFenceCreateFlags   flags;
936                 };
937
938                 m_fence = createFence(vk, *m_device, &fenceParams);
939         }
940
941         // Get queue
942         vk.getDeviceQueue(*m_device, queueFamilyIndex, 0, &m_queue);
943
944         if (m_shaderStage == VK_SHADER_STAGE_COMPUTE_BIT)
945         {
946                 m_testEnvironment = de::MovePtr<TestEnvironment>(new ComputeEnvironment(m_context, *m_device, *m_descriptorSetLayout, *m_descriptorSet));
947         }
948         else
949         {
950                 using tcu::Vec4;
951
952                 const VkVertexInputBindingDescription vertexInputBindingDescription =
953                 {
954                         0u,                                                             // deUint32                                     binding;
955                         sizeof(tcu::Vec4),                              // deUint32                                     strideInBytes;
956                         VK_VERTEX_INPUT_RATE_VERTEX             // VkVertexInputStepRate        inputRate;
957                 };
958
959                 const VkVertexInputAttributeDescription vertexInputAttributeDescription =
960                 {
961                         0u,                                                             // deUint32     location;
962                         0u,                                                             // deUint32     binding;
963                         VK_FORMAT_R32G32B32A32_SFLOAT,  // VkFormat     format;
964                         0u                                                              // deUint32     offset;
965                 };
966
967                 const Vec4 vertices[] =
968                 {
969                         Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
970                         Vec4(-1.0f, 1.0f, 0.0f, 1.0f),
971                         Vec4(1.0f, -1.0f, 0.0f, 1.0f),
972                 };
973
974                 // Create vertex buffer
975                 {
976                         const VkDeviceSize                      vertexBufferSize        = (VkDeviceSize)(4u * sizeof(tcu::Vec4));
977                         const VkBufferCreateInfo        vertexBufferParams      =
978                         {
979                                 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,           // VkStructureType              sType;
980                                 DE_NULL,                                                                        // const void*                  pNext;
981                                 0u,                                                                                     // VkBufferCreateFlags  flags;
982                                 vertexBufferSize,                                                       // VkDeviceSize                 size;
983                                 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,                      // VkBufferUsageFlags   usage;
984                                 VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                sharingMode;
985                                 VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                             queueFamilyIndexCount;
986                                 DE_NULL                                                                         // const deUint32*              pQueueFamilyIndices;
987                         };
988
989                         DE_ASSERT(vertexBufferSize > 0);
990
991                         m_vertexBuffer          = createBuffer(vk, *m_device, &vertexBufferParams);
992                         m_vertexBufferAlloc     = memAlloc.allocate(getBufferMemoryRequirements(vk, *m_device, *m_vertexBuffer), MemoryRequirement::HostVisible);
993
994                         VK_CHECK(vk.bindBufferMemory(*m_device, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
995
996                         // Load vertices into vertex buffer
997                         deMemcpy(m_vertexBufferAlloc->getHostPtr(), vertices, sizeof(tcu::Vec4) * DE_LENGTH_OF_ARRAY(vertices));
998                         flushMappedMemoryRange(vk, *m_device, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset(), VK_WHOLE_SIZE);
999                 }
1000
1001                 const GraphicsEnvironment::DrawConfig drawWithOneVertexBuffer =
1002                 {
1003                         std::vector<VkBuffer>(1, *m_vertexBuffer),      // std::vector<VkBuffer>        vertexBuffers;
1004                         DE_LENGTH_OF_ARRAY(vertices),                           // deUint32                                     vertexCount;
1005                         1,                                                                                      // deUint32                                     instanceCount;
1006                         DE_NULL,                                                                        // VkBuffer                                     indexBuffer;
1007                         0u,                                                                                     // deUint32                                     indexCount;
1008                 };
1009
1010                 m_testEnvironment = de::MovePtr<TestEnvironment>(new GraphicsEnvironment(m_context,
1011                                                                                                                                                                  *m_device,
1012                                                                                                                                                                  *m_descriptorSetLayout,
1013                                                                                                                                                                  *m_descriptorSet,
1014                                                                                                                                                                  GraphicsEnvironment::VertexBindings(1, vertexInputBindingDescription),
1015                                                                                                                                                                  GraphicsEnvironment::VertexAttributes(1, vertexInputAttributeDescription),
1016                                                                                                                                                                  drawWithOneVertexBuffer));
1017         }
1018 }
1019
1020 // Verifies if the buffer has the value initialized by BufferAccessInstance::populateReadBuffer at a given offset.
1021 bool BufferAccessInstance::isExpectedValueFromInBuffer (VkDeviceSize offsetInBytes, const void* valuePtr, VkDeviceSize valueSize)
1022 {
1023         DE_ASSERT(offsetInBytes % 4 == 0);
1024         DE_ASSERT(offsetInBytes < m_inBufferAllocSize);
1025
1026         const deUint32 valueIndex = deUint32(offsetInBytes / 4) + 2;
1027
1028         if (isUintFormat(m_bufferFormat))
1029         {
1030                 return !deMemCmp(valuePtr, &valueIndex, (size_t)valueSize);
1031         }
1032         else if (isIntFormat(m_bufferFormat))
1033         {
1034                 const deInt32 value = -deInt32(valueIndex);
1035                 return !deMemCmp(valuePtr, &value, (size_t)valueSize);
1036         }
1037         else if (isFloatFormat(m_bufferFormat))
1038         {
1039                 const float value = float(valueIndex);
1040                 return !deMemCmp(valuePtr, &value, (size_t)valueSize);
1041         }
1042         else if (m_bufferFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
1043         {
1044                 const deUint32  r               = ((valueIndex + 0) & ((2u << 10) - 1u));
1045                 const deUint32  g               = ((valueIndex + 1) & ((2u << 10) - 1u));
1046                 const deUint32  b               = ((valueIndex + 2) & ((2u << 10) - 1u));
1047                 const deUint32  a               = ((valueIndex + 0) & ((2u << 2) - 1u));
1048                 const deUint32  abgr    = (a << 30) | (b << 20) | (g << 10) | r;
1049
1050                 return !deMemCmp(valuePtr, &abgr, (size_t)valueSize);
1051         }
1052         else
1053         {
1054                 DE_ASSERT(false);
1055                 return false;
1056         }
1057 }
1058
1059 bool BufferAccessInstance::isOutBufferValueUnchanged (VkDeviceSize offsetInBytes, VkDeviceSize valueSize)
1060 {
1061         const deUint8 *const    outValuePtr             = (deUint8*)m_outBufferAlloc->getHostPtr() + offsetInBytes;
1062         const deUint32                  defaultValue    = 0xFFFFFFFFu;
1063
1064         return !deMemCmp(outValuePtr, &defaultValue, (size_t)valueSize);
1065 }
1066
1067 tcu::TestStatus BufferAccessInstance::iterate (void)
1068 {
1069         const DeviceInterface&          vk                      = m_context.getDeviceInterface();
1070         const vk::VkCommandBuffer       cmdBuffer       = m_testEnvironment->getCommandBuffer();
1071
1072         // Submit command buffer
1073         {
1074                 const VkSubmitInfo      submitInfo      =
1075                 {
1076                         VK_STRUCTURE_TYPE_SUBMIT_INFO,  // VkStructureType                              sType;
1077                         DE_NULL,                                                // const void*                                  pNext;
1078                         0u,                                                             // deUint32                                             waitSemaphoreCount;
1079                         DE_NULL,                                                // const VkSemaphore*                   pWaitSemaphores;
1080                         DE_NULL,                                                // const VkPIpelineStageFlags*  pWaitDstStageMask;
1081                         1u,                                                             // deUint32                                             commandBufferCount;
1082                         &cmdBuffer,                                             // const VkCommandBuffer*               pCommandBuffers;
1083                         0u,                                                             // deUint32                                             signalSemaphoreCount;
1084                         DE_NULL                                                 // const VkSemaphore*                   pSignalSemaphores;
1085                 };
1086
1087                 VK_CHECK(vk.resetFences(*m_device, 1, &m_fence.get()));
1088                 VK_CHECK(vk.queueSubmit(m_queue, 1, &submitInfo, *m_fence));
1089                 VK_CHECK(vk.waitForFences(*m_device, 1, &m_fence.get(), true, ~(0ull) /* infinity */));
1090         }
1091
1092         // Prepare result buffer for read
1093         {
1094                 const VkMappedMemoryRange       outBufferRange  =
1095                 {
1096                         VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,  //  VkStructureType     sType;
1097                         DE_NULL,                                                                //  const void*         pNext;
1098                         m_outBufferAlloc->getMemory(),                  //  VkDeviceMemory      mem;
1099                         0ull,                                                                   //  VkDeviceSize        offset;
1100                         m_outBufferAllocSize,                                   //  VkDeviceSize        size;
1101                 };
1102
1103                 VK_CHECK(vk.invalidateMappedMemoryRanges(*m_device, 1u, &outBufferRange));
1104         }
1105
1106         if (verifyResult())
1107                 return tcu::TestStatus::pass("All values OK");
1108         else
1109                 return tcu::TestStatus::fail("Invalid value(s) found");
1110 }
1111
1112 bool BufferAccessInstance::verifyResult (void)
1113 {
1114         std::ostringstream      logMsg;
1115         tcu::TestLog&           log                                     = m_context.getTestContext().getLog();
1116         const bool                      isReadAccess            = !!(m_bufferAccessType == BUFFER_ACCESS_TYPE_READ || m_bufferAccessType == BUFFER_ACCESS_TYPE_READ_FROM_STORAGE);
1117         const void*                     inDataPtr                       = m_inBufferAlloc->getHostPtr();
1118         const void*                     outDataPtr                      = m_outBufferAlloc->getHostPtr();
1119         bool                            allOk                           = true;
1120         deUint32                        valueNdx                        = 0;
1121         const VkDeviceSize      maxAccessRange          = isReadAccess ? m_inBufferMaxAccessRange : m_outBufferMaxAccessRange;
1122
1123         for (VkDeviceSize offsetInBytes = 0; offsetInBytes < m_outBufferAllocSize; offsetInBytes += 4)
1124         {
1125                 deUint8*                        outValuePtr             = (deUint8*)outDataPtr + offsetInBytes;
1126                 const size_t            outValueSize    = (size_t)min(4, (m_outBufferAllocSize - offsetInBytes));
1127
1128                 if (offsetInBytes >= RobustBufferAccessTest::s_numberOfBytesAccessed)
1129                 {
1130                         // The shader will only write 16 values into the result buffer. The rest of the values
1131                         // should remain unchanged or may be modified if we are writing out of bounds.
1132                         if (!isOutBufferValueUnchanged(offsetInBytes, outValueSize)
1133                                 && (isReadAccess || !isValueWithinBufferOrZero(inDataPtr, m_inBufferAllocSize, outValuePtr, 4)))
1134                         {
1135                                 logMsg << "\nValue " << valueNdx++ << " has been modified with an unknown value: " << *((deUint32 *)outValuePtr);
1136                                 allOk = false;
1137                         }
1138                 }
1139                 else
1140                 {
1141                         const deInt32   distanceToOutOfBounds   = (deInt32)maxAccessRange - (deInt32)offsetInBytes;
1142                         bool                    isOutOfBoundsAccess             = false;
1143
1144                         logMsg << "\n" << valueNdx++ << ": ";
1145
1146                         logValue(logMsg, outValuePtr, m_bufferFormat, outValueSize);
1147
1148                         if (m_accessOutOfBackingMemory)
1149                                 isOutOfBoundsAccess = true;
1150
1151                         // Check if the shader operation accessed an operand located less than 16 bytes away
1152                         // from the out of bounds address.
1153                         if (!isOutOfBoundsAccess && distanceToOutOfBounds < 16)
1154                         {
1155                                 deUint32 operandSize = 0;
1156
1157                                 switch (m_shaderType)
1158                                 {
1159                                         case SHADER_TYPE_SCALAR_COPY:
1160                                                 operandSize             = 4; // Size of scalar
1161                                                 break;
1162
1163                                         case SHADER_TYPE_VECTOR_COPY:
1164                                                 operandSize             = 4 * 4; // Size of vec4
1165                                                 break;
1166
1167                                         case SHADER_TYPE_MATRIX_COPY:
1168                                                 operandSize             = 4 * 16; // Size of mat4
1169                                                 break;
1170
1171                                         case SHADER_TYPE_TEXEL_COPY:
1172                                                 operandSize             = mapVkFormat(m_bufferFormat).getPixelSize();
1173                                                 break;
1174
1175                                         default:
1176                                                 DE_ASSERT(false);
1177                                 }
1178
1179                                 isOutOfBoundsAccess = (((offsetInBytes / operandSize) + 1) * operandSize > maxAccessRange);
1180                         }
1181
1182                         if (isOutOfBoundsAccess)
1183                         {
1184                                 logMsg << " (out of bounds " << (isReadAccess ? "read": "write") << ")";
1185
1186                                 const bool      isValuePartiallyOutOfBounds = ((distanceToOutOfBounds > 0) && ((deUint32)distanceToOutOfBounds < 4));
1187                                 bool            isValidValue                            = false;
1188
1189                                 if (isValuePartiallyOutOfBounds && !m_accessOutOfBackingMemory)
1190                                 {
1191                                         // The value is partially out of bounds
1192
1193                                         bool    isOutOfBoundsPartOk = true;
1194                                         bool    isWithinBoundsPartOk = true;
1195
1196                                         if (isReadAccess)
1197                                         {
1198                                                 isWithinBoundsPartOk    = isValueWithinBufferOrZero(inDataPtr, m_inBufferAllocSize, outValuePtr, distanceToOutOfBounds);
1199                                                 isOutOfBoundsPartOk             = isValueWithinBufferOrZero(inDataPtr, m_inBufferAllocSize, (deUint8*)outValuePtr + distanceToOutOfBounds , outValueSize - distanceToOutOfBounds);
1200                                         }
1201                                         else
1202                                         {
1203                                                 isWithinBoundsPartOk    = isValueWithinBufferOrZero(inDataPtr, m_inBufferAllocSize, outValuePtr, distanceToOutOfBounds)
1204                                                                                                   || isOutBufferValueUnchanged(offsetInBytes, distanceToOutOfBounds);
1205
1206                                                 isOutOfBoundsPartOk             = isValueWithinBufferOrZero(inDataPtr, m_inBufferAllocSize, (deUint8*)outValuePtr + distanceToOutOfBounds, outValueSize - distanceToOutOfBounds)
1207                                                                                                   || isOutBufferValueUnchanged(offsetInBytes + distanceToOutOfBounds, outValueSize - distanceToOutOfBounds);
1208                                         }
1209
1210                                         logMsg << ", first " << distanceToOutOfBounds << " byte(s) " << (isWithinBoundsPartOk ? "OK": "wrong");
1211                                         logMsg << ", last " << outValueSize - distanceToOutOfBounds << " byte(s) " << (isOutOfBoundsPartOk ? "OK": "wrong");
1212
1213                                         isValidValue    = isWithinBoundsPartOk && isOutOfBoundsPartOk;
1214                                 }
1215                                 else
1216                                 {
1217                                         if (isReadAccess)
1218                                         {
1219                                                 isValidValue    = isValueWithinBufferOrZero(inDataPtr, m_inBufferAllocSize, outValuePtr, outValueSize);
1220                                         }
1221                                         else
1222                                         {
1223                                                 isValidValue    = isOutBufferValueUnchanged(offsetInBytes, outValueSize);
1224
1225                                                 if (!isValidValue)
1226                                                 {
1227                                                         // Out of bounds writes may modify values withing the memory ranges bound to the buffer
1228                                                         isValidValue    = isValueWithinBufferOrZero(inDataPtr, m_inBufferAllocSize, outValuePtr, outValueSize);
1229
1230                                                         if (isValidValue)
1231                                                                 logMsg << ", OK, written within the memory range bound to the buffer";
1232                                                 }
1233                                         }
1234                                 }
1235
1236                                 if (!isValidValue)
1237                                 {
1238                                         // Check if we are satisfying the [0, 0, 0, x] pattern, where x may be either 0 or 1,
1239                                         // or the maximum representable positive integer value (if the format is integer-based).
1240
1241                                         const bool      canMatchVec4Pattern     = (isReadAccess
1242                                                                                                         && !isValuePartiallyOutOfBounds
1243                                                                                                         && (m_shaderType == SHADER_TYPE_VECTOR_COPY || m_shaderType == SHADER_TYPE_TEXEL_COPY)
1244                                                                                                         && ((offsetInBytes / 4 + 1) % 4 == 0 || m_bufferFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32));
1245                                         bool            matchesVec4Pattern      = false;
1246
1247                                         if (canMatchVec4Pattern)
1248                                         {
1249                                                 if (m_bufferFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
1250                                                         matchesVec4Pattern      = verifyOutOfBoundsVec4(outValuePtr, m_bufferFormat);
1251                                                 else
1252                                                         matchesVec4Pattern      = verifyOutOfBoundsVec4(reinterpret_cast<deUint32*>(outValuePtr) - 3, m_bufferFormat);
1253                                         }
1254
1255                                         if (!canMatchVec4Pattern || !matchesVec4Pattern)
1256                                         {
1257                                                 logMsg << ". Failed: ";
1258
1259                                                 if (isReadAccess)
1260                                                 {
1261                                                         logMsg << "expected value within the buffer range or 0";
1262
1263                                                         if (canMatchVec4Pattern)
1264                                                                 logMsg << ", or the [0, 0, 0, x] pattern";
1265                                                 }
1266                                                 else
1267                                                 {
1268                                                         logMsg << "written out of the range";
1269                                                 }
1270
1271                                                 allOk = false;
1272                                         }
1273                                 }
1274                         }
1275                         else // We are within bounds
1276                         {
1277                                 if (isReadAccess)
1278                                 {
1279                                         if (!isExpectedValueFromInBuffer(offsetInBytes, outValuePtr, 4))
1280                                         {
1281                                                 logMsg << ", Failed: unexpected value";
1282                                                 allOk = false;
1283                                         }
1284                                 }
1285                                 else
1286                                 {
1287                                         // Out of bounds writes may change values within the bounds.
1288                                         if (!isValueWithinBufferOrZero(inDataPtr, m_inBufferAccessRange, outValuePtr, 4))
1289                                         {
1290                                                 logMsg << ", Failed: unexpected value";
1291                                                 allOk = false;
1292                                         }
1293                                 }
1294                         }
1295                 }
1296         }
1297
1298         log << tcu::TestLog::Message << logMsg.str() << tcu::TestLog::EndMessage;
1299
1300         return allOk;
1301 }
1302
1303 // BufferReadInstance
1304
1305 BufferReadInstance::BufferReadInstance (Context&                        context,
1306                                                                                 Move<VkDevice>          device,
1307                                                                                 ShaderType                      shaderType,
1308                                                                                 VkShaderStageFlags      shaderStage,
1309                                                                                 VkFormat                        bufferFormat,
1310                                                                                 bool                            readFromStorage,
1311                                                                                 VkDeviceSize            inBufferAccessRange,
1312                                                                                 bool                            accessOutOfBackingMemory)
1313
1314         : BufferAccessInstance  (context, device, shaderType, shaderStage, bufferFormat,
1315                                                          readFromStorage ? BUFFER_ACCESS_TYPE_READ_FROM_STORAGE : BUFFER_ACCESS_TYPE_READ,
1316                                                          inBufferAccessRange,
1317                                                          RobustBufferAccessTest::s_numberOfBytesAccessed,       // outBufferAccessRange
1318                                                          accessOutOfBackingMemory)
1319 {
1320 }
1321
1322 // BufferWriteInstance
1323
1324 BufferWriteInstance::BufferWriteInstance (Context&                              context,
1325                                                                                   Move<VkDevice>                device,
1326                                                                                   ShaderType                    shaderType,
1327                                                                                   VkShaderStageFlags    shaderStage,
1328                                                                                   VkFormat                              bufferFormat,
1329                                                                                   VkDeviceSize                  writeBufferAccessRange,
1330                                                                                   bool                                  accessOutOfBackingMemory)
1331
1332         : BufferAccessInstance  (context, device, shaderType, shaderStage, bufferFormat,
1333                                                          BUFFER_ACCESS_TYPE_WRITE,
1334                                                          RobustBufferAccessTest::s_numberOfBytesAccessed,       // inBufferAccessRange
1335                                                          writeBufferAccessRange,
1336                                                          accessOutOfBackingMemory)
1337 {
1338 }
1339
1340 // Test node creation functions
1341
1342 static const char* getShaderStageName (VkShaderStageFlagBits shaderStage)
1343 {
1344         switch (shaderStage)
1345         {
1346                 case VK_SHADER_STAGE_VERTEX_BIT:                                        return "vertex";
1347                 case VK_SHADER_STAGE_FRAGMENT_BIT:                                      return "fragment";
1348                 case VK_SHADER_STAGE_COMPUTE_BIT:                                       return "compute";
1349                 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:          return "tess_control";
1350                 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:       return "tess_eval";
1351                 case VK_SHADER_STAGE_GEOMETRY_BIT:                                      return "geometry";
1352
1353                 default:
1354                         DE_ASSERT(false);
1355         }
1356
1357         return DE_NULL;
1358 }
1359
1360 static void addBufferAccessTests (tcu::TestContext& testCtx, tcu::TestCaseGroup* parentNode)
1361 {
1362         struct BufferRangeConfig
1363         {
1364                 const char*             name;
1365                 VkDeviceSize    range;
1366         };
1367
1368         const VkShaderStageFlagBits bufferAccessStages[] =
1369         {
1370                 VK_SHADER_STAGE_VERTEX_BIT,
1371                 VK_SHADER_STAGE_FRAGMENT_BIT,
1372                 VK_SHADER_STAGE_COMPUTE_BIT,
1373         };
1374
1375         const VkFormat bufferFormats[] =
1376         {
1377                 VK_FORMAT_R32_SINT,
1378                 VK_FORMAT_R32_UINT,
1379                 VK_FORMAT_R32_SFLOAT
1380         };
1381
1382         const VkFormat texelBufferFormats[] =
1383         {
1384                 VK_FORMAT_R32G32B32A32_SINT,
1385                 VK_FORMAT_R32G32B32A32_UINT,
1386                 VK_FORMAT_R32G32B32A32_SFLOAT,
1387
1388                 VK_FORMAT_A2B10G10R10_UNORM_PACK32
1389         };
1390
1391         const BufferRangeConfig bufferRangeConfigs[] =
1392         {
1393                 { "range_1_byte",               1ull },
1394                 { "range_3_bytes",              3ull },
1395                 { "range_4_bytes",              4ull },         // size of float
1396                 { "range_32_bytes",             32ull },        // size of half mat4
1397         };
1398
1399         const BufferRangeConfig texelBufferRangeConfigs[] =
1400         {
1401                 { "range_1_texel",              1u },
1402                 { "range_3_texels",             3u },
1403         };
1404
1405         const char* shaderTypeNames[SHADER_TYPE_COUNT] =
1406         {
1407                 "mat4_copy",
1408                 "vec4_copy",
1409                 "scalar_copy",
1410                 "texel_copy",
1411         };
1412
1413         for (int stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(bufferAccessStages); stageNdx++)
1414         {
1415                 const VkShaderStageFlagBits                     stage                   = bufferAccessStages[stageNdx];
1416                 de::MovePtr<tcu::TestCaseGroup>         stageTests              (new tcu::TestCaseGroup(testCtx, getShaderStageName(stage), ""));
1417
1418                 for (int shaderTypeNdx = 0; shaderTypeNdx < SHADER_TYPE_COUNT; shaderTypeNdx++)
1419                 {
1420                         const VkFormat*                                 formats;
1421                         size_t                                                  formatsLength;
1422                         const BufferRangeConfig*                ranges;
1423                         size_t                                                  rangesLength;
1424                         deUint32                                                rangeMultiplier;
1425                         de::MovePtr<tcu::TestCaseGroup> shaderTypeTests (new tcu::TestCaseGroup(testCtx, shaderTypeNames[shaderTypeNdx], ""));
1426
1427                         if ((ShaderType)shaderTypeNdx == SHADER_TYPE_TEXEL_COPY)
1428                         {
1429                                 formats                 = texelBufferFormats;
1430                                 formatsLength   = DE_LENGTH_OF_ARRAY(texelBufferFormats);
1431
1432                                 ranges                  = texelBufferRangeConfigs;
1433                                 rangesLength    = DE_LENGTH_OF_ARRAY(texelBufferRangeConfigs);
1434                         }
1435                         else
1436                         {
1437                                 formats                 = bufferFormats;
1438                                 formatsLength   = DE_LENGTH_OF_ARRAY(bufferFormats);
1439
1440                                 ranges                  = bufferRangeConfigs;
1441                                 rangesLength    = DE_LENGTH_OF_ARRAY(bufferRangeConfigs);
1442                         }
1443
1444                         for (size_t formatNdx = 0; formatNdx < formatsLength; formatNdx++)
1445                         {
1446                                 const VkFormat  bufferFormat    = formats[formatNdx];
1447
1448                                 rangeMultiplier = ((ShaderType)shaderTypeNdx == SHADER_TYPE_TEXEL_COPY) ? mapVkFormat(bufferFormat).getPixelSize() : 1;
1449
1450                                 if (!isFloatFormat(bufferFormat) && ((ShaderType)shaderTypeNdx) == SHADER_TYPE_MATRIX_COPY)
1451                                 {
1452                                         // Use SHADER_TYPE_MATRIX_COPY with floating-point formats only
1453                                         break;
1454                                 }
1455
1456                                 const std::string                               formatName              = getFormatName(bufferFormat);
1457                                 de::MovePtr<tcu::TestCaseGroup> formatTests             (new tcu::TestCaseGroup(testCtx, de::toLower(formatName.substr(10)).c_str(), ""));
1458
1459                                 de::MovePtr<tcu::TestCaseGroup> uboReadTests            (new tcu::TestCaseGroup(testCtx, "oob_uniform_read", ""));
1460                                 de::MovePtr<tcu::TestCaseGroup> ssboReadTests           (new tcu::TestCaseGroup(testCtx, "oob_storage_read", ""));
1461                                 de::MovePtr<tcu::TestCaseGroup> ssboWriteTests          (new tcu::TestCaseGroup(testCtx, "oob_storage_write", ""));
1462
1463                                 for (size_t rangeNdx = 0; rangeNdx < rangesLength; rangeNdx++)
1464                                 {
1465                                         const BufferRangeConfig&        rangeConfig                     = ranges[rangeNdx];
1466                                         const VkDeviceSize                      rangeInBytes            = rangeConfig.range * rangeMultiplier;
1467
1468                                         uboReadTests->addChild(new RobustBufferReadTest(testCtx, rangeConfig.name, "", stage, (ShaderType)shaderTypeNdx, bufferFormat, rangeInBytes, false, false));
1469                                         ssboReadTests->addChild(new RobustBufferReadTest(testCtx, rangeConfig.name, "", stage, (ShaderType)shaderTypeNdx, bufferFormat, rangeInBytes, true, false));
1470                                         ssboWriteTests->addChild(new RobustBufferWriteTest(testCtx, rangeConfig.name, "", stage, (ShaderType)shaderTypeNdx, bufferFormat, rangeInBytes, false));
1471
1472                                 }
1473
1474                                 formatTests->addChild(uboReadTests.release());
1475                                 formatTests->addChild(ssboReadTests.release());
1476                                 formatTests->addChild(ssboWriteTests.release());
1477
1478                                 shaderTypeTests->addChild(formatTests.release());
1479                         }
1480
1481                         // Read/write out of the memory that backs the buffer
1482                         {
1483                                 de::MovePtr<tcu::TestCaseGroup> outOfAllocTests         (new tcu::TestCaseGroup(testCtx, "out_of_alloc", ""));
1484
1485                                 const VkFormat format = (((ShaderType)shaderTypeNdx == SHADER_TYPE_TEXEL_COPY ) ? VK_FORMAT_R32G32B32A32_SFLOAT : VK_FORMAT_R32_SFLOAT);
1486
1487                                 outOfAllocTests->addChild(new RobustBufferReadTest(testCtx, "oob_uniform_read", "", stage, (ShaderType)shaderTypeNdx, format, 16, false, true));
1488                                 outOfAllocTests->addChild(new RobustBufferReadTest(testCtx, "oob_storage_read", "", stage, (ShaderType)shaderTypeNdx, format, 16, true, true));
1489                                 outOfAllocTests->addChild(new RobustBufferWriteTest(testCtx, "oob_storage_write", "", stage, (ShaderType)shaderTypeNdx, format, 16, true));
1490
1491                                 shaderTypeTests->addChild(outOfAllocTests.release());
1492                         }
1493
1494                         stageTests->addChild(shaderTypeTests.release());
1495                 }
1496                 parentNode->addChild(stageTests.release());
1497         }
1498 }
1499
1500 tcu::TestCaseGroup* createBufferAccessTests (tcu::TestContext& testCtx)
1501 {
1502         de::MovePtr<tcu::TestCaseGroup> bufferAccessTests       (new tcu::TestCaseGroup(testCtx, "buffer_access", ""));
1503
1504         addBufferAccessTests(testCtx, bufferAccessTests.get());
1505
1506         return bufferAccessTests.release();
1507 }
1508
1509 } // robustness
1510 } // vkt