fix separate swapchain synchronization
continuous-integration/drone/push Build is passing Details

pull/12/head
cosmonaut 2022-02-09 21:42:19 -08:00
parent 829356d927
commit b54b7cc42d
1 changed files with 116 additions and 147 deletions

View File

@ -745,6 +745,10 @@ typedef struct VulkanSwapchainData
VkImageView *views;
VulkanResourceAccessType *resourceAccessTypes;
uint32_t imageCount;
/* Synchronization primitives */
VkSemaphore imageAvailableSemaphore;
VkSemaphore renderFinishedSemaphore;
} VulkanSwapchainData;
typedef struct SwapChainSupportDetails
@ -1353,10 +1357,6 @@ typedef struct VulkanRenderer
Refresh_PresentMode presentMode;
VkSemaphore transferFinishedSemaphore;
VkSemaphore imageAvailableSemaphore;
VkSemaphore renderFinishedSemaphore;
VkFence *availableFences;
uint32_t availableFenceCount;
uint32_t availableFenceCapacity;
@ -2627,6 +2627,18 @@ static void VULKAN_INTERNAL_DestroySwapchain(
NULL
);
renderer->vkDestroySemaphore(
renderer->logicalDevice,
swapchainData->imageAvailableSemaphore,
NULL
);
renderer->vkDestroySemaphore(
renderer->logicalDevice,
swapchainData->renderFinishedSemaphore,
NULL
);
for (i = 0; i < renderer->swapchainDataCount; i += 1)
{
if (windowHandle == renderer->swapchainDatas[i]->windowHandle)
@ -4188,7 +4200,8 @@ static CreateSwapchainResult VULKAN_INTERNAL_CreateSwapchain(
VkResult vulkanResult;
VulkanSwapchainData *swapchainData;
VkSwapchainCreateInfoKHR swapchainCreateInfo;
VkImageViewCreateInfo createInfo;
VkImageViewCreateInfo imageViewCreateInfo;
VkSemaphoreCreateInfo semaphoreCreateInfo;
SwapChainSupportDetails swapchainSupportDetails;
int32_t drawableWidth, drawableHeight;
uint32_t i;
@ -4488,25 +4501,25 @@ static CreateSwapchainResult VULKAN_INTERNAL_CreateSwapchain(
swapchainData->images
);
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
createInfo.pNext = NULL;
createInfo.flags = 0;
createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
createInfo.format = swapchainData->surfaceFormat.format;
createInfo.components = swapchainData->swapchainSwizzle;
createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
createInfo.subresourceRange.baseMipLevel = 0;
createInfo.subresourceRange.levelCount = 1;
createInfo.subresourceRange.baseArrayLayer = 0;
createInfo.subresourceRange.layerCount = 1;
imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
imageViewCreateInfo.pNext = NULL;
imageViewCreateInfo.flags = 0;
imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
imageViewCreateInfo.format = swapchainData->surfaceFormat.format;
imageViewCreateInfo.components = swapchainData->swapchainSwizzle;
imageViewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
imageViewCreateInfo.subresourceRange.baseMipLevel = 0;
imageViewCreateInfo.subresourceRange.levelCount = 1;
imageViewCreateInfo.subresourceRange.baseArrayLayer = 0;
imageViewCreateInfo.subresourceRange.layerCount = 1;
for (i = 0; i < swapchainData->imageCount; i += 1)
{
createInfo.image = swapchainData->images[i];
imageViewCreateInfo.image = swapchainData->images[i];
vulkanResult = renderer->vkCreateImageView(
renderer->logicalDevice,
&createInfo,
&imageViewCreateInfo,
NULL,
&swapchainData->views[i]
);
@ -4529,6 +4542,24 @@ static CreateSwapchainResult VULKAN_INTERNAL_CreateSwapchain(
swapchainData->resourceAccessTypes[i] = RESOURCE_ACCESS_NONE;
}
semaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
semaphoreCreateInfo.pNext = NULL;
semaphoreCreateInfo.flags = 0;
renderer->vkCreateSemaphore(
renderer->logicalDevice,
&semaphoreCreateInfo,
NULL,
&swapchainData->imageAvailableSemaphore
);
renderer->vkCreateSemaphore(
renderer->logicalDevice,
&semaphoreCreateInfo,
NULL,
&swapchainData->renderFinishedSemaphore
);
SDL_SetWindowData(windowHandle, WINDOW_SWAPCHAIN_DATA, swapchainData);
if (renderer->swapchainDataCount >= renderer->swapchainDataCapacity)
@ -4650,24 +4681,6 @@ static void VULKAN_DestroyDevice(
VULKAN_INTERNAL_DestroyBuffer(renderer, renderer->dummyFragmentUniformBuffer->vulkanBuffer);
VULKAN_INTERNAL_DestroyBuffer(renderer, renderer->dummyComputeUniformBuffer->vulkanBuffer);
renderer->vkDestroySemaphore(
renderer->logicalDevice,
renderer->transferFinishedSemaphore,
NULL
);
renderer->vkDestroySemaphore(
renderer->logicalDevice,
renderer->imageAvailableSemaphore,
NULL
);
renderer->vkDestroySemaphore(
renderer->logicalDevice,
renderer->renderFinishedSemaphore,
NULL
);
for (i = 0; i < renderer->availableFenceCount; i += 1)
{
renderer->vkDestroyFence(
@ -8565,7 +8578,7 @@ static void VULKAN_QueuePresent(
renderer->logicalDevice,
swapchainData->swapchain,
UINT64_MAX,
renderer->imageAvailableSemaphore,
swapchainData->imageAvailableSemaphore,
VK_NULL_HANDLE,
&swapchainImageIndex
);
@ -8668,7 +8681,7 @@ static void VULKAN_INTERNAL_ResetCommandBuffer(
commandPool->inactiveCommandBufferCount += 1;
}
/* Fence management */
/* Synchronization management */
static VkFence VULKAN_INTERNAL_AcquireFence(
VulkanRenderer *renderer
@ -8777,57 +8790,75 @@ static void VULKAN_Submit(
Refresh_CommandBuffer **pCommandBuffers
) {
VulkanRenderer* renderer = (VulkanRenderer*)driverData;
VkSubmitInfo submitInfo;
VkSubmitInfo *submitInfos;
VkPresentInfoKHR *presentInfos;
void **presentWindowHandles;
uint8_t *needsNewSwapchain;
uint32_t presentCount = 0;
VkResult vulkanResult, presentResult = VK_SUCCESS;
VulkanCommandBuffer *currentCommandBuffer;
VkCommandBuffer *commandBuffers;
uint32_t i;
uint8_t presentCount = 0;
VkPipelineStageFlags waitStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
VulkanSwapchainData *swapchainData;
VkFence fence;
VkPipelineStageFlags waitStages[2];
VkSemaphore waitSemaphores[2];
uint32_t waitSemaphoreCount = 0;
VkPresentInfoKHR presentInfo;
uint32_t i;
SDL_LockMutex(renderer->submitLock);
commandBuffers = SDL_stack_alloc(VkCommandBuffer, commandBufferCount);
submitInfos = SDL_stack_alloc(VkSubmitInfo, commandBufferCount);
/* In the worst case we will need 1 semaphore per CB so let's allocate appropriately. */
presentInfos = SDL_stack_alloc(VkPresentInfoKHR, commandBufferCount);
presentWindowHandles = SDL_stack_alloc(void*, commandBufferCount);
needsNewSwapchain = SDL_stack_alloc(uint8_t, commandBufferCount);
for (i = 0; i < commandBufferCount; i += 1)
{
currentCommandBuffer = (VulkanCommandBuffer*)pCommandBuffers[i];
presentCount += currentCommandBuffer->present;
VULKAN_INTERNAL_EndCommandBuffer(renderer, currentCommandBuffer);
commandBuffers[i] = currentCommandBuffer->commandBuffer;
submitInfos[i].sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfos[i].pNext = NULL;
submitInfos[i].commandBufferCount = 1;
submitInfos[i].pCommandBuffers = &commandBuffers[i];
if (currentCommandBuffer->present)
{
swapchainData = (VulkanSwapchainData*) SDL_GetWindowData(currentCommandBuffer->presentWindowHandle, WINDOW_SWAPCHAIN_DATA);
submitInfos[i].pWaitDstStageMask = &waitStage;
submitInfos[i].pWaitSemaphores = &swapchainData->imageAvailableSemaphore;
submitInfos[i].waitSemaphoreCount = 1;
submitInfos[i].pSignalSemaphores = &swapchainData->renderFinishedSemaphore;
submitInfos[i].signalSemaphoreCount = 1;
presentInfos[presentCount].sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
presentInfos[presentCount].pNext = NULL;
presentInfos[presentCount].waitSemaphoreCount = 1;
presentInfos[presentCount].pWaitSemaphores = &swapchainData->renderFinishedSemaphore;
presentInfos[presentCount].swapchainCount = 1;
presentInfos[presentCount].pSwapchains = &swapchainData->swapchain;
presentInfos[presentCount].pImageIndices = &currentCommandBuffer->presentSwapchainImageIndex;
presentInfos[presentCount].pResults = NULL;
presentWindowHandles[presentCount] = currentCommandBuffer->presentWindowHandle;
needsNewSwapchain[presentCount] = currentCommandBuffer->needNewSwapchain;
presentCount += 1;
}
else
{
submitInfos[i].pWaitDstStageMask = NULL;
submitInfos[i].pWaitSemaphores = NULL;
submitInfos[i].waitSemaphoreCount = 0;
submitInfos[i].pSignalSemaphores = NULL;
submitInfos[i].signalSemaphoreCount = 0;
}
}
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.pNext = NULL;
submitInfo.commandBufferCount = commandBufferCount;
submitInfo.pCommandBuffers = commandBuffers;
if (presentCount > 0)
{
waitSemaphores[waitSemaphoreCount] = renderer->imageAvailableSemaphore;
waitStages[waitSemaphoreCount] = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
waitSemaphoreCount += 1;
submitInfo.pWaitDstStageMask = waitStages;
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = &renderer->renderFinishedSemaphore;
}
else
{
submitInfo.pWaitDstStageMask = waitStages;
submitInfo.signalSemaphoreCount = 0;
submitInfo.pSignalSemaphores = NULL;
}
submitInfo.waitSemaphoreCount = waitSemaphoreCount;
submitInfo.pWaitSemaphores = waitSemaphores;
if (presentCount > 0)
{
/* Wait for the previous submission to complete */
@ -8880,8 +8911,8 @@ static void VULKAN_Submit(
/* Submit the commands, finally. */
vulkanResult = renderer->vkQueueSubmit(
renderer->graphicsQueue,
1,
&submitInfo,
commandBufferCount,
submitInfos,
fence
);
@ -8912,36 +8943,24 @@ static void VULKAN_Submit(
/* Present, if applicable */
for (i = 0; i < commandBufferCount; i += 1)
for (i = 0; i < presentCount; i += 1)
{
currentCommandBuffer = (VulkanCommandBuffer*) pCommandBuffers[i];
swapchainData = (VulkanSwapchainData*) SDL_GetWindowData(currentCommandBuffer->presentWindowHandle, WINDOW_SWAPCHAIN_DATA);
presentResult = VK_SUCCESS;
presentResult = renderer->vkQueuePresentKHR(
renderer->presentQueue,
&presentInfos[i]
);
if (currentCommandBuffer->present)
if (presentResult != VK_SUCCESS || needsNewSwapchain[i])
{
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
presentInfo.pNext = NULL;
presentInfo.waitSemaphoreCount = 1;
presentInfo.pWaitSemaphores = &renderer->renderFinishedSemaphore;
presentInfo.swapchainCount = 1;
presentInfo.pSwapchains = &swapchainData->swapchain;
presentInfo.pImageIndices = &currentCommandBuffer->presentSwapchainImageIndex;
presentResult = renderer->vkQueuePresentKHR(
renderer->presentQueue,
&presentInfo
);
}
if (presentResult != VK_SUCCESS || currentCommandBuffer->needNewSwapchain)
{
VULKAN_INTERNAL_RecreateSwapchain(renderer, currentCommandBuffer->presentWindowHandle);
VULKAN_INTERNAL_RecreateSwapchain(renderer, presentWindowHandles[i]);
}
}
SDL_stack_free(commandBuffers);
SDL_stack_free(submitInfos);
SDL_stack_free(presentInfos);
SDL_stack_free(presentWindowHandles);
SDL_stack_free(needsNewSwapchain);
SDL_UnlockMutex(renderer->submitLock);
}
@ -9621,9 +9640,6 @@ static Refresh_Device* VULKAN_CreateDevice(
VkResult vulkanResult;
uint32_t i;
/* Variables: Create semaphores */
VkSemaphoreCreateInfo semaphoreInfo;
/* Variables: Descriptor set layouts */
VkDescriptorSetLayoutCreateInfo setLayoutCreateInfo;
VkDescriptorSetLayoutBinding vertexParamLayoutBinding;
@ -9755,53 +9771,6 @@ static Refresh_Device* VULKAN_CreateDevice(
return NULL;
}
/*
* Create semaphores
*/
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
semaphoreInfo.pNext = NULL;
semaphoreInfo.flags = 0;
vulkanResult = renderer->vkCreateSemaphore(
renderer->logicalDevice,
&semaphoreInfo,
NULL,
&renderer->transferFinishedSemaphore
);
if (vulkanResult != VK_SUCCESS)
{
LogVulkanResultAsError("vkCreateSemaphore", vulkanResult);
return NULL;
}
vulkanResult = renderer->vkCreateSemaphore(
renderer->logicalDevice,
&semaphoreInfo,
NULL,
&renderer->imageAvailableSemaphore
);
if (vulkanResult != VK_SUCCESS)
{
LogVulkanResultAsError("vkCreateSemaphore", vulkanResult);
return NULL;
}
vulkanResult = renderer->vkCreateSemaphore(
renderer->logicalDevice,
&semaphoreInfo,
NULL,
&renderer->renderFinishedSemaphore
);
if (vulkanResult != VK_SUCCESS)
{
LogVulkanResultAsError("vkCreateSemaphore", vulkanResult);
return NULL;
}
/* Threading */
renderer->allocatorLock = SDL_CreateMutex();