| #ifndef _VKREF_HPP |
| #define _VKREF_HPP |
| /*------------------------------------------------------------------------- |
| * Vulkan CTS Framework |
| * -------------------- |
| * |
| * Copyright (c) 2015 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| *//*! |
| * \file |
| * \brief Vulkan object reference holder. |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "vkDefs.hpp" |
| #include "vkStrUtil.hpp" |
| #include "deMeta.hpp" |
| |
| #include <algorithm> |
| |
| namespace vk |
| { |
| |
| namespace refdetails |
| { |
| |
| using std::swap; |
| |
| template <typename T> |
| struct Checked |
| { |
| explicit inline Checked(T object_) : object(object_) |
| { |
| } |
| |
| T object; |
| }; |
| |
| //! Check that object is not null |
| template <typename T> |
| inline Checked<T> check(T object) |
| { |
| if (!object) |
| throw tcu::TestError("Object check() failed", (std::string(getTypeName<T>()) + " = 0").c_str(), __FILE__, |
| __LINE__); |
| return Checked<T>(object); |
| } |
| |
| //! Declare object as checked earlier |
| template <typename T> |
| inline Checked<T> notNull(T object) |
| { |
| if (!object) |
| throw tcu::InternalError("Null object was given to notNull()", (std::string(getTypeName<T>()) + " = 0").c_str(), |
| __FILE__, __LINE__); |
| return Checked<T>(object); |
| } |
| |
| //! Allow null object |
| template <typename T> |
| inline Checked<T> allowNull(T object) |
| { |
| return Checked<T>(object); |
| } |
| |
| template <typename T> |
| class Deleter |
| { |
| public: |
| Deleter(const DeviceInterface &deviceIface, VkDevice device, const VkAllocationCallbacks *allocator) |
| : m_deviceIface(&deviceIface) |
| , m_device(device) |
| , m_allocator(allocator) |
| { |
| } |
| Deleter(void) : m_deviceIface(DE_NULL), m_device(DE_NULL), m_allocator(DE_NULL) |
| { |
| } |
| |
| void operator()(T obj) const; |
| |
| private: |
| const DeviceInterface *m_deviceIface; |
| VkDevice m_device; |
| const VkAllocationCallbacks *m_allocator; |
| }; |
| |
| template <> |
| class Deleter<VkInstance> |
| { |
| public: |
| Deleter(const PlatformInterface &platformIface, VkInstance instance, const VkAllocationCallbacks *allocator) |
| : m_destroyInstance((DestroyInstanceFunc)platformIface.getInstanceProcAddr(instance, "vkDestroyInstance")) |
| , m_allocator(allocator) |
| { |
| } |
| Deleter(void) : m_destroyInstance((DestroyInstanceFunc)DE_NULL), m_allocator(DE_NULL) |
| { |
| } |
| |
| void operator()(VkInstance obj) const |
| { |
| m_destroyInstance(obj, m_allocator); |
| } |
| |
| private: |
| DestroyInstanceFunc m_destroyInstance; |
| const VkAllocationCallbacks *m_allocator; |
| }; |
| |
| template <> |
| class Deleter<VkDevice> |
| { |
| public: |
| Deleter(const PlatformInterface &platformIface, VkInstance instance, VkDevice device, |
| const VkAllocationCallbacks *allocator) |
| { |
| GetDeviceProcAddrFunc getDeviceProcAddr = |
| (GetDeviceProcAddrFunc)platformIface.getInstanceProcAddr(instance, "vkGetDeviceProcAddr"); |
| m_destroyDevice = (DestroyDeviceFunc)getDeviceProcAddr(device, "vkDestroyDevice"); |
| m_allocator = allocator; |
| } |
| Deleter(void) : m_destroyDevice((DestroyDeviceFunc)DE_NULL), m_allocator(DE_NULL) |
| { |
| } |
| |
| void operator()(VkDevice obj) const |
| { |
| m_destroyDevice(obj, m_allocator); |
| } |
| |
| private: |
| DestroyDeviceFunc m_destroyDevice; |
| const VkAllocationCallbacks *m_allocator; |
| }; |
| |
| template <> |
| class Deleter<VkSurfaceKHR> |
| { |
| public: |
| Deleter(const InstanceInterface &instanceIface, VkInstance instance, const VkAllocationCallbacks *allocator) |
| : m_instanceIface(&instanceIface) |
| , m_instance(instance) |
| , m_allocator(allocator) |
| { |
| } |
| Deleter(void) : m_instanceIface(DE_NULL), m_instance((VkInstance)0), m_allocator(DE_NULL) |
| { |
| } |
| |
| void operator()(VkSurfaceKHR obj) const |
| { |
| m_instanceIface->destroySurfaceKHR(m_instance, obj, m_allocator); |
| } |
| |
| private: |
| const InstanceInterface *m_instanceIface; |
| VkInstance m_instance; |
| const VkAllocationCallbacks *m_allocator; |
| }; |
| |
| #ifndef CTS_USES_VULKANSC |
| |
| template <> |
| class Deleter<VkDebugReportCallbackEXT> |
| { |
| public: |
| Deleter(const InstanceInterface &instanceIface, VkInstance instance, const VkAllocationCallbacks *allocator) |
| : m_instanceIface(&instanceIface) |
| , m_instance(instance) |
| , m_allocator(allocator) |
| { |
| } |
| Deleter(void) : m_instanceIface(DE_NULL), m_instance((VkInstance)0), m_allocator(DE_NULL) |
| { |
| } |
| |
| void operator()(VkDebugReportCallbackEXT obj) const |
| { |
| m_instanceIface->destroyDebugReportCallbackEXT(m_instance, obj, m_allocator); |
| } |
| |
| private: |
| const InstanceInterface *m_instanceIface; |
| VkInstance m_instance; |
| const VkAllocationCallbacks *m_allocator; |
| }; |
| |
| #endif // CTS_USES_VULKANSC |
| |
| template <> |
| class Deleter<VkDebugUtilsMessengerEXT> |
| { |
| public: |
| Deleter(const InstanceInterface &instanceIface, VkInstance instance, const VkAllocationCallbacks *allocator) |
| : m_instanceIface(&instanceIface) |
| , m_instance(instance) |
| , m_allocator(allocator) |
| { |
| } |
| Deleter(void) : m_instanceIface(DE_NULL), m_instance((VkInstance)0), m_allocator(DE_NULL) |
| { |
| } |
| |
| void operator()(VkDebugUtilsMessengerEXT obj) const |
| { |
| m_instanceIface->destroyDebugUtilsMessengerEXT(m_instance, obj, m_allocator); |
| } |
| |
| private: |
| const InstanceInterface *m_instanceIface; |
| VkInstance m_instance; |
| const VkAllocationCallbacks *m_allocator; |
| }; |
| |
| template <> |
| class Deleter<VkDescriptorSet> |
| { |
| public: |
| Deleter(const DeviceInterface &deviceIface, VkDevice device, VkDescriptorPool pool) |
| : m_deviceIface(&deviceIface) |
| , m_device(device) |
| , m_pool(pool) |
| { |
| } |
| Deleter(void) : m_deviceIface(DE_NULL), m_device(DE_NULL), m_pool(DE_NULL) |
| { |
| } |
| |
| void operator()(VkDescriptorSet obj) const |
| { |
| m_deviceIface->freeDescriptorSets(m_device, m_pool, 1, &obj); |
| } |
| |
| private: |
| const DeviceInterface *m_deviceIface; |
| VkDevice m_device; |
| VkDescriptorPool m_pool; |
| }; |
| |
| template <> |
| class Deleter<VkCommandBuffer> |
| { |
| public: |
| Deleter(const DeviceInterface &deviceIface, VkDevice device, VkCommandPool pool) |
| : m_deviceIface(&deviceIface) |
| , m_device(device) |
| , m_pool(pool) |
| { |
| } |
| Deleter(void) : m_deviceIface(DE_NULL), m_device(DE_NULL), m_pool(DE_NULL) |
| { |
| } |
| |
| void operator()(VkCommandBuffer obj) const |
| { |
| m_deviceIface->freeCommandBuffers(m_device, m_pool, 1, &obj); |
| } |
| |
| private: |
| const DeviceInterface *m_deviceIface; |
| VkDevice m_device; |
| VkCommandPool m_pool; |
| }; |
| |
| template <typename T> |
| struct RefData |
| { |
| RefData(T object_, Deleter<T> deleter_) : object(object_), deleter(deleter_) |
| { |
| } |
| RefData(void) : object(0) |
| { |
| } |
| |
| T object; |
| Deleter<T> deleter; |
| }; |
| |
| template <typename T> |
| class RefBase |
| { |
| public: |
| ~RefBase(void); |
| |
| inline const T &get(void) const throw() |
| { |
| return m_data.object; |
| } |
| inline const T &operator*(void) const throw() |
| { |
| return get(); |
| } |
| inline operator bool(void) const throw() |
| { |
| return !!get(); |
| } |
| |
| protected: |
| RefBase(RefData<T> data) : m_data(data) |
| { |
| } |
| |
| void reset(void); //!< Release previous object, set to null. |
| RefData<T> disown(void) throw(); //!< Disown and return object (ownership transferred to caller). |
| void assign(RefData<T> data); //!< Set new pointer, release previous pointer. |
| |
| private: |
| RefData<T> m_data; |
| }; |
| |
| template <typename T> |
| inline RefBase<T>::~RefBase(void) |
| { |
| this->reset(); |
| } |
| |
| template <typename T> |
| inline void RefBase<T>::reset(void) |
| { |
| if (!!m_data.object) |
| m_data.deleter(m_data.object); |
| |
| m_data = RefData<T>(); |
| } |
| |
| template <typename T> |
| inline RefData<T> RefBase<T>::disown(void) throw() |
| { |
| RefData<T> tmp; |
| swap(m_data, tmp); |
| return tmp; |
| } |
| |
| template <typename T> |
| inline void RefBase<T>::assign(RefData<T> data) |
| { |
| this->reset(); |
| m_data = data; |
| } |
| |
| /*--------------------------------------------------------------------*//*! |
| * \brief Movable Vulkan object reference. |
| * |
| * Similar to de::MovePtr. |
| *//*--------------------------------------------------------------------*/ |
| template <typename T> |
| class Move : public RefBase<T> |
| { |
| public: |
| template <typename U> |
| Move(Checked<U> object, Deleter<U> deleter) : RefBase<T>(RefData<T>(object.object, deleter)) |
| { |
| } |
| |
| Move(RefData<T> data) : RefBase<T>(data) |
| { |
| } |
| Move(Move<T> &other) : RefBase<T>(other.RefBase<T>::disown()) |
| { |
| } |
| Move(void) : RefBase<T>(RefData<T>()) |
| { |
| } |
| |
| T disown(void) |
| { |
| return this->RefBase<T>::disown().object; |
| } |
| Move<T> &operator=(Move<T> &other); |
| Move<T> &operator=(RefData<T> data); |
| |
| operator RefData<T>(void) |
| { |
| return this->RefBase<T>::disown(); |
| } |
| }; |
| |
| template <typename T> |
| inline Move<T> &Move<T>::operator=(Move<T> &other) |
| { |
| if (this != &other) |
| this->assign(other.RefBase<T>::disown()); |
| |
| return *this; |
| } |
| |
| template <typename T> |
| inline Move<T> &Move<T>::operator=(RefData<T> data) |
| { |
| this->assign(data); |
| return *this; |
| } |
| |
| /*--------------------------------------------------------------------*//*! |
| * \brief Unique Vulkan object reference. |
| * |
| * Similar to de::UniquePtr. |
| *//*--------------------------------------------------------------------*/ |
| template <typename T> |
| class Unique : public RefBase<T> |
| { |
| public: |
| template <typename U> |
| Unique(Checked<U> object, Deleter<U> deleter) : RefBase<T>(RefData<T>(object.object, deleter)) |
| { |
| } |
| |
| Unique(RefData<T> data) : RefBase<T>(data) |
| { |
| } |
| |
| private: |
| Unique(const Unique<T> &); |
| Unique<T> &operator=(const Unique<T> &); |
| }; |
| |
| } // namespace refdetails |
| |
| using refdetails::allowNull; |
| using refdetails::check; |
| using refdetails::Deleter; |
| using refdetails::Move; |
| using refdetails::notNull; |
| using refdetails::Unique; |
| |
| } // namespace vk |
| |
| #endif // _VKREF_HPP |