renderer_vulkan/wrapper: Add owning handle templated class

merge-requests/60/head
ReinUsesLisp 2020-03-27 02:55:07 +07:00
parent 60f351084a
commit d8d392b39a
1 changed files with 144 additions and 0 deletions

@ -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