1 /*
2  * Copyright (c) 2015-2016 The Khronos Group Inc.
3  * Copyright (c) 2015-2016 Valve Corporation
4  * Copyright (c) 2015-2016 LunarG, Inc.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
19  * Author: Cody Northrop <cody@lunarg.com>
20  * Author: John Zulauf <jzulauf@lunarg.com>
21  */
22 
23 #ifndef VKTESTBINDING_H
24 #define VKTESTBINDING_H
25 
26 #include <algorithm>
27 #include <assert.h>
28 #include <iterator>
29 #include <vector>
30 
31 #include "vulkan/vulkan.h"
32 
33 namespace vk_testing {
34 
35 template <class Dst, class Src>
MakeVkHandles(const std::vector<Src> & v)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>
MakeVkHandles(const std::vector<Src * > & v)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:
handle()87     const T &handle() const { return handle_; }
initialized()88     bool initialized() const { return (handle_ != T{}); }
89 
90    protected:
91     typedef T handle_type;
92 
Handle()93     explicit Handle() : handle_{} {}
Handle(T 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
Handle(Handle && src)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 
init(T handle)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:
NonDispHandle()120     explicit NonDispHandle() : Handle<T>(), dev_handle_(VK_NULL_HANDLE) {}
NonDispHandle(VkDevice dev,T handle)121     explicit NonDispHandle(VkDevice dev, T handle) : Handle<T>(handle), dev_handle_(dev) {}
122 
NonDispHandle(NonDispHandle && src)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 
device()134     const VkDevice &device() const { return dev_handle_; }
135 
init(VkDevice dev,T handle)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:
PhysicalDevice(VkPhysicalDevice phy)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);
size()186     size_t size() const { return queue_info_.size(); }
data()187     const VkDeviceQueueCreateInfo *data() const { return queue_info_.data(); }
188 };
189 
190 class Device : public internal::Handle<VkDevice> {
191    public:
Device(VkPhysicalDevice phy)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
init()199     void init() {
200         std::vector<const char *> extensions;
201         init(extensions);
202     };
203 
phy()204     const PhysicalDevice &phy() const { return phy_; }
205 
GetEnabledExtensions()206     std::vector<const char *> GetEnabledExtensions() { return enabled_extensions_; }
207     bool IsEnbledExtension(const char *extension);
208 
209     // vkGetDeviceProcAddr()
get_proc(const char * name)210     PFN_vkVoidFunction get_proc(const char *name) const { return vkGetDeviceProcAddr(handle(), name); }
211 
212     // vkGetDeviceQueue()
graphics_queues()213     const std::vector<Queue *> &graphics_queues() const { return queues_[GRAPHICS]; }
compute_queues()214     const std::vector<Queue *> &compute_queues() { return queues_[COMPUTE]; }
dma_queues()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);
formats()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);
wait(const Fence & fence)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);
update_descriptor_sets(const std::vector<VkWriteDescriptorSet> & writes)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:
Queue(VkQueue queue,int index)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 
get_family_index()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);
map()307     const void *map() const { return map(0); }
map()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()
status()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()
status()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:
Buffer()374     explicit Buffer() : NonDispHandle() {}
Buffer(const Device & dev,const VkBufferCreateInfo & info)375     explicit Buffer(const Device &dev, const VkBufferCreateInfo &info) { init(dev, info); }
Buffer(const Device & dev,VkDeviceSize size)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);
init(const Device & dev,const VkBufferCreateInfo & info)382     void init(const Device &dev, const VkBufferCreateInfo &info) { init(dev, info, 0); }
init(const Device & dev,VkDeviceSize size,VkMemoryPropertyFlags mem_props)383     void init(const Device &dev, VkDeviceSize size, VkMemoryPropertyFlags mem_props) { init(dev, create_info(size, 0), mem_props); }
init(const Device & dev,VkDeviceSize size)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
memory()400     const DeviceMemory &memory() const { return internal_mem_; }
memory()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 
buffer_memory_barrier(VkFlags output_mask,VkFlags input_mask,VkDeviceSize offset,VkDeviceSize size)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 
createInfo(VkBuffer buffer,VkFormat format,VkDeviceSize offset,VkDeviceSize range)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:
Image()457     explicit Image() : NonDispHandle(), format_features_(0) {}
Image(const Device & dev,const VkImageCreateInfo & info)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);
init(const Device & dev,const VkImageCreateInfo & info)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
memory()468     const DeviceMemory &memory() const { return internal_mem_; }
memory()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;
copyable()482     bool copyable() const { return (format_features_ & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT); }
483 
subresource_range(VkImageAspectFlagBits aspect)484     VkImageSubresourceRange subresource_range(VkImageAspectFlagBits aspect) const {
485         return subresource_range(create_info_, aspect);
486     }
extent()487     VkExtent3D extent() const { return create_info_.extent; }
extent(uint32_t mip_level)488     VkExtent3D extent(uint32_t mip_level) const { return extent(create_info_.extent, mip_level); }
format()489     VkFormat format() const { return create_info_.format; }
usage()490     VkImageUsageFlags usage() const { return create_info_.usage; }
sharing_mode()491     VkSharingMode sharing_mode() const { return create_info_.sharingMode; }
image_memory_barrier(VkFlags output_mask,VkFlags input_mask,VkImageLayout old_layout,VkImageLayout new_layout,const VkImageSubresourceRange & range)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:
PipelineLayout()581     PipelineLayout() NOEXCEPT : NonDispHandle(){};
582     ~PipelineLayout();
583 
584     // Move constructor for Visual Studio 2013
PipelineLayout(PipelineLayout && src)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:
DescriptorSetLayout()607     DescriptorSetLayout() NOEXCEPT : NonDispHandle(){};
608     ~DescriptorSetLayout();
609 
610     // Move constructor for Visual Studio 2013
DescriptorSetLayout(DescriptorSetLayout && src)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
GetObj()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()
setDynamicUsage(bool isDynamic)638     void setDynamicUsage(bool isDynamic) { dynamic_usage_ = isDynamic; }
getDynamicUsage()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>
create_info(VkDescriptorPoolCreateFlags flags,uint32_t max_sets,const PoolSizes & pool_sizes)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 
DescriptorSet()674     explicit DescriptorSet() : NonDispHandle() {}
DescriptorSet(const Device & dev,DescriptorPool * pool,VkDescriptorSet set)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 
CommandPool()687     explicit CommandPool() : NonDispHandle() {}
CommandPool(const Device & dev,const VkCommandPoolCreateInfo & info)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 
create_info(uint32_t queue_family_index,VkCommandPoolCreateFlags flags)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 
CommandBuffer()707     explicit CommandBuffer() : Handle() {}
CommandBuffer(const Device & dev,const VkCommandBufferAllocateInfo & info)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);
reset()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 
alloc_info(VkDeviceSize size,uint32_t memory_type_index)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 
create_info(VkDeviceSize size,VkFlags usage,const std::vector<uint32_t> * queue_families)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 
create_info(VkFenceCreateFlags flags)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 
create_info()760 inline VkFenceCreateInfo Fence::create_info() {
761     VkFenceCreateInfo info = {};
762     info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
763     return info;
764 }
765 
create_info(VkFlags flags)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 
create_info(VkFlags flags)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 
create_info(VkQueryType type,uint32_t slot_count)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 
create_info()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 
subresource(VkImageAspectFlags aspect,uint32_t mip_level,uint32_t array_layer)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 
subresource(const VkImageSubresourceRange & range,uint32_t mip_level,uint32_t array_layer)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 
subresource(VkImageAspectFlags aspect,uint32_t mip_level,uint32_t array_layer,uint32_t array_size)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 
subresource(const VkImageSubresourceRange & range,uint32_t mip_level,uint32_t array_layer,uint32_t array_size)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 
subresource_range(VkImageAspectFlags aspect_mask,uint32_t base_mip_level,uint32_t mip_levels,uint32_t base_array_layer,uint32_t num_layers)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 
subresource_range(const VkImageCreateInfo & info,VkImageAspectFlags aspect_mask)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 
subresource_range(const VkImageSubresource & subres)858 inline VkImageSubresourceRange Image::subresource_range(const VkImageSubresource &subres) {
859     return subresource_range(subres.aspectMask, subres.mipLevel, 1, subres.arrayLayer, 1);
860 }
861 
extent(int32_t width,int32_t height)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 
extent(const VkExtent2D & extent,uint32_t mip_level)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 
extent(const VkExtent3D & extent)875 inline VkExtent2D Image::extent(const VkExtent3D &extent) { return Image::extent(extent.width, extent.height); }
876 
extent(int32_t width,int32_t height,int32_t depth)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 
extent(const VkExtent3D & extent,uint32_t mip_level)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 
create_info(size_t code_size,const uint32_t * code,VkFlags flags)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 
write_descriptor_set(const DescriptorSet & set,uint32_t binding,uint32_t array_element,VkDescriptorType type,uint32_t count,const VkDescriptorImageInfo * image_info)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 
write_descriptor_set(const DescriptorSet & set,uint32_t binding,uint32_t array_element,VkDescriptorType type,uint32_t count,const VkDescriptorBufferInfo * buffer_info)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 
write_descriptor_set(const DescriptorSet & set,uint32_t binding,uint32_t array_element,VkDescriptorType type,uint32_t count,const VkBufferView * buffer_views)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 
write_descriptor_set(const DescriptorSet & set,uint32_t binding,uint32_t array_element,VkDescriptorType type,const std::vector<VkDescriptorImageInfo> & image_info)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 
write_descriptor_set(const DescriptorSet & set,uint32_t binding,uint32_t array_element,VkDescriptorType type,const std::vector<VkDescriptorBufferInfo> & buffer_info)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 
write_descriptor_set(const DescriptorSet & set,uint32_t binding,uint32_t array_element,VkDescriptorType type,const std::vector<VkBufferView> & buffer_views)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 
copy_descriptor_set(const DescriptorSet & src_set,uint32_t src_binding,uint32_t src_array_element,const DescriptorSet & dst_set,uint32_t dst_binding,uint32_t dst_array_element,uint32_t count)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 
create_info(VkCommandPool const & pool)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