Merge vk-gl-cts/vulkan-cts-1.0.2 into vk-gl-cts/master
[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  * 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
82         TestConfig (void)
83                 : memoryAllocationCount ((deUint32)-1)
84                 , order                                 (ORDER_LAST)
85         {
86         }
87 };
88
89 class AllocateFreeTestInstance : public TestInstance
90 {
91 public:
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
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
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
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
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
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
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