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