8a3ff9243967f117f27e2d66710236b73bc6a10f
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / memory / vktMemoryAllocationTests.cpp
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 Google Inc.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and/or associated documentation files (the
9  * "Materials"), to deal in the Materials without restriction, including
10  * without limitation the rights to use, copy, modify, merge, publish,
11  * distribute, sublicense, and/or sell copies of the Materials, and to
12  * permit persons to whom the Materials are furnished to do so, subject to
13  * the following conditions:
14  *
15  * The above copyright notice(s) and this permission notice shall be
16  * included in all copies or substantial portions of the Materials.
17  *
18  * The Materials are Confidential Information as defined by the
19  * Khronos Membership Agreement until designated non-confidential by
20  * Khronos, at which point this condition clause shall be removed.
21  *
22  * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
26  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28  * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
29  *
30  *//*!
31  * \file
32  * \brief Simple memory allocation tests.
33  *//*--------------------------------------------------------------------*/
34
35 #include "vktMemoryAllocationTests.hpp"
36
37 #include "vktTestCaseUtil.hpp"
38
39 #include "tcuMaybe.hpp"
40 #include "tcuResultCollector.hpp"
41 #include "tcuTestLog.hpp"
42
43 #include "vkPlatform.hpp"
44 #include "vkStrUtil.hpp"
45 #include "vkRef.hpp"
46 #include "vkDeviceUtil.hpp"
47 #include "vkQueryUtil.hpp"
48
49 #include "deUniquePtr.hpp"
50 #include "deStringUtil.hpp"
51 #include "deRandom.hpp"
52
53 using tcu::Maybe;
54 using tcu::TestLog;
55
56 using std::string;
57 using std::vector;
58
59 using namespace vk;
60
61 namespace vkt
62 {
63 namespace memory
64 {
65 namespace
66 {
67
68 struct TestConfig
69 {
70         enum Order
71         {
72                 ALLOC_FREE,
73                 ALLOC_REVERSE_FREE,
74                 MIXED_ALLOC_FREE,
75                 ORDER_LAST
76         };
77
78         Maybe<VkDeviceSize>     memorySize;
79         Maybe<float>            memoryPercentage;
80         deUint32                        memoryAllocationCount;
81         Order                           order;
82
83         TestConfig (void)
84                 : memoryAllocationCount ((deUint32)-1)
85                 , order                                 (ORDER_LAST)
86         {
87         }
88 };
89
90 class AllocateFreeTestInstance : public TestInstance
91 {
92 public:
93                                                 AllocateFreeTestInstance                (Context& context, const TestConfig config)
94                 : TestInstance                  (context)
95                 , m_config                              (config)
96                 , m_result                              (m_context.getTestContext().getLog())
97                 , m_memoryTypeIndex             (0)
98                 , m_memoryProperties    (getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()))
99         {
100                 DE_ASSERT(!!m_config.memorySize != !!m_config.memoryPercentage);
101         }
102
103         tcu::TestStatus         iterate                                                 (void);
104
105 private:
106         const TestConfig                                                m_config;
107         tcu::ResultCollector                                    m_result;
108         deUint32                                                                m_memoryTypeIndex;
109         const VkPhysicalDeviceMemoryProperties  m_memoryProperties;
110 };
111
112 tcu::TestStatus AllocateFreeTestInstance::iterate (void)
113 {
114         TestLog&                                                                log                                     = m_context.getTestContext().getLog();
115         const VkDevice                                                  device                          = m_context.getDevice();
116         const DeviceInterface&                                  vkd                                     = m_context.getDeviceInterface();
117
118         if (m_memoryTypeIndex == 0)
119         {
120                 log << TestLog::Message << "Memory allocation count: " << m_config.memoryAllocationCount << TestLog::EndMessage;
121                 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;
122
123                 if (m_config.order == TestConfig::ALLOC_REVERSE_FREE)
124                         log << TestLog::Message << "Memory is freed in reversed order. " << TestLog::EndMessage;
125                 else if (m_config.order == TestConfig::ALLOC_FREE)
126                         log << TestLog::Message << "Memory is freed in same order as allocated. " << TestLog::EndMessage;
127                 else if (m_config.order == TestConfig::MIXED_ALLOC_FREE)
128                         log << TestLog::Message << "Memory is freed right after allocation. " << TestLog::EndMessage;
129                 else
130                         DE_FATAL("Unknown allocation order");
131         }
132
133         try
134         {
135                 const VkMemoryType              memoryType              = m_memoryProperties.memoryTypes[m_memoryTypeIndex];
136                 const VkMemoryHeap              memoryHeap              = m_memoryProperties.memoryHeaps[memoryType.heapIndex];
137
138                 const VkDeviceSize              allocationSize  = (m_config.memorySize ? *m_config.memorySize : (VkDeviceSize)(*m_config.memoryPercentage * (float)memoryHeap.size));
139                 vector<VkDeviceMemory>  memoryObjects   (m_config.memoryAllocationCount, (VkDeviceMemory)0);
140
141                 log << TestLog::Message << "Memory type index: " << m_memoryTypeIndex << TestLog::EndMessage;
142
143                 if (memoryType.heapIndex >= m_memoryProperties.memoryHeapCount)
144                         m_result.fail("Invalid heap index defined for memory type.");
145
146                 {
147                         log << TestLog::Message << "Memory type: " << memoryType << TestLog::EndMessage;
148                         log << TestLog::Message << "Memory heap: " << memoryHeap << TestLog::EndMessage;
149
150                         if (allocationSize * m_config.memoryAllocationCount * 8 > memoryHeap.size)
151                                 TCU_THROW(NotSupportedError, "Memory heap doesn't have enough memory.");
152
153                         try
154                         {
155                                 if (m_config.order == TestConfig::ALLOC_FREE || m_config.order == TestConfig::ALLOC_REVERSE_FREE)
156                                 {
157                                         for (size_t ndx = 0; ndx < m_config.memoryAllocationCount; ndx++)
158                                         {
159                                                 const VkMemoryAllocateInfo alloc =
160                                                 {
161                                                         VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType
162                                                         DE_NULL,                                                                // pNext
163                                                         allocationSize,                                                 // allocationSize
164                                                         m_memoryTypeIndex                                               // memoryTypeIndex;
165                                                 };
166
167                                                 VK_CHECK(vkd.allocateMemory(device, &alloc, (const VkAllocationCallbacks*)DE_NULL, &memoryObjects[ndx]));
168
169                                                 TCU_CHECK(!!memoryObjects[ndx]);
170                                         }
171
172                                         if (m_config.order == TestConfig::ALLOC_FREE)
173                                         {
174                                                 for (size_t ndx = 0; ndx < m_config.memoryAllocationCount; ndx++)
175                                                 {
176                                                         const VkDeviceMemory mem = memoryObjects[memoryObjects.size() - 1 - ndx];
177
178                                                         vkd.freeMemory(device, mem, (const VkAllocationCallbacks*)DE_NULL);
179                                                         memoryObjects[memoryObjects.size() - 1 - ndx] = (VkDeviceMemory)0;
180                                                 }
181                                         }
182                                         else
183                                         {
184                                                 for (size_t ndx = 0; ndx < m_config.memoryAllocationCount; ndx++)
185                                                 {
186                                                         const VkDeviceMemory mem = memoryObjects[ndx];
187
188                                                         vkd.freeMemory(device, mem, (const VkAllocationCallbacks*)DE_NULL);
189                                                         memoryObjects[ndx] = (VkDeviceMemory)0;
190                                                 }
191                                         }
192                                 }
193                                 else
194                                 {
195                                         for (size_t ndx = 0; ndx < m_config.memoryAllocationCount; ndx++)
196                                         {
197                                                 const VkMemoryAllocateInfo alloc =
198                                                 {
199                                                         VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType
200                                                         DE_NULL,                                                                // pNext
201                                                         allocationSize,                                                 // allocationSize
202                                                         m_memoryTypeIndex                                               // memoryTypeIndex;
203                                                 };
204
205                                                 VK_CHECK(vkd.allocateMemory(device, &alloc, (const VkAllocationCallbacks*)DE_NULL, &memoryObjects[ndx]));
206                                                 TCU_CHECK(!!memoryObjects[ndx]);
207
208                                                 vkd.freeMemory(device, memoryObjects[ndx], (const VkAllocationCallbacks*)DE_NULL);
209                                                 memoryObjects[ndx] = (VkDeviceMemory)0;
210                                         }
211                                 }
212                         }
213                         catch (...)
214                         {
215                                 for (size_t ndx = 0; ndx < m_config.memoryAllocationCount; ndx++)
216                                 {
217                                         const VkDeviceMemory mem = memoryObjects[ndx];
218
219                                         if (!!mem)
220                                         {
221                                                 vkd.freeMemory(device, mem, (const VkAllocationCallbacks*)DE_NULL);
222                                                 memoryObjects[ndx] = (VkDeviceMemory)0;
223                                         }
224                                 }
225
226                                 throw;
227                         }
228                 }
229         }
230         catch (const tcu::TestError& error)
231         {
232                 m_result.fail(error.getMessage());
233         }
234
235         m_memoryTypeIndex++;
236
237         if (m_memoryTypeIndex < m_memoryProperties.memoryTypeCount)
238                 return tcu::TestStatus::incomplete();
239         else
240                 return tcu::TestStatus(m_result.getResult(), m_result.getMessage());
241 }
242
243 struct MemoryType
244 {
245         deUint32                index;
246         VkMemoryType    type;
247 };
248
249 struct MemoryObject
250 {
251         VkDeviceMemory  memory;
252         VkDeviceSize    size;
253 };
254
255 struct Heap
256 {
257         VkMemoryHeap                    heap;
258         VkDeviceSize                    memoryUsage;
259         VkDeviceSize                    maxMemoryUsage;
260         vector<MemoryType>              types;
261         vector<MemoryObject>    objects;
262 };
263
264 class RandomAllocFreeTestInstance : public TestInstance
265 {
266 public:
267                                                 RandomAllocFreeTestInstance             (Context& context, deUint32 seed);
268                                                 ~RandomAllocFreeTestInstance    (void);
269
270         tcu::TestStatus         iterate                                                 (void);
271
272 private:
273         const size_t            m_opCount;
274         size_t                          m_opNdx;
275         de::Random                      m_rng;
276         vector<Heap>            m_heaps;
277         vector<size_t>          m_nonFullHeaps;
278         vector<size_t>          m_nonEmptyHeaps;
279 };
280
281 RandomAllocFreeTestInstance::RandomAllocFreeTestInstance        (Context& context, deUint32 seed)
282         : TestInstance  (context)
283         , m_opCount             (128)
284         , m_opNdx               (0)
285         , m_rng                 (seed)
286 {
287         const VkPhysicalDevice                                  physicalDevice          = context.getPhysicalDevice();
288         const InstanceInterface&                                vki                                     = context.getInstanceInterface();
289         const VkPhysicalDeviceMemoryProperties  memoryProperties        = getPhysicalDeviceMemoryProperties(vki, physicalDevice);
290
291         TCU_CHECK(memoryProperties.memoryHeapCount <= 32);
292         TCU_CHECK(memoryProperties.memoryTypeCount <= 32);
293
294         m_heaps.resize(memoryProperties.memoryHeapCount);
295
296         m_nonFullHeaps.reserve(m_heaps.size());
297         m_nonEmptyHeaps.reserve(m_heaps.size());
298
299         for (deUint32 heapNdx = 0; heapNdx < memoryProperties.memoryHeapCount; heapNdx++)
300         {
301                 m_heaps[heapNdx].heap                   = memoryProperties.memoryHeaps[heapNdx];
302                 m_heaps[heapNdx].memoryUsage    = 0;
303                 m_heaps[heapNdx].maxMemoryUsage = m_heaps[heapNdx].heap.size / 8;
304
305                 m_heaps[heapNdx].objects.reserve(100);
306
307                 m_nonFullHeaps.push_back((size_t)heapNdx);
308         }
309
310         for (deUint32 memoryTypeNdx = 0; memoryTypeNdx < memoryProperties.memoryTypeCount; memoryTypeNdx++)
311         {
312                 const MemoryType type =
313                 {
314                         memoryTypeNdx,
315                         memoryProperties.memoryTypes[memoryTypeNdx]
316                 };
317
318                 TCU_CHECK(type.type.heapIndex < memoryProperties.memoryHeapCount);
319
320                 m_heaps[type.type.heapIndex].types.push_back(type);
321         }
322 }
323
324 RandomAllocFreeTestInstance::~RandomAllocFreeTestInstance (void)
325 {
326         const VkDevice                                                  device                          = m_context.getDevice();
327         const DeviceInterface&                                  vkd                                     = m_context.getDeviceInterface();
328
329         for (deUint32 heapNdx = 0; heapNdx < (deUint32)m_heaps.size(); heapNdx++)
330         {
331                 const Heap&     heap    = m_heaps[heapNdx];
332
333                 for (size_t objectNdx = 0; objectNdx < heap.objects.size(); objectNdx++)
334                 {
335                         if (!!heap.objects[objectNdx].memory)
336                                 vkd.freeMemory(device, heap.objects[objectNdx].memory, (const VkAllocationCallbacks*)DE_NULL);
337                 }
338         }
339 }
340
341 tcu::TestStatus RandomAllocFreeTestInstance::iterate (void)
342 {
343         const VkDevice                  device                  = m_context.getDevice();
344         const DeviceInterface&  vkd                             = m_context.getDeviceInterface();
345         TestLog&                                log                             = m_context.getTestContext().getLog();
346         bool                                    allocateMore;
347
348         if (m_opNdx == 0)
349         {
350                 log << TestLog::Message << "Performing " << m_opCount << " random VkAllocMemory() / VkFreeMemory() calls before freeing all memory." << TestLog::EndMessage;
351                 log << TestLog::Message << "Using max 1/8 of the memory in each memory heap." << TestLog::EndMessage;
352         }
353
354         if (m_opNdx >= m_opCount)
355         {
356                 if (m_nonEmptyHeaps.empty())
357                         return tcu::TestStatus::pass("Pass");
358                 else
359                         allocateMore = false;
360         }
361         else if (!m_nonEmptyHeaps.empty() && !m_nonFullHeaps.empty())
362                 allocateMore = m_rng.getBool(); // Randomize if both operations are doable.
363         else if (m_nonEmptyHeaps.empty())
364                 allocateMore = true; // Allocate more if there are no objects to free.
365         else if (m_nonFullHeaps.empty())
366                 allocateMore = false; // Free objects if there is no free space for new objects.
367         else
368         {
369                 allocateMore = false;
370                 DE_FATAL("Fail");
371         }
372
373         if (allocateMore)
374         {
375                 const size_t            nonFullHeapNdx  = (size_t)(m_rng.getUint32() % (deUint32)m_nonFullHeaps.size());
376                 const size_t            heapNdx                 = m_nonFullHeaps[nonFullHeapNdx];
377                 Heap&                           heap                    = m_heaps[heapNdx];
378                 const MemoryType&       memoryType              = m_rng.choose<MemoryType>(heap.types.begin(), heap.types.end());
379                 const VkDeviceSize      allocationSize  = 1 + (m_rng.getUint64() % (deUint64)(heap.maxMemoryUsage - heap.memoryUsage));
380
381
382                 if ((allocationSize > (deUint64)(heap.maxMemoryUsage - heap.memoryUsage)) && (allocationSize != 1))
383                         TCU_THROW(InternalError, "Test Error: trying to allocate memory more than the available heap size.");
384
385
386                 const MemoryObject object =
387                 {
388                         (VkDeviceMemory)0,
389                         allocationSize
390                 };
391
392                 heap.objects.push_back(object);
393
394                 const VkMemoryAllocateInfo alloc =
395                 {
396                         VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType
397                         DE_NULL,                                                                // pNext
398                         object.size,                                                    // allocationSize
399                         memoryType.index                                                // memoryTypeIndex;
400                 };
401
402                 VK_CHECK(vkd.allocateMemory(device, &alloc, (const VkAllocationCallbacks*)DE_NULL, &heap.objects.back().memory));
403                 TCU_CHECK(!!heap.objects.back().memory);
404
405                 // If heap was empty add to the non empty heaps.
406                 if (heap.memoryUsage == 0)
407                 {
408                         DE_ASSERT(heap.objects.size() == 1);
409                         m_nonEmptyHeaps.push_back(heapNdx);
410                 }
411                 else
412                         DE_ASSERT(heap.objects.size() > 1);
413
414                 heap.memoryUsage += allocationSize;
415
416                 // If heap became full, remove from non full heaps.
417                 if (heap.memoryUsage >= heap.maxMemoryUsage)
418                 {
419                         m_nonFullHeaps[nonFullHeapNdx] = m_nonFullHeaps.back();
420                         m_nonFullHeaps.pop_back();
421                 }
422         }
423         else
424         {
425                 const size_t            nonEmptyHeapNdx = (size_t)(m_rng.getUint32() % (deUint32)m_nonEmptyHeaps.size());
426                 const size_t            heapNdx                 = m_nonEmptyHeaps[nonEmptyHeapNdx];
427                 Heap&                           heap                    = m_heaps[heapNdx];
428                 const size_t            memoryObjectNdx = m_rng.getUint32() % heap.objects.size();
429                 MemoryObject&           memoryObject    = heap.objects[memoryObjectNdx];
430
431                 vkd.freeMemory(device, memoryObject.memory, (const VkAllocationCallbacks*)DE_NULL);
432                 memoryObject.memory = (VkDeviceMemory)0;
433
434                 if (heap.memoryUsage >= heap.maxMemoryUsage && heap.memoryUsage - memoryObject.size < heap.maxMemoryUsage)
435                         m_nonFullHeaps.push_back(heapNdx);
436
437                 heap.memoryUsage -= memoryObject.size;
438
439                 heap.objects[memoryObjectNdx] = heap.objects.back();
440                 heap.objects.pop_back();
441
442                 if (heap.memoryUsage == 0)
443                 {
444                         DE_ASSERT(heap.objects.empty());
445
446                         m_nonEmptyHeaps[nonEmptyHeapNdx] = m_nonEmptyHeaps.back();
447                         m_nonEmptyHeaps.pop_back();
448                 }
449                 else
450                         DE_ASSERT(!heap.objects.empty());
451         }
452
453         m_opNdx++;
454         return tcu::TestStatus::incomplete();
455 }
456
457
458 } // anonymous
459
460 tcu::TestCaseGroup* createAllocationTests (tcu::TestContext& testCtx)
461 {
462         de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "allocation", "Memory allocation tests."));
463
464         const VkDeviceSize      KiB     = 1024;
465         const VkDeviceSize      MiB     = 1024 * KiB;
466
467         const struct
468         {
469                 const char* const       str;
470                 VkDeviceSize            size;
471         } allocationSizes[] =
472         {
473                 {   "64", 64 },
474                 {  "128", 128 },
475                 {  "256", 256 },
476                 {  "512", 512 },
477                 { "1KiB", 1*KiB },
478                 { "4KiB", 4*KiB },
479                 { "8KiB", 8*KiB },
480                 { "1MiB", 1*MiB }
481         };
482
483         const int allocationPercents[] =
484         {
485                 1
486         };
487
488         const int allocationCounts[] =
489         {
490                 1, 10, 100, 1000, -1
491         };
492
493         const struct
494         {
495                 const char* const               str;
496                 const TestConfig::Order order;
497         } orders[] =
498         {
499                 { "forward",    TestConfig::ALLOC_FREE },
500                 { "reverse",    TestConfig::ALLOC_REVERSE_FREE },
501                 { "mixed",              TestConfig::MIXED_ALLOC_FREE }
502         };
503
504         {
505                 de::MovePtr<tcu::TestCaseGroup> basicGroup      (new tcu::TestCaseGroup(testCtx, "basic", "Basic memory allocation and free tests"));
506
507                 for (size_t allocationSizeNdx = 0; allocationSizeNdx < DE_LENGTH_OF_ARRAY(allocationSizes); allocationSizeNdx++)
508                 {
509                         const VkDeviceSize                              allocationSize          = allocationSizes[allocationSizeNdx].size;
510                         const char* const                               allocationSizeName      = allocationSizes[allocationSizeNdx].str;
511                         de::MovePtr<tcu::TestCaseGroup> sizeGroup                       (new tcu::TestCaseGroup(testCtx, ("size_" + string(allocationSizeName)).c_str(), ("Test different allocation sizes " + de::toString(allocationSize)).c_str()));
512
513                         for (size_t orderNdx = 0; orderNdx < DE_LENGTH_OF_ARRAY(orders); orderNdx++)
514                         {
515                                 const TestConfig::Order                 order                           = orders[orderNdx].order;
516                                 const char* const                               orderName                       = orders[orderNdx].str;
517                                 const char* const                               orderDescription        = orderName;
518                                 de::MovePtr<tcu::TestCaseGroup> orderGroup                      (new tcu::TestCaseGroup(testCtx, orderName, orderDescription));
519
520                                 for (size_t allocationCountNdx = 0; allocationCountNdx < DE_LENGTH_OF_ARRAY(allocationCounts); allocationCountNdx++)
521                                 {
522                                         const int allocationCount = allocationCounts[allocationCountNdx];
523
524                                         if (allocationCount != -1 && allocationCount * allocationSize > 50 * MiB)
525                                                 continue;
526
527                                         TestConfig config;
528
529                                         config.memorySize                               = allocationSize;
530                                         config.order                                    = order;
531
532                                         if (allocationCount == -1)
533                                         {
534                                                 if (allocationSize < 4096)
535                                                         continue;
536
537                                                 config.memoryAllocationCount    = (deUint32)(50 * MiB / allocationSize);
538
539                                                 if (config.memoryAllocationCount == 0
540                                                         || config.memoryAllocationCount == 1
541                                                         || config.memoryAllocationCount == 10
542                                                         || config.memoryAllocationCount == 100
543                                                         || config.memoryAllocationCount == 1000)
544                                                 continue;
545                                         }
546                                         else
547                                                 config.memoryAllocationCount    = allocationCount;
548
549                                         orderGroup->addChild(new InstanceFactory1<AllocateFreeTestInstance, TestConfig>(testCtx, tcu::NODETYPE_SELF_VALIDATE, "count_" + de::toString(config.memoryAllocationCount), "", config));
550                                 }
551
552                                 sizeGroup->addChild(orderGroup.release());
553                         }
554
555                         basicGroup->addChild(sizeGroup.release());
556                 }
557
558                 for (size_t allocationPercentNdx = 0; allocationPercentNdx < DE_LENGTH_OF_ARRAY(allocationPercents); allocationPercentNdx++)
559                 {
560                         const int                                               allocationPercent       = allocationPercents[allocationPercentNdx];
561                         de::MovePtr<tcu::TestCaseGroup> percentGroup            (new tcu::TestCaseGroup(testCtx, ("percent_" + de::toString(allocationPercent)).c_str(), ("Test different allocation percents " + de::toString(allocationPercent)).c_str()));
562
563                         for (size_t orderNdx = 0; orderNdx < DE_LENGTH_OF_ARRAY(orders); orderNdx++)
564                         {
565                                 const TestConfig::Order                 order                           = orders[orderNdx].order;
566                                 const char* const                               orderName                       = orders[orderNdx].str;
567                                 const char* const                               orderDescription        = orderName;
568                                 de::MovePtr<tcu::TestCaseGroup> orderGroup                      (new tcu::TestCaseGroup(testCtx, orderName, orderDescription));
569
570                                 for (size_t allocationCountNdx = 0; allocationCountNdx < DE_LENGTH_OF_ARRAY(allocationCounts); allocationCountNdx++)
571                                 {
572                                         const int allocationCount = allocationCounts[allocationCountNdx];
573
574                                         if ((allocationCount != -1) && ((float)allocationCount * (float)allocationPercent >= 1.00f / 8.00f))
575                                                 continue;
576
577                                         TestConfig config;
578
579                                         config.memoryPercentage                 = (float)allocationPercent / 100.0f;
580                                         config.order                                    = order;
581
582                                         if (allocationCount == -1)
583                                         {
584                                                 config.memoryAllocationCount    = (int)((1.00f / 8.00f) / ((float)allocationPercent / 100.0f));
585
586                                                 if (config.memoryAllocationCount == 0
587                                                         || config.memoryAllocationCount == 1
588                                                         || config.memoryAllocationCount == 10
589                                                         || config.memoryAllocationCount == 100
590                                                         || config.memoryAllocationCount == 1000)
591                                                 continue;
592                                         }
593                                         else
594                                                 config.memoryAllocationCount    = allocationCount;
595
596                                         orderGroup->addChild(new InstanceFactory1<AllocateFreeTestInstance, TestConfig>(testCtx, tcu::NODETYPE_SELF_VALIDATE, "count_" + de::toString(config.memoryAllocationCount), "", config));
597                                 }
598
599                                 percentGroup->addChild(orderGroup.release());
600                         }
601
602                         basicGroup->addChild(percentGroup.release());
603                 }
604
605                 group->addChild(basicGroup.release());
606         }
607
608         {
609                 const deUint32                                  caseCount       = 100;
610                 de::MovePtr<tcu::TestCaseGroup> randomGroup     (new tcu::TestCaseGroup(testCtx, "random", "Random memory allocation tests."));
611
612                 for (deUint32 caseNdx = 0; caseNdx < caseCount; caseNdx++)
613                 {
614                         const deUint32 seed = deInt32Hash(caseNdx ^ 32480);
615
616                         randomGroup->addChild(new InstanceFactory1<RandomAllocFreeTestInstance, deUint32>(testCtx, tcu::NODETYPE_SELF_VALIDATE, de::toString(caseNdx), "Random case", seed));
617                 }
618
619                 group->addChild(randomGroup.release());
620         }
621
622         return group.release();
623 }
624
625 } // memory
626 } // vkt