c++ synchronization gpu vulkan

c++ - Sincronización entre buffers de comando en Vulkan



synchronization gpu (2)

El primer búfer de comandos está representando el objeto con la prueba de profundidad activada. El segundo búfer de comando está representando contornos de mallas con la prueba de profundidad desactivada. Porque tiene que estar encima de los otros objetos.

Para este caso, lo que necesita depende de lo que sean esos buffers de comando.

Si esos son búferes de comando secundarios ejecutados dentro de la misma instancia de pase de procesamiento, entonces no necesita ninguna sincronización. No, a menos que esté leyendo manualmente desde la textura de profundidad en el búfer de comando secundario. ¿Por qué?

Porque los pedidos de API de la sección 2.2.1 te protegen. Las pruebas de profundidad y la escritura en profundidad dentro de una instancia de pase de procesamiento siempre procederán en orden API. Por lo tanto, los comandos posteriores, ya sea en el mismo CB o en otro diferente, se ordenarán con respecto a la prueba / escritura de profundidad.

Sin embargo, si necesita leer ese búfer de profundidad o sus búferes de comando están en diferentes instancias de procesamiento, entonces necesita una sincronización explícita a través de un evento.

En este caso, la máscara de etapa para el comando vkCmdSetEvent debe ser la etapa que escribe el valor de profundidad. Esto podría ser EARLY_FRAGMENT_TESTS_BIT o LATE_FRAGMENT_TESTS_BIT . Para estar seguro, use ambos. Sin embargo, dado que probablemente esté actualizando el mismo búfer de color, también necesitará la etapa COLOR_ATTACHMENT_OUTPUT_BIT . Inserte este comando al final del primer búfer de comandos (o después de que se haya realizado toda la escritura de profundidad).

Para vkCmdWaitEvent , desea esperar en las etapas de canalización que lo necesitan. En su caso, esto es nuevamente las pruebas de fragmentos y el color adjunto. Pero si una etapa de sombreado va a leer la profundidad, también necesita esa etapa en el comando de espera.

Como la memoria está involucrada, su vkCmdWaitEvent también necesitará usar una dependencia de la memoria en los búferes de profundidad y color.

Sin embargo, en realidad, toda esta complejidad es la razón por la que debe intentar colocar estos buffers de comandos en la misma instancia de pase de procesamiento, si es posible. La única razón por la que no podría hacerlo es si necesita leer del búfer de profundidad en un sombreado.

Hay varias formas de manejar la sincronización en Vulkan. Así es como lo entiendo:

  • Las vallas son GPU para sincronizar CPU.
  • Los semáforos son sincronizaciones de GPU a GPU, se utilizan para sincronizar envíos de cola (en la misma o en diferentes colas).
  • Los eventos son más generales, se restablecen y se verifican tanto en la CPU como en la GPU.
  • Las barreras se utilizan para la sincronización dentro de un búfer de comando.

En mi caso tengo dos buffers de comando. Y quiero que el segundo búfer de comandos se ejecute después del primero.

submitInfo.pCommandBuffers = &firstCommandBuffer; vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE); // wait for first command buffer to finish submitInfo.pCommandBuffers = &secondCommandBuffer; vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE);

¿Qué tipo de sincronización es mejor para esto? Si uso vkQueueWaitIdle(queue)), es lo mismo que usar una cerca o debo usar un evento o semáforos para esto?

Si envío múltiples comandos a la cola al mismo tiempo:

std::vector<VkCommandBuffer> submitCmdBuffers = { firstCommandBuffer, secondCommandBuffer }; submitInfo.commandBufferCount = submitCmdBuffers.size(); submitInfo.pCommandBuffers = submitCmdBuffers.data();

¿Todavía hay una manera de sincronizar entre el primero y el segundo?


Para tu escenario deberías usar eventos. Estos deben ser los objetos de sincronización más ligeros para sincronizar la ejecución de dos buffers de comandos en un orden dado, incluso si los envía de una vez. Pero tenga en cuenta que los eventos no funcionan en diferentes colas. Si solo usa uno, use eventos e intente mantener las máscaras de las etapas de tuberías src y dst lo más estrechas posible.

Los semáforos son otra forma de sincronizar la ejecución del comando buffer, pero solo funcionan en el envío de la cola, por lo que son más pesados ​​que los eventos.