Как реализовать Vulkan

Vulkan – это кроссплатформенный API с низкими накладными расходами для высокопроизводительной 3D-графики. Как и OpenGL ES (GLES), Vulkan предоставляет инструменты для создания высококачественной графики в реальном времени. Преимущества Vulkan включают снижение нагрузки на ЦП и поддержку промежуточного двоичного языка SPIR-V.

Чтобы реализовать Vulkan, устройство должно включать:

  • Загрузчик Vulkan, предоставляемый Android.
  • Драйвер Vulkan, предоставляемый SoC, например GPU IHV, который реализует Vulkan API. Чтобы поддерживать функции Vulkan, устройству Android требуется графический процессор с поддержкой Vulkan и соответствующий драйвер. Кроме того, графический процессор должен поддерживать GLES 3.1 и более поздние версии. Обратитесь к поставщику процессора, чтобы запросить поддержку драйвера.

Если на устройстве установлен драйвер Vulkan, в нем должны быть объявлены системные функции FEATURE_VULKAN_HARDWARE_LEVEL и FEATURE_VULKAN_HARDWARE_VERSION с версиями, которые точно отражают возможности устройства. Это помогает убедиться, что устройство соответствует требованиям документа с определением совместимости (CDD).

Загрузчик Vulkan

Загрузчик Vulkan platform/frameworks/native/vulkan – это основной интерфейс между приложениями Vulkan и драйвером Vulkan устройства. Загрузчик Vulkan устанавливается в папку /system/lib[64]/libvulkan.so. Загрузчик предоставляет основные точки входа Vulkan API, точки входа расширений, необходимых для Android CDD, и многие дополнительные необязательные расширения. Расширения для интеграции с системой (WSI) экспортируются загрузчиком и в основном реализуются в нем, а не в драйвере. Загрузчик также поддерживает перечисление и загрузку уровней, которые могут предоставлять дополнительные расширения и перехватывать основные вызовы API на пути к драйверу.

NDK включает библиотеку-заглушку libvulkan.so для связывания. Библиотека экспортирует те же символы, что и загрузчик. Приложения вызывают функции, экспортированные из реальной библиотеки libvulkan.so, чтобы войти в функции-трамплины в загрузчике, которые отправляют вызов соответствующему слою или драйверу на основе первого аргумента. Вызов vkGet*ProcAddr() возвращает указатели на функции, к которым переходят трамплины (то есть напрямую вызывает код основного API). Вызов через указатели функций, а не экспортированные символы, более эффективен, поскольку позволяет пропустить трамплин и диспетчеризацию.

Перечисление и загрузка драйверов

Когда создается образ системы, Android ожидает, что система знает, какие графические процессоры доступны. Загрузчик использует существующий механизм HAL в hardware.h для обнаружения и загрузки драйвера. Рекомендуемые пути для 32- и 64-разрядных драйверов Vulkan:

/vendor/lib/hw/vulkan.<ro.hardware.vulkan>.so
/vendor/lib/hw/vulkan.<ro.board.platform>.so
/vendor/lib64/hw/vulkan.<ro.hardware.vulkan>.so
/vendor/lib64/hw/vulkan.<ro.board.platform>.so

В Android 7.0 и более поздних версиях производная Vulkan hw_module_t содержит одну структуру hw_module_t. Поддерживается только один драйвер, а постоянная строка HWVULKAN_DEVICE_0 передается в open().

Производная Vulkan hw_device_t соответствует одному драйверу, который может поддерживать несколько физических устройств. Структуру hw_device_t можно использовать для функций экспорта vkGetGlobalExtensionProperties(), vkCreateInstance() и vkGetInstanceProcAddr(). Загрузчик может найти все остальные функции VkInstance(), VkPhysicalDevice() и vkGetDeviceProcAddr(), вызвав vkGetInstanceProcAddr() структуры hw_device_t.

