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