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