В Android 15 и более поздних версиях загрузчик поддерживает APEX для загрузки драйвера Vulkan. Укажите в качестве значения ro.vulkan.apex название APEX-пакета Vulkan, чтобы загрузить Vulkan из этого пакета.

Обнаружение и загрузка слоев

Загрузчик Vulkan поддерживает перечисление и загрузку слоев, которые могут предоставлять дополнительные расширения и перехватывать основные вызовы API на пути к драйверу. Приложения могут включать слои в свои APK-файлы. В образе системы Android нет слоев.

При использовании слоев учитывайте, что модель безопасности и правила Android значительно отличаются от других платформ. В частности, Android не позволяет загружать внешний код в процесс, который нельзя отлаживать, на рабочих (не взломанных) устройствах, а также не позволяет внешнему коду проверять или контролировать память, состояние и другие параметры процесса. В частности, запрещено сохранять на диск дампы памяти, трассировки API и другие данные для последующего анализа. На серийных устройствах включены только слои, поставляемые в составе приложений, не предназначенных для отладки. Драйверы не должны предоставлять функции, нарушающие эти правила.

Примеры использования слоев:

  • Слои времени разработки – слои проверки и прокладки для инструментов трассировки, профилирования и отладки не должны быть установлены в системном образе производственных устройств. Уровни проверки и прокладки для инструментов трассировки, профилирования и отладки должны обновляться без образа системы. Разработчики, которые хотят использовать один из этих слоев во время разработки, могут изменить пакет приложения, например добавив файл в каталог нативных библиотек. Предполагается, что инженеры IHV и OEM, которые хотят диагностировать сбои в поставляемых неизменяемых приложениях, имеют доступ к непроизводственным (с настроенным root-доступом) сборкам образа системы, если только эти приложения не доступны для отладки. Подробнее о слоях проверки Vulkan в Android…
  • Служебные уровни. Эти уровни предоставляют доступ к расширениям, например к уровню, который реализует управление памятью для памяти устройства. Разработчики выбирают слои и их версии для использования в своих приложениях. В разных приложениях, использующих один и тот же слой, могут быть разные версии. Разработчики выбирают, какие из этих уровней включить в пакет приложения.
  • Внедренные (неявные) слои – это слои, которые добавляются пользователем или другим приложением без ведома или согласия приложения, например слои с частотой кадров, социальными сетями и оверлеями игровых платформ. Они нарушают правила безопасности Android и не поддерживаются.

Для приложений, которые нельзя отлаживать, загрузчик ищет слои только в каталоге нативных библиотек приложения и пытается загрузить любую библиотеку с названием, соответствующим определенному шаблону (например, libVKLayer_foo.so). Эти слои загружаются в пространство имен приложения. Поэтому их необходимо создавать с помощью NDK.

Для приложений с возможностью отладки загрузчик ищет слои в каталоге /data/local/debug/vulkan и пытается загрузить любую библиотеку, соответствующую определенному шаблону. Начиная с Android 10 (уровень API 29), Vulkan также может загружать слои времени разработки из другого APK. В обоих случаях загрузчик выбирает, какие слои включить для каждого приложения, используя системные настройки. Эти уровни перечислены в vkEnumerateInstanceLayerProperties (то есть приложение может знать о них), даже если они загружены без согласия приложения.

Android позволяет переносить слои с изменениями среды сборки между Android и другими платформами. Подробнее об интерфейсе между уровнями и загрузчиком можно узнать в статье Архитектура интерфейсов загрузчика Vulkan. Уровни проверки, поддерживаемые Khronos, размещены в Vulkan Validation Layers.

Версии и возможности Vulkan API

В таблице ниже перечислены версии Vulkan API для разных версий Android.
Версия Android Версия Vulkan
Android 16 Vulkan 1.4
Android 13 Vulkan 1.3
Android 9 Vulkan 1.1
Android 7 Vulkan 1.0

Обзор функций Vulkan 1.4

