xref: /aosp_15_r20/external/swiftshader/src/Vulkan/VkDeviceMemory.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
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,const DeviceMemory::ExtendedAllocationInfo & extendedAllocationInfo,Device * pDevice)144 DeviceMemory::DeviceMemory(const VkMemoryAllocateInfo *pAllocateInfo, const DeviceMemory::ExtendedAllocationInfo &extendedAllocationInfo, Device *pDevice)
145     : allocationSize(pAllocateInfo->allocationSize)
146     , memoryTypeIndex(pAllocateInfo->memoryTypeIndex)
147     , opaqueCaptureAddress(extendedAllocationInfo.opaqueCaptureAddress)
148     , device(pDevice)
149 {
150 	ASSERT(allocationSize);
151 }
152 
destroy(const VkAllocationCallbacks * pAllocator)153 void DeviceMemory::destroy(const VkAllocationCallbacks *pAllocator)
154 {
155 #ifdef SWIFTSHADER_DEVICE_MEMORY_REPORT
156 	VkDeviceMemoryReportEventTypeEXT eventType = isImport() ? VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_UNIMPORT_EXT : VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_FREE_EXT;
157 	device->emitDeviceMemoryReport(eventType, getMemoryObjectId(), 0 /* size */, VK_OBJECT_TYPE_DEVICE_MEMORY, (uint64_t)(void *)VkDeviceMemory(*this));
158 #endif  // SWIFTSHADER_DEVICE_MEMORY_REPORT
159 
160 	if(buffer)
161 	{
162 		freeBuffer();
163 		buffer = nullptr;
164 	}
165 }
166 
ComputeRequiredAllocationSize(const VkMemoryAllocateInfo * pAllocateInfo)167 size_t DeviceMemory::ComputeRequiredAllocationSize(const VkMemoryAllocateInfo *pAllocateInfo)
168 {
169 	return 0;
170 }
171 
ParseAllocationInfo(const VkMemoryAllocateInfo * pAllocateInfo,DeviceMemory::ExtendedAllocationInfo * extendedAllocationInfo)172 VkResult DeviceMemory::ParseAllocationInfo(const VkMemoryAllocateInfo *pAllocateInfo, DeviceMemory::ExtendedAllocationInfo *extendedAllocationInfo)
173 {
174 	const VkBaseInStructure *allocationInfo = reinterpret_cast<const VkBaseInStructure *>(pAllocateInfo->pNext);
175 	while(allocationInfo)
176 	{
177 		switch(allocationInfo->sType)
178 		{
179 		case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO:
180 			// This can safely be ignored on most platforms, as the Vulkan spec mentions:
181 			// "If the pNext chain includes a VkMemoryDedicatedAllocateInfo structure, then that structure
182 			//  includes a handle of the sole buffer or image resource that the memory *can* be bound to."
183 #if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
184 			extendedAllocationInfo->dedicatedAllocateInfo = reinterpret_cast<const VkMemoryDedicatedAllocateInfo *>(allocationInfo);
185 #endif
186 			break;
187 		case VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO:
188 			// This extension controls on which physical devices the memory gets allocated.
189 			// SwiftShader only has a single physical device, so this extension does nothing in this case.
190 			break;
191 #if SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD
192 		case VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR:
193 			extendedAllocationInfo->importMemoryFdInfo = reinterpret_cast<const VkImportMemoryFdInfoKHR *>(allocationInfo);
194 			if(extendedAllocationInfo->importMemoryFdInfo->handleType != VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT)
195 			{
196 				UNSUPPORTED("extendedAllocationInfo->importMemoryFdInfo->handleType %u", extendedAllocationInfo->importMemoryFdInfo->handleType);
197 				return VK_ERROR_INVALID_EXTERNAL_HANDLE;
198 			}
199 			break;
200 #endif  // SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD
201 		case VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO:
202 			extendedAllocationInfo->exportMemoryAllocateInfo = reinterpret_cast<const VkExportMemoryAllocateInfo *>(allocationInfo);
203 			switch(extendedAllocationInfo->exportMemoryAllocateInfo->handleTypes)
204 			{
205 #if SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD
206 			case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
207 				break;
208 #endif
209 #if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
210 			case VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID:
211 				break;
212 #endif
213 #if VK_USE_PLATFORM_FUCHSIA
214 			case VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA:
215 				break;
216 #endif
217 			default:
218 				UNSUPPORTED("extendedAllocationInfo->exportMemoryAllocateInfo->handleTypes %u", extendedAllocationInfo->exportMemoryAllocateInfo->handleTypes);
219 				return VK_ERROR_INVALID_EXTERNAL_HANDLE;
220 			}
221 			break;
222 #if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
223 		case VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID:
224 			extendedAllocationInfo->importAndroidHardwareBufferInfo = reinterpret_cast<const VkImportAndroidHardwareBufferInfoANDROID *>(allocationInfo);
225 			break;
226 #endif  // SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
227 		case VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT:
228 			extendedAllocationInfo->importMemoryHostPointerInfo = reinterpret_cast<const VkImportMemoryHostPointerInfoEXT *>(allocationInfo);
229 			if((extendedAllocationInfo->importMemoryHostPointerInfo->handleType != VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT) &&
230 			   (extendedAllocationInfo->importMemoryHostPointerInfo->handleType != VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT))
231 			{
232 				UNSUPPORTED("extendedAllocationInfo->importMemoryHostPointerInfo->handleType %u", extendedAllocationInfo->importMemoryHostPointerInfo->handleType);
233 				return VK_ERROR_INVALID_EXTERNAL_HANDLE;
234 			}
235 			break;
236 #if VK_USE_PLATFORM_FUCHSIA
237 		case VK_STRUCTURE_TYPE_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA:
238 			extendedAllocationInfo->importMemoryZirconHandleInfo = reinterpret_cast<const VkImportMemoryZirconHandleInfoFUCHSIA *>(allocationInfo);
239 			if(extendedAllocationInfo->importMemoryZirconHandleInfo->handleType != VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA)
240 			{
241 				UNSUPPORTED("extendedAllocationInfo->importMemoryZirconHandleInfo->handleType %u", extendedAllocationInfo->importMemoryZirconHandleInfo->handleType);
242 				return VK_ERROR_INVALID_EXTERNAL_HANDLE;
243 			}
244 			break;
245 #endif  // VK_USE_PLATFORM_FUCHSIA
246 		case VK_STRUCTURE_TYPE_MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO:
247 			extendedAllocationInfo->opaqueCaptureAddress =
248 			    reinterpret_cast<const VkMemoryOpaqueCaptureAddressAllocateInfo *>(allocationInfo)->opaqueCaptureAddress;
249 			break;
250 		default:
251 			UNSUPPORTED("pAllocateInfo->pNext sType = %s", vk::Stringify(allocationInfo->sType).c_str());
252 			break;
253 		}
254 
255 		allocationInfo = allocationInfo->pNext;
256 	}
257 
258 	return VK_SUCCESS;
259 }
260 
allocate()261 VkResult DeviceMemory::allocate()
262 {
263 	if(allocationSize > MAX_MEMORY_ALLOCATION_SIZE)
264 	{
265 #ifdef SWIFTSHADER_DEVICE_MEMORY_REPORT
266 		device->emitDeviceMemoryReport(VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATION_FAILED_EXT, 0 /* memoryObjectId */, allocationSize, VK_OBJECT_TYPE_DEVICE_MEMORY, 0 /* objectHandle */);
267 #endif  // SWIFTSHADER_DEVICE_MEMORY_REPORT
268 
269 		return VK_ERROR_OUT_OF_DEVICE_MEMORY;
270 	}
271 
272 	VkResult result = VK_SUCCESS;
273 	if(!buffer)
274 	{
275 		result = allocateBuffer();
276 	}
277 
278 #ifdef SWIFTSHADER_DEVICE_MEMORY_REPORT
279 	if(result == VK_SUCCESS)
280 	{
281 		VkDeviceMemoryReportEventTypeEXT eventType = isImport() ? VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_IMPORT_EXT : VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATE_EXT;
282 		device->emitDeviceMemoryReport(eventType, getMemoryObjectId(), allocationSize, VK_OBJECT_TYPE_DEVICE_MEMORY, (uint64_t)(void *)VkDeviceMemory(*this));
283 	}
284 	else
285 	{
286 		device->emitDeviceMemoryReport(VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATION_FAILED_EXT, 0 /* memoryObjectId */, allocationSize, VK_OBJECT_TYPE_DEVICE_MEMORY, 0 /* objectHandle */);
287 	}
288 #endif  // SWIFTSHADER_DEVICE_MEMORY_REPORT
289 
290 	return result;
291 }
292 
map(VkDeviceSize pOffset,VkDeviceSize pSize,void ** ppData)293 VkResult DeviceMemory::map(VkDeviceSize pOffset, VkDeviceSize pSize, void **ppData)
294 {
295 	*ppData = getOffsetPointer(pOffset);
296 
297 	return VK_SUCCESS;
298 }
299 
getCommittedMemoryInBytes() const300 VkDeviceSize DeviceMemory::getCommittedMemoryInBytes() const
301 {
302 	return allocationSize;
303 }
304 
getOffsetPointer(VkDeviceSize pOffset) const305 void *DeviceMemory::getOffsetPointer(VkDeviceSize pOffset) const
306 {
307 	ASSERT(buffer);
308 	return reinterpret_cast<char *>(buffer) + pOffset;
309 }
310 
getOpaqueCaptureAddress() const311 uint64_t DeviceMemory::getOpaqueCaptureAddress() const
312 {
313 	return (opaqueCaptureAddress != 0) ? opaqueCaptureAddress : static_cast<uint64_t>(reinterpret_cast<uintptr_t>(buffer));
314 }
315 
checkExternalMemoryHandleType(VkExternalMemoryHandleTypeFlags supportedHandleTypes) const316 bool DeviceMemory::checkExternalMemoryHandleType(
317     VkExternalMemoryHandleTypeFlags supportedHandleTypes) const
318 {
319 	if(!supportedHandleTypes)
320 	{
321 		// This image or buffer does not need to be stored on external
322 		// memory, so this check should always pass.
323 		return true;
324 	}
325 	VkExternalMemoryHandleTypeFlagBits handle_type_bit = getFlagBit();
326 	if(!handle_type_bit)
327 	{
328 		// This device memory is not external and can accommodate
329 		// any image or buffer as well.
330 		return true;
331 	}
332 	// Return true only if the external memory type is compatible with the
333 	// one specified during VkCreate{Image,Buffer}(), through a
334 	// VkExternalMemory{Image,Buffer}AllocateInfo struct.
335 	return (supportedHandleTypes & handle_type_bit) != 0;
336 }
337 
338 // Allocate the memory according to `allocationSize`. On success return VK_SUCCESS
339 // and sets `buffer`.
allocateBuffer()340 VkResult DeviceMemory::allocateBuffer()
341 {
342 	buffer = vk::allocateDeviceMemory(allocationSize, vk::DEVICE_MEMORY_ALLOCATION_ALIGNMENT);
343 	if(!buffer)
344 	{
345 		return VK_ERROR_OUT_OF_DEVICE_MEMORY;
346 	}
347 
348 	return VK_SUCCESS;
349 }
350 
351 // Free previously allocated memory at `buffer`.
freeBuffer()352 void DeviceMemory::freeBuffer()
353 {
354 	vk::freeDeviceMemory(buffer);
355 	buffer = nullptr;
356 }
357 
358 // Return the handle type flag bit supported by this implementation.
359 // A value of 0 corresponds to non-external memory.
getFlagBit() const360 VkExternalMemoryHandleTypeFlagBits DeviceMemory::getFlagBit() const
361 {
362 	// Does not support any external memory type at all.
363 	static const VkExternalMemoryHandleTypeFlagBits typeFlagBit = (VkExternalMemoryHandleTypeFlagBits)0;
364 	return typeFlagBit;
365 }
366 
367 #if SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD
exportFd(int * pFd) const368 VkResult DeviceMemory::exportFd(int *pFd) const
369 {
370 	return VK_ERROR_INVALID_EXTERNAL_HANDLE;
371 }
372 #endif
373 
374 #if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
exportAndroidHardwareBuffer(struct AHardwareBuffer ** pAhb) const375 VkResult DeviceMemory::exportAndroidHardwareBuffer(struct AHardwareBuffer **pAhb) const
376 {
377 	return VK_ERROR_OUT_OF_HOST_MEMORY;
378 }
379 
GetAndroidHardwareBufferProperties(VkDevice & ahbDevice,const struct AHardwareBuffer * buffer,VkAndroidHardwareBufferPropertiesANDROID * pProperties)380 VkResult DeviceMemory::GetAndroidHardwareBufferProperties(VkDevice &ahbDevice, const struct AHardwareBuffer *buffer, VkAndroidHardwareBufferPropertiesANDROID *pProperties)
381 {
382 	return AHardwareBufferExternalMemory::GetAndroidHardwareBufferProperties(ahbDevice, buffer, pProperties);
383 }
384 #endif
385 
386 #if VK_USE_PLATFORM_FUCHSIA
exportHandle(zx_handle_t * pHandle) const387 VkResult DeviceMemory::exportHandle(zx_handle_t *pHandle) const
388 {
389 	return VK_ERROR_INVALID_EXTERNAL_HANDLE;
390 }
391 #endif
392 
393 }  // namespace vk
394