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