Using multi-threading blocks the vulkan driver

Hi! I’ve a multi-threaded code with runs perfectly with opengl but blocks the vulkan driver.

I use one thread to do frusturm culling and load entities to the renderer. My renderer looks like this :

void PerPixelLinkedListRenderComponent::drawNextFrame() {
            {
                std::lock_guard<std::recursive_mutex> lock(rec_mutex);
                if (datasReady) {
                    datasReady = false;
                    m_instances = batcher.getInstances();
                    m_normals = normalBatcher.getInstances();
                    m_instancesIndexed = batcherIndexed.getInstances();
                    m_normalsIndexed = normalBatcherIndexed.getInstances();
                    m_selected = selectedBatcher.getInstances();
                    m_selectedScale = selectedScaleBatcher.getInstances();
                    m_selectedIndexed = selectedIndexBatcher.getInstances();
                    m_selectedScaleIndexed = selectedIndexScaleBatcher.getInstances();
                    m_selectedInstance = selectedInstanceBatcher.getInstances();
                    m_selectedScaleInstance = selectedInstanceScaleBatcher.getInstances();
                    m_selectedInstanceIndexed = selectedInstanceIndexBatcher.getInstances();
                    m_selectedScaleInstanceIndexed = selectedInstanceIndexScaleBatcher.getInstances();
                    m_skyboxInstance = skyboxBatcher.getInstances();
                }
            }

            /*math::Matrix4f viewMatrix = view.getViewMatrix().getMatrix().transpose();
            math::Matrix4f projMatrix = view.getProjMatrix().getMatrix().transpose();
            viewMatrix = math::Matrix4f(math::Matrix3f(viewMatrix));


            vb.clear();
            //vb.name = "SKYBOXVB";
            for (unsigned int i = 0; i < m_skyboxInstance.size(); i++) {
                if (m_skyboxInstance[i].getAllVertices().getVertexCount() > 0) {
                    vb.setPrimitiveType(m_skyboxInstance[i].getAllVertices().getPrimitiveType());
                    for (unsigned int j = 0; j < m_skyboxInstance[i].getAllVertices().getVertexCount(); j++) {
                        //if (m_skyboxInstance[i].getAllVertices()[j].position.x != 0 && m_skyboxInstance[i].getAllVertices()[j].position.y != 0 && m_skyboxInstance[i].getAllVertices()[j].position.z != 0);
                        vb.append(m_skyboxInstance[i].getAllVertices()[j]);
                    }
                }
            }
            currentStates.blendMode = sf::BlendAlpha;
            currentStates.shader = &skyboxShader;
            currentStates.texture = (skybox == nullptr ) ? nullptr : &static_cast<g3d::Skybox*>(skybox)->getTexture();
            vb.update();
            frameBuffer.drawVertexBuffer(vb, currentStates);
            vb.clear();*/
            math::Matrix4f projMatrix = view.getProjMatrix().getMatrix()/*.transpose()*/;
            math::Matrix4f viewMatrix = view.getViewMatrix().getMatrix()/*.transpose()*/;
            indirectDrawPushConsts.projMatrix = projMatrix;
            indirectDrawPushConsts.viewMatrix = viewMatrix;
            //indirectDrawPushConsts.projMatrix.m22 *= -1;



            drawInstances();
            drawInstancesIndexed();
            drawSelectedInstances();
            drawSelectedInstancesIndexed();



            vb.clear();
            vb.setPrimitiveType(sf::Triangles);
            Vertex v1 (sf::Vector3f(0, 0, quad.getSize().z));
            Vertex v2 (sf::Vector3f(quad.getSize().x,0, quad.getSize().z));
            Vertex v3 (sf::Vector3f(quad.getSize().x, quad.getSize().y, quad.getSize().z));
            Vertex v4 (sf::Vector3f(0, quad.getSize().y, quad.getSize().z));
            vb.append(v1);
            vb.append(v2);
            vb.append(v3);
            vb.append(v1);
            vb.append(v3);
            vb.append(v4);
            vb.update();
            math::Matrix4f matrix = quad.getTransform().getMatrix()/*.transpose()*/;
            ppll2PushConsts.worldMat = matrix;
            RenderStates currentStates;
            currentStates.shader = &perPixelLinkedListP2;
            currentStates.blendMode = sf::BlendNone;
            frameBuffer.enableStencilTest(false);
            //createDescriptorSets2(currentStates);
            createCommandBufferVertexBuffer(currentStates);

        }
        void PerPixelLinkedListRenderComponent::allocateCommandBuffers() {
            commandBuffers.resize(frameBuffer.getSwapchainImages().size());


            VkCommandBufferAllocateInfo allocInfo{};
            allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
            allocInfo.commandPool = commandPool;
            allocInfo.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY;
            allocInfo.commandBufferCount = (uint32_t) commandBuffers.size();
            if (vkAllocateCommandBuffers(vkDevice.getDevice(), &allocInfo, commandBuffers.data()) != VK_SUCCESS) {
                throw core::Erreur(0, "failed to allocate command buffers!", 1);
            }
        }
        void PerPixelLinkedListRenderComponent::createCommandBuffersIndirect(unsigned int p, unsigned int nbIndirectCommands, unsigned int stride, DepthStencilID depthStencilID, RenderStates currentStates) {

            if (needToUpdateDS) {
                createDescriptorSets(p, currentStates);
                needToUpdateDS = false;
            }
            unsigned int currentFrame = frameBuffer.getCurrentFrame();
            frameBuffer.beginRecordCommandBuffers();
            frameBuffer.beginRenderPass();
            /*VkCommandBufferInheritanceInfo inheritanceInfo;
            inheritanceInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
            inheritanceInfo.pNext = nullptr;
            inheritanceInfo.renderPass = frameBuffer.getRenderPass(1);
            inheritanceInfo.subpass = 0;
            inheritanceInfo.framebuffer = frameBuffer.getSwapchainFrameBuffers(1)[currentFrame];
            inheritanceInfo.occlusionQueryEnable = VK_FALSE;
            inheritanceInfo.queryFlags = 0;
            inheritanceInfo.pipelineStatistics = 0;
            VkCommandBufferBeginInfo commandBufferBeginInfo;
            commandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
            commandBufferBeginInfo.pNext = nullptr;
            commandBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
            commandBufferBeginInfo.pInheritanceInfo = &inheritanceInfo;

            if (vkBeginCommandBuffer(commandBuffers[currentFrame], &commandBufferBeginInfo) != VK_SUCCESS) {
                std::runtime_error("Failed to begin recording command buffers");
            }*/

            Shader* shader = const_cast<Shader*>(currentStates.shader);
            std::vector<Texture*> allTextures = Texture::getAllTextures();



            vkCmdPushConstants(frameBuffer.getCommandBuffers()[currentFrame], frameBuffer.getPipelineLayout()[shader->getId() * (Batcher::nbPrimitiveTypes - 1) + p][frameBuffer.getId()][depthStencilID], VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(IndirectDrawPushConsts), &indirectDrawPushConsts);



            frameBuffer.drawIndirect(frameBuffer.getCommandBuffers()[currentFrame], currentFrame, nbIndirectCommands, stride, vbBindlessTex[p], vboIndirect, depthStencilID,currentStates);

            /*vkCmdResetEvent(frameBuffer.getCommandBuffers()[currentFrame], events[currentFrame],  VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
            vkCmdSetEvent(frameBuffer.getCommandBuffers()[currentFrame], events[currentFrame],  VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);*/

            /*frameBuffer.beginRecordCommandBuffers();
            frameBuffer.beginRenderPass();
            vkCmdExecuteCommands(frameBuffer.getCommandBuffers()[currentFrame], static_cast<uint32_t>(commandBuffers.size()), commandBuffers.data());*/
            frameBuffer.display();

        }
        void PerPixelLinkedListRenderComponent::createCommandBufferVertexBuffer(RenderStates currentStates) {
            frameBuffer.beginRecordCommandBuffers();

            unsigned int currentFrame = frameBuffer.getCurrentFrame();
            /*VkCommandBufferInheritanceInfo inheritanceInfo;
            inheritanceInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
            inheritanceInfo.pNext = nullptr;
            inheritanceInfo.renderPass = frameBuffer.getRenderPass(1);
            inheritanceInfo.subpass = 0;
            inheritanceInfo.framebuffer = frameBuffer.getSwapchainFrameBuffers(1)[currentFrame];
            inheritanceInfo.occlusionQueryEnable = VK_FALSE;
            inheritanceInfo.queryFlags = 0;
            inheritanceInfo.pipelineStatistics = 0;
            VkCommandBufferBeginInfo commandBufferBeginInfo;
            commandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
            commandBufferBeginInfo.pNext = nullptr;
            commandBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
            commandBufferBeginInfo.pInheritanceInfo = &inheritanceInfo;
            if (vkBeginCommandBuffer(commandBuffers[currentFrame], &commandBufferBeginInfo) != VK_SUCCESS) {
                std::runtime_error("Failed to begin recording command buffers");
            }*/
            Shader* shader = const_cast<Shader*>(currentStates.shader);

            //for (size_t i = 0; i < commandBuffers.size(); i++) {
                /*vkResetCommandBuffer(commandBuffers[currentFrame], VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
                VkCommandBufferBeginInfo beginInfo{};
                beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;

                if (vkBeginCommandBuffer(commandBuffers[i], &beginInfo) != VK_SUCCESS) {
                    throw core::Erreur(0, "failed to begin recording command buffer!", 1);
                }*/
                /*std::array<VkWriteDescriptorSet, 2> descriptorWrites{};

                VkDescriptorImageInfo headPtrDescriptorImageInfo;
                headPtrDescriptorImageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
                headPtrDescriptorImageInfo.imageView = headPtrTextureImageView;
                headPtrDescriptorImageInfo.sampler = headPtrTextureSampler;

                descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
                descriptorWrites[0].dstSet = 0;
                descriptorWrites[0].dstBinding = 0;
                descriptorWrites[0].dstArrayElement = 0;
                descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
                descriptorWrites[0].descriptorCount = 1;
                descriptorWrites[0].pImageInfo = &headPtrDescriptorImageInfo;

                VkDescriptorBufferInfo linkedListStorageBufferInfoLastFrame{};
                linkedListStorageBufferInfoLastFrame.buffer = linkedListShaderStorageBuffers[currentFrame];
                linkedListStorageBufferInfoLastFrame.offset = 0;
                unsigned int nodeSize = 5 * sizeof(float) + sizeof(unsigned int);
                linkedListStorageBufferInfoLastFrame.range = maxNodes * nodeSize;

                descriptorWrites[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
                descriptorWrites[1].dstSet = 0;
                descriptorWrites[1].dstBinding = 1;
                descriptorWrites[1].dstArrayElement = 0;
                descriptorWrites[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
                descriptorWrites[1].descriptorCount = 1;
                descriptorWrites[1].pBufferInfo = &linkedListStorageBufferInfoLastFrame;*/
                vkCmdPipelineBarrier(frameBuffer.getCommandBuffers()[currentFrame], VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 0, nullptr);


                VkMemoryBarrier memoryBarrier;
                memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
                memoryBarrier.pNext = VK_NULL_HANDLE;
                memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
                memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;



                vkCmdPipelineBarrier(frameBuffer.getCommandBuffers()[currentFrame], VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 1, &memoryBarrier, 0, nullptr, 0, nullptr);
                //vkCmdPushDescriptorSetKHR(commandBuffers[currentFrame], VK_PIPELINE_BIND_POINT_GRAPHICS, frameBuffer.getPipelineLayout()[shader->getId() * (Batcher::nbPrimitiveTypes - 1) + vb.getPrimitiveType()][frameBuffer.getId()][NODEPTHNOSTENCIL], 0, 2, descriptorWrites.data());

                frameBuffer.beginRenderPass();

                vkCmdPushConstants(frameBuffer.getCommandBuffers()[currentFrame], frameBuffer.getPipelineLayout()[shader->getId() * (Batcher::nbPrimitiveTypes - 1) + vb.getPrimitiveType()][frameBuffer.getId()][NODEPTHNOSTENCIL], VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(Ppll2PushConsts), &ppll2PushConsts);
                //vkCmdWaitEvents(frameBuffer.getCommandBuffers()[currentFrame], 1, &events[currentFrame], VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 1, &memoryBarrier, 0, nullptr, 0, nullptr);
                frameBuffer.drawVertexBuffer(frameBuffer.getCommandBuffers()[currentFrame], currentFrame, vb, NODEPTHNOSTENCIL, currentStates);


                /*if (vkEndCommandBuffer(commandBuffers[currentFrame]) != VK_SUCCESS) {
                    throw core::Erreur(0, "failed to record command buffer!", 1);
                }*/

            //}
            /*if(vkEndCommandBuffer(commandBuffers[currentFrame]) != VK_SUCCESS) {
                std::runtime_error("Failed to record command buffers");
            }*/
            /*frameBuffer.beginRecordCommandBuffers();
            frameBuffer.beginRenderPass();
            vkCmdExecuteCommands(frameBuffer.getCommandBuffers()[currentFrame], static_cast<uint32_t>(commandBuffers.size()), commandBuffers.data());*/
            frameBuffer.display();

        }
        bool PerPixelLinkedListRenderComponent::loadEntitiesOnComponent(std::vector<Entity*> vEntities) {
            {
                std::lock_guard<std::recursive_mutex> lock(rec_mutex);
                datasReady = false;
                batcher.clear();
                normalBatcher.clear();
                batcherIndexed.clear();
                normalBatcherIndexed.clear();
                selectedBatcher.clear();
                selectedScaleBatcher.clear();
                selectedIndexBatcher.clear();
                selectedIndexScaleBatcher.clear();
                selectedInstanceBatcher.clear();
                selectedInstanceScaleBatcher.clear();
                selectedInstanceIndexBatcher.clear();
                selectedInstanceIndexScaleBatcher.clear();
                skyboxBatcher.clear();
                visibleSelectedScaleEntities.clear();
            }
            if (skybox != nullptr) {
                for (unsigned int i = 0; i <  skybox->getNbFaces(); i++) {
                    skyboxBatcher.addFace(skybox->getFace(i));
                }
            }
            for (unsigned int i = 0; i < vEntities.size(); i++) {

                if ( vEntities[i] != nullptr && vEntities[i]->isLeaf()) {
                    Entity* border;
                    if (vEntities[i]->isSelected()) {
                        border = vEntities[i]->clone();
                        border->decreaseNbEntities();
                    }
                    for (unsigned int j = 0; j <  vEntities[i]->getNbFaces(); j++) {
                         std::lock_guard<std::recursive_mutex> lock(rec_mutex);
                         if (vEntities[i]->getDrawMode() == Entity::INSTANCED && !vEntities[i]->isSelected()) {
                            if (vEntities[i]->getFace(j)->getVertexArray().getIndexes().size() == 0)
                                batcher.addFace( vEntities[i]->getFace(j));
                            else
                                batcherIndexed.addFace(vEntities[i]->getFace(j));
                         } else if (vEntities[i]->getDrawMode() == Entity::NORMAL && !vEntities[i]->isSelected()) {
                             if (vEntities[i]->getFace(j)->getVertexArray().getIndexes().size() == 0) {
                                normalBatcher.addFace( vEntities[i]->getFace(j));
                             } else
                                normalBatcherIndexed.addFace( vEntities[i]->getFace(j));
                        } else if (vEntities[i]->getDrawMode() == Entity::INSTANCED && vEntities[i]->isSelected()) {

                            if (vEntities[i]->getFace(j)->getVertexArray().getIndexes().size() == 0) {
                                selectedInstanceBatcher.addFace(vEntities[i]->getFace(j));
                           // std::cout<<"remove texture"<<std::endl;

                            //std::cout<<"get va"<<std::endl;
                                VertexArray& va = border->getFace(j)->getVertexArray();
                                //std::cout<<"change color"<<std::endl;
                                for (unsigned int j = 0; j < va.getVertexCount(); j++) {

                                    va[j].color = sf::Color::Cyan;
                                }
                                Entity* root = (vEntities[i]->getRootEntity()->isAnimated()) ? vEntities[i]->getRootEntity() : vEntities[i];
                                math::Vec3f oldSize = root->getSize();
                                border->setOrigin(border->getSize() * 0.5f);
                                border->setScale(math::Vec3f(1.1f, 1.1f, 1.1f));
                                math::Vec3f offset =  root->getSize() - oldSize;
                                border->setPosition(root->getPosition() - offset * 0.5f);
                               // std::cout<<"add to batcher"<<std::endl;
                                selectedInstanceScaleBatcher.addFace(border->getFace(j));
                           // std::cout<<"face added"<<std::endl;
                             } else {
                                 selectedInstanceIndexBatcher.addFace(vEntities[i]->getFace(j));
                               // std::cout<<"remove texture"<<std::endl;

                            //std::cout<<"get va"<<std::endl;
                                VertexArray& va = border->getFace(j)->getVertexArray();
                                //std::cout<<"change color"<<std::endl;
                                for (unsigned int j = 0; j < va.getVertexCount(); j++) {

                                    va[j].color = sf::Color::Cyan;
                                }
                                Entity* root = (vEntities[i]->getRootEntity()->isAnimated()) ? vEntities[i]->getRootEntity() : vEntities[i];
                                math::Vec3f oldSize = root->getSize();
                                border->setOrigin(root->getSize() * 0.5f);
                                border->setSize(root->getSize() * 1.1f);
                                math::Vec3f offset =  root->getSize() - oldSize;
                                border->setPosition(root->getPosition() - offset * 0.5f);

                               // std::cout<<"add to batcher"<<std::endl;
                                selectedInstanceIndexScaleBatcher.addFace(border->getFace(j));
                             }
                        } else {
                            if (vEntities[i]->getFace(j)->getVertexArray().getIndexes().size() == 0) {

                                selectedBatcher.addFace(vEntities[i]->getFace(j));
                           // std::cout<<"remove texture"<<std::endl;

                            //std::cout<<"get va"<<std::endl;
                                VertexArray& va = border->getFace(j)->getVertexArray();
                                //std::cout<<"change color"<<std::endl;
                                for (unsigned int j = 0; j < va.getVertexCount(); j++) {

                                    va[j].color = sf::Color::Cyan;
                                }
                                Entity* root = (vEntities[i]->getRootEntity()->isAnimated()) ? vEntities[i]->getRootEntity() : vEntities[i];
                                math::Vec3f oldSize = root->getSize();
                                border->setOrigin(root->getSize() * 0.5f);
                                border->setSize(root->getSize() * 1.1f);
                                math::Vec3f offset =  root->getSize() - oldSize;
                                border->setPosition(root->getPosition() - offset * 0.5f);
                                selectedScaleBatcher.addFace(border->getFace(j));

                               // std::cout<<"face added"<<std::endl;
                             } else {
                                 selectedIndexBatcher.addFace(vEntities[i]->getFace(j));
                               // std::cout<<"remove texture"<<std::endl;

                            //std::cout<<"get va"<<std::endl;
                                VertexArray& va = border->getFace(j)->getVertexArray();
                                //std::cout<<"change color"<<std::endl;
                                for (unsigned int j = 0; j < va.getVertexCount(); j++) {

                                    va[j].color = sf::Color::Cyan;
                                }

                                border->setOrigin(border->getSize() * 0.5f);
                                border->setScale(math::Vec3f(1.1f, 1.1f, 1.1f));
                               // std::cout<<"add to batcher"<<std::endl;
                                selectedIndexScaleBatcher.addFace(border->getFace(j));
                             }
                        }
                    }
                    if (vEntities[i]->isSelected()) {
                        std::unique_ptr<Entity> ptr;
                        ptr.reset(border);
                        visibleSelectedScaleEntities.push_back(std::move(ptr));
                    }
                }

            }

I update the instances only when the entities are entirely loaded on the component so I use a boolean and an if.
Works perfectly with opengl but blocks the vulkan driver.
Thanks.

Ok it seems it’s when I use several threads that makes the vulkan driver blocking…, I think I’ll return to opengl. (The synchronization is done implicitly so less bugs than with the barriers which are often source of bugs)

Ok I’ve found the issue.