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