Commit e52e2dbc by David 'Digit' Turner Committed by David Turner

[vulkan] Implement VK_FUCHSIA_external_memory extension.

This implements external memory using a Zircon VMO handle that can be transferred between Fuchsia processes easily. Bug: b/140419396 Change-Id: I81cecec35b218eb22f3318ddec7b790b89e5ce09 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/36168Tested-by: 's avatarDavid Turner <digit@google.com> Kokoro-Result: kokoro <noreply+kokoro@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com>
parent 20220a0b
...@@ -51,6 +51,13 @@ public: ...@@ -51,6 +51,13 @@ public:
} }
#endif #endif
#if VK_USE_PLATFORM_FUCHSIA
virtual VkResult exportHandle(zx_handle_t *pHandle) const
{
return VK_ERROR_INVALID_EXTERNAL_HANDLE;
}
#endif
protected: protected:
ExternalBase() = default; ExternalBase() = default;
}; };
...@@ -219,6 +226,10 @@ private: ...@@ -219,6 +226,10 @@ private:
# endif # endif
#endif #endif
#if VK_USE_PLATFORM_FUCHSIA
# include "VkDeviceMemoryExternalFuchsia.hpp"
#endif
namespace vk { namespace vk {
static void findTraits(const VkMemoryAllocateInfo *pAllocateInfo, static void findTraits(const VkMemoryAllocateInfo *pAllocateInfo,
...@@ -236,6 +247,12 @@ static void findTraits(const VkMemoryAllocateInfo *pAllocateInfo, ...@@ -236,6 +247,12 @@ static void findTraits(const VkMemoryAllocateInfo *pAllocateInfo,
return; return;
} }
#endif #endif
#if VK_USE_PLATFORM_FUCHSIA
if(parseCreateInfo<zircon::VmoExternalMemory>(pAllocateInfo, pTraits))
{
return;
}
#endif
if(parseCreateInfo<ExternalMemoryHost>(pAllocateInfo, pTraits)) if(parseCreateInfo<ExternalMemoryHost>(pAllocateInfo, pTraits))
{ {
return; return;
...@@ -348,4 +365,11 @@ VkResult DeviceMemory::getAhbProperties(const struct AHardwareBuffer *buffer, Vk ...@@ -348,4 +365,11 @@ VkResult DeviceMemory::getAhbProperties(const struct AHardwareBuffer *buffer, Vk
} }
#endif #endif
#if VK_USE_PLATFORM_FUCHSIA
VkResult DeviceMemory::exportHandle(zx_handle_t *pHandle) const
{
return external->exportHandle(pHandle);
}
#endif
} // namespace vk } // namespace vk
...@@ -36,6 +36,10 @@ public: ...@@ -36,6 +36,10 @@ public:
static VkResult getAhbProperties(const struct AHardwareBuffer *buffer, VkAndroidHardwareBufferPropertiesANDROID *pProperties); static VkResult getAhbProperties(const struct AHardwareBuffer *buffer, VkAndroidHardwareBufferPropertiesANDROID *pProperties);
#endif #endif
#if VK_USE_PLATFORM_FUCHSIA
VkResult exportHandle(zx_handle_t *pHandle) const;
#endif
void destroy(const VkAllocationCallbacks *pAllocator); void destroy(const VkAllocationCallbacks *pAllocator);
VkResult allocate(); VkResult allocate();
VkResult map(VkDeviceSize offset, VkDeviceSize size, void **ppData); VkResult map(VkDeviceSize offset, VkDeviceSize size, void **ppData);
......
// 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 "VkStringify.hpp"
#include "System/Debug.hpp"
#include <zircon/process.h>
#include <zircon/syscalls.h>
namespace zircon {
class VmoExternalMemory : public vk::DeviceMemory::ExternalBase
{
public:
// Helper struct to parse the VkMemoryAllocateInfo.pNext chain and
// extract relevant information related to the handle type supported
// by this DeviceMemory::ExternalBase subclass.
struct AllocateInfo
{
bool importHandle = false;
bool exportHandle = false;
zx_handle_t handle = ZX_HANDLE_INVALID;
AllocateInfo() = default;
// Parse the VkMemoryAllocateInfo->pNext chain to initialize a AllocateInfo.
AllocateInfo(const VkMemoryAllocateInfo *pAllocateInfo)
{
const auto *extInfo = reinterpret_cast<const VkBaseInStructure *>(pAllocateInfo->pNext);
while(extInfo)
{
switch(extInfo->sType)
{
case VK_STRUCTURE_TYPE_TEMP_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA:
{
const auto *importInfo = reinterpret_cast<const VkImportMemoryZirconHandleInfoFUCHSIA *>(extInfo);
if(importInfo->handleType != VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA)
{
UNSUPPORTED("importInfo->handleType");
}
importHandle = true;
handle = importInfo->handle;
break;
}
case VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO:
{
const auto *exportInfo = reinterpret_cast<const VkExportMemoryAllocateInfo *>(extInfo);
if(exportInfo->handleTypes != VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA)
{
UNSUPPORTED("exportInfo->handleTypes");
}
exportHandle = true;
break;
}
default:
WARN("VkMemoryAllocateInfo->pNext sType = %s", vk::Stringify(extInfo->sType).c_str());
}
extInfo = extInfo->pNext;
}
}
};
static const VkExternalMemoryHandleTypeFlagBits typeFlagBit = VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA;
static bool supportsAllocateInfo(const VkMemoryAllocateInfo *pAllocateInfo)
{
AllocateInfo info(pAllocateInfo);
return info.importHandle || info.exportHandle;
}
explicit VmoExternalMemory(const VkMemoryAllocateInfo *pAllocateInfo)
: allocateInfo(pAllocateInfo)
{
}
~VmoExternalMemory()
{
closeVmo();
}
VkResult allocate(size_t size, void **pBuffer) override
{
if(allocateInfo.importHandle)
{
// NOTE: handle ownership is passed to the VkDeviceMemory.
vmoHandle = allocateInfo.handle;
}
else
{
ASSERT(allocateInfo.exportHandle);
zx_status_t status = zx_vmo_create(size, 0, &vmoHandle);
if(status != ZX_OK)
{
TRACE("zx_vmo_create() returned %d", status);
return VK_ERROR_OUT_OF_DEVICE_MEMORY;
}
}
// Now map it directly.
zx_vaddr_t addr = 0;
zx_status_t status = zx_vmar_map(zx_vmar_root_self(),
ZX_VM_PERM_READ | ZX_VM_PERM_WRITE,
0, // vmar_offset
vmoHandle,
0, // vmo_offset
size,
&addr);
if(status != ZX_OK)
{
TRACE("zx_vmar_map() failed with %d", status);
return VK_ERROR_MEMORY_MAP_FAILED;
}
*pBuffer = reinterpret_cast<void *>(addr);
return VK_SUCCESS;
}
void deallocate(void *buffer, size_t size) override
{
zx_status_t status = zx_vmar_unmap(zx_vmar_root_self(),
reinterpret_cast<zx_vaddr_t>(buffer),
size);
if(status != ZX_OK)
{
TRACE("zx_vmar_unmap() failed with %d", status);
}
closeVmo();
}
VkExternalMemoryHandleTypeFlagBits getFlagBit() const override
{
return typeFlagBit;
}
VkResult exportHandle(zx_handle_t *pHandle) const override
{
if(vmoHandle == ZX_HANDLE_INVALID)
{
return VK_ERROR_INVALID_EXTERNAL_HANDLE;
}
zx_status_t status = zx_handle_duplicate(vmoHandle, ZX_RIGHT_SAME_RIGHTS, pHandle);
if(status != ZX_OK)
{
TRACE("zx_handle_duplicate() returned %d", status);
return VK_ERROR_INVALID_EXTERNAL_HANDLE;
}
return VK_SUCCESS;
}
private:
void closeVmo()
{
if(vmoHandle != ZX_HANDLE_INVALID)
{
zx_handle_close(vmoHandle);
vmoHandle = ZX_HANDLE_INVALID;
}
}
zx_handle_t vmoHandle = ZX_HANDLE_INVALID;
AllocateInfo allocateInfo;
};
} // namespace zircon
...@@ -397,6 +397,16 @@ static const std::vector<std::pair<const char *, std::unordered_map<std::string, ...@@ -397,6 +397,16 @@ static const std::vector<std::pair<const char *, std::unordered_map<std::string,
MAKE_VULKAN_DEVICE_ENTRY(vkGetMemoryAndroidHardwareBufferANDROID), MAKE_VULKAN_DEVICE_ENTRY(vkGetMemoryAndroidHardwareBufferANDROID),
} }, } },
#endif #endif
#if VK_USE_PLATFORM_FUCHSIA
// VK_FUCHSIA_external_memory
{
VK_FUCHSIA_EXTERNAL_MEMORY_EXTENSION_NAME,
{
MAKE_VULKAN_DEVICE_ENTRY(vkGetMemoryZirconHandleFUCHSIA),
MAKE_VULKAN_DEVICE_ENTRY(vkGetMemoryZirconHandlePropertiesFUCHSIA),
} },
#endif
}; };
#undef MAKE_VULKAN_DEVICE_ENTRY #undef MAKE_VULKAN_DEVICE_ENTRY
......
...@@ -43,6 +43,15 @@ static void setExternalMemoryProperties(VkExternalMemoryHandleTypeFlagBits handl ...@@ -43,6 +43,15 @@ static void setExternalMemoryProperties(VkExternalMemoryHandleTypeFlagBits handl
return; return;
} }
#endif #endif
#if VK_USE_PLATFORM_FUCHSIA
if(handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA)
{
properties->compatibleHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA;
properties->exportFromImportedHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA;
properties->externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT;
return;
}
#endif
properties->compatibleHandleTypes = 0; properties->compatibleHandleTypes = 0;
properties->exportFromImportedHandleTypes = 0; properties->exportFromImportedHandleTypes = 0;
properties->externalMemoryFeatures = 0; properties->externalMemoryFeatures = 0;
......
...@@ -348,6 +348,7 @@ static const VkExtensionProperties deviceExtensionProperties[] = { ...@@ -348,6 +348,7 @@ static const VkExtensionProperties deviceExtensionProperties[] = {
#if VK_USE_PLATFORM_FUCHSIA #if VK_USE_PLATFORM_FUCHSIA
{ VK_FUCHSIA_EXTERNAL_SEMAPHORE_EXTENSION_NAME, VK_FUCHSIA_EXTERNAL_SEMAPHORE_SPEC_VERSION }, { VK_FUCHSIA_EXTERNAL_SEMAPHORE_EXTENSION_NAME, VK_FUCHSIA_EXTERNAL_SEMAPHORE_SPEC_VERSION },
{ VK_FUCHSIA_EXTERNAL_MEMORY_EXTENSION_NAME, VK_FUCHSIA_EXTERNAL_MEMORY_SPEC_VERSION },
#endif #endif
{ VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME, VK_EXT_PROVOKING_VERTEX_SPEC_VERSION }, { VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME, VK_EXT_PROVOKING_VERTEX_SPEC_VERSION },
}; };
...@@ -946,6 +947,10 @@ VKAPI_ATTR VkResult VKAPI_CALL vkAllocateMemory(VkDevice device, const VkMemoryA ...@@ -946,6 +947,10 @@ VKAPI_ATTR VkResult VKAPI_CALL vkAllocateMemory(VkDevice device, const VkMemoryA
case VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID: case VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID:
break; break;
#endif #endif
#if VK_USE_PLATFORM_FUCHSIA
case VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA:
break;
#endif
default: default:
UNSUPPORTED("exportInfo->handleTypes %u", exportInfo->handleTypes); UNSUPPORTED("exportInfo->handleTypes %u", exportInfo->handleTypes);
return VK_ERROR_INVALID_EXTERNAL_HANDLE; return VK_ERROR_INVALID_EXTERNAL_HANDLE;
...@@ -967,6 +972,18 @@ VKAPI_ATTR VkResult VKAPI_CALL vkAllocateMemory(VkDevice device, const VkMemoryA ...@@ -967,6 +972,18 @@ VKAPI_ATTR VkResult VKAPI_CALL vkAllocateMemory(VkDevice device, const VkMemoryA
} }
break; break;
} }
#if VK_USE_PLATFORM_FUCHSIA
case VK_STRUCTURE_TYPE_TEMP_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA:
{
auto *importInfo = reinterpret_cast<const VkImportMemoryZirconHandleInfoFUCHSIA *>(allocationInfo);
if(importInfo->handleType != VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA)
{
UNSUPPORTED("importInfo->handleType %u", importInfo->handleType);
return VK_ERROR_INVALID_EXTERNAL_HANDLE;
}
break;
}
#endif // VK_USE_PLATFORM_FUCHSIA
default: default:
LOG_TRAP("pAllocateInfo->pNext sType = %s", vk::Stringify(allocationInfo->sType).c_str()); LOG_TRAP("pAllocateInfo->pNext sType = %s", vk::Stringify(allocationInfo->sType).c_str());
break; break;
...@@ -1039,6 +1056,45 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryFdPropertiesKHR(VkDevice device, VkExt ...@@ -1039,6 +1056,45 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryFdPropertiesKHR(VkDevice device, VkExt
return VK_SUCCESS; return VK_SUCCESS;
} }
#endif // SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD #endif // SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD
#if VK_USE_PLATFORM_FUCHSIA
VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryZirconHandleFUCHSIA(VkDevice device, const VkMemoryGetZirconHandleInfoFUCHSIA *pGetHandleInfo, zx_handle_t *pHandle)
{
TRACE("(VkDevice device = %p, const VkMemoryGetZirconHandleInfoFUCHSIA* pGetHandleInfo = %p, zx_handle_t* pHandle = %p",
device, pGetHandleInfo, pHandle);
if(pGetHandleInfo->handleType != VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA)
{
UNSUPPORTED("pGetHandleInfo->handleType %u", pGetHandleInfo->handleType);
return VK_ERROR_INVALID_EXTERNAL_HANDLE;
}
return vk::Cast(pGetHandleInfo->memory)->exportHandle(pHandle);
}
VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryZirconHandlePropertiesFUCHSIA(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, zx_handle_t handle, VkMemoryZirconHandlePropertiesFUCHSIA *pMemoryZirconHandleProperties)
{
TRACE("(VkDevice device = %p, VkExternalMemoryHandleTypeFlagBits handleType = %x, zx_handle_t handle = %d, VkMemoryZirconHandlePropertiesFUCHSIA* pMemoryZirconHandleProperties = %p)",
device, handleType, handle, pMemoryZirconHandleProperties);
if(handleType != VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA)
{
UNSUPPORTED("handleType %u", handleType);
return VK_ERROR_INVALID_EXTERNAL_HANDLE;
}
if(handle == ZX_HANDLE_INVALID)
{
return VK_ERROR_INVALID_EXTERNAL_HANDLE;
}
const VkPhysicalDeviceMemoryProperties &memoryProperties =
vk::Cast(device)->getPhysicalDevice()->getMemoryProperties();
// All SwiftShader memory types support this!
pMemoryZirconHandleProperties->memoryTypeBits = (1U << memoryProperties.memoryTypeCount) - 1U;
return VK_SUCCESS;
}
#endif // VK_USE_PLATFORM_FUCHSIA
VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryHostPointerPropertiesEXT(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, const void *pHostPointer, VkMemoryHostPointerPropertiesEXT *pMemoryHostPointerProperties) VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryHostPointerPropertiesEXT(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, const void *pHostPointer, VkMemoryHostPointerPropertiesEXT *pMemoryHostPointerProperties)
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment