1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and/or associated documentation files (the
10 * "Materials"), to deal in the Materials without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sublicense, and/or sell copies of the Materials, and to
13 * permit persons to whom the Materials are furnished to do so, subject to
14 * the following conditions:
16 * The above copyright notice(s) and this permission notice shall be included
17 * in all copies or substantial portions of the Materials.
19 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
23 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
29 * \brief Vulkan Buffers Tests
30 *//*--------------------------------------------------------------------*/
32 #include "vktApiBufferTests.hpp"
34 #include "deStringUtil.hpp"
35 #include "gluVarType.hpp"
36 #include "tcuTestLog.hpp"
37 #include "vkPrograms.hpp"
38 #include "vkQueryUtil.hpp"
39 #include "vkRefUtil.hpp"
40 #include "vktTestCase.hpp"
53 static const deUint32 MAX_BUFFER_SIZE_DIVISOR = 16;
55 struct BufferCaseParameters
57 VkBufferUsageFlags usage;
58 VkBufferCreateFlags flags;
59 VkSharingMode sharingMode;
62 class BufferTestInstance : public TestInstance
65 BufferTestInstance (Context& ctx,
66 BufferCaseParameters testCase)
68 , m_testCase (testCase)
70 virtual tcu::TestStatus iterate (void);
71 tcu::TestStatus bufferCreateAndAllocTest (VkDeviceSize size);
74 BufferCaseParameters m_testCase;
77 class BuffersTestCase : public TestCase
80 BuffersTestCase (tcu::TestContext& testCtx,
81 const std::string& name,
82 const std::string& description,
83 BufferCaseParameters testCase)
84 : TestCase(testCtx, name, description)
85 , m_testCase(testCase)
88 virtual ~BuffersTestCase (void) {}
89 virtual TestInstance* createInstance (Context& ctx) const
91 tcu::TestLog& log = m_testCtx.getLog();
92 log << tcu::TestLog::Message << getBufferUsageFlagsStr(m_testCase.usage) << tcu::TestLog::EndMessage;
93 return new BufferTestInstance(ctx, m_testCase);
97 BufferCaseParameters m_testCase;
100 tcu::TestStatus BufferTestInstance::bufferCreateAndAllocTest (VkDeviceSize size)
102 const VkPhysicalDevice vkPhysicalDevice = m_context.getPhysicalDevice();
103 const InstanceInterface& vkInstance = m_context.getInstanceInterface();
104 const VkDevice vkDevice = m_context.getDevice();
105 const DeviceInterface& vk = m_context.getDeviceInterface();
106 Move<VkBuffer> testBuffer;
107 VkMemoryRequirements memReqs;
108 Move<VkDeviceMemory> memory;
109 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
110 const VkPhysicalDeviceMemoryProperties memoryProperties = getPhysicalDeviceMemoryProperties(vkInstance, vkPhysicalDevice);
114 VkBufferCreateInfo bufferParams =
116 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
121 m_testCase.sharingMode,
122 1u, // deUint32 queueFamilyCount;
128 testBuffer = createBuffer(vk, vkDevice, &bufferParams);
130 catch (const vk::Error& error)
132 return tcu::TestStatus::fail("Buffer creation failed! (requested memory size: " + de::toString(size) + ", Error code: " + de::toString(error.getMessage()) + ")");
135 vk.getBufferMemoryRequirements(vkDevice, *testBuffer, &memReqs);
137 const deUint32 heapTypeIndex = (deUint32)deCtz32(memReqs.memoryTypeBits);
138 const VkMemoryType memoryType = memoryProperties.memoryTypes[heapTypeIndex];
139 const VkMemoryHeap memoryHeap = memoryProperties.memoryHeaps[memoryType.heapIndex];
140 const VkDeviceSize maxBufferSize = memoryHeap.size / MAX_BUFFER_SIZE_DIVISOR;
141 // If the requested size is too large, clamp it based on the selected heap size
142 if (size > maxBufferSize)
144 size = maxBufferSize;
145 bufferParams.size = size;
148 // allocate a new buffer with the adjusted size, the old one will be destroyed by the smart pointer
149 testBuffer = createBuffer(vk, vkDevice, &bufferParams);
151 catch (const vk::Error& error)
153 return tcu::TestStatus::fail("Buffer creation failed! (requested memory size: " + de::toString(size) + ", Error code: " + de::toString(error.getMessage()) + ")");
155 vk.getBufferMemoryRequirements(vkDevice, *testBuffer, &memReqs);
158 if (size > memReqs.size)
160 std::ostringstream errorMsg;
161 errorMsg << "Requied memory size (" << memReqs.size << " bytes) smaller than the buffer's size (" << size << " bytes)!";
162 return tcu::TestStatus::fail(errorMsg.str());
166 // Allocate and bind memory
168 const VkMemoryAllocateInfo memAlloc =
170 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
173 (deUint32)deCtz32(memReqs.memoryTypeBits) // deUint32 memoryTypeIndex
178 memory = allocateMemory(vk, vkDevice, &memAlloc, (const VkAllocationCallbacks*)DE_NULL);
180 catch (const vk::Error& error)
182 return tcu::TestStatus::fail("Alloc memory failed! (requested memory size: " + de::toString(size) + ", Error code: " + de::toString(error.getMessage()) + ")");
185 if ((m_testCase.flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) ||
186 (m_testCase.flags & VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT) ||
187 (m_testCase.flags & VK_BUFFER_CREATE_SPARSE_ALIASED_BIT))
191 vk.getDeviceQueue(vkDevice, queueFamilyIndex, 0, &queue);
193 const VkSparseMemoryBind sparseMemoryBind =
195 0, // VkDeviceSize resourceOffset;
196 memReqs.size, // VkDeviceSize size;
197 *memory, // VkDeviceMemory memory;
198 0, // VkDeviceSize memoryOffset;
199 0 // VkSparseMemoryBindFlags flags;
202 const VkSparseBufferMemoryBindInfo sparseBufferMemoryBindInfo =
204 *testBuffer, // VkBuffer buffer;
205 1u, // deUint32 bindCount;
206 &sparseMemoryBind // const VkSparseMemoryBind* pBinds;
209 const VkBindSparseInfo bindSparseInfo =
211 VK_STRUCTURE_TYPE_BIND_SPARSE_INFO, // VkStructureType sType;
212 DE_NULL, // const void* pNext;
213 0, // deUint32 waitSemaphoreCount;
214 DE_NULL, // const VkSemaphore* pWaitSemaphores;
215 1u, // deUint32 bufferBindCount;
216 &sparseBufferMemoryBindInfo, // const VkSparseBufferMemoryBindInfo* pBufferBinds;
217 0, // deUint32 imageOpaqueBindCount;
218 DE_NULL, // const VkSparseImageOpaqueMemoryBindInfo* pImageOpaqueBinds;
219 0, // deUint32 imageBindCount;
220 DE_NULL, // const VkSparseImageMemoryBindInfo* pImageBinds;
221 0, // deUint32 signalSemaphoreCount;
222 DE_NULL, // const VkSemaphore* pSignalSemaphores;
225 const VkFenceCreateInfo fenceParams =
227 VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType;
228 DE_NULL, // const void* pNext;
229 0u // VkFenceCreateFlags flags;
232 const vk::Unique<vk::VkFence> fence(vk::createFence(vk, vkDevice, &fenceParams));
234 VK_CHECK(vk.resetFences(vkDevice, 1, &fence.get()));
235 if (vk.queueBindSparse(queue, 1, &bindSparseInfo, *fence) != VK_SUCCESS)
236 return tcu::TestStatus::fail("Bind sparse buffer memory failed! (requested memory size: " + de::toString(size) + ")");
238 VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), VK_TRUE, ~(0ull) /* infinity */));
240 if (vk.bindBufferMemory(vkDevice, *testBuffer, *memory, 0) != VK_SUCCESS)
241 return tcu::TestStatus::fail("Bind buffer memory failed! (requested memory size: " + de::toString(size) + ")");
244 return tcu::TestStatus::pass("Buffer test");
247 tcu::TestStatus BufferTestInstance::iterate (void)
249 const VkPhysicalDeviceFeatures& physicalDeviceFeatures = m_context.getDeviceFeatures();
251 if ((m_testCase.flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT ) && !physicalDeviceFeatures.sparseBinding)
252 TCU_THROW(NotSupportedError, "Sparse bindings feature is not supported");
254 if ((m_testCase.flags & VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT ) && !physicalDeviceFeatures.sparseResidencyBuffer)
255 TCU_THROW(NotSupportedError, "Sparse buffer residency feature is not supported");
257 if ((m_testCase.flags & VK_BUFFER_CREATE_SPARSE_ALIASED_BIT ) && !physicalDeviceFeatures.sparseResidencyAliased)
258 TCU_THROW(NotSupportedError, "Sparse aliased residency feature is not supported");
260 const VkDeviceSize testSizes[] =
267 tcu::TestStatus testStatus = tcu::TestStatus::pass("Buffer test");
269 for (int i = 0; i < DE_LENGTH_OF_ARRAY(testSizes); i++)
271 if ((testStatus = bufferCreateAndAllocTest(testSizes[i])).getCode() != QP_TEST_RESULT_PASS)
275 if (m_testCase.usage & (VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT))
277 const VkPhysicalDevice vkPhysicalDevice = m_context.getPhysicalDevice();
278 const InstanceInterface& vkInstance = m_context.getInstanceInterface();
279 VkPhysicalDeviceProperties props;
281 vkInstance.getPhysicalDeviceProperties(vkPhysicalDevice, &props);
282 testStatus = bufferCreateAndAllocTest((VkDeviceSize) props.limits.maxTexelBufferElements);
290 tcu::TestCaseGroup* createBufferTests (tcu::TestContext& testCtx)
292 const VkBufferUsageFlags bufferUsageModes[] =
294 VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
295 VK_BUFFER_USAGE_TRANSFER_DST_BIT,
296 VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT,
297 VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT,
298 VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
299 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
300 VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
301 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
302 VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT
305 const VkBufferCreateFlags bufferCreateFlags[] =
307 VK_BUFFER_CREATE_SPARSE_BINDING_BIT,
308 VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT,
309 VK_BUFFER_CREATE_SPARSE_ALIASED_BIT
312 de::MovePtr<tcu::TestCaseGroup> buffersTests (new tcu::TestCaseGroup(testCtx, "buffer", "Buffer Tests"));
314 deUint32 numberOfBufferUsageFlags = DE_LENGTH_OF_ARRAY(bufferUsageModes);
315 deUint32 numberOfBufferCreateFlags = DE_LENGTH_OF_ARRAY(bufferCreateFlags);
316 deUint32 maximumValueOfBufferUsageFlags = (1 << (numberOfBufferUsageFlags - 1)) - 1;
317 deUint32 maximumValueOfBufferCreateFlags = (1 << (numberOfBufferCreateFlags)) - 1;
319 for (deUint32 combinedBufferCreateFlags = 0; combinedBufferCreateFlags <= maximumValueOfBufferCreateFlags; combinedBufferCreateFlags++)
321 for (deUint32 combinedBufferUsageFlags = 1; combinedBufferUsageFlags <= maximumValueOfBufferUsageFlags; combinedBufferUsageFlags++)
323 if (combinedBufferCreateFlags == VK_BUFFER_CREATE_SPARSE_ALIASED_BIT)
325 // spec says: If flags contains VK_BUFFER_CREATE_SPARSE_ALIASED_BIT, it must also contain at least one of
326 // VK_BUFFER_CREATE_SPARSE_BINDING_BIT or VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT
329 BufferCaseParameters testParams =
331 combinedBufferUsageFlags,
332 combinedBufferCreateFlags,
333 VK_SHARING_MODE_EXCLUSIVE
335 std::ostringstream testName;
336 std::ostringstream testDescription;
337 testName << "createBuffer_" << combinedBufferUsageFlags << "_" << combinedBufferCreateFlags;
338 testDescription << "vkCreateBuffer test " << combinedBufferUsageFlags << " " << combinedBufferCreateFlags;
339 buffersTests->addChild(new BuffersTestCase(testCtx, testName.str(), testDescription.str(), testParams));
343 return buffersTests.release();