在Android中将外部缓冲区导入Vulkan时出现问题

在Android中将外部缓冲区导入Vulkan时出现问题,android,android-ndk,vulkan,android-mediacodec,Android,Android Ndk,Vulkan,Android Mediacodec,我正在尝试使用Vulkan在Android 10中显示图像。管道看起来像这样 MediaCodec->ImageReader->AHardwareBuffer(传递到Vulkan上下文)->映射到Vulkan->使用Vulkan API显示它 在本机CPP层中,在Vulkan上下文中执行以下操作以导入hardwarebuffer: 查找AHardwareBuffer的属性->创建VkImage->创建设备内存(专用内存)->使用YUVSampler将缓冲区映射到VkImage->Sample 问

我正在尝试使用Vulkan在Android 10中显示图像。管道看起来像这样

MediaCodec->ImageReader->AHardwareBuffer(传递到Vulkan上下文)->映射到Vulkan->使用Vulkan API显示它

在本机CPP层中,在Vulkan上下文中执行以下操作以导入hardwarebuffer: 查找AHardwareBuffer的属性->创建VkImage->创建设备内存(专用内存)->使用YUVSampler将缓冲区映射到VkImage->Sample

问题在于“创建设备内存”是Vulkan验证层显示错误的步骤。它抱怨该格式不受支持。请注意,我使用的是外部格式(规范允许这样做),因此格式处理是不透明的。 这是不工作,现在和我只看到一个黑色的框架,每次。有人能看一下吗?在将AHardwareBuffer导入Vulkan上下文的逻辑中,我遗漏了什么

为什么是外部格式?因为我不能在不同的设备上控制解码器的输出,我想要一些不透明的处理方法

另外,我正在使用以下设置创建ImageReader

ImageReader.newInstance(1920, 1080, ImageFormat.PRIVATE, MAX_IMAGE_SIZE + 1,
    HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE);
下面是Vulkan中的代码,从我收到AHardwareBuffer到验证层认为引起问题的API。我试着只保留与映射相关的代码

VkAndroidHardwareBufferFormatPropertiesANDROID hardwareBufferFormat{
    .sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID,
    .pNext = nullptr,
};

VkAndroidHardwareBufferPropertiesANDROID hardwareBufferProperties{
    .sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID,
    .pNext = &hardwareBufferFormat,
};

/* Find the properties of AHardwareBuffer that is to be imported */
vkGetAndroidHardwareBufferPropertiesANDROID(mLogicalDevice, buffer, &hardwareBufferProperties);

// mTexture.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
VkImage Image_local;
VkExternalFormatANDROID externalFormatAndroid{
    .sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID,
    .pNext = nullptr,
    .externalFormat = hardwareBufferFormat.externalFormat,
};

VkExternalMemoryImageCreateInfo externalMemoryImageCreateInfo{
    .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
    .pNext = &externalFormatAndroid,
    .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,
};

VkImageCreateInfo imageCreateInfo{
    .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
    .pNext = &externalMemoryImageCreateInfo,
    .flags = 0,
    .imageType = VK_IMAGE_TYPE_2D,
    .format = VK_FORMAT_UNDEFINED,
    .extent = {1920, 1080, 1},
    .mipLevels = 1,
    .arrayLayers = hardwareBufferDesc.layers,
    .samples = VK_SAMPLE_COUNT_1_BIT,
    .tiling = VK_IMAGE_TILING_OPTIMAL,
    .usage = VK_IMAGE_USAGE_SAMPLED_BIT,
    .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
    .queueFamilyIndexCount = 0,
    .pQueueFamilyIndices = nullptr,
    .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
};

vkCreateImage(mLogicalDevice, &imageCreateInfo, nullptr, &Image_local);

VkImportAndroidHardwareBufferInfoANDROID hardwareBufferInfo{
    .sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID,
    .pNext = nullptr,
    .buffer = buffer};

VkMemoryDedicatedAllocateInfo memoryDedicatedAllocateInfo{
    .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
    .pNext = &hardwareBufferInfo,
    .image = Image_local,
    .buffer = VK_NULL_HANDLE,
};

uint32_t mem_index = GetMemoryType(hardwareBufferProperties.memoryTypeBits, 0);
VkMemoryAllocateInfo memoryAllocateInfo{
    .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
    .pNext = &memoryDedicatedAllocateInfo,
    .allocationSize = hardwareBufferProperties.allocationSize,
    .memoryTypeIndex = mem_index,
};

/* So this API here does not return any erros, however the validation layer says that the format
 * is not supported. I am using an external Format, so assuming that this should not complain.
 */
vkAllocateMemory(mLogicalDevice, &memoryAllocateInfo, nullptr, &mTexture.deviceMemory)

不确定这是否是答案,但通过阅读一些其他执行此操作的代码和规范,它看起来像hardwareBufferFormat.format可以是未定义的VK_格式,但也可以是有效的VK_格式,可以写入VkImageCreateInfo。只有当该成员为VK_FORMAT_UNDEFINED时,才需要使用externalFormat成员。@LewisGordon在我的例子中,格式为VK_FORMAT_UNDEFINED。所以我必须使用externalFormat。externalFormat是一个非零的大值。不确定这是否是答案,但通过阅读其他执行此操作的代码和规范,它看起来像hardwareBufferFormat.format可以是未定义的VK_格式,但也可以是可以写入VkImageCreateInfo的有效VK_格式。只有当该成员为VK_FORMAT_UNDEFINED时,才需要使用externalFormat成员。@LewisGordon在我的例子中,格式为VK_FORMAT_UNDEFINED。所以我必须使用externalFormat。externalFormat是一个非零的大值。