|
Para generar cada una de las imágenes del swapchain hay que lanzar la
ejecución de un buffer de comandos asociado a cada una de ellas. Como
hemos comentado en proyectos anteriores, la ejecución de un buffer de comandos es un proceso asíncrono.
Esto quiere decir que la función de lanzamiento devuelve el control
sin que realmente el proceso de renderizado se haya completado. El
problema es que no podemos lanzar un proceso de renderizado sobre una
imagen sin asegurarnos de que el renderizado anterior haya finalizado.
Para sincronizar este proceso se utilizan los semáforos y las vallas
que ya hemos generado.
El proceso de creación de la imagen tiene tres pasos: adquirir la imagen,
generar la imagen y presentar la imagen. Para adquirir la imagen de una
swapchain se utiliza la función vkAcquireNextImageKHR(). Esta función espera
a que la siguiente imagen esté disponible para devolver el control almacenando
en pImageIndex el índice de la imagen disponible.
VkResult vkAcquireNextImageKHR(
VkDevice device,
VkSwapchainKHR swapchain,
uint64_t timeout,
VkSemaphore semaphore,
VkFence fence,
uint32_t* pImageIndex);
|
El campo timeout se refiere al tiempo máximo de espera para obtener la imagen.
El campo semaphore se refiere al semáforo que hay que esperar para poder renderizar en la imagen.
El campo fence indica la valla a abrir cuando sea posible renderizar la imagen.
Para generar la imagen hay que lanzar el buffer de comandos sobre una cola gráfica del
dispositivo. Para esto se utiliza la función vkQueueSubmit().
VkResult vkQueueSubmit (
VkQueue queue,
uint32_t submitCount,
const VkSubmitInfo* pSubmits,
VkFence fence);
|
El argumento fence contiene la valla que se señalará al terminar el proceso
de ejecución del buffer de comandos. La estructura VkSubmitInfo describe la
configuración del lanzamiento.
typedef struct VkSubmitInfo {
VkStructureType sType;
const void* pNext;
uint32_t waitSemaphoreCount;
const VkSemaphore* pWaitSemaphores;
const VkPipelineStageFlags* pWaitDstStageMask;
uint32_t commandBufferCount;
const VkCommandBuffer* pCommandBuffers;
uint32_t signalSemaphoreCount;
const VkSemaphore* pSignalSemaphores;
} VkSubmitInfo;
|
El campo pCommandBuffers indica los buffers a lanzar. Se pueden lanzar
varios buffers en la misma llamada.
El número de buffers se indica en commandBufferCount.
El campo pWaitSemaphores indica los semáforos a los que hay que esperar para lanzar el renderizado. Pueden indicarse varios semáforos.
El campo pSignalSemaphores indica los semáforos que hay que abrir al terminar el proceso de renderizado. Pueden indicarse varios semáforos.
Para terminar el proceso hay que presentar la imagen renderizada. Para esto se
utiliza la función vkQueuePresentKHR(). La configuración de esta llamada se
describe en la estructura VkPresentInfoKHR.
VkResult vkQueuePresentKHR(
VkQueue queue,
const VkPresentInfoKHR* pPresentInfo);
typedef struct VkPresentInfoKHR {
VkStructureType sType;
const void* pNext;
uint32_t waitSemaphoreCount;
const VkSemaphore* pWaitSemaphores;
uint32_t swapchainCount;
const VkSwapchainKHR* pSwapchains;
const uint32_t* pImageIndices;
VkResult* pResults;
} } VkPresentInfoKHR;
|
El campo pWaitSemaphores contiene una lista de semáforos a los que
hay que esperar para realizar la presentación.
El número de semáforos
se indica en waitSemaphoreCount.
En una misma llamada se puede lanzar
la presentación de varias imágenes. Esto puede ser util cuando una
aplicación trabaja con varias ventanas. El campo pSwapchains contiene
la lista de swapchains sobre las que presentar imágenes.
El campo
pImageIndices contiene el índice de la imagen a presentar de cada
swapchain.
El número de swapchains se indica en swapchainCount.
|