|  | // Copyright 2018 The SwiftShader Authors. All Rights Reserved. | 
|  | // | 
|  | // 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. | 
|  |  | 
|  | #ifndef VK_OBJECT_HPP_ | 
|  | #define VK_OBJECT_HPP_ | 
|  |  | 
|  | #include "VkConfig.h" | 
|  | #include "VkDebug.hpp" | 
|  | #include "VkMemory.h" | 
|  | #include <vulkan/vulkan.h> | 
|  | #include <vulkan/vk_icd.h> | 
|  |  | 
|  | namespace vk | 
|  | { | 
|  | // For use in the placement new to make it verbose that we're allocating an object using device memory | 
|  | static constexpr VkAllocationCallbacks* DEVICE_MEMORY = nullptr; | 
|  |  | 
|  | template<typename T, typename VkT, typename CreateInfo> | 
|  | static VkResult Create(const VkAllocationCallbacks* pAllocator, const CreateInfo* pCreateInfo, VkT* outObject) | 
|  | { | 
|  | *outObject = VK_NULL_HANDLE; | 
|  |  | 
|  | size_t size = T::ComputeRequiredAllocationSize(pCreateInfo); | 
|  | void* memory = nullptr; | 
|  | if(size) | 
|  | { | 
|  | memory = vk::allocate(size, REQUIRED_MEMORY_ALIGNMENT, pAllocator, T::GetAllocationScope()); | 
|  | if(!memory) | 
|  | { | 
|  | return VK_ERROR_OUT_OF_HOST_MEMORY; | 
|  | } | 
|  | } | 
|  |  | 
|  | auto object = new (pAllocator) T(pCreateInfo, memory); | 
|  |  | 
|  | if(!object) | 
|  | { | 
|  | vk::deallocate(memory, pAllocator); | 
|  | return VK_ERROR_OUT_OF_HOST_MEMORY; | 
|  | } | 
|  |  | 
|  | *outObject = *object; | 
|  |  | 
|  | return VK_SUCCESS; | 
|  | } | 
|  |  | 
|  | template<typename T, typename VkT> | 
|  | class ObjectBase | 
|  | { | 
|  | public: | 
|  | using VkType = VkT; | 
|  |  | 
|  | void destroy(const VkAllocationCallbacks* pAllocator) {} // Method defined by objects to delete their content, if necessary | 
|  |  | 
|  | void* operator new(size_t count, const VkAllocationCallbacks* pAllocator) | 
|  | { | 
|  | return vk::allocate(count, alignof(T), pAllocator, T::GetAllocationScope()); | 
|  | } | 
|  |  | 
|  | void operator delete(void* ptr, const VkAllocationCallbacks* pAllocator) | 
|  | { | 
|  | // Should never happen | 
|  | ASSERT(false); | 
|  | } | 
|  |  | 
|  | template<typename CreateInfo> | 
|  | static VkResult Create(const VkAllocationCallbacks* pAllocator, const CreateInfo* pCreateInfo, VkT* outObject) | 
|  | { | 
|  | return vk::Create<T, VkT, CreateInfo>(pAllocator, pCreateInfo, outObject); | 
|  | } | 
|  |  | 
|  | static constexpr VkSystemAllocationScope GetAllocationScope() { return VK_SYSTEM_ALLOCATION_SCOPE_OBJECT; } | 
|  |  | 
|  | protected: | 
|  | // All derived classes should have deleted destructors | 
|  | ~ObjectBase() {} | 
|  | }; | 
|  |  | 
|  | template<typename T, typename VkT> | 
|  | class Object : public ObjectBase<T, VkT> | 
|  | { | 
|  | public: | 
|  | operator VkT() | 
|  | { | 
|  | return reinterpret_cast<VkT>(this); | 
|  | } | 
|  | }; | 
|  |  | 
|  | template<typename T, typename VkT> | 
|  | class DispatchableObject | 
|  | { | 
|  | VK_LOADER_DATA loaderData = { ICD_LOADER_MAGIC }; | 
|  |  | 
|  | T object; | 
|  | public: | 
|  | static constexpr VkSystemAllocationScope GetAllocationScope() { return T::GetAllocationScope(); } | 
|  |  | 
|  | template<typename ...Args> | 
|  | DispatchableObject(Args... args) : object(args...) | 
|  | { | 
|  | } | 
|  |  | 
|  | ~DispatchableObject() = delete; | 
|  |  | 
|  | void destroy(const VkAllocationCallbacks* pAllocator) | 
|  | { | 
|  | object.destroy(pAllocator); | 
|  | } | 
|  |  | 
|  | void* operator new(size_t count, const VkAllocationCallbacks* pAllocator) | 
|  | { | 
|  | return vk::allocate(count, alignof(T), pAllocator, T::GetAllocationScope()); | 
|  | } | 
|  |  | 
|  | void operator delete(void* ptr, const VkAllocationCallbacks* pAllocator) | 
|  | { | 
|  | // Should never happen | 
|  | ASSERT(false); | 
|  | } | 
|  |  | 
|  | template<typename CreateInfo> | 
|  | static VkResult Create(const VkAllocationCallbacks* pAllocator, const CreateInfo* pCreateInfo, VkT* outObject) | 
|  | { | 
|  | return vk::Create<DispatchableObject<T, VkT>, VkT, CreateInfo>(pAllocator, pCreateInfo, outObject); | 
|  | } | 
|  |  | 
|  | template<typename CreateInfo> | 
|  | static size_t ComputeRequiredAllocationSize(const CreateInfo* pCreateInfo) | 
|  | { | 
|  | return T::ComputeRequiredAllocationSize(pCreateInfo); | 
|  | } | 
|  |  | 
|  | static inline T* Cast(VkT vkObject) | 
|  | { | 
|  | return &(reinterpret_cast<DispatchableObject<T, VkT>*>(vkObject)->object); | 
|  | } | 
|  |  | 
|  | operator VkT() | 
|  | { | 
|  | return reinterpret_cast<VkT>(this); | 
|  | } | 
|  | }; | 
|  |  | 
|  | } // namespace vk | 
|  |  | 
|  | #endif // VK_OBJECT_HPP_ |