Отображение текстуры из ImageReader в Vulkan - PullRequest
0 голосов
/ 16 июня 2020

Я хотел бы знать, можно ли отобразить содержимое текстуры, поступающей из 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; мне кажется, что это неразумно, поскольку в этой ситуации формат может быть проприетарным.

Спасибо!

...