From d8cee89cf98400e8a2d9f90e13ebedeef9e09980 Mon Sep 17 00:00:00 2001 From: Jordan Halase Date: Wed, 6 Nov 2019 09:29:28 -0600 Subject: Use hacky busy dummy buffer to test semaphore race conditions --- main.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 124 insertions(+), 6 deletions(-) diff --git a/main.c b/main.c index df5eec1..d8e26fd 100755 --- a/main.c +++ b/main.c @@ -192,6 +192,7 @@ struct SwapchainVulkan { }; struct SemaphoreVulkan { + VkSemaphore dummyFinished; VkSemaphore presentComplete; VkSemaphore renderFinished; }; @@ -226,6 +227,7 @@ struct RenderVulkan { VkCommandPool commandPool; struct SwapchainVulkan swapchain; VkCommandBuffer *commandBuffers; + VkCommandBuffer dummyBuffer; struct SyncVulkan sync; }; @@ -1412,6 +1414,8 @@ static VkResult allocateCommandBuffers(struct RenderVulkan *vk) allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; allocInfo.commandPool = vk->commandPool; allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + allocInfo.commandBufferCount = 1; + vk->dev->vkAllocateCommandBuffers(vk->device, &allocInfo, &vk->dummyBuffer); allocInfo.commandBufferCount = vk->swapchain.nImages; vk->commandBuffers = malloc(vk->swapchain.nImages * sizeof(vk->commandBuffers)); return vk->dev->vkAllocateCommandBuffers(vk->device, &allocInfo, vk->commandBuffers); @@ -1494,6 +1498,71 @@ static int recordCommandBuffers(struct RenderVulkan *vk) return 0; } +static int recordDummyBuffer(struct RenderVulkan *vk) +{ + VkClearColorValue clearValue = { 0 }; + clearValue.float32[0] = (float)0xa4/0x100; // R + clearValue.float32[1] = (float)0x1e/0x100; // G + clearValue.float32[2] = (float)0x22/0x100; // B + clearValue.float32[3] = (float)0xff/0x100; // A + + VkImageSubresourceRange range = { 0 }; + range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + range.baseMipLevel = 0; + range.levelCount = 1; + range.baseArrayLayer = 0; + range.layerCount = 1; + + VkCommandBufferBeginInfo beginInfo = { 0 }; + beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + beginInfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT; + + VkImageMemoryBarrier toClearBarrier = { 0 }; + toClearBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + toClearBarrier.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; + toClearBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + toClearBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + toClearBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + toClearBarrier.srcQueueFamilyIndex = vk->graphicsIndex; + toClearBarrier.dstQueueFamilyIndex = vk->graphicsIndex; + toClearBarrier.image = vk->swapchain.images[0]; + toClearBarrier.subresourceRange = range; + + VkImageMemoryBarrier toPresentBarrier = { 0 }; + toPresentBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + toPresentBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + toPresentBarrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; + toPresentBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + toPresentBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + toPresentBarrier.srcQueueFamilyIndex = vk->graphicsIndex; + toPresentBarrier.dstQueueFamilyIndex = vk->graphicsIndex; + toPresentBarrier.image = vk->swapchain.images[0]; + toPresentBarrier.subresourceRange = range; + + vk->dev->vkBeginCommandBuffer(vk->dummyBuffer, &beginInfo); + for (uint32_t i = 0; i < 20000; ++i) { + vk->dev->vkCmdPipelineBarrier(vk->dummyBuffer, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, + 0, + 0, NULL, + 0, NULL, + 1, &toClearBarrier); + vk->dev->vkCmdClearColorImage(vk->dummyBuffer, vk->swapchain.images[0], + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue, 1, &range); + vk->dev->vkCmdPipelineBarrier(vk->dummyBuffer, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + 0, + 0, NULL, + 0, NULL, + 1, &toPresentBarrier); + } + vk->dev->vkEndCommandBuffer(vk->dummyBuffer); + + return 0; +} + int rvkCreateSwapchain(struct RenderVulkan *vk, const int width, const int height) { if (rvkCreateRawSwapchain(vk, width, height)) { @@ -1511,6 +1580,9 @@ int rvkCreateSwapchain(struct RenderVulkan *vk, const int width, const int heigh if (recordCommandBuffers(vk)) { return -1; } + if (recordDummyBuffer(vk)) { + return -1; + } return 0; } @@ -1526,6 +1598,7 @@ int rvkCreateSyncObjects(struct RenderVulkan *vk) { VkSemaphoreCreateInfo semaphoreInfo = { 0 }; semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + vk->dev->vkCreateSemaphore(vk->device, &semaphoreInfo, ALLOC_VK, &vk->sync.semaphore.dummyFinished); vk->dev->vkCreateSemaphore(vk->device, &semaphoreInfo, ALLOC_VK, &vk->sync.semaphore.presentComplete); vk->dev->vkCreateSemaphore(vk->device, &semaphoreInfo, ALLOC_VK, &vk->sync.semaphore.renderFinished); VkFenceCreateInfo fenceInfo = { 0 }; @@ -1563,6 +1636,10 @@ void rvkDestroySyncObjects(struct RenderVulkan *vk) vk->dev->vkDestroySemaphore(vk->device, vk->sync.semaphore.presentComplete, ALLOC_VK); vk->sync.semaphore.presentComplete = VK_NULL_HANDLE; } + if (vk->sync.semaphore.dummyFinished) { + vk->dev->vkDestroySemaphore(vk->device, vk->sync.semaphore.dummyFinished, ALLOC_VK); + vk->sync.semaphore.dummyFinished = VK_NULL_HANDLE; + } } static void rvkCloseDevice(struct RenderVulkan *vk) @@ -1667,9 +1744,44 @@ uint32_t framesDrawn; PuglStatus onDisplay(PuglView *view) { struct RenderVulkan *vk = puglGetHandle(view); - uint32_t imageIndex; VkResult result; + const VkPipelineStageFlags waitStages[] = { + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT + }; + + VkSubmitInfo dummyInfo = { 0 }; + dummyInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + //dummyInfo.waitSemaphoreCount = 1; + //dummyInfo.pWaitSemaphores = &vk->sync.semaphore.presentComplete; + dummyInfo.pWaitDstStageMask = &waitStages[0]; + dummyInfo.commandBufferCount = 1; + dummyInfo.pCommandBuffers = &vk->dummyBuffer; + dummyInfo.signalSemaphoreCount = 1; + dummyInfo.pSignalSemaphores = &vk->sync.semaphore.dummyFinished; + + static bool dummy = true; + static uint32_t dummyIndex = 0; + + if (dummy) { + //printf("Submitting dummy buffer...\n"); + if ((result = vk->dev->vkQueueSubmit(vk->graphicsQueue, + 1, &dummyInfo, + VK_NULL_HANDLE + ))) { + rvkSetErrMsg(vk, "Could not submit dummy to queue: %d", result); + return PUGL_FAILURE; + } + printf("Dummy buffer submitted\n"); + } + + const VkSemaphore waits[] = { + vk->sync.semaphore.presentComplete, + vk->sync.semaphore.dummyFinished + }; + uint32_t imageIndex; + // TODO: Swapchain recreation when rezing, minimizing, etc. // TODO: Possibly use unique semaphores per in-flight image? if ((result = vk->dev->vkAcquireNextImageKHR( @@ -1695,13 +1807,11 @@ PuglStatus onDisplay(PuglView *view) VK_TRUE, UINT64_MAX); vk->dev->vkResetFences(vk->device, 1, &vk->sync.fence.swapchain[imageIndex]); - const VkPipelineStageFlags waitStage = VK_PIPELINE_STAGE_TRANSFER_BIT; - VkSubmitInfo submitInfo = { 0 }; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submitInfo.waitSemaphoreCount = 1; - submitInfo.pWaitSemaphores = &vk->sync.semaphore.presentComplete; - submitInfo.pWaitDstStageMask = &waitStage; + submitInfo.waitSemaphoreCount = dummy ? 2 : 1; + submitInfo.pWaitSemaphores = waits; + submitInfo.pWaitDstStageMask = waitStages; submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = &vk->commandBuffers[imageIndex]; submitInfo.signalSemaphoreCount = 1; @@ -1724,9 +1834,17 @@ PuglStatus onDisplay(PuglView *view) presentInfo.pImageIndices = &imageIndex; presentInfo.pResults = NULL; + //if (dummyIndex < 2) { + // printf("Presenting %d...\n", dummyIndex); + //} vk->dev->vkQueuePresentKHR(vk->graphicsQueue, &presentInfo); + //if (dummyIndex < 2) { + // printf("Present %d submitted\n", dummyIndex); + //} + dummy = false; if (args.continuous) ++framesDrawn; + ++dummyIndex; return PUGL_SUCCESS; } -- cgit v1.2.1