owned_handle.hpp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#pragma once


#include <planet/vk/helpers.hpp>

#include <utility>

#include <vulkan/vulkan.h>


namespace planet::vk {

A Vulkan handle that is owned by some other handle

Examples of these include the surface, which is owned by an Instance and semaphore, which is owned by a device.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
    template<typename O, typename T, void (*D)(O, T, VkAllocationCallbacks const *)>
    class owned_handle final {
        O owner_handle = VK_NULL_HANDLE;
        T handle = VK_NULL_HANDLE;
        VkAllocationCallbacks const *allocator = nullptr;


        owned_handle(O o, T h, VkAllocationCallbacks const *a) noexcept
        : owner_handle{o}, handle{h}, allocator{a} {}


      public:
        owned_handle() noexcept {}
        owned_handle(owned_handle const &) = delete;
        owned_handle(owned_handle &&h) noexcept
        : owner_handle{std::exchange(h.owner_handle, VK_NULL_HANDLE)},
          handle{std::exchange(h.handle, VK_NULL_HANDLE)},
          allocator{std::exchange(h.allocator, nullptr)} {}
        ~owned_handle() noexcept { reset(); }

        owned_handle &operator=(owned_handle const &) = delete;
        owned_handle &operator=(owned_handle &&h) noexcept {
            reset();
            owner_handle = std::exchange(h.owner_handle, VK_NULL_HANDLE);
            handle = std::exchange(h.handle, VK_NULL_HANDLE);
            allocator = std::exchange(h.allocator, nullptr);
            return *this;
        }


        T get() const noexcept { return handle; }
        T const *address() const noexcept { return &handle; }
        O owner() const noexcept { return owner_handle; }

Remove the current content (if any)

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
        void reset() noexcept {
            if (owner_handle and handle) {
                D(std::exchange(owner_handle, VK_NULL_HANDLE),
                  std::exchange(handle, VK_NULL_HANDLE),
                  std::exchange(allocator, nullptr));
            }
        }


        template<auto C, typename I>
        void
                create(O h,
                       I const &info,
                       VkAllocationCallbacks const *alloc,
                       felspar::source_location const &loc =
                               felspar::source_location::current()) {
            reset();
            owner_handle = h;
            allocator = alloc;
            worked(C(h, &info, alloc, &handle), loc);
        }
        template<auto C, typename I>
        void
                create(O h,
                       I const &info,
                       felspar::source_location const &loc =
                               felspar::source_location::current()) {
            create<C, I>(h, info, nullptr, loc);
        }
        static owned_handle bind(O o, T h) noexcept { return {o, h, nullptr}; }
    };

Shorter names for common owners of handles

89
90
91
92
93
    template<typename T, void (*D)(VkDevice, T, VkAllocationCallbacks const *)>
    using device_handle = owned_handle<VkDevice, T, D>;


}