Syncronization Issue when submiting

I’m dealing with a problem of syncronization but only when I try to render a skybox, the rest of the scene works just fine, but if I try to render the skybox it crashes with a validation layer : alidation layer: Fence 0x158 is in use. I tried using VkqueueWaitIdle the message is gone, but it crashes anyway at vkQueueSubmit with a value of -4 wich is DEVICE LOST.
This i my draw cmd creation:

    for (int i = 0; i < cmdBuffers.size(); i++) {
		VkCommandBufferBeginInfo beginInfo{};
		beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
		beginInfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;

		VkResult result = vkBeginCommandBuffer(cmdBuffers[i], &beginInfo);
		vkTools::checkVkresult(result, "Failed to Begin cmdBuffer\n");

		VkRenderPassBeginInfo renderPassInfo{};
		renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
		renderPassInfo.renderPass = mainRenderPass;
		renderPassInfo.framebuffer = mainFrameBuffers[i];
		renderPassInfo.renderArea.offset = { 0,0 };
		renderPassInfo.renderArea.extent = presentationEngine.getExtent();
		
		std::array<VkClearValue,4> clearValues = {};
		clearValues[0].color = { .1f, .3f, .7f, 1.f };
		clearValues[1].color = { .1f, .1f, .1f, 1.f };
		clearValues[2].depthStencil = { 1.0f, 0 };
		clearValues[3].color = { .1f, .1f, .1f, 1.f };

		renderPassInfo.clearValueCount = static_cast<uint32_t>(clearValues.size());
		renderPassInfo.pClearValues = clearValues.data();

		vkCmdBeginRenderPass(cmdBuffers[i], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
	
		VkViewport viewport = {};
		viewport.height = HEIGHT;
		viewport.width = WIDTH;

		viewport.maxDepth = 1.0f;

		VkRect2D rect = {};
		rect.extent.width = WIDTH;
		rect.extent.height = HEIGHT;
		rect.offset = { 0,0 };
		vkCmdSetViewport(cmdBuffers[i], 0, 1, &viewport);
		vkCmdSetScissor(cmdBuffers[i], 0, 1, &rect);
		VkDeviceSize offsets[1] = { 0 };
		vkCmdBindVertexBuffers(cmdBuffers[i], 0, 1, &skybox.vertexBuffer.buffer, offsets);

		std::array<VkDescriptorSet, 1>sets = { skybox.descriptorsets[i] };
		vkCmdBindDescriptorSets(cmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, skyboxPipeline.pipelinelayout, 0, static_cast<uint32_t>(sets.size()), sets.data(), 0, nullptr);
		vkCmdBindPipeline(cmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, skyboxPipeline.pipeline);
		vkCmdDraw(cmdBuffers[i], 36, 1, 0, 0); // If I COMMENT THIS LINE IT WORKS JUST FINE!!!

		for (int j = 0; j < sceneGraph->root->childs.size(); j++) {
						
			Entity *node = sceneGraph->root->childs[j].get()->entity.get();
			switch (node->getPipelineType()) {
			case NONE:
				break;
			case COOK_TORRANCE1:
				node->draw(cmdBuffers[i], cookTorrance1, i, lightDescriptorSets);
				break;
			case COOK_TORRANCE2:
				node->draw(cmdBuffers[i], cookTorrance2, i, lightDescriptorSets);
				break;
			case DUMMY:
				node->draw(cmdBuffers[i], dummyPipeline, i, lightDescriptorSets);
				break;

			}
		}
	
		{
			vkCmdNextSubpass(cmdBuffers[i], VK_SUBPASS_CONTENTS_INLINE);
			vkCmdBindPipeline(cmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, toneMapPipeline.pipeline);
			vkCmdBindDescriptorSets(cmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, toneMapPipeline.pipelinelayout, 0, 1, &toneMapDescriptorSets[i], 0, NULL);
			vkCmdDraw(cmdBuffers[i], 3,1, 0, 0);
			vkCmdEndRenderPass(cmdBuffers[i]);
		}

		{//VerticalBlurPass

			VkRenderPassBeginInfo renderPassInfo{};
			renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
			renderPassInfo.renderPass =verticalBlurRenderPass;
			renderPassInfo.framebuffer = verticalBlurFrameBuffer[i];
			renderPassInfo.renderArea.offset = { 0,0 };
			VkExtent2D extent1 = presentationEngine.getExtent();
			extent1.width  /= 8;
			extent1.height /= 8;

			renderPassInfo.renderArea.extent.width = extent1.width;
			renderPassInfo.renderArea.extent.height = extent1.height;
			std::array<VkClearValue, 2> clearValues = {};
			clearValues[0].color = { .1f, .3f, .7f, 1.f };
			clearValues[1].color = { .1f, .1f, .1f, 1.f };

			renderPassInfo.clearValueCount = static_cast<uint32_t>(clearValues.size());
			renderPassInfo.pClearValues = clearValues.data();

			vkCmdBeginRenderPass(cmdBuffers[i], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);

		
			VkViewport viewport = {};
			viewport.height = extent1.width ;
			viewport.width = extent1.width  ;
			
			viewport.maxDepth = 1.0f;

			VkRect2D rect = {};
			rect.extent.width = extent1.width ;
			rect.extent.height = extent1.width;
			rect.offset = { 0,0 };

			vkCmdSetViewport(cmdBuffers[i], 0, 1, &viewport);
			vkCmdSetScissor(cmdBuffers[i], 0, 1, &rect);
			vkCmdBindPipeline(cmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, verticalBlurPipeline.pipeline);
			vkCmdBindDescriptorSets(cmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, verticalBlurPipeline.pipelinelayout, 0, 1, &verticalBlurDescriptorSet[i], 0, NULL);

			vkCmdDraw(cmdBuffers[i], 3 ,1, 0, 0);

			vkCmdEndRenderPass(cmdBuffers[i]);

		}

		{
			//HorizontalBlurPass
			VkRenderPassBeginInfo renderPassInfo{};
			renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
			renderPassInfo.renderPass = horizontalBlurRenderPass;
			renderPassInfo.framebuffer = horizontalBlurFrameBuffer[i];
			renderPassInfo.renderArea.offset = { 0,0 };
			renderPassInfo.renderArea.extent = presentationEngine.getExtent();

			std::array<VkClearValue, 2> clearValues = {};
			clearValues[0].color = { .1f, .3f, .7f, 1.f };
			clearValues[1].color = { .1f, .1f, .1f, 1.f };


			renderPassInfo.clearValueCount = static_cast<uint32_t>(clearValues.size());
			renderPassInfo.pClearValues = clearValues.data();

			vkCmdBeginRenderPass(cmdBuffers[i], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);

			VkViewport viewport = {};
			viewport.height = HEIGHT;
			viewport.width = WIDTH;

			viewport.maxDepth = 1.0f;

			VkRect2D rect = {};
			rect.extent.width = WIDTH;
			rect.extent.height = HEIGHT;
			rect.offset = { 0,0 };

			vkCmdSetViewport(cmdBuffers[i], 0, 1, &viewport);
			vkCmdSetScissor(cmdBuffers[i], 0, 1, &rect);
			vkCmdBindPipeline(cmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, horizontalBlurPipeline.pipeline);
			vkCmdBindDescriptorSets(cmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, horizontalBlurPipeline.pipelinelayout, 0, 1, &horizontalBlurDescriptorSet[i], 0, NULL);

			vkCmdDraw(cmdBuffers[i], 3, 1, 0, 0);
		
		
			vkCmdEndRenderPass(cmdBuffers[i]);
		}

		if (vkEndCommandBuffer(cmdBuffers[i]) != VK_SUCCESS) {
			std::cout << "Failed to record CommandBuffer\n";
		}

The syncronization is exactly like the Vulkantutorial :

     vkWaitForFences(*device.getDevice(), 1, &syncObjcs.fencesOn[currentFrame],VK_FALSE, UINT64_MAX);

	uint32_t imageIndex;
	VkResult result = vkAcquireNextImageKHR(*device.getDevice(), presentationEngine.getSwapChain(), UINT64_MAX, syncObjcs.imageAvaible [currentFrame], VK_NULL_HANDLE, &imageIndex);

	if (result == VK_ERROR_OUT_OF_DATE_KHR) {
		recreateSwapChain();
		return;
	}
	else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
		throw std::runtime_error("failed to acquire swap chain image!");
	}
	
	update(imageIndex);

	if (syncObjcs.imagesOn[imageIndex] != VK_NULL_HANDLE) {
		vkWaitForFences(*device.getDevice(), 1, &syncObjcs.imagesOn[imageIndex], VK_TRUE, UINT64_MAX);
	}
	syncObjcs.imagesOn[imageIndex] =syncObjcs.fencesOn[currentFrame];

	VkSubmitInfo submitInfo = {};
	submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;

	VkSemaphore waitSemaphores[] = { syncObjcs.imageAvaible[currentFrame] };
	VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
	submitInfo.waitSemaphoreCount = 1;
	submitInfo.pWaitSemaphores = waitSemaphores;
	submitInfo.pWaitDstStageMask = waitStages;

	submitInfo.commandBufferCount = 1;
	submitInfo.pCommandBuffers = &cmdBuffers[imageIndex];

	VkSemaphore signalSemaphores[] = { syncObjcs.renderFinished[currentFrame] };
	submitInfo.signalSemaphoreCount = 1;
	submitInfo.pSignalSemaphores = signalSemaphores;

	vkResetFences(*device.getDevice(),1, &syncObjcs.fencesOn[currentFrame]);

	VkResult r = vkQueueSubmit(device.getGraphicsQueueHandle(), 1, &submitInfo, syncObjcs.fencesOn[currentFrame]);
	if (r != VK_SUCCESS) {
		std::cout << "QueueSubmit result : "<<r << std::endl;
		throw std::runtime_error("failed to submit draw command buffer!");
	}
	
	else {
		std::cout << "QueueSumbmited successfully\n";
	}
	VkPresentInfoKHR presentInfo = {};
	presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;

	presentInfo.waitSemaphoreCount = 1;
	presentInfo.pWaitSemaphores = signalSemaphores;

	VkSwapchainKHR swapChains[] = { presentationEngine.getSwapChain() };
	presentInfo.swapchainCount = 1;
	presentInfo.pSwapchains = swapChains;

	presentInfo.pImageIndices = &imageIndex;

	result = vkQueuePresentKHR(device.getPresentationQueueHandle(), &presentInfo);

	if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR ) {
		recreateSwapChain();
	}
	else if (result != VK_SUCCESS) {
		throw std::runtime_error("failed to present swap chain image!");
	}

	currentFrame = (currentFrame + 1) % MAX_FRAMES;

I have already checked the values of skbox and skyboxPipeline but it seems alright.

fencesOn are created with a signaled Bit

Hi!

where did you find this tutorial ?

https://vulkan-tutorial.com/code/15_hello_triangle.cpp

The error message you get is pretty obvious. Doublecheck your commands which signal a specific fence and where you are waiting for that specific fence!

It could, for example, be that you are passing a fence to a vkQueueSubmit twice (which means that you instruct Vulkan to signal it twice) BEFORE you are waiting on that very same fence (which unsignals it). You must, however, always ensure to follow that strict signal -> unsignal -> signal -> unsignal pattern.

You could search for all usages of the fences and pay close attention to the fence addresses in a debugger. Maybe that reveals some misuse of a fence.

1 Like

Sorry, i have no access to cite. Could you share your project or minimal code where problem cab be reproduced ?

The problem was related to input shader Slot. It was wrong. That causes the sync issue while submitting the buffer.

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.