• 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 "VkDeviceMemoryExternalHost.hpp"
17 
18 #include "VkBuffer.hpp"
19 #include "VkConfig.hpp"
20 #include "VkDevice.hpp"
21 #include "VkImage.hpp"
22 #include "VkMemory.hpp"
23 #include "VkStringify.hpp"
24 
25 #if SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD
26 
27 // Helper struct which reads the parsed allocation info and
28 // extracts relevant information related to the handle type
29 // supported by this DeviceMemory subclass.
30 struct OpaqueFdAllocateInfo
31 {
32 	bool importFd = false;
33 	bool exportFd = false;
34 	int fd = -1;
35 
36 	OpaqueFdAllocateInfo() = default;
37 
38 	// Read the parsed allocation info to initialize an OpaqueFdAllocateInfo.
OpaqueFdAllocateInfoOpaqueFdAllocateInfo39 	OpaqueFdAllocateInfo(const vk::DeviceMemory::ExtendedAllocationInfo &extendedAllocationInfo)
40 	{
41 		if(extendedAllocationInfo.importMemoryFdInfo)
42 		{
43 			if(extendedAllocationInfo.importMemoryFdInfo->handleType != VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT)
44 			{
45 				UNSUPPORTED("VkImportMemoryFdInfoKHR::handleType %d", int(extendedAllocationInfo.importMemoryFdInfo->handleType));
46 			}
47 			importFd = true;
48 			fd = extendedAllocationInfo.importMemoryFdInfo->fd;
49 		}
50 
51 		if(extendedAllocationInfo.exportMemoryAllocateInfo)
52 		{
53 			if(extendedAllocationInfo.exportMemoryAllocateInfo->handleTypes != VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT)
54 			{
55 				UNSUPPORTED("VkExportMemoryAllocateInfo::handleTypes %d", int(extendedAllocationInfo.exportMemoryAllocateInfo->handleTypes));
56 			}
57 			exportFd = true;
58 		}
59 	}
60 };
61 
62 #	if defined(__APPLE__)
63 #		include "VkDeviceMemoryExternalMac.hpp"
64 #	elif defined(__linux__) && !defined(__ANDROID__)
65 #		include "VkDeviceMemoryExternalLinux.hpp"
66 #	else
67 #		error "Missing VK_KHR_external_memory_fd implementation for this platform!"
68 #	endif
69 #endif
70 
71 #if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
72 #	if defined(__ANDROID__)
73 #		include "VkDeviceMemoryExternalAndroid.hpp"
74 #	else
75 #		error "Missing VK_ANDROID_external_memory_android_hardware_buffer implementation for this platform!"
76 #	endif
77 #endif
78 
79 #if VK_USE_PLATFORM_FUCHSIA
80 #	include "VkDeviceMemoryExternalFuchsia.hpp"
81 #endif
82 
83 namespace vk {
84 
Allocate(const VkAllocationCallbacks * pAllocator,const VkMemoryAllocateInfo * pAllocateInfo,VkDeviceMemory * pMemory,Device * device)85 VkResult DeviceMemory::Allocate(const VkAllocationCallbacks *pAllocator, const VkMemoryAllocateInfo *pAllocateInfo, VkDeviceMemory *pMemory, Device *device)
86 {
87 	*pMemory = VK_NULL_HANDLE;
88 
89 	vk::DeviceMemory::ExtendedAllocationInfo extendedAllocationInfo = {};
90 	VkResult result = vk::DeviceMemory::ParseAllocationInfo(pAllocateInfo, &extendedAllocationInfo);
91 	if(result != VK_SUCCESS)
92 	{
93 		return result;
94 	}
95 
96 	result = Allocate(pAllocator, pAllocateInfo, pMemory, extendedAllocationInfo, device);
97 	if(result != VK_SUCCESS)
98 	{
99 		return result;
100 	}
101 
102 	// Make sure the memory allocation is done now so that OOM errors can be checked now
103 	return vk::Cast(*pMemory)->allocate();
104 }
105 
Allocate(const VkAllocationCallbacks * pAllocator,const VkMemoryAllocateInfo * pAllocateInfo,VkDeviceMemory * pMemory,const vk::DeviceMemory::ExtendedAllocationInfo & extendedAllocationInfo,Device * device)106 VkResult DeviceMemory::Allocate(const VkAllocationCallbacks *pAllocator, const VkMemoryAllocateInfo *pAllocateInfo, VkDeviceMemory *pMemory,
107                                 const vk::DeviceMemory::ExtendedAllocationInfo &extendedAllocationInfo, Device *device)
108 {
109 	VkMemoryAllocateInfo allocateInfo = *pAllocateInfo;
110 	// Add 15 bytes of padding to ensure that any type of attribute within
111 	// buffers and images can be read using 16-byte accesses.
112 	if(allocateInfo.allocationSize > UINT64_MAX - 15)
113 	{
114 		return VK_ERROR_OUT_OF_DEVICE_MEMORY;
115 	}
116 	allocateInfo.allocationSize += 15;
117 
118 #if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
119 	if(AHardwareBufferExternalMemory::SupportsAllocateInfo(extendedAllocationInfo))
120 	{
121 		return AHardwareBufferExternalMemory::Create(pAllocator, &allocateInfo, pMemory, extendedAllocationInfo, device);
122 	}
123 #endif
124 #if SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD
125 	if(OpaqueFdExternalMemory::SupportsAllocateInfo(extendedAllocationInfo))
126 	{
127 		return OpaqueFdExternalMemory::Create(pAllocator, &allocateInfo, pMemory, extendedAllocationInfo, device);
128 	}
129 #endif
130 #if VK_USE_PLATFORM_FUCHSIA
131 	if(zircon::VmoExternalMemory::supportsAllocateInfo(extendedAllocationInfo))
132 	{
133 		return zircon::VmoExternalMemory::Create(pAllocator, &allocateInfo, pMemory, extendedAllocationInfo, device);
134 	}
135 #endif
136 	if(ExternalMemoryHost::SupportsAllocateInfo(extendedAllocationInfo))
137 	{
138 		return ExternalMemoryHost::Create(pAllocator, &allocateInfo, pMemory, extendedAllocationInfo, device);
139 	}
140 
141 	return vk::DeviceMemoryInternal::Create(pAllocator, &allocateInfo, pMemory, extendedAllocationInfo, device);
142 }
143 
DeviceMemory(const VkMemoryAllocateInfo * pAllocateInfo,Device * pDevice)144 DeviceMemory::DeviceMemory(const VkMemoryAllocateInfo *pAllocateInfo, Device *pDevice)
145     : allocationSize(pAllocateInfo->allocationSize)
146     , memoryTypeIndex(pAllocateInfo->memoryTypeIndex)
147     , device(pDevice)
148 {
149 	ASSERT(allocationSize);
150 }
151 
destroy(const VkAllocationCallbacks * pAllocator)152 void DeviceMemory::destroy(const VkAllocationCallbacks *pAllocator)
153 {
154 #ifdef SWIFTSHADER_DEVICE_MEMORY_REPORT
155 	VkDeviceMemoryReportEventTypeEXT eventType = isImport() ? VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_UNIMPORT_EXT : VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_FREE_EXT;
156 	device->emitDeviceMemoryReport(eventType, getMemoryObjectId(), 0 /* size */, VK_OBJECT_TYPE_DEVICE_MEMORY, (uint64_t)(void *)VkDeviceMemory(*this));
157 #endif  // SWIFTSHADER_DEVICE_MEMORY_REPORT
158 
159 	if(buffer)
160 	{
161 		freeBuffer();
162 		buffer = nullptr;
163 	}
164 }
165 
ComputeRequiredAllocationSize(const VkMemoryAllocateInfo * pAllocateInfo)166 size_t DeviceMemory::ComputeRequiredAllocationSize(const VkMemoryAllocateInfo *pAllocateInfo)
167 {
168 	return 0;
169 }
170 
ParseAllocationInfo(const VkMemoryAllocateInfo * pAllocateInfo,DeviceMemory::ExtendedAllocationInfo * extendedAllocationInfo)171 VkResult DeviceMemory::ParseAllocationInfo(const VkMemoryAllocateInfo *pAllocateInfo, DeviceMemory::ExtendedAllocationInfo *extendedAllocationInfo)
172 {
173 	const VkBaseInStructure *allocationInfo = reinterpret_cast<const VkBaseInStructure *>(pAllocateInfo->pNext);
174 	while(allocationInfo)
175 	{
176 		switch(allocationInfo->sType)
177 		{
178 		case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO:
179 			// This can safely be ignored on most platforms, as the Vulkan spec mentions:
180 			// "If the pNext chain includes a VkMemoryDedicatedAllocateInfo structure, then that structure
181 			//  includes a handle of the sole buffer or image resource that the memory *can* be bound to."
182 #if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
183 			extendedAllocationInfo->dedicatedAllocateInfo = reinterpret_cast<const VkMemoryDedicatedAllocateInfo *>(allocationInfo);
184 #endif
185 			break;
186 		case VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO:
187 			// This extension controls on which physical devices the memory gets allocated.
188 			// SwiftShader only has a single physical device, so this extension does nothing in this case.
189 			break;
190 #if SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD
191 		case VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR:
192 			extendedAllocationInfo->importMemoryFdInfo = reinterpret_cast<const VkImportMemoryFdInfoKHR *>(allocationInfo);
193 			if(extendedAllocationInfo->importMemoryFdInfo->handleType != VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT)
194 			{
195 				UNSUPPORTED("extendedAllocationInfo->importMemoryFdInfo->handleType %u", extendedAllocationInfo->importMemoryFdInfo->handleType);
196 				return VK_ERROR_INVALID_EXTERNAL_HANDLE;
197 			}
198 			break;
199 #endif  // SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD
200 		case VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO:
201 			extendedAllocationInfo->exportMemoryAllocateInfo = reinterpret_cast<const VkExportMemoryAllocateInfo *>(allocationInfo);
202 			switch(extendedAllocationInfo->exportMemoryAllocateInfo->handleTypes)
203 			{
204 #if SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD
205 			case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
206 				break;
207 #endif
208 #if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
209 			case VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID:
210 				break;
211 #endif
212 #if VK_USE_PLATFORM_FUCHSIA
213 			case VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA:
214 				break;
215 #endif
216 			default:
217 				UNSUPPORTED("extendedAllocationInfo->exportMemoryAllocateInfo->handleTypes %u", extendedAllocationInfo->exportMemoryAllocateInfo->handleTypes);
218 				return VK_ERROR_INVALID_EXTERNAL_HANDLE;
219 			}
220 			break;
221 #if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
222 		case VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID:
223 			extendedAllocationInfo->importAndroidHardwareBufferInfo = reinterpret_cast<const VkImportAndroidHardwareBufferInfoANDROID *>(allocationInfo);
224 			break;
225 #endif  // SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
226 		case VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT:
227 			extendedAllocationInfo->importMemoryHostPointerInfo = reinterpret_cast<const VkImportMemoryHostPointerInfoEXT *>(allocationInfo);
228 			if((extendedAllocationInfo->importMemoryHostPointerInfo->handleType != VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT) &&
229 			   (extendedAllocationInfo->importMemoryHostPointerInfo->handleType != VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT))
230 			{
231 				UNSUPPORTED("extendedAllocationInfo->importMemoryHostPointerInfo->handleType %u", extendedAllocationInfo->importMemoryHostPointerInfo->handleType);
232 				return VK_ERROR_INVALID_EXTERNAL_HANDLE;
233 			}
234 			break;
235 #if VK_USE_PLATFORM_FUCHSIA
236 		case VK_STRUCTURE_TYPE_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA:
237 			extendedAllocationInfo->importMemoryZirconHandleInfo = reinterpret_cast<const VkImportMemoryZirconHandleInfoFUCHSIA *>(allocationInfo);
238 			if(extendedAllocationInfo->importMemoryZirconHandleInfo->handleType != VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA)
239 			{
240 				UNSUPPORTED("extendedAllocationInfo->importMemoryZirconHandleInfo->handleType %u", extendedAllocationInfo->importMemoryZirconHandleInfo->handleType);
241 				return VK_ERROR_INVALID_EXTERNAL_HANDLE;
242 			}
243 			break;
244 #endif  // VK_USE_PLATFORM_FUCHSIA
245 		default:
246 			UNSUPPORTED("pAllocateInfo->pNext sType = %s", vk::Stringify(allocationInfo->sType).c_str());
247 			break;
248 		}
249 
250 		allocationInfo = allocationInfo->pNext;
251 	}
252 
253 	return VK_SUCCESS;
254 }
255 
allocate()256 VkResult DeviceMemory::allocate()
257 {
258 	if(allocationSize > MAX_MEMORY_ALLOCATION_SIZE)
259 	{
260 #ifdef SWIFTSHADER_DEVICE_MEMORY_REPORT
261 		device->emitDeviceMemoryReport(VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATION_FAILED_EXT, 0 /* memoryObjectId */, allocationSize, VK_OBJECT_TYPE_DEVICE_MEMORY, 0 /* objectHandle */);
262 #endif  // SWIFTSHADER_DEVICE_MEMORY_REPORT
263 
264 		return VK_ERROR_OUT_OF_DEVICE_MEMORY;
265 	}
266 
267 	VkResult result = VK_SUCCESS;
268 	if(!buffer)
269 	{
270 		result = allocateBuffer();
271 	}
272 
273 #ifdef SWIFTSHADER_DEVICE_MEMORY_REPORT
274 	if(result == VK_SUCCESS)
275 	{
276 		VkDeviceMemoryReportEventTypeEXT eventType = isImport() ? VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_IMPORT_EXT : VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATE_EXT;
277 		device->emitDeviceMemoryReport(eventType, getMemoryObjectId(), allocationSize, VK_OBJECT_TYPE_DEVICE_MEMORY, (uint64_t)(void *)VkDeviceMemory(*this));
278 	}
279 	else
280 	{
281 		device->emitDeviceMemoryReport(VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATION_FAILED_EXT, 0 /* memoryObjectId */, allocationSize, VK_OBJECT_TYPE_DEVICE_MEMORY, 0 /* objectHandle */);
282 	}
283 #endif  // SWIFTSHADER_DEVICE_MEMORY_REPORT
284 
285 	return result;
286 }
287 
map(VkDeviceSize pOffset,VkDeviceSize pSize,void ** ppData)288 VkResult DeviceMemory::map(VkDeviceSize pOffset, VkDeviceSize pSize, void **ppData)
289 {
290 	*ppData = getOffsetPointer(pOffset);
291 
292 	return VK_SUCCESS;
293 }
294 
getCommittedMemoryInBytes() const295 VkDeviceSize DeviceMemory::getCommittedMemoryInBytes() const
296 {
297 	return allocationSize;
298 }
299 
getOffsetPointer(VkDeviceSize pOffset) const300 void *DeviceMemory::getOffsetPointer(VkDeviceSize pOffset) const
301 {
302 	ASSERT(buffer);
303 	return reinterpret_cast<char *>(buffer) + pOffset;
304 }
305 
checkExternalMemoryHandleType(VkExternalMemoryHandleTypeFlags supportedHandleTypes) const306 bool DeviceMemory::checkExternalMemoryHandleType(
307     VkExternalMemoryHandleTypeFlags supportedHandleTypes) const
308 {
309 	if(!supportedHandleTypes)
310 	{
311 		// This image or buffer does not need to be stored on external
312 		// memory, so this check should always pass.
313 		return true;
314 	}
315 	VkExternalMemoryHandleTypeFlagBits handle_type_bit = getFlagBit();
316 	if(!handle_type_bit)
317 	{
318 		// This device memory is not external and can accommodate
319 		// any image or buffer as well.
320 		return true;
321 	}
322 	// Return true only if the external memory type is compatible with the
323 	// one specified during VkCreate{Image,Buffer}(), through a
324 	// VkExternalMemory{Image,Buffer}AllocateInfo struct.
325 	return (supportedHandleTypes & handle_type_bit) != 0;
326 }
327 
328 // Allocate the memory according to `allocationSize`. On success return VK_SUCCESS
329 // and sets `buffer`.
allocateBuffer()330 VkResult DeviceMemory::allocateBuffer()
331 {
332 	buffer = vk::allocateDeviceMemory(allocationSize, REQUIRED_MEMORY_ALIGNMENT);
333 	if(!buffer)
334 	{
335 		return VK_ERROR_OUT_OF_DEVICE_MEMORY;
336 	}
337 
338 	return VK_SUCCESS;
339 }
340 
341 // Free previously allocated memory at `buffer`.
freeBuffer()342 void DeviceMemory::freeBuffer()
343 {
344 	vk::freeDeviceMemory(buffer);
345 	buffer = nullptr;
346 }
347 
348 // Return the handle type flag bit supported by this implementation.
349 // A value of 0 corresponds to non-external memory.
getFlagBit() const350 VkExternalMemoryHandleTypeFlagBits DeviceMemory::getFlagBit() const
351 {
352 	// Does not support any external memory type at all.
353 	static const VkExternalMemoryHandleTypeFlagBits typeFlagBit = (VkExternalMemoryHandleTypeFlagBits)0;
354 	return typeFlagBit;
355 }
356 
357 #if SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD
exportFd(int * pFd) const358 VkResult DeviceMemory::exportFd(int *pFd) const
359 {
360 	return VK_ERROR_INVALID_EXTERNAL_HANDLE;
361 }
362 #endif
363 
364 #if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
exportAndroidHardwareBuffer(struct AHardwareBuffer ** pAhb) const365 VkResult DeviceMemory::exportAndroidHardwareBuffer(struct AHardwareBuffer **pAhb) const
366 {
367 	return VK_ERROR_OUT_OF_HOST_MEMORY;
368 }
369 
GetAndroidHardwareBufferProperties(VkDevice & ahbDevice,const struct AHardwareBuffer * buffer,VkAndroidHardwareBufferPropertiesANDROID * pProperties)370 VkResult DeviceMemory::GetAndroidHardwareBufferProperties(VkDevice &ahbDevice, const struct AHardwareBuffer *buffer, VkAndroidHardwareBufferPropertiesANDROID *pProperties)
371 {
372 	return AHardwareBufferExternalMemory::GetAndroidHardwareBufferProperties(ahbDevice, buffer, pProperties);
373 }
374 #endif
375 
376 #if VK_USE_PLATFORM_FUCHSIA
exportHandle(zx_handle_t * pHandle) const377 VkResult DeviceMemory::exportHandle(zx_handle_t *pHandle) const
378 {
379 	return VK_ERROR_INVALID_EXTERNAL_HANDLE;
380 }
381 #endif
382 
383 }  // namespace vk
384