Add initial stub implementation of AHB
Bug: b/141698760
Change-Id: Icb293abc63a46c41a5165cdaa2061c23926b2568
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/39988
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Tested-by: Chris Forbes <chrisforbes@google.com>
diff --git a/src/Android.bp b/src/Android.bp
index 79bb946..3d957d6 100644
--- a/src/Android.bp
+++ b/src/Android.bp
@@ -47,7 +47,7 @@
relative_install_path: "egl",
header_libs: [
"swiftshader_platform_headers",
- "libnativebase_headers",
+ "libnativebase_headers",
],
shared_libs: [
"libnativewindow",
@@ -65,7 +65,7 @@
header_libs: [
"swiftshader_host_headers",
"swiftshader_platform_headers",
- "libnativebase_headers",
+ "libnativebase_headers",
],
// Pretend to build for Android
@@ -549,7 +549,7 @@
relative_install_path: "hw",
header_libs: [
"swiftshader_platform_headers",
- "vulkan_headers",
+ "vulkan_headers",
"hwvulkan_headers",
],
shared_libs: [
@@ -559,6 +559,9 @@
"libsync",
"liblog",
],
+ static_libs: [
+ "libarect",
+ ],
},
},
}
@@ -568,6 +571,7 @@
cflags: [
"-DLOG_TAG=\"swiftshader\"",
+ "-DSWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER",
],
srcs: [
diff --git a/src/Vulkan/VkDeviceMemory.cpp b/src/Vulkan/VkDeviceMemory.cpp
index 0e84d74..c524570 100644
--- a/src/Vulkan/VkDeviceMemory.cpp
+++ b/src/Vulkan/VkDeviceMemory.cpp
@@ -13,6 +13,8 @@
// limitations under the License.
#include "VkDeviceMemory.hpp"
+#include "VkBuffer.hpp"
+#include "VkImage.hpp"
#include "VkConfig.h"
@@ -42,6 +44,13 @@
}
#endif
+#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
+ virtual VkResult exportAhb(struct AHardwareBuffer **pAhb) const
+ {
+ return VK_ERROR_INVALID_EXTERNAL_HANDLE;
+ }
+#endif
+
protected:
ExternalBase() = default;
};
@@ -129,6 +138,14 @@
# endif
#endif
+#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
+# if defined(__ANDROID__)
+# include "VkDeviceMemoryExternalAndroid.hpp"
+# else
+# error "Missing VK_ANDROID_external_memory_android_hardware_buffer implementation for this platform!"
+# endif
+#endif
+
namespace vk {
static void findTraits(const VkMemoryAllocateInfo *pAllocateInfo,
@@ -140,6 +157,12 @@
return;
}
#endif
+#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
+ if(parseCreateInfo<AHardwareBufferExternalMemory>(pAllocateInfo, pTraits))
+ {
+ return;
+ }
+#endif
parseCreateInfo<DeviceMemoryHostExternalBase>(pAllocateInfo, pTraits);
}
@@ -236,4 +259,16 @@
}
#endif
+#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
+VkResult DeviceMemory::exportAhb(struct AHardwareBuffer **pAhb) const
+{
+ return external->exportAhb(pAhb);
+}
+
+VkResult DeviceMemory::getAhbProperties(const struct AHardwareBuffer *buffer, VkAndroidHardwareBufferPropertiesANDROID *pProperties)
+{
+ return AHardwareBufferExternalMemory::getAhbProperties(buffer, pProperties);
+}
+#endif
+
} // namespace vk
diff --git a/src/Vulkan/VkDeviceMemory.hpp b/src/Vulkan/VkDeviceMemory.hpp
index 7ec0267..e99fa89 100644
--- a/src/Vulkan/VkDeviceMemory.hpp
+++ b/src/Vulkan/VkDeviceMemory.hpp
@@ -31,6 +31,11 @@
VkResult exportFd(int *pFd) const;
#endif
+#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
+ VkResult exportAhb(struct AHardwareBuffer **pAhb) const;
+ static VkResult getAhbProperties(const struct AHardwareBuffer *buffer, VkAndroidHardwareBufferPropertiesANDROID *pProperties);
+#endif
+
void destroy(const VkAllocationCallbacks *pAllocator);
VkResult allocate();
VkResult map(VkDeviceSize offset, VkDeviceSize size, void **ppData);
diff --git a/src/Vulkan/VkDeviceMemoryExternalAndroid.hpp b/src/Vulkan/VkDeviceMemoryExternalAndroid.hpp
new file mode 100644
index 0000000..6cd2c93
--- /dev/null
+++ b/src/Vulkan/VkDeviceMemoryExternalAndroid.hpp
@@ -0,0 +1,156 @@
+// 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 "VkDebug.hpp"
+#include <android/hardware_buffer.h>
+
+#include <errno.h>
+#include <string.h>
+
+class AHardwareBufferExternalMemory : 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 importAhb = false;
+ bool exportAhb = false;
+ struct AHardwareBuffer *ahb = nullptr;
+ vk::Image *imageHandle = nullptr;
+ vk::Buffer *bufferHandle = nullptr;
+
+ AllocateInfo() = default;
+
+ // Parse the VkMemoryAllocateInfo.pNext chain to initialize an AllocateInfo.
+ AllocateInfo(const VkMemoryAllocateInfo *pAllocateInfo)
+ {
+ const auto *createInfo = reinterpret_cast<const VkBaseInStructure *>(pAllocateInfo->pNext);
+ while(createInfo)
+ {
+ switch(createInfo->sType)
+ {
+ case VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID:
+ {
+ const auto *importInfo = reinterpret_cast<const VkImportAndroidHardwareBufferInfoANDROID *>(createInfo);
+ importAhb = true;
+ ahb = importInfo->buffer;
+ }
+ break;
+ case VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO:
+ {
+ const auto *exportInfo = reinterpret_cast<const VkExportMemoryAllocateInfo *>(createInfo);
+
+ if(exportInfo->handleTypes != VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
+ {
+ UNIMPLEMENTED("exportInfo->handleTypes");
+ }
+ exportAhb = true;
+ }
+ break;
+ case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO:
+ {
+ // AHB requires dedicated allocation -- for images, the gralloc gets to decide the image layout,
+ // not us.
+ const auto *dedicatedAllocateInfo = reinterpret_cast<const VkMemoryDedicatedAllocateInfo *>(createInfo);
+ imageHandle = vk::Cast(dedicatedAllocateInfo->image);
+ bufferHandle = vk::Cast(dedicatedAllocateInfo->buffer);
+ }
+ break;
+
+ default:;
+ }
+ createInfo = createInfo->pNext;
+ }
+ }
+ };
+
+ static const VkExternalMemoryHandleTypeFlagBits typeFlagBit = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
+
+ static bool supportsAllocateInfo(const VkMemoryAllocateInfo *pAllocateInfo)
+ {
+ AllocateInfo info(pAllocateInfo);
+ return (info.importAhb || info.exportAhb) && (info.bufferHandle || info.imageHandle);
+ }
+
+ explicit AHardwareBufferExternalMemory(const VkMemoryAllocateInfo *pAllocateInfo)
+ : allocateInfo(pAllocateInfo)
+ {
+ }
+
+ ~AHardwareBufferExternalMemory()
+ {
+ if(ahb)
+ AHardwareBuffer_release(ahb);
+ }
+
+ VkResult allocate(size_t size, void **pBuffer) override
+ {
+ if(allocateInfo.importAhb)
+ {
+ //ahb = allocateInfo.ahb;
+ //AHardwareBuffer_acquire(ahb);
+ // TODO: also allocate our internal shadow memory
+ return VK_ERROR_INVALID_EXTERNAL_HANDLE;
+ }
+ else
+ {
+ ASSERT(allocateInfo.exportAhb);
+ // TODO: create and import the AHB
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ }
+
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ /*
+ void *addr = memfd.mapReadWrite(0, size);
+ if(!addr)
+ {
+ return VK_ERROR_MEMORY_MAP_FAILED;
+ }
+ *pBuffer = addr;
+ return VK_SUCCESS;
+ */
+ }
+
+ void deallocate(void *buffer, size_t size) override
+ {
+ // FIXME
+ }
+
+ VkExternalMemoryHandleTypeFlagBits getFlagBit() const override
+ {
+ return typeFlagBit;
+ }
+
+ VkResult exportAhb(struct AHardwareBuffer **pAhb) const override
+ {
+ // Each call to vkGetMemoryAndroidHardwareBufferANDROID *must* return an Android hardware buffer with a new reference
+ // acquired in addition to the reference held by the VkDeviceMemory. To avoid leaking resources, the application *must*
+ // release the reference by calling AHardwareBuffer_release when it is no longer needed.
+ AHardwareBuffer_acquire(ahb);
+ *pAhb = ahb;
+ return VK_SUCCESS;
+ }
+
+ static VkResult getAhbProperties(const struct AHardwareBuffer *buffer, VkAndroidHardwareBufferPropertiesANDROID *pProperties)
+ {
+ UNIMPLEMENTED("getAhbProperties");
+ return VK_SUCCESS;
+ }
+
+private:
+ struct AHardwareBuffer *ahb = nullptr;
+ AllocateInfo allocateInfo;
+};
diff --git a/src/Vulkan/VkGetProcAddress.cpp b/src/Vulkan/VkGetProcAddress.cpp
index fe7f282..796596b 100644
--- a/src/Vulkan/VkGetProcAddress.cpp
+++ b/src/Vulkan/VkGetProcAddress.cpp
@@ -371,6 +371,16 @@
MAKE_VULKAN_DEVICE_ENTRY(vkGetMemoryFdPropertiesKHR),
} },
#endif
+
+#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
+ // VK_ANDROID_external_memory_android_hardware_buffer
+ {
+ VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME,
+ {
+ MAKE_VULKAN_DEVICE_ENTRY(vkGetAndroidHardwareBufferPropertiesANDROID),
+ MAKE_VULKAN_DEVICE_ENTRY(vkGetMemoryAndroidHardwareBufferANDROID),
+ } },
+#endif
};
#undef MAKE_VULKAN_DEVICE_ENTRY
diff --git a/src/Vulkan/VkPhysicalDevice.cpp b/src/Vulkan/VkPhysicalDevice.cpp
index a208fc8..10941ef 100644
--- a/src/Vulkan/VkPhysicalDevice.cpp
+++ b/src/Vulkan/VkPhysicalDevice.cpp
@@ -34,6 +34,15 @@
return;
}
#endif
+#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
+ if(handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
+ {
+ properties->compatibleHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
+ properties->exportFromImportedHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
+ properties->externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT;
+ return;
+ }
+#endif
properties->compatibleHandleTypes = 0;
properties->exportFromImportedHandleTypes = 0;
properties->externalMemoryFeatures = 0;
diff --git a/src/Vulkan/libVulkan.cpp b/src/Vulkan/libVulkan.cpp
index 6af8bd9..72d8e69 100644
--- a/src/Vulkan/libVulkan.cpp
+++ b/src/Vulkan/libVulkan.cpp
@@ -243,6 +243,9 @@
// (from KHR_swapchain v70) to vkBindImageMemory2.
{ VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME, 7 },
#endif
+#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
+ { VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME, VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_SPEC_VERSION },
+#endif
#if SWIFTSHADER_EXTERNAL_SEMAPHORE_OPAQUE_FD
{ VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, VK_KHR_EXTERNAL_SEMAPHORE_FD_SPEC_VERSION },
#endif
@@ -815,17 +818,31 @@
}
break;
}
+#endif // SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD
case VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO:
{
auto *exportInfo = reinterpret_cast<const VkExportMemoryAllocateInfo *>(allocationInfo);
- if(exportInfo->handleTypes != VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT)
+ switch(exportInfo->handleTypes)
{
- UNSUPPORTED("exportInfo->handleTypes %u", exportInfo->handleTypes);
- return VK_ERROR_INVALID_EXTERNAL_HANDLE;
+#if SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD
+ case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT:
+ break;
+#endif
+#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
+ case VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID:
+ break;
+#endif
+ default:
+ UNSUPPORTED("exportInfo->handleTypes %u", exportInfo->handleTypes);
+ return VK_ERROR_INVALID_EXTERNAL_HANDLE;
}
break;
}
-#endif // SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD
+#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
+ case VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID:
+ // Ignore
+ break;
+#endif // SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
default:
WARN("pAllocateInfo->pNext sType = %s", vk::Stringify(allocationInfo->sType).c_str());
break;
@@ -899,6 +916,24 @@
}
#endif // SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD
+#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
+VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryAndroidHardwareBufferANDROID(VkDevice device, const VkMemoryGetAndroidHardwareBufferInfoANDROID *pInfo, struct AHardwareBuffer **pBuffer)
+{
+ TRACE("(VkDevice device = %p, const VkMemoryGetAndroidHardwareBufferInfoANDROID *pInfo = %p, struct AHardwareBuffer **pBuffer = %p)",
+ device, pInfo, pBuffer);
+
+ return vk::Cast(pInfo->memory)->exportAhb(pBuffer);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetAndroidHardwareBufferPropertiesANDROID(VkDevice device, const struct AHardwareBuffer *buffer, VkAndroidHardwareBufferPropertiesANDROID *pProperties)
+{
+ TRACE("(VkDevice device = %p, const struct AHardwareBuffer *buffer = %p, VkAndroidHardwareBufferPropertiesANDROID *pProperties = %p)",
+ device, buffer, pProperties);
+
+ return vk::DeviceMemory::getAhbProperties(buffer, pProperties);
+}
+#endif // SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
+
VKAPI_ATTR VkResult VKAPI_CALL vkMapMemory(VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void **ppData)
{
TRACE("(VkDevice device = %p, VkDeviceMemory memory = %p, VkDeviceSize offset = %d, VkDeviceSize size = %d, VkMemoryMapFlags flags = %d, void** ppData = %p)",