| // 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. | |
| #include "VkDeviceMemoryExternalAndroid.hpp" | |
| #include "VkDestroy.hpp" | |
| #include "VkFormat.hpp" | |
| #include "VkObject.hpp" | |
| #include "VkPhysicalDevice.hpp" | |
| #include "VkStringify.hpp" | |
| #include "System/Debug.hpp" | |
| namespace { | |
| uint32_t GetAHBFormatFromVkFormat(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_R8_UNORM: | |
| return AHARDWAREBUFFER_FORMAT_R8_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; | |
| case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16: | |
| return AHARDWAREBUFFER_FORMAT_YCbCr_P010; | |
| case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16: | |
| return AHARDWAREBUFFER_FORMAT_YCbCr_P210; | |
| case VK_FORMAT_B8G8R8A8_UNORM: | |
| return AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM; | |
| default: | |
| UNSUPPORTED("AHardwareBufferExternalMemory::VkFormat %d", int(format)); | |
| return 0; | |
| } | |
| } | |
| uint64_t GetAHBLockUsageFromVkImageUsageFlags(VkImageUsageFlags flags) | |
| { | |
| uint64_t usage = 0; | |
| if(flags & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT || | |
| flags & VK_IMAGE_USAGE_SAMPLED_BIT || | |
| flags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) | |
| { | |
| usage |= AHARDWAREBUFFER_USAGE_CPU_READ_MASK; | |
| } | |
| if(flags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT || | |
| flags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) | |
| { | |
| usage |= AHARDWAREBUFFER_USAGE_CPU_WRITE_MASK; | |
| } | |
| return usage; | |
| } | |
| uint64_t GetAHBLockUsageFromVkBufferUsageFlags(VkBufferUsageFlags flags) | |
| { | |
| uint64_t usage = 0; | |
| if(flags & VK_BUFFER_USAGE_TRANSFER_SRC_BIT) | |
| { | |
| usage |= AHARDWAREBUFFER_USAGE_CPU_READ_MASK; | |
| } | |
| if(flags & VK_BUFFER_USAGE_TRANSFER_DST_BIT) | |
| { | |
| usage |= AHARDWAREBUFFER_USAGE_CPU_WRITE_MASK; | |
| } | |
| return usage; | |
| } | |
| uint64_t GetAHBUsageFromVkImageFlags(VkImageCreateFlags createFlags, VkImageUsageFlags usageFlags) | |
| { | |
| uint64_t ahbUsage = 0; | |
| if(usageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) | |
| { | |
| ahbUsage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN; | |
| } | |
| if(usageFlags & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) | |
| { | |
| ahbUsage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN; | |
| } | |
| if(usageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) | |
| { | |
| ahbUsage |= AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN; | |
| } | |
| if(createFlags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) | |
| { | |
| ahbUsage |= AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP; | |
| } | |
| if(createFlags & VK_IMAGE_CREATE_PROTECTED_BIT) | |
| { | |
| ahbUsage |= AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT; | |
| } | |
| // No usage bits set - set at least one GPU usage | |
| if(ahbUsage == 0) | |
| { | |
| ahbUsage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | | |
| AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN; | |
| } | |
| return ahbUsage; | |
| } | |
| uint64_t GetAHBUsageFromVkBufferFlags(VkBufferCreateFlags /*createFlags*/, VkBufferUsageFlags /*usageFlags*/) | |
| { | |
| uint64_t ahbUsage = 0; | |
| // TODO(b/141698760): needs fleshing out. | |
| ahbUsage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN; | |
| return ahbUsage; | |
| } | |
| VkFormatFeatureFlags GetVkFormatFeaturesFromAHBFormat(uint32_t ahbFormat) | |
| { | |
| VkFormatFeatureFlags features = 0; | |
| VkFormat format = AHardwareBufferExternalMemory::GetVkFormatFromAHBFormat(ahbFormat); | |
| 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 | |
| features |= formatProperties.linearTilingFeatures | | |
| formatProperties.optimalTilingFeatures | | |
| formatProperties.bufferFeatures; | |
| return features; | |
| } | |
| } // namespace | |
| AHardwareBufferExternalMemory::AllocateInfo::AllocateInfo(const vk::DeviceMemory::ExtendedAllocationInfo &extendedAllocationInfo) | |
| { | |
| if(extendedAllocationInfo.importAndroidHardwareBufferInfo) | |
| { | |
| importAhb = true; | |
| ahb = extendedAllocationInfo.importAndroidHardwareBufferInfo->buffer; | |
| } | |
| if(extendedAllocationInfo.exportMemoryAllocateInfo) | |
| { | |
| if(extendedAllocationInfo.exportMemoryAllocateInfo->handleTypes == VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) | |
| { | |
| exportAhb = true; | |
| } | |
| else | |
| { | |
| UNSUPPORTED("VkExportMemoryAllocateInfo::handleTypes %d", int(extendedAllocationInfo.exportMemoryAllocateInfo->handleTypes)); | |
| } | |
| } | |
| if(extendedAllocationInfo.dedicatedAllocateInfo) | |
| { | |
| dedicatedImageHandle = vk::Cast(extendedAllocationInfo.dedicatedAllocateInfo->image); | |
| dedicatedBufferHandle = vk::Cast(extendedAllocationInfo.dedicatedAllocateInfo->buffer); | |
| } | |
| } | |
| AHardwareBufferExternalMemory::AHardwareBufferExternalMemory(const VkMemoryAllocateInfo *pCreateInfo, void *mem, const DeviceMemory::ExtendedAllocationInfo &extendedAllocationInfo, vk::Device *pDevice) | |
| : vk::DeviceMemory(pCreateInfo, extendedAllocationInfo, pDevice) | |
| , allocateInfo(extendedAllocationInfo) | |
| { | |
| } | |
| AHardwareBufferExternalMemory::~AHardwareBufferExternalMemory() | |
| { | |
| freeBuffer(); | |
| } | |
| // vkAllocateMemory | |
| VkResult AHardwareBufferExternalMemory::allocateBuffer() | |
| { | |
| if(allocateInfo.importAhb) | |
| { | |
| return importAndroidHardwareBuffer(allocateInfo.ahb, &buffer); | |
| } | |
| else | |
| { | |
| ASSERT(allocateInfo.exportAhb); | |
| return allocateAndroidHardwareBuffer(allocationSize, &buffer); | |
| } | |
| } | |
| void AHardwareBufferExternalMemory::freeBuffer() | |
| { | |
| if(ahb != nullptr) | |
| { | |
| unlockAndroidHardwareBuffer(); | |
| AHardwareBuffer_release(ahb); | |
| ahb = nullptr; | |
| } | |
| } | |
| VkResult AHardwareBufferExternalMemory::importAndroidHardwareBuffer(AHardwareBuffer *buffer, void **pBuffer) | |
| { | |
| ahb = buffer; | |
| AHardwareBuffer_acquire(ahb); | |
| AHardwareBuffer_describe(ahb, &ahbDesc); | |
| return lockAndroidHardwareBuffer(pBuffer); | |
| } | |
| VkResult AHardwareBufferExternalMemory::allocateAndroidHardwareBuffer(size_t size, void **pBuffer) | |
| { | |
| if(allocateInfo.dedicatedImageHandle) | |
| { | |
| vk::Image *image = allocateInfo.dedicatedImageHandle; | |
| ASSERT(image->getArrayLayers() == 1); | |
| VkExtent3D extent = image->getExtent(); | |
| ahbDesc.width = extent.width; | |
| ahbDesc.height = extent.height; | |
| ahbDesc.layers = image->getArrayLayers(); | |
| ahbDesc.format = GetAHBFormatFromVkFormat(image->getFormat()); | |
| ahbDesc.usage = GetAHBUsageFromVkImageFlags(image->getFlags(), image->getUsage()); | |
| } | |
| else if(allocateInfo.dedicatedBufferHandle) | |
| { | |
| vk::Buffer *buffer = allocateInfo.dedicatedBufferHandle; | |
| ahbDesc.width = static_cast<uint32_t>(buffer->getSize()); | |
| ahbDesc.height = 1; | |
| ahbDesc.layers = 1; | |
| ahbDesc.format = AHARDWAREBUFFER_FORMAT_BLOB; | |
| ahbDesc.usage = GetAHBUsageFromVkBufferFlags(buffer->getFlags(), buffer->getUsage()); | |
| } | |
| else | |
| { | |
| // Android Hardware Buffer Buffer Resources: "Android hardware buffers with a format of | |
| // AHARDWAREBUFFER_FORMAT_BLOB and usage that includes AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER can | |
| // be used as the backing store for VkBuffer objects. Such Android hardware buffers have a size | |
| // in bytes specified by their width; height and layers are both 1." | |
| ahbDesc.width = static_cast<uint32_t>(size); | |
| ahbDesc.height = 1; | |
| ahbDesc.layers = 1; | |
| ahbDesc.format = AHARDWAREBUFFER_FORMAT_BLOB; | |
| ahbDesc.usage = AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER | AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN; | |
| } | |
| int ret = AHardwareBuffer_allocate(&ahbDesc, &ahb); | |
| if(ret != 0) | |
| { | |
| return VK_ERROR_OUT_OF_HOST_MEMORY; | |
| } | |
| AHardwareBuffer_describe(ahb, &ahbDesc); | |
| return lockAndroidHardwareBuffer(pBuffer); | |
| } | |
| VkResult AHardwareBufferExternalMemory::lockAndroidHardwareBuffer(void **pBuffer) | |
| { | |
| uint64_t usage = 0; | |
| if(allocateInfo.dedicatedImageHandle) | |
| { | |
| usage = GetAHBLockUsageFromVkImageUsageFlags(allocateInfo.dedicatedImageHandle->getUsage()); | |
| } | |
| else if(allocateInfo.dedicatedBufferHandle) | |
| { | |
| usage = GetAHBLockUsageFromVkBufferUsageFlags(allocateInfo.dedicatedBufferHandle->getUsage()); | |
| } | |
| else | |
| { | |
| usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN; | |
| } | |
| // Empty fence, lock immediately. | |
| int32_t fence = -1; | |
| // Empty rect, lock entire buffer. | |
| ARect *rect = nullptr; | |
| int ret = AHardwareBuffer_lockPlanes(ahb, usage, fence, rect, &ahbPlanes); | |
| if(ret != 0) | |
| { | |
| return VK_ERROR_OUT_OF_HOST_MEMORY; | |
| } | |
| *pBuffer = ahbPlanes.planes[0].data; | |
| return VK_SUCCESS; | |
| } | |
| VkResult AHardwareBufferExternalMemory::unlockAndroidHardwareBuffer() | |
| { | |
| int ret = AHardwareBuffer_unlock(ahb, /*fence=*/nullptr); | |
| if(ret != 0) | |
| { | |
| return VK_ERROR_UNKNOWN; | |
| } | |
| return VK_SUCCESS; | |
| } | |
| VkResult AHardwareBufferExternalMemory::exportAndroidHardwareBuffer(AHardwareBuffer **pAhb) const | |
| { | |
| if(getFlagBit() != VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) | |
| { | |
| return VK_ERROR_OUT_OF_HOST_MEMORY; | |
| } | |
| // 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; | |
| } | |
| VkFormat AHardwareBufferExternalMemory::GetVkFormatFromAHBFormat(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_R8_UNORM: | |
| return VK_FORMAT_R8_UNORM; | |
| 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: | |
| case AHARDWAREBUFFER_FORMAT_YV12: | |
| return VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM; | |
| case AHARDWAREBUFFER_FORMAT_YCbCr_P010: | |
| return VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16; | |
| case AHARDWAREBUFFER_FORMAT_YCbCr_P210: | |
| return VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16; | |
| case AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM: | |
| return VK_FORMAT_B8G8R8A8_UNORM; | |
| default: | |
| UNSUPPORTED("AHardwareBufferExternalMemory::AHardwareBuffer_Format %d", int(ahbFormat)); | |
| return VK_FORMAT_UNDEFINED; | |
| } | |
| } | |
| 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 = GetVkFormatFromAHBFormat(ahbDesc.format); | |
| pFormat->externalFormat = ahbDesc.format; | |
| pFormat->formatFeatures = GetVkFormatFeaturesFromAHBFormat(ahbDesc.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_YCBCR_601; | |
| pFormat->suggestedYcbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW; | |
| pFormat->suggestedXChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN; | |
| pFormat->suggestedYChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN; | |
| // YUV formats are not listed in the AHardwareBuffer Format Equivalence table in the Vulkan spec. | |
| // Clients must use VkExternalFormatANDROID. | |
| if(pFormat->format == VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM || | |
| pFormat->format == VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16 || | |
| pFormat->format == VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16) | |
| { | |
| pFormat->format = VK_FORMAT_UNDEFINED; | |
| } | |
| return VK_SUCCESS; | |
| } | |
| VkResult AHardwareBufferExternalMemory::GetAndroidHardwareBufferProperties(VkDevice &device, const AHardwareBuffer *buffer, VkAndroidHardwareBufferPropertiesANDROID *pProperties) | |
| { | |
| VkResult result = VK_SUCCESS; | |
| AHardwareBuffer_Desc ahbDesc; | |
| AHardwareBuffer_describe(buffer, &ahbDesc); | |
| if(pProperties->pNext != nullptr) | |
| { | |
| result = GetAndroidHardwareBufferFormatProperties(ahbDesc, (VkAndroidHardwareBufferFormatPropertiesANDROID *)pProperties->pNext); | |
| if(result != VK_SUCCESS) | |
| { | |
| return result; | |
| } | |
| } | |
| 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 = GetVkFormatFromAHBFormat(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; | |
| result = vk::Image::Create(vk::NULL_ALLOCATION_CALLBACKS, &info, &Image, vk::Cast(device)); | |
| if(result != VK_SUCCESS) | |
| { | |
| return result; | |
| } | |
| pProperties->allocationSize = vk::Cast(Image)->getMemoryRequirements().size; | |
| vk::destroy(Image, vk::NULL_ALLOCATION_CALLBACKS); | |
| } | |
| return result; | |
| } | |
| int AHardwareBufferExternalMemory::externalImageRowPitchBytes(VkImageAspectFlagBits aspect) const | |
| { | |
| ASSERT(allocateInfo.dedicatedImageHandle != nullptr); | |
| switch(ahbDesc.format) | |
| { | |
| case AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420: | |
| case AHARDWAREBUFFER_FORMAT_YV12: | |
| case AHARDWAREBUFFER_FORMAT_YCbCr_P010: | |
| case AHARDWAREBUFFER_FORMAT_YCbCr_P210: | |
| switch(aspect) | |
| { | |
| case VK_IMAGE_ASPECT_PLANE_0_BIT: | |
| return static_cast<int>(ahbPlanes.planes[0].rowStride); | |
| case VK_IMAGE_ASPECT_PLANE_1_BIT: | |
| return static_cast<int>(ahbPlanes.planes[1].rowStride); | |
| case VK_IMAGE_ASPECT_PLANE_2_BIT: | |
| return static_cast<int>(ahbPlanes.planes[2].rowStride); | |
| default: | |
| UNSUPPORTED("Unsupported aspect %d for AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420", int(aspect)); | |
| return 0; | |
| } | |
| break; | |
| default: | |
| break; | |
| } | |
| return static_cast<int>(ahbPlanes.planes[0].rowStride); | |
| } | |
| // TODO(b/208505033): Treat each image plane data pointer as a separate address instead of an offset. | |
| VkDeviceSize AHardwareBufferExternalMemory::externalImageMemoryOffset(VkImageAspectFlagBits aspect) const | |
| { | |
| ASSERT(allocateInfo.dedicatedImageHandle != nullptr); | |
| switch(ahbDesc.format) | |
| { | |
| case AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420: | |
| case AHARDWAREBUFFER_FORMAT_YV12: | |
| case AHARDWAREBUFFER_FORMAT_YCbCr_P010: | |
| case AHARDWAREBUFFER_FORMAT_YCbCr_P210: | |
| switch(aspect) | |
| { | |
| case VK_IMAGE_ASPECT_PLANE_0_BIT: | |
| return 0; | |
| case VK_IMAGE_ASPECT_PLANE_1_BIT: | |
| return reinterpret_cast<const char *>(ahbPlanes.planes[1].data) - | |
| reinterpret_cast<const char *>(ahbPlanes.planes[0].data); | |
| case VK_IMAGE_ASPECT_PLANE_2_BIT: | |
| return reinterpret_cast<const char *>(ahbPlanes.planes[2].data) - | |
| reinterpret_cast<const char *>(ahbPlanes.planes[0].data); | |
| default: | |
| UNSUPPORTED("Unsupported aspect %d for AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420", int(aspect)); | |
| return 0; | |
| } | |
| break; | |
| default: | |
| break; | |
| } | |
| return 0; | |
| } | |
| #ifdef SWIFTSHADER_DEVICE_MEMORY_REPORT | |
| uint64_t AHardwareBufferExternalMemory::getMemoryObjectId() const | |
| { | |
| uint64_t id = 0; | |
| int ret = AHardwareBuffer_getId(ahb, &id); | |
| ASSERT(ret == 0); | |
| return id; | |
| } | |
| #endif // SWIFTSHADER_DEVICE_MEMORY_REPORT |