• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef VK_OBJECT_HPP_
16 #define VK_OBJECT_HPP_
17 
18 #include "VkConfig.hpp"
19 #include "VkMemory.hpp"
20 #include "System/Debug.hpp"
21 
22 #include <vulkan/vk_icd.h>
23 #undef None
24 #undef Bool
25 
26 #include <new>
27 
28 namespace vk {
29 
30 template<typename T, typename VkT>
VkTtoT(VkT vkObject)31 static inline T *VkTtoT(VkT vkObject)
32 {
33 	return static_cast<T *>(static_cast<void *>(vkObject));
34 }
35 
36 template<typename T, typename VkT>
TtoVkT(T * object)37 static inline VkT TtoVkT(T *object)
38 {
39 	return { static_cast<uint64_t>(reinterpret_cast<uintptr_t>(object)) };
40 }
41 
42 template<typename T, typename VkT, typename CreateInfo, typename... ExtendedInfo>
Create(const VkAllocationCallbacks * pAllocator,const CreateInfo * pCreateInfo,VkT * outObject,ExtendedInfo...extendedInfo)43 static VkResult Create(const VkAllocationCallbacks *pAllocator, const CreateInfo *pCreateInfo, VkT *outObject, ExtendedInfo... extendedInfo)
44 {
45 	*outObject = VK_NULL_HANDLE;
46 
47 	size_t size = T::ComputeRequiredAllocationSize(pCreateInfo);
48 	void *memory = nullptr;
49 	if(size)
50 	{
51 		memory = vk::allocateHostMemory(size, vk::HOST_MEMORY_ALLOCATION_ALIGNMENT, pAllocator, T::GetAllocationScope());
52 		if(!memory)
53 		{
54 			return VK_ERROR_OUT_OF_HOST_MEMORY;
55 		}
56 	}
57 
58 	void *objectMemory = vk::allocateHostMemory(sizeof(T), alignof(T), pAllocator, T::GetAllocationScope());
59 	if(!objectMemory)
60 	{
61 		vk::freeHostMemory(memory, pAllocator);
62 		return VK_ERROR_OUT_OF_HOST_MEMORY;
63 	}
64 
65 	auto object = new(objectMemory) T(pCreateInfo, memory, extendedInfo...);
66 
67 	if(!object)
68 	{
69 		vk::freeHostMemory(memory, pAllocator);
70 		return VK_ERROR_OUT_OF_HOST_MEMORY;
71 	}
72 
73 	*outObject = *object;
74 
75 	// Assert that potential v-table offsets from multiple inheritance aren't causing an offset on the handle
76 	ASSERT(*outObject == objectMemory);
77 
78 	return VK_SUCCESS;
79 }
80 
81 template<typename T, typename VkT>
82 class ObjectBase
83 {
84 public:
85 	using VkType = VkT;
86 
destroy(const VkAllocationCallbacks * pAllocator)87 	void destroy(const VkAllocationCallbacks *pAllocator) {}  // Method defined by objects to delete their content, if necessary
88 
89 	template<typename CreateInfo, typename... ExtendedInfo>
Create(const VkAllocationCallbacks * pAllocator,const CreateInfo * pCreateInfo,VkT * outObject,ExtendedInfo...extendedInfo)90 	static VkResult Create(const VkAllocationCallbacks *pAllocator, const CreateInfo *pCreateInfo, VkT *outObject, ExtendedInfo... extendedInfo)
91 	{
92 		return vk::Create<T, VkT, CreateInfo>(pAllocator, pCreateInfo, outObject, extendedInfo...);
93 	}
94 
GetAllocationScope()95 	static constexpr VkSystemAllocationScope GetAllocationScope() { return VK_SYSTEM_ALLOCATION_SCOPE_OBJECT; }
96 };
97 
98 template<typename T, typename VkT>
99 class Object : public ObjectBase<T, VkT>
100 {
101 public:
operator VkT()102 	operator VkT()
103 	{
104 		// The static_cast<T*> is used to make sure the returned pointer points to the
105 		// beginning of the object, even if the derived class uses multiple inheritance
106 		return vk::TtoVkT<T, VkT>(static_cast<T *>(this));
107 	}
108 
Cast(VkT vkObject)109 	static inline T *Cast(VkT vkObject)
110 	{
111 		return vk::VkTtoT<T, VkT>(vkObject);
112 	}
113 };
114 
115 template<typename T, typename VkT>
116 class DispatchableObject
117 {
118 	VK_LOADER_DATA loaderData = { ICD_LOADER_MAGIC };
119 
120 	T object;
121 
122 public:
GetAllocationScope()123 	static constexpr VkSystemAllocationScope GetAllocationScope() { return T::GetAllocationScope(); }
124 
125 	template<typename... Args>
DispatchableObject(Args...args)126 	DispatchableObject(Args... args)
127 	    : object(args...)
128 	{
129 	}
130 
131 	~DispatchableObject() = delete;
132 
destroy(const VkAllocationCallbacks * pAllocator)133 	void destroy(const VkAllocationCallbacks *pAllocator)
134 	{
135 		object.destroy(pAllocator);
136 	}
137 
operator delete(void * ptr,const VkAllocationCallbacks * pAllocator)138 	void operator delete(void *ptr, const VkAllocationCallbacks *pAllocator)
139 	{
140 		// Should never happen
141 		ASSERT(false);
142 	}
143 
144 	template<typename CreateInfo, typename... ExtendedInfo>
Create(const VkAllocationCallbacks * pAllocator,const CreateInfo * pCreateInfo,VkT * outObject,ExtendedInfo...extendedInfo)145 	static VkResult Create(const VkAllocationCallbacks *pAllocator, const CreateInfo *pCreateInfo, VkT *outObject, ExtendedInfo... extendedInfo)
146 	{
147 		return vk::Create<DispatchableObject<T, VkT>, VkT, CreateInfo>(pAllocator, pCreateInfo, outObject, extendedInfo...);
148 	}
149 
150 	template<typename CreateInfo>
ComputeRequiredAllocationSize(const CreateInfo * pCreateInfo)151 	static size_t ComputeRequiredAllocationSize(const CreateInfo *pCreateInfo)
152 	{
153 		return T::ComputeRequiredAllocationSize(pCreateInfo);
154 	}
155 
Cast(VkT vkObject)156 	static inline T *Cast(VkT vkObject)
157 	{
158 		return (vkObject == VK_NULL_HANDLE) ? nullptr : &(reinterpret_cast<DispatchableObject<T, VkT> *>(vkObject)->object);
159 	}
160 
operator VkT()161 	operator VkT()
162 	{
163 		return reinterpret_cast<VkT>(this);
164 	}
165 };
166 
167 template <typename T>
GetExtendedStruct(const void * pNext,VkStructureType sType)168 const T *GetExtendedStruct(const void *pNext, VkStructureType sType)
169 {
170 	const VkBaseInStructure *extendedStruct = reinterpret_cast<const VkBaseInStructure *>(pNext);
171 	while(extendedStruct)
172 	{
173 		if(extendedStruct->sType == sType)
174 		{
175 			return reinterpret_cast<const T *>(extendedStruct);
176 		}
177 
178 		extendedStruct = extendedStruct->pNext;
179 	}
180 
181 	return nullptr;
182 }
183 
184 }  // namespace vk
185 
186 #endif  // VK_OBJECT_HPP_
187