Touch watchdog before freeing objs in max_concurrent
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / api / vktApiObjectManagementTests.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 Object management tests
22  *//*--------------------------------------------------------------------*/
23
24 #include "vktApiObjectManagementTests.hpp"
25 #include "vktTestCaseUtil.hpp"
26
27 #include "vkDefs.hpp"
28 #include "vkRef.hpp"
29 #include "vkRefUtil.hpp"
30 #include "vkQueryUtil.hpp"
31 #include "vkMemUtil.hpp"
32 #include "vkPrograms.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkPlatform.hpp"
35 #include "vkStrUtil.hpp"
36 #include "vkAllocationCallbackUtil.hpp"
37
38 #include "tcuVector.hpp"
39 #include "tcuResultCollector.hpp"
40 #include "tcuCommandLine.hpp"
41 #include "tcuTestLog.hpp"
42 #include "tcuPlatform.hpp"
43
44 #include "deUniquePtr.hpp"
45 #include "deSharedPtr.hpp"
46 #include "deArrayUtil.hpp"
47 #include "deSpinBarrier.hpp"
48 #include "deThread.hpp"
49 #include "deInt32.h"
50
51 #include <limits>
52
53 namespace vkt
54 {
55 namespace api
56 {
57
58 namespace
59 {
60
61 using namespace vk;
62
63 using de::UniquePtr;
64 using de::MovePtr;
65 using de::SharedPtr;
66
67 using tcu::IVec3;
68 using tcu::UVec3;
69 using tcu::ResultCollector;
70 using tcu::TestStatus;
71 using tcu::TestLog;
72
73 using std::string;
74 using std::vector;
75
76 typedef SharedPtr<Move<VkPipeline> >                    VkPipelineSp;           // Move so it's possible to disown the handle
77 typedef SharedPtr<Move<VkDescriptorSet> >               VkDescriptorSetSp;
78 typedef SharedPtr<Move<VkCommandBuffer> >               VkCommandBufferSp;
79
80 class ThreadGroupThread;
81
82 /*--------------------------------------------------------------------*//*!
83  * \brief Thread group
84  *
85  * Thread group manages collection of threads that are expected to be
86  * launched simultaneously as a group.
87  *
88  * Shared barrier is provided for synchronizing execution. Terminating thread
89  * early either by returning from ThreadGroupThread::runThread() or throwing
90  * an exception is safe, and other threads will continue execution. The
91  * thread that has been terminated is simply removed from the synchronization
92  * group.
93  *
94  * TestException-based exceptions are collected and translated into a
95  * tcu::TestStatus by using tcu::ResultCollector.
96  *
97  * Use cases for ThreadGroup include for example testing thread-safety of
98  * certain API operations by poking API simultaneously from multiple
99  * threads.
100  *//*--------------------------------------------------------------------*/
101 class ThreadGroup
102 {
103 public:
104                                                         ThreadGroup                     (void);
105                                                         ~ThreadGroup            (void);
106
107         void                                    add                                     (de::MovePtr<ThreadGroupThread> thread);
108         TestStatus                              run                                     (void);
109
110 private:
111         typedef std::vector<de::SharedPtr<ThreadGroupThread> >  ThreadVector;
112
113         ThreadVector                    m_threads;
114         de::SpinBarrier                 m_barrier;
115 } DE_WARN_UNUSED_TYPE;
116
117 class ThreadGroupThread : private de::Thread
118 {
119 public:
120                                                         ThreadGroupThread       (void);
121         virtual                                 ~ThreadGroupThread      (void);
122
123         void                                    start                           (de::SpinBarrier* groupBarrier);
124
125         ResultCollector&                getResultCollector      (void) { return m_resultCollector; }
126
127         using de::Thread::join;
128
129 protected:
130         virtual void                    runThread                       (void) = 0;
131
132         void                                    barrier                         (void);
133
134 private:
135                                                         ThreadGroupThread       (const ThreadGroupThread&);
136         ThreadGroupThread&              operator=                       (const ThreadGroupThread&);
137
138         void                                    run                                     (void);
139
140         ResultCollector                 m_resultCollector;
141         de::SpinBarrier*                m_barrier;
142 };
143
144 // ThreadGroup
145
146 ThreadGroup::ThreadGroup (void)
147         : m_barrier(1)
148 {
149 }
150
151 ThreadGroup::~ThreadGroup (void)
152 {
153 }
154
155 void ThreadGroup::add (de::MovePtr<ThreadGroupThread> thread)
156 {
157         m_threads.push_back(de::SharedPtr<ThreadGroupThread>(thread.release()));
158 }
159
160 tcu::TestStatus ThreadGroup::run (void)
161 {
162         tcu::ResultCollector    resultCollector;
163
164         m_barrier.reset((int)m_threads.size());
165
166         for (ThreadVector::iterator threadIter = m_threads.begin(); threadIter != m_threads.end(); ++threadIter)
167                 (*threadIter)->start(&m_barrier);
168
169         for (ThreadVector::iterator threadIter = m_threads.begin(); threadIter != m_threads.end(); ++threadIter)
170         {
171                 tcu::ResultCollector&   threadResult    = (*threadIter)->getResultCollector();
172                 (*threadIter)->join();
173                 resultCollector.addResult(threadResult.getResult(), threadResult.getMessage());
174         }
175
176         return tcu::TestStatus(resultCollector.getResult(), resultCollector.getMessage());
177 }
178
179 // ThreadGroupThread
180
181 ThreadGroupThread::ThreadGroupThread (void)
182         : m_barrier(DE_NULL)
183 {
184 }
185
186 ThreadGroupThread::~ThreadGroupThread (void)
187 {
188 }
189
190 void ThreadGroupThread::start (de::SpinBarrier* groupBarrier)
191 {
192         m_barrier = groupBarrier;
193         de::Thread::start();
194 }
195
196 void ThreadGroupThread::run (void)
197 {
198         try
199         {
200                 runThread();
201         }
202         catch (const tcu::TestException& e)
203         {
204                 getResultCollector().addResult(e.getTestResult(), e.getMessage());
205         }
206         catch (const std::exception& e)
207         {
208                 getResultCollector().addResult(QP_TEST_RESULT_FAIL, e.what());
209         }
210         catch (...)
211         {
212                 getResultCollector().addResult(QP_TEST_RESULT_FAIL, "Exception");
213         }
214
215         m_barrier->removeThread(de::SpinBarrier::WAIT_MODE_AUTO);
216 }
217
218 inline void ThreadGroupThread::barrier (void)
219 {
220         m_barrier->sync(de::SpinBarrier::WAIT_MODE_AUTO);
221 }
222
223 deUint32 getDefaultTestThreadCount (void)
224 {
225         return de::clamp(deGetNumAvailableLogicalCores(), 2u, 8u);
226 }
227
228 // Utilities
229
230 struct Environment
231 {
232         const PlatformInterface&                vkp;
233         const DeviceInterface&                  vkd;
234         VkDevice                                                device;
235         deUint32                                                queueFamilyIndex;
236         const BinaryCollection&                 programBinaries;
237         const VkAllocationCallbacks*    allocationCallbacks;
238         deUint32                                                maxResourceConsumers;           // Maximum number of objects using same Object::Resources concurrently
239
240         Environment (Context& context, deUint32 maxResourceConsumers_)
241                 : vkp                                   (context.getPlatformInterface())
242                 , vkd                                   (context.getDeviceInterface())
243                 , device                                (context.getDevice())
244                 , queueFamilyIndex              (context.getUniversalQueueFamilyIndex())
245                 , programBinaries               (context.getBinaryCollection())
246                 , allocationCallbacks   (DE_NULL)
247                 , maxResourceConsumers  (maxResourceConsumers_)
248         {
249         }
250
251         Environment (const PlatformInterface&           vkp_,
252                                  const DeviceInterface&                 vkd_,
253                                  VkDevice                                               device_,
254                                  deUint32                                               queueFamilyIndex_,
255                                  const BinaryCollection&                programBinaries_,
256                                  const VkAllocationCallbacks*   allocationCallbacks_,
257                                  deUint32                                               maxResourceConsumers_)
258                 : vkp                                   (vkp_)
259                 , vkd                                   (vkd_)
260                 , device                                (device_)
261                 , queueFamilyIndex              (queueFamilyIndex_)
262                 , programBinaries               (programBinaries_)
263                 , allocationCallbacks   (allocationCallbacks_)
264                 , maxResourceConsumers  (maxResourceConsumers_)
265         {
266         }
267 };
268
269 template<typename Case>
270 struct Dependency
271 {
272         typename Case::Resources                resources;
273         Unique<typename Case::Type>             object;
274
275         Dependency (const Environment& env, const typename Case::Parameters& params)
276                 : resources     (env, params)
277                 , object        (Case::create(env, resources, params))
278         {}
279 };
280
281 template<typename T>
282 T roundUpToNextMultiple (T value, T multiple)
283 {
284         if (value % multiple == 0)
285                 return value;
286         else
287                 return value + multiple - (value % multiple);
288 }
289
290 #if defined(DE_DEBUG)
291 template<typename T>
292 bool isPowerOfTwo (T value)
293 {
294         return ((value & (value - T(1))) == 0);
295 }
296 #endif
297
298 template<typename T>
299 T alignToPowerOfTwo (T value, T align)
300 {
301         DE_ASSERT(isPowerOfTwo(align));
302         return (value + align - T(1)) & ~(align - T(1));
303 }
304
305 inline bool hasDeviceExtension (Context& context, const string& name)
306 {
307         return de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), name);
308 }
309
310 VkDeviceSize getPageTableSize (const PlatformMemoryLimits& limits, VkDeviceSize allocationSize)
311 {
312         VkDeviceSize    totalSize       = 0;
313
314         for (size_t levelNdx = 0; levelNdx < limits.devicePageTableHierarchyLevels; ++levelNdx)
315         {
316                 const VkDeviceSize      coveredAddressSpaceSize = limits.devicePageSize<<levelNdx;
317                 const VkDeviceSize      numPagesNeeded                  = alignToPowerOfTwo(allocationSize, coveredAddressSpaceSize) / coveredAddressSpaceSize;
318
319                 totalSize += numPagesNeeded*limits.devicePageTableEntrySize;
320         }
321
322         return totalSize;
323 }
324
325 size_t getCurrentSystemMemoryUsage (const AllocationCallbackRecorder& allocRecoder)
326 {
327         const size_t                                            systemAllocationOverhead        = sizeof(void*)*2;
328         AllocationCallbackValidationResults     validationResults;
329
330         validateAllocationCallbacks(allocRecoder, &validationResults);
331         TCU_CHECK(validationResults.violations.empty());
332
333         return getLiveSystemAllocationTotal(validationResults) + systemAllocationOverhead*validationResults.liveAllocations.size();
334 }
335
336 template<typename Object>
337 size_t computeSystemMemoryUsage (Context& context, const typename Object::Parameters& params)
338 {
339         AllocationCallbackRecorder                      allocRecorder           (getSystemAllocator());
340         const Environment                                       env                                     (context.getPlatformInterface(),
341                                                                                                                          context.getDeviceInterface(),
342                                                                                                                          context.getDevice(),
343                                                                                                                          context.getUniversalQueueFamilyIndex(),
344                                                                                                                          context.getBinaryCollection(),
345                                                                                                                          allocRecorder.getCallbacks(),
346                                                                                                                          1u);
347         const typename Object::Resources        res                                     (env, params);
348         const size_t                                            resourceMemoryUsage     = getCurrentSystemMemoryUsage(allocRecorder);
349
350         {
351                 Unique<typename Object::Type>   obj                                     (Object::create(env, res, params));
352                 const size_t                                    totalMemoryUsage        = getCurrentSystemMemoryUsage(allocRecorder);
353
354                 return totalMemoryUsage - resourceMemoryUsage;
355         }
356 }
357
358 size_t getSafeObjectCount (const PlatformMemoryLimits&  memoryLimits,
359                                                    size_t                                               objectSystemMemoryUsage,
360                                                    VkDeviceSize                                 objectDeviceMemoryUsage = 0)
361 {
362         const VkDeviceSize      roundedUpDeviceMemory   = roundUpToNextMultiple(objectDeviceMemoryUsage, memoryLimits.deviceMemoryAllocationGranularity);
363
364         if (memoryLimits.totalDeviceLocalMemory > 0 && roundedUpDeviceMemory > 0)
365         {
366                 if (objectSystemMemoryUsage > 0)
367                         return de::min(memoryLimits.totalSystemMemory / objectSystemMemoryUsage,
368                                                    (size_t)(memoryLimits.totalDeviceLocalMemory / roundedUpDeviceMemory));
369                 else
370                         return (size_t)(memoryLimits.totalDeviceLocalMemory / roundedUpDeviceMemory);
371         }
372         else if (objectSystemMemoryUsage + roundedUpDeviceMemory > 0)
373         {
374                 DE_ASSERT(roundedUpDeviceMemory <= std::numeric_limits<size_t>::max() - objectSystemMemoryUsage);
375                 return memoryLimits.totalSystemMemory / (objectSystemMemoryUsage + (size_t)roundedUpDeviceMemory);
376         }
377         else
378         {
379                 // Warning: at this point driver has probably not implemented allocation callbacks correctly
380                 return std::numeric_limits<size_t>::max();
381         }
382 }
383
384 PlatformMemoryLimits getPlatformMemoryLimits (Context& context)
385 {
386         PlatformMemoryLimits    memoryLimits;
387
388         context.getTestContext().getPlatform().getVulkanPlatform().getMemoryLimits(memoryLimits);
389
390         return memoryLimits;
391 }
392
393 size_t getSafeObjectCount (Context& context, size_t objectSystemMemoryUsage, VkDeviceSize objectDeviceMemorySize = 0)
394 {
395         return getSafeObjectCount(getPlatformMemoryLimits(context), objectSystemMemoryUsage, objectDeviceMemorySize);
396 }
397
398 VkDeviceSize getPageTableSize (Context& context, VkDeviceSize allocationSize)
399 {
400         return getPageTableSize(getPlatformMemoryLimits(context), allocationSize);
401 }
402
403 template<typename Object>
404 deUint32 getSafeObjectCount (Context&                                                   context,
405                                                          const typename Object::Parameters&     params,
406                                                          deUint32                                                       hardCountLimit,
407                                                          VkDeviceSize                                           deviceMemoryUsage = 0)
408 {
409         return (deUint32)de::min((size_t)hardCountLimit,
410                                                          getSafeObjectCount(context,
411                                                                                                 computeSystemMemoryUsage<Object>(context, params),
412                                                                                                 deviceMemoryUsage));
413 }
414
415 // Object definitions
416
417 enum
418 {
419         MAX_CONCURRENT_INSTANCES                = 32,
420         MAX_CONCURRENT_DEVICES                  = 32,
421         MAX_CONCURRENT_SYNC_PRIMITIVES  = 100,
422         DEFAULT_MAX_CONCURRENT_OBJECTS  = 16*1024,
423 };
424
425 struct Instance
426 {
427         typedef VkInstance Type;
428
429         struct Parameters
430         {
431                 Parameters (void) {}
432         };
433
434         struct Resources
435         {
436                 Resources (const Environment&, const Parameters&) {}
437         };
438
439         static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
440         {
441                 return getSafeObjectCount<Instance>(context, params, MAX_CONCURRENT_INSTANCES);
442         }
443
444         static Move<VkInstance> create (const Environment& env, const Resources&, const Parameters&)
445         {
446                 const VkApplicationInfo         appInfo                 =
447                 {
448                         VK_STRUCTURE_TYPE_APPLICATION_INFO,
449                         DE_NULL,
450                         DE_NULL,                                                        // pApplicationName
451                         0u,                                                                     // applicationVersion
452                         DE_NULL,                                                        // pEngineName
453                         0u,                                                                     // engineVersion
454                         VK_MAKE_VERSION(1,0,0)
455                 };
456                 const VkInstanceCreateInfo      instanceInfo    =
457                 {
458                         VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
459                         DE_NULL,
460                         (VkInstanceCreateFlags)0,
461                         &appInfo,
462                         0u,                                                                     // enabledLayerNameCount
463                         DE_NULL,                                                        // ppEnabledLayerNames
464                         0u,                                                                     // enabledExtensionNameCount
465                         DE_NULL,                                                        // ppEnabledExtensionNames
466                 };
467
468                 return createInstance(env.vkp, &instanceInfo, env.allocationCallbacks);
469         }
470 };
471
472 struct Device
473 {
474         typedef VkDevice Type;
475
476         struct Parameters
477         {
478                 deUint32                deviceIndex;
479                 VkQueueFlags    queueFlags;
480
481                 Parameters (deUint32 deviceIndex_, VkQueueFlags queueFlags_)
482                         : deviceIndex   (deviceIndex_)
483                         , queueFlags    (queueFlags_)
484                 {}
485         };
486
487         struct Resources
488         {
489                 Dependency<Instance>    instance;
490                 InstanceDriver                  vki;
491                 VkPhysicalDevice                physicalDevice;
492                 deUint32                                queueFamilyIndex;
493
494                 Resources (const Environment& env, const Parameters& params)
495                         : instance                      (env, Instance::Parameters())
496                         , vki                           (env.vkp, *instance.object)
497                         , physicalDevice        (0)
498                         , queueFamilyIndex      (~0u)
499                 {
500                         {
501                                 const vector<VkPhysicalDevice>  physicalDevices = enumeratePhysicalDevices(vki, *instance.object);
502
503                                 if (physicalDevices.size() <= (size_t)params.deviceIndex)
504                                         TCU_THROW(NotSupportedError, "Device not found");
505
506                                 physicalDevice = physicalDevices[params.deviceIndex];
507                         }
508
509                         {
510                                 const vector<VkQueueFamilyProperties>   queueProps              = getPhysicalDeviceQueueFamilyProperties(vki, physicalDevice);
511                                 bool                                                                    foundMatching   = false;
512
513                                 for (size_t curQueueNdx = 0; curQueueNdx < queueProps.size(); curQueueNdx++)
514                                 {
515                                         if ((queueProps[curQueueNdx].queueFlags & params.queueFlags) == params.queueFlags)
516                                         {
517                                                 queueFamilyIndex        = (deUint32)curQueueNdx;
518                                                 foundMatching           = true;
519                                         }
520                                 }
521
522                                 if (!foundMatching)
523                                         TCU_THROW(NotSupportedError, "Matching queue not found");
524                         }
525                 }
526         };
527
528         static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
529         {
530                 return getSafeObjectCount<Device>(context, params, MAX_CONCURRENT_DEVICES);
531         }
532
533         static Move<VkDevice> create (const Environment& env, const Resources& res, const Parameters&)
534         {
535                 const float     queuePriority   = 1.0;
536
537                 const VkDeviceQueueCreateInfo   queues[]        =
538                 {
539                         {
540                                 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
541                                 DE_NULL,
542                                 (VkDeviceQueueCreateFlags)0,
543                                 res.queueFamilyIndex,
544                                 1u,                                                                     // queueCount
545                                 &queuePriority,                                         // pQueuePriorities
546                         }
547                 };
548                 const VkDeviceCreateInfo                deviceInfo      =
549                 {
550                         VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
551                         DE_NULL,
552                         (VkDeviceCreateFlags)0,
553                         DE_LENGTH_OF_ARRAY(queues),
554                         queues,
555                         0u,                                                                             // enabledLayerNameCount
556                         DE_NULL,                                                                // ppEnabledLayerNames
557                         0u,                                                                             // enabledExtensionNameCount
558                         DE_NULL,                                                                // ppEnabledExtensionNames
559                         DE_NULL,                                                                // pEnabledFeatures
560                 };
561
562                 return createDevice(res.vki, res.physicalDevice, &deviceInfo, env.allocationCallbacks);
563         }
564 };
565
566 struct DeviceMemory
567 {
568         typedef VkDeviceMemory Type;
569
570         struct Parameters
571         {
572                 VkDeviceSize    size;
573                 deUint32                memoryTypeIndex;
574
575                 Parameters (VkDeviceSize size_, deUint32 memoryTypeIndex_)
576                         : size                          (size_)
577                         , memoryTypeIndex       (memoryTypeIndex_)
578                 {
579                         DE_ASSERT(memoryTypeIndex < VK_MAX_MEMORY_TYPES);
580                 }
581         };
582
583         struct Resources
584         {
585                 Resources (const Environment&, const Parameters&) {}
586         };
587
588         static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
589         {
590                 const VkDeviceSize      deviceMemoryUsage       = params.size + getPageTableSize(context, params.size);
591
592                 return getSafeObjectCount<DeviceMemory>(context,
593                                                                                                 params,
594                                                                                                 de::min(context.getDeviceProperties().limits.maxMemoryAllocationCount,
595                                                                                                                 (deUint32)DEFAULT_MAX_CONCURRENT_OBJECTS),
596                                                                                                 deviceMemoryUsage);
597         }
598
599         static Move<VkDeviceMemory> create (const Environment& env, const Resources&, const Parameters& params)
600         {
601                 const VkMemoryAllocateInfo      allocInfo       =
602                 {
603                         VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
604                         DE_NULL,
605                         params.size,
606                         params.memoryTypeIndex
607                 };
608
609                 return allocateMemory(env.vkd, env.device, &allocInfo, env.allocationCallbacks);
610         }
611 };
612
613 DeviceMemory::Parameters getDeviceMemoryParameters (const VkMemoryRequirements& memReqs)
614 {
615         return DeviceMemory::Parameters(memReqs.size, deCtz32(memReqs.memoryTypeBits));
616 }
617
618 DeviceMemory::Parameters getDeviceMemoryParameters (const Environment& env, VkImage image)
619 {
620         return getDeviceMemoryParameters(getImageMemoryRequirements(env.vkd, env.device, image));
621 }
622
623 DeviceMemory::Parameters getDeviceMemoryParameters (const Environment& env, VkBuffer image)
624 {
625         return getDeviceMemoryParameters(getBufferMemoryRequirements(env.vkd, env.device, image));
626 }
627
628 struct Buffer
629 {
630         typedef VkBuffer Type;
631
632         struct Parameters
633         {
634                 VkDeviceSize            size;
635                 VkBufferUsageFlags      usage;
636
637                 Parameters (VkDeviceSize                size_,
638                                         VkBufferUsageFlags      usage_)
639                         : size  (size_)
640                         , usage (usage_)
641                 {}
642         };
643
644         struct Resources
645         {
646                 Resources (const Environment&, const Parameters&) {}
647         };
648
649         static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
650         {
651                 const Environment                       env             (context, 1u);
652                 const Resources                         res             (env, params);
653                 const Unique<VkBuffer>          buffer  (create(env, res, params));
654                 const VkMemoryRequirements      memReqs = getBufferMemoryRequirements(env.vkd, env.device, *buffer);
655
656                 return getSafeObjectCount<Buffer>(context,
657                                                                                   params,
658                                                                                   DEFAULT_MAX_CONCURRENT_OBJECTS,
659                                                                                   getPageTableSize(context, memReqs.size));
660         }
661
662         static Move<VkBuffer> create (const Environment& env, const Resources&, const Parameters& params)
663         {
664                 const VkBufferCreateInfo        bufferInfo      =
665                 {
666                         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
667                         DE_NULL,
668                         (VkBufferCreateFlags)0,
669                         params.size,
670                         params.usage,
671                         VK_SHARING_MODE_EXCLUSIVE,
672                         1u,
673                         &env.queueFamilyIndex
674                 };
675
676                 return createBuffer(env.vkd, env.device, &bufferInfo, env.allocationCallbacks);
677         }
678 };
679
680 struct BufferView
681 {
682         typedef VkBufferView Type;
683
684         struct Parameters
685         {
686                 Buffer::Parameters      buffer;
687                 VkFormat                        format;
688                 VkDeviceSize            offset;
689                 VkDeviceSize            range;
690
691                 Parameters (const Buffer::Parameters&   buffer_,
692                                         VkFormat                                        format_,
693                                         VkDeviceSize                            offset_,
694                                         VkDeviceSize                            range_)
695                         : buffer        (buffer_)
696                         , format        (format_)
697                         , offset        (offset_)
698                         , range         (range_)
699                 {}
700         };
701
702         struct Resources
703         {
704                 Dependency<Buffer>                      buffer;
705                 Dependency<DeviceMemory>        memory;
706
707                 Resources (const Environment& env, const Parameters& params)
708                         : buffer(env, params.buffer)
709                         , memory(env, getDeviceMemoryParameters(env, *buffer.object))
710                 {
711                         VK_CHECK(env.vkd.bindBufferMemory(env.device, *buffer.object, *memory.object, 0));
712                 }
713         };
714
715         static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
716         {
717                 return getSafeObjectCount<BufferView>(context, params, DEFAULT_MAX_CONCURRENT_OBJECTS);
718         }
719
720         static Move<VkBufferView> create (const Environment& env, const Resources& res, const Parameters& params)
721         {
722                 const VkBufferViewCreateInfo    bufferViewInfo  =
723                 {
724                         VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,
725                         DE_NULL,
726                         (VkBufferViewCreateFlags)0,
727                         *res.buffer.object,
728                         params.format,
729                         params.offset,
730                         params.range
731                 };
732
733                 return createBufferView(env.vkd, env.device, &bufferViewInfo, env.allocationCallbacks);
734         }
735 };
736
737 struct Image
738 {
739         typedef VkImage Type;
740
741         struct Parameters
742         {
743                 VkImageCreateFlags              flags;
744                 VkImageType                             imageType;
745                 VkFormat                                format;
746                 VkExtent3D                              extent;
747                 deUint32                                mipLevels;
748                 deUint32                                arraySize;
749                 VkSampleCountFlagBits   samples;
750                 VkImageTiling                   tiling;
751                 VkImageUsageFlags               usage;
752                 VkImageLayout                   initialLayout;
753
754                 Parameters (VkImageCreateFlags          flags_,
755                                         VkImageType                             imageType_,
756                                         VkFormat                                format_,
757                                         VkExtent3D                              extent_,
758                                         deUint32                                mipLevels_,
759                                         deUint32                                arraySize_,
760                                         VkSampleCountFlagBits   samples_,
761                                         VkImageTiling                   tiling_,
762                                         VkImageUsageFlags               usage_,
763                                         VkImageLayout                   initialLayout_)
764                         : flags                 (flags_)
765                         , imageType             (imageType_)
766                         , format                (format_)
767                         , extent                (extent_)
768                         , mipLevels             (mipLevels_)
769                         , arraySize             (arraySize_)
770                         , samples               (samples_)
771                         , tiling                (tiling_)
772                         , usage                 (usage_)
773                         , initialLayout (initialLayout_)
774                 {}
775         };
776
777         struct Resources
778         {
779                 Resources (const Environment&, const Parameters&) {}
780         };
781
782         static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
783         {
784                 const Environment                       env             (context, 1u);
785                 const Resources                         res             (env, params);
786                 const Unique<VkImage>           image   (create(env, res, params));
787                 const VkMemoryRequirements      memReqs = getImageMemoryRequirements(env.vkd, env.device, *image);
788
789                 return getSafeObjectCount<Image>(context,
790                                                                                  params,
791                                                                                  DEFAULT_MAX_CONCURRENT_OBJECTS,
792                                                                                  getPageTableSize(context, memReqs.size));
793         }
794
795         static Move<VkImage> create (const Environment& env, const Resources&, const Parameters& params)
796         {
797                 const VkImageCreateInfo         imageInfo       =
798                 {
799                         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
800                         DE_NULL,
801                         params.flags,
802                         params.imageType,
803                         params.format,
804                         params.extent,
805                         params.mipLevels,
806                         params.arraySize,
807                         params.samples,
808                         params.tiling,
809                         params.usage,
810                         VK_SHARING_MODE_EXCLUSIVE,              // sharingMode
811                         1u,                                                             // queueFamilyIndexCount
812                         &env.queueFamilyIndex,                  // pQueueFamilyIndices
813                         params.initialLayout
814                 };
815
816                 return createImage(env.vkd, env.device, &imageInfo, env.allocationCallbacks);
817         }
818 };
819
820 struct ImageView
821 {
822         typedef VkImageView Type;
823
824         struct Parameters
825         {
826                 Image::Parameters               image;
827                 VkImageViewType                 viewType;
828                 VkFormat                                format;
829                 VkComponentMapping              components;
830                 VkImageSubresourceRange subresourceRange;
831
832                 Parameters (const Image::Parameters&    image_,
833                                         VkImageViewType                         viewType_,
834                                         VkFormat                                        format_,
835                                         VkComponentMapping                      components_,
836                                         VkImageSubresourceRange         subresourceRange_)
837                         : image                         (image_)
838                         , viewType                      (viewType_)
839                         , format                        (format_)
840                         , components            (components_)
841                         , subresourceRange      (subresourceRange_)
842                 {}
843         };
844
845         struct Resources
846         {
847                 Dependency<Image>                       image;
848                 Dependency<DeviceMemory>        memory;
849
850                 Resources (const Environment& env, const Parameters& params)
851                         : image (env, params.image)
852                         , memory(env, getDeviceMemoryParameters(env, *image.object))
853                 {
854                         VK_CHECK(env.vkd.bindImageMemory(env.device, *image.object, *memory.object, 0));
855                 }
856         };
857
858         static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
859         {
860                 return getSafeObjectCount<ImageView>(context, params, DEFAULT_MAX_CONCURRENT_OBJECTS);
861         }
862
863         static Move<VkImageView> create (const Environment& env, const Resources& res, const Parameters& params)
864         {
865                 const VkImageViewCreateInfo     imageViewInfo   =
866                 {
867                         VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
868                         DE_NULL,
869                         (VkImageViewCreateFlags)0,
870                         *res.image.object,
871                         params.viewType,
872                         params.format,
873                         params.components,
874                         params.subresourceRange,
875                 };
876
877                 return createImageView(env.vkd, env.device, &imageViewInfo, env.allocationCallbacks);
878         }
879 };
880
881 struct Semaphore
882 {
883         typedef VkSemaphore Type;
884
885         struct Parameters
886         {
887                 VkSemaphoreCreateFlags  flags;
888
889                 Parameters (VkSemaphoreCreateFlags flags_)
890                         : flags(flags_)
891                 {}
892         };
893
894         struct Resources
895         {
896                 Resources (const Environment&, const Parameters&) {}
897         };
898
899         static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
900         {
901                 return getSafeObjectCount<Semaphore>(context, params, MAX_CONCURRENT_SYNC_PRIMITIVES);
902         }
903
904         static Move<VkSemaphore> create (const Environment& env, const Resources&, const Parameters& params)
905         {
906                 const VkSemaphoreCreateInfo     semaphoreInfo   =
907                 {
908                         VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
909                         DE_NULL,
910                         params.flags
911                 };
912
913                 return createSemaphore(env.vkd, env.device, &semaphoreInfo, env.allocationCallbacks);
914         }
915 };
916
917 struct Fence
918 {
919         typedef VkFence Type;
920
921         struct Parameters
922         {
923                 VkFenceCreateFlags      flags;
924
925                 Parameters (VkFenceCreateFlags flags_)
926                         : flags(flags_)
927                 {}
928         };
929
930         struct Resources
931         {
932                 Resources (const Environment&, const Parameters&) {}
933         };
934
935         static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
936         {
937                 return getSafeObjectCount<Fence>(context, params, MAX_CONCURRENT_SYNC_PRIMITIVES);
938         }
939
940         static Move<VkFence> create (const Environment& env, const Resources&, const Parameters& params)
941         {
942                 const VkFenceCreateInfo fenceInfo       =
943                 {
944                         VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
945                         DE_NULL,
946                         params.flags
947                 };
948
949                 return createFence(env.vkd, env.device, &fenceInfo, env.allocationCallbacks);
950         }
951 };
952
953 struct Event
954 {
955         typedef VkEvent Type;
956
957         struct Parameters
958         {
959                 VkEventCreateFlags      flags;
960
961                 Parameters (VkEventCreateFlags flags_)
962                         : flags(flags_)
963                 {}
964         };
965
966         struct Resources
967         {
968                 Resources (const Environment&, const Parameters&) {}
969         };
970
971         static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
972         {
973                 return getSafeObjectCount<Event>(context, params, MAX_CONCURRENT_SYNC_PRIMITIVES);
974         }
975
976         static Move<VkEvent> create (const Environment& env, const Resources&, const Parameters& params)
977         {
978                 const VkEventCreateInfo eventInfo       =
979                 {
980                         VK_STRUCTURE_TYPE_EVENT_CREATE_INFO,
981                         DE_NULL,
982                         params.flags
983                 };
984
985                 return createEvent(env.vkd, env.device, &eventInfo, env.allocationCallbacks);
986         }
987 };
988
989 struct QueryPool
990 {
991         typedef VkQueryPool Type;
992
993         struct Parameters
994         {
995                 VkQueryType                                             queryType;
996                 deUint32                                                entryCount;
997                 VkQueryPipelineStatisticFlags   pipelineStatistics;
998
999                 Parameters (VkQueryType                                         queryType_,
1000                                         deUint32                                                entryCount_,
1001                                         VkQueryPipelineStatisticFlags   pipelineStatistics_)
1002                         : queryType                             (queryType_)
1003                         , entryCount                    (entryCount_)
1004                         , pipelineStatistics    (pipelineStatistics_)
1005                 {}
1006         };
1007
1008         struct Resources
1009         {
1010                 Resources (const Environment&, const Parameters&) {}
1011         };
1012
1013         static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
1014         {
1015                 return getSafeObjectCount<QueryPool>(context, params, DEFAULT_MAX_CONCURRENT_OBJECTS);
1016         }
1017
1018         static Move<VkQueryPool> create (const Environment& env, const Resources&, const Parameters& params)
1019         {
1020                 const VkQueryPoolCreateInfo     queryPoolInfo   =
1021                 {
1022                         VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,
1023                         DE_NULL,
1024                         (VkQueryPoolCreateFlags)0,
1025                         params.queryType,
1026                         params.entryCount,
1027                         params.pipelineStatistics
1028                 };
1029
1030                 return createQueryPool(env.vkd, env.device, &queryPoolInfo, env.allocationCallbacks);
1031         }
1032 };
1033
1034 struct ShaderModule
1035 {
1036         typedef VkShaderModule Type;
1037
1038         struct Parameters
1039         {
1040                 VkShaderStageFlagBits   shaderStage;
1041                 string                                  binaryName;
1042
1043                 Parameters (VkShaderStageFlagBits       shaderStage_,
1044                                         const std::string&              binaryName_)
1045                         : shaderStage   (shaderStage_)
1046                         , binaryName    (binaryName_)
1047                 {}
1048         };
1049
1050         struct Resources
1051         {
1052                 const ProgramBinary&    binary;
1053
1054                 Resources (const Environment& env, const Parameters& params)
1055                         : binary(env.programBinaries.get(params.binaryName))
1056                 {}
1057         };
1058
1059         static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
1060         {
1061                 return getSafeObjectCount<ShaderModule>(context, params, DEFAULT_MAX_CONCURRENT_OBJECTS);
1062         }
1063
1064         static const char* getSource (VkShaderStageFlagBits stage)
1065         {
1066                 switch (stage)
1067                 {
1068                         case VK_SHADER_STAGE_VERTEX_BIT:
1069                                 return "#version 310 es\n"
1070                                            "layout(location = 0) in highp vec4 a_position;\n"
1071                                            "void main () { gl_Position = a_position; }\n";
1072
1073                         case VK_SHADER_STAGE_FRAGMENT_BIT:
1074                                 return "#version 310 es\n"
1075                                            "layout(location = 0) out mediump vec4 o_color;\n"
1076                                            "void main () { o_color = vec4(1.0, 0.5, 0.25, 1.0); }";
1077
1078                         case VK_SHADER_STAGE_COMPUTE_BIT:
1079                                 return "#version 310 es\n"
1080                                            "layout(binding = 0) buffer Input { highp uint dataIn[]; };\n"
1081                                            "layout(binding = 1) buffer Output { highp uint dataOut[]; };\n"
1082                                            "void main (void)\n"
1083                                            "{\n"
1084                                            "    dataOut[gl_GlobalInvocationID.x] = ~dataIn[gl_GlobalInvocationID.x];\n"
1085                                            "}\n";
1086
1087                         default:
1088                                 DE_FATAL("Not implemented");
1089                                 return DE_NULL;
1090                 }
1091         }
1092
1093         static void initPrograms (SourceCollections& dst, Parameters params)
1094         {
1095                 const char* const       source  = getSource(params.shaderStage);
1096
1097                 DE_ASSERT(source);
1098
1099                 dst.glslSources.add(params.binaryName)
1100                         << glu::ShaderSource(getGluShaderType(params.shaderStage), source);
1101         }
1102
1103         static Move<VkShaderModule> create (const Environment& env, const Resources& res, const Parameters&)
1104         {
1105                 const VkShaderModuleCreateInfo  shaderModuleInfo        =
1106                 {
1107                         VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
1108                         DE_NULL,
1109                         (VkShaderModuleCreateFlags)0,
1110                         res.binary.getSize(),
1111                         (const deUint32*)res.binary.getBinary(),
1112                 };
1113
1114                 return createShaderModule(env.vkd, env.device, &shaderModuleInfo, env.allocationCallbacks);
1115         }
1116 };
1117
1118 struct PipelineCache
1119 {
1120         typedef VkPipelineCache Type;
1121
1122         struct Parameters
1123         {
1124                 Parameters (void) {}
1125         };
1126
1127         struct Resources
1128         {
1129                 Resources (const Environment&, const Parameters&) {}
1130         };
1131
1132         static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
1133         {
1134                 return getSafeObjectCount<PipelineCache>(context, params, DEFAULT_MAX_CONCURRENT_OBJECTS);
1135         }
1136
1137         static Move<VkPipelineCache> create (const Environment& env, const Resources&, const Parameters&)
1138         {
1139                 const VkPipelineCacheCreateInfo pipelineCacheInfo       =
1140                 {
1141                         VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO,
1142                         DE_NULL,
1143                         (VkPipelineCacheCreateFlags)0u,
1144                         0u,                                                             // initialDataSize
1145                         DE_NULL,                                                // pInitialData
1146                 };
1147
1148                 return createPipelineCache(env.vkd, env.device, &pipelineCacheInfo, env.allocationCallbacks);
1149         }
1150 };
1151
1152 struct Sampler
1153 {
1154         typedef VkSampler Type;
1155
1156         struct Parameters
1157         {
1158                 VkFilter                                magFilter;
1159                 VkFilter                                minFilter;
1160                 VkSamplerMipmapMode             mipmapMode;
1161                 VkSamplerAddressMode    addressModeU;
1162                 VkSamplerAddressMode    addressModeV;
1163                 VkSamplerAddressMode    addressModeW;
1164                 float                                   mipLodBias;
1165                 VkBool32                                anisotropyEnable;
1166                 float                                   maxAnisotropy;
1167                 VkBool32                                compareEnable;
1168                 VkCompareOp                             compareOp;
1169                 float                                   minLod;
1170                 float                                   maxLod;
1171                 VkBorderColor                   borderColor;
1172                 VkBool32                                unnormalizedCoordinates;
1173
1174                 // \todo [2015-09-17 pyry] Other configurations
1175                 Parameters (void)
1176                         : magFilter                                     (VK_FILTER_NEAREST)
1177                         , minFilter                                     (VK_FILTER_NEAREST)
1178                         , mipmapMode                            (VK_SAMPLER_MIPMAP_MODE_NEAREST)
1179                         , addressModeU                          (VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)
1180                         , addressModeV                          (VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)
1181                         , addressModeW                          (VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE)
1182                         , mipLodBias                            (0.0f)
1183                         , anisotropyEnable                      (VK_FALSE)
1184                         , maxAnisotropy                         (1.0f)
1185                         , compareEnable                         (VK_FALSE)
1186                         , compareOp                                     (VK_COMPARE_OP_ALWAYS)
1187                         , minLod                                        (-1000.f)
1188                         , maxLod                                        (+1000.f)
1189                         , borderColor                           (VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK)
1190                         , unnormalizedCoordinates       (VK_FALSE)
1191                 {}
1192         };
1193
1194         struct Resources
1195         {
1196                 Resources (const Environment&, const Parameters&) {}
1197         };
1198
1199         static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
1200         {
1201                 return getSafeObjectCount<Sampler>(context,
1202                                                                                    params,
1203                                                                                    de::min(context.getDeviceProperties().limits.maxSamplerAllocationCount,
1204                                                                                                    (deUint32)DEFAULT_MAX_CONCURRENT_OBJECTS));
1205         }
1206
1207         static Move<VkSampler> create (const Environment& env, const Resources&, const Parameters& params)
1208         {
1209                 const VkSamplerCreateInfo       samplerInfo     =
1210                 {
1211                         VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
1212                         DE_NULL,
1213                         (VkSamplerCreateFlags)0,
1214                         params.magFilter,
1215                         params.minFilter,
1216                         params.mipmapMode,
1217                         params.addressModeU,
1218                         params.addressModeV,
1219                         params.addressModeW,
1220                         params.mipLodBias,
1221                         params.anisotropyEnable,
1222                         params.maxAnisotropy,
1223                         params.compareEnable,
1224                         params.compareOp,
1225                         params.minLod,
1226                         params.maxLod,
1227                         params.borderColor,
1228                         params.unnormalizedCoordinates
1229                 };
1230
1231                 return createSampler(env.vkd, env.device, &samplerInfo, env.allocationCallbacks);
1232         }
1233 };
1234
1235 struct DescriptorSetLayout
1236 {
1237         typedef VkDescriptorSetLayout Type;
1238
1239         struct Parameters
1240         {
1241                 struct Binding
1242                 {
1243                         deUint32                        binding;
1244                         VkDescriptorType        descriptorType;
1245                         deUint32                        descriptorCount;
1246                         VkShaderStageFlags      stageFlags;
1247                         bool                            useImmutableSampler;
1248
1249                         Binding (deUint32                       binding_,
1250                                          VkDescriptorType       descriptorType_,
1251                                          deUint32                       descriptorCount_,
1252                                          VkShaderStageFlags     stageFlags_,
1253                                          bool                           useImmutableSampler_)
1254                                 : binding                               (binding_)
1255                                 , descriptorType                (descriptorType_)
1256                                 , descriptorCount               (descriptorCount_)
1257                                 , stageFlags                    (stageFlags_)
1258                                 , useImmutableSampler   (useImmutableSampler_)
1259                         {}
1260
1261                         Binding (void) {}
1262                 };
1263
1264                 vector<Binding> bindings;
1265
1266                 Parameters (const vector<Binding>& bindings_)
1267                         : bindings(bindings_)
1268                 {}
1269
1270                 static Parameters empty (void)
1271                 {
1272                         return Parameters(vector<Binding>());
1273                 }
1274
1275                 static Parameters single (deUint32                              binding,
1276                                                                   VkDescriptorType              descriptorType,
1277                                                                   deUint32                              descriptorCount,
1278                                                                   VkShaderStageFlags    stageFlags,
1279                                                                   bool                                  useImmutableSampler = false)
1280                 {
1281                         vector<Binding> bindings;
1282                         bindings.push_back(Binding(binding, descriptorType, descriptorCount, stageFlags, useImmutableSampler));
1283                         return Parameters(bindings);
1284                 }
1285         };
1286
1287         struct Resources
1288         {
1289                 vector<VkDescriptorSetLayoutBinding>    bindings;
1290                 MovePtr<Dependency<Sampler> >                   immutableSampler;
1291                 vector<VkSampler>                                               immutableSamplersPtr;
1292
1293                 Resources (const Environment& env, const Parameters& params)
1294                 {
1295                         // Create immutable sampler if needed
1296                         for (vector<Parameters::Binding>::const_iterator cur = params.bindings.begin(); cur != params.bindings.end(); cur++)
1297                         {
1298                                 if (cur->useImmutableSampler && !immutableSampler)
1299                                 {
1300                                         immutableSampler = de::newMovePtr<Dependency<Sampler> >(env, Sampler::Parameters());
1301
1302                                         if (cur->useImmutableSampler && immutableSamplersPtr.size() < (size_t)cur->descriptorCount)
1303                                                 immutableSamplersPtr.resize(cur->descriptorCount, *immutableSampler->object);
1304                                 }
1305                         }
1306
1307                         for (vector<Parameters::Binding>::const_iterator cur = params.bindings.begin(); cur != params.bindings.end(); cur++)
1308                         {
1309                                 const VkDescriptorSetLayoutBinding      binding =
1310                                 {
1311                                         cur->binding,
1312                                         cur->descriptorType,
1313                                         cur->descriptorCount,
1314                                         cur->stageFlags,
1315                                         (cur->useImmutableSampler ? &immutableSamplersPtr[0] : DE_NULL)
1316                                 };
1317
1318                                 bindings.push_back(binding);
1319                         }
1320                 }
1321         };
1322
1323         static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
1324         {
1325                 return getSafeObjectCount<DescriptorSetLayout>(context, params, DEFAULT_MAX_CONCURRENT_OBJECTS);
1326         }
1327
1328         static Move<VkDescriptorSetLayout> create (const Environment& env, const Resources& res, const Parameters&)
1329         {
1330                 const VkDescriptorSetLayoutCreateInfo   descriptorSetLayoutInfo =
1331                 {
1332                         VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
1333                         DE_NULL,
1334                         (VkDescriptorSetLayoutCreateFlags)0,
1335                         (deUint32)res.bindings.size(),
1336                         (res.bindings.empty() ? DE_NULL : &res.bindings[0])
1337                 };
1338
1339                 return createDescriptorSetLayout(env.vkd, env.device, &descriptorSetLayoutInfo, env.allocationCallbacks);
1340         }
1341 };
1342
1343 struct PipelineLayout
1344 {
1345         typedef VkPipelineLayout Type;
1346
1347         struct Parameters
1348         {
1349                 vector<DescriptorSetLayout::Parameters> descriptorSetLayouts;
1350                 vector<VkPushConstantRange>                             pushConstantRanges;
1351
1352                 Parameters (void) {}
1353
1354                 static Parameters empty (void)
1355                 {
1356                         return Parameters();
1357                 }
1358
1359                 static Parameters singleDescriptorSet (const DescriptorSetLayout::Parameters& descriptorSetLayout)
1360                 {
1361                         Parameters params;
1362                         params.descriptorSetLayouts.push_back(descriptorSetLayout);
1363                         return params;
1364                 }
1365         };
1366
1367         struct Resources
1368         {
1369                 typedef SharedPtr<Dependency<DescriptorSetLayout> >     DescriptorSetLayoutDepSp;
1370                 typedef vector<DescriptorSetLayoutDepSp>                        DescriptorSetLayouts;
1371
1372                 DescriptorSetLayouts                    descriptorSetLayouts;
1373                 vector<VkDescriptorSetLayout>   pSetLayouts;
1374
1375                 Resources (const Environment& env, const Parameters& params)
1376                 {
1377                         for (vector<DescriptorSetLayout::Parameters>::const_iterator dsParams = params.descriptorSetLayouts.begin();
1378                                  dsParams != params.descriptorSetLayouts.end();
1379                                  ++dsParams)
1380                         {
1381                                 descriptorSetLayouts.push_back(DescriptorSetLayoutDepSp(new Dependency<DescriptorSetLayout>(env, *dsParams)));
1382                                 pSetLayouts.push_back(*descriptorSetLayouts.back()->object);
1383                         }
1384                 }
1385         };
1386
1387         static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
1388         {
1389                 return getSafeObjectCount<PipelineLayout>(context, params, DEFAULT_MAX_CONCURRENT_OBJECTS);
1390         }
1391
1392         static Move<VkPipelineLayout> create (const Environment& env, const Resources& res, const Parameters& params)
1393         {
1394                 const VkPipelineLayoutCreateInfo        pipelineLayoutInfo      =
1395                 {
1396                         VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
1397                         DE_NULL,
1398                         (VkPipelineLayoutCreateFlags)0,
1399                         (deUint32)res.pSetLayouts.size(),
1400                         (res.pSetLayouts.empty() ? DE_NULL : &res.pSetLayouts[0]),
1401                         (deUint32)params.pushConstantRanges.size(),
1402                         (params.pushConstantRanges.empty() ? DE_NULL : &params.pushConstantRanges[0]),
1403                 };
1404
1405                 return createPipelineLayout(env.vkd, env.device, &pipelineLayoutInfo, env.allocationCallbacks);
1406         }
1407 };
1408
1409 struct RenderPass
1410 {
1411         typedef VkRenderPass Type;
1412
1413         // \todo [2015-09-17 pyry] More interesting configurations
1414         struct Parameters
1415         {
1416                 Parameters (void) {}
1417         };
1418
1419         struct Resources
1420         {
1421                 Resources (const Environment&, const Parameters&) {}
1422         };
1423
1424         static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
1425         {
1426                 return getSafeObjectCount<RenderPass>(context, params, DEFAULT_MAX_CONCURRENT_OBJECTS);
1427         }
1428
1429         static Move<VkRenderPass> create (const Environment& env, const Resources&, const Parameters&)
1430         {
1431                 const VkAttachmentDescription   attachments[]           =
1432                 {
1433                         {
1434                                 (VkAttachmentDescriptionFlags)0,
1435                                 VK_FORMAT_R8G8B8A8_UNORM,
1436                                 VK_SAMPLE_COUNT_1_BIT,
1437                                 VK_ATTACHMENT_LOAD_OP_CLEAR,
1438                                 VK_ATTACHMENT_STORE_OP_STORE,
1439                                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
1440                                 VK_ATTACHMENT_STORE_OP_DONT_CARE,
1441                                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1442                                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1443                         },
1444                         {
1445                                 (VkAttachmentDescriptionFlags)0,
1446                                 VK_FORMAT_D16_UNORM,
1447                                 VK_SAMPLE_COUNT_1_BIT,
1448                                 VK_ATTACHMENT_LOAD_OP_CLEAR,
1449                                 VK_ATTACHMENT_STORE_OP_DONT_CARE,
1450                                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
1451                                 VK_ATTACHMENT_STORE_OP_DONT_CARE,
1452                                 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
1453                                 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
1454                         }
1455                 };
1456                 const VkAttachmentReference             colorAttachments[]      =
1457                 {
1458                         {
1459                                 0u,                                                                                     // attachment
1460                                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1461                         }
1462                 };
1463                 const VkAttachmentReference             dsAttachment            =
1464                 {
1465                         1u,                                                                                     // attachment
1466                         VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
1467                 };
1468                 const VkSubpassDescription              subpasses[]                     =
1469                 {
1470                         {
1471                                 (VkSubpassDescriptionFlags)0,
1472                                 VK_PIPELINE_BIND_POINT_GRAPHICS,
1473                                 0u,                                                                                     // inputAttachmentCount
1474                                 DE_NULL,                                                                        // pInputAttachments
1475                                 DE_LENGTH_OF_ARRAY(colorAttachments),
1476                                 colorAttachments,
1477                                 DE_NULL,                                                                        // pResolveAttachments
1478                                 &dsAttachment,
1479                                 0u,                                                                                     // preserveAttachmentCount
1480                                 DE_NULL,                                                                        // pPreserveAttachments
1481                         }
1482                 };
1483                 const VkRenderPassCreateInfo    renderPassInfo          =
1484                 {
1485                         VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
1486                         DE_NULL,
1487                         (VkRenderPassCreateFlags)0,
1488                         DE_LENGTH_OF_ARRAY(attachments),
1489                         attachments,
1490                         DE_LENGTH_OF_ARRAY(subpasses),
1491                         subpasses,
1492                         0u,                                                                                             // dependencyCount
1493                         DE_NULL                                                                                 // pDependencies
1494                 };
1495
1496                 return createRenderPass(env.vkd, env.device, &renderPassInfo, env.allocationCallbacks);
1497         }
1498 };
1499
1500 struct GraphicsPipeline
1501 {
1502         typedef VkPipeline Type;
1503
1504         // \todo [2015-09-17 pyry] More interesting configurations
1505         struct Parameters
1506         {
1507                 Parameters (void) {}
1508         };
1509
1510         struct Resources
1511         {
1512                 Dependency<ShaderModule>        vertexShader;
1513                 Dependency<ShaderModule>        fragmentShader;
1514                 Dependency<PipelineLayout>      layout;
1515                 Dependency<RenderPass>          renderPass;
1516                 Dependency<PipelineCache>       pipelineCache;
1517
1518                 Resources (const Environment& env, const Parameters&)
1519                         : vertexShader          (env, ShaderModule::Parameters(VK_SHADER_STAGE_VERTEX_BIT, "vert"))
1520                         , fragmentShader        (env, ShaderModule::Parameters(VK_SHADER_STAGE_FRAGMENT_BIT, "frag"))
1521                         , layout                        (env, PipelineLayout::Parameters::singleDescriptorSet(
1522                                                                                 DescriptorSetLayout::Parameters::single(0u, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1u, VK_SHADER_STAGE_FRAGMENT_BIT, true)))
1523                         , renderPass            (env, RenderPass::Parameters())
1524                         , pipelineCache         (env, PipelineCache::Parameters())
1525                 {}
1526         };
1527
1528         static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
1529         {
1530                 return getSafeObjectCount<GraphicsPipeline>(context, params, DEFAULT_MAX_CONCURRENT_OBJECTS);
1531         }
1532
1533         static void initPrograms (SourceCollections& dst, Parameters)
1534         {
1535                 ShaderModule::initPrograms(dst, ShaderModule::Parameters(VK_SHADER_STAGE_VERTEX_BIT, "vert"));
1536                 ShaderModule::initPrograms(dst, ShaderModule::Parameters(VK_SHADER_STAGE_FRAGMENT_BIT, "frag"));
1537         }
1538
1539         static vector<VkPipelineSp> createMultiple (const Environment& env, const Resources& res, const Parameters&, vector<VkPipeline>* const pOutHandles, VkResult* const pOutResult)
1540         {
1541                 DE_ASSERT(pOutResult);
1542                 DE_ASSERT(pOutHandles);
1543                 DE_ASSERT(pOutHandles->size() != 0);
1544
1545                 const VkPipelineShaderStageCreateInfo                   stages[]                        =
1546                 {
1547                         {
1548                                 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1549                                 DE_NULL,
1550                                 (VkPipelineShaderStageCreateFlags)0,
1551                                 VK_SHADER_STAGE_VERTEX_BIT,
1552                                 *res.vertexShader.object,
1553                                 "main",
1554                                 DE_NULL,                                                        // pSpecializationInfo
1555                         },
1556                         {
1557                                 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1558                                 DE_NULL,
1559                                 (VkPipelineShaderStageCreateFlags)0,
1560                                 VK_SHADER_STAGE_FRAGMENT_BIT,
1561                                 *res.fragmentShader.object,
1562                                 "main",
1563                                 DE_NULL,                                                        // pSpecializationInfo
1564                         }
1565                 };
1566                 const VkVertexInputBindingDescription                   vertexBindings[]        =
1567                 {
1568                         {
1569                                 0u,                                                                     // binding
1570                                 16u,                                                            // stride
1571                                 VK_VERTEX_INPUT_RATE_VERTEX
1572                         }
1573                 };
1574                 const VkVertexInputAttributeDescription                 vertexAttribs[]         =
1575                 {
1576                         {
1577                                 0u,                                                                     // location
1578                                 0u,                                                                     // binding
1579                                 VK_FORMAT_R32G32B32A32_SFLOAT,
1580                                 0u,                                                                     // offset
1581                         }
1582                 };
1583                 const VkPipelineVertexInputStateCreateInfo              vertexInputState        =
1584                 {
1585                         VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
1586                         DE_NULL,
1587                         (VkPipelineVertexInputStateCreateFlags)0,
1588                         DE_LENGTH_OF_ARRAY(vertexBindings),
1589                         vertexBindings,
1590                         DE_LENGTH_OF_ARRAY(vertexAttribs),
1591                         vertexAttribs
1592                 };
1593                 const VkPipelineInputAssemblyStateCreateInfo    inputAssemblyState      =
1594                 {
1595                         VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
1596                         DE_NULL,
1597                         (VkPipelineInputAssemblyStateCreateFlags)0,
1598                         VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
1599                         VK_FALSE                                                                // primitiveRestartEnable
1600                 };
1601                 const VkViewport                                                                viewports[]                     =
1602                 {
1603                         { 0.0f, 0.0f, 64.f, 64.f, 0.0f, 1.0f }
1604                 };
1605                 const VkRect2D                                                                  scissors[]                      =
1606                 {
1607                         { { 0, 0 }, { 64, 64 } }
1608                 };
1609                 const VkPipelineViewportStateCreateInfo                 viewportState           =
1610                 {
1611                         VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
1612                         DE_NULL,
1613                         (VkPipelineViewportStateCreateFlags)0,
1614                         DE_LENGTH_OF_ARRAY(viewports),
1615                         viewports,
1616                         DE_LENGTH_OF_ARRAY(scissors),
1617                         scissors,
1618                 };
1619                 const VkPipelineRasterizationStateCreateInfo    rasterState                     =
1620                 {
1621                         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
1622                         DE_NULL,
1623                         (VkPipelineRasterizationStateCreateFlags)0,
1624                         VK_TRUE,                                                                // depthClampEnable
1625                         VK_FALSE,                                                               // rasterizerDiscardEnable
1626                         VK_POLYGON_MODE_FILL,
1627                         VK_CULL_MODE_BACK_BIT,
1628                         VK_FRONT_FACE_COUNTER_CLOCKWISE,
1629                         VK_FALSE,                                                               // depthBiasEnable
1630                         0.0f,                                                                   // depthBiasConstantFactor
1631                         0.0f,                                                                   // depthBiasClamp
1632                         0.0f,                                                                   // depthBiasSlopeFactor
1633                         1.0f,                                                                   // lineWidth
1634                 };
1635                 const VkPipelineMultisampleStateCreateInfo              multisampleState        =
1636                 {
1637                         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
1638                         DE_NULL,
1639                         (VkPipelineMultisampleStateCreateFlags)0,
1640                         VK_SAMPLE_COUNT_1_BIT,
1641                         VK_FALSE,                                                               // sampleShadingEnable
1642                         1.0f,                                                                   // minSampleShading
1643                         DE_NULL,                                                                // pSampleMask
1644                         VK_FALSE,                                                               // alphaToCoverageEnable
1645                         VK_FALSE,                                                               // alphaToOneEnable
1646                 };
1647                 const VkPipelineDepthStencilStateCreateInfo             depthStencilState       =
1648                 {
1649                         VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
1650                         DE_NULL,
1651                         (VkPipelineDepthStencilStateCreateFlags)0,
1652                         VK_TRUE,                                                                // depthTestEnable
1653                         VK_TRUE,                                                                // depthWriteEnable
1654                         VK_COMPARE_OP_LESS,                                             // depthCompareOp
1655                         VK_FALSE,                                                               // depthBoundsTestEnable
1656                         VK_FALSE,                                                               // stencilTestEnable
1657                         { VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_ALWAYS, 0u, 0u, 0u },
1658                         { VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_ALWAYS, 0u, 0u, 0u },
1659                         0.0f,                                                                   // minDepthBounds
1660                         1.0f,                                                                   // maxDepthBounds
1661                 };
1662                 const VkPipelineColorBlendAttachmentState               colorBlendAttState[]=
1663                 {
1664                         {
1665                                 VK_FALSE,                                                       // blendEnable
1666                                 VK_BLEND_FACTOR_ONE,
1667                                 VK_BLEND_FACTOR_ZERO,
1668                                 VK_BLEND_OP_ADD,
1669                                 VK_BLEND_FACTOR_ONE,
1670                                 VK_BLEND_FACTOR_ZERO,
1671                                 VK_BLEND_OP_ADD,
1672                                 VK_COLOR_COMPONENT_R_BIT|VK_COLOR_COMPONENT_G_BIT|VK_COLOR_COMPONENT_B_BIT|VK_COLOR_COMPONENT_A_BIT
1673                         }
1674                 };
1675                 const VkPipelineColorBlendStateCreateInfo               colorBlendState         =
1676                 {
1677                         VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
1678                         DE_NULL,
1679                         (VkPipelineColorBlendStateCreateFlags)0,
1680                         VK_FALSE,                                                               // logicOpEnable
1681                         VK_LOGIC_OP_COPY,
1682                         DE_LENGTH_OF_ARRAY(colorBlendAttState),
1683                         colorBlendAttState,
1684                         { 0.0f, 0.0f, 0.0f, 0.0f }                              // blendConstants
1685                 };
1686                 const VkGraphicsPipelineCreateInfo                              pipelineInfo            =
1687                 {
1688                         VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
1689                         DE_NULL,
1690                         (VkPipelineCreateFlags)0,
1691                         DE_LENGTH_OF_ARRAY(stages),
1692                         stages,
1693                         &vertexInputState,
1694                         &inputAssemblyState,
1695                         DE_NULL,                                                                // pTessellationState
1696                         &viewportState,
1697                         &rasterState,
1698                         &multisampleState,
1699                         &depthStencilState,
1700                         &colorBlendState,
1701                         (const VkPipelineDynamicStateCreateInfo*)DE_NULL,
1702                         *res.layout.object,
1703                         *res.renderPass.object,
1704                         0u,                                                                             // subpass
1705                         (VkPipeline)0,                                                  // basePipelineHandle
1706                         0,                                                                              // basePipelineIndex
1707                 };
1708
1709                 const deUint32                                                  numPipelines    = static_cast<deUint32>(pOutHandles->size());
1710                 VkPipeline*     const                                           pHandles                = &(*pOutHandles)[0];
1711                 vector<VkGraphicsPipelineCreateInfo>    pipelineInfos   (numPipelines, pipelineInfo);
1712
1713                 *pOutResult = env.vkd.createGraphicsPipelines(env.device, *res.pipelineCache.object, numPipelines, &pipelineInfos[0], env.allocationCallbacks, pHandles);
1714
1715                 vector<VkPipelineSp>    pipelines;
1716
1717                 // Even if an error is returned, some pipelines may have been created successfully
1718                 for (deUint32 i = 0; i < numPipelines; ++i)
1719                 {
1720                         if (pHandles[i] != DE_NULL)
1721                                 pipelines.push_back(VkPipelineSp(new Move<VkPipeline>(check<VkPipeline>(pHandles[i]), Deleter<VkPipeline>(env.vkd, env.device, env.allocationCallbacks))));
1722                 }
1723
1724                 return pipelines;
1725         }
1726
1727         static Move<VkPipeline> create (const Environment& env, const Resources& res, const Parameters&)
1728         {
1729                 vector<VkPipeline>              handles                 (1, DE_NULL);
1730                 VkResult                                result                  = VK_NOT_READY;
1731                 vector<VkPipelineSp>    scopedHandles   = createMultiple(env, res, Parameters(), &handles, &result);
1732
1733                 VK_CHECK(result);
1734                 return Move<VkPipeline>(check<VkPipeline>(scopedHandles.front()->disown()), Deleter<VkPipeline>(env.vkd, env.device, env.allocationCallbacks));
1735         }
1736 };
1737
1738 struct ComputePipeline
1739 {
1740         typedef VkPipeline Type;
1741
1742         // \todo [2015-09-17 pyry] More interesting configurations
1743         struct Parameters
1744         {
1745                 Parameters (void) {}
1746         };
1747
1748         struct Resources
1749         {
1750                 Dependency<ShaderModule>        shaderModule;
1751                 Dependency<PipelineLayout>      layout;
1752                 Dependency<PipelineCache>       pipelineCache;
1753
1754                 static DescriptorSetLayout::Parameters getDescriptorSetLayout (void)
1755                 {
1756                         typedef DescriptorSetLayout::Parameters::Binding Binding;
1757
1758                         vector<Binding> bindings;
1759
1760                         bindings.push_back(Binding(0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u, VK_SHADER_STAGE_COMPUTE_BIT, false));
1761                         bindings.push_back(Binding(1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u, VK_SHADER_STAGE_COMPUTE_BIT, false));
1762
1763                         return DescriptorSetLayout::Parameters(bindings);
1764                 }
1765
1766                 Resources (const Environment& env, const Parameters&)
1767                         : shaderModule          (env, ShaderModule::Parameters(VK_SHADER_STAGE_COMPUTE_BIT, "comp"))
1768                         , layout                        (env, PipelineLayout::Parameters::singleDescriptorSet(getDescriptorSetLayout()))
1769                         , pipelineCache         (env, PipelineCache::Parameters())
1770                 {}
1771         };
1772
1773         static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
1774         {
1775                 return getSafeObjectCount<ComputePipeline>(context, params, DEFAULT_MAX_CONCURRENT_OBJECTS);
1776         }
1777
1778         static void initPrograms (SourceCollections& dst, Parameters)
1779         {
1780                 ShaderModule::initPrograms(dst, ShaderModule::Parameters(VK_SHADER_STAGE_COMPUTE_BIT, "comp"));
1781         }
1782
1783         static Move<VkPipeline> create (const Environment& env, const Resources& res, const Parameters&)
1784         {
1785                 const VkComputePipelineCreateInfo       pipelineInfo    =
1786                 {
1787                         VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
1788                         DE_NULL,
1789                         (VkPipelineCreateFlags)0,
1790                         {
1791                                 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1792                                 DE_NULL,
1793                                 (VkPipelineShaderStageCreateFlags)0,
1794                                 VK_SHADER_STAGE_COMPUTE_BIT,
1795                                 *res.shaderModule.object,
1796                                 "main",
1797                                 DE_NULL                                 // pSpecializationInfo
1798                         },
1799                         *res.layout.object,
1800                         (VkPipeline)0,                          // basePipelineHandle
1801                         0u,                                                     // basePipelineIndex
1802                 };
1803
1804                 return createComputePipeline(env.vkd, env.device, *res.pipelineCache.object, &pipelineInfo, env.allocationCallbacks);
1805         }
1806
1807         static vector<VkPipelineSp> createMultiple (const Environment& env, const Resources& res, const Parameters&, vector<VkPipeline>* const pOutHandles, VkResult* const pOutResult)
1808         {
1809                 DE_ASSERT(pOutResult);
1810                 DE_ASSERT(pOutHandles);
1811                 DE_ASSERT(pOutHandles->size() != 0);
1812
1813                 const VkComputePipelineCreateInfo       commonPipelineInfo      =
1814                 {
1815                         VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
1816                         DE_NULL,
1817                         (VkPipelineCreateFlags)0,
1818                         {
1819                                 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1820                                 DE_NULL,
1821                                 (VkPipelineShaderStageCreateFlags)0,
1822                                 VK_SHADER_STAGE_COMPUTE_BIT,
1823                                 *res.shaderModule.object,
1824                                 "main",
1825                                 DE_NULL                                 // pSpecializationInfo
1826                         },
1827                         *res.layout.object,
1828                         (VkPipeline)0,                          // basePipelineHandle
1829                         0u,                                                     // basePipelineIndex
1830                 };
1831
1832                 const deUint32                                          numPipelines    = static_cast<deUint32>(pOutHandles->size());
1833                 VkPipeline*     const                                   pHandles                = &(*pOutHandles)[0];
1834                 vector<VkComputePipelineCreateInfo>     pipelineInfos   (numPipelines, commonPipelineInfo);
1835
1836                 *pOutResult = env.vkd.createComputePipelines(env.device, *res.pipelineCache.object, numPipelines, &pipelineInfos[0], env.allocationCallbacks, pHandles);
1837
1838                 vector<VkPipelineSp>    pipelines;
1839
1840                 // Even if an error is returned, some pipelines may have been created successfully
1841                 for (deUint32 i = 0; i < numPipelines; ++i)
1842                 {
1843                         if (pHandles[i] != DE_NULL)
1844                                 pipelines.push_back(VkPipelineSp(new Move<VkPipeline>(check<VkPipeline>(pHandles[i]), Deleter<VkPipeline>(env.vkd, env.device, env.allocationCallbacks))));
1845                 }
1846
1847                 return pipelines;
1848         }
1849 };
1850
1851 struct DescriptorPool
1852 {
1853         typedef VkDescriptorPool Type;
1854
1855         struct Parameters
1856         {
1857                 VkDescriptorPoolCreateFlags             flags;
1858                 deUint32                                                maxSets;
1859                 vector<VkDescriptorPoolSize>    poolSizes;
1860
1861                 Parameters (VkDescriptorPoolCreateFlags                         flags_,
1862                                         deUint32                                                                maxSets_,
1863                                         const vector<VkDescriptorPoolSize>&             poolSizes_)
1864                         : flags         (flags_)
1865                         , maxSets       (maxSets_)
1866                         , poolSizes     (poolSizes_)
1867                 {}
1868
1869                 static Parameters singleType (VkDescriptorPoolCreateFlags       flags,
1870                                                                           deUint32                                              maxSets,
1871                                                                           VkDescriptorType                              type,
1872                                                                           deUint32                                              count)
1873                 {
1874                         vector<VkDescriptorPoolSize> poolSizes;
1875                         poolSizes.push_back(makeDescriptorPoolSize(type, count));
1876                         return Parameters(flags, maxSets, poolSizes);
1877                 }
1878         };
1879
1880         struct Resources
1881         {
1882                 Resources (const Environment&, const Parameters&) {}
1883         };
1884
1885         static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
1886         {
1887                 return getSafeObjectCount<DescriptorPool>(context, params, DEFAULT_MAX_CONCURRENT_OBJECTS);
1888         }
1889
1890         static Move<VkDescriptorPool> create (const Environment& env, const Resources&, const Parameters& params)
1891         {
1892                 const VkDescriptorPoolCreateInfo        descriptorPoolInfo      =
1893                 {
1894                         VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
1895                         DE_NULL,
1896                         params.flags,
1897                         params.maxSets,
1898                         (deUint32)params.poolSizes.size(),
1899                         (params.poolSizes.empty() ? DE_NULL : &params.poolSizes[0])
1900                 };
1901
1902                 return createDescriptorPool(env.vkd, env.device, &descriptorPoolInfo, env.allocationCallbacks);
1903         }
1904 };
1905
1906 struct DescriptorSet
1907 {
1908         typedef VkDescriptorSet Type;
1909
1910         struct Parameters
1911         {
1912                 DescriptorSetLayout::Parameters descriptorSetLayout;
1913
1914                 Parameters (const DescriptorSetLayout::Parameters& descriptorSetLayout_)
1915                         : descriptorSetLayout(descriptorSetLayout_)
1916                 {}
1917         };
1918
1919         struct Resources
1920         {
1921                 Dependency<DescriptorPool>              descriptorPool;
1922                 Dependency<DescriptorSetLayout> descriptorSetLayout;
1923
1924                 static vector<VkDescriptorPoolSize> computePoolSizes (const DescriptorSetLayout::Parameters& layout, int maxSets)
1925                 {
1926                         deUint32                                                countByType[VK_DESCRIPTOR_TYPE_LAST];
1927                         vector<VkDescriptorPoolSize>    typeCounts;
1928
1929                         std::fill(DE_ARRAY_BEGIN(countByType), DE_ARRAY_END(countByType), 0u);
1930
1931                         for (vector<DescriptorSetLayout::Parameters::Binding>::const_iterator cur = layout.bindings.begin();
1932                                  cur != layout.bindings.end();
1933                                  ++cur)
1934                         {
1935                                 DE_ASSERT((deUint32)cur->descriptorType < VK_DESCRIPTOR_TYPE_LAST);
1936                                 countByType[cur->descriptorType] += cur->descriptorCount * maxSets;
1937                         }
1938
1939                         for (deUint32 type = 0; type < VK_DESCRIPTOR_TYPE_LAST; ++type)
1940                         {
1941                                 if (countByType[type] > 0)
1942                                         typeCounts.push_back(makeDescriptorPoolSize((VkDescriptorType)type, countByType[type]));
1943                         }
1944
1945                         return typeCounts;
1946                 }
1947
1948                 Resources (const Environment& env, const Parameters& params)
1949                         : descriptorPool                (env, DescriptorPool::Parameters(VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, env.maxResourceConsumers, computePoolSizes(params.descriptorSetLayout, env.maxResourceConsumers)))
1950                         , descriptorSetLayout   (env, params.descriptorSetLayout)
1951                 {
1952                 }
1953         };
1954
1955         static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
1956         {
1957                 return getSafeObjectCount<DescriptorSet>(context, params, DEFAULT_MAX_CONCURRENT_OBJECTS);
1958         }
1959
1960         static Move<VkDescriptorSet> create (const Environment& env, const Resources& res, const Parameters&)
1961         {
1962                 const VkDescriptorSetAllocateInfo       allocateInfo    =
1963                 {
1964                         VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
1965                         DE_NULL,
1966                         *res.descriptorPool.object,
1967                         1u,
1968                         &res.descriptorSetLayout.object.get(),
1969                 };
1970
1971                 return allocateDescriptorSet(env.vkd, env.device, &allocateInfo);
1972         }
1973
1974         static vector<VkDescriptorSetSp> createMultiple (const Environment& env, const Resources& res, const Parameters&, vector<VkDescriptorSet>* const pOutHandles, VkResult* const pOutResult)
1975         {
1976                 DE_ASSERT(pOutResult);
1977                 DE_ASSERT(pOutHandles);
1978                 DE_ASSERT(pOutHandles->size() != 0);
1979
1980                 const deUint32                                          numDescriptorSets               = static_cast<deUint32>(pOutHandles->size());
1981                 VkDescriptorSet* const                          pHandles                                = &(*pOutHandles)[0];
1982                 const vector<VkDescriptorSetLayout>     descriptorSetLayouts    (numDescriptorSets, res.descriptorSetLayout.object.get());
1983
1984                 const VkDescriptorSetAllocateInfo       allocateInfo                    =
1985                 {
1986                         VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
1987                         DE_NULL,
1988                         *res.descriptorPool.object,
1989                         numDescriptorSets,
1990                         &descriptorSetLayouts[0],
1991                 };
1992
1993                 *pOutResult = env.vkd.allocateDescriptorSets(env.device, &allocateInfo, pHandles);
1994
1995                 vector<VkDescriptorSetSp>       descriptorSets;
1996
1997                 if (*pOutResult == VK_SUCCESS)
1998                 {
1999                         for (deUint32 i = 0; i < numDescriptorSets; ++i)
2000                                 descriptorSets.push_back(VkDescriptorSetSp(new Move<VkDescriptorSet>(check<VkDescriptorSet>(pHandles[i]), Deleter<VkDescriptorSet>(env.vkd, env.device, *res.descriptorPool.object))));
2001                 }
2002
2003                 return descriptorSets;
2004         }
2005 };
2006
2007 struct Framebuffer
2008 {
2009         typedef VkFramebuffer Type;
2010
2011         struct Parameters
2012         {
2013                 Parameters (void)
2014                 {}
2015         };
2016
2017         struct Resources
2018         {
2019                 Dependency<ImageView>   colorAttachment;
2020                 Dependency<ImageView>   depthStencilAttachment;
2021                 Dependency<RenderPass>  renderPass;
2022
2023                 Resources (const Environment& env, const Parameters&)
2024                         : colorAttachment                       (env, ImageView::Parameters(Image::Parameters(0u, VK_IMAGE_TYPE_2D, VK_FORMAT_R8G8B8A8_UNORM,
2025                                                                                                                                                                           makeExtent3D(256, 256, 1),
2026                                                                                                                                                                           1u, 1u,
2027                                                                                                                                                                           VK_SAMPLE_COUNT_1_BIT,
2028                                                                                                                                                                           VK_IMAGE_TILING_OPTIMAL,
2029                                                                                                                                                                           VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
2030                                                                                                                                                                           VK_IMAGE_LAYOUT_UNDEFINED),
2031                                                                                                                                                  VK_IMAGE_VIEW_TYPE_2D, VK_FORMAT_R8G8B8A8_UNORM,
2032                                                                                                                                                  makeComponentMappingRGBA(),
2033                                                                                                                                                  makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u)))
2034                         , depthStencilAttachment        (env, ImageView::Parameters(Image::Parameters(0u, VK_IMAGE_TYPE_2D, VK_FORMAT_D16_UNORM,
2035                                                                                                                                                                           makeExtent3D(256, 256, 1),
2036                                                                                                                                                                           1u, 1u,
2037                                                                                                                                                                           VK_SAMPLE_COUNT_1_BIT,
2038                                                                                                                                                                           VK_IMAGE_TILING_OPTIMAL,
2039                                                                                                                                                                           VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
2040                                                                                                                                                                           VK_IMAGE_LAYOUT_UNDEFINED),
2041                                                                                                                                                  VK_IMAGE_VIEW_TYPE_2D, VK_FORMAT_D16_UNORM,
2042                                                                                                                                                  makeComponentMappingRGBA(),
2043                                                                                                                                                  makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u)))
2044                         , renderPass                            (env, RenderPass::Parameters())
2045                 {}
2046         };
2047
2048         static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
2049         {
2050                 // \todo [2016-03-23 pyry] Take into account attachment sizes
2051                 return getSafeObjectCount<Framebuffer>(context, params, DEFAULT_MAX_CONCURRENT_OBJECTS);
2052         }
2053
2054         static Move<VkFramebuffer> create (const Environment& env, const Resources& res, const Parameters&)
2055         {
2056                 const VkImageView                               attachments[]   =
2057                 {
2058                         *res.colorAttachment.object,
2059                         *res.depthStencilAttachment.object,
2060                 };
2061                 const VkFramebufferCreateInfo   framebufferInfo =
2062                 {
2063                         VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
2064                         DE_NULL,
2065                         (VkFramebufferCreateFlags)0,
2066                         *res.renderPass.object,
2067                         (deUint32)DE_LENGTH_OF_ARRAY(attachments),
2068                         attachments,
2069                         256u,                                                                           // width
2070                         256u,                                                                           // height
2071                         1u                                                                                      // layers
2072                 };
2073
2074                 return createFramebuffer(env.vkd, env.device, &framebufferInfo, env.allocationCallbacks);
2075         }
2076 };
2077
2078 struct CommandPool
2079 {
2080         typedef VkCommandPool Type;
2081
2082         struct Parameters
2083         {
2084                 VkCommandPoolCreateFlags        flags;
2085
2086                 Parameters (VkCommandPoolCreateFlags flags_)
2087                         : flags(flags_)
2088                 {}
2089         };
2090
2091         struct Resources
2092         {
2093                 Resources (const Environment&, const Parameters&) {}
2094         };
2095
2096         static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
2097         {
2098                 return getSafeObjectCount<CommandPool>(context, params, DEFAULT_MAX_CONCURRENT_OBJECTS);
2099         }
2100
2101         static Move<VkCommandPool> create (const Environment& env, const Resources&, const Parameters& params)
2102         {
2103                 const VkCommandPoolCreateInfo   cmdPoolInfo     =
2104                 {
2105                         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
2106                         DE_NULL,
2107                         params.flags,
2108                         env.queueFamilyIndex,
2109                 };
2110
2111                 return createCommandPool(env.vkd, env.device, &cmdPoolInfo, env.allocationCallbacks);
2112         }
2113 };
2114
2115 struct CommandBuffer
2116 {
2117         typedef VkCommandBuffer Type;
2118
2119         struct Parameters
2120         {
2121                 CommandPool::Parameters         commandPool;
2122                 VkCommandBufferLevel            level;
2123
2124                 Parameters (const CommandPool::Parameters&      commandPool_,
2125                                         VkCommandBufferLevel                    level_)
2126                         : commandPool   (commandPool_)
2127                         , level                 (level_)
2128                 {}
2129         };
2130
2131         struct Resources
2132         {
2133                 Dependency<CommandPool> commandPool;
2134
2135                 Resources (const Environment& env, const Parameters& params)
2136                         : commandPool(env, params.commandPool)
2137                 {}
2138         };
2139
2140         static deUint32 getMaxConcurrent (Context& context, const Parameters& params)
2141         {
2142                 return getSafeObjectCount<CommandBuffer>(context, params, DEFAULT_MAX_CONCURRENT_OBJECTS);
2143         }
2144
2145         static Move<VkCommandBuffer> create (const Environment& env, const Resources& res, const Parameters& params)
2146         {
2147                 const VkCommandBufferAllocateInfo       cmdBufferInfo   =
2148                 {
2149                         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
2150                         DE_NULL,
2151                         *res.commandPool.object,
2152                         params.level,
2153                         1,                                                      // bufferCount
2154                 };
2155
2156                 return allocateCommandBuffer(env.vkd, env.device, &cmdBufferInfo);
2157         }
2158
2159         static vector<VkCommandBufferSp> createMultiple (const Environment& env, const Resources& res, const Parameters& params, vector<VkCommandBuffer>* const pOutHandles, VkResult* const pOutResult)
2160         {
2161                 DE_ASSERT(pOutResult);
2162                 DE_ASSERT(pOutHandles);
2163                 DE_ASSERT(pOutHandles->size() != 0);
2164
2165                 const deUint32                                          numCommandBuffers       = static_cast<deUint32>(pOutHandles->size());
2166                 VkCommandBuffer* const                          pHandles                        = &(*pOutHandles)[0];
2167
2168                 const VkCommandBufferAllocateInfo       cmdBufferInfo           =
2169                 {
2170                         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
2171                         DE_NULL,
2172                         *res.commandPool.object,
2173                         params.level,
2174                         numCommandBuffers,
2175                 };
2176
2177                 *pOutResult = env.vkd.allocateCommandBuffers(env.device, &cmdBufferInfo, pHandles);
2178
2179                 vector<VkCommandBufferSp>       commandBuffers;
2180
2181                 if (*pOutResult == VK_SUCCESS)
2182                 {
2183                         for (deUint32 i = 0; i < numCommandBuffers; ++i)
2184                                 commandBuffers.push_back(VkCommandBufferSp(new Move<VkCommandBuffer>(check<VkCommandBuffer>(pHandles[i]), Deleter<VkCommandBuffer>(env.vkd, env.device, *res.commandPool.object))));
2185                 }
2186
2187                 return commandBuffers;
2188         }
2189 };
2190
2191 // Test cases
2192
2193 template<typename Object>
2194 tcu::TestStatus createSingleTest (Context& context, typename Object::Parameters params)
2195 {
2196         const Environment                                       env     (context, 1u);
2197         const typename Object::Resources        res     (env, params);
2198
2199         {
2200                 Unique<typename Object::Type>   obj     (Object::create(env, res, params));
2201         }
2202
2203         return tcu::TestStatus::pass("Ok");
2204 }
2205
2206 template<typename Object>
2207 tcu::TestStatus createMultipleUniqueResourcesTest (Context& context, typename Object::Parameters params)
2208 {
2209         const Environment                                       env             (context, 1u);
2210         const typename Object::Resources        res0    (env, params);
2211         const typename Object::Resources        res1    (env, params);
2212         const typename Object::Resources        res2    (env, params);
2213         const typename Object::Resources        res3    (env, params);
2214
2215         {
2216                 Unique<typename Object::Type>   obj0    (Object::create(env, res0, params));
2217                 Unique<typename Object::Type>   obj1    (Object::create(env, res1, params));
2218                 Unique<typename Object::Type>   obj2    (Object::create(env, res2, params));
2219                 Unique<typename Object::Type>   obj3    (Object::create(env, res3, params));
2220         }
2221
2222         return tcu::TestStatus::pass("Ok");
2223 }
2224
2225 template<typename Object>
2226 tcu::TestStatus createMultipleSharedResourcesTest (Context& context, typename Object::Parameters params)
2227 {
2228         const Environment                                       env     (context, 4u);
2229         const typename Object::Resources        res     (env, params);
2230
2231         {
2232                 Unique<typename Object::Type>   obj0    (Object::create(env, res, params));
2233                 Unique<typename Object::Type>   obj1    (Object::create(env, res, params));
2234                 Unique<typename Object::Type>   obj2    (Object::create(env, res, params));
2235                 Unique<typename Object::Type>   obj3    (Object::create(env, res, params));
2236         }
2237
2238         return tcu::TestStatus::pass("Ok");
2239 }
2240
2241 template<typename Object>
2242 tcu::TestStatus createMaxConcurrentTest (Context& context, typename Object::Parameters params)
2243 {
2244         typedef Unique<typename Object::Type>   UniqueObject;
2245         typedef SharedPtr<UniqueObject>                 ObjectPtr;
2246
2247         const deUint32                                          numObjects                      = Object::getMaxConcurrent(context, params);
2248         const Environment                                       env                                     (context, numObjects);
2249         const typename Object::Resources        res                                     (env, params);
2250         vector<ObjectPtr>                                       objects                         (numObjects);
2251         const deUint32                                          watchdogInterval        = 1024;
2252
2253         context.getTestContext().getLog()
2254                 << TestLog::Message << "Creating " << numObjects << " " << getTypeName<typename Object::Type>() << " objects" << TestLog::EndMessage;
2255
2256         for (deUint32 ndx = 0; ndx < numObjects; ndx++)
2257         {
2258                 objects[ndx] = ObjectPtr(new UniqueObject(Object::create(env, res, params)));
2259
2260                 if ((ndx > 0) && ((ndx % watchdogInterval) == 0))
2261                         context.getTestContext().touchWatchdog();
2262         }
2263
2264         context.getTestContext().touchWatchdog();
2265         objects.clear();
2266
2267         return tcu::TestStatus::pass("Ok");
2268 }
2269
2270 // How many objects to create per thread
2271 template<typename Object>       int getCreateCount                              (void) { return 100;    }
2272
2273 // Creating VkDevice and VkInstance can take significantly longer than other object types
2274 template<>                                      int getCreateCount<Instance>    (void) { return 20;             }
2275 template<>                                      int getCreateCount<Device>              (void) { return 20;             }
2276
2277 template<typename Object>
2278 class CreateThread : public ThreadGroupThread
2279 {
2280 public:
2281         CreateThread (const Environment& env, const typename Object::Resources& resources, const typename Object::Parameters& params)
2282                 : m_env                 (env)
2283                 , m_resources   (resources)
2284                 , m_params              (params)
2285         {}
2286
2287         void runThread (void)
2288         {
2289                 const int       numIters                        = getCreateCount<Object>();
2290                 const int       itersBetweenSyncs       = numIters / 5;
2291
2292                 DE_ASSERT(itersBetweenSyncs > 0);
2293
2294                 for (int iterNdx = 0; iterNdx < numIters; iterNdx++)
2295                 {
2296                         // Sync every Nth iteration to make entering driver at the same time more likely
2297                         if ((iterNdx % itersBetweenSyncs) == 0)
2298                                 barrier();
2299
2300                         {
2301                                 Unique<typename Object::Type>   obj     (Object::create(m_env, m_resources, m_params));
2302                         }
2303                 }
2304         }
2305
2306 private:
2307         const Environment&                                      m_env;
2308         const typename Object::Resources&       m_resources;
2309         const typename Object::Parameters&      m_params;
2310 };
2311
2312 template<typename Object>
2313 tcu::TestStatus multithreadedCreateSharedResourcesTest (Context& context, typename Object::Parameters params)
2314 {
2315         const deUint32                                          numThreads      = getDefaultTestThreadCount();
2316         const Environment                                       env                     (context, numThreads);
2317         const typename Object::Resources        res                     (env, params);
2318         ThreadGroup                                                     threads;
2319
2320         for (deUint32 ndx = 0; ndx < numThreads; ndx++)
2321                 threads.add(MovePtr<ThreadGroupThread>(new CreateThread<Object>(env, res, params)));
2322
2323         return threads.run();
2324 }
2325
2326 template<typename Object>
2327 tcu::TestStatus multithreadedCreatePerThreadResourcesTest (Context& context, typename Object::Parameters params)
2328 {
2329         typedef SharedPtr<typename Object::Resources>   ResPtr;
2330
2331         const deUint32          numThreads      = getDefaultTestThreadCount();
2332         const Environment       env                     (context, 1u);
2333         vector<ResPtr>          resources       (numThreads);
2334         ThreadGroup                     threads;
2335
2336         for (deUint32 ndx = 0; ndx < numThreads; ndx++)
2337         {
2338                 resources[ndx] = ResPtr(new typename Object::Resources(env, params));
2339                 threads.add(MovePtr<ThreadGroupThread>(new CreateThread<Object>(env, *resources[ndx], params)));
2340         }
2341
2342         return threads.run();
2343 }
2344
2345 struct EnvClone
2346 {
2347         Device::Resources       deviceRes;
2348         Unique<VkDevice>        device;
2349         DeviceDriver            vkd;
2350         Environment                     env;
2351
2352         EnvClone (const Environment& parent, const Device::Parameters& deviceParams, deUint32 maxResourceConsumers)
2353                 : deviceRes     (parent, deviceParams)
2354                 , device        (Device::create(parent, deviceRes, deviceParams))
2355                 , vkd           (deviceRes.vki, *device)
2356                 , env           (parent.vkp, vkd, *device, deviceRes.queueFamilyIndex, parent.programBinaries, parent.allocationCallbacks, maxResourceConsumers)
2357         {
2358         }
2359 };
2360
2361 Device::Parameters getDefaulDeviceParameters (Context& context)
2362 {
2363         return Device::Parameters(context.getTestContext().getCommandLine().getVKDeviceId()-1u,
2364                                                           VK_QUEUE_GRAPHICS_BIT|VK_QUEUE_COMPUTE_BIT);
2365 }
2366
2367 template<typename Object>
2368 tcu::TestStatus multithreadedCreatePerThreadDeviceTest (Context& context, typename Object::Parameters params)
2369 {
2370         typedef SharedPtr<EnvClone>                                             EnvPtr;
2371         typedef SharedPtr<typename Object::Resources>   ResPtr;
2372
2373         const deUint32                          numThreads              = getDefaultTestThreadCount();
2374         const Device::Parameters        deviceParams    = getDefaulDeviceParameters(context);
2375         const Environment                       sharedEnv               (context, numThreads);                  // For creating Device's
2376         vector<EnvPtr>                          perThreadEnv    (numThreads);
2377         vector<ResPtr>                          resources               (numThreads);
2378         ThreadGroup                                     threads;
2379
2380         for (deUint32 ndx = 0; ndx < numThreads; ndx++)
2381         {
2382                 perThreadEnv[ndx]       = EnvPtr(new EnvClone(sharedEnv, deviceParams, 1u));
2383                 resources[ndx]          = ResPtr(new typename Object::Resources(perThreadEnv[ndx]->env, params));
2384
2385                 threads.add(MovePtr<ThreadGroupThread>(new CreateThread<Object>(perThreadEnv[ndx]->env, *resources[ndx], params)));
2386         }
2387
2388         return threads.run();
2389 }
2390
2391 template<typename Object>
2392 tcu::TestStatus createSingleAllocCallbacksTest (Context& context, typename Object::Parameters params)
2393 {
2394         const deUint32                                          noCmdScope              = (1u << VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE)
2395                                                                                                                 | (1u << VK_SYSTEM_ALLOCATION_SCOPE_DEVICE)
2396                                                                                                                 | (1u << VK_SYSTEM_ALLOCATION_SCOPE_CACHE)
2397                                                                                                                 | (1u << VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
2398
2399         // Callbacks used by resources
2400         AllocationCallbackRecorder                      resCallbacks    (getSystemAllocator(), 128);
2401
2402         // Root environment still uses default instance and device, created without callbacks
2403         const Environment                                       rootEnv                 (context.getPlatformInterface(),
2404                                                                                                                  context.getDeviceInterface(),
2405                                                                                                                  context.getDevice(),
2406                                                                                                                  context.getUniversalQueueFamilyIndex(),
2407                                                                                                                  context.getBinaryCollection(),
2408                                                                                                                  resCallbacks.getCallbacks(),
2409                                                                                                                  1u);
2410
2411         {
2412                 // Test env has instance & device created with callbacks
2413                 const EnvClone                                          resEnv          (rootEnv, getDefaulDeviceParameters(context), 1u);
2414                 const typename Object::Resources        res                     (resEnv.env, params);
2415
2416                 // Supply a separate callback recorder just for object construction
2417                 AllocationCallbackRecorder                      objCallbacks(getSystemAllocator(), 128);
2418                 const Environment                                       objEnv          (resEnv.env.vkp,
2419                                                                                                                  resEnv.env.vkd,
2420                                                                                                                  resEnv.env.device,
2421                                                                                                                  resEnv.env.queueFamilyIndex,
2422                                                                                                                  resEnv.env.programBinaries,
2423                                                                                                                  objCallbacks.getCallbacks(),
2424                                                                                                                  resEnv.env.maxResourceConsumers);
2425
2426                 {
2427                         Unique<typename Object::Type>   obj     (Object::create(objEnv, res, params));
2428
2429                         // Validate that no command-level allocations are live
2430                         if (!validateAndLog(context.getTestContext().getLog(), objCallbacks, noCmdScope))
2431                                 return tcu::TestStatus::fail("Invalid allocation callback");
2432                 }
2433
2434                 // At this point all allocations made against object callbacks must have been freed
2435                 if (!validateAndLog(context.getTestContext().getLog(), objCallbacks, 0u))
2436                         return tcu::TestStatus::fail("Invalid allocation callback");
2437         }
2438
2439         if (!validateAndLog(context.getTestContext().getLog(), resCallbacks, 0u))
2440                 return tcu::TestStatus::fail("Invalid allocation callback");
2441
2442         return tcu::TestStatus::pass("Ok");
2443 }
2444
2445 template<typename Object>       deUint32        getOomIterLimit                 (void) { return 1024;   }
2446 template<>                                      deUint32        getOomIterLimit<Device> (void) { return 20;             }
2447
2448 template<typename Object>
2449 tcu::TestStatus allocCallbackFailTest (Context& context, typename Object::Parameters params)
2450 {
2451         AllocationCallbackRecorder                      resCallbacks            (getSystemAllocator(), 128);
2452         const Environment                                       rootEnv                         (context.getPlatformInterface(),
2453                                                                                                                          context.getDeviceInterface(),
2454                                                                                                                          context.getDevice(),
2455                                                                                                                          context.getUniversalQueueFamilyIndex(),
2456                                                                                                                          context.getBinaryCollection(),
2457                                                                                                                          resCallbacks.getCallbacks(),
2458                                                                                                                          1u);
2459         deUint32                                                        numPassingAllocs        = 0;
2460         const deUint32                                          cmdLineIterCount        = (deUint32)context.getTestContext().getCommandLine().getTestIterationCount();
2461         const deUint32                                          maxTries                        = cmdLineIterCount != 0 ? cmdLineIterCount : getOomIterLimit<Object>();
2462
2463         {
2464                 const EnvClone                                          resEnv  (rootEnv, getDefaulDeviceParameters(context), 1u);
2465                 const typename Object::Resources        res             (resEnv.env, params);
2466
2467                 // Iterate over test until object allocation succeeds
2468                 for (; numPassingAllocs < maxTries; ++numPassingAllocs)
2469                 {
2470                         DeterministicFailAllocator                      objAllocator(getSystemAllocator(),
2471                                                                                                                          DeterministicFailAllocator::MODE_COUNT_AND_FAIL,
2472                                                                                                                          numPassingAllocs);
2473                         AllocationCallbackRecorder                      recorder        (objAllocator.getCallbacks(), 128);
2474                         const Environment                                       objEnv          (resEnv.env.vkp,
2475                                                                                                                          resEnv.env.vkd,
2476                                                                                                                          resEnv.env.device,
2477                                                                                                                          resEnv.env.queueFamilyIndex,
2478                                                                                                                          resEnv.env.programBinaries,
2479                                                                                                                          recorder.getCallbacks(),
2480                                                                                                                          resEnv.env.maxResourceConsumers);
2481                         bool                                                            createOk        = false;
2482
2483                         context.getTestContext().getLog()
2484                                 << TestLog::Message
2485                                 << "Trying to create object with " << numPassingAllocs << " allocation" << (numPassingAllocs != 1 ? "s" : "") << " passing"
2486                                 << TestLog::EndMessage;
2487
2488                         try
2489                         {
2490                                 Unique<typename Object::Type>   obj     (Object::create(objEnv, res, params));
2491                                 createOk = true;
2492                         }
2493                         catch (const vk::OutOfMemoryError& e)
2494                         {
2495                                 if (e.getError() != VK_ERROR_OUT_OF_HOST_MEMORY)
2496                                 {
2497                                         context.getTestContext().getLog() << e;
2498                                         return tcu::TestStatus::fail("Got invalid error code");
2499                                 }
2500                         }
2501
2502                         if (!validateAndLog(context.getTestContext().getLog(), recorder, 0u))
2503                                 return tcu::TestStatus::fail("Invalid allocation callback");
2504
2505                         if (createOk)
2506                         {
2507                                 context.getTestContext().getLog()
2508                                         << TestLog::Message << "Object construction succeeded! " << TestLog::EndMessage;
2509                                 break;
2510                         }
2511                 }
2512         }
2513
2514         if (!validateAndLog(context.getTestContext().getLog(), resCallbacks, 0u))
2515                 return tcu::TestStatus::fail("Invalid allocation callback");
2516
2517         if (numPassingAllocs == 0)
2518                 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Allocation callbacks not called");
2519         else if (numPassingAllocs == maxTries)
2520         {
2521                 context.getTestContext().getLog()
2522                         << TestLog::Message << "WARNING: Maximum iteration count (" << maxTries << ") reached without object construction passing. "
2523                                                                 << "OOM testing incomplete, use --deqp-test-iteration-count= to test with higher limit." << TestLog::EndMessage;
2524                 return tcu::TestStatus(QP_TEST_RESULT_PASS, "Max iter count reached");
2525         }
2526         else
2527                 return tcu::TestStatus::pass("Ok");
2528 }
2529
2530 // Determine whether an API call sets the invalid handles to NULL (true) or leaves them undefined or not modified (false)
2531 template<typename T> inline bool isNullHandleOnAllocationFailure                                  (Context&)             { return false; }
2532 template<>                       inline bool isNullHandleOnAllocationFailure<VkCommandBuffer> (Context& context) { return hasDeviceExtension(context, "VK_KHR_maintenance1"); }
2533 template<>                       inline bool isNullHandleOnAllocationFailure<VkDescriptorSet> (Context& context) { return hasDeviceExtension(context, "VK_KHR_maintenance1"); }
2534 template<>                       inline bool isNullHandleOnAllocationFailure<VkPipeline>          (Context&)             { return true;  }
2535
2536 template<typename T> inline bool isPooledObject                                  (void) { return false; };
2537 template<>                       inline bool isPooledObject<VkCommandBuffer> (void) { return true;  };
2538 template<>                       inline bool isPooledObject<VkDescriptorSet> (void) { return true;  };
2539
2540 template<typename Object>
2541 tcu::TestStatus allocCallbackFailMultipleObjectsTest (Context& context, typename Object::Parameters params)
2542 {
2543         typedef SharedPtr<Move<typename Object::Type> > ObjectTypeSp;
2544
2545         static const deUint32   numObjects                      = 4;
2546         const bool                              expectNullHandles       = isNullHandleOnAllocationFailure<typename Object::Type>(context);
2547         deUint32                                numPassingAllocs        = 0;
2548
2549         {
2550                 vector<typename Object::Type>   handles (numObjects);
2551                 VkResult                                                result  = VK_NOT_READY;
2552
2553                 for (; numPassingAllocs <= numObjects; ++numPassingAllocs)
2554                 {
2555                         ValidateQueryBits::fillBits(handles.begin(), handles.end());    // fill with garbage
2556
2557                         // \note We have to use the same allocator for both resource dependencies and the object under test,
2558                         //       because pooled objects take memory from the pool.
2559                         DeterministicFailAllocator                      objAllocator(getSystemAllocator(), DeterministicFailAllocator::MODE_DO_NOT_COUNT, 0);
2560                         AllocationCallbackRecorder                      recorder        (objAllocator.getCallbacks(), 128);
2561                         const Environment                                       objEnv          (context.getPlatformInterface(),
2562                                                                                                                          context.getDeviceInterface(),
2563                                                                                                                          context.getDevice(),
2564                                                                                                                          context.getUniversalQueueFamilyIndex(),
2565                                                                                                                          context.getBinaryCollection(),
2566                                                                                                                          recorder.getCallbacks(),
2567                                                                                                                          numObjects);
2568
2569                         context.getTestContext().getLog()
2570                                 << TestLog::Message
2571                                 << "Trying to create " << numObjects << " objects with " << numPassingAllocs << " allocation" << (numPassingAllocs != 1 ? "s" : "") << " passing"
2572                                 << TestLog::EndMessage;
2573
2574                         {
2575                                 const typename Object::Resources res (objEnv, params);
2576
2577                                 objAllocator.reset(DeterministicFailAllocator::MODE_COUNT_AND_FAIL, numPassingAllocs);
2578                                 const vector<ObjectTypeSp> scopedHandles = Object::createMultiple(objEnv, res, params, &handles, &result);
2579                         }
2580
2581                         if (result == VK_SUCCESS)
2582                         {
2583                                 context.getTestContext().getLog() << TestLog::Message << "Construction of all objects succeeded! " << TestLog::EndMessage;
2584                                 break;
2585                         }
2586                         else
2587                         {
2588                                 if (expectNullHandles)
2589                                 {
2590                                         for (deUint32 nullNdx = numPassingAllocs; nullNdx < numObjects; ++nullNdx)
2591                                         {
2592                                                 if (handles[nullNdx] != DE_NULL)
2593                                                         return tcu::TestStatus::fail("Some object handles weren't set to NULL");
2594                                         }
2595                                 }
2596
2597                                 if (result != VK_ERROR_OUT_OF_HOST_MEMORY)
2598                                         return tcu::TestStatus::fail("Got invalid error code: " + de::toString(getResultName(result)));
2599
2600                                 if (!validateAndLog(context.getTestContext().getLog(), recorder, 0u))
2601                                         return tcu::TestStatus::fail("Invalid allocation callback");
2602                         }
2603                 }
2604         }
2605
2606         if (numPassingAllocs == 0)
2607         {
2608                 if (isPooledObject<typename Object::Type>())
2609                         return tcu::TestStatus::pass("Not validated: pooled objects didn't seem to use host memory");
2610                 else
2611                         return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Allocation callbacks not called");
2612         }
2613         else
2614                 return tcu::TestStatus::pass("Ok");
2615 }
2616
2617 // Utilities for creating groups
2618
2619 template<typename Object>
2620 struct NamedParameters
2621 {
2622         const char*                                             name;
2623         typename Object::Parameters             parameters;
2624 };
2625
2626 template<typename Object>
2627 struct CaseDescription
2628 {
2629         typename FunctionInstance1<typename Object::Parameters>::Function       function;
2630         const NamedParameters<Object>*                                                                          paramsBegin;
2631         const NamedParameters<Object>*                                                                          paramsEnd;
2632 };
2633
2634 #define EMPTY_CASE_DESC(OBJECT) \
2635         { (FunctionInstance1<OBJECT::Parameters>::Function)DE_NULL, DE_NULL, DE_NULL }
2636
2637 #define CASE_DESC(FUNCTION, CASES)      \
2638         { FUNCTION, DE_ARRAY_BEGIN(CASES), DE_ARRAY_END(CASES)  }
2639
2640 struct CaseDescriptions
2641 {
2642         CaseDescription<Instance>                               instance;
2643         CaseDescription<Device>                                 device;
2644         CaseDescription<DeviceMemory>                   deviceMemory;
2645         CaseDescription<Buffer>                                 buffer;
2646         CaseDescription<BufferView>                             bufferView;
2647         CaseDescription<Image>                                  image;
2648         CaseDescription<ImageView>                              imageView;
2649         CaseDescription<Semaphore>                              semaphore;
2650         CaseDescription<Event>                                  event;
2651         CaseDescription<Fence>                                  fence;
2652         CaseDescription<QueryPool>                              queryPool;
2653         CaseDescription<ShaderModule>                   shaderModule;
2654         CaseDescription<PipelineCache>                  pipelineCache;
2655         CaseDescription<PipelineLayout>                 pipelineLayout;
2656         CaseDescription<RenderPass>                             renderPass;
2657         CaseDescription<GraphicsPipeline>               graphicsPipeline;
2658         CaseDescription<ComputePipeline>                computePipeline;
2659         CaseDescription<DescriptorSetLayout>    descriptorSetLayout;
2660         CaseDescription<Sampler>                                sampler;
2661         CaseDescription<DescriptorPool>                 descriptorPool;
2662         CaseDescription<DescriptorSet>                  descriptorSet;
2663         CaseDescription<Framebuffer>                    framebuffer;
2664         CaseDescription<CommandPool>                    commandPool;
2665         CaseDescription<CommandBuffer>                  commandBuffer;
2666 };
2667
2668 template<typename Object>
2669 void addCases (const MovePtr<tcu::TestCaseGroup>& group, const CaseDescription<Object>& cases)
2670 {
2671         for (const NamedParameters<Object>* cur = cases.paramsBegin; cur != cases.paramsEnd; ++cur)
2672                 addFunctionCase(group.get(), cur->name, "", cases.function, cur->parameters);
2673 }
2674
2675 template<typename Object>
2676 void addCasesWithProgs (const MovePtr<tcu::TestCaseGroup>& group, const CaseDescription<Object>& cases)
2677 {
2678         for (const NamedParameters<Object>* cur = cases.paramsBegin; cur != cases.paramsEnd; ++cur)
2679                 addFunctionCaseWithPrograms(group.get(), cur->name, "", Object::initPrograms, cases.function, cur->parameters);
2680 }
2681
2682 tcu::TestCaseGroup* createGroup (tcu::TestContext& testCtx, const char* name, const char* desc, const CaseDescriptions& cases)
2683 {
2684         MovePtr<tcu::TestCaseGroup>     group   (new tcu::TestCaseGroup(testCtx, name, desc));
2685
2686         addCases                        (group, cases.instance);
2687         addCases                        (group, cases.device);
2688         addCases                        (group, cases.deviceMemory);
2689         addCases                        (group, cases.buffer);
2690         addCases                        (group, cases.bufferView);
2691         addCases                        (group, cases.image);
2692         addCases                        (group, cases.imageView);
2693         addCases                        (group, cases.semaphore);
2694         addCases                        (group, cases.event);
2695         addCases                        (group, cases.fence);
2696         addCases                        (group, cases.queryPool);
2697         addCases                        (group, cases.sampler);
2698         addCasesWithProgs       (group, cases.shaderModule);
2699         addCases                        (group, cases.pipelineCache);
2700         addCases                        (group, cases.pipelineLayout);
2701         addCases                        (group, cases.renderPass);
2702         addCasesWithProgs       (group, cases.graphicsPipeline);
2703         addCasesWithProgs       (group, cases.computePipeline);
2704         addCases                        (group, cases.descriptorSetLayout);
2705         addCases                        (group, cases.descriptorPool);
2706         addCases                        (group, cases.descriptorSet);
2707         addCases                        (group, cases.framebuffer);
2708         addCases                        (group, cases.commandPool);
2709         addCases                        (group, cases.commandBuffer);
2710
2711         return group.release();
2712 }
2713
2714 } // anonymous
2715
2716 tcu::TestCaseGroup* createObjectManagementTests (tcu::TestContext& testCtx)
2717 {
2718         MovePtr<tcu::TestCaseGroup>     objectMgmtTests (new tcu::TestCaseGroup(testCtx, "object_management", "Object management tests"));
2719
2720         const Image::Parameters         img1D                   (0u, VK_IMAGE_TYPE_1D, VK_FORMAT_R8G8B8A8_UNORM, makeExtent3D(256,   1, 1), 1u,  4u, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_UNDEFINED);
2721         const Image::Parameters         img2D                   (0u, VK_IMAGE_TYPE_2D, VK_FORMAT_R8G8B8A8_UNORM, makeExtent3D( 64,  64, 1), 1u, 12u, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_SAMPLED_BIT|VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_LAYOUT_UNDEFINED);
2722         const Image::Parameters         imgCube                 (VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT, VK_IMAGE_TYPE_2D, VK_FORMAT_R8G8B8A8_UNORM, makeExtent3D( 64,  64, 1), 1u, 12u, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_SAMPLED_BIT|VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_LAYOUT_UNDEFINED);
2723         const Image::Parameters         img3D                   (0u, VK_IMAGE_TYPE_3D, VK_FORMAT_R8G8B8A8_UNORM, makeExtent3D( 64,  64, 4), 1u,  1u, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_UNDEFINED);
2724         const ImageView::Parameters     imgView1D               (img1D, VK_IMAGE_VIEW_TYPE_1D,                  img1D.format, makeComponentMappingRGBA(), makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
2725         const ImageView::Parameters     imgView1DArr    (img1D, VK_IMAGE_VIEW_TYPE_1D_ARRAY,    img1D.format, makeComponentMappingRGBA(), makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 4u));
2726         const ImageView::Parameters     imgView2D               (img2D, VK_IMAGE_VIEW_TYPE_2D,                  img2D.format, makeComponentMappingRGBA(), makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
2727         const ImageView::Parameters     imgView2DArr    (img2D, VK_IMAGE_VIEW_TYPE_2D_ARRAY,    img2D.format, makeComponentMappingRGBA(), makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 8u));
2728         const ImageView::Parameters     imgViewCube             (imgCube, VK_IMAGE_VIEW_TYPE_CUBE,              img2D.format, makeComponentMappingRGBA(), makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 6u));
2729         const ImageView::Parameters     imgViewCubeArr  (imgCube, VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,        img2D.format, makeComponentMappingRGBA(), makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 12u));
2730         const ImageView::Parameters     imgView3D               (img3D, VK_IMAGE_VIEW_TYPE_3D,                  img3D.format, makeComponentMappingRGBA(), makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
2731
2732         const DescriptorSetLayout::Parameters   singleUboDescLayout     = DescriptorSetLayout::Parameters::single(0u, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u, VK_SHADER_STAGE_VERTEX_BIT);
2733
2734         static NamedParameters<Instance>                                s_instanceCases[]                       =
2735         {
2736                 { "instance",                                   Instance::Parameters() },
2737         };
2738         // \note Device index may change - must not be static
2739         const NamedParameters<Device>                                   s_deviceCases[]                         =
2740         {
2741                 { "device",                                             Device::Parameters(testCtx.getCommandLine().getVKDeviceId()-1u, VK_QUEUE_GRAPHICS_BIT)  },
2742         };
2743         static const NamedParameters<DeviceMemory>                      s_deviceMemCases[]                              =
2744         {
2745                 { "device_memory_small",                DeviceMemory::Parameters(1024, 0u)      },
2746         };
2747         static const NamedParameters<Buffer>                            s_bufferCases[]                                 =
2748         {
2749                 { "buffer_uniform_small",               Buffer::Parameters(1024u,                       VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT),    },
2750                 { "buffer_uniform_large",               Buffer::Parameters(1024u*1024u*16u,     VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT),    },
2751                 { "buffer_storage_small",               Buffer::Parameters(1024u,                       VK_BUFFER_USAGE_STORAGE_BUFFER_BIT),    },
2752                 { "buffer_storage_large",               Buffer::Parameters(1024u*1024u*16u,     VK_BUFFER_USAGE_STORAGE_BUFFER_BIT),    },
2753         };
2754         static const NamedParameters<BufferView>                        s_bufferViewCases[]                             =
2755         {
2756                 { "buffer_view_uniform_r8g8b8a8_unorm", BufferView::Parameters(Buffer::Parameters(8192u, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT), VK_FORMAT_R8G8B8A8_UNORM, 0u, 4096u)        },
2757                 { "buffer_view_storage_r8g8b8a8_unorm", BufferView::Parameters(Buffer::Parameters(8192u, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT), VK_FORMAT_R8G8B8A8_UNORM, 0u, 4096u)        },
2758         };
2759         static const NamedParameters<Image>                                     s_imageCases[]                                  =
2760         {
2761                 { "image_1d",                                   img1D           },
2762                 { "image_2d",                                   img2D           },
2763                 { "image_3d",                                   img3D           },
2764         };
2765         static const NamedParameters<ImageView>                         s_imageViewCases[]                              =
2766         {
2767                 { "image_view_1d",                              imgView1D               },
2768                 { "image_view_1d_arr",                  imgView1DArr    },
2769                 { "image_view_2d",                              imgView2D               },
2770                 { "image_view_2d_arr",                  imgView2DArr    },
2771                 { "image_view_cube",                    imgViewCube             },
2772                 { "image_view_cube_arr",                imgViewCubeArr  },
2773                 { "image_view_3d",                              imgView3D               },
2774         };
2775         static const NamedParameters<Semaphore>                         s_semaphoreCases[]                              =
2776         {
2777                 { "semaphore",                                  Semaphore::Parameters(0u),      }
2778         };
2779         static const NamedParameters<Event>                                     s_eventCases[]                                  =
2780         {
2781                 { "event",                                              Event::Parameters(0u)           }
2782         };
2783         static const NamedParameters<Fence>                                     s_fenceCases[]                                  =
2784         {
2785                 { "fence",                                              Fence::Parameters(0u)                                                           },
2786                 { "fence_signaled",                             Fence::Parameters(VK_FENCE_CREATE_SIGNALED_BIT)         }
2787         };
2788         static const NamedParameters<QueryPool>                         s_queryPoolCases[]                              =
2789         {
2790                 { "query_pool",                                 QueryPool::Parameters(VK_QUERY_TYPE_OCCLUSION, 1u, 0u)  }
2791         };
2792         static const NamedParameters<ShaderModule>                      s_shaderModuleCases[]                   =
2793         {
2794                 { "shader_module",                              ShaderModule::Parameters(VK_SHADER_STAGE_COMPUTE_BIT, "test")   }
2795         };
2796         static const NamedParameters<PipelineCache>                     s_pipelineCacheCases[]                  =
2797         {
2798                 { "pipeline_cache",                             PipelineCache::Parameters()             }
2799         };
2800         static const NamedParameters<PipelineLayout>            s_pipelineLayoutCases[]                 =
2801         {
2802                 { "pipeline_layout_empty",              PipelineLayout::Parameters::empty()                                                                             },
2803                 { "pipeline_layout_single",             PipelineLayout::Parameters::singleDescriptorSet(singleUboDescLayout)    }
2804         };
2805         static const NamedParameters<RenderPass>                        s_renderPassCases[]                             =
2806         {
2807                 { "render_pass",                                RenderPass::Parameters()                }
2808         };
2809         static const NamedParameters<GraphicsPipeline>          s_graphicsPipelineCases[]               =
2810         {
2811                 { "graphics_pipeline",                  GraphicsPipeline::Parameters()  }
2812         };
2813         static const NamedParameters<ComputePipeline>           s_computePipelineCases[]                =
2814         {
2815                 { "compute_pipeline",                   ComputePipeline::Parameters()   }
2816         };
2817         static const NamedParameters<DescriptorSetLayout>       s_descriptorSetLayoutCases[]    =
2818         {
2819                 { "descriptor_set_layout_empty",        DescriptorSetLayout::Parameters::empty()        },
2820                 { "descriptor_set_layout_single",       singleUboDescLayout                                                     }
2821         };
2822         static const NamedParameters<Sampler>                           s_samplerCases[]                                =
2823         {
2824                 { "sampler",                                    Sampler::Parameters()   }
2825         };
2826         static const NamedParameters<DescriptorPool>            s_descriptorPoolCases[]                 =
2827         {
2828                 { "descriptor_pool",                                            DescriptorPool::Parameters::singleType((VkDescriptorPoolCreateFlags)0,                                          4u, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3u)      },
2829                 { "descriptor_pool_free_descriptor_set",        DescriptorPool::Parameters::singleType(VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,       4u, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3u)      }
2830         };
2831         static const NamedParameters<DescriptorSet>                     s_descriptorSetCases[]                  =
2832         {
2833                 { "descriptor_set",                             DescriptorSet::Parameters(singleUboDescLayout)  }
2834         };
2835         static const NamedParameters<Framebuffer>                       s_framebufferCases[]                    =
2836         {
2837                 { "framebuffer",                                Framebuffer::Parameters()       }
2838         };
2839         static const NamedParameters<CommandPool>                       s_commandPoolCases[]                    =
2840         {
2841                 { "command_pool",                               CommandPool::Parameters((VkCommandPoolCreateFlags)0)                    },
2842                 { "command_pool_transient",             CommandPool::Parameters(VK_COMMAND_POOL_CREATE_TRANSIENT_BIT)   }
2843         };
2844         static const NamedParameters<CommandBuffer>                     s_commandBufferCases[]                  =
2845         {
2846                 { "command_buffer_primary",             CommandBuffer::Parameters(CommandPool::Parameters((VkCommandPoolCreateFlags)0u), VK_COMMAND_BUFFER_LEVEL_PRIMARY)       },
2847                 { "command_buffer_secondary",   CommandBuffer::Parameters(CommandPool::Parameters((VkCommandPoolCreateFlags)0u), VK_COMMAND_BUFFER_LEVEL_SECONDARY)     }
2848         };
2849
2850         static const CaseDescriptions   s_createSingleGroup     =
2851         {
2852                 CASE_DESC(createSingleTest      <Instance>,                                     s_instanceCases),
2853                 CASE_DESC(createSingleTest      <Device>,                                       s_deviceCases),
2854                 CASE_DESC(createSingleTest      <DeviceMemory>,                         s_deviceMemCases),
2855                 CASE_DESC(createSingleTest      <Buffer>,                                       s_bufferCases),
2856                 CASE_DESC(createSingleTest      <BufferView>,                           s_bufferViewCases),
2857                 CASE_DESC(createSingleTest      <Image>,                                        s_imageCases),
2858                 CASE_DESC(createSingleTest      <ImageView>,                            s_imageViewCases),
2859                 CASE_DESC(createSingleTest      <Semaphore>,                            s_semaphoreCases),
2860                 CASE_DESC(createSingleTest      <Event>,                                        s_eventCases),
2861                 CASE_DESC(createSingleTest      <Fence>,                                        s_fenceCases),
2862                 CASE_DESC(createSingleTest      <QueryPool>,                            s_queryPoolCases),
2863                 CASE_DESC(createSingleTest      <ShaderModule>,                         s_shaderModuleCases),
2864                 CASE_DESC(createSingleTest      <PipelineCache>,                        s_pipelineCacheCases),
2865                 CASE_DESC(createSingleTest      <PipelineLayout>,                       s_pipelineLayoutCases),
2866                 CASE_DESC(createSingleTest      <RenderPass>,                           s_renderPassCases),
2867                 CASE_DESC(createSingleTest      <GraphicsPipeline>,                     s_graphicsPipelineCases),
2868                 CASE_DESC(createSingleTest      <ComputePipeline>,                      s_computePipelineCases),
2869                 CASE_DESC(createSingleTest      <DescriptorSetLayout>,          s_descriptorSetLayoutCases),
2870                 CASE_DESC(createSingleTest      <Sampler>,                                      s_samplerCases),
2871                 CASE_DESC(createSingleTest      <DescriptorPool>,                       s_descriptorPoolCases),
2872                 CASE_DESC(createSingleTest      <DescriptorSet>,                        s_descriptorSetCases),
2873                 CASE_DESC(createSingleTest      <Framebuffer>,                          s_framebufferCases),
2874                 CASE_DESC(createSingleTest      <CommandPool>,                          s_commandPoolCases),
2875                 CASE_DESC(createSingleTest      <CommandBuffer>,                        s_commandBufferCases),
2876         };
2877         objectMgmtTests->addChild(createGroup(testCtx, "single", "Create single object", s_createSingleGroup));
2878
2879         static const CaseDescriptions   s_createMultipleUniqueResourcesGroup    =
2880         {
2881                 CASE_DESC(createMultipleUniqueResourcesTest     <Instance>,                                     s_instanceCases),
2882                 CASE_DESC(createMultipleUniqueResourcesTest     <Device>,                                       s_deviceCases),
2883                 CASE_DESC(createMultipleUniqueResourcesTest     <DeviceMemory>,                         s_deviceMemCases),
2884                 CASE_DESC(createMultipleUniqueResourcesTest     <Buffer>,                                       s_bufferCases),
2885                 CASE_DESC(createMultipleUniqueResourcesTest     <BufferView>,                           s_bufferViewCases),
2886                 CASE_DESC(createMultipleUniqueResourcesTest     <Image>,                                        s_imageCases),
2887                 CASE_DESC(createMultipleUniqueResourcesTest     <ImageView>,                            s_imageViewCases),
2888                 CASE_DESC(createMultipleUniqueResourcesTest     <Semaphore>,                            s_semaphoreCases),
2889                 CASE_DESC(createMultipleUniqueResourcesTest     <Event>,                                        s_eventCases),
2890                 CASE_DESC(createMultipleUniqueResourcesTest     <Fence>,                                        s_fenceCases),
2891                 CASE_DESC(createMultipleUniqueResourcesTest     <QueryPool>,                            s_queryPoolCases),
2892                 CASE_DESC(createMultipleUniqueResourcesTest     <ShaderModule>,                         s_shaderModuleCases),
2893                 CASE_DESC(createMultipleUniqueResourcesTest     <PipelineCache>,                        s_pipelineCacheCases),
2894                 CASE_DESC(createMultipleUniqueResourcesTest     <PipelineLayout>,                       s_pipelineLayoutCases),
2895                 CASE_DESC(createMultipleUniqueResourcesTest     <RenderPass>,                           s_renderPassCases),
2896                 CASE_DESC(createMultipleUniqueResourcesTest     <GraphicsPipeline>,                     s_graphicsPipelineCases),
2897                 CASE_DESC(createMultipleUniqueResourcesTest     <ComputePipeline>,                      s_computePipelineCases),
2898                 CASE_DESC(createMultipleUniqueResourcesTest     <DescriptorSetLayout>,          s_descriptorSetLayoutCases),
2899                 CASE_DESC(createMultipleUniqueResourcesTest     <Sampler>,                                      s_samplerCases),
2900                 CASE_DESC(createMultipleUniqueResourcesTest     <DescriptorPool>,                       s_descriptorPoolCases),
2901                 CASE_DESC(createMultipleUniqueResourcesTest     <DescriptorSet>,                        s_descriptorSetCases),
2902                 CASE_DESC(createMultipleUniqueResourcesTest     <Framebuffer>,                          s_framebufferCases),
2903                 CASE_DESC(createMultipleUniqueResourcesTest     <CommandPool>,                          s_commandPoolCases),
2904                 CASE_DESC(createMultipleUniqueResourcesTest     <CommandBuffer>,                        s_commandBufferCases),
2905         };
2906         objectMgmtTests->addChild(createGroup(testCtx, "multiple_unique_resources", "Multiple objects with per-object unique resources", s_createMultipleUniqueResourcesGroup));
2907
2908         static const CaseDescriptions   s_createMultipleSharedResourcesGroup    =
2909         {
2910                 EMPTY_CASE_DESC(Instance), // No resources used
2911                 CASE_DESC(createMultipleSharedResourcesTest     <Device>,                                       s_deviceCases),
2912                 CASE_DESC(createMultipleSharedResourcesTest     <DeviceMemory>,                         s_deviceMemCases),
2913                 CASE_DESC(createMultipleSharedResourcesTest     <Buffer>,                                       s_bufferCases),
2914                 CASE_DESC(createMultipleSharedResourcesTest     <BufferView>,                           s_bufferViewCases),
2915                 CASE_DESC(createMultipleSharedResourcesTest     <Image>,                                        s_imageCases),
2916                 CASE_DESC(createMultipleSharedResourcesTest     <ImageView>,                            s_imageViewCases),
2917                 CASE_DESC(createMultipleSharedResourcesTest     <Semaphore>,                            s_semaphoreCases),
2918                 CASE_DESC(createMultipleSharedResourcesTest     <Event>,                                        s_eventCases),
2919                 CASE_DESC(createMultipleSharedResourcesTest     <Fence>,                                        s_fenceCases),
2920                 CASE_DESC(createMultipleSharedResourcesTest     <QueryPool>,                            s_queryPoolCases),
2921                 CASE_DESC(createMultipleSharedResourcesTest     <ShaderModule>,                         s_shaderModuleCases),
2922                 CASE_DESC(createMultipleSharedResourcesTest     <PipelineCache>,                        s_pipelineCacheCases),
2923                 CASE_DESC(createMultipleSharedResourcesTest     <PipelineLayout>,                       s_pipelineLayoutCases),
2924                 CASE_DESC(createMultipleSharedResourcesTest     <RenderPass>,                           s_renderPassCases),
2925                 CASE_DESC(createMultipleSharedResourcesTest     <GraphicsPipeline>,                     s_graphicsPipelineCases),
2926                 CASE_DESC(createMultipleSharedResourcesTest     <ComputePipeline>,                      s_computePipelineCases),
2927                 CASE_DESC(createMultipleSharedResourcesTest     <DescriptorSetLayout>,          s_descriptorSetLayoutCases),
2928                 CASE_DESC(createMultipleSharedResourcesTest     <Sampler>,                                      s_samplerCases),
2929                 CASE_DESC(createMultipleSharedResourcesTest     <DescriptorPool>,                       s_descriptorPoolCases),
2930                 CASE_DESC(createMultipleSharedResourcesTest     <DescriptorSet>,                        s_descriptorSetCases),
2931                 CASE_DESC(createMultipleSharedResourcesTest     <Framebuffer>,                          s_framebufferCases),
2932                 CASE_DESC(createMultipleSharedResourcesTest     <CommandPool>,                          s_commandPoolCases),
2933                 CASE_DESC(createMultipleSharedResourcesTest     <CommandBuffer>,                        s_commandBufferCases),
2934         };
2935         objectMgmtTests->addChild(createGroup(testCtx, "multiple_shared_resources", "Multiple objects with shared resources", s_createMultipleSharedResourcesGroup));
2936
2937         static const CaseDescriptions   s_createMaxConcurrentGroup      =
2938         {
2939                 CASE_DESC(createMaxConcurrentTest       <Instance>,                                     s_instanceCases),
2940                 CASE_DESC(createMaxConcurrentTest       <Device>,                                       s_deviceCases),
2941                 CASE_DESC(createMaxConcurrentTest       <DeviceMemory>,                         s_deviceMemCases),
2942                 CASE_DESC(createMaxConcurrentTest       <Buffer>,                                       s_bufferCases),
2943                 CASE_DESC(createMaxConcurrentTest       <BufferView>,                           s_bufferViewCases),
2944                 CASE_DESC(createMaxConcurrentTest       <Image>,                                        s_imageCases),
2945                 CASE_DESC(createMaxConcurrentTest       <ImageView>,                            s_imageViewCases),
2946                 CASE_DESC(createMaxConcurrentTest       <Semaphore>,                            s_semaphoreCases),
2947                 CASE_DESC(createMaxConcurrentTest       <Event>,                                        s_eventCases),
2948                 CASE_DESC(createMaxConcurrentTest       <Fence>,                                        s_fenceCases),
2949                 CASE_DESC(createMaxConcurrentTest       <QueryPool>,                            s_queryPoolCases),
2950                 CASE_DESC(createMaxConcurrentTest       <ShaderModule>,                         s_shaderModuleCases),
2951                 CASE_DESC(createMaxConcurrentTest       <PipelineCache>,                        s_pipelineCacheCases),
2952                 CASE_DESC(createMaxConcurrentTest       <PipelineLayout>,                       s_pipelineLayoutCases),
2953                 CASE_DESC(createMaxConcurrentTest       <RenderPass>,                           s_renderPassCases),
2954                 CASE_DESC(createMaxConcurrentTest       <GraphicsPipeline>,                     s_graphicsPipelineCases),
2955                 CASE_DESC(createMaxConcurrentTest       <ComputePipeline>,                      s_computePipelineCases),
2956                 CASE_DESC(createMaxConcurrentTest       <DescriptorSetLayout>,          s_descriptorSetLayoutCases),
2957                 CASE_DESC(createMaxConcurrentTest       <Sampler>,                                      s_samplerCases),
2958                 CASE_DESC(createMaxConcurrentTest       <DescriptorPool>,                       s_descriptorPoolCases),
2959                 CASE_DESC(createMaxConcurrentTest       <DescriptorSet>,                        s_descriptorSetCases),
2960                 CASE_DESC(createMaxConcurrentTest       <Framebuffer>,                          s_framebufferCases),
2961                 CASE_DESC(createMaxConcurrentTest       <CommandPool>,                          s_commandPoolCases),
2962                 CASE_DESC(createMaxConcurrentTest       <CommandBuffer>,                        s_commandBufferCases),
2963         };
2964         objectMgmtTests->addChild(createGroup(testCtx, "max_concurrent", "Maximum number of concurrently live objects", s_createMaxConcurrentGroup));
2965
2966         static const CaseDescriptions   s_multithreadedCreatePerThreadDeviceGroup       =
2967         {
2968                 EMPTY_CASE_DESC(Instance),      // Does not make sense
2969                 EMPTY_CASE_DESC(Device),        // Does not make sense
2970                 CASE_DESC(multithreadedCreatePerThreadDeviceTest        <DeviceMemory>,                         s_deviceMemCases),
2971                 CASE_DESC(multithreadedCreatePerThreadDeviceTest        <Buffer>,                                       s_bufferCases),
2972                 CASE_DESC(multithreadedCreatePerThreadDeviceTest        <BufferView>,                           s_bufferViewCases),
2973                 CASE_DESC(multithreadedCreatePerThreadDeviceTest        <Image>,                                        s_imageCases),
2974                 CASE_DESC(multithreadedCreatePerThreadDeviceTest        <ImageView>,                            s_imageViewCases),
2975                 CASE_DESC(multithreadedCreatePerThreadDeviceTest        <Semaphore>,                            s_semaphoreCases),
2976                 CASE_DESC(multithreadedCreatePerThreadDeviceTest        <Event>,                                        s_eventCases),
2977                 CASE_DESC(multithreadedCreatePerThreadDeviceTest        <Fence>,                                        s_fenceCases),
2978                 CASE_DESC(multithreadedCreatePerThreadDeviceTest        <QueryPool>,                            s_queryPoolCases),
2979                 CASE_DESC(multithreadedCreatePerThreadDeviceTest        <ShaderModule>,                         s_shaderModuleCases),
2980                 CASE_DESC(multithreadedCreatePerThreadDeviceTest        <PipelineCache>,                        s_pipelineCacheCases),
2981                 CASE_DESC(multithreadedCreatePerThreadDeviceTest        <PipelineLayout>,                       s_pipelineLayoutCases),
2982                 CASE_DESC(multithreadedCreatePerThreadDeviceTest        <RenderPass>,                           s_renderPassCases),
2983                 CASE_DESC(multithreadedCreatePerThreadDeviceTest        <GraphicsPipeline>,                     s_graphicsPipelineCases),
2984                 CASE_DESC(multithreadedCreatePerThreadDeviceTest        <ComputePipeline>,                      s_computePipelineCases),
2985                 CASE_DESC(multithreadedCreatePerThreadDeviceTest        <DescriptorSetLayout>,          s_descriptorSetLayoutCases),
2986                 CASE_DESC(multithreadedCreatePerThreadDeviceTest        <Sampler>,                                      s_samplerCases),
2987                 CASE_DESC(multithreadedCreatePerThreadDeviceTest        <DescriptorPool>,                       s_descriptorPoolCases),
2988                 CASE_DESC(multithreadedCreatePerThreadDeviceTest        <DescriptorSet>,                        s_descriptorSetCases),
2989                 CASE_DESC(multithreadedCreatePerThreadDeviceTest        <Framebuffer>,                          s_framebufferCases),
2990                 CASE_DESC(multithreadedCreatePerThreadDeviceTest        <CommandPool>,                          s_commandPoolCases),
2991                 CASE_DESC(multithreadedCreatePerThreadDeviceTest        <CommandBuffer>,                        s_commandBufferCases),
2992         };
2993         objectMgmtTests->addChild(createGroup(testCtx, "multithreaded_per_thread_device", "Multithreaded object construction with per-thread device ", s_multithreadedCreatePerThreadDeviceGroup));
2994
2995         static const CaseDescriptions   s_multithreadedCreatePerThreadResourcesGroup    =
2996         {
2997                 CASE_DESC(multithreadedCreatePerThreadResourcesTest     <Instance>,                                     s_instanceCases),
2998                 CASE_DESC(multithreadedCreatePerThreadResourcesTest     <Device>,                                       s_deviceCases),
2999                 CASE_DESC(multithreadedCreatePerThreadResourcesTest     <DeviceMemory>,                         s_deviceMemCases),
3000                 CASE_DESC(multithreadedCreatePerThreadResourcesTest     <Buffer>,                                       s_bufferCases),
3001                 CASE_DESC(multithreadedCreatePerThreadResourcesTest     <BufferView>,                           s_bufferViewCases),
3002                 CASE_DESC(multithreadedCreatePerThreadResourcesTest     <Image>,                                        s_imageCases),
3003                 CASE_DESC(multithreadedCreatePerThreadResourcesTest     <ImageView>,                            s_imageViewCases),
3004                 CASE_DESC(multithreadedCreatePerThreadResourcesTest     <Semaphore>,                            s_semaphoreCases),
3005                 CASE_DESC(multithreadedCreatePerThreadResourcesTest     <Event>,                                        s_eventCases),
3006                 CASE_DESC(multithreadedCreatePerThreadResourcesTest     <Fence>,                                        s_fenceCases),
3007                 CASE_DESC(multithreadedCreatePerThreadResourcesTest     <QueryPool>,                            s_queryPoolCases),
3008                 CASE_DESC(multithreadedCreatePerThreadResourcesTest     <ShaderModule>,                         s_shaderModuleCases),
3009                 CASE_DESC(multithreadedCreatePerThreadResourcesTest     <PipelineCache>,                        s_pipelineCacheCases),
3010                 CASE_DESC(multithreadedCreatePerThreadResourcesTest     <PipelineLayout>,                       s_pipelineLayoutCases),
3011                 CASE_DESC(multithreadedCreatePerThreadResourcesTest     <RenderPass>,                           s_renderPassCases),
3012                 CASE_DESC(multithreadedCreatePerThreadResourcesTest     <GraphicsPipeline>,                     s_graphicsPipelineCases),
3013                 CASE_DESC(multithreadedCreatePerThreadResourcesTest     <ComputePipeline>,                      s_computePipelineCases),
3014                 CASE_DESC(multithreadedCreatePerThreadResourcesTest     <DescriptorSetLayout>,          s_descriptorSetLayoutCases),
3015                 CASE_DESC(multithreadedCreatePerThreadResourcesTest     <Sampler>,                                      s_samplerCases),
3016                 CASE_DESC(multithreadedCreatePerThreadResourcesTest     <DescriptorPool>,                       s_descriptorPoolCases),
3017                 CASE_DESC(multithreadedCreatePerThreadResourcesTest     <DescriptorSet>,                        s_descriptorSetCases),
3018                 CASE_DESC(multithreadedCreatePerThreadResourcesTest     <Framebuffer>,                          s_framebufferCases),
3019                 CASE_DESC(multithreadedCreatePerThreadResourcesTest     <CommandPool>,                          s_commandPoolCases),
3020                 CASE_DESC(multithreadedCreatePerThreadResourcesTest     <CommandBuffer>,                        s_commandBufferCases),
3021         };
3022         objectMgmtTests->addChild(createGroup(testCtx, "multithreaded_per_thread_resources", "Multithreaded object construction with per-thread resources", s_multithreadedCreatePerThreadResourcesGroup));
3023
3024         static const CaseDescriptions   s_multithreadedCreateSharedResourcesGroup       =
3025         {
3026                 EMPTY_CASE_DESC(Instance),
3027                 CASE_DESC(multithreadedCreateSharedResourcesTest        <Device>,                                       s_deviceCases),
3028                 CASE_DESC(multithreadedCreateSharedResourcesTest        <DeviceMemory>,                         s_deviceMemCases),
3029                 CASE_DESC(multithreadedCreateSharedResourcesTest        <Buffer>,                                       s_bufferCases),
3030                 CASE_DESC(multithreadedCreateSharedResourcesTest        <BufferView>,                           s_bufferViewCases),
3031                 CASE_DESC(multithreadedCreateSharedResourcesTest        <Image>,                                        s_imageCases),
3032                 CASE_DESC(multithreadedCreateSharedResourcesTest        <ImageView>,                            s_imageViewCases),
3033                 CASE_DESC(multithreadedCreateSharedResourcesTest        <Semaphore>,                            s_semaphoreCases),
3034                 CASE_DESC(multithreadedCreateSharedResourcesTest        <Event>,                                        s_eventCases),
3035                 CASE_DESC(multithreadedCreateSharedResourcesTest        <Fence>,                                        s_fenceCases),
3036                 CASE_DESC(multithreadedCreateSharedResourcesTest        <QueryPool>,                            s_queryPoolCases),
3037                 CASE_DESC(multithreadedCreateSharedResourcesTest        <ShaderModule>,                         s_shaderModuleCases),
3038                 CASE_DESC(multithreadedCreateSharedResourcesTest        <PipelineCache>,                        s_pipelineCacheCases),
3039                 CASE_DESC(multithreadedCreateSharedResourcesTest        <PipelineLayout>,                       s_pipelineLayoutCases),
3040                 CASE_DESC(multithreadedCreateSharedResourcesTest        <RenderPass>,                           s_renderPassCases),
3041                 CASE_DESC(multithreadedCreateSharedResourcesTest        <GraphicsPipeline>,                     s_graphicsPipelineCases),
3042                 CASE_DESC(multithreadedCreateSharedResourcesTest        <ComputePipeline>,                      s_computePipelineCases),
3043                 CASE_DESC(multithreadedCreateSharedResourcesTest        <DescriptorSetLayout>,          s_descriptorSetLayoutCases),
3044                 CASE_DESC(multithreadedCreateSharedResourcesTest        <Sampler>,                                      s_samplerCases),
3045                 CASE_DESC(multithreadedCreateSharedResourcesTest        <DescriptorPool>,                       s_descriptorPoolCases),
3046                 EMPTY_CASE_DESC(DescriptorSet),         // \note Needs per-thread DescriptorPool
3047                 CASE_DESC(multithreadedCreateSharedResourcesTest        <Framebuffer>,                          s_framebufferCases),
3048                 CASE_DESC(multithreadedCreateSharedResourcesTest        <CommandPool>,                          s_commandPoolCases),
3049                 EMPTY_CASE_DESC(CommandBuffer),                 // \note Needs per-thread CommandPool
3050         };
3051         objectMgmtTests->addChild(createGroup(testCtx, "multithreaded_shared_resources", "Multithreaded object construction with shared resources", s_multithreadedCreateSharedResourcesGroup));
3052
3053         static const CaseDescriptions   s_createSingleAllocCallbacksGroup       =
3054         {
3055                 CASE_DESC(createSingleAllocCallbacksTest        <Instance>,                                     s_instanceCases),
3056                 CASE_DESC(createSingleAllocCallbacksTest        <Device>,                                       s_deviceCases),
3057                 CASE_DESC(createSingleAllocCallbacksTest        <DeviceMemory>,                         s_deviceMemCases),
3058                 CASE_DESC(createSingleAllocCallbacksTest        <Buffer>,                                       s_bufferCases),
3059                 CASE_DESC(createSingleAllocCallbacksTest        <BufferView>,                           s_bufferViewCases),
3060                 CASE_DESC(createSingleAllocCallbacksTest        <Image>,                                        s_imageCases),
3061                 CASE_DESC(createSingleAllocCallbacksTest        <ImageView>,                            s_imageViewCases),
3062                 CASE_DESC(createSingleAllocCallbacksTest        <Semaphore>,                            s_semaphoreCases),
3063                 CASE_DESC(createSingleAllocCallbacksTest        <Event>,                                        s_eventCases),
3064                 CASE_DESC(createSingleAllocCallbacksTest        <Fence>,                                        s_fenceCases),
3065                 CASE_DESC(createSingleAllocCallbacksTest        <QueryPool>,                            s_queryPoolCases),
3066                 CASE_DESC(createSingleAllocCallbacksTest        <ShaderModule>,                         s_shaderModuleCases),
3067                 CASE_DESC(createSingleAllocCallbacksTest        <PipelineCache>,                        s_pipelineCacheCases),
3068                 CASE_DESC(createSingleAllocCallbacksTest        <PipelineLayout>,                       s_pipelineLayoutCases),
3069                 CASE_DESC(createSingleAllocCallbacksTest        <RenderPass>,                           s_renderPassCases),
3070                 CASE_DESC(createSingleAllocCallbacksTest        <GraphicsPipeline>,                     s_graphicsPipelineCases),
3071                 CASE_DESC(createSingleAllocCallbacksTest        <ComputePipeline>,                      s_computePipelineCases),
3072                 CASE_DESC(createSingleAllocCallbacksTest        <DescriptorSetLayout>,          s_descriptorSetLayoutCases),
3073                 CASE_DESC(createSingleAllocCallbacksTest        <Sampler>,                                      s_samplerCases),
3074                 CASE_DESC(createSingleAllocCallbacksTest        <DescriptorPool>,                       s_descriptorPoolCases),
3075                 CASE_DESC(createSingleAllocCallbacksTest        <DescriptorSet>,                        s_descriptorSetCases),
3076                 CASE_DESC(createSingleAllocCallbacksTest        <Framebuffer>,                          s_framebufferCases),
3077                 CASE_DESC(createSingleAllocCallbacksTest        <CommandPool>,                          s_commandPoolCases),
3078                 CASE_DESC(createSingleAllocCallbacksTest        <CommandBuffer>,                        s_commandBufferCases),
3079         };
3080         objectMgmtTests->addChild(createGroup(testCtx, "single_alloc_callbacks", "Create single object", s_createSingleAllocCallbacksGroup));
3081
3082         // \note Skip pooled objects in this test group. They are properly handled by the "multiple" group farther down below.
3083         static const CaseDescriptions   s_allocCallbackFailGroup        =
3084         {
3085                 CASE_DESC(allocCallbackFailTest <Instance>,                                     s_instanceCases),
3086                 CASE_DESC(allocCallbackFailTest <Device>,                                       s_deviceCases),
3087                 CASE_DESC(allocCallbackFailTest <DeviceMemory>,                         s_deviceMemCases),
3088                 CASE_DESC(allocCallbackFailTest <Buffer>,                                       s_bufferCases),
3089                 CASE_DESC(allocCallbackFailTest <BufferView>,                           s_bufferViewCases),
3090                 CASE_DESC(allocCallbackFailTest <Image>,                                        s_imageCases),
3091                 CASE_DESC(allocCallbackFailTest <ImageView>,                            s_imageViewCases),
3092                 CASE_DESC(allocCallbackFailTest <Semaphore>,                            s_semaphoreCases),
3093                 CASE_DESC(allocCallbackFailTest <Event>,                                        s_eventCases),
3094                 CASE_DESC(allocCallbackFailTest <Fence>,                                        s_fenceCases),
3095                 CASE_DESC(allocCallbackFailTest <QueryPool>,                            s_queryPoolCases),
3096                 CASE_DESC(allocCallbackFailTest <ShaderModule>,                         s_shaderModuleCases),
3097                 CASE_DESC(allocCallbackFailTest <PipelineCache>,                        s_pipelineCacheCases),
3098                 CASE_DESC(allocCallbackFailTest <PipelineLayout>,                       s_pipelineLayoutCases),
3099                 CASE_DESC(allocCallbackFailTest <RenderPass>,                           s_renderPassCases),
3100                 CASE_DESC(allocCallbackFailTest <GraphicsPipeline>,                     s_graphicsPipelineCases),
3101                 CASE_DESC(allocCallbackFailTest <ComputePipeline>,                      s_computePipelineCases),
3102                 CASE_DESC(allocCallbackFailTest <DescriptorSetLayout>,          s_descriptorSetLayoutCases),
3103                 CASE_DESC(allocCallbackFailTest <Sampler>,                                      s_samplerCases),
3104                 CASE_DESC(allocCallbackFailTest <DescriptorPool>,                       s_descriptorPoolCases),
3105                 EMPTY_CASE_DESC(DescriptorSet),
3106                 CASE_DESC(allocCallbackFailTest <Framebuffer>,                          s_framebufferCases),
3107                 CASE_DESC(allocCallbackFailTest <CommandPool>,                          s_commandPoolCases),
3108                 EMPTY_CASE_DESC(CommandBuffer),
3109         };
3110         objectMgmtTests->addChild(createGroup(testCtx, "alloc_callback_fail", "Allocation callback failure", s_allocCallbackFailGroup));
3111
3112         // \note Test objects that can be created in bulk
3113         static const CaseDescriptions   s_allocCallbackFailMultipleObjectsGroup =
3114         {
3115                 EMPTY_CASE_DESC(Instance),                      // most objects can be created one at a time only
3116                 EMPTY_CASE_DESC(Device),
3117                 EMPTY_CASE_DESC(DeviceMemory),
3118                 EMPTY_CASE_DESC(Buffer),
3119                 EMPTY_CASE_DESC(BufferView),
3120                 EMPTY_CASE_DESC(Image),
3121                 EMPTY_CASE_DESC(ImageView),
3122                 EMPTY_CASE_DESC(Semaphore),
3123                 EMPTY_CASE_DESC(Event),
3124                 EMPTY_CASE_DESC(Fence),
3125                 EMPTY_CASE_DESC(QueryPool),
3126                 EMPTY_CASE_DESC(ShaderModule),
3127                 EMPTY_CASE_DESC(PipelineCache),
3128                 EMPTY_CASE_DESC(PipelineLayout),
3129                 EMPTY_CASE_DESC(RenderPass),
3130                 CASE_DESC(allocCallbackFailMultipleObjectsTest <GraphicsPipeline>,              s_graphicsPipelineCases),
3131                 CASE_DESC(allocCallbackFailMultipleObjectsTest <ComputePipeline>,               s_computePipelineCases),
3132                 EMPTY_CASE_DESC(DescriptorSetLayout),
3133                 EMPTY_CASE_DESC(Sampler),
3134                 EMPTY_CASE_DESC(DescriptorPool),
3135                 CASE_DESC(allocCallbackFailMultipleObjectsTest <DescriptorSet>,                 s_descriptorSetCases),
3136                 EMPTY_CASE_DESC(Framebuffer),
3137                 EMPTY_CASE_DESC(CommandPool),
3138                 CASE_DESC(allocCallbackFailMultipleObjectsTest <CommandBuffer>,                 s_commandBufferCases),
3139         };
3140         objectMgmtTests->addChild(createGroup(testCtx, "alloc_callback_fail_multiple", "Allocation callback failure creating multiple objects with one call", s_allocCallbackFailMultipleObjectsGroup));
3141
3142         return objectMgmtTests.release();
3143 }
3144
3145 } // api
3146 } // vkt