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