我正在尝试使用 Vulkan 在 Android 10 中显示图像。管道看起来像这样
MediaCodec -> ImageReader -> AHardwareBuffer(传递到 Vulkan 上下文) -> 映射到 Vulkan -> 使用 Vulkan API 显示它
在 Native CPP 层中,在 Vulkan Context 中完成以下操作以导入 hardwarebuffer:查找 AHardwareBuffer 的属性 -> 创建 VkImage ->创建设备内存(专用内存)-> 将缓冲区映射到 VkImage -> 使用 YUVSampler 进行采样
问题在于“创建设备内存”是 Vulkan 验证层显示错误的步骤。它抱怨该格式不受支持。请注意,我使用的是外部格式(SPEC 允许这样做),因此格式处理是不透明的。
这现在不起作用,我每次都只看到一个黑框。有人可以评论一下吗?我在将 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)