Google se compromete a impulsar la igualdad racial para las comunidades afrodescendientes. Obtén información al respecto.

Implementando Vulkan

Vulkan es una baja sobrecarga, API multiplataforma de alto rendimiento de gráficos 3D. Como OpenGL ES (GLES) , Vulkan proporciona herramientas para crear de alta calidad, gráficos en tiempo real en las aplicaciones. Ventajas del uso de Vulkan incluyen reducciones de sobrecarga de la CPU y el apoyo para el SPIR-V Binary Intermedio idioma.

Para implementar Vulkan con éxito, un dispositivo debe incluir:

  • El cargador Vulkan, proporcionado por Android.
  • Un conductor Vulkan, proporcionado por SoC como GPU IHVs, que implementa la API Vulkan . Para admitir la funcionalidad de Vulkan, el dispositivo Android necesita hardware GPU compatible con Vulkan y el controlador asociado. La GPU también debe ser compatible con GLES 3.1 y superior. Consulte a su proveedor de SoC para solicitar soporte para controladores.

Si un dispositivo incluye un controlador de Vulkan, las necesidades de dispositivos para declarar FEATURE_VULKAN_HARDWARE_LEVEL y FEATURE_VULKAN_HARDWARE_VERSION Características del sistema, con versiones que reflejen con precisión las capacidades del dispositivo. Esto ayuda a asegurar que el dispositivo cumple con la definición de compatibilidad de documentos (CDD).

Cargador Vulkan

El cargador de Vulkan platform/frameworks/native/vulkan es la principal interfaz entre las aplicaciones y el conductor Vulkan Vulkan de un dispositivo. El cargador de Vulkan se instala en /system/lib[64]/libvulkan.so . El cargador proporciona los puntos de entrada principales de la API de Vulkan, así como los puntos de entrada de las extensiones requeridas por el CDD de Android. Las extensiones de Windows System Integration (WSI) son exportadas por el cargador y se implementan principalmente en el cargador en lugar de en el controlador. El cargador también admite la enumeración y carga de capas que pueden exponer extensiones adicionales e interceptar llamadas de API principales en su camino hacia el controlador.

La NDK incluye un stub libvulkan.so biblioteca para ligarse. La biblioteca exporta los mismos símbolos que el cargador. Aplicaciones llaman a las funciones exportadas de la verdadera libvulkan.so biblioteca para entrar en funciones el trampolín en el cargador, que envío a la capa o controlador apropiado basado en su primer argumento. El vkGet*ProcAddr() llamada devuelve los punteros de función a la que los trampolines de envío (es decir, se pone directamente en el código API central). Llamar a través de los punteros de función, en lugar de los símbolos exportados, es más eficiente ya que se salta el trampolín y se envía.

Enumeración y carga de controladores

Cuando se crea la imagen del sistema, Android espera que el sistema sepa qué GPU están disponibles. El cargador utiliza el mecanismo de HAL existente en hardware.h para descubrir y cargar el controlador. Las rutas preferidas para los controladores Vulkan de 32 y 64 bits son:

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

En Android 7.0 y superior, el Vulkan hw_module_t derivado envuelve un solo hw_module_t struct; sólo un controlador está soportado y la cadena constante HWVULKAN_DEVICE_0 se pasa a open() .

El Vulkan hw_device_t corresponde derivados para un único controlador que puede soportar múltiples dispositivos físicos. El hw_device_t estructura puede extenderse a la exportación vkGetGlobalExtensionProperties() , vkCreateInstance() , y vkGetInstanceProcAddr() funciones. El cargador puede encontrar todos los otros VkInstance() , VkPhysicalDevice() , y vkGetDeviceProcAddr() funciones llamando al hw_device_t de estructura vkGetInstanceProcAddr() .

Descubrimiento y carga de capas

