Synchronization

Certain operations need to be synchronized in order to assure proper operation.

We will create 3 synchronization primitives:

  1. Semaphore to be signalled when a new backbuffer becomes available, halting command buffer execution until the backbuffer can be written to
  2. Semaphore to be signalled when the command buffer completes, allowing the backbuffer to be presented on screen
  3. Fence to be signalled when the command buffer completes, indicating to the CPU the GPU is done using the command buffer, allowing the command buffer to be reused for recording

for ( uint32_t i = 0; i < FRAME_BUFFER_COUNT; i++ )
{
    result = vkCreateSemaphore (
        renderer->device,
        &(VkSemaphoreCreateInfo){
            .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
            .pNext = NULL,
        },
        NULL,
        &renderer->frameCommands[i].frameWritableSemaphore
    );
    if ( result != VK_SUCCESS )
        RETURN_ERROR(-1,"vkCreateSemaphore failed (0x%08X)", (uint32_t)result);

    result = vkCreateSemaphore (
        renderer->device,
        &(VkSemaphoreCreateInfo){
            .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
            .pNext = NULL,
        },
        NULL,
        &renderer->frameCommands[i].commandBufferCompletedSemaphore
    );
    if ( result != VK_SUCCESS )
        RETURN_ERROR(-1,"vkCreateSemaphore failed (0x%08X)", (uint32_t)result);

    result = vkCreateFence (
        renderer->device,
        &(VkFenceCreateInfo){
            .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
            .pNext = NULL,
            .flags = VK_FENCE_CREATE_SIGNALED_BIT,
        },
        NULL,
        &renderer->frameCommands[i].commandBufferCompletedFence
    );
}