d0ea30204f3c7ae2f69e7cd96183bb8e5d6f4484
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / robustness / vktRobustnessVertexAccessTests.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 Vertex Buffer Access Tests
23  *//*--------------------------------------------------------------------*/
24
25 #include "vktRobustnessVertexAccessTests.hpp"
26 #include "vktRobustnessUtil.hpp"
27 #include "vktTestCaseUtil.hpp"
28 #include "vkBuilderUtil.hpp"
29 #include "vkImageUtil.hpp"
30 #include "vkMemUtil.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 #include "deMath.h"
39 #include "deUniquePtr.hpp"
40 #include <vector>
41
42 namespace vkt
43 {
44 namespace robustness
45 {
46
47 using namespace vk;
48
49 typedef std::vector<VkVertexInputBindingDescription>    BindingList;
50 typedef std::vector<VkVertexInputAttributeDescription>  AttributeList;
51
52 class VertexAccessTest : public vkt::TestCase
53 {
54 public:
55                                                 VertexAccessTest        (tcu::TestContext&              testContext,
56                                                                                          const std::string&             name,
57                                                                                          const std::string&             description,
58                                                                                          VkFormat                               inputFormat,
59                                                                                          deUint32                               numVertexValues,
60                                                                                          deUint32                               numInstanceValues,
61                                                                                          deUint32                               numVertices,
62                                                                                          deUint32                               numInstances);
63
64         virtual                         ~VertexAccessTest       (void) {}
65
66         void                            initPrograms            (SourceCollections& programCollection) const;
67         void                            checkSupport            (Context& context) const;
68         TestInstance*           createInstance          (Context& context) const = 0;
69
70 protected:
71         const VkFormat          m_inputFormat;
72         const deUint32          m_numVertexValues;
73         const deUint32          m_numInstanceValues;
74         const deUint32          m_numVertices;
75         const deUint32          m_numInstances;
76
77 };
78
79 class DrawAccessTest : public VertexAccessTest
80 {
81 public:
82                                                 DrawAccessTest          (tcu::TestContext&              testContext,
83                                                                                          const std::string&             name,
84                                                                                          const std::string&             description,
85                                                                                          VkFormat                               inputFormat,
86                                                                                          deUint32                               numVertexValues,
87                                                                                          deUint32                               numInstanceValues,
88                                                                                          deUint32                               numVertices,
89                                                                                          deUint32                               numInstances);
90
91         virtual                         ~DrawAccessTest         (void) {}
92         TestInstance*           createInstance          (Context& context) const;
93
94 protected:
95 };
96
97 class DrawIndexedAccessTest : public VertexAccessTest
98 {
99 public:
100         enum IndexConfig
101         {
102                 INDEX_CONFIG_LAST_INDEX_OUT_OF_BOUNDS,
103                 INDEX_CONFIG_INDICES_OUT_OF_BOUNDS,
104                 INDEX_CONFIG_TRIANGLE_OUT_OF_BOUNDS,
105
106                 INDEX_CONFIG_COUNT
107         };
108
109         const static std::vector<deUint32> s_indexConfigs[INDEX_CONFIG_COUNT];
110
111                                                 DrawIndexedAccessTest           (tcu::TestContext&              testContext,
112                                                                                                          const std::string&             name,
113                                                                                                          const std::string&             description,
114                                                                                                          VkFormat                               inputFormat,
115                                                                                                          IndexConfig                    indexConfig);
116
117         virtual                         ~DrawIndexedAccessTest          (void) {}
118         TestInstance*           createInstance                          (Context& context) const;
119
120 protected:
121         const IndexConfig       m_indexConfig;
122 };
123
124 class VertexAccessInstance : public vkt::TestInstance
125 {
126 public:
127                                                                                 VertexAccessInstance                                    (Context&                                               context,
128                                                                                                                                                                  std::shared_ptr<CustomInstanceWrapper> instanceWrapper,
129                                                                                                                                                                  Move<VkDevice>                                 device,
130 #ifndef CTS_USES_VULKANSC
131                                                                                                                                                                 de::MovePtr<vk::DeviceDriver>   deviceDriver,
132 #else
133                                                                                                                                                                 de::MovePtr<vk::DeviceDriverSC, vk::DeinitDeviceDeleter>        deviceDriver,
134 #endif // CTS_USES_VULKANSC
135                                                                                                                                                                  VkFormat                                               inputFormat,
136                                                                                                                                                                  deUint32                                               numVertexValues,
137                                                                                                                                                                  deUint32                                               numInstanceValues,
138                                                                                                                                                                  deUint32                                               numVertices,
139                                                                                                                                                                  deUint32                                               numInstances,
140                                                                                                                                                                  const std::vector<deUint32>&   indices);
141
142         virtual                                                         ~VertexAccessInstance                                   (void);
143         virtual tcu::TestStatus                         iterate                                                                 (void);
144         virtual bool                                            verifyResult                                                    (void);
145
146 private:
147         bool                                                            isValueWithinVertexBufferOrZero                 (void* vertexBuffer, VkDeviceSize vertexBufferSize, const void* value, deUint32 valueIndexa);
148
149 protected:
150         static bool                                                     isExpectedValueFromVertexBuffer                 (const void* vertexBuffer, deUint32 vertexIndex, VkFormat vertexFormat, const void* value);
151         static VkDeviceSize                                     getBufferSizeInBytes                                    (deUint32 numScalars, VkFormat format);
152
153         virtual void                                            initVertexIds                                                   (deUint32 *indicesPtr, size_t indexCount) = 0;
154         virtual deUint32                                        getIndex                                                                (deUint32 vertexNum) const = 0;
155
156         std::shared_ptr<CustomInstanceWrapper>  m_instanceWrapper;
157         Move<VkDevice>                                          m_device;
158 #ifndef CTS_USES_VULKANSC
159         de::MovePtr<vk::DeviceDriver>           m_deviceDriver;
160 #else
161         de::MovePtr<vk::DeviceDriverSC, vk::DeinitDeviceDeleter>        m_deviceDriver;
162 #endif // CTS_USES_VULKANSC
163
164         const VkFormat                                          m_inputFormat;
165         const deUint32                                          m_numVertexValues;
166         const deUint32                                          m_numInstanceValues;
167         const deUint32                                          m_numVertices;
168         const deUint32                                          m_numInstances;
169         AttributeList                                           m_vertexInputAttributes;
170         BindingList                                                     m_vertexInputBindings;
171
172         Move<VkBuffer>                                          m_vertexRateBuffer;
173         VkDeviceSize                                            m_vertexRateBufferSize;
174         de::MovePtr<Allocation>                         m_vertexRateBufferAlloc;
175         VkDeviceSize                                            m_vertexRateBufferAllocSize;
176
177         Move<VkBuffer>                                          m_instanceRateBuffer;
178         VkDeviceSize                                            m_instanceRateBufferSize;
179         de::MovePtr<Allocation>                         m_instanceRateBufferAlloc;
180         VkDeviceSize                                            m_instanceRateBufferAllocSize;
181
182         Move<VkBuffer>                                          m_vertexNumBuffer;
183         VkDeviceSize                                            m_vertexNumBufferSize;
184         de::MovePtr<Allocation>                         m_vertexNumBufferAlloc;
185
186         Move<VkBuffer>                                          m_indexBuffer;
187         VkDeviceSize                                            m_indexBufferSize;
188         de::MovePtr<Allocation>                         m_indexBufferAlloc;
189
190         Move<VkBuffer>                                          m_outBuffer; // SSBO
191         VkDeviceSize                                            m_outBufferSize;
192         de::MovePtr<Allocation>                         m_outBufferAlloc;
193         VkDeviceSize                                            m_outBufferAllocSize;
194
195         Move<VkDescriptorPool>                          m_descriptorPool;
196         Move<VkDescriptorSetLayout>                     m_descriptorSetLayout;
197         Move<VkDescriptorSet>                           m_descriptorSet;
198
199         Move<VkFence>                                           m_fence;
200         VkQueue                                                         m_queue;
201
202         de::MovePtr<GraphicsEnvironment>        m_graphicsTestEnvironment;
203 };
204
205 class DrawAccessInstance : public VertexAccessInstance
206 {
207 public:
208                                                 DrawAccessInstance      (Context&                               context,
209                                                                                          std::shared_ptr<CustomInstanceWrapper> instanceWrapper,
210                                                                                          Move<VkDevice>                 device,
211 #ifndef CTS_USES_VULKANSC
212                                                                                         de::MovePtr<vk::DeviceDriver>   deviceDriver,
213 #else
214                                                                                         de::MovePtr<vk::DeviceDriverSC, vk::DeinitDeviceDeleter>        deviceDriver,
215 #endif // CTS_USES_VULKANSC
216                                                                                          VkFormat                               inputFormat,
217                                                                                          deUint32                               numVertexValues,
218                                                                                          deUint32                               numInstanceValues,
219                                                                                          deUint32                               numVertices,
220                                                                                          deUint32                               numInstances);
221
222         virtual                         ~DrawAccessInstance     (void) {}
223
224 protected:
225         virtual void            initVertexIds           (deUint32 *indicesPtr, size_t indexCount);
226         virtual deUint32        getIndex                        (deUint32 vertexNum) const;
227 };
228
229 class DrawIndexedAccessInstance : public VertexAccessInstance
230 {
231 public:
232                                                                                 DrawIndexedAccessInstance       (Context&                                               context,
233                                                                                                                                          std::shared_ptr<CustomInstanceWrapper> instanceWrapper,
234                                                                                                                                          Move<VkDevice>                                 device,
235 #ifndef CTS_USES_VULKANSC
236                                                                                                                                          de::MovePtr<vk::DeviceDriver>          deviceDriver,
237 #else
238                                                                                                                                          de::MovePtr<vk::DeviceDriverSC, vk::DeinitDeviceDeleter>       deviceDriver,
239 #endif // CTS_USES_VULKANSC
240                                                                                                                                          VkFormat                                               inputFormat,
241                                                                                                                                          deUint32                                               numVertexValues,
242                                                                                                                                          deUint32                                               numInstanceValues,
243                                                                                                                                          deUint32                                               numVertices,
244                                                                                                                                          deUint32                                               numInstances,
245                                                                                                                                          const std::vector<deUint32>&   indices);
246
247         virtual                                                         ~DrawIndexedAccessInstance      (void) {}
248
249 protected:
250         virtual void                                            initVertexIds                           (deUint32 *indicesPtr, size_t indexCount);
251         virtual deUint32                                        getIndex                                        (deUint32 vertexNum) const;
252
253         const std::vector<deUint32>                     m_indices;
254 };
255
256 // VertexAccessTest
257
258 VertexAccessTest::VertexAccessTest (tcu::TestContext&           testContext,
259                                                                         const std::string&              name,
260                                                                         const std::string&              description,
261                                                                         VkFormat                                inputFormat,
262                                                                         deUint32                                numVertexValues,
263                                                                         deUint32                                numInstanceValues,
264                                                                         deUint32                                numVertices,
265                                                                         deUint32                                numInstances)
266
267         : vkt::TestCase                         (testContext, name, description)
268         , m_inputFormat                         (inputFormat)
269         , m_numVertexValues                     (numVertexValues)
270         , m_numInstanceValues           (numInstanceValues)
271         , m_numVertices                         (numVertices)
272         , m_numInstances                        (numInstances)
273 {
274 }
275
276
277 void VertexAccessTest::checkSupport(Context& context) const
278 {
279         if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") && !context.getDeviceFeatures().robustBufferAccess)
280                 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: robustBufferAccess not supported by this implementation");
281 }
282
283 void VertexAccessTest::initPrograms (SourceCollections& programCollection) const
284 {
285         std::ostringstream              attributeDeclaration;
286         std::ostringstream              attributeUse;
287
288         std::ostringstream              vertexShaderSource;
289         std::ostringstream              fragmentShaderSource;
290
291         std::ostringstream              attributeTypeStr;
292         const int                               numChannels                             = getNumUsedChannels(mapVkFormat(m_inputFormat).order);
293         const deUint32                  numScalarsPerVertex             = numChannels * 3; // Use 3 identical attributes
294         deUint32                                numValues                               = 0;
295
296         const bool                              isR64                                   = (m_inputFormat == VK_FORMAT_R64_UINT || m_inputFormat == VK_FORMAT_R64_SINT);
297
298         if (numChannels == 1)
299         {
300                 if (isUintFormat(m_inputFormat))
301                         attributeTypeStr << "uint";
302                 else if (isIntFormat(m_inputFormat))
303                         attributeTypeStr << "int";
304                 else
305                         attributeTypeStr << "float";
306
307                 attributeTypeStr << (isR64 ? "64_t" : " ");
308         }
309         else
310         {
311                 if (isUintFormat(m_inputFormat))
312                         attributeTypeStr << "uvec";
313                 else if (isIntFormat(m_inputFormat))
314                         attributeTypeStr << "ivec";
315                 else
316                         attributeTypeStr << "vec";
317
318                 attributeTypeStr << numChannels;
319         }
320
321         for (int attrNdx = 0; attrNdx < 3; attrNdx++)
322         {
323                 attributeDeclaration << "layout(location = " << attrNdx << ") in " << attributeTypeStr.str() << " attr" << attrNdx << ";\n";
324
325                 for (int chanNdx = 0; chanNdx < numChannels; chanNdx++)
326                 {
327                         attributeUse << "\toutData[(gl_InstanceIndex * " << numScalarsPerVertex * m_numVertices
328                                                  << ") + (vertexNum * " << numScalarsPerVertex << " + " << numValues++ << ")] = attr" << attrNdx;
329
330                         if (numChannels == 1)
331                                 attributeUse << ";\n";
332                         else
333                                 attributeUse << "[" << chanNdx << "];\n";
334                 }
335         }
336
337         attributeDeclaration << "layout(location = 3) in int vertexNum;\n";
338
339         attributeUse << "\n";
340
341         std::string outType = "";
342         if (isUintFormat(m_inputFormat))
343                 outType = "uint";
344         else if (isIntFormat(m_inputFormat))
345                 outType = "int";
346         else
347                 outType = "float";
348
349         outType += isR64 ? "64_t" : "";
350
351         std::string extensions  = "";
352         std::string version             = "#version 310 es\n";
353         if (isR64)
354         {
355                 extensions      = "#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require\n";
356                 version         = "#version 440\n";
357         }
358
359         vertexShaderSource <<
360                 version <<
361                 "precision highp float;\n"
362                 << extensions
363                 << attributeDeclaration.str() <<
364                 "layout(set = 0, binding = 0, std430) buffer outBuffer\n"
365                 "{\n"
366                 "\t" << outType << " outData[" << (m_numVertices * numValues) * m_numInstances << "];\n"
367                 "};\n\n"
368                 "void main (void)\n"
369                 "{\n"
370                 << attributeUse.str() <<
371                 "\tgl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
372                 "}\n";
373
374         programCollection.glslSources.add("vertex") << glu::VertexSource(vertexShaderSource.str());
375
376         fragmentShaderSource <<
377                 "#version 310 es\n"
378                 "precision highp float;\n"
379                 "layout(location = 0) out vec4 fragColor;\n"
380                 "void main (void)\n"
381                 "{\n"
382                 "\tfragColor = vec4(1.0);\n"
383                 "}\n";
384
385         programCollection.glslSources.add("fragment") << glu::FragmentSource(fragmentShaderSource.str());
386 }
387
388 // DrawAccessTest
389
390 DrawAccessTest::DrawAccessTest (tcu::TestContext&               testContext,
391                                                                 const std::string&              name,
392                                                                 const std::string&              description,
393                                                                 VkFormat                                inputFormat,
394                                                                 deUint32                                numVertexValues,
395                                                                 deUint32                                numInstanceValues,
396                                                                 deUint32                                numVertices,
397                                                                 deUint32                                numInstances)
398
399         : VertexAccessTest              (testContext, name, description, inputFormat, numVertexValues, numInstanceValues, numVertices, numInstances)
400 {
401 }
402
403 TestInstance* DrawAccessTest::createInstance (Context& context) const
404 {
405         std::shared_ptr<CustomInstanceWrapper> instanceWrapper(new CustomInstanceWrapper(context));
406         Move<VkDevice>  device = createRobustBufferAccessDevice(context, instanceWrapper->instance, instanceWrapper->instance.getDriver());
407 #ifndef CTS_USES_VULKANSC
408         de::MovePtr<vk::DeviceDriver>   deviceDriver = de::MovePtr<DeviceDriver>(new DeviceDriver(context.getPlatformInterface(), instanceWrapper->instance, *device));
409 #else
410         de::MovePtr<vk::DeviceDriverSC, vk::DeinitDeviceDeleter>        deviceDriver = de::MovePtr<DeviceDriverSC, DeinitDeviceDeleter>(new DeviceDriverSC(context.getPlatformInterface(), instanceWrapper->instance, *device, context.getTestContext().getCommandLine(), context.getResourceInterface(), context.getDeviceVulkanSC10Properties(), context.getDeviceProperties()), vk::DeinitDeviceDeleter(context.getResourceInterface().get(), *device));
411 #endif // CTS_USES_VULKANSC
412
413         return new DrawAccessInstance(context,
414                                                                   instanceWrapper,
415                                                                   device,
416                                                                   deviceDriver,
417                                                                   m_inputFormat,
418                                                                   m_numVertexValues,
419                                                                   m_numInstanceValues,
420                                                                   m_numVertices,
421                                                                   m_numInstances);
422 }
423
424 // DrawIndexedAccessTest
425
426 const deUint32 lastIndexOutOfBounds[] =
427 {
428         0, 1, 2, 3, 4, 100,             // Indices of 100 and above are out of bounds
429 };
430 const deUint32 indicesOutOfBounds[] =
431 {
432         0, 100, 2, 101, 3, 102, // Indices of 100 and above are out of bounds
433 };
434 const deUint32 triangleOutOfBounds[] =
435 {
436         100, 101, 102, 3, 4, 5, // Indices of 100 and above are out of bounds
437 };
438
439 const std::vector<deUint32> DrawIndexedAccessTest::s_indexConfigs[INDEX_CONFIG_COUNT] =
440 {
441         std::vector<deUint32>(lastIndexOutOfBounds, lastIndexOutOfBounds + DE_LENGTH_OF_ARRAY(lastIndexOutOfBounds)),
442         std::vector<deUint32>(indicesOutOfBounds, indicesOutOfBounds + DE_LENGTH_OF_ARRAY(indicesOutOfBounds)),
443         std::vector<deUint32>(triangleOutOfBounds, triangleOutOfBounds + DE_LENGTH_OF_ARRAY(triangleOutOfBounds)),
444 };
445
446 DrawIndexedAccessTest::DrawIndexedAccessTest (tcu::TestContext&         testContext,
447                                                                                           const std::string&    name,
448                                                                                           const std::string&    description,
449                                                                                           VkFormat                              inputFormat,
450                                                                                           IndexConfig                   indexConfig)
451
452         : VertexAccessTest      (testContext,
453                                                  name,
454                                                  description,
455                                                  inputFormat,
456                                                  getNumUsedChannels(mapVkFormat(inputFormat).order) * (deUint32)s_indexConfigs[indexConfig].size() * 2, // numVertexValues
457                                                  getNumUsedChannels(mapVkFormat(inputFormat).order),                                                                                                    // numInstanceValues
458                                                  (deUint32)s_indexConfigs[indexConfig].size(),                                                                                                                  // numVertices
459                                                  1)                                                                                                                                                                                                             // numInstances
460         , m_indexConfig         (indexConfig)
461 {
462 }
463
464 TestInstance* DrawIndexedAccessTest::createInstance (Context& context) const
465 {
466         std::shared_ptr<CustomInstanceWrapper> instanceWrapper(new CustomInstanceWrapper(context));
467         Move<VkDevice>  device = createRobustBufferAccessDevice(context, instanceWrapper->instance, instanceWrapper->instance.getDriver());
468 #ifndef CTS_USES_VULKANSC
469         de::MovePtr<vk::DeviceDriver>   deviceDriver = de::MovePtr<DeviceDriver>(new DeviceDriver(context.getPlatformInterface(), instanceWrapper->instance, *device));
470 #else
471         de::MovePtr<vk::DeviceDriverSC, vk::DeinitDeviceDeleter>        deviceDriver = de::MovePtr<DeviceDriverSC, DeinitDeviceDeleter>(new DeviceDriverSC(context.getPlatformInterface(), instanceWrapper->instance, *device, context.getTestContext().getCommandLine(), context.getResourceInterface(), context.getDeviceVulkanSC10Properties(), context.getDeviceProperties()), vk::DeinitDeviceDeleter(context.getResourceInterface().get(), *device));
472 #endif // CTS_USES_VULKANSC
473
474         return new DrawIndexedAccessInstance(context,
475                                                                                  instanceWrapper,
476                                                                                  device,
477                                                                                  deviceDriver,
478                                                                                  m_inputFormat,
479                                                                                  m_numVertexValues,
480                                                                                  m_numInstanceValues,
481                                                                                  m_numVertices,
482                                                                                  m_numInstances,
483                                                                                  s_indexConfigs[m_indexConfig]);
484 }
485
486 // VertexAccessInstance
487
488 VertexAccessInstance::VertexAccessInstance (Context&                                            context,
489                                                                                         std::shared_ptr<CustomInstanceWrapper>  instanceWrapper,
490                                                                                         Move<VkDevice>                                  device,
491 #ifndef CTS_USES_VULKANSC
492                                                                                         de::MovePtr<vk::DeviceDriver>   deviceDriver,
493 #else
494                                                                                         de::MovePtr<vk::DeviceDriverSC, vk::DeinitDeviceDeleter>        deviceDriver,
495 #endif // CTS_USES_VULKANSC
496                                                                                         VkFormat                                                inputFormat,
497                                                                                         deUint32                                                numVertexValues,
498                                                                                         deUint32                                                numInstanceValues,
499                                                                                         deUint32                                                numVertices,
500                                                                                         deUint32                                                numInstances,
501                                                                                         const std::vector<deUint32>&    indices)
502
503         : vkt::TestInstance                     (context)
504         , m_instanceWrapper                     (instanceWrapper)
505         , m_device                                      (device)
506         , m_deviceDriver                        (deviceDriver)
507         , m_inputFormat                         (inputFormat)
508         , m_numVertexValues                     (numVertexValues)
509         , m_numInstanceValues           (numInstanceValues)
510         , m_numVertices                         (numVertices)
511         , m_numInstances                        (numInstances)
512 {
513         const DeviceInterface&          vk                                              = *m_deviceDriver;
514         const deUint32                          queueFamilyIndex                = context.getUniversalQueueFamilyIndex();
515         const VkPhysicalDevice          physicalDevice                  = chooseDevice(instanceWrapper->instance.getDriver(), instanceWrapper->instance, context.getTestContext().getCommandLine());
516         SimpleAllocator                         memAlloc                                (vk, *m_device, getPhysicalDeviceMemoryProperties(instanceWrapper->instance.getDriver(), physicalDevice));
517         const deUint32                          formatSizeInBytes               = tcu::getPixelSize(mapVkFormat(m_inputFormat));
518
519         // Check storage support
520         if (!context.getDeviceFeatures().vertexPipelineStoresAndAtomics)
521         {
522                 TCU_THROW(NotSupportedError, "Stores not supported in vertex stage");
523         }
524
525         if (m_inputFormat == VK_FORMAT_R64_UINT || m_inputFormat == VK_FORMAT_R64_SINT)
526         {
527                 const VkFormatProperties        formatProperties        = getPhysicalDeviceFormatProperties(instanceWrapper->instance.getDriver(), physicalDevice, m_inputFormat);
528                 context.requireDeviceFunctionality("VK_EXT_shader_image_atomic_int64");
529
530                 if ((formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) != VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)
531                         TCU_THROW(NotSupportedError, "VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT not supported");
532         }
533
534
535         const VkVertexInputAttributeDescription attributes[] =
536         {
537                 // input rate: vertex
538                 {
539                         0u,                                                             // deUint32 location;
540                         0u,                                                             // deUint32 binding;
541                         m_inputFormat,                                  // VkFormat format;
542                         0u,                                                             // deUint32 offset;
543                 },
544                 {
545                         1u,                                                             // deUint32 location;
546                         0u,                                                             // deUint32 binding;
547                         m_inputFormat,                                  // VkFormat format;
548                         formatSizeInBytes,                              // deUint32 offset;
549                 },
550
551                 // input rate: instance
552                 {
553                         2u,                                                             // deUint32 location;
554                         1u,                                                             // deUint32 binding;
555                         m_inputFormat,                                  // VkFormat format;
556                         0u,                                                             // deUint32 offset;
557                 },
558
559                 // Attribute for vertex number
560                 {
561                         3u,                                                             // deUint32 location;
562                         2u,                                                             // deUint32 binding;
563                         VK_FORMAT_R32_SINT,                             // VkFormat format;
564                         0,                                                              // deUint32 offset;
565                 },
566         };
567
568         const VkVertexInputBindingDescription bindings[] =
569         {
570                 {
571                         0u,                                                             // deUint32                             binding;
572                         formatSizeInBytes * 2,                  // deUint32                             stride;
573                         VK_VERTEX_INPUT_RATE_VERTEX             // VkVertexInputRate    inputRate;
574                 },
575                 {
576                         1u,                                                             // deUint32                             binding;
577                         formatSizeInBytes,                              // deUint32                             stride;
578                         VK_VERTEX_INPUT_RATE_INSTANCE   // VkVertexInputRate    inputRate;
579                 },
580                 {
581                         2u,                                                             // deUint32                             binding;
582                         sizeof(deInt32),                                // deUint32                             stride;
583                         VK_VERTEX_INPUT_RATE_VERTEX             // VkVertexInputRate    inputRate;
584                 },
585         };
586
587         m_vertexInputBindings   = std::vector<VkVertexInputBindingDescription>(bindings, bindings + DE_LENGTH_OF_ARRAY(bindings));
588         m_vertexInputAttributes = std::vector<VkVertexInputAttributeDescription>(attributes, attributes + DE_LENGTH_OF_ARRAY(attributes));
589
590         // Create vertex buffer for vertex input rate
591         {
592                 VkMemoryRequirements bufferMemoryReqs;
593
594                 m_vertexRateBufferSize = getBufferSizeInBytes(m_numVertexValues, m_inputFormat); // All formats used in this test suite are 32-bit based.
595
596                 const VkBufferCreateInfo        vertexRateBufferParams  =
597                 {
598                         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,           // VkStructureType              sType;
599                         DE_NULL,                                                                        // const void*                  pNext;
600                         0u,                                                                                     // VkBufferCreateFlags  flags;
601                         m_vertexRateBufferSize,                                         // VkDeviceSize                 size;
602                         VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,                      // VkBufferUsageFlags   usage;
603                         VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                sharingMode;
604                         1u,                                                                                     // deUint32                             queueFamilyIndexCount;
605                         &queueFamilyIndex                                                       // const deUint32*              pQueueFamilyIndices;
606                 };
607
608                 m_vertexRateBuffer                      = createBuffer(vk, *m_device, &vertexRateBufferParams);
609                 bufferMemoryReqs                        = getBufferMemoryRequirements(vk, *m_device, *m_vertexRateBuffer);
610                 m_vertexRateBufferAllocSize     = bufferMemoryReqs.size;
611                 m_vertexRateBufferAlloc         = memAlloc.allocate(bufferMemoryReqs, MemoryRequirement::HostVisible);
612
613                 VK_CHECK(vk.bindBufferMemory(*m_device, *m_vertexRateBuffer, m_vertexRateBufferAlloc->getMemory(), m_vertexRateBufferAlloc->getOffset()));
614                 populateBufferWithTestValues(m_vertexRateBufferAlloc->getHostPtr(), (deUint32)m_vertexRateBufferAllocSize, m_inputFormat);
615                 flushMappedMemoryRange(vk, *m_device, m_vertexRateBufferAlloc->getMemory(), m_vertexRateBufferAlloc->getOffset(), VK_WHOLE_SIZE);
616         }
617
618         // Create vertex buffer for instance input rate
619         {
620                 VkMemoryRequirements bufferMemoryReqs;
621
622                 m_instanceRateBufferSize = getBufferSizeInBytes(m_numInstanceValues, m_inputFormat); // All formats used in this test suite are 32-bit based.
623
624                 const VkBufferCreateInfo        instanceRateBufferParams        =
625                 {
626                         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,           // VkStructureType              sType;
627                         DE_NULL,                                                                        // const void*                  pNext;
628                         0u,                                                                                     // VkBufferCreateFlags  flags;
629                         m_instanceRateBufferSize,                                       // VkDeviceSize                 size;
630                         VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,                      // VkBufferUsageFlags   usage;
631                         VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                sharingMode;
632                         1u,                                                                                     // deUint32                             queueFamilyIndexCount;
633                         &queueFamilyIndex                                                       // const deUint32*              pQueueFamilyIndices;
634                 };
635
636                 m_instanceRateBuffer                    = createBuffer(vk, *m_device, &instanceRateBufferParams);
637                 bufferMemoryReqs                                = getBufferMemoryRequirements(vk, *m_device, *m_instanceRateBuffer);
638                 m_instanceRateBufferAllocSize   = bufferMemoryReqs.size;
639                 m_instanceRateBufferAlloc               = memAlloc.allocate(bufferMemoryReqs, MemoryRequirement::HostVisible);
640
641                 VK_CHECK(vk.bindBufferMemory(*m_device, *m_instanceRateBuffer, m_instanceRateBufferAlloc->getMemory(), m_instanceRateBufferAlloc->getOffset()));
642                 populateBufferWithTestValues(m_instanceRateBufferAlloc->getHostPtr(), (deUint32)m_instanceRateBufferAllocSize, m_inputFormat);
643                 flushMappedMemoryRange(vk, *m_device, m_instanceRateBufferAlloc->getMemory(), m_instanceRateBufferAlloc->getOffset(), VK_WHOLE_SIZE);
644         }
645
646         // Create vertex buffer that stores the vertex number (from 0 to m_numVertices - 1)
647         {
648                 m_vertexNumBufferSize = 128 * sizeof(deInt32); // Allocate enough device memory for all indices (0 to 127).
649
650                 const VkBufferCreateInfo        vertexNumBufferParams   =
651                 {
652                         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,           // VkStructureType              sType;
653                         DE_NULL,                                                                        // const void*                  pNext;
654                         0u,                                                                                     // VkBufferCreateFlags  flags;
655                         m_vertexNumBufferSize,                                          // VkDeviceSize                 size;
656                         VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,                      // VkBufferUsageFlags   usage;
657                         VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                sharingMode;
658                         1u,                                                                                     // deUint32                             queueFamilyIndexCount;
659                         &queueFamilyIndex                                                       // const deUint32*              pQueueFamilyIndices;
660                 };
661
662                 m_vertexNumBuffer               = createBuffer(vk, *m_device, &vertexNumBufferParams);
663                 m_vertexNumBufferAlloc  = memAlloc.allocate(getBufferMemoryRequirements(vk, *m_device, *m_vertexNumBuffer), MemoryRequirement::HostVisible);
664
665                 VK_CHECK(vk.bindBufferMemory(*m_device, *m_vertexNumBuffer, m_vertexNumBufferAlloc->getMemory(), m_vertexNumBufferAlloc->getOffset()));
666         }
667
668         // Create index buffer if required
669         if (!indices.empty())
670         {
671                 m_indexBufferSize = sizeof(deUint32) * indices.size();
672
673                 const VkBufferCreateInfo        indexBufferParams       =
674                 {
675                         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,           // VkStructureType              sType;
676                         DE_NULL,                                                                        // const void*                  pNext;
677                         0u,                                                                                     // VkBufferCreateFlags  flags;
678                         m_indexBufferSize,                                                      // VkDeviceSize                 size;
679                         VK_BUFFER_USAGE_INDEX_BUFFER_BIT,                       // VkBufferUsageFlags   usage;
680                         VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                sharingMode;
681                         1u,                                                                                     // deUint32                             queueFamilyIndexCount;
682                         &queueFamilyIndex                                                       // const deUint32*              pQueueFamilyIndices;
683                 };
684
685                 m_indexBuffer           = createBuffer(vk, *m_device, &indexBufferParams);
686                 m_indexBufferAlloc      = memAlloc.allocate(getBufferMemoryRequirements(vk, *m_device, *m_indexBuffer), MemoryRequirement::HostVisible);
687
688                 VK_CHECK(vk.bindBufferMemory(*m_device, *m_indexBuffer, m_indexBufferAlloc->getMemory(), m_indexBufferAlloc->getOffset()));
689                 deMemcpy(m_indexBufferAlloc->getHostPtr(), indices.data(), (size_t)m_indexBufferSize);
690                 flushMappedMemoryRange(vk, *m_device, m_indexBufferAlloc->getMemory(), m_indexBufferAlloc->getOffset(), VK_WHOLE_SIZE);
691         }
692
693         // Create result ssbo
694         {
695                 const int       numChannels     = getNumUsedChannels(mapVkFormat(m_inputFormat).order);
696
697                 m_outBufferSize = getBufferSizeInBytes(m_numVertices * m_numInstances * numChannels * 3, VK_FORMAT_R32_UINT);
698
699                 const VkBufferCreateInfo        outBufferParams         =
700                 {
701                         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,           // VkStructureType              sType;
702                         DE_NULL,                                                                        // const void*                  pNext;
703                         0u,                                                                                     // VkBufferCreateFlags  flags;
704                         m_outBufferSize,                                                        // VkDeviceSize                 size;
705                         VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,                     // VkBufferUsageFlags   usage;
706                         VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                sharingMode;
707                         1u,                                                                                     // deUint32                             queueFamilyIndexCount;
708                         &queueFamilyIndex                                                       // const deUint32*              pQueueFamilyIndices;
709                 };
710
711                 m_outBuffer                                                             = createBuffer(vk, *m_device, &outBufferParams);
712                 const VkMemoryRequirements requirements = getBufferMemoryRequirements(vk, *m_device, *m_outBuffer);
713                 m_outBufferAlloc                                                = memAlloc.allocate(requirements, MemoryRequirement::HostVisible);
714                 m_outBufferAllocSize                                    = requirements.size;
715
716                 VK_CHECK(vk.bindBufferMemory(*m_device, *m_outBuffer, m_outBufferAlloc->getMemory(), m_outBufferAlloc->getOffset()));
717                 deMemset(m_outBufferAlloc->getHostPtr(), 0xFF, (size_t)m_outBufferSize);
718                 flushMappedMemoryRange(vk, *m_device, m_outBufferAlloc->getMemory(), m_outBufferAlloc->getOffset(), VK_WHOLE_SIZE);
719         }
720
721         // Create descriptor set data
722         {
723                 DescriptorPoolBuilder descriptorPoolBuilder;
724                 descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u);
725                 m_descriptorPool = descriptorPoolBuilder.build(vk, *m_device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
726
727                 DescriptorSetLayoutBuilder setLayoutBuilder;
728                 setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_VERTEX_BIT);
729                 m_descriptorSetLayout = setLayoutBuilder.build(vk, *m_device);
730
731                 const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo =
732                 {
733                         VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,         // VkStructureType                              sType;
734                         DE_NULL,                                                                                        // const void*                                  pNext;
735                         *m_descriptorPool,                                                                      // VkDescriptorPool                             desciptorPool;
736                         1u,                                                                                                     // deUint32                                             setLayoutCount;
737                         &m_descriptorSetLayout.get()                                            // const VkDescriptorSetLayout* pSetLayouts;
738                 };
739
740                 m_descriptorSet = allocateDescriptorSet(vk, *m_device, &descriptorSetAllocateInfo);
741
742                 const VkDescriptorBufferInfo outBufferDescriptorInfo    = makeDescriptorBufferInfo(*m_outBuffer, 0ull, VK_WHOLE_SIZE);
743
744                 DescriptorSetUpdateBuilder setUpdateBuilder;
745                 setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &outBufferDescriptorInfo);
746                 setUpdateBuilder.update(vk, *m_device);
747         }
748
749         // Create fence
750         {
751                 const VkFenceCreateInfo fenceParams =
752                 {
753                         VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,    // VkStructureType              sType;
754                         DE_NULL,                                                                // const void*                  pNext;
755                         0u                                                                              // VkFenceCreateFlags   flags;
756                 };
757
758                 m_fence = createFence(vk, *m_device, &fenceParams);
759         }
760
761         // Get queue
762         vk.getDeviceQueue(*m_device, queueFamilyIndex, 0, &m_queue);
763
764         // Setup graphics test environment
765         {
766                 GraphicsEnvironment::DrawConfig drawConfig;
767
768                 drawConfig.vertexBuffers.push_back(*m_vertexRateBuffer);
769                 drawConfig.vertexBuffers.push_back(*m_instanceRateBuffer);
770                 drawConfig.vertexBuffers.push_back(*m_vertexNumBuffer);
771
772                 drawConfig.vertexCount          = m_numVertices;
773                 drawConfig.instanceCount        = m_numInstances;
774                 drawConfig.indexBuffer          = *m_indexBuffer;
775                 drawConfig.indexCount           = (deUint32)(m_indexBufferSize / sizeof(deUint32));
776
777                 m_graphicsTestEnvironment       = de::MovePtr<GraphicsEnvironment>(new GraphicsEnvironment(m_context,
778                                                                                                                                                                                            m_instanceWrapper->instance,
779                                                                                                                                                                                            m_instanceWrapper->instance.getDriver(),
780                                                                                                                                                                                            *m_device,
781                                                                                                                                                                                            *m_descriptorSetLayout,
782                                                                                                                                                                                            *m_descriptorSet,
783                                                                                                                                                                                            GraphicsEnvironment::VertexBindings(bindings, bindings + DE_LENGTH_OF_ARRAY(bindings)),
784                                                                                                                                                                                            GraphicsEnvironment::VertexAttributes(attributes, attributes + DE_LENGTH_OF_ARRAY(attributes)),
785                                                                                                                                                                                            drawConfig));
786         }
787 }
788
789 VertexAccessInstance::~VertexAccessInstance(void)
790 {
791 }
792
793 tcu::TestStatus VertexAccessInstance::iterate (void)
794 {
795         const DeviceInterface&          vk                      = *m_deviceDriver;
796         const vk::VkCommandBuffer       cmdBuffer       = m_graphicsTestEnvironment->getCommandBuffer();
797
798         // Initialize vertex ids
799         {
800                 deUint32 *bufferPtr = reinterpret_cast<deUint32*>(m_vertexNumBufferAlloc->getHostPtr());
801                 deMemset(bufferPtr, 0, (size_t)m_vertexNumBufferSize);
802
803                 initVertexIds(bufferPtr, (size_t)(m_vertexNumBufferSize / sizeof(deUint32)));
804
805                 flushMappedMemoryRange(vk, *m_device, m_vertexNumBufferAlloc->getMemory(), m_vertexNumBufferAlloc->getOffset(), VK_WHOLE_SIZE);
806         }
807
808         // Submit command buffer
809         {
810                 const VkSubmitInfo      submitInfo      =
811                 {
812                         VK_STRUCTURE_TYPE_SUBMIT_INFO,  // VkStructureType                              sType;
813                         DE_NULL,                                                // const void*                                  pNext;
814                         0u,                                                             // deUint32                                             waitSemaphoreCount;
815                         DE_NULL,                                                // const VkSemaphore*                   pWaitSemaphores;
816                         DE_NULL,                                                // const VkPIpelineStageFlags*  pWaitDstStageMask;
817                         1u,                                                             // deUint32                                             commandBufferCount;
818                         &cmdBuffer,                                             // const VkCommandBuffer*               pCommandBuffers;
819                         0u,                                                             // deUint32                                             signalSemaphoreCount;
820                         DE_NULL                                                 // const VkSemaphore*                   pSignalSemaphores;
821                 };
822
823                 VK_CHECK(vk.resetFences(*m_device, 1, &m_fence.get()));
824                 VK_CHECK(vk.queueSubmit(m_queue, 1, &submitInfo, *m_fence));
825                 VK_CHECK(vk.waitForFences(*m_device, 1, &m_fence.get(), true, ~(0ull) /* infinity */));
826         }
827
828         // Prepare result buffer for read
829         {
830                 const VkMappedMemoryRange       outBufferRange  =
831                 {
832                         VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,  //  VkStructureType     sType;
833                         DE_NULL,                                                                //  const void*         pNext;
834                         m_outBufferAlloc->getMemory(),                  //  VkDeviceMemory      mem;
835                         0ull,                                                                   //  VkDeviceSize        offset;
836                         m_outBufferAllocSize,                                   //  VkDeviceSize        size;
837                 };
838
839                 VK_CHECK(vk.invalidateMappedMemoryRanges(*m_device, 1u, &outBufferRange));
840         }
841
842         if (verifyResult())
843                 return tcu::TestStatus::pass("All values OK");
844         else
845                 return tcu::TestStatus::fail("Invalid value(s) found");
846 }
847
848 bool VertexAccessInstance::verifyResult (void)
849 {
850         std::ostringstream                      logMsg;
851         const DeviceInterface&          vk                                              = *m_deviceDriver;
852         tcu::TestLog&                           log                                             = m_context.getTestContext().getLog();
853         const deUint32                          numChannels                             = getNumUsedChannels(mapVkFormat(m_inputFormat).order);
854         const deUint32                          numScalarsPerVertex             = numChannels * 3; // Use 3 identical attributes
855         void*                                           outDataPtr                              = m_outBufferAlloc->getHostPtr();
856         const deUint32                          outValueSize                    = static_cast<deUint32>((m_inputFormat == VK_FORMAT_R64_UINT || m_inputFormat == VK_FORMAT_R64_SINT)
857                                                                                 ? sizeof(deUint64) : sizeof(deUint32));
858         bool                                            allOk                                   = true;
859
860         const VkMappedMemoryRange       outBufferRange                  =
861         {
862                 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,  // VkStructureType      sType;
863                 DE_NULL,                                                                // const void*          pNext;
864                 m_outBufferAlloc->getMemory(),                  // VkDeviceMemory       mem;
865                 m_outBufferAlloc->getOffset(),                  // VkDeviceSize         offset;
866                 m_outBufferAllocSize,                                   // VkDeviceSize         size;
867         };
868
869         VK_CHECK(vk.invalidateMappedMemoryRanges(*m_device, 1u, &outBufferRange));
870
871         for (deUint32 valueNdx = 0; valueNdx < m_outBufferSize / outValueSize; valueNdx++)
872         {
873                 deUint32                        numInBufferValues;
874                 void*                           inBufferPtr;
875                 VkDeviceSize            inBufferAllocSize;
876                 deUint32                        inBufferValueIndex;
877                 bool                            isOutOfBoundsAccess             = false;
878                 const deUint32          attributeIndex                  = (valueNdx / numChannels) % 3;
879                 deUint32*                       ptr32                                   = (deUint32*)outDataPtr;
880                 deUint64*                       ptr64                                   = (deUint64*)outDataPtr;
881                 const void*                     outValuePtr                             = ((m_inputFormat == VK_FORMAT_R64_UINT || m_inputFormat == VK_FORMAT_R64_SINT) ?
882                                                                                                                 (void*)(ptr64 + valueNdx) :
883                                                                                                                 (void*)(ptr32 + valueNdx));
884
885                 if (attributeIndex == 2)
886                 {
887                         // Instance rate
888                         const deUint32  elementIndex    = valueNdx / (numScalarsPerVertex * m_numVertices); // instance id
889
890                         numInBufferValues       = m_numInstanceValues;
891                         inBufferPtr                     = m_instanceRateBufferAlloc->getHostPtr();
892                         inBufferAllocSize       = m_instanceRateBufferAllocSize;
893                         inBufferValueIndex      = (elementIndex * numChannels) + (valueNdx % numScalarsPerVertex) - (2 * numChannels);
894                 }
895                 else
896                 {
897                         // Vertex rate
898                         const deUint32  vertexNdx               = valueNdx / numScalarsPerVertex;
899                         const deUint32  instanceNdx             = vertexNdx / m_numVertices;
900                         const deUint32  elementIndex    = valueNdx / numScalarsPerVertex; // vertex id
901
902                         numInBufferValues       = m_numVertexValues;
903                         inBufferPtr                     = m_vertexRateBufferAlloc->getHostPtr();
904                         inBufferAllocSize       = m_vertexRateBufferAllocSize;
905                         inBufferValueIndex      = (getIndex(elementIndex) * (numChannels * 2)) + (valueNdx % numScalarsPerVertex) - instanceNdx * (m_numVertices * numChannels * 2);
906
907                         // Binding 0 contains two attributes, so bounds checking for attribute 0 must also consider attribute 1 to determine if the binding is out of bounds.
908                         if ((attributeIndex == 0) && (numInBufferValues >= numChannels))
909                                 numInBufferValues -= numChannels;
910                 }
911
912                 isOutOfBoundsAccess     = (inBufferValueIndex >= numInBufferValues);
913
914                 const deInt32           distanceToOutOfBounds   = (deInt32)outValueSize * ((deInt32)numInBufferValues - (deInt32)inBufferValueIndex);
915
916                 if (!isOutOfBoundsAccess && (distanceToOutOfBounds < 16))
917                         isOutOfBoundsAccess = (((inBufferValueIndex / numChannels) + 1) * numChannels > numInBufferValues);
918
919                 // Log value information
920                 {
921                         // Vertex separator
922                         if (valueNdx && valueNdx % numScalarsPerVertex == 0)
923                                 logMsg << "\n";
924
925                         logMsg << "\n" << valueNdx << ": Value ";
926
927                         // Result index and value
928                         if (m_inputFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
929                                 logValue(logMsg, outValuePtr, VK_FORMAT_R32_SFLOAT, 4);
930                         else
931                                 logValue(logMsg, outValuePtr, m_inputFormat, 4);
932
933                         // Attribute name
934                         logMsg << "\tfrom attr" << attributeIndex;
935                         if (numChannels > 1)
936                                 logMsg << "[" << valueNdx % numChannels << "]";
937
938                         // Input rate
939                         if (attributeIndex == 2)
940                                 logMsg << "\tinstance rate";
941                         else
942                                 logMsg << "\tvertex rate";
943                 }
944
945                 if (isOutOfBoundsAccess)
946                 {
947                         const bool isValidValue = isValueWithinVertexBufferOrZero(inBufferPtr, inBufferAllocSize, outValuePtr, inBufferValueIndex);
948
949                         logMsg << "\t(out of bounds)";
950
951                         if (!isValidValue)
952                         {
953                                 // Check if we are satisfying the [0, 0, 0, x] pattern, where x may be either 0 or 1,
954                                 // or the maximum representable positive integer value (if the format is integer-based).
955
956                                 const bool      canMatchVec4Pattern     = ((valueNdx % numChannels == 3) || m_inputFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32);
957                                 bool            matchesVec4Pattern      = false;
958
959                                 if (canMatchVec4Pattern)
960                                 {
961                                         if (m_inputFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
962                                                 matchesVec4Pattern      =  verifyOutOfBoundsVec4(outValuePtr, m_inputFormat);
963                                         else
964                                                 matchesVec4Pattern      =  verifyOutOfBoundsVec4(((deUint32*)outValuePtr) - 3, m_inputFormat);
965                                 }
966
967                                 if (!canMatchVec4Pattern || !matchesVec4Pattern)
968                                 {
969                                         logMsg << ", Failed: expected a value within the buffer range or 0";
970
971                                         if (canMatchVec4Pattern)
972                                                 logMsg << ", or the [0, 0, 0, x] pattern";
973
974                                         allOk = false;
975                                 }
976                         }
977                 }
978                 else if (!isExpectedValueFromVertexBuffer(inBufferPtr, inBufferValueIndex, m_inputFormat, outValuePtr))
979                 {
980                         logMsg << ", Failed: unexpected value";
981                         allOk = false;
982                 }
983         }
984         log << tcu::TestLog::Message << logMsg.str() << tcu::TestLog::EndMessage;
985
986         return allOk;
987 }
988
989 bool VertexAccessInstance::isValueWithinVertexBufferOrZero(void* vertexBuffer, VkDeviceSize vertexBufferSize, const void* value, deUint32 valueIndex)
990 {
991         if (m_inputFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
992         {
993                 const float             normValue               = *reinterpret_cast<const float*>(value);
994                 const deUint32  scalarIndex             = valueIndex % 4;
995                 const bool              isAlpha                 = (scalarIndex == 3);
996                 deUint32                encodedValue;
997
998                 if (isAlpha)
999                         encodedValue = deMin32(deUint32(deFloatRound(normValue * 0x3u)), 0x3u);
1000                 else
1001                         encodedValue = deMin32(deUint32(deFloatRound(normValue * 0x3FFu)), 0x3FFu);
1002
1003                 if (encodedValue == 0)
1004                         return true;
1005
1006                 for (deUint32 i = 0; i < vertexBufferSize / 4; i++)
1007                 {
1008                         const deUint32  packedValue             = reinterpret_cast<deUint32*>(vertexBuffer)[i];
1009                         deUint32                unpackedValue;
1010
1011                         if (scalarIndex < 3)
1012                                 unpackedValue = (packedValue >> (10 * scalarIndex)) & 0x3FFu;
1013                         else
1014                                 unpackedValue = (packedValue >> 30) & 0x3u;
1015
1016                         if (unpackedValue == encodedValue)
1017                                 return true;
1018                 }
1019
1020                 return false;
1021         }
1022         else
1023         {
1024                 return isValueWithinBufferOrZero(vertexBuffer, vertexBufferSize, value, sizeof(deUint32));
1025         }
1026 }
1027
1028 bool VertexAccessInstance::isExpectedValueFromVertexBuffer (const void* vertexBuffer, deUint32 vertexIndex, VkFormat vertexFormat, const void* value)
1029 {
1030         if (isUintFormat(vertexFormat))
1031         {
1032                 if (vertexFormat == VK_FORMAT_R64_UINT || vertexFormat == VK_FORMAT_R64_SINT)
1033                 {
1034                         const deUint64* bufferPtr = reinterpret_cast<const deUint64*>(vertexBuffer);
1035                         return bufferPtr[vertexIndex] == *reinterpret_cast<const deUint64 *>(value);
1036                 }
1037                 else
1038                 {
1039                         const deUint32* bufferPtr = reinterpret_cast<const deUint32*>(vertexBuffer);
1040                         return bufferPtr[vertexIndex] == *reinterpret_cast<const deUint32 *>(value);
1041                 }
1042         }
1043         else if (isIntFormat(vertexFormat))
1044         {
1045                 if (vertexFormat == VK_FORMAT_R64_UINT || vertexFormat == VK_FORMAT_R64_SINT)
1046                 {
1047                         const deInt64* bufferPtr = reinterpret_cast<const deInt64*>(vertexBuffer);
1048                         return bufferPtr[vertexIndex] == *reinterpret_cast<const deInt64 *>(value);
1049                 }
1050                 else
1051                 {
1052                         const deInt32* bufferPtr = reinterpret_cast<const deInt32*>(vertexBuffer);
1053                         return bufferPtr[vertexIndex] == *reinterpret_cast<const deInt32 *>(value);
1054                 }
1055         }
1056         else if (isFloatFormat(vertexFormat))
1057         {
1058                 const float* bufferPtr = reinterpret_cast<const float*>(vertexBuffer);
1059
1060                 return areEqual(bufferPtr[vertexIndex], *reinterpret_cast<const float *>(value));
1061         }
1062         else if (vertexFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
1063         {
1064                 const deUint32* bufferPtr               = reinterpret_cast<const deUint32*>(vertexBuffer);
1065                 const deUint32  packedValue             = bufferPtr[vertexIndex / 4];
1066                 const deUint32  scalarIndex             = vertexIndex % 4;
1067                 float                   normValue;
1068
1069                 if (scalarIndex < 3)
1070                         normValue = float((packedValue >> (10 * scalarIndex)) & 0x3FFu) / 0x3FFu;
1071                 else
1072                         normValue = float(packedValue >> 30) / 0x3u;
1073
1074                 return areEqual(normValue, *reinterpret_cast<const float *>(value));
1075         }
1076
1077         DE_ASSERT(false);
1078         return false;
1079 }
1080
1081 VkDeviceSize VertexAccessInstance::getBufferSizeInBytes (deUint32 numScalars, VkFormat format)
1082 {
1083         if (isUintFormat(format) || isIntFormat(format) || isFloatFormat(format))
1084         {
1085                 return numScalars * ((format == VK_FORMAT_R64_UINT || format == VK_FORMAT_R64_SINT) ? 8 : 4);
1086         }
1087         else if (format == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
1088         {
1089                 DE_ASSERT(numScalars % 4 == 0);
1090                 return numScalars;
1091         }
1092
1093         DE_ASSERT(false);
1094         return 0;
1095 }
1096
1097 // DrawAccessInstance
1098
1099 DrawAccessInstance::DrawAccessInstance (Context&                                context,
1100                                                                                 std::shared_ptr<CustomInstanceWrapper>  instanceWrapper,
1101                                                                                 Move<VkDevice>                  device,
1102 #ifndef CTS_USES_VULKANSC
1103                                                                                 de::MovePtr<vk::DeviceDriver>   deviceDriver,
1104 #else
1105                                                                                 de::MovePtr<vk::DeviceDriverSC, vk::DeinitDeviceDeleter>        deviceDriver,
1106 #endif // CTS_USES_VULKANSC
1107                                                                                 VkFormat                                inputFormat,
1108                                                                                 deUint32                                numVertexValues,
1109                                                                                 deUint32                                numInstanceValues,
1110                                                                                 deUint32                                numVertices,
1111                                                                                 deUint32                                numInstances)
1112         : VertexAccessInstance (context,
1113                                                         instanceWrapper,
1114                                                         device,
1115                                                         deviceDriver,
1116                                                         inputFormat,
1117                                                         numVertexValues,
1118                                                         numInstanceValues,
1119                                                         numVertices,
1120                                                         numInstances,
1121                                                         std::vector<deUint32>()) // No index buffer
1122 {
1123 }
1124
1125 void DrawAccessInstance::initVertexIds (deUint32 *indicesPtr, size_t indexCount)
1126 {
1127         for (deUint32 i = 0; i < indexCount; i++)
1128                 indicesPtr[i] = i;
1129 }
1130
1131 deUint32 DrawAccessInstance::getIndex (deUint32 vertexNum) const
1132 {
1133         return vertexNum;
1134 }
1135
1136 // DrawIndexedAccessInstance
1137
1138 DrawIndexedAccessInstance::DrawIndexedAccessInstance (Context&                                          context,
1139                                                                                                           std::shared_ptr<CustomInstanceWrapper>        instanceWrapper,
1140                                                                                                           Move<VkDevice>                                device,
1141 #ifndef CTS_USES_VULKANSC
1142                                                                                                           de::MovePtr<vk::DeviceDriver>         deviceDriver,
1143 #else
1144                                                                                                           de::MovePtr<vk::DeviceDriverSC, vk::DeinitDeviceDeleter>      deviceDriver,
1145 #endif // CTS_USES_VULKANSC
1146                                                                                                           VkFormat                                              inputFormat,
1147                                                                                                           deUint32                                              numVertexValues,
1148                                                                                                           deUint32                                              numInstanceValues,
1149                                                                                                           deUint32                                              numVertices,
1150                                                                                                           deUint32                                              numInstances,
1151                                                                                                           const std::vector<deUint32>&  indices)
1152         : VertexAccessInstance  (context,
1153                                                          instanceWrapper,
1154                                                          device,
1155                                                          deviceDriver,
1156                                                          inputFormat,
1157                                                          numVertexValues,
1158                                                          numInstanceValues,
1159                                                          numVertices,
1160                                                          numInstances,
1161                                                          indices)
1162         , m_indices                             (indices)
1163 {
1164 }
1165
1166 void DrawIndexedAccessInstance::initVertexIds (deUint32 *indicesPtr, size_t indexCount)
1167 {
1168         DE_UNREF(indexCount);
1169
1170         for (deUint32 i = 0; i < m_indices.size(); i++)
1171         {
1172                 DE_ASSERT(m_indices[i] < indexCount);
1173
1174                 indicesPtr[m_indices[i]] = i;
1175         }
1176 }
1177
1178 deUint32 DrawIndexedAccessInstance::getIndex (deUint32 vertexNum) const
1179 {
1180         DE_ASSERT(vertexNum < (deUint32)m_indices.size());
1181
1182         return m_indices[vertexNum];
1183 }
1184
1185 // Test node creation functions
1186
1187 static tcu::TestCaseGroup* createDrawTests (tcu::TestContext& testCtx, VkFormat format)
1188 {
1189         struct TestConfig
1190         {
1191                 std::string             name;
1192                 std::string             description;
1193                 VkFormat                inputFormat;
1194                 deUint32                numVertexValues;
1195                 deUint32                numInstanceValues;
1196                 deUint32                numVertices;
1197                 deUint32                numInstances;
1198         };
1199
1200         const deUint32 numChannels = getNumUsedChannels(mapVkFormat(format).order);
1201
1202         const TestConfig testConfigs[] =
1203         {
1204                 // name                                         description                                                                                     format  numVertexValues                 numInstanceValues       numVertices             numInstances
1205                 { "vertex_out_of_bounds",       "Create data for 6 vertices, draw 9 vertices",          format, numChannels * 2 * 6,    numChannels,            9,                              1        },
1206                 { "vertex_incomplete",          "Create data for half a vertex, draw 3 vertices",       format, numChannels,                    numChannels,            3,                              1        },
1207                 { "instance_out_of_bounds", "Create data for 1 instance, draw 3 instances",             format, numChannels * 2 * 9,    numChannels,            3,                              3        },
1208         };
1209
1210         de::MovePtr<tcu::TestCaseGroup> drawTests (new tcu::TestCaseGroup(testCtx, "draw", ""));
1211
1212         for (int i = 0; i < DE_LENGTH_OF_ARRAY(testConfigs); i++)
1213         {
1214                 const TestConfig &config = testConfigs[i];
1215
1216                 drawTests->addChild(new DrawAccessTest(testCtx, config.name, config.description, config.inputFormat,
1217                                                                                            config.numVertexValues, config.numInstanceValues,
1218                                                                                            config.numVertices, config.numInstances));
1219         }
1220
1221         return drawTests.release();
1222 }
1223
1224 static tcu::TestCaseGroup* createDrawIndexedTests (tcu::TestContext& testCtx, VkFormat format)
1225 {
1226         struct TestConfig
1227         {
1228                 std::string                                                     name;
1229                 std::string                                                     description;
1230                 VkFormat                                                        inputFormat;
1231                 DrawIndexedAccessTest::IndexConfig      indexConfig;
1232         };
1233
1234         const TestConfig testConfigs[] =
1235         {
1236                 // name                                                 description                                                             format          indexConfig
1237                 { "last_index_out_of_bounds",   "Only last index is out of bounds",             format,         DrawIndexedAccessTest::INDEX_CONFIG_LAST_INDEX_OUT_OF_BOUNDS },
1238                 { "indices_out_of_bounds",              "Random indices out of bounds",                 format,         DrawIndexedAccessTest::INDEX_CONFIG_INDICES_OUT_OF_BOUNDS },
1239                 { "triangle_out_of_bounds",             "First triangle is out of bounds",              format,         DrawIndexedAccessTest::INDEX_CONFIG_TRIANGLE_OUT_OF_BOUNDS },
1240         };
1241
1242         de::MovePtr<tcu::TestCaseGroup> drawTests (new tcu::TestCaseGroup(testCtx, "draw_indexed", ""));
1243
1244         for (int i = 0; i < DE_LENGTH_OF_ARRAY(testConfigs); i++)
1245         {
1246                 const TestConfig &config = testConfigs[i];
1247
1248                 drawTests->addChild(new DrawIndexedAccessTest(testCtx, config.name, config.description, config.inputFormat, config.indexConfig));
1249         }
1250
1251         return drawTests.release();
1252 }
1253
1254 static void addVertexFormatTests (tcu::TestContext& testCtx, tcu::TestCaseGroup* parentGroup)
1255 {
1256         const VkFormat vertexFormats[] =
1257         {
1258                 VK_FORMAT_R32_UINT,
1259                 VK_FORMAT_R32_SINT,
1260                 VK_FORMAT_R32_SFLOAT,
1261                 VK_FORMAT_R32G32_UINT,
1262                 VK_FORMAT_R32G32_SINT,
1263                 VK_FORMAT_R32G32_SFLOAT,
1264                 VK_FORMAT_R32G32B32_UINT,
1265                 VK_FORMAT_R32G32B32_SINT,
1266                 VK_FORMAT_R32G32B32_SFLOAT,
1267                 VK_FORMAT_R32G32B32A32_UINT,
1268                 VK_FORMAT_R32G32B32A32_SINT,
1269                 VK_FORMAT_R32G32B32A32_SFLOAT,
1270                 VK_FORMAT_R64_UINT,
1271                 VK_FORMAT_R64_SINT,
1272
1273                 VK_FORMAT_A2B10G10R10_UNORM_PACK32
1274         };
1275
1276         for (int i = 0; i < DE_LENGTH_OF_ARRAY(vertexFormats); i++)
1277         {
1278                 const std::string                               formatName      = getFormatName(vertexFormats[i]);
1279                 de::MovePtr<tcu::TestCaseGroup> formatGroup     (new tcu::TestCaseGroup(testCtx, de::toLower(formatName.substr(10)).c_str(), ""));
1280
1281                 formatGroup->addChild(createDrawTests(testCtx, vertexFormats[i]));
1282                 formatGroup->addChild(createDrawIndexedTests(testCtx, vertexFormats[i]));
1283
1284                 parentGroup->addChild(formatGroup.release());
1285         }
1286 }
1287
1288 tcu::TestCaseGroup* createVertexAccessTests (tcu::TestContext& testCtx)
1289 {
1290         de::MovePtr<tcu::TestCaseGroup> vertexAccessTests       (new tcu::TestCaseGroup(testCtx, "vertex_access", ""));
1291
1292         addVertexFormatTests(testCtx, vertexAccessTests.get());
1293
1294         return vertexAccessTests.release();
1295 }
1296
1297 } // robustness
1298 } // vkt