1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Samsung Electronics Co., 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 Vulkan Buffers Tests
23 *//*--------------------------------------------------------------------*/
25 #include "vktApiBufferTests.hpp"
26 #include "gluVarType.hpp"
27 #include "deStringUtil.hpp"
28 #include "tcuTestLog.hpp"
29 #include "vkPlatform.hpp"
30 #include "vkPrograms.hpp"
31 #include "vkQueryUtil.hpp"
32 #include "vkRefUtil.hpp"
33 #include "vktTestCase.hpp"
34 #include "vktTestCaseUtil.hpp"
35 #include "tcuPlatform.hpp"
50 ALLOCATION_KIND_SUBALLOCATED = 0,
51 ALLOCATION_KIND_DEDICATED,
56 tcu::PlatformMemoryLimits getPlatformMemoryLimits (Context& context)
58 tcu::PlatformMemoryLimits memoryLimits;
60 context.getTestContext().getPlatform().getMemoryLimits(memoryLimits);
65 VkDeviceSize getMaxBufferSize(const VkDeviceSize& bufferSize,
66 const VkDeviceSize& alignment,
67 const tcu::PlatformMemoryLimits& limits)
69 VkDeviceSize size = bufferSize;
71 if (limits.totalDeviceLocalMemory == 0)
73 // 'UMA' systems where device memory counts against system memory
74 size = std::min(bufferSize, limits.totalSystemMemory - alignment);
78 // 'LMA' systems where device memory is local to the GPU
79 size = std::min(bufferSize, limits.totalDeviceLocalMemory - alignment);
85 struct BufferCaseParameters
87 VkBufferUsageFlags usage;
88 VkBufferCreateFlags flags;
89 VkSharingMode sharingMode;
92 class BufferTestInstance : public TestInstance
95 BufferTestInstance (Context& ctx,
96 BufferCaseParameters testCase)
98 , m_testCase (testCase)
101 virtual tcu::TestStatus iterate (void);
102 virtual tcu::TestStatus bufferCreateAndAllocTest (VkDeviceSize size);
105 BufferCaseParameters m_testCase;
108 class DedicatedAllocationBufferTestInstance : public BufferTestInstance
111 DedicatedAllocationBufferTestInstance
113 BufferCaseParameters testCase)
114 : BufferTestInstance (ctx, testCase)
117 virtual tcu::TestStatus bufferCreateAndAllocTest (VkDeviceSize size);
120 class BuffersTestCase : public TestCase
123 BuffersTestCase (tcu::TestContext& testCtx,
124 const std::string& name,
125 const std::string& description,
126 BufferCaseParameters testCase)
127 : TestCase (testCtx, name, description)
128 , m_testCase (testCase)
132 virtual ~BuffersTestCase (void)
136 virtual TestInstance* createInstance (Context& ctx) const
138 tcu::TestLog& log = m_testCtx.getLog();
139 log << tcu::TestLog::Message << getBufferUsageFlagsStr(m_testCase.usage) << tcu::TestLog::EndMessage;
140 return new BufferTestInstance(ctx, m_testCase);
143 virtual void checkSupport (Context& ctx) const
145 const VkPhysicalDeviceFeatures& physicalDeviceFeatures = getPhysicalDeviceFeatures(ctx.getInstanceInterface(), ctx.getPhysicalDevice());
147 if ((m_testCase.flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) && !physicalDeviceFeatures.sparseBinding)
148 TCU_THROW(NotSupportedError, "Sparse bindings feature is not supported");
150 if ((m_testCase.flags & VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT) && !physicalDeviceFeatures.sparseResidencyBuffer)
151 TCU_THROW(NotSupportedError, "Sparse buffer residency feature is not supported");
153 if ((m_testCase.flags & VK_BUFFER_CREATE_SPARSE_ALIASED_BIT) && !physicalDeviceFeatures.sparseResidencyAliased)
154 TCU_THROW(NotSupportedError, "Sparse aliased residency feature is not supported");
158 BufferCaseParameters m_testCase;
161 class DedicatedAllocationBuffersTestCase : public TestCase
164 DedicatedAllocationBuffersTestCase
165 (tcu::TestContext& testCtx,
166 const std::string& name,
167 const std::string& description,
168 BufferCaseParameters testCase)
169 : TestCase (testCtx, name, description)
170 , m_testCase (testCase)
174 virtual ~DedicatedAllocationBuffersTestCase
179 virtual TestInstance* createInstance (Context& ctx) const
181 tcu::TestLog& log = m_testCtx.getLog();
182 log << tcu::TestLog::Message << getBufferUsageFlagsStr(m_testCase.usage) << tcu::TestLog::EndMessage;
183 return new DedicatedAllocationBufferTestInstance(ctx, m_testCase);
186 virtual void checkSupport (Context& ctx) const
188 if (!ctx.isDeviceFunctionalitySupported("VK_KHR_dedicated_allocation"))
189 TCU_THROW(NotSupportedError, "Not supported");
192 BufferCaseParameters m_testCase;
195 tcu::TestStatus BufferTestInstance::bufferCreateAndAllocTest (VkDeviceSize size)
197 const VkPhysicalDevice vkPhysicalDevice = m_context.getPhysicalDevice();
198 const InstanceInterface& vkInstance = m_context.getInstanceInterface();
199 const VkDevice vkDevice = m_context.getDevice();
200 const DeviceInterface& vk = m_context.getDeviceInterface();
201 const deUint32 queueFamilyIndex = m_context.getSparseQueueFamilyIndex();
202 const VkPhysicalDeviceMemoryProperties
203 memoryProperties = getPhysicalDeviceMemoryProperties(vkInstance, vkPhysicalDevice);
204 const VkPhysicalDeviceLimits limits = getPhysicalDeviceProperties(vkInstance, vkPhysicalDevice).limits;
205 Move<VkBuffer> buffer;
206 Move<VkDeviceMemory> memory;
207 VkMemoryRequirements memReqs;
209 if ((m_testCase.flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) != 0)
211 size = std::min(size, limits.sparseAddressSpaceSize);
214 // Create the test buffer and a memory allocation for it
216 // Create a minimal buffer first to get the supported memory types
217 VkBufferCreateInfo bufferParams =
219 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
220 DE_NULL, // const void* pNext;
221 m_testCase.flags, // VkBufferCreateFlags flags;
222 1u, // VkDeviceSize size;
223 m_testCase.usage, // VkBufferUsageFlags usage;
224 m_testCase.sharingMode, // VkSharingMode sharingMode;
225 1u, // uint32_t queueFamilyIndexCount;
226 &queueFamilyIndex, // const uint32_t* pQueueFamilyIndices;
229 buffer = createBuffer(vk, vkDevice, &bufferParams);
230 vk.getBufferMemoryRequirements(vkDevice, *buffer, &memReqs);
232 const deUint32 heapTypeIndex = (deUint32)deCtz32(memReqs.memoryTypeBits);
233 const VkMemoryType memoryType = memoryProperties.memoryTypes[heapTypeIndex];
234 const VkMemoryHeap memoryHeap = memoryProperties.memoryHeaps[memoryType.heapIndex];
235 const deUint32 shrinkBits = 4u; // number of bits to shift when reducing the size with each iteration
237 // Buffer size - Choose half of the reported heap size for the maximum buffer size, we
238 // should attempt to test as large a portion as possible.
240 // However on a system where device memory is shared with the system, the maximum size
241 // should be tested against the platform memory limits as significant portion of the heap
242 // may already be in use by the operating system and other running processes.
243 const VkDeviceSize availableBufferSize = getMaxBufferSize(memoryHeap.size,
245 getPlatformMemoryLimits(m_context));
247 // For our test buffer size, halve the maximum available size and align
248 const VkDeviceSize maxBufferSize = deAlign64(availableBufferSize >> 1, memReqs.alignment);
250 size = std::min(size, maxBufferSize);
252 while (*memory == DE_NULL)
256 VkResult result = VK_ERROR_OUT_OF_HOST_MEMORY;
257 VkBuffer rawBuffer = DE_NULL;
259 bufferParams.size = size;
260 buffer = Move<VkBuffer>(); // free the previous buffer, if any
261 result = vk.createBuffer(vkDevice, &bufferParams, (vk::VkAllocationCallbacks*)DE_NULL, &rawBuffer);
263 if (result != VK_SUCCESS)
265 size = deAlign64(size >> shrinkBits, memReqs.alignment);
267 if (size == 0 || bufferParams.size == memReqs.alignment)
269 return tcu::TestStatus::fail("Buffer creation failed! (" + de::toString(getResultName(result)) + ")");
272 continue; // didn't work, try with a smaller buffer
275 buffer = Move<VkBuffer>(check<VkBuffer>(rawBuffer), Deleter<VkBuffer>(vk, vkDevice, DE_NULL));
278 vk.getBufferMemoryRequirements(vkDevice, *buffer, &memReqs); // get the proper size requirement
280 #ifdef CTS_USES_VULKANSC
281 if (m_context.getTestContext().getCommandLine().isSubProcess())
282 #endif // CTS_USES_VULKANSC
284 if (size > memReqs.size)
286 std::ostringstream errorMsg;
287 errorMsg << "Required memory size (" << memReqs.size << " bytes) smaller than the buffer's size (" << size << " bytes)!";
288 return tcu::TestStatus::fail(errorMsg.str());
292 // Allocate the memory
294 VkResult result = VK_ERROR_OUT_OF_HOST_MEMORY;
295 VkDeviceMemory rawMemory = DE_NULL;
297 const VkMemoryAllocateInfo
300 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType;
301 NULL, // const void* pNext;
302 memReqs.size, // VkDeviceSize allocationSize;
303 heapTypeIndex, // uint32_t memoryTypeIndex;
306 result = vk.allocateMemory(vkDevice, &memAlloc, (VkAllocationCallbacks*)DE_NULL, &rawMemory);
308 if (result != VK_SUCCESS)
310 size = deAlign64(size >> shrinkBits, memReqs.alignment);
312 if (size == 0 || memReqs.size == memReqs.alignment)
314 return tcu::TestStatus::fail("Unable to allocate " + de::toString(memReqs.size) + " bytes of memory");
317 continue; // didn't work, try with a smaller allocation (and a smaller buffer)
320 memory = Move<VkDeviceMemory>(check<VkDeviceMemory>(rawMemory), Deleter<VkDeviceMemory>(vk, vkDevice, DE_NULL));
326 #ifndef CTS_USES_VULKANSC
327 if ((m_testCase.flags & (VK_BUFFER_CREATE_SPARSE_BINDING_BIT | VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT | VK_BUFFER_CREATE_SPARSE_ALIASED_BIT)) != 0)
329 const VkQueue queue = m_context.getSparseQueue();
331 const VkSparseMemoryBind sparseMemoryBind =
333 0, // VkDeviceSize resourceOffset;
334 memReqs.size, // VkDeviceSize size;
335 *memory, // VkDeviceMemory memory;
336 0, // VkDeviceSize memoryOffset;
337 0 // VkSparseMemoryBindFlags flags;
340 const VkSparseBufferMemoryBindInfo
341 sparseBufferMemoryBindInfo =
343 *buffer, // VkBuffer buffer;
344 1u, // deUint32 bindCount;
345 &sparseMemoryBind // const VkSparseMemoryBind* pBinds;
348 const VkBindSparseInfo bindSparseInfo =
350 VK_STRUCTURE_TYPE_BIND_SPARSE_INFO, // VkStructureType sType;
351 DE_NULL, // const void* pNext;
352 0, // deUint32 waitSemaphoreCount;
353 DE_NULL, // const VkSemaphore* pWaitSemaphores;
354 1u, // deUint32 bufferBindCount;
355 &sparseBufferMemoryBindInfo, // const VkSparseBufferMemoryBindInfo* pBufferBinds;
356 0, // deUint32 imageOpaqueBindCount;
357 DE_NULL, // const VkSparseImageOpaqueMemoryBindInfo* pImageOpaqueBinds;
358 0, // deUint32 imageBindCount;
359 DE_NULL, // const VkSparseImageMemoryBindInfo* pImageBinds;
360 0, // deUint32 signalSemaphoreCount;
361 DE_NULL, // const VkSemaphore* pSignalSemaphores;
364 const vk::Unique<vk::VkFence> fence (vk::createFence(vk, vkDevice));
366 if (vk.queueBindSparse(queue, 1, &bindSparseInfo, *fence) != VK_SUCCESS)
367 return tcu::TestStatus::fail("Bind sparse buffer memory failed! (requested memory size: " + de::toString(size) + ")");
369 VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), VK_TRUE, ~(0ull) /* infinity */));
371 else if (vk.bindBufferMemory(vkDevice, *buffer, *memory, 0) != VK_SUCCESS)
372 return tcu::TestStatus::fail("Bind buffer memory failed! (requested memory size: " + de::toString(size) + ")");
374 if (vk.bindBufferMemory(vkDevice, *buffer, *memory, 0) != VK_SUCCESS)
375 return tcu::TestStatus::fail("Bind buffer memory failed! (requested memory size: " + de::toString(size) + ")");
376 #endif // CTS_USES_VULKANSC
378 return tcu::TestStatus::pass("Pass");
381 tcu::TestStatus BufferTestInstance::iterate (void)
383 const VkDeviceSize testSizes[] =
389 #ifndef CTS_USES_VULKANSC
390 ~0ull, // try to exercise a very large buffer too (will be clamped to a sensible size later)
391 #endif // CTS_USES_VULKANSC
394 for (int i = 0; i < DE_LENGTH_OF_ARRAY(testSizes); ++i)
396 const tcu::TestStatus testStatus = bufferCreateAndAllocTest(testSizes[i]);
398 if (testStatus.getCode() != QP_TEST_RESULT_PASS)
402 return tcu::TestStatus::pass("Pass");
405 tcu::TestStatus DedicatedAllocationBufferTestInstance::bufferCreateAndAllocTest
408 const VkPhysicalDevice vkPhysicalDevice = m_context.getPhysicalDevice();
409 const InstanceInterface& vkInstance = m_context.getInstanceInterface();
410 const VkDevice vkDevice = m_context.getDevice();
411 const DeviceInterface& vk = m_context.getDeviceInterface();
412 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
413 const VkPhysicalDeviceMemoryProperties
414 memoryProperties = getPhysicalDeviceMemoryProperties(vkInstance, vkPhysicalDevice);
415 const VkPhysicalDeviceLimits limits = getPhysicalDeviceProperties(vkInstance, vkPhysicalDevice).limits;
417 VkMemoryDedicatedRequirements dedicatedRequirements =
419 VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS, // VkStructureType sType;
420 DE_NULL, // const void* pNext;
421 false, // VkBool32 prefersDedicatedAllocation
422 false // VkBool32 requiresDedicatedAllocation
424 VkMemoryRequirements2 memReqs =
426 VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, // VkStructureType sType
427 &dedicatedRequirements, // void* pNext
428 {0, 0, 0} // VkMemoryRequirements memoryRequirements
431 if ((m_testCase.flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) != 0)
432 size = std::min(size, limits.sparseAddressSpaceSize);
434 // Create a minimal buffer first to get the supported memory types
435 VkBufferCreateInfo bufferParams =
437 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType
438 DE_NULL, // const void* pNext
439 m_testCase.flags, // VkBufferCreateFlags flags
440 1u, // VkDeviceSize size
441 m_testCase.usage, // VkBufferUsageFlags usage
442 m_testCase.sharingMode, // VkSharingMode sharingMode
443 1u, // uint32_t queueFamilyIndexCount
444 &queueFamilyIndex, // const uint32_t* pQueueFamilyIndices
447 Move<VkBuffer> buffer = createBuffer(vk, vkDevice, &bufferParams);
449 VkBufferMemoryRequirementsInfo2 info =
451 VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2, // VkStructureType sType
452 DE_NULL, // const void* pNext
453 *buffer // VkBuffer buffer
456 vk.getBufferMemoryRequirements2(vkDevice, &info, &memReqs);
458 if (dedicatedRequirements.requiresDedicatedAllocation == VK_TRUE)
460 std::ostringstream errorMsg;
461 errorMsg << "Nonexternal objects cannot require dedicated allocation.";
462 return tcu::TestStatus::fail(errorMsg.str());
465 if(memReqs.memoryRequirements.memoryTypeBits == 0)
466 return tcu::TestStatus::fail("memoryTypeBits is 0");
468 const deUint32 heapTypeIndex = static_cast<deUint32>(deCtz32(memReqs.memoryRequirements.memoryTypeBits));
469 const VkMemoryType memoryType = memoryProperties.memoryTypes[heapTypeIndex];
470 const VkMemoryHeap memoryHeap = memoryProperties.memoryHeaps[memoryType.heapIndex];
471 const deUint32 shrinkBits = 4u; // number of bits to shift when reducing the size with each iteration
473 // Buffer size - Choose half of the reported heap size for the maximum buffer size, we
474 // should attempt to test as large a portion as possible.
476 // However on a system where device memory is shared with the system, the maximum size
477 // should be tested against the platform memory limits as a significant portion of the heap
478 // may already be in use by the operating system and other running processes.
479 const VkDeviceSize maxBufferSize = getMaxBufferSize(memoryHeap.size,
480 memReqs.memoryRequirements.alignment,
481 getPlatformMemoryLimits(m_context));
483 Move<VkDeviceMemory> memory;
484 size = deAlign64(std::min(size, maxBufferSize >> 1), memReqs.memoryRequirements.alignment);
485 while (*memory == DE_NULL)
489 VkResult result = VK_ERROR_OUT_OF_HOST_MEMORY;
490 VkBuffer rawBuffer = DE_NULL;
492 bufferParams.size = size;
493 buffer = Move<VkBuffer>(); // free the previous buffer, if any
494 result = vk.createBuffer(vkDevice, &bufferParams, (VkAllocationCallbacks*)DE_NULL, &rawBuffer);
496 if (result != VK_SUCCESS)
498 size = deAlign64(size >> shrinkBits, memReqs.memoryRequirements.alignment);
500 if (size == 0 || bufferParams.size == memReqs.memoryRequirements.alignment)
501 return tcu::TestStatus::fail("Buffer creation failed! (" + de::toString(getResultName(result)) + ")");
503 continue; // didn't work, try with a smaller buffer
506 buffer = Move<VkBuffer>(check<VkBuffer>(rawBuffer), Deleter<VkBuffer>(vk, vkDevice, DE_NULL));
509 info.buffer = *buffer;
510 vk.getBufferMemoryRequirements2(vkDevice, &info, &memReqs); // get the proper size requirement
512 if (size > memReqs.memoryRequirements.size)
514 std::ostringstream errorMsg;
515 errorMsg << "Requied memory size (" << memReqs.memoryRequirements.size << " bytes) smaller than the buffer's size (" << size << " bytes)!";
516 return tcu::TestStatus::fail(errorMsg.str());
519 // Allocate the memory
521 VkResult result = VK_ERROR_OUT_OF_HOST_MEMORY;
522 VkDeviceMemory rawMemory = DE_NULL;
524 vk::VkMemoryDedicatedAllocateInfo
527 VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, // VkStructureType sType
528 DE_NULL, // const void* pNext
529 DE_NULL, // VkImage image
530 *buffer // VkBuffer buffer
533 VkMemoryAllocateInfo memoryAllocateInfo =
535 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType
536 &dedicatedInfo, // const void* pNext
537 memReqs.memoryRequirements.size, // VkDeviceSize allocationSize
538 heapTypeIndex, // deUint32 memoryTypeIndex
541 result = vk.allocateMemory(vkDevice, &memoryAllocateInfo, (VkAllocationCallbacks*)DE_NULL, &rawMemory);
543 if (result != VK_SUCCESS)
545 size = deAlign64(size >> shrinkBits, memReqs.memoryRequirements.alignment);
547 if (size == 0 || memReqs.memoryRequirements.size == memReqs.memoryRequirements.alignment)
548 return tcu::TestStatus::fail("Unable to allocate " + de::toString(memReqs.memoryRequirements.size) + " bytes of memory");
550 continue; // didn't work, try with a smaller allocation (and a smaller buffer)
553 memory = Move<VkDeviceMemory>(check<VkDeviceMemory>(rawMemory), Deleter<VkDeviceMemory>(vk, vkDevice, DE_NULL));
557 if (vk.bindBufferMemory(vkDevice, *buffer, *memory, 0) != VK_SUCCESS)
558 return tcu::TestStatus::fail("Bind buffer memory failed! (requested memory size: " + de::toString(size) + ")");
560 return tcu::TestStatus::pass("Pass");
563 std::string getBufferUsageFlagsName (const VkBufferUsageFlags flags)
567 case VK_BUFFER_USAGE_TRANSFER_SRC_BIT: return "transfer_src";
568 case VK_BUFFER_USAGE_TRANSFER_DST_BIT: return "transfer_dst";
569 case VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT: return "uniform_texel";
570 case VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT: return "storage_texel";
571 case VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT: return "uniform";
572 case VK_BUFFER_USAGE_STORAGE_BUFFER_BIT: return "storage";
573 case VK_BUFFER_USAGE_INDEX_BUFFER_BIT: return "index";
574 case VK_BUFFER_USAGE_VERTEX_BUFFER_BIT: return "vertex";
575 case VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT: return "indirect";
577 DE_FATAL("Unknown buffer usage flag");
582 std::string getBufferCreateFlagsName (const VkBufferCreateFlags flags)
584 std::ostringstream name;
586 if (flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT)
588 if (flags & VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT)
589 name << "_residency";
590 if (flags & VK_BUFFER_CREATE_SPARSE_ALIASED_BIT)
595 DE_ASSERT(!name.str().empty());
597 return name.str().substr(1);
600 // Create all VkBufferUsageFlags combinations recursively
601 void createBufferUsageCases (tcu::TestCaseGroup& testGroup, const deUint32 firstNdx, const deUint32 bufferUsageFlags, const AllocationKind allocationKind)
603 const VkBufferUsageFlags bufferUsageModes[] =
605 VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
606 VK_BUFFER_USAGE_TRANSFER_DST_BIT,
607 VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT,
608 VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT,
609 VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
610 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
611 VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
612 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
613 VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT
616 tcu::TestContext& testCtx = testGroup.getTestContext();
619 for (deUint32 currentNdx = firstNdx; currentNdx < DE_LENGTH_OF_ARRAY(bufferUsageModes); currentNdx++)
621 const deUint32 newBufferUsageFlags = bufferUsageFlags | bufferUsageModes[currentNdx];
622 const std::string newGroupName = getBufferUsageFlagsName(bufferUsageModes[currentNdx]);
623 de::MovePtr<tcu::TestCaseGroup> newTestGroup (new tcu::TestCaseGroup(testCtx, newGroupName.c_str(), ""));
625 createBufferUsageCases(*newTestGroup, currentNdx + 1u, newBufferUsageFlags, allocationKind);
626 testGroup.addChild(newTestGroup.release());
630 if (bufferUsageFlags != 0u)
632 // \note SPARSE_RESIDENCY and SPARSE_ALIASED have to be used together with the SPARSE_BINDING flag.
633 const VkBufferCreateFlags bufferCreateFlags[] =
636 #ifndef CTS_USES_VULKANSC
637 VK_BUFFER_CREATE_SPARSE_BINDING_BIT,
638 VK_BUFFER_CREATE_SPARSE_BINDING_BIT | VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT,
639 VK_BUFFER_CREATE_SPARSE_BINDING_BIT | VK_BUFFER_CREATE_SPARSE_ALIASED_BIT,
640 VK_BUFFER_CREATE_SPARSE_BINDING_BIT | VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT | VK_BUFFER_CREATE_SPARSE_ALIASED_BIT,
641 #endif // CTS_USES_VULKANSC
644 // Dedicated allocation does not support sparse feature
645 const int numBufferCreateFlags = (allocationKind == ALLOCATION_KIND_SUBALLOCATED) ? DE_LENGTH_OF_ARRAY(bufferCreateFlags) : 1;
647 de::MovePtr<tcu::TestCaseGroup> newTestGroup (new tcu::TestCaseGroup(testCtx, "create", ""));
649 for (int bufferCreateFlagsNdx = 0; bufferCreateFlagsNdx < numBufferCreateFlags; bufferCreateFlagsNdx++)
651 const BufferCaseParameters testParams =
654 bufferCreateFlags[bufferCreateFlagsNdx],
655 VK_SHARING_MODE_EXCLUSIVE
658 const std::string allocStr = (allocationKind == ALLOCATION_KIND_SUBALLOCATED) ? "suballocation of " : "dedicated alloc. of ";
659 const std::string caseName = getBufferCreateFlagsName(bufferCreateFlags[bufferCreateFlagsNdx]);
660 const std::string caseDesc = "vkCreateBuffer test: " + allocStr + de::toString(bufferUsageFlags) + " " + de::toString(testParams.flags);
662 switch (allocationKind)
664 case ALLOCATION_KIND_SUBALLOCATED:
665 newTestGroup->addChild(new BuffersTestCase(testCtx, caseName.c_str(), caseDesc.c_str(), testParams));
667 case ALLOCATION_KIND_DEDICATED:
668 newTestGroup->addChild(new DedicatedAllocationBuffersTestCase(testCtx, caseName.c_str(), caseDesc.c_str(), testParams));
671 DE_FATAL("Unknown test type");
674 testGroup.addChild(newTestGroup.release());
678 tcu::TestStatus testDepthStencilBufferFeatures(Context& context, VkFormat format)
680 const InstanceInterface& vki = context.getInstanceInterface();
681 VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
682 VkFormatProperties formatProperties;
684 vki.getPhysicalDeviceFormatProperties(physicalDevice, format, &formatProperties);
686 if (formatProperties.bufferFeatures == 0x0)
687 return tcu::TestStatus::pass("Pass");
689 return tcu::TestStatus::fail("Fail");
692 struct LargeBufferParameters
695 bool useMaxBufferSize;
696 VkBufferCreateFlags flags;
699 #ifndef CTS_USES_VULKANSC
700 tcu::TestStatus testLargeBuffer(Context& context, LargeBufferParameters params)
702 const DeviceInterface& vk = context.getDeviceInterface();
703 const VkDevice vkDevice = context.getDevice();
704 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
705 const VkPhysicalDeviceLimits limits = getPhysicalDeviceProperties(context.getInstanceInterface(),
706 context.getPhysicalDevice()).limits;
707 VkBuffer rawBuffer = DE_NULL;
709 #ifndef CTS_USES_VULKANSC
710 if (params.useMaxBufferSize)
711 params.bufferSize = context.getMaintenance4Properties().maxBufferSize;
712 #endif // CTS_USES_VULKANSC
714 if ((params.flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) != 0)
715 params.bufferSize = std::min(params.bufferSize, limits.sparseAddressSpaceSize);
717 VkBufferCreateInfo bufferParams =
719 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
720 DE_NULL, // const void* pNext;
721 params.flags, // VkBufferCreateFlags flags;
722 params.bufferSize, // VkDeviceSize size;
723 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, // VkBufferUsageFlags usage;
724 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
725 1u, // uint32_t queueFamilyIndexCount;
726 &queueFamilyIndex, // const uint32_t* pQueueFamilyIndices;
729 VkResult result = vk.createBuffer(vkDevice, &bufferParams, (vk::VkAllocationCallbacks*)DE_NULL, &rawBuffer);
731 // if buffer creation succeeds verify that the correct amount of memory was bound to it
732 if (result == VK_SUCCESS)
734 VkMemoryRequirements memoryRequirements;
735 vk.getBufferMemoryRequirements(vkDevice, rawBuffer, &memoryRequirements);
736 vk.destroyBuffer(vkDevice, rawBuffer, DE_NULL);
738 if (memoryRequirements.size >= params.bufferSize)
739 return tcu::TestStatus::pass("Pass");
740 return tcu::TestStatus::fail("Fail");
743 // check if one of the allowed errors was returned
744 if ((result == VK_ERROR_OUT_OF_DEVICE_MEMORY) ||
745 (result == VK_ERROR_OUT_OF_HOST_MEMORY))
746 return tcu::TestStatus::pass("Pass");
748 return tcu::TestStatus::fail("Fail");
750 #endif // CTS_USES_VULKANSC
752 #ifndef CTS_USES_VULKANSC
753 void checkMaintenance4Support(Context& context, LargeBufferParameters params)
755 if (params.useMaxBufferSize)
756 context.requireDeviceFunctionality("VK_KHR_maintenance4");
757 else if (context.isDeviceFunctionalitySupported("VK_KHR_maintenance4") &&
758 params.bufferSize > context.getMaintenance4Properties().maxBufferSize)
759 TCU_THROW(NotSupportedError, "vkCreateBuffer with a size larger than maxBufferSize is not valid usage");
761 const VkPhysicalDeviceFeatures& physicalDeviceFeatures = getPhysicalDeviceFeatures(context.getInstanceInterface(), context.getPhysicalDevice());
762 if ((params.flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) && !physicalDeviceFeatures.sparseBinding)
763 TCU_THROW(NotSupportedError, "Sparse bindings feature is not supported");
765 #endif // CTS_USES_VULKANSC
769 tcu::TestCaseGroup* createBufferTests (tcu::TestContext& testCtx)
771 de::MovePtr<tcu::TestCaseGroup> buffersTests (new tcu::TestCaseGroup(testCtx, "buffer", "Buffer Tests"));
774 de::MovePtr<tcu::TestCaseGroup> regularAllocation (new tcu::TestCaseGroup(testCtx, "suballocation", "Regular suballocation of memory."));
775 createBufferUsageCases(*regularAllocation, 0u, 0u, ALLOCATION_KIND_SUBALLOCATED);
776 buffersTests->addChild(regularAllocation.release());
780 de::MovePtr<tcu::TestCaseGroup> dedicatedAllocation (new tcu::TestCaseGroup(testCtx, "dedicated_alloc", "Dedicated allocation of memory."));
781 createBufferUsageCases(*dedicatedAllocation, 0u, 0u, ALLOCATION_KIND_DEDICATED);
782 buffersTests->addChild(dedicatedAllocation.release());
786 de::MovePtr<tcu::TestCaseGroup> basicTests(new tcu::TestCaseGroup(testCtx, "basic", "Basic buffer tests."));
787 #ifndef CTS_USES_VULKANSC
788 addFunctionCase(basicTests.get(), "max_size", "Creating buffer using maxBufferSize limit.",
789 checkMaintenance4Support, testLargeBuffer, LargeBufferParameters
795 addFunctionCase(basicTests.get(), "max_size_sparse", "Creating sparse buffer using maxBufferSize limit.",
796 checkMaintenance4Support, testLargeBuffer, LargeBufferParameters
800 VK_BUFFER_CREATE_SPARSE_BINDING_BIT
802 addFunctionCase(basicTests.get(), "size_max_uint64", "Creating a ULLONG_MAX buffer and verify that it either succeeds or returns one of the allowed errors.",
803 checkMaintenance4Support, testLargeBuffer, LargeBufferParameters
805 std::numeric_limits<deUint64>::max(),
809 #endif // CTS_USES_VULKANSC
810 buffersTests->addChild(basicTests.release());
814 static const VkFormat dsFormats[] =
818 VK_FORMAT_D16_UNORM_S8_UINT,
819 VK_FORMAT_D24_UNORM_S8_UINT,
820 VK_FORMAT_D32_SFLOAT,
821 VK_FORMAT_D32_SFLOAT_S8_UINT,
822 VK_FORMAT_X8_D24_UNORM_PACK32
825 de::MovePtr<tcu::TestCaseGroup> invalidBufferFeatures(new tcu::TestCaseGroup(testCtx, "invalid_buffer_features", "Checks that drivers are not exposing undesired format features for depth/stencil formats."));
827 for (const auto& testFormat : dsFormats)
829 std::string formatName = de::toLower(getFormatName(testFormat));
831 addFunctionCase(invalidBufferFeatures.get(), formatName, formatName, testDepthStencilBufferFeatures, testFormat);
834 buffersTests->addChild(invalidBufferFeatures.release());
837 return buffersTests.release();