В Vulkan 1.4 ряд ранее необязательных расширений стали основными функциями. Большая часть этих функций предназначена для того, чтобы повысить уровень контроля и детализации программного интерфейса Vulkan. По сравнению с Vulkan 1.3, в Vulkan 1.4 повышены требования к оборудованию. Большая часть реализации находится в графическом драйвере, предназначенном для определенной системы на кристалле, а не в фреймворке.

Обзор функций Vulkan 1.3

В Vulkan 1.3 ряд ранее необязательных расширений стал частью основных функций. Многие из этих функций добавлены для того, чтобы обеспечить более точное управление интерфейсом программирования Vulkan. Для экземпляров проходов рендеринга с одним проходом больше не нужны объекты проходов рендеринга или буферы кадров. Общее количество объектов состояния конвейера можно уменьшить, а синхронизация в API полностью переработана. У Vulkan 1.3 те же требования к оборудованию, что и у Vulkan 1.2, 1.1 и 1.0. Большая часть реализации находится в графическом драйвере, предназначенном для определенной системы на кристалле, а не в фреймворке.

Наиболее важные функции Vulkan 1.3 для Android:

  • Поддержка экземпляров проходов рендеринга с одним проходом
  • Поддержка немедленного завершения вызова шейдера
  • Более точное управление созданием, предоставлением доступа и контролем над конвейерами.

В Vulkan 1.3 также есть несколько небольших функций и улучшений удобства использования API. Все изменения, внесенные в основной Vulkan API в рамках незначительной версии 1.3, можно найти на странице Core Revisions (Vulkan 1.3).

Обзор функций Vulkan 1.2

В Vulkan 1.2 добавлено несколько функций и расширений, которые упрощают поверхность API. В частности, это единая модель памяти и дополнительная информация, которую можно запросить у драйвера устройства. У Vulkan 1.2 те же требования к оборудованию, что и у Vulkan 1.0 и 1.1. Все реализации находятся в графическом драйвере, предназначенном для определенной системы на кристалле, а не в фреймворке.

Самая важная функция Vulkan 1.2 для Android – поддержка 8-битного хранилища.

Vulkan 1.2 также включает несколько небольших функций и улучшений удобства использования API. Все изменения, внесенные в основной API Vulkan в рамках незначительной версии 1.2, можно найти на странице Core Revisions (Vulkan 1.2).

Обзор функций Vulkan 1.1

Vulkan 1.1 поддерживает взаимодействие памяти и синхронизации, что позволяет производителям устройств поддерживать Vulkan 1.1 на своих устройствах. Кроме того, совместимость памяти и синхронизации позволяет разработчикам определять, поддерживается ли Vulkan 1.1 на устройстве, и эффективно использовать его, если это так. Vulkan 1.1 имеет те же требования к оборудованию, что и Vulkan 1.0, но большая часть реализации находится в графическом драйвере, специфичном для SOC, а не в платформе.

Наиболее важные функции Vulkan 1.1 для Android:

  • Поддержка импорта и экспорта буферов памяти и объектов синхронизации извне Vulkan (для взаимодействия с камерой, кодеками и GLES)
  • Поддержка форматов YCbCr

Vulkan 1.1 также включает несколько небольших функций и улучшений удобства использования API. Все изменения, внесенные в основной Vulkan API с незначительной версией 1.1, можно найти на странице Core Revisions (Vulkan 1.1).

Выберите поддержку Vulkan

Все устройства Android должны поддерживать самый продвинутый набор функций Vulkan, если они поддерживают 64-разрядный ABI и не имеют малый объем памяти.

Устройства, которые изначально поставляются с Android 16 или более поздней версией, должны поддерживать Vulkan 1.4.

Устройства, выпущенные с Android 13 и более поздними версиями, должны поддерживать Vulkan 1.3.

Устройства, выпущенные с Android 10, должны поддерживать Vulkan 1.1.

Другие устройства могут поддерживать Vulkan 1.4, 1.3, 1.2 и 1.1.

Как добавить поддержку версии Vulkan

