1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2015 Google Inc.
6 *
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
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
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.
18 *
19 *//*!
20 * \file
21 * \brief Simple memory allocation tests.
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktMemoryAllocationTests.hpp"
25
26 #include "vktTestCaseUtil.hpp"
27
28 #include "tcuMaybe.hpp"
29 #include "tcuResultCollector.hpp"
30 #include "tcuTestLog.hpp"
31 #include "tcuPlatform.hpp"
32
33 #include "vkPlatform.hpp"
34 #include "vkStrUtil.hpp"
35 #include "vkRef.hpp"
36 #include "vkDeviceUtil.hpp"
37 #include "vkQueryUtil.hpp"
38 #include "vkRefUtil.hpp"
39 #include "vkAllocationCallbackUtil.hpp"
40
41 #include "deUniquePtr.hpp"
42 #include "deStringUtil.hpp"
43 #include "deRandom.hpp"
44
45 using tcu::Maybe;
46 using tcu::TestLog;
47
48 using std::string;
49 using std::vector;
50
51 using namespace vk;
52
53 namespace vkt
54 {
55 namespace memory
56 {
57 namespace
58 {
59
60 enum
61 {
62 // The min max for allocation count is 4096. Use 4000 to take into account
63 // possible memory allocations made by layers etc.
64 MAX_ALLOCATION_COUNT = 4000
65 };
66
67 struct TestConfig
68 {
69 enum Order
70 {
71 ALLOC_FREE,
72 ALLOC_REVERSE_FREE,
73 MIXED_ALLOC_FREE,
74 ORDER_LAST
75 };
76
77 Maybe<VkDeviceSize> memorySize;
78 Maybe<float> memoryPercentage;
79 deUint32 memoryAllocationCount;
80 Order order;
81
TestConfigvkt::memory::__anon9eb46d4e0111::TestConfig82 TestConfig (void)
83 : memoryAllocationCount ((deUint32)-1)
84 , order (ORDER_LAST)
85 {
86 }
87 };
88
89 class AllocateFreeTestInstance : public TestInstance
90 {
91 public:
AllocateFreeTestInstance(Context & context,const TestConfig config)92 AllocateFreeTestInstance (Context& context, const TestConfig config)
93 : TestInstance (context)
94 , m_config (config)
95 , m_result (m_context.getTestContext().getLog())
96 , m_memoryTypeIndex (0)
97 , m_memoryProperties (getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()))
98 {
99 DE_ASSERT(!!m_config.memorySize != !!m_config.memoryPercentage);
100 }
101
102 tcu::TestStatus iterate (void);
103
104 private:
105 const TestConfig m_config;
106 tcu::ResultCollector m_result;
107 deUint32 m_memoryTypeIndex;
108 const VkPhysicalDeviceMemoryProperties m_memoryProperties;
109 };
110
iterate(void)111 tcu::TestStatus AllocateFreeTestInstance::iterate (void)
112 {
113 TestLog& log = m_context.getTestContext().getLog();
114 const VkDevice device = m_context.getDevice();
115 const DeviceInterface& vkd = m_context.getDeviceInterface();
116
117 DE_ASSERT(m_config.memoryAllocationCount <= MAX_ALLOCATION_COUNT);
118
119 if (m_memoryTypeIndex == 0)
120 {
121 log << TestLog::Message << "Memory allocation count: " << m_config.memoryAllocationCount << TestLog::EndMessage;
122 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;
123
124 if (m_config.order == TestConfig::ALLOC_REVERSE_FREE)
125 log << TestLog::Message << "Memory is freed in reversed order. " << TestLog::EndMessage;
126 else if (m_config.order == TestConfig::ALLOC_FREE)
127 log << TestLog::Message << "Memory is freed in same order as allocated. " << TestLog::EndMessage;
128 else if (m_config.order == TestConfig::MIXED_ALLOC_FREE)
129 log << TestLog::Message << "Memory is freed right after allocation. " << TestLog::EndMessage;
130 else
131 DE_FATAL("Unknown allocation order");
132 }
133
134 try
135 {
136 const VkMemoryType memoryType = m_memoryProperties.memoryTypes[m_memoryTypeIndex];
137 const VkMemoryHeap memoryHeap = m_memoryProperties.memoryHeaps[memoryType.heapIndex];
138
139 const VkDeviceSize allocationSize = (m_config.memorySize ? *m_config.memorySize : (VkDeviceSize)(*m_config.memoryPercentage * (float)memoryHeap.size));
140 vector<VkDeviceMemory> memoryObjects (m_config.memoryAllocationCount, (VkDeviceMemory)0);
141
142 log << TestLog::Message << "Memory type index: " << m_memoryTypeIndex << TestLog::EndMessage;
143
144 if (memoryType.heapIndex >= m_memoryProperties.memoryHeapCount)
145 m_result.fail("Invalid heap index defined for memory type.");
146
147 {
148 log << TestLog::Message << "Memory type: " << memoryType << TestLog::EndMessage;
149 log << TestLog::Message << "Memory heap: " << memoryHeap << TestLog::EndMessage;
150
151 if (allocationSize * m_config.memoryAllocationCount * 8 > memoryHeap.size)
152 TCU_THROW(NotSupportedError, "Memory heap doesn't have enough memory.");
153
154 try
155 {
156 if (m_config.order == TestConfig::ALLOC_FREE || m_config.order == TestConfig::ALLOC_REVERSE_FREE)
157 {
158 for (size_t ndx = 0; ndx < m_config.memoryAllocationCount; ndx++)
159 {
160 const VkMemoryAllocateInfo alloc =
161 {
162 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType
163 DE_NULL, // pNext
164 allocationSize, // allocationSize
165 m_memoryTypeIndex // memoryTypeIndex;
166 };
167
168 VK_CHECK(vkd.allocateMemory(device, &alloc, (const VkAllocationCallbacks*)DE_NULL, &memoryObjects[ndx]));
169
170 TCU_CHECK(!!memoryObjects[ndx]);
171 }
172
173 if (m_config.order == TestConfig::ALLOC_FREE)
174 {
175 for (size_t ndx = 0; ndx < m_config.memoryAllocationCount; ndx++)
176 {
177 const VkDeviceMemory mem = memoryObjects[memoryObjects.size() - 1 - ndx];
178
179 vkd.freeMemory(device, mem, (const VkAllocationCallbacks*)DE_NULL);
180 memoryObjects[memoryObjects.size() - 1 - ndx] = (VkDeviceMemory)0;
181 }
182 }
183 else
184 {
185 for (size_t ndx = 0; ndx < m_config.memoryAllocationCount; ndx++)
186 {
187 const VkDeviceMemory mem = memoryObjects[ndx];
188
189 vkd.freeMemory(device, mem, (const VkAllocationCallbacks*)DE_NULL);
190 memoryObjects[ndx] = (VkDeviceMemory)0;
191 }
192 }
193 }
194 else
195 {
196 for (size_t ndx = 0; ndx < m_config.memoryAllocationCount; ndx++)
197 {
198 const VkMemoryAllocateInfo alloc =
199 {
200 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType
201 DE_NULL, // pNext
202 allocationSize, // allocationSize
203 m_memoryTypeIndex // memoryTypeIndex;
204 };
205
206 VK_CHECK(vkd.allocateMemory(device, &alloc, (const VkAllocationCallbacks*)DE_NULL, &memoryObjects[ndx]));
207 TCU_CHECK(!!memoryObjects[ndx]);
208
209 vkd.freeMemory(device, memoryObjects[ndx], (const VkAllocationCallbacks*)DE_NULL);
210 memoryObjects[ndx] = (VkDeviceMemory)0;
211 }
212 }
213 }
214 catch (...)
215 {
216 for (size_t ndx = 0; ndx < m_config.memoryAllocationCount; ndx++)
217 {
218 const VkDeviceMemory mem = memoryObjects[ndx];
219
220 if (!!mem)
221 {
222 vkd.freeMemory(device, mem, (const VkAllocationCallbacks*)DE_NULL);
223 memoryObjects[ndx] = (VkDeviceMemory)0;
224 }
225 }
226
227 throw;
228 }
229 }
230 }
231 catch (const tcu::TestError& error)
232 {
233 m_result.fail(error.getMessage());
234 }
235
236 m_memoryTypeIndex++;
237
238 if (m_memoryTypeIndex < m_memoryProperties.memoryTypeCount)
239 return tcu::TestStatus::incomplete();
240 else
241 return tcu::TestStatus(m_result.getResult(), m_result.getMessage());
242 }
243
computeDeviceMemorySystemMemFootprint(const DeviceInterface & vk,VkDevice device)244 size_t computeDeviceMemorySystemMemFootprint (const DeviceInterface& vk, VkDevice device)
245 {
246 AllocationCallbackRecorder callbackRecorder (getSystemAllocator());
247
248 {
249 // 1 B allocation from memory type 0
250 const VkMemoryAllocateInfo allocInfo =
251 {
252 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
253 DE_NULL,
254 1u,
255 0u,
256 };
257 const Unique<VkDeviceMemory> memory (allocateMemory(vk, device, &allocInfo));
258 AllocationCallbackValidationResults validateRes;
259
260 validateAllocationCallbacks(callbackRecorder, &validateRes);
261
262 TCU_CHECK(validateRes.violations.empty());
263
264 return getLiveSystemAllocationTotal(validateRes)
265 + sizeof(void*)*validateRes.liveAllocations.size(); // allocation overhead
266 }
267 }
268
269 struct MemoryType
270 {
271 deUint32 index;
272 VkMemoryType type;
273 };
274
275 struct MemoryObject
276 {
277 VkDeviceMemory memory;
278 VkDeviceSize size;
279 };
280
281 struct Heap
282 {
283 VkMemoryHeap heap;
284 VkDeviceSize memoryUsage;
285 VkDeviceSize maxMemoryUsage;
286 vector<MemoryType> types;
287 vector<MemoryObject> objects;
288 };
289
290 class RandomAllocFreeTestInstance : public TestInstance
291 {
292 public:
293 RandomAllocFreeTestInstance (Context& context, deUint32 seed);
294 ~RandomAllocFreeTestInstance (void);
295
296 tcu::TestStatus iterate (void);
297
298 private:
299 const size_t m_opCount;
300 const size_t m_allocSysMemSize;
301 const PlatformMemoryLimits m_memoryLimits;
302
303 deUint32 m_memoryObjectCount;
304 size_t m_opNdx;
305 de::Random m_rng;
306 vector<Heap> m_heaps;
307 VkDeviceSize m_totalSystemMem;
308 VkDeviceSize m_totalDeviceMem;
309 };
310
RandomAllocFreeTestInstance(Context & context,deUint32 seed)311 RandomAllocFreeTestInstance::RandomAllocFreeTestInstance (Context& context, deUint32 seed)
312 : TestInstance (context)
313 , m_opCount (128)
314 , m_allocSysMemSize (computeDeviceMemorySystemMemFootprint(context.getDeviceInterface(), context.getDevice())
315 + sizeof(MemoryObject))
316 , m_memoryLimits (getMemoryLimits(context.getTestContext().getPlatform().getVulkanPlatform()))
317 , m_memoryObjectCount (0)
318 , m_opNdx (0)
319 , m_rng (seed)
320 , m_totalSystemMem (0)
321 , m_totalDeviceMem (0)
322 {
323 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
324 const InstanceInterface& vki = context.getInstanceInterface();
325 const VkPhysicalDeviceMemoryProperties memoryProperties = getPhysicalDeviceMemoryProperties(vki, physicalDevice);
326
327 TCU_CHECK(memoryProperties.memoryHeapCount <= 32);
328 TCU_CHECK(memoryProperties.memoryTypeCount <= 32);
329
330 m_heaps.resize(memoryProperties.memoryHeapCount);
331
332 for (deUint32 heapNdx = 0; heapNdx < memoryProperties.memoryHeapCount; heapNdx++)
333 {
334 m_heaps[heapNdx].heap = memoryProperties.memoryHeaps[heapNdx];
335 m_heaps[heapNdx].memoryUsage = 0;
336 m_heaps[heapNdx].maxMemoryUsage = m_heaps[heapNdx].heap.size / 2; /* Use at maximum 50% of heap */
337
338 m_heaps[heapNdx].objects.reserve(100);
339 }
340
341 for (deUint32 memoryTypeNdx = 0; memoryTypeNdx < memoryProperties.memoryTypeCount; memoryTypeNdx++)
342 {
343 const MemoryType type =
344 {
345 memoryTypeNdx,
346 memoryProperties.memoryTypes[memoryTypeNdx]
347 };
348
349 TCU_CHECK(type.type.heapIndex < memoryProperties.memoryHeapCount);
350
351 m_heaps[type.type.heapIndex].types.push_back(type);
352 }
353 }
354
~RandomAllocFreeTestInstance(void)355 RandomAllocFreeTestInstance::~RandomAllocFreeTestInstance (void)
356 {
357 const VkDevice device = m_context.getDevice();
358 const DeviceInterface& vkd = m_context.getDeviceInterface();
359
360 for (deUint32 heapNdx = 0; heapNdx < (deUint32)m_heaps.size(); heapNdx++)
361 {
362 const Heap& heap = m_heaps[heapNdx];
363
364 for (size_t objectNdx = 0; objectNdx < heap.objects.size(); objectNdx++)
365 {
366 if (!!heap.objects[objectNdx].memory)
367 vkd.freeMemory(device, heap.objects[objectNdx].memory, (const VkAllocationCallbacks*)DE_NULL);
368 }
369 }
370 }
371
iterate(void)372 tcu::TestStatus RandomAllocFreeTestInstance::iterate (void)
373 {
374 const VkDevice device = m_context.getDevice();
375 const DeviceInterface& vkd = m_context.getDeviceInterface();
376 TestLog& log = m_context.getTestContext().getLog();
377 const bool isUMA = m_memoryLimits.totalDeviceLocalMemory == 0;
378 const VkDeviceSize usedSysMem = isUMA ? (m_totalDeviceMem+m_totalSystemMem) : m_totalSystemMem;
379 const bool canAllocateSys = usedSysMem + m_allocSysMemSize + 1024 < m_memoryLimits.totalSystemMemory; // \note Always leave room for 1 KiB sys mem alloc
380 const bool canAllocateDev = isUMA ? canAllocateSys : (m_totalDeviceMem + 16 < m_memoryLimits.totalDeviceLocalMemory);
381 vector<size_t> nonFullHeaps;
382 vector<size_t> nonEmptyHeaps;
383 bool allocateMore;
384
385 if (m_opNdx == 0)
386 {
387 log << TestLog::Message << "Performing " << m_opCount << " random VkAllocMemory() / VkFreeMemory() calls before freeing all memory." << TestLog::EndMessage;
388 log << TestLog::Message << "Using max 1/8 of the memory in each memory heap." << TestLog::EndMessage;
389 }
390
391 // Sort heaps based on whether allocations or frees are possible
392 for (size_t heapNdx = 0; heapNdx < m_heaps.size(); ++heapNdx)
393 {
394 const bool isDeviceLocal = (m_heaps[heapNdx].heap.flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) != 0;
395 const bool isHeapFull = m_heaps[heapNdx].memoryUsage >= m_heaps[heapNdx].maxMemoryUsage;
396 const bool isHeapEmpty = m_heaps[heapNdx].memoryUsage == 0;
397
398 if (!isHeapEmpty)
399 nonEmptyHeaps.push_back(heapNdx);
400
401 if (!isHeapFull && ((isUMA && canAllocateSys) ||
402 (!isUMA && isDeviceLocal && canAllocateDev) ||
403 (!isUMA && !isDeviceLocal && canAllocateSys)))
404 nonFullHeaps.push_back(heapNdx);
405 }
406
407 if (m_opNdx >= m_opCount)
408 {
409 if (nonEmptyHeaps.empty())
410 return tcu::TestStatus::pass("Pass");
411 else
412 allocateMore = false;
413 }
414 else if (!nonEmptyHeaps.empty() &&
415 !nonFullHeaps.empty() &&
416 (m_memoryObjectCount < MAX_ALLOCATION_COUNT) &&
417 canAllocateSys)
418 allocateMore = m_rng.getBool(); // Randomize if both operations are doable.
419 else if (nonEmptyHeaps.empty())
420 {
421 DE_ASSERT(canAllocateSys);
422 allocateMore = true; // Allocate more if there are no objects to free.
423 }
424 else if (nonFullHeaps.empty() || !canAllocateSys)
425 allocateMore = false; // Free objects if there is no free space for new objects.
426 else
427 {
428 allocateMore = false;
429 DE_FATAL("Fail");
430 }
431
432 if (allocateMore)
433 {
434 const size_t nonFullHeapNdx = (size_t)(m_rng.getUint32() % (deUint32)nonFullHeaps.size());
435 const size_t heapNdx = nonFullHeaps[nonFullHeapNdx];
436 Heap& heap = m_heaps[heapNdx];
437 const MemoryType& memoryType = m_rng.choose<MemoryType>(heap.types.begin(), heap.types.end());
438 const bool isDeviceLocal = (heap.heap.flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) != 0;
439 const VkDeviceSize maxAllocSize = (isDeviceLocal && !isUMA)
440 ? de::min(heap.maxMemoryUsage - heap.memoryUsage, (VkDeviceSize)m_memoryLimits.totalDeviceLocalMemory - m_totalDeviceMem)
441 : de::min(heap.maxMemoryUsage - heap.memoryUsage, (VkDeviceSize)m_memoryLimits.totalSystemMemory - usedSysMem - m_allocSysMemSize);
442 const VkDeviceSize allocationSize = 1 + (m_rng.getUint64() % maxAllocSize);
443
444 if ((allocationSize > (deUint64)(heap.maxMemoryUsage - heap.memoryUsage)) && (allocationSize != 1))
445 TCU_THROW(InternalError, "Test Error: trying to allocate memory more than the available heap size.");
446
447 const MemoryObject object =
448 {
449 (VkDeviceMemory)0,
450 allocationSize
451 };
452
453 heap.objects.push_back(object);
454
455 const VkMemoryAllocateInfo alloc =
456 {
457 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType
458 DE_NULL, // pNext
459 object.size, // allocationSize
460 memoryType.index // memoryTypeIndex;
461 };
462
463 VK_CHECK(vkd.allocateMemory(device, &alloc, (const VkAllocationCallbacks*)DE_NULL, &heap.objects.back().memory));
464 TCU_CHECK(!!heap.objects.back().memory);
465 m_memoryObjectCount++;
466
467 heap.memoryUsage += allocationSize;
468 (isDeviceLocal ? m_totalDeviceMem : m_totalSystemMem) += allocationSize;
469 m_totalSystemMem += m_allocSysMemSize;
470 }
471 else
472 {
473 const size_t nonEmptyHeapNdx = (size_t)(m_rng.getUint32() % (deUint32)nonEmptyHeaps.size());
474 const size_t heapNdx = nonEmptyHeaps[nonEmptyHeapNdx];
475 Heap& heap = m_heaps[heapNdx];
476 const size_t memoryObjectNdx = m_rng.getUint32() % heap.objects.size();
477 MemoryObject& memoryObject = heap.objects[memoryObjectNdx];
478 const bool isDeviceLocal = (heap.heap.flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) != 0;
479
480 vkd.freeMemory(device, memoryObject.memory, (const VkAllocationCallbacks*)DE_NULL);
481 memoryObject.memory = (VkDeviceMemory)0;
482 m_memoryObjectCount--;
483
484 heap.memoryUsage -= memoryObject.size;
485 (isDeviceLocal ? m_totalDeviceMem : m_totalSystemMem) -= memoryObject.size;
486 m_totalSystemMem -= m_allocSysMemSize;
487
488 heap.objects[memoryObjectNdx] = heap.objects.back();
489 heap.objects.pop_back();
490
491 DE_ASSERT(heap.memoryUsage == 0 || !heap.objects.empty());
492 }
493
494 m_opNdx++;
495 return tcu::TestStatus::incomplete();
496 }
497
498
499 } // anonymous
500
createAllocationTests(tcu::TestContext & testCtx)501 tcu::TestCaseGroup* createAllocationTests (tcu::TestContext& testCtx)
502 {
503 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "allocation", "Memory allocation tests."));
504
505 const VkDeviceSize KiB = 1024;
506 const VkDeviceSize MiB = 1024 * KiB;
507
508 const struct
509 {
510 const char* const str;
511 VkDeviceSize size;
512 } allocationSizes[] =
513 {
514 { "64", 64 },
515 { "128", 128 },
516 { "256", 256 },
517 { "512", 512 },
518 { "1KiB", 1*KiB },
519 { "4KiB", 4*KiB },
520 { "8KiB", 8*KiB },
521 { "1MiB", 1*MiB }
522 };
523
524 const int allocationPercents[] =
525 {
526 1
527 };
528
529 const int allocationCounts[] =
530 {
531 1, 10, 100, 1000, -1
532 };
533
534 const struct
535 {
536 const char* const str;
537 const TestConfig::Order order;
538 } orders[] =
539 {
540 { "forward", TestConfig::ALLOC_FREE },
541 { "reverse", TestConfig::ALLOC_REVERSE_FREE },
542 { "mixed", TestConfig::MIXED_ALLOC_FREE }
543 };
544
545 {
546 de::MovePtr<tcu::TestCaseGroup> basicGroup (new tcu::TestCaseGroup(testCtx, "basic", "Basic memory allocation and free tests"));
547
548 for (size_t allocationSizeNdx = 0; allocationSizeNdx < DE_LENGTH_OF_ARRAY(allocationSizes); allocationSizeNdx++)
549 {
550 const VkDeviceSize allocationSize = allocationSizes[allocationSizeNdx].size;
551 const char* const allocationSizeName = allocationSizes[allocationSizeNdx].str;
552 de::MovePtr<tcu::TestCaseGroup> sizeGroup (new tcu::TestCaseGroup(testCtx, ("size_" + string(allocationSizeName)).c_str(), ("Test different allocation sizes " + de::toString(allocationSize)).c_str()));
553
554 for (size_t orderNdx = 0; orderNdx < DE_LENGTH_OF_ARRAY(orders); orderNdx++)
555 {
556 const TestConfig::Order order = orders[orderNdx].order;
557 const char* const orderName = orders[orderNdx].str;
558 const char* const orderDescription = orderName;
559 de::MovePtr<tcu::TestCaseGroup> orderGroup (new tcu::TestCaseGroup(testCtx, orderName, orderDescription));
560
561 for (size_t allocationCountNdx = 0; allocationCountNdx < DE_LENGTH_OF_ARRAY(allocationCounts); allocationCountNdx++)
562 {
563 const int allocationCount = allocationCounts[allocationCountNdx];
564
565 if (allocationCount != -1 && allocationCount * allocationSize > 50 * MiB)
566 continue;
567
568 TestConfig config;
569
570 config.memorySize = allocationSize;
571 config.order = order;
572
573 if (allocationCount == -1)
574 {
575 if (allocationSize < 4096)
576 continue;
577
578 config.memoryAllocationCount = de::min((deUint32)(50 * MiB / allocationSize), (deUint32)MAX_ALLOCATION_COUNT);
579
580 if (config.memoryAllocationCount == 0
581 || config.memoryAllocationCount == 1
582 || config.memoryAllocationCount == 10
583 || config.memoryAllocationCount == 100
584 || config.memoryAllocationCount == 1000)
585 continue;
586 }
587 else
588 config.memoryAllocationCount = allocationCount;
589
590 orderGroup->addChild(new InstanceFactory1<AllocateFreeTestInstance, TestConfig>(testCtx, tcu::NODETYPE_SELF_VALIDATE, "count_" + de::toString(config.memoryAllocationCount), "", config));
591 }
592
593 sizeGroup->addChild(orderGroup.release());
594 }
595
596 basicGroup->addChild(sizeGroup.release());
597 }
598
599 for (size_t allocationPercentNdx = 0; allocationPercentNdx < DE_LENGTH_OF_ARRAY(allocationPercents); allocationPercentNdx++)
600 {
601 const int allocationPercent = allocationPercents[allocationPercentNdx];
602 de::MovePtr<tcu::TestCaseGroup> percentGroup (new tcu::TestCaseGroup(testCtx, ("percent_" + de::toString(allocationPercent)).c_str(), ("Test different allocation percents " + de::toString(allocationPercent)).c_str()));
603
604 for (size_t orderNdx = 0; orderNdx < DE_LENGTH_OF_ARRAY(orders); orderNdx++)
605 {
606 const TestConfig::Order order = orders[orderNdx].order;
607 const char* const orderName = orders[orderNdx].str;
608 const char* const orderDescription = orderName;
609 de::MovePtr<tcu::TestCaseGroup> orderGroup (new tcu::TestCaseGroup(testCtx, orderName, orderDescription));
610
611 for (size_t allocationCountNdx = 0; allocationCountNdx < DE_LENGTH_OF_ARRAY(allocationCounts); allocationCountNdx++)
612 {
613 const int allocationCount = allocationCounts[allocationCountNdx];
614
615 if ((allocationCount != -1) && ((float)allocationCount * (float)allocationPercent >= 1.00f / 8.00f))
616 continue;
617
618 TestConfig config;
619
620 config.memoryPercentage = (float)allocationPercent / 100.0f;
621 config.order = order;
622
623 if (allocationCount == -1)
624 {
625 config.memoryAllocationCount = de::min((deUint32)((1.00f / 8.00f) / ((float)allocationPercent / 100.0f)), (deUint32)MAX_ALLOCATION_COUNT);
626
627 if (config.memoryAllocationCount == 0
628 || config.memoryAllocationCount == 1
629 || config.memoryAllocationCount == 10
630 || config.memoryAllocationCount == 100
631 || config.memoryAllocationCount == 1000)
632 continue;
633 }
634 else
635 config.memoryAllocationCount = allocationCount;
636
637 orderGroup->addChild(new InstanceFactory1<AllocateFreeTestInstance, TestConfig>(testCtx, tcu::NODETYPE_SELF_VALIDATE, "count_" + de::toString(config.memoryAllocationCount), "", config));
638 }
639
640 percentGroup->addChild(orderGroup.release());
641 }
642
643 basicGroup->addChild(percentGroup.release());
644 }
645
646 group->addChild(basicGroup.release());
647 }
648
649 {
650 const deUint32 caseCount = 100;
651 de::MovePtr<tcu::TestCaseGroup> randomGroup (new tcu::TestCaseGroup(testCtx, "random", "Random memory allocation tests."));
652
653 for (deUint32 caseNdx = 0; caseNdx < caseCount; caseNdx++)
654 {
655 const deUint32 seed = deInt32Hash(caseNdx ^ 32480);
656
657 randomGroup->addChild(new InstanceFactory1<RandomAllocFreeTestInstance, deUint32>(testCtx, tcu::NODETYPE_SELF_VALIDATE, de::toString(caseNdx), "Random case", seed));
658 }
659
660 group->addChild(randomGroup.release());
661 }
662
663 return group.release();
664 }
665
666 } // memory
667 } // vkt
668