1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2015 Google Inc.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
21 * \brief Simple memory allocation tests.
22 *//*--------------------------------------------------------------------*/
24 #include "vktMemoryAllocationTests.hpp"
26 #include "vktTestCaseUtil.hpp"
28 #include "tcuMaybe.hpp"
29 #include "tcuResultCollector.hpp"
30 #include "tcuTestLog.hpp"
31 #include "tcuPlatform.hpp"
32 #include "tcuCommandLine.hpp"
34 #include "vkPlatform.hpp"
35 #include "vkStrUtil.hpp"
37 #include "vkDeviceUtil.hpp"
38 #include "vkQueryUtil.hpp"
39 #include "vkRefUtil.hpp"
40 #include "vkAllocationCallbackUtil.hpp"
42 #include "deUniquePtr.hpp"
43 #include "deStringUtil.hpp"
44 #include "deRandom.hpp"
63 // The min max for allocation count is 4096. Use 4000 to take into account
64 // possible memory allocations made by layers etc.
65 MAX_ALLOCATION_COUNT = 4000
78 Maybe<VkDeviceSize> memorySize;
79 Maybe<float> memoryPercentage;
80 deUint32 memoryAllocationCount;
85 : memoryAllocationCount ((deUint32)-1)
87 , useDeviceGroups (false)
92 struct TestConfigRandom
95 const bool useDeviceGroups;
97 TestConfigRandom (const deUint32 _seed, const bool _useDeviceGroups)
99 , useDeviceGroups (_useDeviceGroups)
104 vk::Move<VkInstance> createInstanceWithExtensions (const vk::PlatformInterface& vkp, deUint32 version, const std::vector<std::string>& enableExtensions)
106 std::vector<std::string> enableExtensionPtrs;
107 const std::vector<VkExtensionProperties> availableExtensions = enumerateInstanceExtensionProperties(vkp, DE_NULL);
108 for (size_t extensionID = 0; extensionID < enableExtensions.size(); extensionID++)
110 if (!isInstanceExtensionSupported(version, availableExtensions, RequiredExtension(enableExtensions[extensionID])))
111 TCU_THROW(NotSupportedError, (enableExtensions[extensionID] + " is not supported").c_str());
113 if (!isCoreInstanceExtension(version, enableExtensions[extensionID]))
114 enableExtensionPtrs.push_back(enableExtensions[extensionID]);
117 return createDefaultInstance(vkp, version, std::vector<std::string>() /* layers */, enableExtensionPtrs);
120 class BaseAllocateTestInstance : public TestInstance
123 BaseAllocateTestInstance (Context& context, bool useDeviceGroups)
124 : TestInstance (context)
125 , m_useDeviceGroups (useDeviceGroups)
126 , m_subsetAllocationAllowed (false)
127 , m_numPhysDevices (1)
128 , m_memoryProperties (getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()))
130 if (m_useDeviceGroups)
132 m_allocFlagsInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHR;
133 m_allocFlagsInfo.pNext = DE_NULL;
134 m_allocFlagsInfo.flags = VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT;
135 m_allocFlagsInfo.deviceMask = 0;
138 void createDeviceGroup (void);
139 const vk::DeviceInterface& getDeviceInterface (void) { return m_useDeviceGroups ? *m_deviceDriver : m_context.getDeviceInterface(); }
140 vk::VkDevice getDevice (void) { return m_useDeviceGroups ? m_logicalDevice.get() : m_context.getDevice(); }
143 bool m_useDeviceGroups;
144 bool m_subsetAllocationAllowed;
145 VkMemoryAllocateFlagsInfo m_allocFlagsInfo;
146 deUint32 m_numPhysDevices;
147 VkPhysicalDeviceMemoryProperties m_memoryProperties;
150 vk::Move<vk::VkInstance> m_deviceGroupInstance;
151 vk::Move<vk::VkDevice> m_logicalDevice;
152 de::MovePtr<vk::DeviceDriver> m_deviceDriver;
155 void BaseAllocateTestInstance::createDeviceGroup (void)
157 const tcu::CommandLine& cmdLine = m_context.getTestContext().getCommandLine();
158 const deUint32 devGroupIdx = cmdLine.getVKDeviceGroupId() - 1;
159 const deUint32 physDeviceIdx = cmdLine.getVKDeviceId() - 1;
160 const float queuePriority = 1.0f;
161 deUint32 queueFamilyIndex = 0;
162 const std::vector<std::string> requiredExtensions (1, "VK_KHR_device_group_creation");
163 m_deviceGroupInstance = createInstanceWithExtensions(m_context.getPlatformInterface(), m_context.getUsedApiVersion(), requiredExtensions);
164 std::vector<VkPhysicalDeviceGroupProperties> devGroupProperties = enumeratePhysicalDeviceGroups(m_context.getInstanceInterface(), m_deviceGroupInstance.get());
165 m_numPhysDevices = devGroupProperties[devGroupIdx].physicalDeviceCount;
166 m_subsetAllocationAllowed = devGroupProperties[devGroupIdx].subsetAllocation;
167 if (m_numPhysDevices < 2)
168 TCU_THROW(NotSupportedError, "Device group allocation tests not supported with 1 physical device");
169 std::vector<const char*> deviceExtensions;
171 if (!isCoreDeviceExtension(m_context.getUsedApiVersion(), "VK_KHR_device_group"))
172 deviceExtensions.push_back("VK_KHR_device_group");
174 VkDeviceGroupDeviceCreateInfo deviceGroupInfo =
176 VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR, //stype
178 devGroupProperties[devGroupIdx].physicalDeviceCount, //physicalDeviceCount
179 devGroupProperties[devGroupIdx].physicalDevices //physicalDevices
181 InstanceDriver instance (m_context.getPlatformInterface(), m_useDeviceGroups ? m_deviceGroupInstance.get() : m_context.getInstance());
182 const VkPhysicalDeviceFeatures deviceFeatures = getPhysicalDeviceFeatures(instance, deviceGroupInfo.pPhysicalDevices[physDeviceIdx]);
184 const std::vector<VkQueueFamilyProperties> queueProps = getPhysicalDeviceQueueFamilyProperties(instance, devGroupProperties[devGroupIdx].physicalDevices[physDeviceIdx]);
185 for (size_t queueNdx = 0; queueNdx < queueProps.size(); queueNdx++)
187 if (queueProps[queueNdx].queueFlags & VK_QUEUE_COMPUTE_BIT)
188 queueFamilyIndex = (deUint32)queueNdx;
191 VkDeviceQueueCreateInfo queueInfo =
193 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType;
194 DE_NULL, // const void* pNext;
195 (VkDeviceQueueCreateFlags)0u, // VkDeviceQueueCreateFlags flags;
196 queueFamilyIndex, // deUint32 queueFamilyIndex;
197 1u, // deUint32 queueCount;
198 &queuePriority // const float* pQueuePriorities;
201 const VkDeviceCreateInfo deviceInfo =
203 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // VkStructureType sType;
204 m_useDeviceGroups ? &deviceGroupInfo : DE_NULL, // const void* pNext;
205 (VkDeviceCreateFlags)0, // VkDeviceCreateFlags flags;
206 1u , // uint32_t queueCreateInfoCount;
207 &queueInfo, // const VkDeviceQueueCreateInfo* pQueueCreateInfos;
208 0u, // uint32_t enabledLayerCount;
209 DE_NULL, // const char* const* ppEnabledLayerNames;
210 deUint32(deviceExtensions.size()), // uint32_t enabledExtensionCount;
211 deviceExtensions.empty() ? DE_NULL : &deviceExtensions[0], // const char* const* ppEnabledExtensionNames;
212 &deviceFeatures, // const VkPhysicalDeviceFeatures* pEnabledFeatures;
214 m_logicalDevice = createDevice(instance, deviceGroupInfo.pPhysicalDevices[physDeviceIdx], &deviceInfo);
215 m_deviceDriver = de::MovePtr<DeviceDriver>(new DeviceDriver(instance, *m_logicalDevice));
216 m_memoryProperties = getPhysicalDeviceMemoryProperties(instance, deviceGroupInfo.pPhysicalDevices[physDeviceIdx]);
219 class AllocateFreeTestInstance : public BaseAllocateTestInstance
222 AllocateFreeTestInstance (Context& context, const TestConfig config)
223 : BaseAllocateTestInstance (context, config.useDeviceGroups)
225 , m_result (m_context.getTestContext().getLog())
226 , m_memoryTypeIndex (0)
228 DE_ASSERT(!!m_config.memorySize != !!m_config.memoryPercentage);
231 tcu::TestStatus iterate (void);
234 const TestConfig m_config;
235 tcu::ResultCollector m_result;
236 deUint32 m_memoryTypeIndex;
240 tcu::TestStatus AllocateFreeTestInstance::iterate (void)
242 TestLog& log = m_context.getTestContext().getLog();
243 const VkDevice device = getDevice();
244 const DeviceInterface& vkd = getDeviceInterface();
246 DE_ASSERT(m_config.memoryAllocationCount <= MAX_ALLOCATION_COUNT);
248 if (m_memoryTypeIndex == 0)
250 log << TestLog::Message << "Memory allocation count: " << m_config.memoryAllocationCount << TestLog::EndMessage;
251 log << TestLog::Message << "Single allocation size: " << (m_config.memorySize ? de::toString(*m_config.memorySize) : de::toString(100.0f * (*m_config.memoryPercentage)) + " percent of the heap size.") << TestLog::EndMessage;
253 if (m_config.order == TestConfig::ALLOC_REVERSE_FREE)
254 log << TestLog::Message << "Memory is freed in reversed order. " << TestLog::EndMessage;
255 else if (m_config.order == TestConfig::ALLOC_FREE)
256 log << TestLog::Message << "Memory is freed in same order as allocated. " << TestLog::EndMessage;
257 else if (m_config.order == TestConfig::MIXED_ALLOC_FREE)
258 log << TestLog::Message << "Memory is freed right after allocation. " << TestLog::EndMessage;
260 DE_FATAL("Unknown allocation order");
265 const VkMemoryType memoryType = m_memoryProperties.memoryTypes[m_memoryTypeIndex];
266 const VkMemoryHeap memoryHeap = m_memoryProperties.memoryHeaps[memoryType.heapIndex];
268 const VkDeviceSize allocationSize = (m_config.memorySize ? *m_config.memorySize : (VkDeviceSize)(*m_config.memoryPercentage * (float)memoryHeap.size));
269 vector<VkDeviceMemory> memoryObjects (m_config.memoryAllocationCount, (VkDeviceMemory)0);
271 log << TestLog::Message << "Memory type index: " << m_memoryTypeIndex << TestLog::EndMessage;
273 if (memoryType.heapIndex >= m_memoryProperties.memoryHeapCount)
274 m_result.fail("Invalid heap index defined for memory type.");
277 log << TestLog::Message << "Memory type: " << memoryType << TestLog::EndMessage;
278 log << TestLog::Message << "Memory heap: " << memoryHeap << TestLog::EndMessage;
280 if (allocationSize * m_config.memoryAllocationCount * 8 > memoryHeap.size)
281 TCU_THROW(NotSupportedError, "Memory heap doesn't have enough memory.");
283 #if (DE_PTR_SIZE == 4)
284 // For 32-bit binaries we cap the total host visible allocations to 1.5GB to
285 // avoid exhausting CPU virtual address space and throwing a false negative result.
286 if ((memoryType.propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) &&
287 allocationSize * m_config.memoryAllocationCount >= 1610612736)
289 log << TestLog::Message << " Skipping: Not enough CPU virtual address space for all host visible allocations." << TestLog::EndMessage;
298 const deUint32 totalDeviceMaskCombinations = m_subsetAllocationAllowed ? (1 << m_numPhysDevices) - 1 : 1;
299 for (deUint32 deviceMask = 1; deviceMask <= totalDeviceMaskCombinations; deviceMask++)
301 // Allocate on all physical devices if subset allocation is not allowed, do only once.
302 if (!m_subsetAllocationAllowed)
303 deviceMask = (1 << m_numPhysDevices) - 1;
304 m_allocFlagsInfo.deviceMask = deviceMask;
306 if (m_config.order == TestConfig::ALLOC_FREE || m_config.order == TestConfig::ALLOC_REVERSE_FREE)
308 for (size_t ndx = 0; ndx < m_config.memoryAllocationCount; ndx++)
310 VkMemoryAllocateInfo alloc =
312 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType
313 m_useDeviceGroups ? &m_allocFlagsInfo : DE_NULL, // pNext
314 allocationSize, // allocationSize
315 m_memoryTypeIndex // memoryTypeIndex;
318 VK_CHECK(vkd.allocateMemory(device, &alloc, (const VkAllocationCallbacks*)DE_NULL, &memoryObjects[ndx]));
320 TCU_CHECK(!!memoryObjects[ndx]);
323 if (m_config.order == TestConfig::ALLOC_FREE)
325 for (size_t ndx = 0; ndx < m_config.memoryAllocationCount; ndx++)
327 const VkDeviceMemory mem = memoryObjects[memoryObjects.size() - 1 - ndx];
329 vkd.freeMemory(device, mem, (const VkAllocationCallbacks*)DE_NULL);
330 memoryObjects[memoryObjects.size() - 1 - ndx] = (VkDeviceMemory)0;
335 for (size_t ndx = 0; ndx < m_config.memoryAllocationCount; ndx++)
337 const VkDeviceMemory mem = memoryObjects[ndx];
339 vkd.freeMemory(device, mem, (const VkAllocationCallbacks*)DE_NULL);
340 memoryObjects[ndx] = (VkDeviceMemory)0;
346 for (size_t ndx = 0; ndx < m_config.memoryAllocationCount; ndx++)
348 const VkMemoryAllocateInfo alloc =
350 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType
351 m_useDeviceGroups ? &m_allocFlagsInfo : DE_NULL, // pNext
352 allocationSize, // allocationSize
353 m_memoryTypeIndex // memoryTypeIndex;
356 VK_CHECK(vkd.allocateMemory(device, &alloc, (const VkAllocationCallbacks*)DE_NULL, &memoryObjects[ndx]));
357 TCU_CHECK(!!memoryObjects[ndx]);
359 vkd.freeMemory(device, memoryObjects[ndx], (const VkAllocationCallbacks*)DE_NULL);
360 memoryObjects[ndx] = (VkDeviceMemory)0;
367 for (size_t ndx = 0; ndx < m_config.memoryAllocationCount; ndx++)
369 const VkDeviceMemory mem = memoryObjects[ndx];
373 vkd.freeMemory(device, mem, (const VkAllocationCallbacks*)DE_NULL);
374 memoryObjects[ndx] = (VkDeviceMemory)0;
383 catch (const tcu::TestError& error)
385 m_result.fail(error.getMessage());
390 if (m_memoryTypeIndex < m_memoryProperties.memoryTypeCount)
391 return tcu::TestStatus::incomplete();
393 return tcu::TestStatus(m_result.getResult(), m_result.getMessage());
396 size_t computeDeviceMemorySystemMemFootprint (const DeviceInterface& vk, VkDevice device)
398 AllocationCallbackRecorder callbackRecorder (getSystemAllocator());
401 // 1 B allocation from memory type 0
402 const VkMemoryAllocateInfo allocInfo =
404 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
409 const Unique<VkDeviceMemory> memory (allocateMemory(vk, device, &allocInfo));
410 AllocationCallbackValidationResults validateRes;
412 validateAllocationCallbacks(callbackRecorder, &validateRes);
414 TCU_CHECK(validateRes.violations.empty());
416 return getLiveSystemAllocationTotal(validateRes)
417 + sizeof(void*)*validateRes.liveAllocations.size(); // allocation overhead
429 VkDeviceMemory memory;
436 VkDeviceSize memoryUsage;
437 VkDeviceSize maxMemoryUsage;
438 vector<MemoryType> types;
439 vector<MemoryObject> objects;
442 class RandomAllocFreeTestInstance : public BaseAllocateTestInstance
445 RandomAllocFreeTestInstance (Context& context, TestConfigRandom config);
446 ~RandomAllocFreeTestInstance (void);
448 tcu::TestStatus iterate (void);
451 const size_t m_opCount;
452 const size_t m_allocSysMemSize;
453 const PlatformMemoryLimits m_memoryLimits;
454 const deUint32 m_totalDeviceMaskCombinations;
456 deUint32 m_memoryObjectCount;
457 deUint32 m_currentDeviceMask;
460 vector<Heap> m_heaps;
461 VkDeviceSize m_totalSystemMem;
462 VkDeviceSize m_totalDeviceMem;
465 RandomAllocFreeTestInstance::RandomAllocFreeTestInstance (Context& context, TestConfigRandom config)
466 : BaseAllocateTestInstance (context, config.useDeviceGroups)
468 , m_allocSysMemSize (computeDeviceMemorySystemMemFootprint(getDeviceInterface(), context.getDevice())
469 + sizeof(MemoryObject))
470 , m_memoryLimits (getMemoryLimits(context.getTestContext().getPlatform().getVulkanPlatform()))
471 , m_totalDeviceMaskCombinations (m_subsetAllocationAllowed ? (1 << m_numPhysDevices) - 1 : 1)
472 , m_memoryObjectCount (0)
473 , m_currentDeviceMask (m_subsetAllocationAllowed ? 1 : (1 << m_numPhysDevices) - 1)
475 , m_rng (config.seed)
476 , m_totalSystemMem (0)
477 , m_totalDeviceMem (0)
479 TCU_CHECK(m_memoryProperties.memoryHeapCount <= 32);
480 TCU_CHECK(m_memoryProperties.memoryTypeCount <= 32);
482 m_heaps.resize(m_memoryProperties.memoryHeapCount);
484 for (deUint32 heapNdx = 0; heapNdx < m_memoryProperties.memoryHeapCount; heapNdx++)
486 m_heaps[heapNdx].heap = m_memoryProperties.memoryHeaps[heapNdx];
487 m_heaps[heapNdx].memoryUsage = 0;
488 m_heaps[heapNdx].maxMemoryUsage = m_heaps[heapNdx].heap.size / 8; /* Use at maximum 12.5% of heap */
490 m_heaps[heapNdx].objects.reserve(100);
493 for (deUint32 memoryTypeNdx = 0; memoryTypeNdx < m_memoryProperties.memoryTypeCount; memoryTypeNdx++)
495 const MemoryType type =
498 m_memoryProperties.memoryTypes[memoryTypeNdx]
501 TCU_CHECK(type.type.heapIndex < m_memoryProperties.memoryHeapCount);
503 m_heaps[type.type.heapIndex].types.push_back(type);
507 RandomAllocFreeTestInstance::~RandomAllocFreeTestInstance (void)
509 const VkDevice device = getDevice();
510 const DeviceInterface& vkd = getDeviceInterface();
512 for (deUint32 heapNdx = 0; heapNdx < (deUint32)m_heaps.size(); heapNdx++)
514 const Heap& heap = m_heaps[heapNdx];
516 for (size_t objectNdx = 0; objectNdx < heap.objects.size(); objectNdx++)
518 if (!!heap.objects[objectNdx].memory)
519 vkd.freeMemory(device, heap.objects[objectNdx].memory, (const VkAllocationCallbacks*)DE_NULL);
524 tcu::TestStatus RandomAllocFreeTestInstance::iterate (void)
526 const VkDevice device = getDevice();
527 const DeviceInterface& vkd = getDeviceInterface();
528 TestLog& log = m_context.getTestContext().getLog();
529 const bool isUMA = m_memoryLimits.totalDeviceLocalMemory == 0;
530 const VkDeviceSize usedSysMem = isUMA ? (m_totalDeviceMem+m_totalSystemMem) : m_totalSystemMem;
531 const bool canAllocateSys = usedSysMem + m_allocSysMemSize + 1024 < m_memoryLimits.totalSystemMemory; // \note Always leave room for 1 KiB sys mem alloc
532 const bool canAllocateDev = isUMA ? canAllocateSys : (m_totalDeviceMem + 16 < m_memoryLimits.totalDeviceLocalMemory);
533 vector<size_t> nonFullHeaps;
534 vector<size_t> nonEmptyHeaps;
539 log << TestLog::Message << "Performing " << m_opCount << " random VkAllocMemory() / VkFreeMemory() calls before freeing all memory." << TestLog::EndMessage;
540 log << TestLog::Message << "Using max 1/8 of the memory in each memory heap." << TestLog::EndMessage;
543 // Sort heaps based on whether allocations or frees are possible
544 for (size_t heapNdx = 0; heapNdx < m_heaps.size(); ++heapNdx)
546 const bool isDeviceLocal = (m_heaps[heapNdx].heap.flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) != 0;
547 const bool isHeapFull = m_heaps[heapNdx].memoryUsage >= m_heaps[heapNdx].maxMemoryUsage;
548 const bool isHeapEmpty = m_heaps[heapNdx].memoryUsage == 0;
551 nonEmptyHeaps.push_back(heapNdx);
553 if (!isHeapFull && ((isUMA && canAllocateSys) ||
554 (!isUMA && isDeviceLocal && canAllocateDev) ||
555 (!isUMA && !isDeviceLocal && canAllocateSys)))
556 nonFullHeaps.push_back(heapNdx);
559 if (m_opNdx >= m_opCount)
561 if (nonEmptyHeaps.empty())
563 m_currentDeviceMask++;
564 if (m_currentDeviceMask > m_totalDeviceMaskCombinations)
565 return tcu::TestStatus::pass("Pass");
569 return tcu::TestStatus::incomplete();
573 allocateMore = false;
575 else if (!nonEmptyHeaps.empty() &&
576 !nonFullHeaps.empty() &&
577 (m_memoryObjectCount < MAX_ALLOCATION_COUNT) &&
579 allocateMore = m_rng.getBool(); // Randomize if both operations are doable.
580 else if (nonEmptyHeaps.empty())
582 DE_ASSERT(canAllocateSys);
583 allocateMore = true; // Allocate more if there are no objects to free.
585 else if (nonFullHeaps.empty() || !canAllocateSys)
586 allocateMore = false; // Free objects if there is no free space for new objects.
589 allocateMore = false;
595 const size_t nonFullHeapNdx = (size_t)(m_rng.getUint32() % (deUint32)nonFullHeaps.size());
596 const size_t heapNdx = nonFullHeaps[nonFullHeapNdx];
597 Heap& heap = m_heaps[heapNdx];
598 const MemoryType& memoryType = m_rng.choose<MemoryType>(heap.types.begin(), heap.types.end());
599 const bool isDeviceLocal = (heap.heap.flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) != 0;
600 const VkDeviceSize maxAllocSize = (isDeviceLocal && !isUMA)
601 ? de::min(heap.maxMemoryUsage - heap.memoryUsage, (VkDeviceSize)m_memoryLimits.totalDeviceLocalMemory - m_totalDeviceMem)
602 : de::min(heap.maxMemoryUsage - heap.memoryUsage, (VkDeviceSize)m_memoryLimits.totalSystemMemory - usedSysMem - m_allocSysMemSize);
603 const VkDeviceSize allocationSize = 1 + (m_rng.getUint64() % maxAllocSize);
605 if ((allocationSize > (deUint64)(heap.maxMemoryUsage - heap.memoryUsage)) && (allocationSize != 1))
606 TCU_THROW(InternalError, "Test Error: trying to allocate memory more than the available heap size.");
608 const MemoryObject object =
614 heap.objects.push_back(object);
616 m_allocFlagsInfo.deviceMask = m_currentDeviceMask;
617 const VkMemoryAllocateInfo alloc =
619 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType
620 m_useDeviceGroups ? &m_allocFlagsInfo : DE_NULL, // pNext
621 object.size, // allocationSize
622 memoryType.index // memoryTypeIndex;
625 VK_CHECK(vkd.allocateMemory(device, &alloc, (const VkAllocationCallbacks*)DE_NULL, &heap.objects.back().memory));
626 TCU_CHECK(!!heap.objects.back().memory);
627 m_memoryObjectCount++;
629 heap.memoryUsage += allocationSize;
630 (isDeviceLocal ? m_totalDeviceMem : m_totalSystemMem) += allocationSize;
631 m_totalSystemMem += m_allocSysMemSize;
635 const size_t nonEmptyHeapNdx = (size_t)(m_rng.getUint32() % (deUint32)nonEmptyHeaps.size());
636 const size_t heapNdx = nonEmptyHeaps[nonEmptyHeapNdx];
637 Heap& heap = m_heaps[heapNdx];
638 const size_t memoryObjectNdx = m_rng.getUint32() % heap.objects.size();
639 MemoryObject& memoryObject = heap.objects[memoryObjectNdx];
640 const bool isDeviceLocal = (heap.heap.flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) != 0;
642 vkd.freeMemory(device, memoryObject.memory, (const VkAllocationCallbacks*)DE_NULL);
643 memoryObject.memory = (VkDeviceMemory)0;
644 m_memoryObjectCount--;
646 heap.memoryUsage -= memoryObject.size;
647 (isDeviceLocal ? m_totalDeviceMem : m_totalSystemMem) -= memoryObject.size;
648 m_totalSystemMem -= m_allocSysMemSize;
650 heap.objects[memoryObjectNdx] = heap.objects.back();
651 heap.objects.pop_back();
653 DE_ASSERT(heap.memoryUsage == 0 || !heap.objects.empty());
657 return tcu::TestStatus::incomplete();
663 tcu::TestCaseGroup* createAllocationTestsCommon (tcu::TestContext& testCtx, bool useDeviceGroups)
665 const char* name = useDeviceGroups ? "device_group_allocation" : "allocation";
666 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, name, "Memory allocation tests."));
668 const VkDeviceSize KiB = 1024;
669 const VkDeviceSize MiB = 1024 * KiB;
673 const char* const str;
675 } allocationSizes[] =
687 const int allocationPercents[] =
692 const int allocationCounts[] =
699 const char* const str;
700 const TestConfig::Order order;
703 { "forward", TestConfig::ALLOC_FREE },
704 { "reverse", TestConfig::ALLOC_REVERSE_FREE },
705 { "mixed", TestConfig::MIXED_ALLOC_FREE }
709 de::MovePtr<tcu::TestCaseGroup> basicGroup(new tcu::TestCaseGroup(testCtx, "basic", "Basic memory allocation and free tests"));
711 for (size_t allocationSizeNdx = 0; allocationSizeNdx < DE_LENGTH_OF_ARRAY(allocationSizes); allocationSizeNdx++)
713 const VkDeviceSize allocationSize = allocationSizes[allocationSizeNdx].size;
714 const char* const allocationSizeName = allocationSizes[allocationSizeNdx].str;
715 de::MovePtr<tcu::TestCaseGroup> sizeGroup (new tcu::TestCaseGroup(testCtx, ("size_" + string(allocationSizeName)).c_str(), ("Test different allocation sizes " + de::toString(allocationSize)).c_str()));
717 for (size_t orderNdx = 0; orderNdx < DE_LENGTH_OF_ARRAY(orders); orderNdx++)
719 const TestConfig::Order order = orders[orderNdx].order;
720 const char* const orderName = orders[orderNdx].str;
721 const char* const orderDescription = orderName;
722 de::MovePtr<tcu::TestCaseGroup> orderGroup (new tcu::TestCaseGroup(testCtx, orderName, orderDescription));
724 for (size_t allocationCountNdx = 0; allocationCountNdx < DE_LENGTH_OF_ARRAY(allocationCounts); allocationCountNdx++)
726 const int allocationCount = allocationCounts[allocationCountNdx];
728 if (allocationCount != -1 && allocationCount * allocationSize > 50 * MiB)
733 config.memorySize = allocationSize;
734 config.order = order;
735 config.useDeviceGroups = useDeviceGroups;
736 if (allocationCount == -1)
738 if (allocationSize < 4096)
741 config.memoryAllocationCount = de::min((deUint32)(50 * MiB / allocationSize), (deUint32)MAX_ALLOCATION_COUNT);
743 if (config.memoryAllocationCount == 0
744 || config.memoryAllocationCount == 1
745 || config.memoryAllocationCount == 10
746 || config.memoryAllocationCount == 100
747 || config.memoryAllocationCount == 1000)
751 config.memoryAllocationCount = allocationCount;
753 orderGroup->addChild(new InstanceFactory1<AllocateFreeTestInstance, TestConfig>(testCtx, tcu::NODETYPE_SELF_VALIDATE, "count_" + de::toString(config.memoryAllocationCount), "", config));
756 sizeGroup->addChild(orderGroup.release());
759 basicGroup->addChild(sizeGroup.release());
762 for (size_t allocationPercentNdx = 0; allocationPercentNdx < DE_LENGTH_OF_ARRAY(allocationPercents); allocationPercentNdx++)
764 const int allocationPercent = allocationPercents[allocationPercentNdx];
765 de::MovePtr<tcu::TestCaseGroup> percentGroup (new tcu::TestCaseGroup(testCtx, ("percent_" + de::toString(allocationPercent)).c_str(), ("Test different allocation percents " + de::toString(allocationPercent)).c_str()));
767 for (size_t orderNdx = 0; orderNdx < DE_LENGTH_OF_ARRAY(orders); orderNdx++)
769 const TestConfig::Order order = orders[orderNdx].order;
770 const char* const orderName = orders[orderNdx].str;
771 const char* const orderDescription = orderName;
772 de::MovePtr<tcu::TestCaseGroup> orderGroup (new tcu::TestCaseGroup(testCtx, orderName, orderDescription));
774 for (size_t allocationCountNdx = 0; allocationCountNdx < DE_LENGTH_OF_ARRAY(allocationCounts); allocationCountNdx++)
776 const int allocationCount = allocationCounts[allocationCountNdx];
778 if ((allocationCount != -1) && ((float)allocationCount * (float)allocationPercent >= 1.00f / 8.00f))
783 config.memoryPercentage = (float)allocationPercent / 100.0f;
784 config.order = order;
785 config.useDeviceGroups = useDeviceGroups;
787 if (allocationCount == -1)
789 config.memoryAllocationCount = de::min((deUint32)((1.00f / 8.00f) / ((float)allocationPercent / 100.0f)), (deUint32)MAX_ALLOCATION_COUNT);
791 if (config.memoryAllocationCount == 0
792 || config.memoryAllocationCount == 1
793 || config.memoryAllocationCount == 10
794 || config.memoryAllocationCount == 100
795 || config.memoryAllocationCount == 1000)
799 config.memoryAllocationCount = allocationCount;
801 orderGroup->addChild(new InstanceFactory1<AllocateFreeTestInstance, TestConfig>(testCtx, tcu::NODETYPE_SELF_VALIDATE, "count_" + de::toString(config.memoryAllocationCount), "", config));
804 percentGroup->addChild(orderGroup.release());
807 basicGroup->addChild(percentGroup.release());
810 group->addChild(basicGroup.release());
814 const deUint32 caseCount = 100;
815 de::MovePtr<tcu::TestCaseGroup> randomGroup (new tcu::TestCaseGroup(testCtx, "random", "Random memory allocation tests."));
817 for (deUint32 caseNdx = 0; caseNdx < caseCount; caseNdx++)
819 TestConfigRandom config(deInt32Hash(caseNdx ^ 32480), useDeviceGroups);
821 randomGroup->addChild(new InstanceFactory1<RandomAllocFreeTestInstance, TestConfigRandom>(testCtx, tcu::NODETYPE_SELF_VALIDATE, de::toString(caseNdx), "Random case", config));
824 group->addChild(randomGroup.release());
827 return group.release();
830 tcu::TestCaseGroup* createAllocationTests (tcu::TestContext& testCtx)
832 return createAllocationTestsCommon(testCtx, false);
835 tcu::TestCaseGroup* createDeviceGroupAllocationTests (tcu::TestContext& testCtx)
837 return createAllocationTestsCommon(testCtx, true);