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"
33 #include "vkDeviceUtil.hpp"
35 #include "vkRefUtil.hpp"
36 #include "vkTypeUtil.hpp"
37 #include "tcuTestLog.hpp"
39 #include "deUniquePtr.hpp"
49 typedef std::vector<VkVertexInputBindingDescription> BindingList;
50 typedef std::vector<VkVertexInputAttributeDescription> AttributeList;
52 class VertexAccessTest : public vkt::TestCase
55 VertexAccessTest (tcu::TestContext& testContext,
56 const std::string& name,
57 const std::string& description,
59 deUint32 numVertexValues,
60 deUint32 numInstanceValues,
62 deUint32 numInstances);
64 virtual ~VertexAccessTest (void) {}
66 void initPrograms (SourceCollections& programCollection) const;
67 void checkSupport (Context& context) const;
68 TestInstance* createInstance (Context& context) const = 0;
71 const VkFormat m_inputFormat;
72 const deUint32 m_numVertexValues;
73 const deUint32 m_numInstanceValues;
74 const deUint32 m_numVertices;
75 const deUint32 m_numInstances;
79 class DrawAccessTest : public VertexAccessTest
82 DrawAccessTest (tcu::TestContext& testContext,
83 const std::string& name,
84 const std::string& description,
86 deUint32 numVertexValues,
87 deUint32 numInstanceValues,
89 deUint32 numInstances);
91 virtual ~DrawAccessTest (void) {}
92 TestInstance* createInstance (Context& context) const;
97 class DrawIndexedAccessTest : public VertexAccessTest
102 INDEX_CONFIG_LAST_INDEX_OUT_OF_BOUNDS,
103 INDEX_CONFIG_INDICES_OUT_OF_BOUNDS,
104 INDEX_CONFIG_TRIANGLE_OUT_OF_BOUNDS,
109 const static std::vector<deUint32> s_indexConfigs[INDEX_CONFIG_COUNT];
111 DrawIndexedAccessTest (tcu::TestContext& testContext,
112 const std::string& name,
113 const std::string& description,
114 VkFormat inputFormat,
115 IndexConfig indexConfig);
117 virtual ~DrawIndexedAccessTest (void) {}
118 TestInstance* createInstance (Context& context) const;
121 const IndexConfig m_indexConfig;
124 class VertexAccessInstance : public vkt::TestInstance
127 VertexAccessInstance (Context& context,
128 std::shared_ptr<CustomInstanceWrapper> instanceWrapper,
129 Move<VkDevice> device,
130 #ifndef CTS_USES_VULKANSC
131 de::MovePtr<vk::DeviceDriver> deviceDriver,
133 de::MovePtr<vk::DeviceDriverSC, vk::DeinitDeviceDeleter> deviceDriver,
134 #endif // CTS_USES_VULKANSC
135 VkFormat inputFormat,
136 deUint32 numVertexValues,
137 deUint32 numInstanceValues,
138 deUint32 numVertices,
139 deUint32 numInstances,
140 const std::vector<deUint32>& indices);
142 virtual ~VertexAccessInstance (void);
143 virtual tcu::TestStatus iterate (void);
144 virtual bool verifyResult (void);
147 bool isValueWithinVertexBufferOrZero (void* vertexBuffer, VkDeviceSize vertexBufferSize, const void* value, deUint32 valueIndexa);
150 static bool isExpectedValueFromVertexBuffer (const void* vertexBuffer, deUint32 vertexIndex, VkFormat vertexFormat, const void* value);
151 static VkDeviceSize getBufferSizeInBytes (deUint32 numScalars, VkFormat format);
153 virtual void initVertexIds (deUint32 *indicesPtr, size_t indexCount) = 0;
154 virtual deUint32 getIndex (deUint32 vertexNum) const = 0;
156 std::shared_ptr<CustomInstanceWrapper> m_instanceWrapper;
157 Move<VkDevice> m_device;
158 #ifndef CTS_USES_VULKANSC
159 de::MovePtr<vk::DeviceDriver> m_deviceDriver;
161 de::MovePtr<vk::DeviceDriverSC, vk::DeinitDeviceDeleter> m_deviceDriver;
162 #endif // CTS_USES_VULKANSC
164 const VkFormat m_inputFormat;
165 const deUint32 m_numVertexValues;
166 const deUint32 m_numInstanceValues;
167 const deUint32 m_numVertices;
168 const deUint32 m_numInstances;
169 AttributeList m_vertexInputAttributes;
170 BindingList m_vertexInputBindings;
172 Move<VkBuffer> m_vertexRateBuffer;
173 VkDeviceSize m_vertexRateBufferSize;
174 de::MovePtr<Allocation> m_vertexRateBufferAlloc;
175 VkDeviceSize m_vertexRateBufferAllocSize;
177 Move<VkBuffer> m_instanceRateBuffer;
178 VkDeviceSize m_instanceRateBufferSize;
179 de::MovePtr<Allocation> m_instanceRateBufferAlloc;
180 VkDeviceSize m_instanceRateBufferAllocSize;
182 Move<VkBuffer> m_vertexNumBuffer;
183 VkDeviceSize m_vertexNumBufferSize;
184 de::MovePtr<Allocation> m_vertexNumBufferAlloc;
186 Move<VkBuffer> m_indexBuffer;
187 VkDeviceSize m_indexBufferSize;
188 de::MovePtr<Allocation> m_indexBufferAlloc;
190 Move<VkBuffer> m_outBuffer; // SSBO
191 VkDeviceSize m_outBufferSize;
192 de::MovePtr<Allocation> m_outBufferAlloc;
193 VkDeviceSize m_outBufferAllocSize;
195 Move<VkDescriptorPool> m_descriptorPool;
196 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
197 Move<VkDescriptorSet> m_descriptorSet;
199 Move<VkFence> m_fence;
202 de::MovePtr<GraphicsEnvironment> m_graphicsTestEnvironment;
205 class DrawAccessInstance : public VertexAccessInstance
208 DrawAccessInstance (Context& context,
209 std::shared_ptr<CustomInstanceWrapper> instanceWrapper,
210 Move<VkDevice> device,
211 #ifndef CTS_USES_VULKANSC
212 de::MovePtr<vk::DeviceDriver> deviceDriver,
214 de::MovePtr<vk::DeviceDriverSC, vk::DeinitDeviceDeleter> deviceDriver,
215 #endif // CTS_USES_VULKANSC
216 VkFormat inputFormat,
217 deUint32 numVertexValues,
218 deUint32 numInstanceValues,
219 deUint32 numVertices,
220 deUint32 numInstances);
222 virtual ~DrawAccessInstance (void) {}
225 virtual void initVertexIds (deUint32 *indicesPtr, size_t indexCount);
226 virtual deUint32 getIndex (deUint32 vertexNum) const;
229 class DrawIndexedAccessInstance : public VertexAccessInstance
232 DrawIndexedAccessInstance (Context& context,
233 std::shared_ptr<CustomInstanceWrapper> instanceWrapper,
234 Move<VkDevice> device,
235 #ifndef CTS_USES_VULKANSC
236 de::MovePtr<vk::DeviceDriver> deviceDriver,
238 de::MovePtr<vk::DeviceDriverSC, vk::DeinitDeviceDeleter> deviceDriver,
239 #endif // CTS_USES_VULKANSC
240 VkFormat inputFormat,
241 deUint32 numVertexValues,
242 deUint32 numInstanceValues,
243 deUint32 numVertices,
244 deUint32 numInstances,
245 const std::vector<deUint32>& indices);
247 virtual ~DrawIndexedAccessInstance (void) {}
250 virtual void initVertexIds (deUint32 *indicesPtr, size_t indexCount);
251 virtual deUint32 getIndex (deUint32 vertexNum) const;
253 const std::vector<deUint32> m_indices;
258 VertexAccessTest::VertexAccessTest (tcu::TestContext& testContext,
259 const std::string& name,
260 const std::string& description,
261 VkFormat inputFormat,
262 deUint32 numVertexValues,
263 deUint32 numInstanceValues,
264 deUint32 numVertices,
265 deUint32 numInstances)
267 : vkt::TestCase (testContext, name, description)
268 , m_inputFormat (inputFormat)
269 , m_numVertexValues (numVertexValues)
270 , m_numInstanceValues (numInstanceValues)
271 , m_numVertices (numVertices)
272 , m_numInstances (numInstances)
277 void VertexAccessTest::checkSupport(Context& context) const
279 if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") && !context.getDeviceFeatures().robustBufferAccess)
280 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: robustBufferAccess not supported by this implementation");
283 void VertexAccessTest::initPrograms (SourceCollections& programCollection) const
285 std::ostringstream attributeDeclaration;
286 std::ostringstream attributeUse;
288 std::ostringstream vertexShaderSource;
289 std::ostringstream fragmentShaderSource;
291 std::ostringstream attributeTypeStr;
292 const int numChannels = getNumUsedChannels(mapVkFormat(m_inputFormat).order);
293 const deUint32 numScalarsPerVertex = numChannels * 3; // Use 3 identical attributes
294 deUint32 numValues = 0;
296 const bool isR64 = (m_inputFormat == VK_FORMAT_R64_UINT || m_inputFormat == VK_FORMAT_R64_SINT);
298 if (numChannels == 1)
300 if (isUintFormat(m_inputFormat))
301 attributeTypeStr << "uint";
302 else if (isIntFormat(m_inputFormat))
303 attributeTypeStr << "int";
305 attributeTypeStr << "float";
307 attributeTypeStr << (isR64 ? "64_t" : " ");
311 if (isUintFormat(m_inputFormat))
312 attributeTypeStr << "uvec";
313 else if (isIntFormat(m_inputFormat))
314 attributeTypeStr << "ivec";
316 attributeTypeStr << "vec";
318 attributeTypeStr << numChannels;
321 for (int attrNdx = 0; attrNdx < 3; attrNdx++)
323 attributeDeclaration << "layout(location = " << attrNdx << ") in " << attributeTypeStr.str() << " attr" << attrNdx << ";\n";
325 for (int chanNdx = 0; chanNdx < numChannels; chanNdx++)
327 attributeUse << "\toutData[(gl_InstanceIndex * " << numScalarsPerVertex * m_numVertices
328 << ") + (vertexNum * " << numScalarsPerVertex << " + " << numValues++ << ")] = attr" << attrNdx;
330 if (numChannels == 1)
331 attributeUse << ";\n";
333 attributeUse << "[" << chanNdx << "];\n";
337 attributeDeclaration << "layout(location = 3) in int vertexNum;\n";
339 attributeUse << "\n";
341 std::string outType = "";
342 if (isUintFormat(m_inputFormat))
344 else if (isIntFormat(m_inputFormat))
349 outType += isR64 ? "64_t" : "";
351 std::string extensions = "";
352 std::string version = "#version 310 es\n";
355 extensions = "#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require\n";
356 version = "#version 440\n";
359 vertexShaderSource <<
361 "precision highp float;\n"
363 << attributeDeclaration.str() <<
364 "layout(set = 0, binding = 0, std430) buffer outBuffer\n"
366 "\t" << outType << " outData[" << (m_numVertices * numValues) * m_numInstances << "];\n"
370 << attributeUse.str() <<
371 "\tgl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
374 programCollection.glslSources.add("vertex") << glu::VertexSource(vertexShaderSource.str());
376 fragmentShaderSource <<
378 "precision highp float;\n"
379 "layout(location = 0) out vec4 fragColor;\n"
382 "\tfragColor = vec4(1.0);\n"
385 programCollection.glslSources.add("fragment") << glu::FragmentSource(fragmentShaderSource.str());
390 DrawAccessTest::DrawAccessTest (tcu::TestContext& testContext,
391 const std::string& name,
392 const std::string& description,
393 VkFormat inputFormat,
394 deUint32 numVertexValues,
395 deUint32 numInstanceValues,
396 deUint32 numVertices,
397 deUint32 numInstances)
399 : VertexAccessTest (testContext, name, description, inputFormat, numVertexValues, numInstanceValues, numVertices, numInstances)
403 TestInstance* DrawAccessTest::createInstance (Context& context) const
405 std::shared_ptr<CustomInstanceWrapper> instanceWrapper(new CustomInstanceWrapper(context));
406 Move<VkDevice> device = createRobustBufferAccessDevice(context, instanceWrapper->instance, instanceWrapper->instance.getDriver());
407 #ifndef CTS_USES_VULKANSC
408 de::MovePtr<vk::DeviceDriver> deviceDriver = de::MovePtr<DeviceDriver>(new DeviceDriver(context.getPlatformInterface(), instanceWrapper->instance, *device));
410 de::MovePtr<vk::DeviceDriverSC, vk::DeinitDeviceDeleter> deviceDriver = de::MovePtr<DeviceDriverSC, DeinitDeviceDeleter>(new DeviceDriverSC(context.getPlatformInterface(), instanceWrapper->instance, *device, context.getTestContext().getCommandLine(), context.getResourceInterface(), context.getDeviceVulkanSC10Properties(), context.getDeviceProperties()), vk::DeinitDeviceDeleter(context.getResourceInterface().get(), *device));
411 #endif // CTS_USES_VULKANSC
413 return new DrawAccessInstance(context,
424 // DrawIndexedAccessTest
426 const deUint32 lastIndexOutOfBounds[] =
428 0, 1, 2, 3, 4, 100, // Indices of 100 and above are out of bounds
430 const deUint32 indicesOutOfBounds[] =
432 0, 100, 2, 101, 3, 102, // Indices of 100 and above are out of bounds
434 const deUint32 triangleOutOfBounds[] =
436 100, 101, 102, 3, 4, 5, // Indices of 100 and above are out of bounds
439 const std::vector<deUint32> DrawIndexedAccessTest::s_indexConfigs[INDEX_CONFIG_COUNT] =
441 std::vector<deUint32>(lastIndexOutOfBounds, lastIndexOutOfBounds + DE_LENGTH_OF_ARRAY(lastIndexOutOfBounds)),
442 std::vector<deUint32>(indicesOutOfBounds, indicesOutOfBounds + DE_LENGTH_OF_ARRAY(indicesOutOfBounds)),
443 std::vector<deUint32>(triangleOutOfBounds, triangleOutOfBounds + DE_LENGTH_OF_ARRAY(triangleOutOfBounds)),
446 DrawIndexedAccessTest::DrawIndexedAccessTest (tcu::TestContext& testContext,
447 const std::string& name,
448 const std::string& description,
449 VkFormat inputFormat,
450 IndexConfig indexConfig)
452 : VertexAccessTest (testContext,
456 getNumUsedChannels(mapVkFormat(inputFormat).order) * (deUint32)s_indexConfigs[indexConfig].size() * 2, // numVertexValues
457 getNumUsedChannels(mapVkFormat(inputFormat).order), // numInstanceValues
458 (deUint32)s_indexConfigs[indexConfig].size(), // numVertices
460 , m_indexConfig (indexConfig)
464 TestInstance* DrawIndexedAccessTest::createInstance (Context& context) const
466 std::shared_ptr<CustomInstanceWrapper> instanceWrapper(new CustomInstanceWrapper(context));
467 Move<VkDevice> device = createRobustBufferAccessDevice(context, instanceWrapper->instance, instanceWrapper->instance.getDriver());
468 #ifndef CTS_USES_VULKANSC
469 de::MovePtr<vk::DeviceDriver> deviceDriver = de::MovePtr<DeviceDriver>(new DeviceDriver(context.getPlatformInterface(), instanceWrapper->instance, *device));
471 de::MovePtr<vk::DeviceDriverSC, vk::DeinitDeviceDeleter> deviceDriver = de::MovePtr<DeviceDriverSC, DeinitDeviceDeleter>(new DeviceDriverSC(context.getPlatformInterface(), instanceWrapper->instance, *device, context.getTestContext().getCommandLine(), context.getResourceInterface(), context.getDeviceVulkanSC10Properties(), context.getDeviceProperties()), vk::DeinitDeviceDeleter(context.getResourceInterface().get(), *device));
472 #endif // CTS_USES_VULKANSC
474 return new DrawIndexedAccessInstance(context,
483 s_indexConfigs[m_indexConfig]);
486 // VertexAccessInstance
488 VertexAccessInstance::VertexAccessInstance (Context& context,
489 std::shared_ptr<CustomInstanceWrapper> instanceWrapper,
490 Move<VkDevice> device,
491 #ifndef CTS_USES_VULKANSC
492 de::MovePtr<vk::DeviceDriver> deviceDriver,
494 de::MovePtr<vk::DeviceDriverSC, vk::DeinitDeviceDeleter> deviceDriver,
495 #endif // CTS_USES_VULKANSC
496 VkFormat inputFormat,
497 deUint32 numVertexValues,
498 deUint32 numInstanceValues,
499 deUint32 numVertices,
500 deUint32 numInstances,
501 const std::vector<deUint32>& indices)
503 : vkt::TestInstance (context)
504 , m_instanceWrapper (instanceWrapper)
506 , m_deviceDriver (deviceDriver)
507 , m_inputFormat (inputFormat)
508 , m_numVertexValues (numVertexValues)
509 , m_numInstanceValues (numInstanceValues)
510 , m_numVertices (numVertices)
511 , m_numInstances (numInstances)
513 const DeviceInterface& vk = *m_deviceDriver;
514 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
515 const VkPhysicalDevice physicalDevice = chooseDevice(instanceWrapper->instance.getDriver(), instanceWrapper->instance, context.getTestContext().getCommandLine());
516 SimpleAllocator memAlloc (vk, *m_device, getPhysicalDeviceMemoryProperties(instanceWrapper->instance.getDriver(), physicalDevice));
517 const deUint32 formatSizeInBytes = tcu::getPixelSize(mapVkFormat(m_inputFormat));
519 // Check storage support
520 if (!context.getDeviceFeatures().vertexPipelineStoresAndAtomics)
522 TCU_THROW(NotSupportedError, "Stores not supported in vertex stage");
525 if (m_inputFormat == VK_FORMAT_R64_UINT || m_inputFormat == VK_FORMAT_R64_SINT)
527 const VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(instanceWrapper->instance.getDriver(), physicalDevice, m_inputFormat);
528 context.requireDeviceFunctionality("VK_EXT_shader_image_atomic_int64");
530 if ((formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) != VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)
531 TCU_THROW(NotSupportedError, "VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT not supported");
535 const VkVertexInputAttributeDescription attributes[] =
537 // input rate: vertex
539 0u, // deUint32 location;
540 0u, // deUint32 binding;
541 m_inputFormat, // VkFormat format;
542 0u, // deUint32 offset;
545 1u, // deUint32 location;
546 0u, // deUint32 binding;
547 m_inputFormat, // VkFormat format;
548 formatSizeInBytes, // deUint32 offset;
551 // input rate: instance
553 2u, // deUint32 location;
554 1u, // deUint32 binding;
555 m_inputFormat, // VkFormat format;
556 0u, // deUint32 offset;
559 // Attribute for vertex number
561 3u, // deUint32 location;
562 2u, // deUint32 binding;
563 VK_FORMAT_R32_SINT, // VkFormat format;
564 0, // deUint32 offset;
568 const VkVertexInputBindingDescription bindings[] =
571 0u, // deUint32 binding;
572 formatSizeInBytes * 2, // deUint32 stride;
573 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate inputRate;
576 1u, // deUint32 binding;
577 formatSizeInBytes, // deUint32 stride;
578 VK_VERTEX_INPUT_RATE_INSTANCE // VkVertexInputRate inputRate;
581 2u, // deUint32 binding;
582 sizeof(deInt32), // deUint32 stride;
583 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate inputRate;
587 m_vertexInputBindings = std::vector<VkVertexInputBindingDescription>(bindings, bindings + DE_LENGTH_OF_ARRAY(bindings));
588 m_vertexInputAttributes = std::vector<VkVertexInputAttributeDescription>(attributes, attributes + DE_LENGTH_OF_ARRAY(attributes));
590 // Create vertex buffer for vertex input rate
592 VkMemoryRequirements bufferMemoryReqs;
594 m_vertexRateBufferSize = getBufferSizeInBytes(m_numVertexValues, m_inputFormat); // All formats used in this test suite are 32-bit based.
596 const VkBufferCreateInfo vertexRateBufferParams =
598 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
599 DE_NULL, // const void* pNext;
600 0u, // VkBufferCreateFlags flags;
601 m_vertexRateBufferSize, // VkDeviceSize size;
602 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
603 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
604 1u, // deUint32 queueFamilyIndexCount;
605 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
608 m_vertexRateBuffer = createBuffer(vk, *m_device, &vertexRateBufferParams);
609 bufferMemoryReqs = getBufferMemoryRequirements(vk, *m_device, *m_vertexRateBuffer);
610 m_vertexRateBufferAllocSize = bufferMemoryReqs.size;
611 m_vertexRateBufferAlloc = memAlloc.allocate(bufferMemoryReqs, MemoryRequirement::HostVisible);
613 VK_CHECK(vk.bindBufferMemory(*m_device, *m_vertexRateBuffer, m_vertexRateBufferAlloc->getMemory(), m_vertexRateBufferAlloc->getOffset()));
614 populateBufferWithTestValues(m_vertexRateBufferAlloc->getHostPtr(), (deUint32)m_vertexRateBufferAllocSize, m_inputFormat);
615 flushMappedMemoryRange(vk, *m_device, m_vertexRateBufferAlloc->getMemory(), m_vertexRateBufferAlloc->getOffset(), VK_WHOLE_SIZE);
618 // Create vertex buffer for instance input rate
620 VkMemoryRequirements bufferMemoryReqs;
622 m_instanceRateBufferSize = getBufferSizeInBytes(m_numInstanceValues, m_inputFormat); // All formats used in this test suite are 32-bit based.
624 const VkBufferCreateInfo instanceRateBufferParams =
626 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
627 DE_NULL, // const void* pNext;
628 0u, // VkBufferCreateFlags flags;
629 m_instanceRateBufferSize, // VkDeviceSize size;
630 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
631 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
632 1u, // deUint32 queueFamilyIndexCount;
633 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
636 m_instanceRateBuffer = createBuffer(vk, *m_device, &instanceRateBufferParams);
637 bufferMemoryReqs = getBufferMemoryRequirements(vk, *m_device, *m_instanceRateBuffer);
638 m_instanceRateBufferAllocSize = bufferMemoryReqs.size;
639 m_instanceRateBufferAlloc = memAlloc.allocate(bufferMemoryReqs, MemoryRequirement::HostVisible);
641 VK_CHECK(vk.bindBufferMemory(*m_device, *m_instanceRateBuffer, m_instanceRateBufferAlloc->getMemory(), m_instanceRateBufferAlloc->getOffset()));
642 populateBufferWithTestValues(m_instanceRateBufferAlloc->getHostPtr(), (deUint32)m_instanceRateBufferAllocSize, m_inputFormat);
643 flushMappedMemoryRange(vk, *m_device, m_instanceRateBufferAlloc->getMemory(), m_instanceRateBufferAlloc->getOffset(), VK_WHOLE_SIZE);
646 // Create vertex buffer that stores the vertex number (from 0 to m_numVertices - 1)
648 m_vertexNumBufferSize = 128 * sizeof(deInt32); // Allocate enough device memory for all indices (0 to 127).
650 const VkBufferCreateInfo vertexNumBufferParams =
652 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
653 DE_NULL, // const void* pNext;
654 0u, // VkBufferCreateFlags flags;
655 m_vertexNumBufferSize, // VkDeviceSize size;
656 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
657 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
658 1u, // deUint32 queueFamilyIndexCount;
659 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
662 m_vertexNumBuffer = createBuffer(vk, *m_device, &vertexNumBufferParams);
663 m_vertexNumBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, *m_device, *m_vertexNumBuffer), MemoryRequirement::HostVisible);
665 VK_CHECK(vk.bindBufferMemory(*m_device, *m_vertexNumBuffer, m_vertexNumBufferAlloc->getMemory(), m_vertexNumBufferAlloc->getOffset()));
668 // Create index buffer if required
669 if (!indices.empty())
671 m_indexBufferSize = sizeof(deUint32) * indices.size();
673 const VkBufferCreateInfo indexBufferParams =
675 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
676 DE_NULL, // const void* pNext;
677 0u, // VkBufferCreateFlags flags;
678 m_indexBufferSize, // VkDeviceSize size;
679 VK_BUFFER_USAGE_INDEX_BUFFER_BIT, // VkBufferUsageFlags usage;
680 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
681 1u, // deUint32 queueFamilyIndexCount;
682 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
685 m_indexBuffer = createBuffer(vk, *m_device, &indexBufferParams);
686 m_indexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, *m_device, *m_indexBuffer), MemoryRequirement::HostVisible);
688 VK_CHECK(vk.bindBufferMemory(*m_device, *m_indexBuffer, m_indexBufferAlloc->getMemory(), m_indexBufferAlloc->getOffset()));
689 deMemcpy(m_indexBufferAlloc->getHostPtr(), indices.data(), (size_t)m_indexBufferSize);
690 flushMappedMemoryRange(vk, *m_device, m_indexBufferAlloc->getMemory(), m_indexBufferAlloc->getOffset(), VK_WHOLE_SIZE);
693 // Create result ssbo
695 const int numChannels = getNumUsedChannels(mapVkFormat(m_inputFormat).order);
697 m_outBufferSize = getBufferSizeInBytes(m_numVertices * m_numInstances * numChannels * 3, VK_FORMAT_R32_UINT);
699 const VkBufferCreateInfo outBufferParams =
701 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
702 DE_NULL, // const void* pNext;
703 0u, // VkBufferCreateFlags flags;
704 m_outBufferSize, // VkDeviceSize size;
705 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, // VkBufferUsageFlags usage;
706 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
707 1u, // deUint32 queueFamilyIndexCount;
708 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
711 m_outBuffer = createBuffer(vk, *m_device, &outBufferParams);
712 const VkMemoryRequirements requirements = getBufferMemoryRequirements(vk, *m_device, *m_outBuffer);
713 m_outBufferAlloc = memAlloc.allocate(requirements, MemoryRequirement::HostVisible);
714 m_outBufferAllocSize = requirements.size;
716 VK_CHECK(vk.bindBufferMemory(*m_device, *m_outBuffer, m_outBufferAlloc->getMemory(), m_outBufferAlloc->getOffset()));
717 deMemset(m_outBufferAlloc->getHostPtr(), 0xFF, (size_t)m_outBufferSize);
718 flushMappedMemoryRange(vk, *m_device, m_outBufferAlloc->getMemory(), m_outBufferAlloc->getOffset(), VK_WHOLE_SIZE);
721 // Create descriptor set data
723 DescriptorPoolBuilder descriptorPoolBuilder;
724 descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u);
725 m_descriptorPool = descriptorPoolBuilder.build(vk, *m_device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
727 DescriptorSetLayoutBuilder setLayoutBuilder;
728 setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_VERTEX_BIT);
729 m_descriptorSetLayout = setLayoutBuilder.build(vk, *m_device);
731 const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo =
733 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType;
734 DE_NULL, // const void* pNext;
735 *m_descriptorPool, // VkDescriptorPool desciptorPool;
736 1u, // deUint32 setLayoutCount;
737 &m_descriptorSetLayout.get() // const VkDescriptorSetLayout* pSetLayouts;
740 m_descriptorSet = allocateDescriptorSet(vk, *m_device, &descriptorSetAllocateInfo);
742 const VkDescriptorBufferInfo outBufferDescriptorInfo = makeDescriptorBufferInfo(*m_outBuffer, 0ull, VK_WHOLE_SIZE);
744 DescriptorSetUpdateBuilder setUpdateBuilder;
745 setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &outBufferDescriptorInfo);
746 setUpdateBuilder.update(vk, *m_device);
751 const VkFenceCreateInfo fenceParams =
753 VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType;
754 DE_NULL, // const void* pNext;
755 0u // VkFenceCreateFlags flags;
758 m_fence = createFence(vk, *m_device, &fenceParams);
762 vk.getDeviceQueue(*m_device, queueFamilyIndex, 0, &m_queue);
764 // Setup graphics test environment
766 GraphicsEnvironment::DrawConfig drawConfig;
768 drawConfig.vertexBuffers.push_back(*m_vertexRateBuffer);
769 drawConfig.vertexBuffers.push_back(*m_instanceRateBuffer);
770 drawConfig.vertexBuffers.push_back(*m_vertexNumBuffer);
772 drawConfig.vertexCount = m_numVertices;
773 drawConfig.instanceCount = m_numInstances;
774 drawConfig.indexBuffer = *m_indexBuffer;
775 drawConfig.indexCount = (deUint32)(m_indexBufferSize / sizeof(deUint32));
777 m_graphicsTestEnvironment = de::MovePtr<GraphicsEnvironment>(new GraphicsEnvironment(m_context,
778 m_instanceWrapper->instance,
779 m_instanceWrapper->instance.getDriver(),
781 *m_descriptorSetLayout,
783 GraphicsEnvironment::VertexBindings(bindings, bindings + DE_LENGTH_OF_ARRAY(bindings)),
784 GraphicsEnvironment::VertexAttributes(attributes, attributes + DE_LENGTH_OF_ARRAY(attributes)),
789 VertexAccessInstance::~VertexAccessInstance(void)
793 tcu::TestStatus VertexAccessInstance::iterate (void)
795 const DeviceInterface& vk = *m_deviceDriver;
796 const vk::VkCommandBuffer cmdBuffer = m_graphicsTestEnvironment->getCommandBuffer();
798 // Initialize vertex ids
800 deUint32 *bufferPtr = reinterpret_cast<deUint32*>(m_vertexNumBufferAlloc->getHostPtr());
801 deMemset(bufferPtr, 0, (size_t)m_vertexNumBufferSize);
803 initVertexIds(bufferPtr, (size_t)(m_vertexNumBufferSize / sizeof(deUint32)));
805 flushMappedMemoryRange(vk, *m_device, m_vertexNumBufferAlloc->getMemory(), m_vertexNumBufferAlloc->getOffset(), VK_WHOLE_SIZE);
808 // Submit command buffer
810 const VkSubmitInfo submitInfo =
812 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
813 DE_NULL, // const void* pNext;
814 0u, // deUint32 waitSemaphoreCount;
815 DE_NULL, // const VkSemaphore* pWaitSemaphores;
816 DE_NULL, // const VkPIpelineStageFlags* pWaitDstStageMask;
817 1u, // deUint32 commandBufferCount;
818 &cmdBuffer, // const VkCommandBuffer* pCommandBuffers;
819 0u, // deUint32 signalSemaphoreCount;
820 DE_NULL // const VkSemaphore* pSignalSemaphores;
823 VK_CHECK(vk.resetFences(*m_device, 1, &m_fence.get()));
824 VK_CHECK(vk.queueSubmit(m_queue, 1, &submitInfo, *m_fence));
825 VK_CHECK(vk.waitForFences(*m_device, 1, &m_fence.get(), true, ~(0ull) /* infinity */));
828 // Prepare result buffer for read
830 const VkMappedMemoryRange outBufferRange =
832 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType;
833 DE_NULL, // const void* pNext;
834 m_outBufferAlloc->getMemory(), // VkDeviceMemory mem;
835 0ull, // VkDeviceSize offset;
836 m_outBufferAllocSize, // VkDeviceSize size;
839 VK_CHECK(vk.invalidateMappedMemoryRanges(*m_device, 1u, &outBufferRange));
843 return tcu::TestStatus::pass("All values OK");
845 return tcu::TestStatus::fail("Invalid value(s) found");
848 bool VertexAccessInstance::verifyResult (void)
850 std::ostringstream logMsg;
851 const DeviceInterface& vk = *m_deviceDriver;
852 tcu::TestLog& log = m_context.getTestContext().getLog();
853 const deUint32 numChannels = getNumUsedChannels(mapVkFormat(m_inputFormat).order);
854 const deUint32 numScalarsPerVertex = numChannels * 3; // Use 3 identical attributes
855 void* outDataPtr = m_outBufferAlloc->getHostPtr();
856 const deUint32 outValueSize = static_cast<deUint32>((m_inputFormat == VK_FORMAT_R64_UINT || m_inputFormat == VK_FORMAT_R64_SINT)
857 ? sizeof(deUint64) : sizeof(deUint32));
860 const VkMappedMemoryRange outBufferRange =
862 VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // VkStructureType sType;
863 DE_NULL, // const void* pNext;
864 m_outBufferAlloc->getMemory(), // VkDeviceMemory mem;
865 m_outBufferAlloc->getOffset(), // VkDeviceSize offset;
866 m_outBufferAllocSize, // VkDeviceSize size;
869 VK_CHECK(vk.invalidateMappedMemoryRanges(*m_device, 1u, &outBufferRange));
871 for (deUint32 valueNdx = 0; valueNdx < m_outBufferSize / outValueSize; valueNdx++)
873 deUint32 numInBufferValues;
875 VkDeviceSize inBufferAllocSize;
876 deUint32 inBufferValueIndex;
877 bool isOutOfBoundsAccess = false;
878 const deUint32 attributeIndex = (valueNdx / numChannels) % 3;
879 deUint32* ptr32 = (deUint32*)outDataPtr;
880 deUint64* ptr64 = (deUint64*)outDataPtr;
881 const void* outValuePtr = ((m_inputFormat == VK_FORMAT_R64_UINT || m_inputFormat == VK_FORMAT_R64_SINT) ?
882 (void*)(ptr64 + valueNdx) :
883 (void*)(ptr32 + valueNdx));
885 if (attributeIndex == 2)
888 const deUint32 elementIndex = valueNdx / (numScalarsPerVertex * m_numVertices); // instance id
890 numInBufferValues = m_numInstanceValues;
891 inBufferPtr = m_instanceRateBufferAlloc->getHostPtr();
892 inBufferAllocSize = m_instanceRateBufferAllocSize;
893 inBufferValueIndex = (elementIndex * numChannels) + (valueNdx % numScalarsPerVertex) - (2 * numChannels);
898 const deUint32 vertexNdx = valueNdx / numScalarsPerVertex;
899 const deUint32 instanceNdx = vertexNdx / m_numVertices;
900 const deUint32 elementIndex = valueNdx / numScalarsPerVertex; // vertex id
902 numInBufferValues = m_numVertexValues;
903 inBufferPtr = m_vertexRateBufferAlloc->getHostPtr();
904 inBufferAllocSize = m_vertexRateBufferAllocSize;
905 inBufferValueIndex = (getIndex(elementIndex) * (numChannels * 2)) + (valueNdx % numScalarsPerVertex) - instanceNdx * (m_numVertices * numChannels * 2);
907 // 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.
908 if ((attributeIndex == 0) && (numInBufferValues >= numChannels))
909 numInBufferValues -= numChannels;
912 isOutOfBoundsAccess = (inBufferValueIndex >= numInBufferValues);
914 const deInt32 distanceToOutOfBounds = (deInt32)outValueSize * ((deInt32)numInBufferValues - (deInt32)inBufferValueIndex);
916 if (!isOutOfBoundsAccess && (distanceToOutOfBounds < 16))
917 isOutOfBoundsAccess = (((inBufferValueIndex / numChannels) + 1) * numChannels > numInBufferValues);
919 // Log value information
922 if (valueNdx && valueNdx % numScalarsPerVertex == 0)
925 logMsg << "\n" << valueNdx << ": Value ";
927 // Result index and value
928 if (m_inputFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
929 logValue(logMsg, outValuePtr, VK_FORMAT_R32_SFLOAT, 4);
931 logValue(logMsg, outValuePtr, m_inputFormat, 4);
934 logMsg << "\tfrom attr" << attributeIndex;
936 logMsg << "[" << valueNdx % numChannels << "]";
939 if (attributeIndex == 2)
940 logMsg << "\tinstance rate";
942 logMsg << "\tvertex rate";
945 if (isOutOfBoundsAccess)
947 const bool isValidValue = isValueWithinVertexBufferOrZero(inBufferPtr, inBufferAllocSize, outValuePtr, inBufferValueIndex);
949 logMsg << "\t(out of bounds)";
953 // Check if we are satisfying the [0, 0, 0, x] pattern, where x may be either 0 or 1,
954 // or the maximum representable positive integer value (if the format is integer-based).
956 const bool canMatchVec4Pattern = ((valueNdx % numChannels == 3) || m_inputFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32);
957 bool matchesVec4Pattern = false;
959 if (canMatchVec4Pattern)
961 if (m_inputFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
962 matchesVec4Pattern = verifyOutOfBoundsVec4(outValuePtr, m_inputFormat);
964 matchesVec4Pattern = verifyOutOfBoundsVec4(((deUint32*)outValuePtr) - 3, m_inputFormat);
967 if (!canMatchVec4Pattern || !matchesVec4Pattern)
969 logMsg << ", Failed: expected a value within the buffer range or 0";
971 if (canMatchVec4Pattern)
972 logMsg << ", or the [0, 0, 0, x] pattern";
978 else if (!isExpectedValueFromVertexBuffer(inBufferPtr, inBufferValueIndex, m_inputFormat, outValuePtr))
980 logMsg << ", Failed: unexpected value";
984 log << tcu::TestLog::Message << logMsg.str() << tcu::TestLog::EndMessage;
989 bool VertexAccessInstance::isValueWithinVertexBufferOrZero(void* vertexBuffer, VkDeviceSize vertexBufferSize, const void* value, deUint32 valueIndex)
991 if (m_inputFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
993 const float normValue = *reinterpret_cast<const float*>(value);
994 const deUint32 scalarIndex = valueIndex % 4;
995 const bool isAlpha = (scalarIndex == 3);
996 deUint32 encodedValue;
999 encodedValue = deMin32(deUint32(deFloatRound(normValue * 0x3u)), 0x3u);
1001 encodedValue = deMin32(deUint32(deFloatRound(normValue * 0x3FFu)), 0x3FFu);
1003 if (encodedValue == 0)
1006 for (deUint32 i = 0; i < vertexBufferSize / 4; i++)
1008 const deUint32 packedValue = reinterpret_cast<deUint32*>(vertexBuffer)[i];
1009 deUint32 unpackedValue;
1011 if (scalarIndex < 3)
1012 unpackedValue = (packedValue >> (10 * scalarIndex)) & 0x3FFu;
1014 unpackedValue = (packedValue >> 30) & 0x3u;
1016 if (unpackedValue == encodedValue)
1024 return isValueWithinBufferOrZero(vertexBuffer, vertexBufferSize, value, sizeof(deUint32));
1028 bool VertexAccessInstance::isExpectedValueFromVertexBuffer (const void* vertexBuffer, deUint32 vertexIndex, VkFormat vertexFormat, const void* value)
1030 if (isUintFormat(vertexFormat))
1032 if (vertexFormat == VK_FORMAT_R64_UINT || vertexFormat == VK_FORMAT_R64_SINT)
1034 const deUint64* bufferPtr = reinterpret_cast<const deUint64*>(vertexBuffer);
1035 return bufferPtr[vertexIndex] == *reinterpret_cast<const deUint64 *>(value);
1039 const deUint32* bufferPtr = reinterpret_cast<const deUint32*>(vertexBuffer);
1040 return bufferPtr[vertexIndex] == *reinterpret_cast<const deUint32 *>(value);
1043 else if (isIntFormat(vertexFormat))
1045 if (vertexFormat == VK_FORMAT_R64_UINT || vertexFormat == VK_FORMAT_R64_SINT)
1047 const deInt64* bufferPtr = reinterpret_cast<const deInt64*>(vertexBuffer);
1048 return bufferPtr[vertexIndex] == *reinterpret_cast<const deInt64 *>(value);
1052 const deInt32* bufferPtr = reinterpret_cast<const deInt32*>(vertexBuffer);
1053 return bufferPtr[vertexIndex] == *reinterpret_cast<const deInt32 *>(value);
1056 else if (isFloatFormat(vertexFormat))
1058 const float* bufferPtr = reinterpret_cast<const float*>(vertexBuffer);
1060 return areEqual(bufferPtr[vertexIndex], *reinterpret_cast<const float *>(value));
1062 else if (vertexFormat == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
1064 const deUint32* bufferPtr = reinterpret_cast<const deUint32*>(vertexBuffer);
1065 const deUint32 packedValue = bufferPtr[vertexIndex / 4];
1066 const deUint32 scalarIndex = vertexIndex % 4;
1069 if (scalarIndex < 3)
1070 normValue = float((packedValue >> (10 * scalarIndex)) & 0x3FFu) / 0x3FFu;
1072 normValue = float(packedValue >> 30) / 0x3u;
1074 return areEqual(normValue, *reinterpret_cast<const float *>(value));
1081 VkDeviceSize VertexAccessInstance::getBufferSizeInBytes (deUint32 numScalars, VkFormat format)
1083 if (isUintFormat(format) || isIntFormat(format) || isFloatFormat(format))
1085 return numScalars * ((format == VK_FORMAT_R64_UINT || format == VK_FORMAT_R64_SINT) ? 8 : 4);
1087 else if (format == VK_FORMAT_A2B10G10R10_UNORM_PACK32)
1089 DE_ASSERT(numScalars % 4 == 0);
1097 // DrawAccessInstance
1099 DrawAccessInstance::DrawAccessInstance (Context& context,
1100 std::shared_ptr<CustomInstanceWrapper> instanceWrapper,
1101 Move<VkDevice> device,
1102 #ifndef CTS_USES_VULKANSC
1103 de::MovePtr<vk::DeviceDriver> deviceDriver,
1105 de::MovePtr<vk::DeviceDriverSC, vk::DeinitDeviceDeleter> deviceDriver,
1106 #endif // CTS_USES_VULKANSC
1107 VkFormat inputFormat,
1108 deUint32 numVertexValues,
1109 deUint32 numInstanceValues,
1110 deUint32 numVertices,
1111 deUint32 numInstances)
1112 : VertexAccessInstance (context,
1121 std::vector<deUint32>()) // No index buffer
1125 void DrawAccessInstance::initVertexIds (deUint32 *indicesPtr, size_t indexCount)
1127 for (deUint32 i = 0; i < indexCount; i++)
1131 deUint32 DrawAccessInstance::getIndex (deUint32 vertexNum) const
1136 // DrawIndexedAccessInstance
1138 DrawIndexedAccessInstance::DrawIndexedAccessInstance (Context& context,
1139 std::shared_ptr<CustomInstanceWrapper> instanceWrapper,
1140 Move<VkDevice> device,
1141 #ifndef CTS_USES_VULKANSC
1142 de::MovePtr<vk::DeviceDriver> deviceDriver,
1144 de::MovePtr<vk::DeviceDriverSC, vk::DeinitDeviceDeleter> deviceDriver,
1145 #endif // CTS_USES_VULKANSC
1146 VkFormat inputFormat,
1147 deUint32 numVertexValues,
1148 deUint32 numInstanceValues,
1149 deUint32 numVertices,
1150 deUint32 numInstances,
1151 const std::vector<deUint32>& indices)
1152 : VertexAccessInstance (context,
1162 , m_indices (indices)
1166 void DrawIndexedAccessInstance::initVertexIds (deUint32 *indicesPtr, size_t indexCount)
1168 DE_UNREF(indexCount);
1170 for (deUint32 i = 0; i < m_indices.size(); i++)
1172 DE_ASSERT(m_indices[i] < indexCount);
1174 indicesPtr[m_indices[i]] = i;
1178 deUint32 DrawIndexedAccessInstance::getIndex (deUint32 vertexNum) const
1180 DE_ASSERT(vertexNum < (deUint32)m_indices.size());
1182 return m_indices[vertexNum];
1185 // Test node creation functions
1187 static tcu::TestCaseGroup* createDrawTests (tcu::TestContext& testCtx, VkFormat format)
1192 std::string description;
1193 VkFormat inputFormat;
1194 deUint32 numVertexValues;
1195 deUint32 numInstanceValues;
1196 deUint32 numVertices;
1197 deUint32 numInstances;
1200 const deUint32 numChannels = getNumUsedChannels(mapVkFormat(format).order);
1202 const TestConfig testConfigs[] =
1204 // name description format numVertexValues numInstanceValues numVertices numInstances
1205 { "vertex_out_of_bounds", "Create data for 6 vertices, draw 9 vertices", format, numChannels * 2 * 6, numChannels, 9, 1 },
1206 { "vertex_incomplete", "Create data for half a vertex, draw 3 vertices", format, numChannels, numChannels, 3, 1 },
1207 { "instance_out_of_bounds", "Create data for 1 instance, draw 3 instances", format, numChannels * 2 * 9, numChannels, 3, 3 },
1210 de::MovePtr<tcu::TestCaseGroup> drawTests (new tcu::TestCaseGroup(testCtx, "draw", ""));
1212 for (int i = 0; i < DE_LENGTH_OF_ARRAY(testConfigs); i++)
1214 const TestConfig &config = testConfigs[i];
1216 drawTests->addChild(new DrawAccessTest(testCtx, config.name, config.description, config.inputFormat,
1217 config.numVertexValues, config.numInstanceValues,
1218 config.numVertices, config.numInstances));
1221 return drawTests.release();
1224 static tcu::TestCaseGroup* createDrawIndexedTests (tcu::TestContext& testCtx, VkFormat format)
1229 std::string description;
1230 VkFormat inputFormat;
1231 DrawIndexedAccessTest::IndexConfig indexConfig;
1234 const TestConfig testConfigs[] =
1236 // name description format indexConfig
1237 { "last_index_out_of_bounds", "Only last index is out of bounds", format, DrawIndexedAccessTest::INDEX_CONFIG_LAST_INDEX_OUT_OF_BOUNDS },
1238 { "indices_out_of_bounds", "Random indices out of bounds", format, DrawIndexedAccessTest::INDEX_CONFIG_INDICES_OUT_OF_BOUNDS },
1239 { "triangle_out_of_bounds", "First triangle is out of bounds", format, DrawIndexedAccessTest::INDEX_CONFIG_TRIANGLE_OUT_OF_BOUNDS },
1242 de::MovePtr<tcu::TestCaseGroup> drawTests (new tcu::TestCaseGroup(testCtx, "draw_indexed", ""));
1244 for (int i = 0; i < DE_LENGTH_OF_ARRAY(testConfigs); i++)
1246 const TestConfig &config = testConfigs[i];
1248 drawTests->addChild(new DrawIndexedAccessTest(testCtx, config.name, config.description, config.inputFormat, config.indexConfig));
1251 return drawTests.release();
1254 static void addVertexFormatTests (tcu::TestContext& testCtx, tcu::TestCaseGroup* parentGroup)
1256 const VkFormat vertexFormats[] =
1260 VK_FORMAT_R32_SFLOAT,
1261 VK_FORMAT_R32G32_UINT,
1262 VK_FORMAT_R32G32_SINT,
1263 VK_FORMAT_R32G32_SFLOAT,
1264 VK_FORMAT_R32G32B32_UINT,
1265 VK_FORMAT_R32G32B32_SINT,
1266 VK_FORMAT_R32G32B32_SFLOAT,
1267 VK_FORMAT_R32G32B32A32_UINT,
1268 VK_FORMAT_R32G32B32A32_SINT,
1269 VK_FORMAT_R32G32B32A32_SFLOAT,
1273 VK_FORMAT_A2B10G10R10_UNORM_PACK32
1276 for (int i = 0; i < DE_LENGTH_OF_ARRAY(vertexFormats); i++)
1278 const std::string formatName = getFormatName(vertexFormats[i]);
1279 de::MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx, de::toLower(formatName.substr(10)).c_str(), ""));
1281 formatGroup->addChild(createDrawTests(testCtx, vertexFormats[i]));
1282 formatGroup->addChild(createDrawIndexedTests(testCtx, vertexFormats[i]));
1284 parentGroup->addChild(formatGroup.release());
1288 tcu::TestCaseGroup* createVertexAccessTests (tcu::TestContext& testCtx)
1290 de::MovePtr<tcu::TestCaseGroup> vertexAccessTests (new tcu::TestCaseGroup(testCtx, "vertex_access", ""));
1292 addVertexFormatTests(testCtx, vertexAccessTests.get());
1294 return vertexAccessTests.release();