• 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 #include "VkDeviceMemory.hpp"
16 #include "VkBuffer.hpp"
17 #include "VkImage.hpp"
18 
19 #include "VkConfig.h"
20 
21 namespace vk {
22 
23 // Base abstract interface for a device memory implementation.
24 class DeviceMemory::ExternalBase
25 {
26 public:
27 	virtual ~ExternalBase() = default;
28 
29 	// Allocate the memory according to |size|. On success return VK_SUCCESS
30 	// and sets |*pBuffer|.
31 	virtual VkResult allocate(size_t size, void **pBuffer) = 0;
32 
33 	// Deallocate previously allocated memory at |buffer|.
34 	virtual void deallocate(void *buffer, size_t size) = 0;
35 
36 	// Return the handle type flag bit supported by this implementation.
37 	// A value of 0 corresponds to non-external memory.
38 	virtual VkExternalMemoryHandleTypeFlagBits getFlagBit() const = 0;
39 
40 #if SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD
exportFd(int * pFd) const41 	virtual VkResult exportFd(int *pFd) const
42 	{
43 		return VK_ERROR_INVALID_EXTERNAL_HANDLE;
44 	}
45 #endif
46 
47 #if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
exportAhb(struct AHardwareBuffer ** pAhb) const48 	virtual VkResult exportAhb(struct AHardwareBuffer **pAhb) const
49 	{
50 		return VK_ERROR_INVALID_EXTERNAL_HANDLE;
51 	}
52 #endif
53 
54 protected:
55 	ExternalBase() = default;
56 };
57 
58 // Small class describing a given DeviceMemory::ExternalBase derived class.
59 // |typeFlagBit| corresponds to the external memory handle type.
60 // |instanceSize| is the size of each class instance in bytes.
61 // |instanceInit| is a function pointer used to initialize an instance inplace
62 // according to a |pAllocateInfo| parameter.
63 class ExternalMemoryTraits
64 {
65 public:
66 	VkExternalMemoryHandleTypeFlagBits typeFlagBit;
67 	size_t instanceSize;
68 	void (*instanceInit)(void *external, const VkMemoryAllocateInfo *pAllocateInfo);
69 };
70 
71 // Template function that parses a |pAllocateInfo.pNext| chain to verify that
72 // it asks for the creation or import of a memory type managed by implementation
73 // class T. On success, return true and sets |pTraits| accordingly. Otherwise
74 // return false.
75 template<typename T>
parseCreateInfo(const VkMemoryAllocateInfo * pAllocateInfo,ExternalMemoryTraits * pTraits)76 static bool parseCreateInfo(const VkMemoryAllocateInfo *pAllocateInfo,
77                             ExternalMemoryTraits *pTraits)
78 {
79 	if(T::supportsAllocateInfo(pAllocateInfo))
80 	{
81 		pTraits->typeFlagBit = T::typeFlagBit;
82 		pTraits->instanceSize = sizeof(T);
83 		pTraits->instanceInit = [](void *external,
84 		                           const VkMemoryAllocateInfo *pAllocateInfo) {
85 			new(external) T(pAllocateInfo);
86 		};
87 		return true;
88 	}
89 	return false;
90 }
91 
92 // DeviceMemory::ExternalBase implementation that uses host memory.
93 // Not really external, but makes everything simpler.
94 class DeviceMemoryHostExternalBase : public DeviceMemory::ExternalBase
95 {
96 public:
97 	// Does not support any external memory type at all.
98 	static const VkExternalMemoryHandleTypeFlagBits typeFlagBit = (VkExternalMemoryHandleTypeFlagBits)0;
99 
100 	// Always return true as is used as a fallback in findTraits() below.
supportsAllocateInfo(const VkMemoryAllocateInfo * pAllocateInfo)101 	static bool supportsAllocateInfo(const VkMemoryAllocateInfo *pAllocateInfo)
102 	{
103 		return true;
104 	}
105 
DeviceMemoryHostExternalBase(const VkMemoryAllocateInfo * pAllocateInfo)106 	DeviceMemoryHostExternalBase(const VkMemoryAllocateInfo *pAllocateInfo) {}
107 
allocate(size_t size,void ** pBuffer)108 	VkResult allocate(size_t size, void **pBuffer) override
109 	{
110 		void *buffer = vk::allocate(size, REQUIRED_MEMORY_ALIGNMENT, DEVICE_MEMORY);
111 		if(!buffer)
112 		{
113 			return VK_ERROR_OUT_OF_DEVICE_MEMORY;
114 		}
115 
116 		*pBuffer = buffer;
117 		return VK_SUCCESS;
118 	}
119 
deallocate(void * buffer,size_t size)120 	void deallocate(void *buffer, size_t size) override
121 	{
122 		vk::deallocate(buffer, DEVICE_MEMORY);
123 	}
124 
getFlagBit() const125 	VkExternalMemoryHandleTypeFlagBits getFlagBit() const override
126 	{
127 		return typeFlagBit;
128 	}
129 };
130 
131 }  // namespace vk
132 
133 // Host-allocated memory and host-mapped foreign memory
134 class ExternalMemoryHost : public vk::DeviceMemory::ExternalBase
135 {
136 public:
137 	struct AllocateInfo
138 	{
139 		bool supported = false;
140 		void *hostPointer = nullptr;
141 
142 		AllocateInfo() = default;
143 
AllocateInfoExternalMemoryHost::AllocateInfo144 		AllocateInfo(const VkMemoryAllocateInfo *pAllocateInfo)
145 		{
146 			const auto *createInfo = reinterpret_cast<const VkBaseInStructure *>(pAllocateInfo->pNext);
147 			while(createInfo)
148 			{
149 				switch(createInfo->sType)
150 				{
151 					case VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT:
152 					{
153 						const auto *importInfo = reinterpret_cast<const VkImportMemoryHostPointerInfoEXT *>(createInfo);
154 
155 						if(importInfo->handleType != VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT && importInfo->handleType != VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT)
156 						{
157 							UNSUPPORTED("importInfo->handleType");
158 						}
159 						hostPointer = importInfo->pHostPointer;
160 						supported = true;
161 						break;
162 					}
163 					default:
164 						break;
165 				}
166 				createInfo = createInfo->pNext;
167 			}
168 		}
169 	};
170 
171 	static const VkExternalMemoryHandleTypeFlagBits typeFlagBit = (VkExternalMemoryHandleTypeFlagBits)(VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT | VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT);
172 
supportsAllocateInfo(const VkMemoryAllocateInfo * pAllocateInfo)173 	static bool supportsAllocateInfo(const VkMemoryAllocateInfo *pAllocateInfo)
174 	{
175 		AllocateInfo info(pAllocateInfo);
176 		return info.supported;
177 	}
178 
ExternalMemoryHost(const VkMemoryAllocateInfo * pAllocateInfo)179 	explicit ExternalMemoryHost(const VkMemoryAllocateInfo *pAllocateInfo)
180 	    : allocateInfo(pAllocateInfo)
181 	{
182 	}
183 
allocate(size_t size,void ** pBuffer)184 	VkResult allocate(size_t size, void **pBuffer) override
185 	{
186 		if(allocateInfo.supported)
187 		{
188 			*pBuffer = allocateInfo.hostPointer;
189 			return VK_SUCCESS;
190 		}
191 		return VK_ERROR_INVALID_EXTERNAL_HANDLE;
192 	}
193 
deallocate(void * buffer,size_t size)194 	void deallocate(void *buffer, size_t size) override
195 	{}
196 
getFlagBit() const197 	VkExternalMemoryHandleTypeFlagBits getFlagBit() const override
198 	{
199 		return typeFlagBit;
200 	}
201 
202 private:
203 	AllocateInfo allocateInfo;
204 };
205 
206 #if SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD
207 #	if defined(__linux__) || defined(__ANDROID__)
208 #		include "VkDeviceMemoryExternalLinux.hpp"
209 #	else
210 #		error "Missing VK_KHR_external_memory_fd implementation for this platform!"
211 #	endif
212 #endif
213 
214 #if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
215 #	if defined(__ANDROID__)
216 #		include "VkDeviceMemoryExternalAndroid.hpp"
217 #	else
218 #		error "Missing VK_ANDROID_external_memory_android_hardware_buffer implementation for this platform!"
219 #	endif
220 #endif
221 
222 namespace vk {
223 
findTraits(const VkMemoryAllocateInfo * pAllocateInfo,ExternalMemoryTraits * pTraits)224 static void findTraits(const VkMemoryAllocateInfo *pAllocateInfo,
225                        ExternalMemoryTraits *pTraits)
226 {
227 #if SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD
228 	if(parseCreateInfo<OpaqueFdExternalMemory>(pAllocateInfo, pTraits))
229 	{
230 		return;
231 	}
232 #endif
233 #if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
234 	if(parseCreateInfo<AHardwareBufferExternalMemory>(pAllocateInfo, pTraits))
235 	{
236 		return;
237 	}
238 #endif
239 	if(parseCreateInfo<ExternalMemoryHost>(pAllocateInfo, pTraits))
240 	{
241 		return;
242 	}
243 	parseCreateInfo<DeviceMemoryHostExternalBase>(pAllocateInfo, pTraits);
244 }
245 
DeviceMemory(const VkMemoryAllocateInfo * pAllocateInfo,void * mem)246 DeviceMemory::DeviceMemory(const VkMemoryAllocateInfo *pAllocateInfo, void *mem)
247     : size(pAllocateInfo->allocationSize)
248     , memoryTypeIndex(pAllocateInfo->memoryTypeIndex)
249     , external(reinterpret_cast<ExternalBase *>(mem))
250 {
251 	ASSERT(size);
252 
253 	ExternalMemoryTraits traits;
254 	findTraits(pAllocateInfo, &traits);
255 	traits.instanceInit(external, pAllocateInfo);
256 }
257 
destroy(const VkAllocationCallbacks * pAllocator)258 void DeviceMemory::destroy(const VkAllocationCallbacks *pAllocator)
259 {
260 	if(buffer)
261 	{
262 		external->deallocate(buffer, size);
263 		buffer = nullptr;
264 	}
265 	external->~ExternalBase();  // Call virtual destructor in place.
266 	vk::deallocate(external, pAllocator);
267 }
268 
ComputeRequiredAllocationSize(const VkMemoryAllocateInfo * pAllocateInfo)269 size_t DeviceMemory::ComputeRequiredAllocationSize(const VkMemoryAllocateInfo *pAllocateInfo)
270 {
271 	ExternalMemoryTraits traits;
272 	findTraits(pAllocateInfo, &traits);
273 	return traits.instanceSize;
274 }
275 
allocate()276 VkResult DeviceMemory::allocate()
277 {
278 	if(size > MAX_MEMORY_ALLOCATION_SIZE)
279 	{
280 		return VK_ERROR_OUT_OF_DEVICE_MEMORY;
281 	}
282 
283 	VkResult result = VK_SUCCESS;
284 	if(!buffer)
285 	{
286 		result = external->allocate(size, &buffer);
287 	}
288 	return result;
289 }
290 
map(VkDeviceSize pOffset,VkDeviceSize pSize,void ** ppData)291 VkResult DeviceMemory::map(VkDeviceSize pOffset, VkDeviceSize pSize, void **ppData)
292 {
293 	*ppData = getOffsetPointer(pOffset);
294 
295 	return VK_SUCCESS;
296 }
297 
getCommittedMemoryInBytes() const298 VkDeviceSize DeviceMemory::getCommittedMemoryInBytes() const
299 {
300 	return size;
301 }
302 
getOffsetPointer(VkDeviceSize pOffset) const303 void *DeviceMemory::getOffsetPointer(VkDeviceSize pOffset) const
304 {
305 	ASSERT(buffer);
306 
307 	return reinterpret_cast<char *>(buffer) + pOffset;
308 }
309 
checkExternalMemoryHandleType(VkExternalMemoryHandleTypeFlags supportedHandleTypes) const310 bool DeviceMemory::checkExternalMemoryHandleType(
311     VkExternalMemoryHandleTypeFlags supportedHandleTypes) const
312 {
313 	if(!supportedHandleTypes)
314 	{
315 		// This image or buffer does not need to be stored on external
316 		// memory, so this check should always pass.
317 		return true;
318 	}
319 	VkExternalMemoryHandleTypeFlagBits handle_type_bit = external->getFlagBit();
320 	if(!handle_type_bit)
321 	{
322 		// This device memory is not external and can accomodate
323 		// any image or buffer as well.
324 		return true;
325 	}
326 	// Return true only if the external memory type is compatible with the
327 	// one specified during VkCreate{Image,Buffer}(), through a
328 	// VkExternalMemory{Image,Buffer}AllocateInfo struct.
329 	return (supportedHandleTypes & handle_type_bit) != 0;
330 }
331 
332 #if SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD
exportFd(int * pFd) const333 VkResult DeviceMemory::exportFd(int *pFd) const
334 {
335 	return external->exportFd(pFd);
336 }
337 #endif
338 
339 #if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
exportAhb(struct AHardwareBuffer ** pAhb) const340 VkResult DeviceMemory::exportAhb(struct AHardwareBuffer **pAhb) const
341 {
342 	return external->exportAhb(pAhb);
343 }
344 
getAhbProperties(const struct AHardwareBuffer * buffer,VkAndroidHardwareBufferPropertiesANDROID * pProperties)345 VkResult DeviceMemory::getAhbProperties(const struct AHardwareBuffer *buffer, VkAndroidHardwareBufferPropertiesANDROID *pProperties)
346 {
347 	return AHardwareBufferExternalMemory::getAhbProperties(buffer, pProperties);
348 }
349 #endif
350 
351 }  // namespace vk
352