android - 在 Vulkan 中显示来自 ImageReader 的纹理
问题描述
我想知道是否可以使用 vulkan 显示来自 ImageReader 的纹理内容。
这就是创建 ImageReader 的方式
mReader = ImageReader.newInstance(1920, 1080, ImageFormat.PRIVATE, MAX_IMAGE_SIZE + 1);
图像包含安全内容。在 Vulkan 方面,我尝试获取硬件缓冲区并实例化图像,但验证层抱怨:
(ERROR / SPEC): msgNum: 0 - vkAllocateMemory: AHardwareBuffer_Desc 的格式 (2141391878) 和/或用法 (0x20002900) 与 Vulkan 不兼容。Vulkan 规范规定:如果 buffer 不为 NULL,则它必须是有效的 Android 硬件缓冲区对象,其 AHardwareBuffer_Desc::format 和 AHardwareBuffer_Desc::usage 与 Vulkan 兼容,如 Android 硬件缓冲区中所述。( https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkImportAndroidHardwareBufferInfoANDROID-buffer-01881 )
问题是 AHardwareBuffer 不是我创建的,是由 ImageReader 类创建的。
这是 C++ 端的代码:
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,
};
vkGetAndroidHardwareBufferPropertiesANDROID(mLogicalDevice, buffer, &hardwareBufferProperties);
LOGD("Size %lu MemType %s format 0x%X extFormat 0x%lX flags 0x%X",
hardwareBufferProperties.allocationSize,
GetMemoryTypeString(hardwareBufferProperties.memoryTypeBits).c_str(),
hardwareBufferFormat.format, hardwareBufferFormat.externalFormat,
hardwareBufferFormat.formatFeatures);
LOGD("Flags: \n%s", GetFeatureFlagBitsString(hardwareBufferFormat.formatFeatures).c_str());
LOGD("AHardwareBuffer format in vulkan is %d", hardwareBufferFormat.format);
//VkFormat fmt = vk_format_from_android(hardwareBufferFormat.format, 0 );
AHardwareBuffer_Desc hardwareBufferDesc{};
AHardwareBuffer_describe(buffer, &hardwareBufferDesc);
// Width and Height must be same as per spec
mTexture.width = hardwareBufferDesc.width;
mTexture.height = hardwareBufferDesc.height;
mTexture.mipLevels = 1;
mTexture.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
LOGD("Image width x height %dx%d", mTexture.width, mTexture.height);
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,
};
VkAndroidHardwareBufferUsageANDROID hardwareBufferUsage {};
VkImageFormatProperties2 properties {};
VkPhysicalDeviceImageFormatInfo2 deviceImageFormat {};
VkImageCreateInfo imageCreateInfo{
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
.pNext = &externalMemoryImageCreateInfo,
.flags = 0,
.imageType = VK_IMAGE_TYPE_2D,
.format = VK_FORMAT_UNDEFINED,
.extent = {mTexture.width, mTexture.height, 1},
.mipLevels = mTexture.mipLevels,
.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_PREINITIALIZED,
};
CHECK_VK_RESULT(vkCreateImage(mLogicalDevice, &imageCreateInfo, nullptr, &mTexture.image));
// AHardwareBuffer_Desc::format and AHardwareBuffer_Desc::usage must be valid and compatible
// with Vulkan
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 = mTexture.image,
.buffer = VK_NULL_HANDLE,
};
/* TODO: Double check memoryTypeBits and using VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT */
uint32_t mem_index = GetMemoryType(hardwareBufferProperties.memoryTypeBits, 0);
if (mem_index < 0) {
LOGE("Could not find matching memory type!");
return VK_ERROR_INITIALIZATION_FAILED;
}
VkMemoryAllocateInfo memoryAllocateInfo{
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.pNext = &memoryDedicatedAllocateInfo,
.allocationSize = hardwareBufferProperties.allocationSize,
.memoryTypeIndex = mem_index};
// THIS IS WHERE THE VALIDATION THROWS ERROR
CHECK_VK_RESULT(
vkAllocateMemory(mLogicalDevice, &memoryAllocateInfo, nullptr, &mTexture.deviceMemory))
我知道正在处理私有内存,但规范似乎要求(即使是未知的内存格式)AHardwareBuffer_desc 格式必须是在 Vulkan 中具有等价物的东西;在我看来这是不合理的,因为在这种情况下,格式可能是专有的。
谢谢!
解决方案
推荐阅读
- arrays - 这个问题是否存在任何 O(1) 解决方案?
- php - 尽管输入已输入,但请求包含 null
- python - 从 bitbucket 服务器检索 python 脚本中提交的哈希值
- docker - prometheus 无法访问节点导出器
- python - Cron 运行我的 Python 脚本,但没有任何反应
- python - 如何在纯函数式工作流中使用 python 迭代器
- javascript - 在网站上显示当地天气和时间
- wso2 - API 3.1.0 和 BPS (EI 6.6.0) 中的用户注册工作流程
- java - Java Buffered Reader 的 readline() 读取结果为 null 是怎么回事?
- swiftui - 在 SwiftUI 中声明这么多函数是否可取?