Устройство Android поддерживает версию Vulkan, если выполняются следующие условия:

  1. Добавьте драйвер Vulkan, поддерживающий нужную версию Vulkan (1.4, 1.3, 1.1 или 1.0), а также дополнительные требования CDD для версии Android. Вы также можете обновить существующий драйвер Vulkan более ранней версии.
  2. Для Vulkan 1.4, 1.3 или 1.1 убедитесь, что системная функция, возвращаемая менеджером пакетов, возвращает true для правильной версии Vulkan.
    • Для Vulkan 1.4 функция имеет значение PackageManager#hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_VERSION, 0x404000).
    • Для Vulkan 1.3 функция имеет значение PackageManager#hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_VERSION, 0x403000).
    • Для Vulkan 1.1 функция имеет значение PackageManager#hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_VERSION, 0x401000).
    Менеджер пакетов вернет значение true для Vulkan 1.4, 1.3 и 1.1, добавив правило, показанное ниже, в подходящий файл device.mk.
    • Для Vulkan 1.4 добавьте следующее:
      PRODUCT_COPY_FILES += frameworks/native/data/etc/android.hardware.vulkan.version-1_4.xml:
      $(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.vulkan.version.xml
    • Для Vulkan 1.3 добавьте следующее:
      PRODUCT_COPY_FILES += frameworks/native/data/etc/android.hardware.vulkan.version-1_3.xml:
      $(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.vulkan.version.xml
    • Для Vulkan 1.1 добавьте следующее:
      PRODUCT_COPY_FILES += frameworks/native/data/etc/android.hardware.vulkan.version-1_1.xml:
      $(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.vulkan.version.xml

Профиль базовой конфигурации Android (ABP)

Мы рекомендуем всем устройствам Android соответствовать последнему профилю Android Baseline 2022, как описано в руководстве по профилю Android Baseline.

Любое устройство, поддерживающее Android 14 или более позднюю версию и Vulkan API, должно соответствовать всем требованиям, определенным в базовом профиле Android 2021. Полный список необходимых функций приведен в файле профиля Vulkan json, но ключевые из них перечислены ниже:

  • Сжатые текстуры (ASTC и ETC).
  • Переменные цветовые пространства через VK_EXT_swapchain_colorspace.
  • Затенение выборки и мультивыборочная интерполяция с помощью sampleRateShading.

Интеграция оконной системы (WSI)

В libvulkan.so драйвер реализует следующие расширения интеграции оконной системы (WSI):

  • VK_KHR_surface
  • VK_KHR_android_surface
  • VK_KHR_swapchain
  • VK_KHR_driver_properties, реализованное для Vulkan 1.1 только в Android 10.
  • VK_GOOGLE_display_timing, реализованный для любой версии Vulkan в Android 10.

Объекты VkSurfaceKHR и VkSwapchainKHR, а также все взаимодействия с ANativeWindow обрабатываются платформой и не показываются водителям. Реализация WSI основана на расширении VK_ANDROID_native_buffer, которое должно поддерживаться драйвером. Это расширение используется только реализацией WSI и недоступно для приложений.

Флаги использования Gralloc

Для реализации Vulkan может потребоваться, чтобы буферы цепочки обмена были выделены с помощью частных флагов использования Gralloc, определенных реализацией. При создании цепочки обмена Android просит драйвер преобразовать запрошенный формат и флаги использования изображений в флаги использования Gralloc, вызывая:

typedef enum VkSwapchainImageUsageFlagBitsANDROID {
    VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID = 0x00000001,
    VK_SWAPCHAIN_IMAGE_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkSwapchainImageUsageFlagBitsANDROID;
typedef VkFlags VkSwapchainImageUsageFlagsANDROID;

VkResult VKAPI vkGetSwapchainGrallocUsage2ANDROID(
    VkDevice                          device,
    VkFormat                          format,
    VkImageUsageFlags                 imageUsage,
    VkSwapchainImageUsageFlagsANDROID swapchainUsage,
    uint64_t*                         grallocConsumerUsage,
    uint64_t*                         grallocProducerUsage
);

Параметры format и imageUsage берутся из структуры VkSwapchainCreateInfoKHR. Водитель должен заполнить поля *grallocConsumerUsage и *grallocProducerUsage флагами использования Gralloc, необходимыми для формата и использования. Флаги использования, возвращаемые драйвером, объединяются с флагами использования, запрошенными потребителем цепочки буферов при выделении буферов.

Android 7.x вызывает более раннюю версию VkSwapchainImageUsageFlagsANDROID(), которая называется vkGetSwapchainGrallocUsageANDROID(). В Android 8.0 и более поздних версиях функция vkGetSwapchainGrallocUsageANDROID() считается устаревшей, но по-прежнему вызывается vkGetSwapchainGrallocUsageANDROID(), если драйвер не предоставляет функцию vkGetSwapchainGrallocUsage2ANDROID():

VkResult VKAPI vkGetSwapchainGrallocUsageANDROID(
    VkDevice            device,
    VkFormat            format,
    VkImageUsageFlags   imageUsage,
    int*                grallocUsage
);

vkGetSwapchainGrallocUsageANDROID() не поддерживает флаги использования цепочки буферов или расширенные флаги использования Gralloc.

Изображения на основе Gralloc

VkNativeBufferANDROID – это структура расширения vkCreateImage для создания изображения на основе буфера Gralloc. VkNativeBufferANDROID предоставляется vkCreateImage() в цепочке структур VkImageCreateInfo. Звонки на номер vkCreateImage() с абонентом VkNativeBufferANDROID происходят во время звонка на номер vkCreateSwapchainKHR. При реализации WSI выделяется количество нативных буферов, запрошенных для цепочки обмена, а затем для каждого из них создается VkImage:

typedef struct {
    VkStructureType             sType; // must be VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID
    const void*                 pNext;

    // Buffer handle and stride returned from gralloc alloc()
    buffer_handle_t             handle;
    int                         stride;

    // Gralloc format and usage requested when the buffer was allocated.
    int                         format;
    int                         usage;
    // Beginning in Android 8.0, the usage field above is deprecated and the
    // usage2 struct below was added. The usage field is still filled in for
    // compatibility with Android 7.0 drivers. Drivers for Android 8.0
    // should prefer the usage2 struct, especially if the
    // android.hardware.graphics.allocator HAL uses the extended usage bits.
    struct {
        uint64_t                consumer;
        uint64_t                producer;
    } usage2;
} VkNativeBufferANDROID;

При создании изображения с поддержкой Gralloc VkImageCreateInfo имеет следующие данные:

  .sType               = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
  .pNext               = the above VkNativeBufferANDROID structure
  .imageType           = VK_IMAGE_TYPE_2D
  .format              = a VkFormat matching the format requested for the gralloc buffer
  .extent              = the 2D dimensions requested for the gralloc buffer
  .mipLevels           = 1
  .arraySize           = 1
  .samples             = 1
  .tiling              = VK_IMAGE_TILING_OPTIMAL
  .usage               = VkSwapchainCreateInfoKHR::imageUsage
  .flags               = 0
  .sharingMode         = VkSwapchainCreateInfoKHR::imageSharingMode
  .queueFamilyCount    = VkSwapchainCreateInfoKHR::queueFamilyIndexCount
  .pQueueFamilyIndices = VkSwapchainCreateInfoKHR::pQueueFamilyIndices

В Android 8.0 и более поздних версий платформа предоставляет структуру расширения VkSwapchainImageCreateInfoKHR в цепочке VkImageCreateInfo, переданной в vkCreateImage, когда для цепочки обмена требуются флаги использования изображений цепочки обмена. Структура расширения содержит флаги использования изображений цепочки буферов:

typedef struct {
    VkStructureType                        sType; // must be VK_STRUCTURE_TYPE_SWAPCHAIN_IMAGE_CREATE_INFO_ANDROID
    const void*                            pNext;

    VkSwapchainImageUsageFlagsANDROID      usage;
} VkSwapchainImageCreateInfoANDROID;

В Android 10 и более поздних версиях платформа поддерживает VK_KHR_swapchain версии 70, поэтому приложение Vulkan может создать VkImage, поддерживаемый памятью цепочки обмена. Сначала приложение вызывает vkCreateImage со структурой VkImageSwapchainCreateInfoKHR, связанной со структурой VkImageCreateInfo. Затем приложение вызывает vkBindImageMemory2(KHR) со структурой VkBindImageMemorySwapchainInfoKHR, связанной со структурой VkBindImageMemoryInfo. Значение imageIndex, указанное в структуре VkBindImageMemorySwapchainInfoKHR, должно быть действительным индексом изображения цепочки буферов. В то же время платформа предоставляет цепочке VkBindImageMemoryInfo структуру расширения VkNativeBufferANDROID с соответствующей информацией о буфере Gralloc, чтобы драйвер знал, какой буфер Gralloc нужно связать с VkImage.

Как получить изображения

vkAcquireImageANDROID получает право собственности на изображение цепочки буферов и импортирует внешний сигнальный собственный барьер в существующий объект VkSemaphore и существующий объект VkFence:

VkResult VKAPI vkAcquireImageANDROID(
    VkDevice            device,
    VkImage             image,
    int                 nativeFenceFd,
    VkSemaphore         semaphore,
    VkFence             fence
);

vkAcquireImageANDROID() вызывается во время vkAcquireNextImageKHR, чтобы импортировать нативный барьер в объекты VkSemaphore и VkFence, предоставленные приложением (однако объекты семафора и барьера необязательны в этом вызове). Драйвер также может использовать эту возможность, чтобы распознать и обработать любые внешние изменения состояния буфера Gralloc. Многим драйверам не нужно ничего делать в этом случае. Этот вызов переводит VkSemaphore и VkFence в то же состояние ожидания, что и при сигнале от vkQueueSubmit, поэтому очереди могут ожидать семафор, а приложение – ограждение.

Оба объекта получают сигнал, когда это делает базовый нативный барьер. Если нативный барьер уже подал сигнал, то семафор находится в сигнальном состоянии, когда эта функция возвращает значение. Драйвер принимает право собственности на дескриптор файла барьера и закрывает его, когда он больше не нужен. Драйвер должен сделать это, даже если не предоставлен ни семафор, ни объект ограждения, или если vkAcquireImageANDROID завершается с ошибкой. Если значение параметра fenceFd равно -1, это означает, что сигнал о готовности собственного ограждения уже был отправлен.

Изображения для выпуска

vkQueueSignalReleaseImageANDROID подготавливает изображение цепочки буферов для внешнего использования, создает собственный барьер и планирует его активацию после того, как будут активированы входные семафоры:

VkResult VKAPI vkQueueSignalReleaseImageANDROID(
    VkQueue             queue,
    uint32_t            waitSemaphoreCount,
    const VkSemaphore*  pWaitSemaphores,
    VkImage             image,
    int*                pNativeFenceFd
);

vkQueuePresentKHR() звонит vkQueueSignalReleaseImageANDROID() в указанную очередь. Драйвер должен создать собственный барьер, который не будет сигнализировать, пока не будут поданы сигналы всех семафоров waitSemaphoreCount в pWaitSemaphores и не будет завершена любая дополнительная работа, необходимая для подготовки image к показу.

Если семафоры ожидания (при наличии) уже подали сигнал и queue уже бездействует, драйвер может установить для *pNativeFenceFd значение -1 вместо фактического дескриптора файла нативного барьера, указывая, что ждать нечего. Вызывающий процесс владеет дескриптором файла, возвращенным в *pNativeFenceFd, и закрывает его.

Многие драйверы могут игнорировать параметр image, но некоторым может потребоваться подготовить структуры данных на стороне ЦП, связанные с буфером Gralloc, для использования внешними потребителями изображений. Подготовка содержимого буфера для использования внешними потребителями должна выполняться асинхронно в рамках перехода изображения в VK_IMAGE_LAYOUT_PRESENT_SRC_KHR.

Если изображение было создано с помощью VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID, драйвер должен разрешать многократный вызов vkQueueSignalReleaseImageANDROID() без промежуточных вызовов vkAcquireImageANDROID().

Поддержка общих изображений для показа

Некоторые устройства могут передавать право собственности на одно изображение между конвейером дисплея и реализацией Vulkan, чтобы минимизировать задержку. В Android 9 и более поздних версиях загрузчик условно рекламирует расширение VK_KHR_shared_presentable_image на основе ответа драйвера на вызов vkGetPhysicalDeviceProperties2.

Если драйвер не поддерживает Vulkan 1.1 или расширение VK_KHR_physical_device_properties2, загрузчик не будет сообщать о поддержке общих изображений для показа. В противном случае загрузчик запрашивает возможности драйвера, вызывая vkGetPhysicalDeviceProperties2() и включая следующую структуру в цепочку VkPhysicalDeviceProperties2::pNext:

typedef struct {
    VkStructureType sType; // must be VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENTATION_PROPERTIES_ANDROID
    const void*     pNext;
    VkBool32        sharedImage;
} VkPhysicalDevicePresentationPropertiesANDROID;

Если драйвер может передать право собственности на изображение системе отображения, он устанавливает для элемента sharedImage значение VK_TRUE.

Проверка

Производители оригинального оборудования могут протестировать реализацию Vulkan с помощью CTS, в который входят:

  • Тесты на соответствие Khronos Vulkan в модуле CtsDeqpTestCases, которые включают функциональные тесты API для Vulkan 1.0, 1.1, 1.2, 1.3 и 1.4.
  • Модуль CtsGraphicsTestCases, который проверяет, правильно ли настроено устройство для поддержки возможностей Vulkan.

Флаг функции Vulkan

Для флага функции android.software.vulkan.deqp.level требуется устройство с Android 11 или более поздней версии и поддержкой API Vulkan. Значение этого флага функции – дата, закодированная как целое число. Указывает дату, связанную с тестами Vulkan dEQP, которые, как утверждается, прошло устройство.

Дата в формате ГГГГ-ММ-ДД кодируется как 32-битное целое число следующим образом:

  • Биты 0–15 хранят год.
  • Биты 16–23 содержат месяц.
  • Биты 24–31 хранят день.

Минимальное допустимое значение для флага функции – 0x07E30301, что соответствует дате 1 марта 2019 г. Именно в этот день были добавлены тесты dEQP Vulkan для Android 10. Если флаг функции имеет это значение или больше, устройство считается прошедшим все тесты dEQP Vulkan для Android 10.

Значение 0x07E40301 соответствует дате 1 марта 2020 г., которая связана с тестами Vulkan dEQP для Android 11. Если значение флага функции не меньше указанного, устройство заявляет, что проходит все тесты dEQP для Vulkan в Android 11.

Значение 0x07E60301 соответствует дате 1 марта 2022 г., которая связана с тестами dEQP Vulkan для Android 13. Если значение флага функции не меньше указанного, устройство считается прошедшим все тесты dEQP Vulkan для Android 13.

Устройство, которое предоставляет определенный флаг функции (например, 0x07E30301, 0x07E40301, 0x07E60301), должно пройти все тесты dEQP Android Vulkan для этого флага (Android 10, Android 11 и Android 13 соответственно). Это устройство может пройти тесты Vulkan dEQP из более поздней версии Android.

Vulkan dEQP входит в состав Android CTS. В Android 11 компонент CTS dEQP test runner учитывает флаг функции android.software.vulkan.deqp.level и пропускает все тесты Vulkan dEQP, которые, согласно этому флагу функции, устройство не поддерживает. Такие тесты считаются пройденными.