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
~VertexAccessTest(void)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
~DrawAccessTest(void)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
~DrawIndexedAccessTest(void)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
~VertexAccessInstance(void)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
~DrawAccessInstance(void)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
~DrawIndexedAccessInstance(void)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
VertexAccessTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,VkFormat inputFormat,deUint32 numVertexValues,deUint32 numInstanceValues,deUint32 numVertices,deUint32 numInstances)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
initPrograms(SourceCollections & programCollection) const249 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
DrawAccessTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,VkFormat inputFormat,deUint32 numVertexValues,deUint32 numInstanceValues,deUint32 numVertices,deUint32 numInstances)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
createInstance(Context & context) const354 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
DrawIndexedAccessTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,VkFormat inputFormat,IndexConfig indexConfig)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
createInstance(Context & context) const407 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
VertexAccessInstance(Context & context,Move<VkDevice> device,VkFormat inputFormat,deUint32 numVertexValues,deUint32 numInstanceValues,deUint32 numVertices,deUint32 numInstances,const std::vector<deUint32> & indices)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
iterate(void)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
verifyResult(void)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 deUint32 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 deUint32 attributeIndex = (valueNdx / numChannels) % 3;
786 const deUint32* outValuePtr = (deUint32*)outDataPtr + valueNdx;
787
788 if (attributeIndex == 2)
789 {
790 // Instance rate
791 const deUint32 elementIndex = valueNdx / (numScalarsPerVertex * m_numVertices); // instance id
792
793 numInBufferValues = m_numInstanceValues;
794 inBufferPtr = m_instanceRateBufferAlloc->getHostPtr();
795 inBufferAllocSize = m_instanceRateBufferAllocSize;
796 inBufferValueIndex = (elementIndex * numChannels) + (valueNdx % numScalarsPerVertex) - (2 * numChannels);
797 }
798 else
799 {
800 // Vertex rate
801 const deUint32 vertexNdx = valueNdx / numScalarsPerVertex;
802 const deUint32 instanceNdx = vertexNdx / m_numVertices;
803 const deUint32 elementIndex = valueNdx / numScalarsPerVertex; // vertex id
804
805 numInBufferValues = m_numVertexValues;
806 inBufferPtr = m_vertexRateBufferAlloc->getHostPtr();
807 inBufferAllocSize = m_vertexRateBufferAllocSize;
808 inBufferValueIndex = (getIndex(elementIndex) * (numChannels * 2)) + (valueNdx % numScalarsPerVertex) - instanceNdx * (m_numVertices * numChannels * 2);
809
810 // 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.
811 if ((attributeIndex == 0) && (numInBufferValues >= numChannels))
812 numInBufferValues -= numChannels;
813 }
814
815 isOutOfBoundsAccess = (inBufferValueIndex >= numInBufferValues);
816
817 const deInt32 distanceToOutOfBounds = (deInt32)outValueSize * ((deInt32)numInBufferValues - (deInt32)inBufferValueIndex);
818
819 if (!isOutOfBoundsAccess && (distanceToOutOfBounds < 16))
820 isOutOfBoundsAccess = (((inBufferValueIndex / numChannels) + 1) * numChannels > numInBufferValues);
821
822 // Log value information
823 {
824 // Vertex separator
825 if (valueNdx && valueNdx % numScalarsPerVertex == 0)
826 logMsg << "\n";
827
828 logMsg << "\n" << valueNdx << ": Value ";
829
830 // Result index and value
831 if (m_inputFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
832 logValue(logMsg, outValuePtr, VK_FORMAT_R32_SFLOAT, 4);
833 else
834 logValue(logMsg, outValuePtr, m_inputFormat, 4);
835
836 // Attribute name
837 logMsg << "\tfrom attr" << attributeIndex;
838 if (numChannels > 1)
839 logMsg << "[" << valueNdx % numChannels << "]";
840
841 // Input rate
842 if (attributeIndex == 2)
843 logMsg << "\tinstance rate";
844 else
845 logMsg << "\tvertex rate";
846 }
847
848 if (isOutOfBoundsAccess)
849 {
850 const bool isValidValue = isValueWithinVertexBufferOrZero(inBufferPtr, inBufferAllocSize, outValuePtr, inBufferValueIndex);
851
852 logMsg << "\t(out of bounds)";
853
854 if (!isValidValue)
855 {
856 // Check if we are satisfying the [0, 0, 0, x] pattern, where x may be either 0 or 1,
857 // or the maximum representable positive integer value (if the format is integer-based).
858
859 const bool canMatchVec4Pattern = ((valueNdx % numChannels == 3) || m_inputFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32);
860 bool matchesVec4Pattern = false;
861
862 if (canMatchVec4Pattern)
863 {
864 if (m_inputFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
865 matchesVec4Pattern = verifyOutOfBoundsVec4(outValuePtr, m_inputFormat);
866 else
867 matchesVec4Pattern = verifyOutOfBoundsVec4(outValuePtr - 3, m_inputFormat);
868 }
869
870 if (!canMatchVec4Pattern || !matchesVec4Pattern)
871 {
872 logMsg << ", Failed: expected a value within the buffer range or 0";
873
874 if (canMatchVec4Pattern)
875 logMsg << ", or the [0, 0, 0, x] pattern";
876
877 allOk = false;
878 }
879 }
880 }
881 else if (!isExpectedValueFromVertexBuffer(inBufferPtr, inBufferValueIndex, m_inputFormat, outValuePtr))
882 {
883 logMsg << ", Failed: unexpected value";
884 allOk = false;
885 }
886 }
887 log << tcu::TestLog::Message << logMsg.str() << tcu::TestLog::EndMessage;
888
889 return allOk;
890 }
891
isValueWithinVertexBufferOrZero(void * vertexBuffer,VkDeviceSize vertexBufferSize,const void * value,deUint32 valueIndex)892 bool VertexAccessInstance::isValueWithinVertexBufferOrZero(void* vertexBuffer, VkDeviceSize vertexBufferSize, const void* value, deUint32 valueIndex)
893 {
894 if (m_inputFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
895 {
896 const float normValue = *reinterpret_cast<const float*>(value);
897 const deUint32 scalarIndex = valueIndex % 4;
898 const bool isAlpha = (scalarIndex == 3);
899 deUint32 encodedValue;
900
901 if (isAlpha)
902 encodedValue = deMin32(deUint32(deFloatRound(normValue * 0x3u)), 0x3u);
903 else
904 encodedValue = deMin32(deUint32(deFloatRound(normValue * 0x3FFu)), 0x3FFu);
905
906 if (encodedValue == 0)
907 return true;
908
909 for (deUint32 i = 0; i < vertexBufferSize / 4; i++)
910 {
911 const deUint32 packedValue = reinterpret_cast<deUint32*>(vertexBuffer)[i];
912 deUint32 unpackedValue;
913
914 if (scalarIndex < 3)
915 unpackedValue = (packedValue >> (10 * scalarIndex)) & 0x3FFu;
916 else
917 unpackedValue = (packedValue >> 30) & 0x3u;
918
919 if (unpackedValue == encodedValue)
920 return true;
921 }
922
923 return false;
924 }
925 else
926 {
927 return isValueWithinBufferOrZero(vertexBuffer, vertexBufferSize, value, sizeof(deUint32));
928 }
929 }
930
isExpectedValueFromVertexBuffer(const void * vertexBuffer,deUint32 vertexIndex,VkFormat vertexFormat,const void * value)931 bool VertexAccessInstance::isExpectedValueFromVertexBuffer (const void* vertexBuffer, deUint32 vertexIndex, VkFormat vertexFormat, const void* value)
932 {
933 if (isUintFormat(vertexFormat))
934 {
935 const deUint32* bufferPtr = reinterpret_cast<const deUint32*>(vertexBuffer);
936
937 return bufferPtr[vertexIndex] == *reinterpret_cast<const deUint32 *>(value);
938 }
939 else if (isIntFormat(vertexFormat))
940 {
941 const deInt32* bufferPtr = reinterpret_cast<const deInt32*>(vertexBuffer);
942
943 return bufferPtr[vertexIndex] == *reinterpret_cast<const deInt32 *>(value);
944 }
945 else if (isFloatFormat(vertexFormat))
946 {
947 const float* bufferPtr = reinterpret_cast<const float*>(vertexBuffer);
948
949 return areEqual(bufferPtr[vertexIndex], *reinterpret_cast<const float *>(value));
950 }
951 else if (vertexFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
952 {
953 const deUint32* bufferPtr = reinterpret_cast<const deUint32*>(vertexBuffer);
954 const deUint32 packedValue = bufferPtr[vertexIndex / 4];
955 const deUint32 scalarIndex = vertexIndex % 4;
956 float normValue;
957
958 if (scalarIndex < 3)
959 normValue = float((packedValue >> (10 * scalarIndex)) & 0x3FFu) / 0x3FFu;
960 else
961 normValue = float(packedValue >> 30) / 0x3u;
962
963 return areEqual(normValue, *reinterpret_cast<const float *>(value));
964 }
965
966 DE_ASSERT(false);
967 return false;
968 }
969
getBufferSizeInBytes(deUint32 numScalars,VkFormat format)970 VkDeviceSize VertexAccessInstance::getBufferSizeInBytes (deUint32 numScalars, VkFormat format)
971 {
972 if (isUintFormat(format) || isIntFormat(format) || isFloatFormat(format))
973 {
974 return numScalars * 4;
975 }
976 else if (format == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
977 {
978 DE_ASSERT(numScalars % 4 == 0);
979 return numScalars;
980 }
981
982 DE_ASSERT(false);
983 return 0;
984 }
985
986 // DrawAccessInstance
987
DrawAccessInstance(Context & context,Move<VkDevice> device,VkFormat inputFormat,deUint32 numVertexValues,deUint32 numInstanceValues,deUint32 numVertices,deUint32 numInstances)988 DrawAccessInstance::DrawAccessInstance (Context& context,
989 Move<VkDevice> device,
990 VkFormat inputFormat,
991 deUint32 numVertexValues,
992 deUint32 numInstanceValues,
993 deUint32 numVertices,
994 deUint32 numInstances)
995 : VertexAccessInstance (context,
996 device,
997 inputFormat,
998 numVertexValues,
999 numInstanceValues,
1000 numVertices,
1001 numInstances,
1002 std::vector<deUint32>()) // No index buffer
1003 {
1004 }
1005
initVertexIds(deUint32 * indicesPtr,size_t indexCount)1006 void DrawAccessInstance::initVertexIds (deUint32 *indicesPtr, size_t indexCount)
1007 {
1008 for (deUint32 i = 0; i < indexCount; i++)
1009 indicesPtr[i] = i;
1010 }
1011
getIndex(deUint32 vertexNum) const1012 deUint32 DrawAccessInstance::getIndex (deUint32 vertexNum) const
1013 {
1014 return vertexNum;
1015 }
1016
1017 // DrawIndexedAccessInstance
1018
DrawIndexedAccessInstance(Context & context,Move<VkDevice> device,VkFormat inputFormat,deUint32 numVertexValues,deUint32 numInstanceValues,deUint32 numVertices,deUint32 numInstances,const std::vector<deUint32> & indices)1019 DrawIndexedAccessInstance::DrawIndexedAccessInstance (Context& context,
1020 Move<VkDevice> device,
1021 VkFormat inputFormat,
1022 deUint32 numVertexValues,
1023 deUint32 numInstanceValues,
1024 deUint32 numVertices,
1025 deUint32 numInstances,
1026 const std::vector<deUint32>& indices)
1027 : VertexAccessInstance (context,
1028 device,
1029 inputFormat,
1030 numVertexValues,
1031 numInstanceValues,
1032 numVertices,
1033 numInstances,
1034 indices)
1035 , m_indices (indices)
1036 {
1037 }
1038
initVertexIds(deUint32 * indicesPtr,size_t indexCount)1039 void DrawIndexedAccessInstance::initVertexIds (deUint32 *indicesPtr, size_t indexCount)
1040 {
1041 DE_UNREF(indexCount);
1042
1043 for (deUint32 i = 0; i < m_indices.size(); i++)
1044 {
1045 DE_ASSERT(m_indices[i] < indexCount);
1046
1047 indicesPtr[m_indices[i]] = i;
1048 }
1049 }
1050
getIndex(deUint32 vertexNum) const1051 deUint32 DrawIndexedAccessInstance::getIndex (deUint32 vertexNum) const
1052 {
1053 DE_ASSERT(vertexNum < (deUint32)m_indices.size());
1054
1055 return m_indices[vertexNum];
1056 }
1057
1058 // Test node creation functions
1059
createDrawTests(tcu::TestContext & testCtx,VkFormat format)1060 static tcu::TestCaseGroup* createDrawTests (tcu::TestContext& testCtx, VkFormat format)
1061 {
1062 struct TestConfig
1063 {
1064 std::string name;
1065 std::string description;
1066 VkFormat inputFormat;
1067 deUint32 numVertexValues;
1068 deUint32 numInstanceValues;
1069 deUint32 numVertices;
1070 deUint32 numInstances;
1071 };
1072
1073 const deUint32 numChannels = getNumUsedChannels(mapVkFormat(format).order);
1074
1075 const TestConfig testConfigs[] =
1076 {
1077 // name description format numVertexValues numInstanceValues numVertices numInstances
1078 { "vertex_out_of_bounds", "Create data for 6 vertices, draw 9 vertices", format, numChannels * 2 * 6, numChannels, 9, 1 },
1079 { "vertex_incomplete", "Create data for half a vertex, draw 3 vertices", format, numChannels, numChannels, 3, 1 },
1080 { "instance_out_of_bounds", "Create data for 1 instance, draw 3 instances", format, numChannels * 2 * 9, numChannels, 3, 3 },
1081 };
1082
1083 de::MovePtr<tcu::TestCaseGroup> drawTests (new tcu::TestCaseGroup(testCtx, "draw", ""));
1084
1085 for (int i = 0; i < DE_LENGTH_OF_ARRAY(testConfigs); i++)
1086 {
1087 const TestConfig &config = testConfigs[i];
1088
1089 drawTests->addChild(new DrawAccessTest(testCtx, config.name, config.description, config.inputFormat,
1090 config.numVertexValues, config.numInstanceValues,
1091 config.numVertices, config.numInstances));
1092 }
1093
1094 return drawTests.release();
1095 }
1096
createDrawIndexedTests(tcu::TestContext & testCtx,VkFormat format)1097 static tcu::TestCaseGroup* createDrawIndexedTests (tcu::TestContext& testCtx, VkFormat format)
1098 {
1099 struct TestConfig
1100 {
1101 std::string name;
1102 std::string description;
1103 VkFormat inputFormat;
1104 DrawIndexedAccessTest::IndexConfig indexConfig;
1105 };
1106
1107 const TestConfig testConfigs[] =
1108 {
1109 // name description format indexConfig
1110 { "last_index_out_of_bounds", "Only last index is out of bounds", format, DrawIndexedAccessTest::INDEX_CONFIG_LAST_INDEX_OUT_OF_BOUNDS },
1111 { "indices_out_of_bounds", "Random indices out of bounds", format, DrawIndexedAccessTest::INDEX_CONFIG_INDICES_OUT_OF_BOUNDS },
1112 { "triangle_out_of_bounds", "First triangle is out of bounds", format, DrawIndexedAccessTest::INDEX_CONFIG_TRIANGLE_OUT_OF_BOUNDS },
1113 };
1114
1115 de::MovePtr<tcu::TestCaseGroup> drawTests (new tcu::TestCaseGroup(testCtx, "draw_indexed", ""));
1116
1117 for (int i = 0; i < DE_LENGTH_OF_ARRAY(testConfigs); i++)
1118 {
1119 const TestConfig &config = testConfigs[i];
1120
1121 drawTests->addChild(new DrawIndexedAccessTest(testCtx, config.name, config.description, config.inputFormat, config.indexConfig));
1122 }
1123
1124 return drawTests.release();
1125 }
1126
addVertexFormatTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * parentGroup)1127 static void addVertexFormatTests (tcu::TestContext& testCtx, tcu::TestCaseGroup* parentGroup)
1128 {
1129 const VkFormat vertexFormats[] =
1130 {
1131 VK_FORMAT_R32_UINT,
1132 VK_FORMAT_R32_SINT,
1133 VK_FORMAT_R32_SFLOAT,
1134 VK_FORMAT_R32G32_UINT,
1135 VK_FORMAT_R32G32_SINT,
1136 VK_FORMAT_R32G32_SFLOAT,
1137 VK_FORMAT_R32G32B32_UINT,
1138 VK_FORMAT_R32G32B32_SINT,
1139 VK_FORMAT_R32G32B32_SFLOAT,
1140 VK_FORMAT_R32G32B32A32_UINT,
1141 VK_FORMAT_R32G32B32A32_SINT,
1142 VK_FORMAT_R32G32B32A32_SFLOAT,
1143
1144 VK_FORMAT_A2B10G10R10_UNORM_PACK32
1145 };
1146
1147 for (int i = 0; i < DE_LENGTH_OF_ARRAY(vertexFormats); i++)
1148 {
1149 const std::string formatName = getFormatName(vertexFormats[i]);
1150 de::MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx, de::toLower(formatName.substr(10)).c_str(), ""));
1151
1152 formatGroup->addChild(createDrawTests(testCtx, vertexFormats[i]));
1153 formatGroup->addChild(createDrawIndexedTests(testCtx, vertexFormats[i]));
1154
1155 parentGroup->addChild(formatGroup.release());
1156 }
1157 }
1158
createVertexAccessTests(tcu::TestContext & testCtx)1159 tcu::TestCaseGroup* createVertexAccessTests (tcu::TestContext& testCtx)
1160 {
1161 de::MovePtr<tcu::TestCaseGroup> vertexAccessTests (new tcu::TestCaseGroup(testCtx, "vertex_access", ""));
1162
1163 addVertexFormatTests(testCtx, vertexAccessTests.get());
1164
1165 return vertexAccessTests.release();
1166 }
1167
1168 } // robustness
1169 } // vkt
1170