fix separate swapchain synchronization

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