Pautas de diseño de Vulkan

Vulkan difiere de las API de gráficos anteriores en que los controladores no realizan determinadas optimizaciones para apps, como la reutilización de la canalización. En cambio, las apps que usan Vulkan deben implementar esas optimizaciones por sí mismas. Si no lo hacen, pueden exhibir un peor rendimiento que las apps que ejecutan OpenGL ES.

Cuando las apps implementan esas optimizaciones por sí mismas, tienen la posibilidad de hacerlo de manera más satisfactoria que el controlador, ya que tienen acceso a información específica sobre un caso práctico determinado. Como resultado, optimizar con habilidad una app que usa Vulkan puede proporcionar un mejor rendimiento en comparación con una situación en la que la app usa OpenGL ES.

En esta página, se presentan varias optimizaciones que tu app para Android puede implementar a fin de obtener un mayor rendimiento gracias a Vulkan.

Aceleración de hardware

La mayoría de los dispositivos admiten Vulkan 1.1 mediante la aceleración de hardware, mientras que un pequeño subconjunto lo admite mediante emulación de software. Para detectar un dispositivo Vulkan basado en software, las apps pueden usar vkGetPhysicalDeviceProperties y verificar el campo deviceType de la estructura que se muestra. SwiftShader y otras implementaciones basadas en CPU tienen el valor VK_PHYSICAL_DEVICE_TYPE_CPU. Las apps pueden buscar SwiftShader específicamente; para ello, deben buscar valores específicos de SwiftShader en los campos vendorID y deviceID de esta misma estructura.

Las apps fundamentales para el rendimiento deben evitar usar implementaciones Vulkan emuladas por software y, en su lugar, recurrir a OpenGL ES.

Aplica la rotación de pantalla durante el procesamiento

Cuando la orientación hacia arriba de una app no coincide con la orientación de la pantalla del dispositivo, el compositor gira las imágenes de la cadena de intercambio de la app de modo que coincidan. La rotación ocurre mientras se muestran las imágenes, lo cual genera un mayor consumo de energía (a veces, muy significativo) que cuando estas no giran.

Por el contrario, girar las imágenes de la cadena de intercambio mientras se generan produce un consumo de energía adicional muy reducido o nulo. En el campo VkSurfaceCapabilitiesKHR::currentTransform, se indica la rotación que el compositor aplica a la ventana. Después de aplicar esa rotación durante el procesamiento, la app usa el campo VkSwapchainCreateInfoKHR::preTransform para informar que la rotación se completó.

Minimiza los pases de procesamiento por fotograma

En la mayoría de las arquitecturas de GPU para dispositivos móviles, comenzar y finalizar un pase de procesamiento es una operación que consume muchos recursos. Tu app puede mejorar el rendimiento si organiza las operaciones de procesamiento en la menor cantidad de pases de procesamiento posible.

Las diferentes operaciones de carga y almacenamiento de archivos adjuntos ofrecen diferentes niveles de rendimiento. Por ejemplo, si no necesitas preservar el contenido de un archivo adjunto, puedes usar VK_ATTACHMENT_LOAD_OP_CLEAR o VK_ATTACHMENT_LOAD_OP_DONT_CARE en lugar de VK_ATTACHMENT_LOAD_OP_LOAD, ya que son mucho más rápidos. Asimismo, si no necesitas escribir los valores finales del archivo adjunto en la memoria para usarlos más adelante, puedes usar VK_ATTACHMENT_STORE_OP_DONT_CARE para obtener un rendimiento mucho mejor que con VK_ATTACHMENT_STORE_OP_STORE.

En la mayoría de los pases de procesamiento, tu app no necesita cargar ni almacenar el archivo adjunto de profundidad ni los símbolos. En esos casos, puedes evitar tener que asignar memoria física para el archivo adjunto usando la marca VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT cuando creas la imagen del archivo adjunto. Este bit proporciona los mismos beneficios que glFramebufferDiscard en OpenGL ES.

Elige los tipos adecuados de memoria

Cuando asignan memoria del dispositivo, las apps deben elegir un tipo de memoria. El tipo de memoria determina la manera en que una app puede usar la memoria y también describe propiedades de almacenamiento en caché y coherencia de la memoria. Los diferentes dispositivos tienen diferentes tipos de memoria disponibles, y los diferentes tipos de memoria exhiben distintas características de rendimiento.

Una app puede usar un algoritmo simple para elegir el mejor tipo de memoria para un uso determinado. Este algoritmo selecciona el primer tipo de memoria del arreglo VkPhysicalDeviceMemoryProperties::memoryTypes que cumpla dos criterios: el tipo de memoria debe estar permitido para el búfer o la imagen y debe contar con las propiedades mínimas que requiere la app.

Por lo general, los sistemas móviles no tienen montones de memoria física separados para la CPU y la GPU. En esos sistemas, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT no es tan significativo como en sistemas que tienen GPU discretas con su propia memoria dedicada exclusiva. Una app no debe suponer que esta propiedad es obligatoria.

Agrupa conjuntos de descriptores por frecuencia

Si tienes vinculaciones de recursos que cambian en frecuencias diferentes, usa varios conjuntos de descriptores por canalización en lugar de volver a vincular todos los recursos para cada dibujo. Por ejemplo, puedes tener un conjunto de descriptores para la vinculación por escena, otro conjunto para las vinculaciones por material y un tercer conjunto para vinculaciones por instancia de malla.

Usa constantes inmediatas para los cambios de mayor frecuencia, como los que se ejecutan con cada llamada de dibujo.