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