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