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