Added support for AndroidHardwareBuffer Bug: b/141698760 Change-Id: I8d3895b2ee79a0ba71f20917ae1edc83dd19dab8 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/48508 Reviewed-by: Trevor Black <vantablack@google.com> Reviewed-by: Nicolas Capens <nicolascapens@google.com> Kokoro-Result: Trevor Black <vantablack@google.com> Kokoro-Result: kokoro <noreply+kokoro@google.com> Presubmit-Ready: Trevor Black <vantablack@google.com> Tested-by: Trevor Black <vantablack@google.com>
diff --git a/src/Android.bp b/src/Android.bp index 332c51f..026e23c 100644 --- a/src/Android.bp +++ b/src/Android.bp
@@ -56,6 +56,7 @@ shared_libs: [ "android.hardware.graphics.mapper@3.0", "android.hardware.graphics.mapper@4.0", + "libdrm", "libnativewindow", "libhardware", "libhidlbase", @@ -590,6 +591,7 @@ shared_libs: [ "android.hardware.graphics.mapper@3.0", "android.hardware.graphics.mapper@4.0", + "libdrm", "libnativewindow", "libhardware", "libhidlbase", @@ -661,7 +663,9 @@ include_dirs: [ "external/swiftshader/third_party/SPIRV-Headers/include", - "external/swiftshader/include" + "external/swiftshader/include", + "external/minigbm", + "external/libdrm" ], }
diff --git a/src/Vulkan/VkDevice.cpp b/src/Vulkan/VkDevice.cpp index 4cdca03..cc0a359 100644 --- a/src/Vulkan/VkDevice.cpp +++ b/src/Vulkan/VkDevice.cpp
@@ -146,6 +146,10 @@ debugger.server = vk::dbg::Server::create(debugger.context, atoi(port)); } #endif // ENABLE_VK_DEBUGGER + +#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER + ahbAddressMap.reset(new AHBAddressMap()); +#endif } void Device::destroy(const VkAllocationCallbacks *pAllocator) @@ -375,4 +379,60 @@ } } +#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER +Device::AHBAddressMap *Device::getAHBAddressMap() const +{ + return ahbAddressMap.get(); +} + +void *Device::AHBAddressMap::query(const uint32_t key) +{ + std::unique_lock<std::mutex> lock(addressMapMutex); + if(addressMap.find(key) == addressMap.end()) + return nullptr; + + return addressMap[key].address; +} + +void Device::AHBAddressMap::add(const uint32_t key, void *value) +{ + std::unique_lock<std::mutex> lock(addressMapMutex); + auto it = addressMap.find(key); + if(it == addressMap.end()) + { + MapValue mv; + mv.refCount = 1; + mv.address = value; + addressMap[key] = mv; + } + else + { + it->second.address = value; + it->second.refCount++; + } +} + +int Device::AHBAddressMap::incrementReference(const uint32_t key) +{ + std::unique_lock<std::mutex> lock(addressMapMutex); + auto it = addressMap.find(key); + if(it == addressMap.end()) + return -1; + + it->second.refCount++; + return it->second.refCount; +} + +int Device::AHBAddressMap::decrementReference(const uint32_t key) +{ + std::unique_lock<std::mutex> lock(addressMapMutex); + auto it = addressMap.find(key); + if(it == addressMap.end()) + return -1; + + it->second.refCount--; + return it->second.refCount; +} +#endif // SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER + } // namespace vk
diff --git a/src/Vulkan/VkDevice.hpp b/src/Vulkan/VkDevice.hpp index 7f67ffa..9fce601 100644 --- a/src/Vulkan/VkDevice.hpp +++ b/src/Vulkan/VkDevice.hpp
@@ -193,6 +193,41 @@ std::shared_ptr<vk::dbg::Server> server; } debugger; #endif // ENABLE_VK_DEBUGGER + +#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER +public: + class AHBAddressMap + { + public: + AHBAddressMap() {} + ~AHBAddressMap() {} + + struct MapValue + { + MapValue() + : refCount(0) + , address(nullptr) + { + } + int refCount; + void *address; + }; + + void *query(const uint32_t key); + int incrementReference(const uint32_t key); + int decrementReference(const uint32_t key); + void add(const uint32_t key, void *value); + + private: + std::map<uint32_t, MapValue> addressMap; + std::mutex addressMapMutex; + }; + + AHBAddressMap *getAHBAddressMap() const; + +private: + std::unique_ptr<AHBAddressMap> ahbAddressMap; +#endif }; using DispatchableDevice = DispatchableObject<Device, VkDevice>;
diff --git a/src/Vulkan/VkDeviceMemory.cpp b/src/Vulkan/VkDeviceMemory.cpp index 84a2a7e..fd47bf5 100644 --- a/src/Vulkan/VkDeviceMemory.cpp +++ b/src/Vulkan/VkDeviceMemory.cpp
@@ -14,54 +14,13 @@ #include "VkDeviceMemory.hpp" #include "VkBuffer.hpp" +#include "VkDeviceMemoryExternalBase.hpp" #include "VkImage.hpp" #include "VkConfig.hpp" namespace vk { -// Base abstract interface for a device memory implementation. -class DeviceMemory::ExternalBase -{ -public: - virtual ~ExternalBase() = default; - - // Allocate the memory according to |size|. On success return VK_SUCCESS - // and sets |*pBuffer|. - virtual VkResult allocate(size_t size, void **pBuffer) = 0; - - // Deallocate previously allocated memory at |buffer|. - virtual void deallocate(void *buffer, size_t size) = 0; - - // Return the handle type flag bit supported by this implementation. - // A value of 0 corresponds to non-external memory. - virtual VkExternalMemoryHandleTypeFlagBits getFlagBit() const = 0; - -#if SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD - virtual VkResult exportFd(int *pFd) const - { - return VK_ERROR_INVALID_EXTERNAL_HANDLE; - } -#endif - -#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER - virtual VkResult exportAhb(struct AHardwareBuffer **pAhb) const - { - return VK_ERROR_INVALID_EXTERNAL_HANDLE; - } -#endif - -#if VK_USE_PLATFORM_FUCHSIA - virtual VkResult exportHandle(zx_handle_t *pHandle) const - { - return VK_ERROR_INVALID_EXTERNAL_HANDLE; - } -#endif - -protected: - ExternalBase() = default; -}; - // Small class describing a given DeviceMemory::ExternalBase derived class. // |typeFlagBit| corresponds to the external memory handle type. // |instanceSize| is the size of each class instance in bytes. @@ -83,7 +42,7 @@ static bool parseCreateInfo(const VkMemoryAllocateInfo *pAllocateInfo, ExternalMemoryTraits *pTraits) { - if(T::supportsAllocateInfo(pAllocateInfo)) + if(T::SupportsAllocateInfo(pAllocateInfo)) { pTraits->typeFlagBit = T::typeFlagBit; pTraits->instanceSize = sizeof(T); @@ -105,7 +64,7 @@ static const VkExternalMemoryHandleTypeFlagBits typeFlagBit = (VkExternalMemoryHandleTypeFlagBits)0; // Always return true as is used as a fallback in findTraits() below. - static bool supportsAllocateInfo(const VkMemoryAllocateInfo *pAllocateInfo) + static bool SupportsAllocateInfo(const VkMemoryAllocateInfo *pAllocateInfo) { return true; } @@ -177,7 +136,7 @@ static const VkExternalMemoryHandleTypeFlagBits typeFlagBit = (VkExternalMemoryHandleTypeFlagBits)(VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT | VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT); - static bool supportsAllocateInfo(const VkMemoryAllocateInfo *pAllocateInfo) + static bool SupportsAllocateInfo(const VkMemoryAllocateInfo *pAllocateInfo) { AllocateInfo info(pAllocateInfo); return info.supported; @@ -235,14 +194,14 @@ static void findTraits(const VkMemoryAllocateInfo *pAllocateInfo, ExternalMemoryTraits *pTraits) { -#if SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD - if(parseCreateInfo<OpaqueFdExternalMemory>(pAllocateInfo, pTraits)) +#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER + if(parseCreateInfo<AHardwareBufferExternalMemory>(pAllocateInfo, pTraits)) { return; } #endif -#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER - if(parseCreateInfo<AHardwareBufferExternalMemory>(pAllocateInfo, pTraits)) +#if SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD + if(parseCreateInfo<OpaqueFdExternalMemory>(pAllocateInfo, pTraits)) { return; } @@ -260,9 +219,10 @@ parseCreateInfo<DeviceMemoryHostExternalBase>(pAllocateInfo, pTraits); } -DeviceMemory::DeviceMemory(const VkMemoryAllocateInfo *pAllocateInfo, void *mem) +DeviceMemory::DeviceMemory(const VkMemoryAllocateInfo *pAllocateInfo, void *mem, Device *pDevice) : size(pAllocateInfo->allocationSize) , memoryTypeIndex(pAllocateInfo->memoryTypeIndex) + , device(pDevice) { ASSERT(size); @@ -270,6 +230,7 @@ findTraits(pAllocateInfo, &traits); traits.instanceInit(mem, pAllocateInfo); external = reinterpret_cast<ExternalBase *>(mem); + external->setDevicePtr(device); } void DeviceMemory::destroy(const VkAllocationCallbacks *pAllocator) @@ -320,7 +281,6 @@ void *DeviceMemory::getOffsetPointer(VkDeviceSize pOffset) const { ASSERT(buffer); - return reinterpret_cast<char *>(buffer) + pOffset; } @@ -354,14 +314,14 @@ #endif #if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER -VkResult DeviceMemory::exportAhb(struct AHardwareBuffer **pAhb) const +VkResult DeviceMemory::exportAndroidHardwareBuffer(struct AHardwareBuffer **pAhb) const { - return external->exportAhb(pAhb); + return external->exportAndroidHardwareBuffer(pAhb); } -VkResult DeviceMemory::getAhbProperties(const struct AHardwareBuffer *buffer, VkAndroidHardwareBufferPropertiesANDROID *pProperties) +VkResult DeviceMemory::GetAndroidHardwareBufferProperties(VkDevice &ahbDevice, const struct AHardwareBuffer *buffer, VkAndroidHardwareBufferPropertiesANDROID *pProperties) { - return AHardwareBufferExternalMemory::getAhbProperties(buffer, pProperties); + return AHardwareBufferExternalMemory::GetAndroidHardwareBufferProperties(ahbDevice, buffer, pProperties); } #endif
diff --git a/src/Vulkan/VkDeviceMemory.hpp b/src/Vulkan/VkDeviceMemory.hpp index 6a388fb..fa04e6a 100644 --- a/src/Vulkan/VkDeviceMemory.hpp +++ b/src/Vulkan/VkDeviceMemory.hpp
@@ -20,10 +20,12 @@ namespace vk { +class Device; + class DeviceMemory : public Object<DeviceMemory, VkDeviceMemory> { public: - DeviceMemory(const VkMemoryAllocateInfo *pCreateInfo, void *mem); + DeviceMemory(const VkMemoryAllocateInfo *pCreateInfo, void *mem, Device *pDevice); static size_t ComputeRequiredAllocationSize(const VkMemoryAllocateInfo *pCreateInfo); @@ -32,8 +34,8 @@ #endif #if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER - VkResult exportAhb(struct AHardwareBuffer **pAhb) const; - static VkResult getAhbProperties(const struct AHardwareBuffer *buffer, VkAndroidHardwareBufferPropertiesANDROID *pProperties); + VkResult exportAndroidHardwareBuffer(struct AHardwareBuffer **pAhb) const; + static VkResult GetAndroidHardwareBufferProperties(VkDevice &device, const struct AHardwareBuffer *buffer, VkAndroidHardwareBufferPropertiesANDROID *pProperties); #endif #if VK_USE_PLATFORM_FUCHSIA @@ -60,6 +62,7 @@ VkDeviceSize size = 0; uint32_t memoryTypeIndex = 0; ExternalBase *external = nullptr; + Device *device; }; static inline DeviceMemory *Cast(VkDeviceMemory object)
diff --git a/src/Vulkan/VkDeviceMemoryExternalAndroid.cpp b/src/Vulkan/VkDeviceMemoryExternalAndroid.cpp new file mode 100644 index 0000000..edeaf2a --- /dev/null +++ b/src/Vulkan/VkDeviceMemoryExternalAndroid.cpp
@@ -0,0 +1,442 @@ +// Copyright 2020 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. + +#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER + +# include "VkDeviceMemoryExternalAndroid.hpp" + +# include "VkDestroy.hpp" +# include "VkDevice.hpp" +# include "VkFormat.hpp" +# include "VkObject.hpp" +# include "VkPhysicalDevice.hpp" + +# include "System/Debug.hpp" +# include "System/Linux/MemFd.hpp" +# include <sys/mman.h> + +# include <android/hardware_buffer.h> +# include <cutils/native_handle.h> +# include <vndk/hardware_buffer.h> + +# include <cros_gralloc/cros_gralloc_handle.h> +# include <unistd.h> +# include <virgl_hw.h> +# include <virtgpu_drm.h> +# include <xf86drm.h> + +AHardwareBufferExternalMemory::~AHardwareBufferExternalMemory() +{ + // correct deallocation of AHB does not require a pointer or size + deallocate(nullptr, 0); +} + +VkResult AHardwareBufferExternalMemory::allocate(size_t size, void **pBuffer) +{ + if(allocateInfo.importAhb) + { + ahb = allocateInfo.ahb; + AHardwareBuffer_acquire(ahb); + return allocateAndroidHardwareBuffer(size, pBuffer); + } + else + { + ASSERT(allocateInfo.exportAhb); + + // Outline ahbDesc + AHardwareBuffer_Desc ahbDesc; + if(allocateInfo.imageHandle) + { + ahbDesc.format = GetAndroidHardwareBufferDescFormat(VkFormat(allocateInfo.imageHandle->getFormat())); + VkExtent3D extent = allocateInfo.imageHandle->getMipLevelExtent(VK_IMAGE_ASPECT_COLOR_BIT, 0); + ahbDesc.width = extent.width; + ahbDesc.height = extent.height; + ahbDesc.layers = allocateInfo.imageHandle->getArrayLayers(); + ahbDesc.stride = allocateInfo.imageHandle->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, 0); + + VkImageCreateFlags createFlags = allocateInfo.imageHandle->getFlags(); + VkImageUsageFlags usageFlags = allocateInfo.imageHandle->getUsage(); + GetAndroidHardwareBufferUsageFromVkUsage(createFlags, usageFlags, ahbDesc.usage); + } + else + { + ASSERT(allocateInfo.bufferHandle); + ahbDesc.format = AHARDWAREBUFFER_FORMAT_BLOB; + ahbDesc.width = uint32_t(allocateInfo.bufferHandle->getSize()); + ahbDesc.height = 1; + ahbDesc.layers = 1; + ahbDesc.stride = uint32_t(allocateInfo.bufferHandle->getSize()); + // TODO(b/141698760) + // This will be fairly specific, needs fleshing out + ahbDesc.usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN; + } + + // create a new ahb from desc + if(AHardwareBuffer_allocate(&ahbDesc, &ahb) != 0) + { + return VK_ERROR_OUT_OF_HOST_MEMORY; + } + + return allocateAndroidHardwareBuffer(size, pBuffer); + } +} + +VkResult AHardwareBufferExternalMemory::allocateAndroidHardwareBuffer(size_t size, void **pBuffer) +{ + // get native_handle_t from ahb + const native_handle_t *h = AHardwareBuffer_getNativeHandle(ahb); + if(h == nullptr) + { + return VK_ERROR_INVALID_EXTERNAL_HANDLE; + } + + // get rendernodeFD and primeHandle from native_handle_t.data + uint32_t primeHandle; + createRenderNodeFD(); + VkResult result = getPrimeHandle(h, primeHandle); + if(result != VK_SUCCESS) + { + return result; + } + + // get memory pointer from store or mmap it + vk::Device::AHBAddressMap *pDeviceHandleMap = device->getAHBAddressMap(); + void *pAddress = pDeviceHandleMap->query(primeHandle); + if(pAddress != nullptr) + { + *pBuffer = pAddress; + pDeviceHandleMap->incrementReference(primeHandle); + } + else + { + // map memory + void *ptr; + VkResult result = mapMemory(primeHandle, &ptr); + if(result != VK_SUCCESS) + { + return result; + } + + // Add primeHandle and ptr to deviceHandleMap + pDeviceHandleMap->add(primeHandle, ptr); + *pBuffer = pDeviceHandleMap->query(primeHandle); + } + + return VK_SUCCESS; +} + +void AHardwareBufferExternalMemory::deallocate(void *buffer, size_t size) +{ + if(ahb != nullptr) + { + const native_handle_t *h = AHardwareBuffer_getNativeHandle(ahb); + uint32_t primeHandle; + VkResult result = getPrimeHandle(h, primeHandle); + ASSERT(result == VK_SUCCESS); + + // close gpu memory and rendernodeFD + vk::Device::AHBAddressMap *pDeviceHandleMap = device->getAHBAddressMap(); + if(pDeviceHandleMap->decrementReference(primeHandle) == 0) + { + closeMemory(primeHandle); + } + close(rendernodeFD); + + AHardwareBuffer_release(ahb); + ahb = nullptr; + } +} + +VkResult AHardwareBufferExternalMemory::exportAndroidHardwareBuffer(struct AHardwareBuffer **pAhb) const +{ + // 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; +} + +uint32_t AHardwareBufferExternalMemory::GetAndroidHardwareBufferDescFormat(VkFormat format) +{ + switch(format) + { + case VK_FORMAT_D16_UNORM: + return AHARDWAREBUFFER_FORMAT_D16_UNORM; + case VK_FORMAT_X8_D24_UNORM_PACK32: + UNSUPPORTED("AHardwareBufferExternalMemory::VkFormat VK_FORMAT_X8_D24_UNORM_PACK32"); + return AHARDWAREBUFFER_FORMAT_D24_UNORM; + case VK_FORMAT_D24_UNORM_S8_UINT: + UNSUPPORTED("AHardwareBufferExternalMemory::VkFormat VK_FORMAT_D24_UNORM_S8_UINT"); + return AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT; + case VK_FORMAT_D32_SFLOAT: + return AHARDWAREBUFFER_FORMAT_D32_FLOAT; + case VK_FORMAT_D32_SFLOAT_S8_UINT: + return AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT; + case VK_FORMAT_A2B10G10R10_UNORM_PACK32: + return AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM; + case VK_FORMAT_R16G16B16A16_SFLOAT: + return AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT; + case VK_FORMAT_R5G6B5_UNORM_PACK16: + return AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM; + case VK_FORMAT_R8G8B8A8_UNORM: + return AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM; + case VK_FORMAT_R8G8B8_UNORM: + return AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM; + case VK_FORMAT_S8_UINT: + return AHARDWAREBUFFER_FORMAT_S8_UINT; + case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM: + return AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420; + default: + UNSUPPORTED("AHardwareBufferExternalMemory::VkFormat %d", int(format)); + return 0; + } +} + +VkFormat AHardwareBufferExternalMemory::GetVkFormat(uint32_t ahbFormat) +{ + switch(ahbFormat) + { + case AHARDWAREBUFFER_FORMAT_BLOB: + return VK_FORMAT_UNDEFINED; + case AHARDWAREBUFFER_FORMAT_D16_UNORM: + return VK_FORMAT_D16_UNORM; + case AHARDWAREBUFFER_FORMAT_D24_UNORM: + UNSUPPORTED("AHardwareBufferExternalMemory::AndroidHardwareBuffer_Format AHARDWAREBUFFER_FORMAT_D24_UNORM"); + return VK_FORMAT_X8_D24_UNORM_PACK32; + case AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT: + UNSUPPORTED("AHardwareBufferExternalMemory::AndroidHardwareBuffer_Format AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT"); + return VK_FORMAT_X8_D24_UNORM_PACK32; + case AHARDWAREBUFFER_FORMAT_D32_FLOAT: + return VK_FORMAT_D32_SFLOAT; + case AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT: + return VK_FORMAT_D32_SFLOAT_S8_UINT; + case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM: + return VK_FORMAT_A2B10G10R10_UNORM_PACK32; + case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT: + return VK_FORMAT_R16G16B16A16_SFLOAT; + case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM: + return VK_FORMAT_R5G6B5_UNORM_PACK16; + case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM: + return VK_FORMAT_R8G8B8A8_UNORM; + case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM: + return VK_FORMAT_R8G8B8A8_UNORM; + case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM: + return VK_FORMAT_R8G8B8_UNORM; + case AHARDWAREBUFFER_FORMAT_S8_UINT: + return VK_FORMAT_S8_UINT; + case AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420: + return VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM; + default: + UNSUPPORTED("AHardwareBufferExternalMemory::AHardwareBuffer_Format %d", int(ahbFormat)); + return VK_FORMAT_UNDEFINED; + } +} + +VkFormatFeatureFlags AHardwareBufferExternalMemory::GetVkFormatFeatures(VkFormat format) +{ + VkFormatProperties formatProperties; + vk::PhysicalDevice::GetFormatProperties(vk::Format(format), &formatProperties); + + formatProperties.optimalTilingFeatures |= VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT; + + // TODO: b/167896057 + // The correct formatFeatureFlags depends on consumer and format + // So this solution is incomplete without more information + return formatProperties.linearTilingFeatures | formatProperties.optimalTilingFeatures | formatProperties.bufferFeatures; +} + +VkResult AHardwareBufferExternalMemory::GetAndroidHardwareBufferFormatProperties(const AHardwareBuffer_Desc &ahbDesc, VkAndroidHardwareBufferFormatPropertiesANDROID *pFormat) +{ + + pFormat->sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID; + pFormat->pNext = nullptr; + + pFormat->format = GetVkFormat(ahbDesc.format); + pFormat->externalFormat = ahbDesc.format; + pFormat->formatFeatures = GetVkFormatFeatures(pFormat->format); + + pFormat->samplerYcbcrConversionComponents = { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY }; + pFormat->suggestedYcbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY; + pFormat->suggestedYcbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL; + pFormat->suggestedXChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN; + pFormat->suggestedYChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN; + + return VK_SUCCESS; +} + +VkResult AHardwareBufferExternalMemory::GetAndroidHardwareBufferProperties(VkDevice &device, const struct AHardwareBuffer *buffer, VkAndroidHardwareBufferPropertiesANDROID *pProperties) +{ + AHardwareBuffer_Desc ahbDesc; + AHardwareBuffer_describe(buffer, &ahbDesc); + + GetAndroidHardwareBufferFormatProperties(ahbDesc, (VkAndroidHardwareBufferFormatPropertiesANDROID *)pProperties->pNext); + + const VkPhysicalDeviceMemoryProperties phyDeviceMemProps = vk::PhysicalDevice::GetMemoryProperties(); + pProperties->memoryTypeBits = phyDeviceMemProps.memoryTypes[0].propertyFlags; + + if(ahbDesc.format == AHARDWAREBUFFER_FORMAT_BLOB) + { + pProperties->allocationSize = ahbDesc.width; + } + else + { + VkImageCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO; + info.pNext = nullptr; + info.flags = 0; + info.imageType = VK_IMAGE_TYPE_2D; + info.format = GetVkFormat(ahbDesc.format); + info.extent.width = ahbDesc.width; + info.extent.height = ahbDesc.height; + info.extent.depth = 1; + info.mipLevels = 1; + info.arrayLayers = 1; + info.samples = VK_SAMPLE_COUNT_1_BIT; + info.tiling = VK_IMAGE_TILING_OPTIMAL; + info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + + VkImage Image; + VkResult result = vk::Image::Create(vk::DEVICE_MEMORY, &info, &Image, vk::Cast(device)); + + pProperties->allocationSize = vk::Cast(Image)->getMemoryRequirements().size; + vk::destroy(Image, vk::DEVICE_MEMORY); + } + + return VK_SUCCESS; +} + +VkResult AHardwareBufferExternalMemory::GetAndroidHardwareBufferUsageFromVkUsage(const VkImageCreateFlags createFlags, const VkImageUsageFlags usageFlags, uint64_t &ahbDescUsage) +{ + if(usageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) + ahbDescUsage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; + if(usageFlags & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) + ahbDescUsage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; + if(usageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) + ahbDescUsage |= AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT; + + if(createFlags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) + ahbDescUsage |= AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP; + if(createFlags & VK_IMAGE_CREATE_PROTECTED_BIT) + ahbDescUsage |= AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT; + + // No usage bits set - set at least one GPU usage + if(ahbDescUsage == 0) + ahbDescUsage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; + + return VK_SUCCESS; +} + +// Call into the native gralloc implementation to request a handle for the +// rendernodeFD +VkResult AHardwareBufferExternalMemory::getPrimeHandle(const native_handle_t *h, uint32_t &primeHandle) +{ + cros_gralloc_handle const *crosHandle = reinterpret_cast<cros_gralloc_handle const *>(h); + int ret = drmPrimeFDToHandle(rendernodeFD, crosHandle->fds[0], &primeHandle); + if(ret != 0) + { + return VK_ERROR_INVALID_EXTERNAL_HANDLE; + } + + return VK_SUCCESS; +} + +// Create a rendernodeFD +void AHardwareBufferExternalMemory::createRenderNodeFD() +{ + rendernodeFD = drmOpenRender(128); +} + +// using a primeHandle associated with a specific rendernodeFD, map a new block +// of memory +VkResult AHardwareBufferExternalMemory::mapMemory(uint32_t &primeHandle, void **ptr) +{ + drm_virtgpu_map map; + memset(&map, 0, sizeof(drm_virtgpu_map)); + map.handle = primeHandle; + int ret = drmIoctl(rendernodeFD, DRM_IOCTL_VIRTGPU_MAP, &map); + if(ret != 0) + { + return VK_ERROR_INVALID_EXTERNAL_HANDLE; + } + + // mmap it + *ptr = static_cast<unsigned char *>( + mmap64(nullptr, 4096, PROT_WRITE, MAP_SHARED, rendernodeFD, map.offset)); + if(ptr == MAP_FAILED) + { + return VK_ERROR_MEMORY_MAP_FAILED; + } + + return VK_SUCCESS; +} + +// Close out the memory block associated with rendernodeFD +VkResult AHardwareBufferExternalMemory::closeMemory(uint32_t &primeHandle) +{ + struct drm_gem_close gem_close; + memset(&gem_close, 0x0, sizeof(gem_close)); + gem_close.handle = primeHandle; + int ret = drmIoctl(rendernodeFD, DRM_IOCTL_GEM_CLOSE, &gem_close); + if(ret != 0) + { + return VK_ERROR_INVALID_EXTERNAL_HANDLE; + } + + return VK_SUCCESS; +} + +AHardwareBufferExternalMemory::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) + { + UNSUPPORTED("VkExportMemoryAllocateInfo::handleTypes %d", int(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: + WARN("VkMemoryAllocateInfo->pNext sType = %s", vk::Stringify(createInfo->sType).c_str()); + } + createInfo = createInfo->pNext; + } +} + +#endif // SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER
diff --git a/src/Vulkan/VkDeviceMemoryExternalAndroid.hpp b/src/Vulkan/VkDeviceMemoryExternalAndroid.hpp index 9bfb381..6292af5 100644 --- a/src/Vulkan/VkDeviceMemoryExternalAndroid.hpp +++ b/src/Vulkan/VkDeviceMemoryExternalAndroid.hpp
@@ -12,14 +12,33 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "VkStringify.hpp" +#ifndef VK_DEVICE_MEMORY_EXTERNAL_ANDROID_HPP_ +#define VK_DEVICE_MEMORY_EXTERNAL_ANDROID_HPP_ -#include "System/Debug.hpp" +#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER -#include <android/hardware_buffer.h> +# include "VkDevice.hpp" +# include "VkDeviceMemory.hpp" +# include "VkDeviceMemoryExternalBase.hpp" -#include <errno.h> -#include <string.h> +# include "VkBuffer.hpp" +# include "VkDeviceMemory.hpp" +# include "VkImage.hpp" +# include "VkStringify.hpp" + +# include "System/Debug.hpp" +# include "System/Linux/MemFd.hpp" + +# include <android/hardware_buffer.h> + +# include <cros_gralloc/cros_gralloc_handle.h> +# include <unistd.h> +# include <virtgpu_drm.h> +# include <xf86drm.h> + +# include <errno.h> +# include <string.h> +# include <map> class AHardwareBufferExternalMemory : public vk::DeviceMemory::ExternalBase { @@ -38,52 +57,12 @@ 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) - { - UNSUPPORTED("VkExportMemoryAllocateInfo::handleTypes %d", int(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: - WARN("VkMemoryAllocateInfo->pNext sType = %s", vk::Stringify(createInfo->sType).c_str()); - } - createInfo = createInfo->pNext; - } - } + AllocateInfo(const VkMemoryAllocateInfo *pAllocateInfo); }; static const VkExternalMemoryHandleTypeFlagBits typeFlagBit = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; - static bool supportsAllocateInfo(const VkMemoryAllocateInfo *pAllocateInfo) + static bool SupportsAllocateInfo(const VkMemoryAllocateInfo *pAllocateInfo) { AllocateInfo info(pAllocateInfo); return (info.importAhb || info.exportAhb) && (info.bufferHandle || info.imageHandle); @@ -94,67 +73,47 @@ { } - ~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 - } + ~AHardwareBufferExternalMemory(); + VkResult allocate(size_t size, void **pBuffer) override; + void deallocate(void *buffer, size_t size) override; + VkResult allocateAndroidHardwareBuffer(size_t size, void **pBuffer); VkExternalMemoryHandleTypeFlagBits getFlagBit() const override { return typeFlagBit; } - VkResult exportAhb(struct AHardwareBuffer **pAhb) const override + VkResult exportAndroidHardwareBuffer(struct AHardwareBuffer **pAhb) const override; + + void setDevicePtr(vk::Device *pDevice) 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; + device = pDevice; } - static VkResult getAhbProperties(const struct AHardwareBuffer *buffer, VkAndroidHardwareBufferPropertiesANDROID *pProperties) + bool isAndroidHardwareBuffer() override { - UNIMPLEMENTED("b/141698760: getAhbProperties"); // FIXME(b/141698760) - return VK_SUCCESS; + return true; } + static uint32_t GetAndroidHardwareBufferDescFormat(VkFormat format); + static VkFormat GetVkFormat(uint32_t ahbFormat); + static VkFormatFeatureFlags GetVkFormatFeatures(VkFormat format); + static VkResult GetAndroidHardwareBufferFormatProperties(const AHardwareBuffer_Desc &ahbDesc, VkAndroidHardwareBufferFormatPropertiesANDROID *pFormat); + static VkResult GetAndroidHardwareBufferProperties(VkDevice &device, const struct AHardwareBuffer *buffer, VkAndroidHardwareBufferPropertiesANDROID *pProperties); + static VkResult GetAndroidHardwareBufferUsageFromVkUsage(const VkImageCreateFlags createFlags, const VkImageUsageFlags usageFlags, uint64_t &ahbDescUsage); + + // All reliance on minigbm and DRM is contained in these functions + VkResult getPrimeHandle(const native_handle_t *h, uint32_t &primeHandle); + void createRenderNodeFD(); + VkResult mapMemory(uint32_t &primeHandle, void **ptr); + VkResult closeMemory(uint32_t &primeHandle); + private: struct AHardwareBuffer *ahb = nullptr; + int rendernodeFD; + vk::Device *device = nullptr; AllocateInfo allocateInfo; }; + +#endif // SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER +#endif // VK_DEVICE_MEMORY_EXTERNAL_ANDROID_HPP_
diff --git a/src/Vulkan/VkDeviceMemoryExternalBase.hpp b/src/Vulkan/VkDeviceMemoryExternalBase.hpp new file mode 100644 index 0000000..428678e --- /dev/null +++ b/src/Vulkan/VkDeviceMemoryExternalBase.hpp
@@ -0,0 +1,66 @@ +// Copyright 2020 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. + +#ifndef VK_DEVICE_MEMORY_EXTERNAL_BASE_HPP_ +#define VK_DEVICE_MEMORY_EXTERNAL_BASE_HPP_ + +#include "VkDeviceMemory.hpp" + +namespace vk { + +// Base abstract interface for a device memory implementation. +class DeviceMemory::ExternalBase +{ +public: + virtual ~ExternalBase() = default; + + // Allocate the memory according to |size|. On success return VK_SUCCESS + // and sets |*pBuffer|. + virtual VkResult allocate(size_t size, void **pBuffer) = 0; + + // Deallocate previously allocated memory at |buffer|. + virtual void deallocate(void *buffer, size_t size) = 0; + + // Return the handle type flag bit supported by this implementation. + // A value of 0 corresponds to non-external memory. + virtual VkExternalMemoryHandleTypeFlagBits getFlagBit() const = 0; + + virtual void setDevicePtr(Device *pDevice) {} + +#if SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD + virtual VkResult exportFd(int *pFd) const + { + return VK_ERROR_INVALID_EXTERNAL_HANDLE; + } +#endif + +#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER + virtual VkResult exportAndroidHardwareBuffer(struct AHardwareBuffer **pAhb) const + { + return VK_ERROR_INVALID_EXTERNAL_HANDLE; + } + + virtual bool isAndroidHardwareBuffer() + { + return false; + } +#endif + +protected: + ExternalBase() = default; +}; + +} // namespace vk + +#endif // VK_DEVICE_MEMORY_EXTERNAL_BASE_HPP_
diff --git a/src/Vulkan/VkDeviceMemoryExternalLinux.hpp b/src/Vulkan/VkDeviceMemoryExternalLinux.hpp index 0763fd9..b4f22fc 100644 --- a/src/Vulkan/VkDeviceMemoryExternalLinux.hpp +++ b/src/Vulkan/VkDeviceMemoryExternalLinux.hpp
@@ -82,7 +82,7 @@ static const VkExternalMemoryHandleTypeFlagBits typeFlagBit = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; - static bool supportsAllocateInfo(const VkMemoryAllocateInfo *pAllocateInfo) + static bool SupportsAllocateInfo(const VkMemoryAllocateInfo *pAllocateInfo) { AllocateInfo info(pAllocateInfo); return info.importFd || info.exportFd;
diff --git a/src/Vulkan/VkImage.hpp b/src/Vulkan/VkImage.hpp index 92979d7..6869d53 100644 --- a/src/Vulkan/VkImage.hpp +++ b/src/Vulkan/VkImage.hpp
@@ -81,6 +81,7 @@ uint32_t getArrayLayers() const { return arrayLayers; } uint32_t getMipLevels() const { return mipLevels; } VkImageUsageFlags getUsage() const { return usage; } + VkImageCreateFlags getFlags() const { return flags; } VkSampleCountFlagBits getSampleCountFlagBits() const { return samples; } const VkExtent3D &getExtent() const { return extent; } VkExtent3D getMipLevelExtent(VkImageAspectFlagBits aspect, uint32_t mipLevel) const; @@ -110,8 +111,11 @@ } bool hasExternalMemory() const { return backingMemory.externalMemory; } VkDeviceMemory getExternalMemory() const; + VkExternalMemoryHandleTypeFlags getSupportedExternalMemoryHandleTypes() const { return supportedExternalMemoryHandleTypes; } #endif + DeviceMemory *deviceMemory = nullptr; + private: void copy(Buffer *buffer, const VkBufferImageCopy ®ion, bool bufferIsSource); VkDeviceSize getStorageSize(VkImageAspectFlags flags) const; @@ -135,7 +139,6 @@ void decodeASTC(const VkImageSubresource &subresource); const Device *const device = nullptr; - DeviceMemory *deviceMemory = nullptr; VkDeviceSize memoryOffset = 0; VkImageCreateFlags flags = 0; VkImageType imageType = VK_IMAGE_TYPE_2D;
diff --git a/src/Vulkan/VkPhysicalDevice.cpp b/src/Vulkan/VkPhysicalDevice.cpp index 165db86..37ff223 100644 --- a/src/Vulkan/VkPhysicalDevice.cpp +++ b/src/Vulkan/VkPhysicalDevice.cpp
@@ -22,41 +22,21 @@ #include <cstring> #include <limits> +#ifdef __ANDROID__ +# include <android/hardware_buffer.h> +#endif + namespace vk { -static void setExternalMemoryProperties(VkExternalMemoryHandleTypeFlagBits handleType, VkExternalMemoryProperties *properties) -{ -#if SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD - if(handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT) - { - properties->compatibleHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; - properties->exportFromImportedHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; - properties->externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT; - 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 #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->exportFromImportedHandleTypes = 0; - properties->externalMemoryFeatures = 0; +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 PhysicalDevice::PhysicalDevice(const void *, void *mem) { @@ -537,7 +517,72 @@ void PhysicalDevice::getProperties(const VkExternalMemoryHandleTypeFlagBits *handleType, VkExternalImageFormatProperties *properties) const { - setExternalMemoryProperties(*handleType, &properties->externalMemoryProperties); + VkExternalMemoryProperties *extMemProperties = &properties->externalMemoryProperties; +#if SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD + if(*handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT) + { + extMemProperties->compatibleHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; + extMemProperties->exportFromImportedHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; + extMemProperties->externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT; + return; + } +#endif +#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER + if(*handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) + { + extMemProperties->compatibleHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; + extMemProperties->exportFromImportedHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; + extMemProperties->externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT; + return; + } +#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 + extMemProperties->compatibleHandleTypes = 0; + extMemProperties->exportFromImportedHandleTypes = 0; + extMemProperties->externalMemoryFeatures = 0; +} + +void PhysicalDevice::getProperties(const VkExternalMemoryHandleTypeFlagBits *handleType, VkExternalBufferProperties *properties) const +{ + VkExternalMemoryProperties *extMemProperties = &properties->externalMemoryProperties; +#if SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD + if(*handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT) + { + extMemProperties->compatibleHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; + extMemProperties->exportFromImportedHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; + extMemProperties->externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT; + return; + } +#endif +#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER + if(*handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) + { + extMemProperties->compatibleHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; + extMemProperties->exportFromImportedHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; + extMemProperties->externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT; + return; + } +#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 + extMemProperties->compatibleHandleTypes = 0; + extMemProperties->exportFromImportedHandleTypes = 0; + extMemProperties->externalMemoryFeatures = 0; } void PhysicalDevice::getProperties(VkSamplerYcbcrConversionImageFormatProperties *properties) const @@ -550,11 +595,46 @@ { properties->sharedImage = VK_FALSE; } + +void PhysicalDevice::getProperties(VkAndroidHardwareBufferUsageANDROID *properties) const +{ + // TODO(b/169439421) + // This AHB could be either a framebuffer, OR a sampled image + // Here we just say it's both + // Need to pass down info on the type of image in question + properties->androidHardwareBufferUsage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT; +} #endif void PhysicalDevice::getProperties(const VkPhysicalDeviceExternalBufferInfo *pExternalBufferInfo, VkExternalBufferProperties *pExternalBufferProperties) const { - setExternalMemoryProperties(pExternalBufferInfo->handleType, &pExternalBufferProperties->externalMemoryProperties); + VkExternalMemoryProperties *properties = &pExternalBufferProperties->externalMemoryProperties; + +#if SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD || SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER + const VkExternalMemoryHandleTypeFlagBits *handleType = &pExternalBufferInfo->handleType; +#endif + +#if SWIFTSHADER_EXTERNAL_MEMORY_OPAQUE_FD + if(*handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT) + { + properties->compatibleHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; + properties->exportFromImportedHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; + properties->externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT; + 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; } void PhysicalDevice::getProperties(const VkPhysicalDeviceExternalFenceInfo *pExternalFenceInfo, VkExternalFenceProperties *pExternalFenceProperties) const @@ -630,7 +710,7 @@ return true; } -void PhysicalDevice::getFormatProperties(Format format, VkFormatProperties *pFormatProperties) const +void PhysicalDevice::GetFormatProperties(Format format, VkFormatProperties *pFormatProperties) { pFormatProperties->linearTilingFeatures = 0; // Unsupported format pFormatProperties->optimalTilingFeatures = 0; // Unsupported format @@ -1047,7 +1127,7 @@ pImageFormatProperties->maxExtent.height = 1 << (vk::MAX_IMAGE_LEVELS_2D - 1); VkFormatProperties props; - getFormatProperties(format, &props); + GetFormatProperties(format, &props); auto features = tiling == VK_IMAGE_TILING_LINEAR ? props.linearTilingFeatures : props.optimalTilingFeatures; if(features & (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) { @@ -1122,7 +1202,7 @@ } } -const VkPhysicalDeviceMemoryProperties &PhysicalDevice::getMemoryProperties() const +const VkPhysicalDeviceMemoryProperties &PhysicalDevice::GetMemoryProperties() { static const VkPhysicalDeviceMemoryProperties properties{ 1, // memoryTypeCount
diff --git a/src/Vulkan/VkPhysicalDevice.hpp b/src/Vulkan/VkPhysicalDevice.hpp index 4c8430b..2daeddc 100644 --- a/src/Vulkan/VkPhysicalDevice.hpp +++ b/src/Vulkan/VkPhysicalDevice.hpp
@@ -46,9 +46,11 @@ void getProperties(VkPhysicalDeviceProtectedMemoryProperties *properties) const; void getProperties(VkPhysicalDeviceSubgroupProperties *properties) const; void getProperties(const VkExternalMemoryHandleTypeFlagBits *handleType, VkExternalImageFormatProperties *properties) const; + void getProperties(const VkExternalMemoryHandleTypeFlagBits *handleType, VkExternalBufferProperties *properties) const; void getProperties(VkSamplerYcbcrConversionImageFormatProperties *properties) const; #ifdef __ANDROID__ void getProperties(VkPhysicalDevicePresentationPropertiesANDROID *properties) const; + void getProperties(VkAndroidHardwareBufferUsageANDROID *properties) const; #endif void getProperties(const VkPhysicalDeviceExternalBufferInfo *pExternalBufferInfo, VkExternalBufferProperties *pExternalBufferProperties) const; void getProperties(const VkPhysicalDeviceExternalFenceInfo *pExternalFenceInfo, VkExternalFenceProperties *pExternalFenceProperties) const; @@ -58,7 +60,7 @@ void getProperties(VkPhysicalDeviceLineRasterizationPropertiesEXT *properties) const; void getProperties(VkPhysicalDeviceProvokingVertexPropertiesEXT *properties) const; - void getFormatProperties(Format format, VkFormatProperties *pFormatProperties) const; + static void GetFormatProperties(Format format, VkFormatProperties *pFormatProperties); void getImageFormatProperties(Format format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties *pImageFormatProperties) const; @@ -67,7 +69,7 @@ VkQueueFamilyProperties *pQueueFamilyProperties) const; void getQueueFamilyProperties(uint32_t pQueueFamilyPropertyCount, VkQueueFamilyProperties2 *pQueueFamilyProperties) const; - const VkPhysicalDeviceMemoryProperties &getMemoryProperties() const; + static const VkPhysicalDeviceMemoryProperties &GetMemoryProperties(); private: const VkPhysicalDeviceLimits &getLimits() const;
diff --git a/src/Vulkan/libVulkan.cpp b/src/Vulkan/libVulkan.cpp index b630658..09cd2b9 100644 --- a/src/Vulkan/libVulkan.cpp +++ b/src/Vulkan/libVulkan.cpp
@@ -75,6 +75,9 @@ # include <android/log.h> # include <hardware/gralloc1.h> # include <sync/sync.h> +# ifdef SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER +# include "VkDeviceMemoryExternalAndroid.hpp" +# endif #endif #include "WSI/VkSwapchainKHR.hpp" @@ -518,7 +521,7 @@ TRACE("GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice = %p, VkFormat format = %d, VkFormatProperties* pFormatProperties = %p)", physicalDevice, (int)format, pFormatProperties); - vk::Cast(physicalDevice)->getFormatProperties(format, pFormatProperties); + vk::PhysicalDevice::GetFormatProperties(format, pFormatProperties); } VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties *pImageFormatProperties) @@ -531,7 +534,7 @@ memset(pImageFormatProperties, 0, sizeof(VkImageFormatProperties)); VkFormatProperties properties; - vk::Cast(physicalDevice)->getFormatProperties(format, &properties); + vk::PhysicalDevice::GetFormatProperties(format, &properties); VkFormatFeatureFlags features; switch(tiling) @@ -656,7 +659,7 @@ { TRACE("(VkPhysicalDevice physicalDevice = %p, VkPhysicalDeviceMemoryProperties* pMemoryProperties = %p)", physicalDevice, pMemoryProperties); - *pMemoryProperties = vk::Cast(physicalDevice)->getMemoryProperties(); + *pMemoryProperties = vk::PhysicalDevice::GetMemoryProperties(); } VK_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *pName) @@ -1085,7 +1088,7 @@ allocationInfo = allocationInfo->pNext; } - VkResult result = vk::DeviceMemory::Create(pAllocator, pAllocateInfo, pMemory); + VkResult result = vk::DeviceMemory::Create(pAllocator, pAllocateInfo, pMemory, vk::Cast(device)); if(result != VK_SUCCESS) { return result; @@ -1141,7 +1144,7 @@ } const VkPhysicalDeviceMemoryProperties &memoryProperties = - vk::Cast(device)->getPhysicalDevice()->getMemoryProperties(); + vk::PhysicalDevice::GetMemoryProperties(); // All SwiftShader memory types support this! pMemoryFdProperties->memoryTypeBits = (1U << memoryProperties.memoryTypeCount) - 1U; @@ -1180,7 +1183,7 @@ } const VkPhysicalDeviceMemoryProperties &memoryProperties = - vk::Cast(device)->getPhysicalDevice()->getMemoryProperties(); + vk::PhysicalDevice::GetMemoryProperties(); // All SwiftShader memory types support this! pMemoryZirconHandleProperties->memoryTypeBits = (1U << memoryProperties.memoryTypeCount) - 1U; @@ -1210,7 +1213,7 @@ TRACE("(VkDevice device = %p, const VkMemoryGetAndroidHardwareBufferInfoANDROID *pInfo = %p, struct AHardwareBuffer **pBuffer = %p)", device, pInfo, pBuffer); - return vk::Cast(pInfo->memory)->exportAhb(pBuffer); + return vk::Cast(pInfo->memory)->exportAndroidHardwareBuffer(pBuffer); } VKAPI_ATTR VkResult VKAPI_CALL vkGetAndroidHardwareBufferPropertiesANDROID(VkDevice device, const struct AHardwareBuffer *buffer, VkAndroidHardwareBufferPropertiesANDROID *pProperties) @@ -1218,7 +1221,7 @@ TRACE("(VkDevice device = %p, const struct AHardwareBuffer *buffer = %p, VkAndroidHardwareBufferPropertiesANDROID *pProperties = %p)", device, buffer, pProperties); - return vk::DeviceMemory::getAhbProperties(buffer, pProperties); + return vk::DeviceMemory::GetAndroidHardwareBufferProperties(device, buffer, pProperties); } #endif // SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER @@ -1271,7 +1274,7 @@ auto memory = vk::Cast(pMemory); #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON) - const auto &memoryProperties = vk::Cast(pDevice)->getPhysicalDevice()->getMemoryProperties(); + const auto &memoryProperties = vk::PhysicalDevice::GetMemoryProperties(); uint32_t typeIndex = memory->getMemoryTypeIndex(); ASSERT(typeIndex < memoryProperties.memoryTypeCount); ASSERT(memoryProperties.memoryTypes[typeIndex].propertyFlags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT); @@ -1669,6 +1672,8 @@ swapchainImage = true; } break; + case VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID: + break; #endif case VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO: // Do nothing. Should be handled by vk::Image::Create() @@ -2862,6 +2867,12 @@ { auto requirements = reinterpret_cast<VkMemoryDedicatedRequirements *>(extensionRequirements); vk::Cast(device)->getRequirements(requirements); +#if SWIFTSHADER_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER + if(vk::Cast(pInfo->image)->getSupportedExternalMemoryHandleTypes() == VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) + { + requirements->requiresDedicatedAllocation = VK_TRUE; + } +#endif } break; default: @@ -3120,6 +3131,14 @@ ASSERT(!hasDeviceExtension(VK_AMD_TEXTURE_GATHER_BIAS_LOD_EXTENSION_NAME)); } break; +#ifdef __ANDROID__ + case VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID: + { + auto properties = reinterpret_cast<VkAndroidHardwareBufferUsageANDROID *>(extensionProperties); + vk::Cast(physicalDevice)->getProperties(properties); + } + break; +#endif default: LOG_TRAP("pImageFormatProperties->pNext sType = %s", vk::Stringify(extensionProperties->sType).c_str()); break;
diff --git a/tests/VulkanBenchmarks/VulkanBenchmarks.cpp b/tests/VulkanBenchmarks/VulkanBenchmarks.cpp index fd0fb84..dd5bb3e 100644 --- a/tests/VulkanBenchmarks/VulkanBenchmarks.cpp +++ b/tests/VulkanBenchmarks/VulkanBenchmarks.cpp
@@ -73,7 +73,7 @@ protected: uint32_t getMemoryTypeIndex(uint32_t typeBits, vk::MemoryPropertyFlags properties) { - vk::PhysicalDeviceMemoryProperties deviceMemoryProperties = physicalDevice.getMemoryProperties(); + vk::PhysicalDeviceMemoryProperties deviceMemoryProperties = vk::PhysicalDevice::GetMemoryProperties(); for(uint32_t i = 0; i < deviceMemoryProperties.memoryTypeCount; i++) { if((typeBits & 1) == 1)