El cargador Vulkan admite la enumeración y carga de capas que pueden exponer extensiones adicionales e interceptar llamadas de API principales en su camino hacia el controlador. Android no incluye capas en la imagen del sistema; sin embargo, las aplicaciones pueden incluir capas en su APK.

Al usar capas, tenga en cuenta que el modelo y las políticas de seguridad de Android difieren significativamente de otras plataformas. En particular, Android no permite cargar código externo en un proceso no depurable en dispositivos de producción (no rooteados), ni permite que el código externo inspeccione o controle la memoria, el estado, etc. del proceso. Esto incluye la prohibición de guardar volcados de núcleo, seguimientos de API, etc. en el disco para una inspección posterior. Solo las capas entregadas como parte de aplicaciones no depurables están habilitadas en los dispositivos de producción y los controladores no deben proporcionar funciones que infrinjan estas políticas.

Los casos de uso de capas incluyen:

  • Capas en tiempo de desarrollo - capas de validación y cuñas para el rastreo / perfiles / herramientas de depuración no se deben instalar la imagen del sistema de producción de dispositivos. Las capas de validación y las calzas para las herramientas de seguimiento, creación de perfiles y depuración deben poder actualizarse sin una imagen del sistema. Los desarrolladores que quieran usar una de estas capas durante el desarrollo pueden modificar el paquete de la aplicación, por ejemplo, agregando un archivo a su directorio de bibliotecas nativas. Se supone que los ingenieros de IHV y OEM que desean diagnosticar fallas en el envío de aplicaciones no modificables tienen acceso a compilaciones de no producción (rooteadas) de la imagen del sistema, a menos que esas aplicaciones sean depurables. Para más información ver capas de validación Vulkan en Android .
  • Capas de Utilidad - Estas capas exponen extensiones, como una capa que implementa un gestor de memoria para la memoria del dispositivo. Los desarrolladores eligen capas y versiones de esas capas para usar en su aplicación; diferentes aplicaciones que usan la misma capa pueden seguir usando diferentes versiones. Los desarrolladores eligen cuál de estas capas enviar en su paquete de aplicación.
  • Inyectadas (implícitas) - capas incluye capas tales como la velocidad de fotogramas, la red social y juego lanzador superposiciones proporcionada por el usuario o alguna otra aplicación sin el conocimiento o consentimiento de la aplicación. Estos violan las políticas de seguridad de Android y no son compatibles.

Para aplicaciones nondebuggable, las búsquedas cargador para capas solamente en el directorio biblioteca nativa de la aplicación e intenta cargar cualquier biblioteca con un nombre que coincida con un patrón particular (por ejemplo, libVKLayer_foo.so ).

Para aplicaciones depurables, las búsquedas cargador para capas en /data/local/debug/vulkan e intenta cargar cualquier biblioteca de búsqueda de un patrón particular.

Android permite portar capas con cambios en el entorno de compilación entre Android y otras plataformas. Para más detalles sobre la interfaz entre las capas y el cargador, ver Arquitectura de la Vulkan Loader Interfaces . Las capas de validación mantenidos Khronos están alojados en Capas Vulkan de validación .

Versiones y capacidades de la API de Vulkan

Android 9 y versiones posteriores son compatibles con la versión 1.1 de la API de Vulkan. Android 7 a Android 9 son compatibles con la versión 1.0 de la API de Vulkan. Para obtener más información sobre la API Vulkan 1.1, consulte la especificación API 1.1 Vulkan .

Descripción general de la compatibilidad con Vulkan 1.1

Vulkan 1.1 incluye soporte para interoperabilidad de memoria / sincronización, lo que permite a los OEM admitir Vulkan 1.1 en dispositivos. Además, la interoperabilidad de memoria / sincronización permite a los desarrolladores determinar si Vulkan 1.1 es compatible con un dispositivo y usarlo de manera efectiva cuando lo sea. Vulkan 1.1 tiene los mismos requisitos de hardware que Vulkan 1.0, pero la mayor parte de la implementación está en el controlador de gráficos específico de SOC, no en el marco.

