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