|
|
@@ -278,4 +278,148 @@ void Destroy(VkInstance, VkSurfaceKHR, const InstanceDispatch&) noexcept;
|
|
|
VkResult Free(VkDevice, VkDescriptorPool, Span<VkDescriptorSet>, const DeviceDispatch&) noexcept;
|
|
|
VkResult Free(VkDevice, VkCommandPool, Span<VkCommandBuffer>, const DeviceDispatch&) noexcept;
|
|
|
|
|
|
+template <typename Type, typename OwnerType, typename Dispatch>
|
|
|
+class Handle;
|
|
|
+
|
|
|
+/// Handle with an owning type.
|
|
|
+/// Analogue to std::unique_ptr.
|
|
|
+template <typename Type, typename OwnerType, typename Dispatch>
|
|
|
+class Handle {
|
|
|
+public:
|
|
|
+ /// Construct a handle and hold it's ownership.
|
|
|
+ explicit Handle(Type handle_, OwnerType owner_, const Dispatch& dld_) noexcept
|
|
|
+ : handle{handle_}, owner{owner_}, dld{&dld_} {}
|
|
|
+
|
|
|
+ /// Construct an empty handle.
|
|
|
+ Handle() = default;
|
|
|
+
|
|
|
+ /// Copying Vulkan objects is not supported and will never be.
|
|
|
+ Handle(const Handle&) = delete;
|
|
|
+ Handle& operator=(const Handle&) = delete;
|
|
|
+
|
|
|
+ /// Construct a handle transfering the ownership from another handle.
|
|
|
+ Handle(Handle&& rhs) noexcept
|
|
|
+ : handle{std::exchange(rhs.handle, nullptr)}, owner{rhs.owner}, dld{rhs.dld} {}
|
|
|
+
|
|
|
+ /// Assign the current handle transfering the ownership from another handle.
|
|
|
+ /// Destroys any previously held object.
|
|
|
+ Handle& operator=(Handle&& rhs) noexcept {
|
|
|
+ Release();
|
|
|
+ handle = std::exchange(rhs.handle, nullptr);
|
|
|
+ owner = rhs.owner;
|
|
|
+ dld = rhs.dld;
|
|
|
+ return *this;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Destroys the current handle if it existed.
|
|
|
+ ~Handle() noexcept {
|
|
|
+ Release();
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Destroys any held object.
|
|
|
+ void reset() noexcept {
|
|
|
+ Release();
|
|
|
+ handle = nullptr;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Returns the address of the held object.
|
|
|
+ /// Intended for Vulkan structures that expect a pointer to an array.
|
|
|
+ const Type* address() const noexcept {
|
|
|
+ return &handle;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Returns the held Vulkan handle.
|
|
|
+ Type operator*() const noexcept {
|
|
|
+ return handle;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Returns true when there's a held object.
|
|
|
+ operator bool() const noexcept {
|
|
|
+ return handle != nullptr;
|
|
|
+ }
|
|
|
+
|
|
|
+protected:
|
|
|
+ Type handle = nullptr;
|
|
|
+ OwnerType owner = nullptr;
|
|
|
+ const Dispatch* dld = nullptr;
|
|
|
+
|
|
|
+private:
|
|
|
+ /// Destroys the held object if it exists.
|
|
|
+ void Release() noexcept {
|
|
|
+ if (handle) {
|
|
|
+ Destroy(owner, handle, *dld);
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+/// Dummy type used to specify a handle has no owner.
|
|
|
+struct NoOwner {};
|
|
|
+
|
|
|
+/// Handle without an owning type.
|
|
|
+/// Analogue to std::unique_ptr
|
|
|
+template <typename Type, typename Dispatch>
|
|
|
+class Handle<Type, NoOwner, Dispatch> {
|
|
|
+public:
|
|
|
+ /// Construct a handle and hold it's ownership.
|
|
|
+ explicit Handle(Type handle_, const Dispatch& dld_) noexcept : handle{handle_}, dld{&dld_} {}
|
|
|
+
|
|
|
+ /// Construct an empty handle.
|
|
|
+ Handle() noexcept = default;
|
|
|
+
|
|
|
+ /// Copying Vulkan objects is not supported and will never be.
|
|
|
+ Handle(const Handle&) = delete;
|
|
|
+ Handle& operator=(const Handle&) = delete;
|
|
|
+
|
|
|
+ /// Construct a handle transfering ownership from another handle.
|
|
|
+ Handle(Handle&& rhs) noexcept : handle{std::exchange(rhs.handle, nullptr)}, dld{rhs.dld} {}
|
|
|
+
|
|
|
+ /// Assign the current handle transfering the ownership from another handle.
|
|
|
+ /// Destroys any previously held object.
|
|
|
+ Handle& operator=(Handle&& rhs) noexcept {
|
|
|
+ Release();
|
|
|
+ handle = std::exchange(rhs.handle, nullptr);
|
|
|
+ dld = rhs.dld;
|
|
|
+ return *this;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Destroys the current handle if it existed.
|
|
|
+ ~Handle() noexcept {
|
|
|
+ Release();
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Destroys any held object.
|
|
|
+ void reset() noexcept {
|
|
|
+ Release();
|
|
|
+ handle = nullptr;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Returns the address of the held object.
|
|
|
+ /// Intended for Vulkan structures that expect a pointer to an array.
|
|
|
+ const Type* address() const noexcept {
|
|
|
+ return &handle;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Returns the held Vulkan handle.
|
|
|
+ Type operator*() const noexcept {
|
|
|
+ return handle;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Returns true when there's a held object.
|
|
|
+ operator bool() const noexcept {
|
|
|
+ return handle != nullptr;
|
|
|
+ }
|
|
|
+
|
|
|
+protected:
|
|
|
+ Type handle = nullptr;
|
|
|
+ const Dispatch* dld = nullptr;
|
|
|
+
|
|
|
+private:
|
|
|
+ /// Destroys the held object if it exists.
|
|
|
+ void Release() noexcept {
|
|
|
+ if (handle) {
|
|
|
+ Destroy(handle, *dld);
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
} // namespace Vulkan::vk
|