summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJordan Halase <jordan@halase.me>2019-11-06 09:29:28 -0600
committerJordan Halase <jordan@halase.me>2019-11-06 09:29:28 -0600
commitd8cee89cf98400e8a2d9f90e13ebedeef9e09980 (patch)
tree7c70ef83826d67e890779fc0f6238be43998e994
parent0b25f596751e36e0e4fc323911921fda2f673102 (diff)
Use hacky busy dummy buffer to test semaphore race conditions
-rwxr-xr-xmain.c130
1 files 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;
}