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