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