diff options
| author | Jordan Halase <jordan@halase.me> | 2019-11-06 09:29:28 -0600 | 
|---|---|---|
| committer | Jordan Halase <jordan@halase.me> | 2019-11-06 09:29:28 -0600 | 
| commit | d8cee89cf98400e8a2d9f90e13ebedeef9e09980 (patch) | |
| tree | 7c70ef83826d67e890779fc0f6238be43998e994 | |
| parent | 0b25f596751e36e0e4fc323911921fda2f673102 (diff) | |
Use hacky busy dummy buffer to test semaphore race conditions
| -rwxr-xr-x | main.c | 130 | 
1 files changed, 124 insertions, 6 deletions
@@ -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;  }  | 
