1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2016 The Khronos Group Inc.
6 * Copyright (c) 2016 Imagination Technologies Ltd.
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 * \brief Robust Vertex Buffer Access Tests
23 *//*--------------------------------------------------------------------*/
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"
34 #include "vkRefUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "tcuTestLog.hpp"
38 #include "deUniquePtr.hpp"
48 typedef std::vector<VkVertexInputBindingDescription> BindingList;
49 typedef std::vector<VkVertexInputAttributeDescription> AttributeList;
51 class VertexAccessTest : public vkt::TestCase
54 VertexAccessTest (tcu::TestContext& testContext,
55 const std::string& name,
56 const std::string& description,
58 deUint32 numVertexValues,
59 deUint32 numInstanceValues,
61 deUint32 numInstances);
63 virtual ~VertexAccessTest (void) {}
65 void initPrograms (SourceCollections& programCollection) const;
66 TestInstance* createInstance (Context& context) const = 0;
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;
77 class DrawAccessTest : public VertexAccessTest
80 DrawAccessTest (tcu::TestContext& testContext,
81 const std::string& name,
82 const std::string& description,
84 deUint32 numVertexValues,
85 deUint32 numInstanceValues,
87 deUint32 numInstances);
89 virtual ~DrawAccessTest (void) {}
90 TestInstance* createInstance (Context& context) const;
95 class DrawIndexedAccessTest : public VertexAccessTest
100 INDEX_CONFIG_LAST_INDEX_OUT_OF_BOUNDS,
101 INDEX_CONFIG_INDICES_OUT_OF_BOUNDS,
102 INDEX_CONFIG_TRIANGLE_OUT_OF_BOUNDS,
107 const static std::vector<deUint32> s_indexConfigs[INDEX_CONFIG_COUNT];
109 DrawIndexedAccessTest (tcu::TestContext& testContext,
110 const std::string& name,
111 const std::string& description,
112 VkFormat inputFormat,
113 IndexConfig indexConfig);
115 virtual ~DrawIndexedAccessTest (void) {}
116 TestInstance* createInstance (Context& context) const;
119 const IndexConfig m_indexConfig;
122 class VertexAccessInstance : public vkt::TestInstance
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);
134 virtual ~VertexAccessInstance (void) {}
135 virtual tcu::TestStatus iterate (void);
136 virtual bool verifyResult (void);
139 bool isValueWithinVertexBufferOrZero (void* vertexBuffer, VkDeviceSize vertexBufferSize, const void* value, deUint32 valueIndexa);
142 static bool isExpectedValueFromVertexBuffer (const void* vertexBuffer, deUint32 vertexIndex, VkFormat vertexFormat, const void* value);
143 static VkDeviceSize getBufferSizeInBytes (deUint32 numScalars, VkFormat format);
145 virtual void initVertexIds (deUint32 *indicesPtr, size_t indexCount) = 0;
146 virtual deUint32 getIndex (deUint32 vertexNum) const = 0;
148 Move<VkDevice> m_device;
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;
158 Move<VkBuffer> m_vertexRateBuffer;
159 VkDeviceSize m_vertexRateBufferSize;
160 de::MovePtr<Allocation> m_vertexRateBufferAlloc;
161 VkDeviceSize m_vertexRateBufferAllocSize;
163 Move<VkBuffer> m_instanceRateBuffer;
164 VkDeviceSize m_instanceRateBufferSize;
165 de::MovePtr<Allocation> m_instanceRateBufferAlloc;
166 VkDeviceSize m_instanceRateBufferAllocSize;
168 Move<VkBuffer> m_vertexNumBuffer;
169 VkDeviceSize m_vertexNumBufferSize;
170 de::MovePtr<Allocation> m_vertexNumBufferAlloc;
172 Move<VkBuffer> m_indexBuffer;
173 VkDeviceSize m_indexBufferSize;
174 de::MovePtr<Allocation> m_indexBufferAlloc;
176 Move<VkBuffer> m_outBuffer; // SSBO
177 VkDeviceSize m_outBufferSize;
178 de::MovePtr<Allocation> m_outBufferAlloc;
180 Move<VkDescriptorPool> m_descriptorPool;
181 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
182 Move<VkDescriptorSet> m_descriptorSet;
184 Move<VkFence> m_fence;
187 de::MovePtr<GraphicsEnvironment> m_graphicsTestEnvironment;
190 class DrawAccessInstance : public VertexAccessInstance
193 DrawAccessInstance (Context& context,
194 Move<VkDevice> device,
195 VkFormat inputFormat,
196 deUint32 numVertexValues,
197 deUint32 numInstanceValues,
198 deUint32 numVertices,
199 deUint32 numInstances);
201 virtual ~DrawAccessInstance (void) {}
204 virtual void initVertexIds (deUint32 *indicesPtr, size_t indexCount);
205 virtual deUint32 getIndex (deUint32 vertexNum) const;
208 class DrawIndexedAccessInstance : public VertexAccessInstance
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);
220 virtual ~DrawIndexedAccessInstance (void) {}
223 virtual void initVertexIds (deUint32 *indicesPtr, size_t indexCount);
224 virtual deUint32 getIndex (deUint32 vertexNum) const;
226 const std::vector<deUint32> m_indices;
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)
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)
249 void VertexAccessTest::initPrograms (SourceCollections& programCollection) const
251 std::ostringstream attributeDeclaration;
252 std::ostringstream attributeUse;
254 std::ostringstream vertexShaderSource;
255 std::ostringstream fragmentShaderSource;
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;
262 if (numChannels == 1)
264 if (isUintFormat(m_inputFormat))
265 attributeTypeStr << "uint";
266 else if (isIntFormat(m_inputFormat))
267 attributeTypeStr << "int";
269 attributeTypeStr << "float";
273 if (isUintFormat(m_inputFormat))
274 attributeTypeStr << "uvec";
275 else if (isIntFormat(m_inputFormat))
276 attributeTypeStr << "ivec";
278 attributeTypeStr << "vec";
280 attributeTypeStr << numChannels;
283 for (int attrNdx = 0; attrNdx < 3; attrNdx++)
285 attributeDeclaration << "layout(location = " << attrNdx << ") in " << attributeTypeStr.str() << " attr" << attrNdx << ";\n";
287 for (int chanNdx = 0; chanNdx < numChannels; chanNdx++)
289 attributeUse << "\toutData[(gl_InstanceIndex * " << numScalarsPerVertex * m_numVertices
290 << ") + (vertexNum * " << numScalarsPerVertex << " + " << numValues++ << ")] = attr" << attrNdx;
292 if (numChannels == 1)
293 attributeUse << ";\n";
295 attributeUse << "[" << chanNdx << "];\n";
299 attributeDeclaration << "layout(location = 3) in int vertexNum;\n";
301 attributeUse << "\n";
303 const char *outType = "";
304 if (isUintFormat(m_inputFormat))
306 else if (isIntFormat(m_inputFormat))
311 vertexShaderSource <<
313 "precision highp float;\n"
314 << attributeDeclaration.str() <<
315 "layout(set = 0, binding = 0, std430) buffer outBuffer\n"
317 "\t" << outType << " outData[" << (m_numVertices * numValues) * m_numInstances << "];\n"
321 << attributeUse.str() <<
322 "\tgl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
325 programCollection.glslSources.add("vertex") << glu::VertexSource(vertexShaderSource.str());
327 fragmentShaderSource <<
329 "precision highp float;\n"
330 "layout(location = 0) out vec4 fragColor;\n"
333 "\tfragColor = vec4(1.0);\n"
336 programCollection.glslSources.add("fragment") << glu::FragmentSource(fragmentShaderSource.str());
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)
350 : VertexAccessTest (testContext, name, description, inputFormat, numVertexValues, numInstanceValues, numVertices, numInstances)
354 TestInstance* DrawAccessTest::createInstance (Context& context) const
356 Move<VkDevice> device = createRobustBufferAccessDevice(context);
358 return new DrawAccessInstance(context,
367 // DrawIndexedAccessTest
369 const deUint32 lastIndexOutOfBounds[] =
371 0, 1, 2, 3, 4, 100, // Indices of 100 and above are out of bounds
373 const deUint32 indicesOutOfBounds[] =
375 0, 100, 2, 101, 3, 102, // Indices of 100 and above are out of bounds
377 const deUint32 triangleOutOfBounds[] =
379 100, 101, 102, 3, 4, 5, // Indices of 100 and above are out of bounds
382 const std::vector<deUint32> DrawIndexedAccessTest::s_indexConfigs[INDEX_CONFIG_COUNT] =
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)),
389 DrawIndexedAccessTest::DrawIndexedAccessTest (tcu::TestContext& testContext,
390 const std::string& name,
391 const std::string& description,
392 VkFormat inputFormat,
393 IndexConfig indexConfig)
395 : VertexAccessTest (testContext,
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
403 , m_indexConfig (indexConfig)
407 TestInstance* DrawIndexedAccessTest::createInstance (Context& context) const
409 Move<VkDevice> device = createRobustBufferAccessDevice(context);
411 return new DrawIndexedAccessInstance(context,
418 s_indexConfigs[m_indexConfig]);
421 // VertexAccessInstance
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)
432 : vkt::TestInstance (context)
434 , m_inputFormat (inputFormat)
435 , m_numVertexValues (numVertexValues)
436 , m_numInstanceValues (numInstanceValues)
437 , m_numVertices (numVertices)
438 , m_numInstances (numInstances)
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));
445 // Check storage support
446 if (!context.getDeviceFeatures().vertexPipelineStoresAndAtomics)
448 TCU_THROW(NotSupportedError, "Stores not supported in vertex stage");
451 const VkVertexInputAttributeDescription attributes[] =
453 // input rate: vertex
455 0u, // deUint32 location;
456 0u, // deUint32 binding;
457 m_inputFormat, // VkFormat format;
458 0u, // deUint32 offset;
461 1u, // deUint32 location;
462 0u, // deUint32 binding;
463 m_inputFormat, // VkFormat format;
464 formatSizeInBytes, // deUint32 offset;
467 // input rate: instance
469 2u, // deUint32 location;
470 1u, // deUint32 binding;
471 m_inputFormat, // VkFormat format;
472 0u, // deUint32 offset;
475 // Attribute for vertex number
477 3u, // deUint32 location;
478 2u, // deUint32 binding;
479 VK_FORMAT_R32_SINT, // VkFormat format;
480 0, // deUint32 offset;
484 const VkVertexInputBindingDescription bindings[] =
487 0u, // deUint32 binding;
488 formatSizeInBytes * 2, // deUint32 stride;
489 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate inputRate;
492 1u, // deUint32 binding;
493 formatSizeInBytes, // deUint32 stride;
494 VK_VERTEX_INPUT_RATE_INSTANCE // VkVertexInputRate inputRate;
497 2u, // deUint32 binding;
498 sizeof(deInt32), // deUint32 stride;
499 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate inputRate;
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));
506 // Create vertex buffer for vertex input rate
508 VkMemoryRequirements bufferMemoryReqs;
510 m_vertexRateBufferSize = getBufferSizeInBytes(m_numVertexValues, m_inputFormat); // All formats used in this test suite are 32-bit based.
512 const VkBufferCreateInfo vertexRateBufferParams =
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;
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);
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);
534 // Create vertex buffer for instance input rate
536 VkMemoryRequirements bufferMemoryReqs;
538 m_instanceRateBufferSize = getBufferSizeInBytes(m_numInstanceValues, m_inputFormat); // All formats used in this test suite are 32-bit based.
540 const VkBufferCreateInfo instanceRateBufferParams =
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;
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);
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);
562 // Create vertex buffer that stores the vertex number (from 0 to m_numVertices - 1)
564 m_vertexNumBufferSize = 128 * sizeof(deInt32); // Allocate enough device memory for all indices (0 to 127).
566 const VkBufferCreateInfo vertexNumBufferParams =
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;
578 m_vertexNumBuffer = createBuffer(vk, *m_device, &vertexNumBufferParams);
579 m_vertexNumBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, *m_device, *m_vertexNumBuffer), MemoryRequirement::HostVisible);
581 VK_CHECK(vk.bindBufferMemory(*m_device, *m_vertexNumBuffer, m_vertexNumBufferAlloc->getMemory(), m_vertexNumBufferAlloc->getOffset()));
584 // Create index buffer if required
585 if (!indices.empty())
587 m_indexBufferSize = sizeof(deUint32) * indices.size();
589 const VkBufferCreateInfo indexBufferParams =
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;
601 m_indexBuffer = createBuffer(vk, *m_device, &indexBufferParams);
602 m_indexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, *m_device, *m_indexBuffer), MemoryRequirement::HostVisible);
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);
609 // Create result ssbo
611 const int numChannels = getNumUsedChannels(mapVkFormat(m_inputFormat).order);
613 m_outBufferSize = getBufferSizeInBytes(m_numVertices * m_numInstances * numChannels * 3, VK_FORMAT_R32_UINT);
615 const VkBufferCreateInfo outBufferParams =
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;
627 m_outBuffer = createBuffer(vk, *m_device, &outBufferParams);
628 m_outBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, *m_device, *m_outBuffer), MemoryRequirement::HostVisible);
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);
635 // Create descriptor set data
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);
641 DescriptorSetLayoutBuilder setLayoutBuilder;
642 setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_VERTEX_BIT);
643 m_descriptorSetLayout = setLayoutBuilder.build(vk, *m_device);
645 const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo =
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;
654 m_descriptorSet = allocateDescriptorSet(vk, *m_device, &descriptorSetAllocateInfo);
656 const VkDescriptorBufferInfo outBufferDescriptorInfo = makeDescriptorBufferInfo(*m_outBuffer, 0ull, VK_WHOLE_SIZE);
658 DescriptorSetUpdateBuilder setUpdateBuilder;
659 setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &outBufferDescriptorInfo);
660 setUpdateBuilder.update(vk, *m_device);
665 const VkFenceCreateInfo fenceParams =
667 VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType;
668 DE_NULL, // const void* pNext;
669 0u // VkFenceCreateFlags flags;
672 m_fence = createFence(vk, *m_device, &fenceParams);
676 vk.getDeviceQueue(*m_device, queueFamilyIndex, 0, &m_queue);
678 // Setup graphics test environment
680 GraphicsEnvironment::DrawConfig drawConfig;
682 drawConfig.vertexBuffers.push_back(*m_vertexRateBuffer);
683 drawConfig.vertexBuffers.push_back(*m_instanceRateBuffer);
684 drawConfig.vertexBuffers.push_back(*m_vertexNumBuffer);
686 drawConfig.vertexCount = m_numVertices;
687 drawConfig.instanceCount = m_numInstances;
688 drawConfig.indexBuffer = *m_indexBuffer;
689 drawConfig.indexCount = (deUint32)(m_indexBufferSize / sizeof(deUint32));
691 m_graphicsTestEnvironment = de::MovePtr<GraphicsEnvironment>(new GraphicsEnvironment(m_context,
693 *m_descriptorSetLayout,
695 GraphicsEnvironment::VertexBindings(bindings, bindings + DE_LENGTH_OF_ARRAY(bindings)),
696 GraphicsEnvironment::VertexAttributes(attributes, attributes + DE_LENGTH_OF_ARRAY(attributes)),
701 tcu::TestStatus VertexAccessInstance::iterate (void)
703 const DeviceInterface& vk = m_context.getDeviceInterface();
704 const vk::VkCommandBuffer cmdBuffer = m_graphicsTestEnvironment->getCommandBuffer();
706 // Initialize vertex ids
708 deUint32 *bufferPtr = reinterpret_cast<deUint32*>(m_vertexNumBufferAlloc->getHostPtr());
709 deMemset(bufferPtr, 0, (size_t)m_vertexNumBufferSize);
711 initVertexIds(bufferPtr, (size_t)(m_vertexNumBufferSize / sizeof(deUint32)));
713 flushMappedMemoryRange(vk, *m_device, m_vertexNumBufferAlloc->getMemory(), m_vertexNumBufferAlloc->getOffset(), VK_WHOLE_SIZE);
716 // Submit command buffer
718 const VkSubmitInfo submitInfo =
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;
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 */));
736 // Prepare result buffer for read
738 const VkMappedMemoryRange outBufferRange =
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;
747 VK_CHECK(vk.invalidateMappedMemoryRanges(*m_device, 1u, &outBufferRange));
751 return tcu::TestStatus::pass("All values OK");
753 return tcu::TestStatus::fail("Invalid value(s) found");
756 bool VertexAccessInstance::verifyResult (void)
758 std::ostringstream logMsg;
759 const DeviceInterface& vk = m_context.getDeviceInterface();
760 tcu::TestLog& log = m_context.getTestContext().getLog();
761 const int numChannels = getNumUsedChannels(mapVkFormat(m_inputFormat).order);
762 const deUint32 numScalarsPerVertex = numChannels * 3; // Use 3 identical attributes
763 void* outDataPtr = m_outBufferAlloc->getHostPtr();
764 const deUint32 outValueSize = sizeof(deUint32);
767 const VkMappedMemoryRange outBufferRange =
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;
776 VK_CHECK(vk.invalidateMappedMemoryRanges(*m_device, 1u, &outBufferRange));
778 for (deUint32 valueNdx = 0; valueNdx < m_outBufferSize / outValueSize; valueNdx++)
780 deUint32 numInBufferValues;
782 VkDeviceSize inBufferAllocSize;
783 deUint32 inBufferValueIndex;
784 bool isOutOfBoundsAccess = false;
785 const bool isInstanceRateValue = ((valueNdx / numChannels) % 3 == 2);
786 const deUint32* outValuePtr = (deUint32*)outDataPtr + valueNdx;
788 if (isInstanceRateValue)
790 const deUint32 elementIndex = valueNdx / (numScalarsPerVertex * m_numVertices); // instance id
792 numInBufferValues = m_numInstanceValues;
793 inBufferPtr = m_instanceRateBufferAlloc->getHostPtr();
794 inBufferAllocSize = m_instanceRateBufferAllocSize;
795 inBufferValueIndex = (getIndex(elementIndex) * numChannels) + (valueNdx % numScalarsPerVertex) - (2 * numChannels);
799 const deUint32 vertexNdx = valueNdx / numScalarsPerVertex;
800 const deUint32 instanceNdx = vertexNdx / m_numVertices;
801 const deUint32 elementIndex = valueNdx / numScalarsPerVertex; // vertex id
803 numInBufferValues = m_numVertexValues;
804 inBufferPtr = m_vertexRateBufferAlloc->getHostPtr();
805 inBufferAllocSize = m_vertexRateBufferAllocSize;
806 inBufferValueIndex = (getIndex(elementIndex) * (numChannels * 2)) + (valueNdx % numScalarsPerVertex) - instanceNdx * (m_numVertices * numChannels * 2);
809 isOutOfBoundsAccess = (inBufferValueIndex >= numInBufferValues);
811 const deInt32 distanceToOutOfBounds = (deInt32)outValueSize * ((deInt32)numInBufferValues - (deInt32)inBufferValueIndex);
813 if (!isOutOfBoundsAccess && (distanceToOutOfBounds < 16))
814 isOutOfBoundsAccess = (((inBufferValueIndex / numChannels) + 1) * numChannels > numInBufferValues);
816 // Log value information
818 const deUint32 attributeIndex = (valueNdx % numScalarsPerVertex) / numChannels;
821 if (valueNdx && valueNdx % numScalarsPerVertex == 0)
824 logMsg << "\n" << valueNdx << ": Value ";
826 // Result index and value
827 if (m_inputFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
828 logValue(logMsg, outValuePtr, VK_FORMAT_R32_SFLOAT, 4);
830 logValue(logMsg, outValuePtr, m_inputFormat, 4);
833 logMsg << "\tfrom attr" << attributeIndex;
835 logMsg << "[" << valueNdx % numChannels << "]";
838 if (attributeIndex == 2)
839 logMsg << "\tinstance rate";
841 logMsg << "\tvertex rate";
844 if (isOutOfBoundsAccess)
846 const bool isValidValue = isValueWithinVertexBufferOrZero(inBufferPtr, inBufferAllocSize, outValuePtr, inBufferValueIndex);
848 logMsg << "\t(out of bounds)";
852 // Check if we are satisfying the [0, 0, 0, x] pattern, where x may be either 0 or 1,
853 // or the maximum representable positive integer value (if the format is integer-based).
855 const bool canMatchVec4Pattern = ((valueNdx % numChannels == 3) || m_inputFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32);
856 bool matchesVec4Pattern = false;
858 if (canMatchVec4Pattern)
860 if (m_inputFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
861 matchesVec4Pattern = verifyOutOfBoundsVec4(outValuePtr - 3, VK_FORMAT_R32G32B32_SFLOAT);
863 matchesVec4Pattern = verifyOutOfBoundsVec4(outValuePtr - 3, m_inputFormat);
866 if (!canMatchVec4Pattern || !matchesVec4Pattern)
868 logMsg << ", Failed: expected a value within the buffer range or 0";
870 if (canMatchVec4Pattern)
871 logMsg << ", or the [0, 0, 0, x] pattern";
877 else if (!isExpectedValueFromVertexBuffer(inBufferPtr, inBufferValueIndex, m_inputFormat, outValuePtr))
879 logMsg << ", Failed: unexpected value";
883 log << tcu::TestLog::Message << logMsg.str() << tcu::TestLog::EndMessage;
888 bool VertexAccessInstance::isValueWithinVertexBufferOrZero(void* vertexBuffer, VkDeviceSize vertexBufferSize, const void* value, deUint32 valueIndex)
890 if (m_inputFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
892 const float normValue = *reinterpret_cast<const float*>(value);
893 const deUint32 scalarIndex = valueIndex % 4;
894 const bool isAlpha = (scalarIndex == 3);
895 deUint32 encodedValue;
898 encodedValue = deMin32(deUint32(normValue * 0x3u), 0x3u);
900 encodedValue = deMin32(deUint32(normValue * 0x3FFu), 0x3FFu);
902 if (encodedValue == 0)
905 for (deUint32 i = 0; i < vertexBufferSize / 4; i++)
907 const deUint32 packedValue = reinterpret_cast<deUint32*>(vertexBuffer)[i];
908 deUint32 unpackedValue;
911 unpackedValue = (packedValue >> (10 * scalarIndex)) & 0x3FFu;
913 unpackedValue = (packedValue >> 30) & 0x3u;
915 if (unpackedValue == encodedValue)
923 return isValueWithinBufferOrZero(vertexBuffer, vertexBufferSize, value, sizeof(deUint32));
927 bool VertexAccessInstance::isExpectedValueFromVertexBuffer (const void* vertexBuffer, deUint32 vertexIndex, VkFormat vertexFormat, const void* value)
929 if (isUintFormat(vertexFormat))
931 const deUint32* bufferPtr = reinterpret_cast<const deUint32*>(vertexBuffer);
933 return bufferPtr[vertexIndex] == *reinterpret_cast<const deUint32 *>(value);
935 else if (isIntFormat(vertexFormat))
937 const deInt32* bufferPtr = reinterpret_cast<const deInt32*>(vertexBuffer);
939 return bufferPtr[vertexIndex] == *reinterpret_cast<const deInt32 *>(value);
941 else if (isFloatFormat(vertexFormat))
943 const float* bufferPtr = reinterpret_cast<const float*>(vertexBuffer);
945 return areEqual(bufferPtr[vertexIndex], *reinterpret_cast<const float *>(value));
947 else if (vertexFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
949 const deUint32* bufferPtr = reinterpret_cast<const deUint32*>(vertexBuffer);
950 const deUint32 packedValue = bufferPtr[vertexIndex / 4];
951 const deUint32 scalarIndex = vertexIndex % 4;
955 normValue = float((packedValue >> (10 * scalarIndex)) & 0x3FFu) / 0x3FFu;
957 normValue = float(packedValue >> 30) / 0x3u;
959 return areEqual(normValue, *reinterpret_cast<const float *>(value));
966 VkDeviceSize VertexAccessInstance::getBufferSizeInBytes (deUint32 numScalars, VkFormat format)
968 if (isUintFormat(format) || isIntFormat(format) || isFloatFormat(format))
970 return numScalars * 4;
972 else if (format == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
974 DE_ASSERT(numScalars % 4 == 0);
982 // DrawAccessInstance
984 DrawAccessInstance::DrawAccessInstance (Context& context,
985 Move<VkDevice> device,
986 VkFormat inputFormat,
987 deUint32 numVertexValues,
988 deUint32 numInstanceValues,
989 deUint32 numVertices,
990 deUint32 numInstances)
991 : VertexAccessInstance (context,
998 std::vector<deUint32>()) // No index buffer
1002 void DrawAccessInstance::initVertexIds (deUint32 *indicesPtr, size_t indexCount)
1004 for (deUint32 i = 0; i < indexCount; i++)
1008 deUint32 DrawAccessInstance::getIndex (deUint32 vertexNum) const
1013 // DrawIndexedAccessInstance
1015 DrawIndexedAccessInstance::DrawIndexedAccessInstance (Context& context,
1016 Move<VkDevice> device,
1017 VkFormat inputFormat,
1018 deUint32 numVertexValues,
1019 deUint32 numInstanceValues,
1020 deUint32 numVertices,
1021 deUint32 numInstances,
1022 const std::vector<deUint32>& indices)
1023 : VertexAccessInstance (context,
1031 , m_indices (indices)
1035 void DrawIndexedAccessInstance::initVertexIds (deUint32 *indicesPtr, size_t indexCount)
1037 DE_UNREF(indexCount);
1039 for (deUint32 i = 0; i < m_indices.size(); i++)
1041 DE_ASSERT(m_indices[i] < indexCount);
1043 indicesPtr[m_indices[i]] = i;
1047 deUint32 DrawIndexedAccessInstance::getIndex (deUint32 vertexNum) const
1049 DE_ASSERT(vertexNum < (deUint32)m_indices.size());
1051 return m_indices[vertexNum];
1054 // Test node creation functions
1056 static tcu::TestCaseGroup* createDrawTests (tcu::TestContext& testCtx, VkFormat format)
1061 std::string description;
1062 VkFormat inputFormat;
1063 deUint32 numVertexValues;
1064 deUint32 numInstanceValues;
1065 deUint32 numVertices;
1066 deUint32 numInstances;
1069 const deUint32 numChannels = getNumUsedChannels(mapVkFormat(format).order);
1071 const TestConfig testConfigs[] =
1073 // name description format numVertexValues numInstanceValues numVertices numInstances
1074 { "vertex_out_of_bounds", "Create data for 6 vertices, draw 9 vertices", format, numChannels * 2 * 6, numChannels, 9, 1 },
1075 { "vertex_incomplete", "Create data for half a vertex, draw 3 vertices", format, numChannels, numChannels, 3, 1 },
1076 { "instance_out_of_bounds", "Create data for 1 instance, draw 3 instances", format, numChannels * 2 * 9, numChannels, 3, 3 },
1079 de::MovePtr<tcu::TestCaseGroup> drawTests (new tcu::TestCaseGroup(testCtx, "draw", ""));
1081 for (int i = 0; i < DE_LENGTH_OF_ARRAY(testConfigs); i++)
1083 const TestConfig &config = testConfigs[i];
1085 drawTests->addChild(new DrawAccessTest(testCtx, config.name, config.description, config.inputFormat,
1086 config.numVertexValues, config.numInstanceValues,
1087 config.numVertices, config.numInstances));
1090 return drawTests.release();
1093 static tcu::TestCaseGroup* createDrawIndexedTests (tcu::TestContext& testCtx, VkFormat format)
1098 std::string description;
1099 VkFormat inputFormat;
1100 DrawIndexedAccessTest::IndexConfig indexConfig;
1103 const TestConfig testConfigs[] =
1105 // name description format indexConfig
1106 { "last_index_out_of_bounds", "Only last index is out of bounds", format, DrawIndexedAccessTest::INDEX_CONFIG_LAST_INDEX_OUT_OF_BOUNDS },
1107 { "indices_out_of_bounds", "Random indices out of bounds", format, DrawIndexedAccessTest::INDEX_CONFIG_INDICES_OUT_OF_BOUNDS },
1108 { "triangle_out_of_bounds", "First triangle is out of bounds", format, DrawIndexedAccessTest::INDEX_CONFIG_TRIANGLE_OUT_OF_BOUNDS },
1111 de::MovePtr<tcu::TestCaseGroup> drawTests (new tcu::TestCaseGroup(testCtx, "draw_indexed", ""));
1113 for (int i = 0; i < DE_LENGTH_OF_ARRAY(testConfigs); i++)
1115 const TestConfig &config = testConfigs[i];
1117 drawTests->addChild(new DrawIndexedAccessTest(testCtx, config.name, config.description, config.inputFormat, config.indexConfig));
1120 return drawTests.release();
1123 static void addVertexFormatTests (tcu::TestContext& testCtx, tcu::TestCaseGroup* parentGroup)
1125 const VkFormat vertexFormats[] =
1129 VK_FORMAT_R32_SFLOAT,
1130 VK_FORMAT_R32G32_UINT,
1131 VK_FORMAT_R32G32_SINT,
1132 VK_FORMAT_R32G32_SFLOAT,
1133 VK_FORMAT_R32G32B32_UINT,
1134 VK_FORMAT_R32G32B32_SINT,
1135 VK_FORMAT_R32G32B32_SFLOAT,
1136 VK_FORMAT_R32G32B32A32_UINT,
1137 VK_FORMAT_R32G32B32A32_SINT,
1138 VK_FORMAT_R32G32B32A32_SFLOAT,
1140 VK_FORMAT_A2B10G10R10_UNORM_PACK32
1143 for (int i = 0; i < DE_LENGTH_OF_ARRAY(vertexFormats); i++)
1145 const std::string formatName = getFormatName(vertexFormats[i]);
1146 de::MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx, de::toLower(formatName.substr(10)).c_str(), ""));
1148 formatGroup->addChild(createDrawTests(testCtx, vertexFormats[i]));
1149 formatGroup->addChild(createDrawIndexedTests(testCtx, vertexFormats[i]));
1151 parentGroup->addChild(formatGroup.release());
1155 tcu::TestCaseGroup* createVertexAccessTests (tcu::TestContext& testCtx)
1157 de::MovePtr<tcu::TestCaseGroup> vertexAccessTests (new tcu::TestCaseGroup(testCtx, "vertex_access", ""));
1159 addVertexFormatTests(testCtx, vertexAccessTests.get());
1161 return vertexAccessTests.release();