// Copyright 2019 The SwiftShader Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "VkDeviceMemory.hpp" #include "System/Debug.hpp" #include "System/Linux/MemFd.hpp" #include #include #include class OpaqueFdExternalMemory : public vk::DeviceMemory, public vk::ObjectBase { public: static const VkExternalMemoryHandleTypeFlagBits typeFlagBit = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; static bool SupportsAllocateInfo(const vk::DeviceMemory::ExtendedAllocationInfo &extendedAllocationInfo) { OpaqueFdAllocateInfo info(extendedAllocationInfo); return info.importFd || info.exportFd; } explicit OpaqueFdExternalMemory(const VkMemoryAllocateInfo *pCreateInfo, void *mem, const vk::DeviceMemory::ExtendedAllocationInfo &extendedAllocationInfo, vk::Device *pDevice) : vk::DeviceMemory(pCreateInfo, extendedAllocationInfo, pDevice) , allocateInfo(extendedAllocationInfo) { } ~OpaqueFdExternalMemory() { memfd.close(); } VkResult allocateBuffer() override { if(allocateInfo.importFd) { memfd.importFd(allocateInfo.fd); if(!memfd.isValid()) { return VK_ERROR_INVALID_EXTERNAL_HANDLE; } } else { ASSERT(allocateInfo.exportFd); static int counter = 0; char name[40]; snprintf(name, sizeof(name), "SwiftShader.Memory.%d", ++counter); if(!memfd.allocate(name, allocationSize)) { TRACE("memfd.allocate() returned %s", strerror(errno)); return VK_ERROR_OUT_OF_DEVICE_MEMORY; } } void *addr = memfd.mapReadWrite(0, allocationSize); if(!addr) { return VK_ERROR_MEMORY_MAP_FAILED; } buffer = addr; return VK_SUCCESS; } void freeBuffer() override { memfd.unmap(buffer, allocationSize); } VkExternalMemoryHandleTypeFlagBits getFlagBit() const override { return typeFlagBit; } VkResult exportFd(int *pFd) const override { int fd = memfd.exportFd(); if(fd < 0) { return VK_ERROR_INVALID_EXTERNAL_HANDLE; } *pFd = fd; return VK_SUCCESS; } private: LinuxMemFd memfd; OpaqueFdAllocateInfo allocateInfo; };