Las características más importantes de Vulkan 1.1 para Android son:

  • Soporte para importar y exportar búferes de memoria y objetos de sincronización desde fuera de Vulkan (para interoperabilidad con cámara, códecs y GLES)
  • Soporte para formatos YCbCr

Vulkan 1.1 también incluye varias funciones más pequeñas y mejoras de usabilidad de API.

Implementación de Vulkan 1.1

Los dispositivos Android deben admitir Vulkan 1.1 si:

  • Lanzamiento con Android 10.
  • Admite una ABI de 64 bits.
  • No tengo poca memoria.

Otros dispositivos pueden admitir opcionalmente Vulkan 1.1.

Para implementar Vulkan 1.1:

  1. Añadir un conductor que Vulkan Vulkan soportes 1.1, más el Android 1.1 adicionales requisitos de DDC , o actualizar el controlador 1.0 Vulkan existente.
  2. Asegúrese de que PackageManager#hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_VERSION, 0x401000) devuelve true añadiendo una regla como la siguiente a una adecuada device.mk archivo:
    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
    

Integración de sistemas de ventanas (WSI)

En libvulkan.so , los implementos conductor la siguiente ventana de integración del sistema (WSI) Extensiones:

  • VK_KHR_surface
  • VK_KHR_android_surface
  • VK_KHR_swapchain
  • VK_KHR_driver_properties , implementado por Vulkan 1.1 en Android 10 sólo
  • VK_GOOGLE_display_timing , implementado para cualquier versión de Android Vulkan 10

Los VkSurfaceKHR y VkSwapchainKHR objetos y todas las interacciones con ANativeWindow son manejados por la plataforma y no están expuestos a los conductores. La aplicación se basa en la WSI VK_ANDROID_native_buffer extensión, que debe ser compatible con el controlador; esta extensión solo la usa la implementación de WSI y no está expuesta a las aplicaciones.

Banderas de uso de Gralloc

Las implementaciones de Vulkan pueden necesitar que se asignen búferes de cadena de intercambio con indicadores de uso de Gralloc privados definidos por la implementación. Al crear una cadena de intercambio, Android le pide al controlador que traduzca el formato solicitado y los indicadores de uso de la imagen en indicadores de uso de Gralloc llamando a:

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
);

Las format y imageUsage parámetros se toman de la VkSwapchainCreateInfoKHR estructura. El conductor debe llenar *grallocConsumerUsage y *grallocProducerUsage con las banderas de uso Gralloc necesarios para el formato y uso. Los indicadores de uso devueltos por el controlador se combinan con los indicadores de uso solicitados por el consumidor de la cadena de intercambio al asignar búferes.

7.x Android llama a una versión anterior de VkSwapchainImageUsageFlagsANDROID() , llamado vkGetSwapchainGrallocUsageANDROID() . Android 8.0 y superiores desaprueba vkGetSwapchainGrallocUsageANDROID() , pero todavía llama vkGetSwapchainGrallocUsageANDROID() si vkGetSwapchainGrallocUsage2ANDROID() no es proporcionado por el conductor:

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

vkGetSwapchainGrallocUsageANDROID() no es compatible con banderas de uso swapchain o banderas de uso Gralloc extendidas.

Imágenes respaldadas por Gralloc

VkNativeBufferANDROID es un vkCreateImage estructura de extensión para la creación de una imagen respaldada por una Gralloc buffer. VkNativeBufferANDROID se proporciona a vkCreateImage() en el VkImageCreateInfo cadena de estructura. Las llamadas a vkCreateImage() con VkNativeBufferANDROID ocurren durante la llamada a vkCreateSwapchainKHR . Asigna la ejecución de WSI el número de buffers nativos solicitaron para el swapchain, a continuación, crea un VkImage para cada uno:

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;

