renderer_vulkan/wrapper: Add owning handle templated class
This commit is contained in:
parent
60f351084a
commit
d8d392b39a
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue