Home | History | Annotate | Download | only in tests
      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 (at) LunarG.com>
     19  * Author: Cody Northrop <cody (at) lunarg.com>
     20  * Author: John Zulauf <jzulauf (at) 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 
     33 namespace vk_testing {
     34 
     35 template <class Dst, class Src>
     36 std::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 
     43 template <class Dst, class Src>
     44 std::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 
     51 typedef void (*ErrorCallback)(const char *expr, const char *file, unsigned int line, const char *function);
     52 void set_error_callback(ErrorCallback callback);
     53 
     54 class PhysicalDevice;
     55 class Device;
     56 class Queue;
     57 class DeviceMemory;
     58 class Fence;
     59 class Semaphore;
     60 class Event;
     61 class QueryPool;
     62 class Buffer;
     63 class BufferView;
     64 class Image;
     65 class ImageView;
     66 class DepthStencilView;
     67 class Shader;
     68 class Pipeline;
     69 class PipelineDelta;
     70 class Sampler;
     71 class DescriptorSetLayout;
     72 class PipelineLayout;
     73 class DescriptorSetPool;
     74 class DescriptorSet;
     75 class CommandBuffer;
     76 class CommandPool;
     77 
     78 std::vector<VkLayerProperties> GetGlobalLayers();
     79 std::vector<VkExtensionProperties> GetGlobalExtensions();
     80 std::vector<VkExtensionProperties> GetGlobalExtensions(const char *pLayerName);
     81 
     82 namespace internal {
     83 
     84 template <typename T>
     85 class 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 
    117 template <typename T>
    118 class 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 
    148 class 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 
    179 class 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 
    190 class 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 
    279 class 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 
    297 class 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 
    318 class 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 
    332 class 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 
    342 class 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 
    359 class 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 
    372 class 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 
    433 class 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 
    443 inline 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 
    455 class 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 
    538 class ImageView : public internal::NonDispHandle<VkImageView> {
    539    public:
    540     ~ImageView();
    541 
    542     // vkCreateImageView()
    543     void init(const Device &dev, const VkImageViewCreateInfo &info);
    544 };
    545 
    546 class 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 
    557 class 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 
    579 class 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 
    597 class Sampler : public internal::NonDispHandle<VkSampler> {
    598    public:
    599     ~Sampler();
    600 
    601     // vkCreateSampler()
    602     void init(const Device &dev, const VkSamplerCreateInfo &info);
    603 };
    604 
    605 class 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 
    623 class 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 
    657 template <typename PoolSizes>
    658 inline 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 
    670 class 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 
    683 class 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 
    695 inline 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 
    703 class 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 
    730 inline 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 
    738 inline 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 
    753 inline 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 
    760 inline VkFenceCreateInfo Fence::create_info() {
    761     VkFenceCreateInfo info = {};
    762     info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
    763     return info;
    764 }
    765 
    766 inline 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 
    773 inline 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 
    780 inline 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 
    788 inline 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 
    800 inline 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 
    811 inline 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 
    815 inline 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 
    835 inline 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 
    840 inline 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 
    854 inline VkImageSubresourceRange Image::subresource_range(const VkImageCreateInfo &info, VkImageAspectFlags aspect_mask) {
    855     return subresource_range(aspect_mask, 0, info.mipLevels, 0, info.arrayLayers);
    856 }
    857 
    858 inline VkImageSubresourceRange Image::subresource_range(const VkImageSubresource &subres) {
    859     return subresource_range(subres.aspectMask, subres.mipLevel, 1, subres.arrayLayer, 1);
    860 }
    861 
    862 inline 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 
    869 inline 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 
    875 inline VkExtent2D Image::extent(const VkExtent3D &extent) { return Image::extent(extent.width, extent.height); }
    876 
    877 inline 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 
    885 inline 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 
    892 inline 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 
    901 inline 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 
    915 inline 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 
    929 inline 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 
    942 inline 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 
    948 inline 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 
    954 inline 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 
    959 inline 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 
    975 inline 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