Al crear una imagen Gralloc respaldados, VkImageCreateInfo tiene los siguientes datos:

  .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

En Android 8.0 y superior, la plataforma proporciona un VkSwapchainImageCreateInfoKHR estructura de extensión en el VkImageCreateInfo cadena proporcionada a vkCreateImage cuando se requieren ningún banderas de uso de imagen swapchain para la swapchain. La estructura de la extensión contiene los indicadores de uso de la imagen de la cadena de intercambio:

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

    VkSwapchainImageUsageFlagsANDROID      usage;
} VkSwapchainImageCreateInfoANDROID;

En Android 10 y superior, la plataforma soporta VK_KHR_swapchain v70, por lo que la aplicación Vulkan es capaz de crear un VkImage respaldado por la memoria swapchain. La aplicación llama primero vkCreateImage con un VkImageSwapchainCreateInfoKHR estructura encadenada al VkImageCreateInfo estructura. A continuación, la aplicación llama vkBindImageMemory2(KHR) con un VkBindImageMemorySwapchainInfoKHR estructura encadenada al VkBindImageMemoryInfo estructura. El imageIndex especificado en el VkBindImageMemorySwapchainInfoKHR estructura debe ser un índice de imágenes swapchain válida. Mientras tanto, la plataforma proporciona un VkNativeBufferANDROID estructura de extensión con la correspondiente información de tampón Gralloc a la VkBindImageMemoryInfo cadena, por lo que el conductor sabe que Gralloc tampón de obligar a la VkImage con.

Adquirir imágenes

vkAcquireImageANDROID adquiere la propiedad de una imagen swapchain y las importaciones un cerco nativa señalan externamente, tanto en una ya existente de VkSemaphore objeto y una ya existente VkFence objeto:

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

vkAcquireImageANDROID() se llama durante vkAcquireNextImageKHR para importar una valla nativa en el VkSemaphore y VkFence objetos proporcionados por la aplicación (sin embargo, los dos semáforos y valla objetos son opcionales en esta convocatoria). El controlador también puede aprovechar esta oportunidad para reconocer y manejar cualquier cambio externo en el estado del búfer de Gralloc; muchos conductores no necesitarán hacer nada aquí. Esta llamada pone la VkSemaphore y VkFence en el mismo estado pendiente como si señalizan mediante vkQueueSubmit , por lo que las colas pueden esperar en el semáforo y la aplicación pueden esperar en la valla.

Ambos objetos se señalan cuando la cerca nativa subyacente señala; si la cerca nativa ya ha señalado, entonces el semáforo está en el estado señalado cuando esta función regresa. El controlador toma posesión del descriptor de archivo de cerca y cierra el descriptor de archivo de cerca cuando ya no es necesario. El conductor debe hacerlo aunque se proporcionen ni un semáforo o un objeto cerca, o incluso si vkAcquireImageANDROID falla y devuelve un error. Si fenceFd es -1, es como si la valla nativa ya fue señalada.

Liberar imágenes

vkQueueSignalReleaseImageANDROID prepara una imagen de swapchain para uso externo, crea una valla nativa, y los horarios de la valla nativa de ser señalado después de los semáforos de entrada han señalado:

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

vkQueuePresentKHR() llama a vkQueueSignalReleaseImageANDROID() en la cola proporcionada. El conductor debe producir una valla nativo que no es una señal hasta que todos los waitSemaphoreCount semáforos en pWaitSemaphores señal, y cualquier trabajo adicional requerido para preparar image para la ultima presentación.

Si los semáforos de espera (si las hubiera) ya señaladas, y la queue ya está inactivo, el conductor puede ajustar *pNativeFenceFd a -1 en lugar de un descriptor de archivo valla nativa real, lo que indica que no hay nada que esperar. La persona que llama es propietaria y cierra el descriptor de archivo devuelto en *pNativeFenceFd .

