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.
30struct 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.
39 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
83namespace vk {
84
85VkResult 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: &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(object: *pMemory)->allocate();
104}
105
106VkResult 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, pCreateInfo: &allocateInfo, outObject: pMemory, extendedInfo: extendedAllocationInfo, extendedInfo: 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, pCreateInfo: &allocateInfo, outObject: pMemory, extendedInfo: extendedAllocationInfo, extendedInfo: device);
139 }
140
141 return vk::DeviceMemoryInternal::Create(pAllocator, pCreateInfo: &allocateInfo, outObject: pMemory, extendedInfo: extendedAllocationInfo, extendedInfo: device);
142}
143
144DeviceMemory::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
153void 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
167size_t DeviceMemory::ComputeRequiredAllocationSize(const VkMemoryAllocateInfo *pAllocateInfo)
168{
169 return 0;
170}
171
172VkResult 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
261VkResult 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
293VkResult DeviceMemory::map(VkDeviceSize pOffset, VkDeviceSize pSize, void **ppData)
294{
295 *ppData = getOffsetPointer(pOffset);
296
297 return VK_SUCCESS;
298}
299
300VkDeviceSize DeviceMemory::getCommittedMemoryInBytes() const
301{
302 return allocationSize;
303}
304
305void *DeviceMemory::getOffsetPointer(VkDeviceSize pOffset) const
306{
307 ASSERT(buffer);
308 return reinterpret_cast<char *>(buffer) + pOffset;
309}
310
311uint64_t DeviceMemory::getOpaqueCaptureAddress() const
312{
313 return (opaqueCaptureAddress != 0) ? opaqueCaptureAddress : static_cast<uint64_t>(reinterpret_cast<uintptr_t>(buffer));
314}
315
316bool 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`.
340VkResult DeviceMemory::allocateBuffer()
341{
342 buffer = vk::allocateDeviceMemory(bytes: allocationSize, alignment: 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`.
352void DeviceMemory::freeBuffer()
353{
354 vk::freeDeviceMemory(ptr: 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.
360VkExternalMemoryHandleTypeFlagBits 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
368VkResult 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
375VkResult DeviceMemory::exportAndroidHardwareBuffer(struct AHardwareBuffer **pAhb) const
376{
377 return VK_ERROR_OUT_OF_HOST_MEMORY;
378}
379
380VkResult 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
387VkResult DeviceMemory::exportHandle(zx_handle_t *pHandle) const
388{
389 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
390}
391#endif
392
393} // namespace vk
394

Provided by KDAB

Privacy Policy
Learn more about Flutter for embedded and desktop on industrialflutter.com

source code of flutter_engine/third_party/swiftshader/src/Vulkan/VkDeviceMemory.cpp