1/*
2 * Copyright (c) 2015-2016 The Khronos Group Inc.
3 * Copyright (c) 2015-2016 Valve Corporation
4 * Copyright (c) 2015-2016 LunarG, Inc.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 *     http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
19 * Author: Cody Northrop <cody@lunarg.com>
20 * Author: John Zulauf <jzulauf@lunarg.com>
21 */
22
23#ifndef VKTESTBINDING_H
24#define VKTESTBINDING_H
25
26#include <algorithm>
27#include <assert.h>
28#include <iterator>
29#include <vector>
30
31#include "vulkan/vulkan.h"
32
33namespace vk_testing {
34
35template <class Dst, class Src>
36std::vector<Dst> MakeVkHandles(const std::vector<Src> &v) {
37    std::vector<Dst> handles;
38    handles.reserve(v.size());
39    std::transform(v.begin(), v.end(), std::back_inserter(handles), [](const Src &o) { return o.handle(); });
40    return handles;
41}
42
43template <class Dst, class Src>
44std::vector<Dst> MakeVkHandles(const std::vector<Src *> &v) {
45    std::vector<Dst> handles;
46    handles.reserve(v.size());
47    std::transform(v.begin(), v.end(), std::back_inserter(handles), [](const Src *o) { return o->handle(); });
48    return handles;
49}
50
51typedef void (*ErrorCallback)(const char *expr, const char *file, unsigned int line, const char *function);
52void set_error_callback(ErrorCallback callback);
53
54class PhysicalDevice;
55class Device;
56class Queue;
57class DeviceMemory;
58class Fence;
59class Semaphore;
60class Event;
61class QueryPool;
62class Buffer;
63class BufferView;
64class Image;
65class ImageView;
66class DepthStencilView;
67class Shader;
68class Pipeline;
69class PipelineDelta;
70class Sampler;
71class DescriptorSetLayout;
72class PipelineLayout;
73class DescriptorSetPool;
74class DescriptorSet;
75class CommandBuffer;
76class CommandPool;
77
78std::vector<VkLayerProperties> GetGlobalLayers();
79std::vector<VkExtensionProperties> GetGlobalExtensions();
80std::vector<VkExtensionProperties> GetGlobalExtensions(const char *pLayerName);
81
82namespace internal {
83
84template <typename T>
85class Handle {
86   public:
87    const T &handle() const { return handle_; }
88    bool initialized() const { return (handle_ != T{}); }
89
90   protected:
91    typedef T handle_type;
92
93    explicit Handle() : handle_{} {}
94    explicit Handle(T handle) : handle_(handle) {}
95
96    // handles are non-copyable
97    Handle(const Handle &) = delete;
98    Handle &operator=(const Handle &) = delete;
99
100    // handles can be moved out
101    Handle(Handle &&src) NOEXCEPT : handle_{src.handle_} { src.handle_ = {}; }
102    Handle &operator=(Handle &&src) NOEXCEPT {
103        handle_ = src.handle_;
104        src.handle_ = {};
105        return *this;
106    }
107
108    void init(T handle) {
109        assert(!initialized());
110        handle_ = handle;
111    }
112
113   private:
114    T handle_;
115};
116
117template <typename T>
118class NonDispHandle : public Handle<T> {
119   protected:
120    explicit NonDispHandle() : Handle<T>(), dev_handle_(VK_NULL_HANDLE) {}
121    explicit NonDispHandle(VkDevice dev, T handle) : Handle<T>(handle), dev_handle_(dev) {}
122
123    NonDispHandle(NonDispHandle &&src) : Handle<T>(std::move(src)) {
124        dev_handle_ = src.dev_handle_;
125        src.dev_handle_ = VK_NULL_HANDLE;
126    }
127    NonDispHandle &operator=(NonDispHandle &&src) {
128        Handle<T>::operator=(std::move(src));
129        dev_handle_ = src.dev_handle_;
130        src.dev_handle_ = VK_NULL_HANDLE;
131        return *this;
132    }
133
134    const VkDevice &device() const { return dev_handle_; }
135
136    void init(VkDevice dev, T handle) {
137        assert(!Handle<T>::initialized() && dev_handle_ == VK_NULL_HANDLE);
138        Handle<T>::init(handle);
139        dev_handle_ = dev;
140    }
141
142   private:
143    VkDevice dev_handle_;
144};
145
146}  // namespace internal
147
148class PhysicalDevice : public internal::Handle<VkPhysicalDevice> {
149   public:
150    explicit PhysicalDevice(VkPhysicalDevice phy) : Handle(phy) {
151        memory_properties_ = memory_properties();
152        device_properties_ = properties();
153    }
154
155    VkPhysicalDeviceProperties properties() const;
156    VkPhysicalDeviceMemoryProperties memory_properties() const;
157    std::vector<VkQueueFamilyProperties> queue_properties() const;
158    VkPhysicalDeviceFeatures features() const;
159
160    bool set_memory_type(const uint32_t type_bits, VkMemoryAllocateInfo *info, const VkMemoryPropertyFlags properties,
161                         const VkMemoryPropertyFlags forbid = 0) const;
162
163    // vkEnumerateDeviceExtensionProperties()
164    std::vector<VkExtensionProperties> extensions() const;
165    std::vector<VkExtensionProperties> extensions(const char *pLayerName) const;
166
167    // vkEnumerateLayers()
168    std::vector<VkLayerProperties> layers() const;
169
170   private:
171    void add_extension_dependencies(uint32_t dependency_count, VkExtensionProperties *depencency_props,
172                                    std::vector<VkExtensionProperties> &ext_list);
173
174    VkPhysicalDeviceMemoryProperties memory_properties_;
175
176    VkPhysicalDeviceProperties device_properties_;
177};
178
179class QueueCreateInfoArray {
180   private:
181    std::vector<VkDeviceQueueCreateInfo> queue_info_;
182    std::vector<std::vector<float>> queue_priorities_;
183
184   public:
185    QueueCreateInfoArray(const std::vector<VkQueueFamilyProperties> &queue_props);
186    size_t size() const { return queue_info_.size(); }
187    const VkDeviceQueueCreateInfo *data() const { return queue_info_.data(); }
188};
189
190class Device : public internal::Handle<VkDevice> {
191   public:
192    explicit Device(VkPhysicalDevice phy) : phy_(phy) {}
193    ~Device();
194
195    // vkCreateDevice()
196    void init(const VkDeviceCreateInfo &info);
197    void init(std::vector<const char *> &extensions,
198              VkPhysicalDeviceFeatures *features = nullptr);  // all queues, all extensions, etc
199    void init() {
200        std::vector<const char *> extensions;
201        init(extensions);
202    };
203
204    const PhysicalDevice &phy() const { return phy_; }
205
206    std::vector<const char *> GetEnabledExtensions() { return enabled_extensions_; }
207    bool IsEnbledExtension(const char *extension);
208
209    // vkGetDeviceProcAddr()
210    PFN_vkVoidFunction get_proc(const char *name) const { return vkGetDeviceProcAddr(handle(), name); }
211
212    // vkGetDeviceQueue()
213    const std::vector<Queue *> &graphics_queues() const { return queues_[GRAPHICS]; }
214    const std::vector<Queue *> &compute_queues() { return queues_[COMPUTE]; }
215    const std::vector<Queue *> &dma_queues() { return queues_[DMA]; }
216    uint32_t queue_family_without_capabilities(VkQueueFlags capabilities);
217    uint32_t graphics_queue_node_index_;
218
219    struct Format {
220        VkFormat format;
221        VkImageTiling tiling;
222        VkFlags features;
223    };
224    // vkGetFormatInfo()
225    VkFormatProperties format_properties(VkFormat format);
226    const std::vector<Format> &formats() const { return formats_; }
227
228    // vkDeviceWaitIdle()
229    void wait();
230
231    // vkWaitForFences()
232    VkResult wait(const std::vector<const Fence *> &fences, bool wait_all, uint64_t timeout);
233    VkResult wait(const Fence &fence) { return wait(std::vector<const Fence *>(1, &fence), true, (uint64_t)-1); }
234
235    // vkUpdateDescriptorSets()
236    void update_descriptor_sets(const std::vector<VkWriteDescriptorSet> &writes, const std::vector<VkCopyDescriptorSet> &copies);
237    void update_descriptor_sets(const std::vector<VkWriteDescriptorSet> &writes) {
238        return update_descriptor_sets(writes, std::vector<VkCopyDescriptorSet>());
239    }
240
241    static VkWriteDescriptorSet write_descriptor_set(const DescriptorSet &set, uint32_t binding, uint32_t array_element,
242                                                     VkDescriptorType type, uint32_t count,
243                                                     const VkDescriptorImageInfo *image_info);
244    static VkWriteDescriptorSet write_descriptor_set(const DescriptorSet &set, uint32_t binding, uint32_t array_element,
245                                                     VkDescriptorType type, uint32_t count,
246                                                     const VkDescriptorBufferInfo *buffer_info);
247    static VkWriteDescriptorSet write_descriptor_set(const DescriptorSet &set, uint32_t binding, uint32_t array_element,
248                                                     VkDescriptorType type, uint32_t count, const VkBufferView *buffer_views);
249    static VkWriteDescriptorSet write_descriptor_set(const DescriptorSet &set, uint32_t binding, uint32_t array_element,
250                                                     VkDescriptorType type, const std::vector<VkDescriptorImageInfo> &image_info);
251    static VkWriteDescriptorSet write_descriptor_set(const DescriptorSet &set, uint32_t binding, uint32_t array_element,
252                                                     VkDescriptorType type, const std::vector<VkDescriptorBufferInfo> &buffer_info);
253    static VkWriteDescriptorSet write_descriptor_set(const DescriptorSet &set, uint32_t binding, uint32_t array_element,
254                                                     VkDescriptorType type, const std::vector<VkBufferView> &buffer_views);
255
256    static VkCopyDescriptorSet copy_descriptor_set(const DescriptorSet &src_set, uint32_t src_binding, uint32_t src_array_element,
257                                                   const DescriptorSet &dst_set, uint32_t dst_binding, uint32_t dst_array_element,
258                                                   uint32_t count);
259
260   private:
261    enum QueueIndex {
262        GRAPHICS,
263        COMPUTE,
264        DMA,
265        QUEUE_COUNT,
266    };
267
268    void init_queues();
269    void init_formats();
270
271    PhysicalDevice phy_;
272
273    std::vector<const char *> enabled_extensions_;
274
275    std::vector<Queue *> queues_[QUEUE_COUNT];
276    std::vector<Format> formats_;
277};
278
279class Queue : public internal::Handle<VkQueue> {
280   public:
281    explicit Queue(VkQueue queue, int index) : Handle(queue) { family_index_ = index; }
282
283    // vkQueueSubmit()
284    void submit(const std::vector<const CommandBuffer *> &cmds, Fence &fence);
285    void submit(const CommandBuffer &cmd, Fence &fence);
286    void submit(const CommandBuffer &cmd);
287
288    // vkQueueWaitIdle()
289    void wait();
290
291    int get_family_index() { return family_index_; }
292
293   private:
294    int family_index_;
295};
296
297class DeviceMemory : public internal::NonDispHandle<VkDeviceMemory> {
298   public:
299    ~DeviceMemory();
300
301    // vkAllocateMemory()
302    void init(const Device &dev, const VkMemoryAllocateInfo &info);
303
304    // vkMapMemory()
305    const void *map(VkFlags flags) const;
306    void *map(VkFlags flags);
307    const void *map() const { return map(0); }
308    void *map() { return map(0); }
309
310    // vkUnmapMemory()
311    void unmap() const;
312
313    static VkMemoryAllocateInfo alloc_info(VkDeviceSize size, uint32_t memory_type_index);
314    static VkMemoryAllocateInfo get_resource_alloc_info(const vk_testing::Device &dev, const VkMemoryRequirements &reqs,
315                                                        VkMemoryPropertyFlags mem_props);
316};
317
318class Fence : public internal::NonDispHandle<VkFence> {
319   public:
320    ~Fence();
321
322    // vkCreateFence()
323    void init(const Device &dev, const VkFenceCreateInfo &info);
324
325    // vkGetFenceStatus()
326    VkResult status() const { return vkGetFenceStatus(device(), handle()); }
327
328    static VkFenceCreateInfo create_info(VkFenceCreateFlags flags);
329    static VkFenceCreateInfo create_info();
330};
331
332class Semaphore : public internal::NonDispHandle<VkSemaphore> {
333   public:
334    ~Semaphore();
335
336    // vkCreateSemaphore()
337    void init(const Device &dev, const VkSemaphoreCreateInfo &info);
338
339    static VkSemaphoreCreateInfo create_info(VkFlags flags);
340};
341
342class Event : public internal::NonDispHandle<VkEvent> {
343   public:
344    ~Event();
345
346    // vkCreateEvent()
347    void init(const Device &dev, const VkEventCreateInfo &info);
348
349    // vkGetEventStatus()
350    // vkSetEvent()
351    // vkResetEvent()
352    VkResult status() const { return vkGetEventStatus(device(), handle()); }
353    void set();
354    void reset();
355
356    static VkEventCreateInfo create_info(VkFlags flags);
357};
358
359class QueryPool : public internal::NonDispHandle<VkQueryPool> {
360   public:
361    ~QueryPool();
362
363    // vkCreateQueryPool()
364    void init(const Device &dev, const VkQueryPoolCreateInfo &info);
365
366    // vkGetQueryPoolResults()
367    VkResult results(uint32_t first, uint32_t count, size_t size, void *data, size_t stride);
368
369    static VkQueryPoolCreateInfo create_info(VkQueryType type, uint32_t slot_count);
370};
371
372class Buffer : public internal::NonDispHandle<VkBuffer> {
373   public:
374    explicit Buffer() : NonDispHandle() {}
375    explicit Buffer(const Device &dev, const VkBufferCreateInfo &info) { init(dev, info); }
376    explicit Buffer(const Device &dev, VkDeviceSize size) { init(dev, size); }
377
378    ~Buffer();
379
380    // vkCreateBuffer()
381    void init(const Device &dev, const VkBufferCreateInfo &info, VkMemoryPropertyFlags mem_props);
382    void init(const Device &dev, const VkBufferCreateInfo &info) { init(dev, info, 0); }
383    void init(const Device &dev, VkDeviceSize size, VkMemoryPropertyFlags mem_props) { init(dev, create_info(size, 0), mem_props); }
384    void init(const Device &dev, VkDeviceSize size) { init(dev, size, 0); }
385    void init_as_src(const Device &dev, VkDeviceSize size, VkMemoryPropertyFlags &reqs,
386                     const std::vector<uint32_t> *queue_families = nullptr) {
387        init(dev, create_info(size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, queue_families), reqs);
388    }
389    void init_as_dst(const Device &dev, VkDeviceSize size, VkMemoryPropertyFlags &reqs,
390                     const std::vector<uint32_t> *queue_families = nullptr) {
391        init(dev, create_info(size, VK_BUFFER_USAGE_TRANSFER_DST_BIT, queue_families), reqs);
392    }
393    void init_as_src_and_dst(const Device &dev, VkDeviceSize size, VkMemoryPropertyFlags &reqs,
394                             const std::vector<uint32_t> *queue_families = nullptr) {
395        init(dev, create_info(size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, queue_families), reqs);
396    }
397    void init_no_mem(const Device &dev, const VkBufferCreateInfo &info);
398
399    // get the internal memory
400    const DeviceMemory &memory() const { return internal_mem_; }
401    DeviceMemory &memory() { return internal_mem_; }
402
403    // vkGetObjectMemoryRequirements()
404    VkMemoryRequirements memory_requirements() const;
405
406    // vkBindObjectMemory()
407    void bind_memory(const DeviceMemory &mem, VkDeviceSize mem_offset);
408
409    static VkBufferCreateInfo create_info(VkDeviceSize size, VkFlags usage, const std::vector<uint32_t> *queue_families = nullptr);
410
411    VkBufferMemoryBarrier buffer_memory_barrier(VkFlags output_mask, VkFlags input_mask, VkDeviceSize offset,
412                                                VkDeviceSize size) const {
413        VkBufferMemoryBarrier barrier = {};
414        barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
415        barrier.buffer = handle();
416        barrier.srcAccessMask = output_mask;
417        barrier.dstAccessMask = input_mask;
418        barrier.offset = offset;
419        barrier.size = size;
420        if (create_info_.sharingMode == VK_SHARING_MODE_CONCURRENT) {
421            barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
422            barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
423        }
424        return barrier;
425    }
426
427   private:
428    VkBufferCreateInfo create_info_;
429
430    DeviceMemory internal_mem_;
431};
432
433class BufferView : public internal::NonDispHandle<VkBufferView> {
434   public:
435    ~BufferView();
436
437    // vkCreateBufferView()
438    void init(const Device &dev, const VkBufferViewCreateInfo &info);
439    static VkBufferViewCreateInfo createInfo(VkBuffer buffer, VkFormat format, VkDeviceSize offset = 0,
440                                             VkDeviceSize range = VK_WHOLE_SIZE);
441};
442
443inline VkBufferViewCreateInfo BufferView::createInfo(VkBuffer buffer, VkFormat format, VkDeviceSize offset, VkDeviceSize range) {
444    VkBufferViewCreateInfo info = {};
445    info.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO;
446    info.pNext = nullptr;
447    info.flags = VkFlags(0);
448    info.buffer = buffer;
449    info.format = format;
450    info.offset = offset;
451    info.range = range;
452    return info;
453}
454
455class Image : public internal::NonDispHandle<VkImage> {
456   public:
457    explicit Image() : NonDispHandle(), format_features_(0) {}
458    explicit Image(const Device &dev, const VkImageCreateInfo &info) : format_features_(0) { init(dev, info); }
459
460    ~Image();
461
462    // vkCreateImage()
463    void init(const Device &dev, const VkImageCreateInfo &info, VkMemoryPropertyFlags mem_props);
464    void init(const Device &dev, const VkImageCreateInfo &info) { init(dev, info, 0); }
465    void init_no_mem(const Device &dev, const VkImageCreateInfo &info);
466
467    // get the internal memory
468    const DeviceMemory &memory() const { return internal_mem_; }
469    DeviceMemory &memory() { return internal_mem_; }
470
471    // vkGetObjectMemoryRequirements()
472    VkMemoryRequirements memory_requirements() const;
473
474    // vkBindObjectMemory()
475    void bind_memory(const DeviceMemory &mem, VkDeviceSize mem_offset);
476
477    // vkGetImageSubresourceLayout()
478    VkSubresourceLayout subresource_layout(const VkImageSubresource &subres) const;
479    VkSubresourceLayout subresource_layout(const VkImageSubresourceLayers &subres) const;
480
481    bool transparent() const;
482    bool copyable() const { return (format_features_ & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT); }
483
484    VkImageSubresourceRange subresource_range(VkImageAspectFlagBits aspect) const {
485        return subresource_range(create_info_, aspect);
486    }
487    VkExtent3D extent() const { return create_info_.extent; }
488    VkExtent3D extent(uint32_t mip_level) const { return extent(create_info_.extent, mip_level); }
489    VkFormat format() const { return create_info_.format; }
490    VkImageUsageFlags usage() const { return create_info_.usage; }
491    VkSharingMode sharing_mode() const { return create_info_.sharingMode; }
492    VkImageMemoryBarrier image_memory_barrier(VkFlags output_mask, VkFlags input_mask, VkImageLayout old_layout,
493                                              VkImageLayout new_layout, const VkImageSubresourceRange &range) const {
494        VkImageMemoryBarrier barrier = {};
495        barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
496        barrier.srcAccessMask = output_mask;
497        barrier.dstAccessMask = input_mask;
498        barrier.oldLayout = old_layout;
499        barrier.newLayout = new_layout;
500        barrier.image = handle();
501        barrier.subresourceRange = range;
502
503        if (sharing_mode() == VK_SHARING_MODE_CONCURRENT) {
504            barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
505            barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
506        }
507        return barrier;
508    }
509
510    static VkImageCreateInfo create_info();
511    static VkImageSubresource subresource(VkImageAspectFlags aspect, uint32_t mip_level, uint32_t array_layer);
512    static VkImageSubresource subresource(const VkImageSubresourceRange &range, uint32_t mip_level, uint32_t array_layer);
513    static VkImageSubresourceLayers subresource(VkImageAspectFlags aspect, uint32_t mip_level, uint32_t array_layer,
514                                                uint32_t array_size);
515    static VkImageSubresourceLayers subresource(const VkImageSubresourceRange &range, uint32_t mip_level, uint32_t array_layer,
516                                                uint32_t array_size);
517    static VkImageSubresourceRange subresource_range(VkImageAspectFlags aspect_mask, uint32_t base_mip_level, uint32_t mip_levels,
518                                                     uint32_t base_array_layer, uint32_t num_layers);
519    static VkImageSubresourceRange subresource_range(const VkImageCreateInfo &info, VkImageAspectFlags aspect_mask);
520    static VkImageSubresourceRange subresource_range(const VkImageSubresource &subres);
521
522    static VkExtent2D extent(int32_t width, int32_t height);
523    static VkExtent2D extent(const VkExtent2D &extent, uint32_t mip_level);
524    static VkExtent2D extent(const VkExtent3D &extent);
525
526    static VkExtent3D extent(int32_t width, int32_t height, int32_t depth);
527    static VkExtent3D extent(const VkExtent3D &extent, uint32_t mip_level);
528
529   private:
530    void init_info(const Device &dev, const VkImageCreateInfo &info);
531
532    VkImageCreateInfo create_info_;
533    VkFlags format_features_;
534
535    DeviceMemory internal_mem_;
536};
537
538class ImageView : public internal::NonDispHandle<VkImageView> {
539   public:
540    ~ImageView();
541
542    // vkCreateImageView()
543    void init(const Device &dev, const VkImageViewCreateInfo &info);
544};
545
546class ShaderModule : public internal::NonDispHandle<VkShaderModule> {
547   public:
548    ~ShaderModule();
549
550    // vkCreateShaderModule()
551    void init(const Device &dev, const VkShaderModuleCreateInfo &info);
552    VkResult init_try(const Device &dev, const VkShaderModuleCreateInfo &info);
553
554    static VkShaderModuleCreateInfo create_info(size_t code_size, const uint32_t *code, VkFlags flags);
555};
556
557class Pipeline : public internal::NonDispHandle<VkPipeline> {
558   public:
559    ~Pipeline();
560
561    // vkCreateGraphicsPipeline()
562    void init(const Device &dev, const VkGraphicsPipelineCreateInfo &info);
563    // vkCreateGraphicsPipelineDerivative()
564    void init(const Device &dev, const VkGraphicsPipelineCreateInfo &info, const VkPipeline basePipeline);
565    // vkCreateComputePipeline()
566    void init(const Device &dev, const VkComputePipelineCreateInfo &info);
567    // vkLoadPipeline()
568    void init(const Device &dev, size_t size, const void *data);
569    // vkLoadPipelineDerivative()
570    void init(const Device &dev, size_t size, const void *data, VkPipeline basePipeline);
571
572    // vkCreateGraphicsPipeline with error return
573    VkResult init_try(const Device &dev, const VkGraphicsPipelineCreateInfo &info);
574
575    // vkStorePipeline()
576    size_t store(size_t size, void *data);
577};
578
579class PipelineLayout : public internal::NonDispHandle<VkPipelineLayout> {
580   public:
581    PipelineLayout() NOEXCEPT : NonDispHandle(){};
582    ~PipelineLayout();
583
584    // Move constructor for Visual Studio 2013
585    PipelineLayout(PipelineLayout &&src) : NonDispHandle(std::move(src)){};
586
587    PipelineLayout &operator=(PipelineLayout &&src) {
588        this->~PipelineLayout();
589        this->NonDispHandle::operator=(std::move(src));
590        return *this;
591    };
592
593    // vCreatePipelineLayout()
594    void init(const Device &dev, VkPipelineLayoutCreateInfo &info, const std::vector<const DescriptorSetLayout *> &layouts);
595};
596
597class Sampler : public internal::NonDispHandle<VkSampler> {
598   public:
599    ~Sampler();
600
601    // vkCreateSampler()
602    void init(const Device &dev, const VkSamplerCreateInfo &info);
603};
604
605class DescriptorSetLayout : public internal::NonDispHandle<VkDescriptorSetLayout> {
606   public:
607    DescriptorSetLayout() NOEXCEPT : NonDispHandle(){};
608    ~DescriptorSetLayout();
609
610    // Move constructor for Visual Studio 2013
611    DescriptorSetLayout(DescriptorSetLayout &&src) : NonDispHandle(std::move(src)){};
612
613    DescriptorSetLayout &operator=(DescriptorSetLayout &&src) NOEXCEPT {
614        this->~DescriptorSetLayout();
615        this->NonDispHandle::operator=(std::move(src));
616        return *this;
617    }
618
619    // vkCreateDescriptorSetLayout()
620    void init(const Device &dev, const VkDescriptorSetLayoutCreateInfo &info);
621};
622
623class DescriptorPool : public internal::NonDispHandle<VkDescriptorPool> {
624   public:
625    ~DescriptorPool();
626
627    // Descriptor sets allocated from this pool will need access to the original
628    // object
629    VkDescriptorPool GetObj() { return pool_; }
630
631    // vkCreateDescriptorPool()
632    void init(const Device &dev, const VkDescriptorPoolCreateInfo &info);
633
634    // vkResetDescriptorPool()
635    void reset();
636
637    // vkFreeDescriptorSet()
638    void setDynamicUsage(bool isDynamic) { dynamic_usage_ = isDynamic; }
639    bool getDynamicUsage() { return dynamic_usage_; }
640
641    // vkAllocateDescriptorSets()
642    std::vector<DescriptorSet *> alloc_sets(const Device &dev, const std::vector<const DescriptorSetLayout *> &layouts);
643    std::vector<DescriptorSet *> alloc_sets(const Device &dev, const DescriptorSetLayout &layout, uint32_t count);
644    DescriptorSet *alloc_sets(const Device &dev, const DescriptorSetLayout &layout);
645
646    template <typename PoolSizes>
647    static VkDescriptorPoolCreateInfo create_info(VkDescriptorPoolCreateFlags flags, uint32_t max_sets,
648                                                  const PoolSizes &pool_sizes);
649
650   private:
651    VkDescriptorPool pool_;
652
653    // Track whether this pool's usage is VK_DESCRIPTOR_POOL_USAGE_DYNAMIC
654    bool dynamic_usage_;
655};
656
657template <typename PoolSizes>
658inline VkDescriptorPoolCreateInfo DescriptorPool::create_info(VkDescriptorPoolCreateFlags flags, uint32_t max_sets,
659                                                              const PoolSizes &pool_sizes) {
660    VkDescriptorPoolCreateInfo info{};
661    info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
662    info.pNext = nullptr;
663    info.flags = flags;
664    info.maxSets = max_sets;
665    info.poolSizeCount = pool_sizes.size();
666    info.pPoolSizes = (info.poolSizeCount) ? pool_sizes.data() : nullptr;
667    return info;
668}
669
670class DescriptorSet : public internal::NonDispHandle<VkDescriptorSet> {
671   public:
672    ~DescriptorSet();
673
674    explicit DescriptorSet() : NonDispHandle() {}
675    explicit DescriptorSet(const Device &dev, DescriptorPool *pool, VkDescriptorSet set) : NonDispHandle(dev.handle(), set) {
676        containing_pool_ = pool;
677    }
678
679   private:
680    DescriptorPool *containing_pool_;
681};
682
683class CommandPool : public internal::NonDispHandle<VkCommandPool> {
684   public:
685    ~CommandPool();
686
687    explicit CommandPool() : NonDispHandle() {}
688    explicit CommandPool(const Device &dev, const VkCommandPoolCreateInfo &info) { init(dev, info); }
689
690    void init(const Device &dev, const VkCommandPoolCreateInfo &info);
691
692    static VkCommandPoolCreateInfo create_info(uint32_t queue_family_index, VkCommandPoolCreateFlags flags);
693};
694
695inline VkCommandPoolCreateInfo CommandPool::create_info(uint32_t queue_family_index, VkCommandPoolCreateFlags flags) {
696    VkCommandPoolCreateInfo info = {};
697    info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
698    info.queueFamilyIndex = queue_family_index;
699    info.flags = flags;
700    return info;
701}
702
703class CommandBuffer : public internal::Handle<VkCommandBuffer> {
704   public:
705    ~CommandBuffer();
706
707    explicit CommandBuffer() : Handle() {}
708    explicit CommandBuffer(const Device &dev, const VkCommandBufferAllocateInfo &info) { init(dev, info); }
709
710    // vkAllocateCommandBuffers()
711    void init(const Device &dev, const VkCommandBufferAllocateInfo &info);
712
713    // vkBeginCommandBuffer()
714    void begin(const VkCommandBufferBeginInfo *info);
715    void begin();
716
717    // vkEndCommandBuffer()
718    // vkResetCommandBuffer()
719    void end();
720    void reset(VkCommandBufferResetFlags flags);
721    void reset() { reset(VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT); }
722
723    static VkCommandBufferAllocateInfo create_info(VkCommandPool const &pool);
724
725   private:
726    VkDevice dev_handle_;
727    VkCommandPool cmd_pool_;
728};
729
730inline VkMemoryAllocateInfo DeviceMemory::alloc_info(VkDeviceSize size, uint32_t memory_type_index) {
731    VkMemoryAllocateInfo info = {};
732    info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
733    info.allocationSize = size;
734    info.memoryTypeIndex = memory_type_index;
735    return info;
736}
737
738inline VkBufferCreateInfo Buffer::create_info(VkDeviceSize size, VkFlags usage, const std::vector<uint32_t> *queue_families) {
739    VkBufferCreateInfo info = {};
740    info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
741    info.size = size;
742    info.usage = usage;
743
744    if (queue_families && queue_families->size() > 1) {
745        info.sharingMode = VK_SHARING_MODE_CONCURRENT;
746        info.queueFamilyIndexCount = static_cast<uint32_t>(queue_families->size());
747        info.pQueueFamilyIndices = queue_families->data();
748    }
749
750    return info;
751}
752
753inline VkFenceCreateInfo Fence::create_info(VkFenceCreateFlags flags) {
754    VkFenceCreateInfo info = {};
755    info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
756    info.flags = flags;
757    return info;
758}
759
760inline VkFenceCreateInfo Fence::create_info() {
761    VkFenceCreateInfo info = {};
762    info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
763    return info;
764}
765
766inline VkSemaphoreCreateInfo Semaphore::create_info(VkFlags flags) {
767    VkSemaphoreCreateInfo info = {};
768    info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
769    info.flags = flags;
770    return info;
771}
772
773inline VkEventCreateInfo Event::create_info(VkFlags flags) {
774    VkEventCreateInfo info = {};
775    info.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO;
776    info.flags = flags;
777    return info;
778}
779
780inline VkQueryPoolCreateInfo QueryPool::create_info(VkQueryType type, uint32_t slot_count) {
781    VkQueryPoolCreateInfo info = {};
782    info.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;
783    info.queryType = type;
784    info.queryCount = slot_count;
785    return info;
786}
787
788inline VkImageCreateInfo Image::create_info() {
789    VkImageCreateInfo info = {};
790    info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
791    info.extent.width = 1;
792    info.extent.height = 1;
793    info.extent.depth = 1;
794    info.mipLevels = 1;
795    info.arrayLayers = 1;
796    info.samples = VK_SAMPLE_COUNT_1_BIT;
797    return info;
798}
799
800inline VkImageSubresource Image::subresource(VkImageAspectFlags aspect, uint32_t mip_level, uint32_t array_layer) {
801    VkImageSubresource subres = {};
802    if (aspect == 0) {
803        assert(!"Invalid VkImageAspectFlags");
804    }
805    subres.aspectMask = aspect;
806    subres.mipLevel = mip_level;
807    subres.arrayLayer = array_layer;
808    return subres;
809}
810
811inline VkImageSubresource Image::subresource(const VkImageSubresourceRange &range, uint32_t mip_level, uint32_t array_layer) {
812    return subresource(range.aspectMask, range.baseMipLevel + mip_level, range.baseArrayLayer + array_layer);
813}
814
815inline VkImageSubresourceLayers Image::subresource(VkImageAspectFlags aspect, uint32_t mip_level, uint32_t array_layer,
816                                                   uint32_t array_size) {
817    VkImageSubresourceLayers subres = {};
818    switch (aspect) {
819        case VK_IMAGE_ASPECT_COLOR_BIT:
820        case VK_IMAGE_ASPECT_DEPTH_BIT:
821        case VK_IMAGE_ASPECT_STENCIL_BIT:
822        case VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT:
823            /* valid */
824            break;
825        default:
826            assert(!"Invalid VkImageAspectFlags");
827    }
828    subres.aspectMask = aspect;
829    subres.mipLevel = mip_level;
830    subres.baseArrayLayer = array_layer;
831    subres.layerCount = array_size;
832    return subres;
833}
834
835inline VkImageSubresourceLayers Image::subresource(const VkImageSubresourceRange &range, uint32_t mip_level, uint32_t array_layer,
836                                                   uint32_t array_size) {
837    return subresource(range.aspectMask, range.baseMipLevel + mip_level, range.baseArrayLayer + array_layer, array_size);
838}
839
840inline VkImageSubresourceRange Image::subresource_range(VkImageAspectFlags aspect_mask, uint32_t base_mip_level,
841                                                        uint32_t mip_levels, uint32_t base_array_layer, uint32_t num_layers) {
842    VkImageSubresourceRange range = {};
843    if (aspect_mask == 0) {
844        assert(!"Invalid VkImageAspectFlags");
845    }
846    range.aspectMask = aspect_mask;
847    range.baseMipLevel = base_mip_level;
848    range.levelCount = mip_levels;
849    range.baseArrayLayer = base_array_layer;
850    range.layerCount = num_layers;
851    return range;
852}
853
854inline VkImageSubresourceRange Image::subresource_range(const VkImageCreateInfo &info, VkImageAspectFlags aspect_mask) {
855    return subresource_range(aspect_mask, 0, info.mipLevels, 0, info.arrayLayers);
856}
857
858inline VkImageSubresourceRange Image::subresource_range(const VkImageSubresource &subres) {
859    return subresource_range(subres.aspectMask, subres.mipLevel, 1, subres.arrayLayer, 1);
860}
861
862inline VkExtent2D Image::extent(int32_t width, int32_t height) {
863    VkExtent2D extent = {};
864    extent.width = width;
865    extent.height = height;
866    return extent;
867}
868
869inline VkExtent2D Image::extent(const VkExtent2D &extent, uint32_t mip_level) {
870    const int32_t width = (extent.width >> mip_level) ? extent.width >> mip_level : 1;
871    const int32_t height = (extent.height >> mip_level) ? extent.height >> mip_level : 1;
872    return Image::extent(width, height);
873}
874
875inline VkExtent2D Image::extent(const VkExtent3D &extent) { return Image::extent(extent.width, extent.height); }
876
877inline VkExtent3D Image::extent(int32_t width, int32_t height, int32_t depth) {
878    VkExtent3D extent = {};
879    extent.width = width;
880    extent.height = height;
881    extent.depth = depth;
882    return extent;
883}
884
885inline VkExtent3D Image::extent(const VkExtent3D &extent, uint32_t mip_level) {
886    const int32_t width = (extent.width >> mip_level) ? extent.width >> mip_level : 1;
887    const int32_t height = (extent.height >> mip_level) ? extent.height >> mip_level : 1;
888    const int32_t depth = (extent.depth >> mip_level) ? extent.depth >> mip_level : 1;
889    return Image::extent(width, height, depth);
890}
891
892inline VkShaderModuleCreateInfo ShaderModule::create_info(size_t code_size, const uint32_t *code, VkFlags flags) {
893    VkShaderModuleCreateInfo info = {};
894    info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
895    info.codeSize = code_size;
896    info.pCode = code;
897    info.flags = flags;
898    return info;
899}
900
901inline VkWriteDescriptorSet Device::write_descriptor_set(const DescriptorSet &set, uint32_t binding, uint32_t array_element,
902                                                         VkDescriptorType type, uint32_t count,
903                                                         const VkDescriptorImageInfo *image_info) {
904    VkWriteDescriptorSet write = {};
905    write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
906    write.dstSet = set.handle();
907    write.dstBinding = binding;
908    write.dstArrayElement = array_element;
909    write.descriptorCount = count;
910    write.descriptorType = type;
911    write.pImageInfo = image_info;
912    return write;
913}
914
915inline VkWriteDescriptorSet Device::write_descriptor_set(const DescriptorSet &set, uint32_t binding, uint32_t array_element,
916                                                         VkDescriptorType type, uint32_t count,
917                                                         const VkDescriptorBufferInfo *buffer_info) {
918    VkWriteDescriptorSet write = {};
919    write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
920    write.dstSet = set.handle();
921    write.dstBinding = binding;
922    write.dstArrayElement = array_element;
923    write.descriptorCount = count;
924    write.descriptorType = type;
925    write.pBufferInfo = buffer_info;
926    return write;
927}
928
929inline VkWriteDescriptorSet Device::write_descriptor_set(const DescriptorSet &set, uint32_t binding, uint32_t array_element,
930                                                         VkDescriptorType type, uint32_t count, const VkBufferView *buffer_views) {
931    VkWriteDescriptorSet write = {};
932    write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
933    write.dstSet = set.handle();
934    write.dstBinding = binding;
935    write.dstArrayElement = array_element;
936    write.descriptorCount = count;
937    write.descriptorType = type;
938    write.pTexelBufferView = buffer_views;
939    return write;
940}
941
942inline VkWriteDescriptorSet Device::write_descriptor_set(const DescriptorSet &set, uint32_t binding, uint32_t array_element,
943                                                         VkDescriptorType type,
944                                                         const std::vector<VkDescriptorImageInfo> &image_info) {
945    return write_descriptor_set(set, binding, array_element, type, image_info.size(), &image_info[0]);
946}
947
948inline VkWriteDescriptorSet Device::write_descriptor_set(const DescriptorSet &set, uint32_t binding, uint32_t array_element,
949                                                         VkDescriptorType type,
950                                                         const std::vector<VkDescriptorBufferInfo> &buffer_info) {
951    return write_descriptor_set(set, binding, array_element, type, buffer_info.size(), &buffer_info[0]);
952}
953
954inline VkWriteDescriptorSet Device::write_descriptor_set(const DescriptorSet &set, uint32_t binding, uint32_t array_element,
955                                                         VkDescriptorType type, const std::vector<VkBufferView> &buffer_views) {
956    return write_descriptor_set(set, binding, array_element, type, buffer_views.size(), &buffer_views[0]);
957}
958
959inline VkCopyDescriptorSet Device::copy_descriptor_set(const DescriptorSet &src_set, uint32_t src_binding,
960                                                       uint32_t src_array_element, const DescriptorSet &dst_set,
961                                                       uint32_t dst_binding, uint32_t dst_array_element, uint32_t count) {
962    VkCopyDescriptorSet copy = {};
963    copy.sType = VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET;
964    copy.srcSet = src_set.handle();
965    copy.srcBinding = src_binding;
966    copy.srcArrayElement = src_array_element;
967    copy.dstSet = dst_set.handle();
968    copy.dstBinding = dst_binding;
969    copy.dstArrayElement = dst_array_element;
970    copy.descriptorCount = count;
971
972    return copy;
973}
974
975inline VkCommandBufferAllocateInfo CommandBuffer::create_info(VkCommandPool const &pool) {
976    VkCommandBufferAllocateInfo info = {};
977    info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
978    info.commandPool = pool;
979    info.commandBufferCount = 1;
980    return info;
981}
982
983}  // namespace vk_testing
984
985#endif  // VKTESTBINDING_H
986