Muchos controladores pueden ignorar el parámetro de imagen, pero algunos pueden necesitar preparar estructuras de datos del lado de la CPU asociadas con un búfer de Gralloc para que las utilicen los consumidores de imágenes externos. Preparación de los contenidos del búfer para su uso por los consumidores externos deben hacerse de forma asincrónica como parte de la transición de la imagen para VK_IMAGE_LAYOUT_PRESENT_SRC_KHR .

Si la imagen fue creada con VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID , entonces el conductor debe permitir vkQueueSignalReleaseImageANDROID() para ser llamado en repetidas ocasiones sin intervenir llamadas a vkAcquireImageANDROID() .

Soporte de imagen presentable compartido

Algunos dispositivos pueden compartir la propiedad de una sola imagen entre el canal de visualización y la implementación de Vulkan para minimizar la latencia. En Android 9 y superior, el cargador anuncia condicionalmente la VK_KHR_shared_presentable_image extensión basado en la respuesta del conductor para una llamada a vkGetPhysicalDeviceProperties2 .

Si el conductor no soporta ya sea Vulkan 1.1 o el VK_KHR_physical_device_properties2 extensión, el cargador no se anuncia soporte para imágenes presentables compartidos. De lo contrario, el cargador de consultas de las capacidades del controlador llamando vkGetPhysicalDeviceProperties2() y que incluye la siguiente estructura en el VkPhysicalDeviceProperties2::pNext cadena:

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

Si el conductor puede compartir la propiedad de una imagen con el sistema de visualización, se establece el sharedImage miembro para VK_TRUE .

Validación

Los OEM pueden probar su implementación de Vulkan utilizando CTS, que incluye:

  • Pruebas Khronos Vulkan Conformidad en la CtsDeqpTestCases módulo, que incluyen pruebas API funcionales para Vulkan 1,0 y 1,1.
  • El CtsGraphicsTestCases módulo, que prueba que el dispositivo está configurado correctamente para las capacidades de Vulkan que soporta.

Bandera característica de Vulkan

Un dispositivo que admita Android 11 o más alto y que los soportes se requiere la API Vulkan para exponer un indicador de la función, android.software.vulkan.deqp.level . El valor de esta marca de característica es una fecha, codificada como un valor entero. Especifica la fecha asociada con las pruebas Vulkan dEQP que el dispositivo dice haber pasado.

Una fecha con el formato AAAA-MM-DD se codifica como un entero de 32 bits de la siguiente manera:

  • Bits 0-15 almacenan el año
  • Los bits 16-23 almacenan el mes
  • Bits 24-31 almacenan el día

El valor mínimo permitido para el indicador de la función es 0x07E30301 , que corresponde a la fecha de 03.01.2019, que es la fecha asociada con las pruebas de Vulkan dEQP para Android 10. Si la bandera característica es al menos este valor, las reivindicaciones de dispositivo a pasar todas las pruebas dEQP de Vulkan de Android 10.

Valor 0x07E40301 corresponde a la fecha 01.03.2020, que es la fecha asociada con las pruebas de Vulkan dEQP para Android 11. Si la bandera característica es al menos este valor, las reivindicaciones de dispositivo para pasar todas las Android 11 pruebas Vulkan dEQP.

Si el valor del indicador característica es al menos 0x07E30301 pero menos de 0x07E40301 , esto significa que las reivindicaciones de dispositivo para pasar todas las Android 10 pruebas Vulkan dEQP pero no está garantizada para pasar las pruebas Vulkan dEQP que se han añadido para Android 11.

Vulkan dEQP forma parte de Android CTS. De androide 11, el componente corredor de prueba dEQP de CTS es consciente de la android.software.vulkan.deqp.level indicador de la función, y se salta las pruebas Vulkan dEQP que - de acuerdo con este indicador de la función - el dispositivo no tiene la pretensión de apoyo. Se informa que estas pruebas pasan trivialmente.