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