#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 namespace vk { namespace refdetails { using std::swap; template struct Checked { explicit inline Checked (T object_) : object(object_) {} T object; }; //! Check that object is not null template inline Checked check (T object) { if (!object) throw tcu::TestError("Object check() failed", (std::string(getTypeName()) + " = 0").c_str(), __FILE__, __LINE__); return Checked(object); } //! Declare object as checked earlier template inline Checked notNull (T object) { if (!object) throw tcu::InternalError("Null object was given to notNull()", (std::string(getTypeName()) + " = 0").c_str(), __FILE__, __LINE__); return Checked(object); } //! Allow null object template inline Checked allowNull (T object) { return Checked(object); } template 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 { 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 { 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 { 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; }; template<> class Deleter { 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; }; template<> class Deleter { 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 { 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 { 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 struct RefData { RefData (T object_, Deleter deleter_) : object (object_) , deleter (deleter_) {} RefData (void) : object (0) {} T object; Deleter deleter; }; template 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 data) : m_data(data) {} void reset (void); //!< Release previous object, set to null. RefData disown (void) throw(); //!< Disown and return object (ownership transferred to caller). void assign (RefData data); //!< Set new pointer, release previous pointer. private: RefData m_data; }; template inline RefBase::~RefBase (void) { this->reset(); } template inline void RefBase::reset (void) { if (!!m_data.object) m_data.deleter(m_data.object); m_data = RefData(); } template inline RefData RefBase::disown (void) throw() { RefData tmp; swap(m_data, tmp); return tmp; } template inline void RefBase::assign (RefData data) { this->reset(); m_data = data; } /*--------------------------------------------------------------------*//*! * \brief Movable Vulkan object reference. * * Similar to de::MovePtr. *//*--------------------------------------------------------------------*/ template class Move : public RefBase { public: template Move (Checked object, Deleter deleter) : RefBase(RefData(object.object, deleter)) {} Move (RefData data) : RefBase(data) {} Move (Move& other) : RefBase(other.RefBase::disown()) {} Move (void) : RefBase(RefData()) {} T disown (void) { return this->RefBase::disown().object; } Move& operator= (Move& other); Move& operator= (RefData data); operator RefData (void) { return this->RefBase::disown(); } }; template inline Move& Move::operator= (Move& other) { if (this != &other) this->assign(other.RefBase::disown()); return *this; } template inline Move& Move::operator= (RefData data) { this->assign(data); return *this; } /*--------------------------------------------------------------------*//*! * \brief Unique Vulkan object reference. * * Similar to de::UniquePtr. *//*--------------------------------------------------------------------*/ template class Unique : public RefBase { public: template Unique (Checked object, Deleter deleter) : RefBase(RefData(object.object, deleter)) {} Unique (RefData data) : RefBase(data) {} private: Unique (const Unique&); Unique& operator= (const Unique&); }; } // refdetails using refdetails::Move; using refdetails::Unique; using refdetails::Deleter; using refdetails::check; using refdetails::notNull; using refdetails::allowNull; } // vk #endif // _VKREF_HPP