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.

Aplica rotación de pantalla durante la representación

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 aplicación 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 no 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. El campo VkSurfaceCapabilitiesKHR::currentTransform indica la rotación que el compositor aplica a la ventana. Después de que aplica esa rotación durante el procesamiento, la app usa el campo VkSwapchainCreateInfoKHR::preTransform para informar que la rotación está completa.

Minimiza las pasadas de representación 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 al organizar 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 debes conservar 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 debes escribir los valores finales del archivo adjunto en la memoria para usarlos posteriormente, puedes usar VK_ATTACHMENT_STORE_OP_DONT_CARE para obtener un mejor rendimiento 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 o símbolos. En esos casos, puedes evitar tener que asignar memoria física para el archivo adjunto usando el indicador 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

Al asignar 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 escoger el mejor tipo de memoria para un uso determinado. Este algoritmo selecciona el primer tipo de memoria en el arreglo VkPhysicalDeviceMemoryProperties::memoryTypes que cumpla con 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.

Los sistemas para dispositivos móviles generalmente no tienen montones de memoria física independientes 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 draw. 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 a draw.