Я хотел бы знать, можно ли отобразить содержимое текстуры, поступающей из ImageReader, с помощью vulkan.
Вот как создается ImageReader
mReader = ImageReader.newInstance(1920, 1080, ImageFormat.PRIVATE, MAX_IMAGE_SIZE + 1);
Изображение содержит защищенное содержимое . На стороне Vulkan я пытаюсь получить аппаратный буфер и создать экземпляр изображения, но уровни проверки жалуются:
(ERROR / SPE C): msgNum: 0 - vkAllocateMemory: The AHardwareBuffer_Des * Формат 1028 * (2141391878) и / или использование (0x20002900) несовместимы с Vulkan. В Vulkan spe c указано: Если буфер не равен NULL, это должен быть допустимый объект аппаратного буфера Android с AHardwareBuffer_Des c :: format и AHardwareBuffer_Des c :: использование, совместимое с Vulkan, как описано в Android Аппаратные буферы. (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID -VkImportAndroidHardwareBufferInfo ANDROID -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))
Я понимаю, что имею дело с частной памятью, однако SPE c, похоже, требует (даже с неизвестными форматами памяти), что Формат AHardwareBuffer_des c должен иметь аналог в Vulkan; мне кажется, что это неразумно, поскольку в этой ситуации формат может быть проприетарным.
Спасибо!