summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/video_core/renderer_vulkan/wrapper.h144
1 files changed, 144 insertions, 0 deletions
diff --git a/src/video_core/renderer_vulkan/wrapper.h b/src/video_core/renderer_vulkan/wrapper.h
index e5d9b34f2..5c6729dbc 100644
--- a/src/video_core/renderer_vulkan/wrapper.h
+++ b/src/video_core/renderer_vulkan/wrapper.h
@@ -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