在第二次创建命令缓冲区时,vkCmdDrawIndexed中的段错误

时间:2017-04-22 11:43:37

标签: c++ vulkan

编辑: 这是valgrind的输出:

==6785== 
==6785== Process terminating with default action of signal 11 (SIGSEGV)
==6785==  Access not within mapped region at address 0xE0
==6785==    at 0xA138542: cvdescriptorset::DescriptorSet::ValidateDrawState(std::map<unsigned int, descriptor_req, std::less<unsigned int>, std::allocator<std::pair<unsigned int const, descriptor_req> > > const&, std::vector<unsigned int, std::allocator<unsigned int> > const&, std::string*) const (in /home/user/VulkanSDK/1.0.37.0/x86_64/lib/libVkLayer_core_validation.so)
==6785==    by 0xA0D9A06: core_validation::validate_and_update_draw_state(core_validation::layer_data*, GLOBAL_CB_NODE*, bool, VkPipelineBindPoint, char const*) (in /home/user/VulkanSDK/1.0.37.0/x86_64/lib/libVkLayer_core_validation.so)
==6785==    by 0xA0EE4F3: core_validation::CmdDrawIndexed(VkCommandBuffer_T*, unsigned int, unsigned int, unsigned int, int, unsigned int) (in /home/user/VulkanSDK/1.0.37.0/x86_64/lib/libVkLayer_core_validation.so)
==6785==    by 0xA8B6F23: object_tracker::CmdDrawIndexed(VkCommandBuffer_T*, unsigned int, unsigned int, unsigned int, int, unsigned int) (in /home/user/VulkanSDK/1.0.37.0/x86_64/lib/libVkLayer_object_tracker.so)
==6785==    by 0xB3AD421: threading::CmdDrawIndexed(VkCommandBuffer_T*, unsigned int, unsigned int, unsigned int, int, unsigned int) (in /home/user/VulkanSDK/1.0.37.0/x86_64/lib/libVkLayer_threading.so)
==6785==    by 0x13B147: VulkanRenderer::createCommandBuffers(ObjectInRAM*, ObjectInRAM*) (in /home/wobbi/git/Code/Implementierungen/Vulkan/VulkanTest)
==6785==    by 0x13F1FF: VulkanRenderer::mainLoop() (in /home/wobbi/git/Code/Implementierungen/Vulkan/VulkanTest)
==6785==    by 0x110716: main (in /home/wobbi/git/Code/Implementierungen/Vulkan/VulkanTest)

我在Vulkan应用程序中以某种方式设法获得了vkCmdDrawIndexed中的段错误。 我想做的是想画两个物体。第一个只有一次和第二个对象在不同的​​位置可变次数(没有实例化)。我通过pushConstants获得了不同的位置,一切正常。

当按下按钮时,我想增加第二个对象的绘制次数,所以我等到设备空闲,然后用新的绘制调用次数重新创建命令缓冲区。

但是在重新创建命令缓冲区时,我遇到了一个段错误: vkCmdDrawIndexed(commandBuffers [i],obj2-&gt; indices.size(),1,0,0,0);

我的代码基于Vulkan-Tutorial.com,所以我只是再次调用createCommandBuffers() - 函数。

我分配了我的游泳池: poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;

非常感谢任何有关我为什么会遇到段错误的帮助

代码:

void VulkanRenderer::mainLoop() 
{
    float lastTextureChange = glfwGetTime();
    float lastFPSUpdate = glfwGetTime();
    int numFrames = 0;
    int lastGPULoad = 1; 

    while (!glfwWindowShouldClose(window)) {
        glfwPollEvents();

        //adjust camera values
        //if frames are further apart then movement between frames has to be faster
        float currentFrame = glfwGetTime();
        deltaTime = currentFrame - lastFrame;
        lastFrame = currentFrame;  


        do_movement();

        updateUniformBuffer(glm::vec3(0.0f), 0.1f);


        if(lastGPULoad != GPULoad)
        {           
            lastGPULoad = GPULoad;
            recreateSwapChain();
        }

        drawFrame();

    }

    vkDeviceWaitIdle(device);

    glfwDestroyWindow(window);
}


void VulkanRenderer::recreateSwapChain()
{
    vkDeviceWaitIdle(device);

    createSwapChain();
    createImageViews();
    createRenderPass();
    createGraphicsPipeline();
    createDepthResources();
    createFramebuffers();
    createCommandBuffers(&male, &cube); 
}


void VulkanRenderer::createCommandBuffers(ObjectInRAM* obj, ObjectInRAM* obj2)
{
    //check if old command buffers are still around and free them
    if (commandBuffers.size() > 0) 
    {
        vkFreeCommandBuffers(device, commandPool, commandBuffers.size(), commandBuffers.data());
    }

    commandBuffers.resize(swapChainFramebuffers.size());
    std::cout <<"creating new command buffers:" <<commandBuffers.size() <<std::endl;

    VkCommandBufferAllocateInfo allocInfo = {};
    allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
    allocInfo.commandPool = commandPool;
    allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
    allocInfo.commandBufferCount = (uint32_t) commandBuffers.size();

    if (vkAllocateCommandBuffers(device, &allocInfo, commandBuffers.data()) != VK_SUCCESS) {
        throw std::runtime_error("failed to allocate command buffers!");
    }

    for (size_t i = 0; i < commandBuffers.size(); i++) {
        VkCommandBufferBeginInfo beginInfo = {};
        beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
        beginInfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
        beginInfo.pInheritanceInfo = nullptr; // Optional

        vkBeginCommandBuffer(commandBuffers[i], &beginInfo);

            VkRenderPassBeginInfo renderPassInfo = {};
            renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
            renderPassInfo.renderPass = renderPass;
            renderPassInfo.framebuffer = swapChainFramebuffers[i];

            renderPassInfo.renderArea.offset = {0};
            renderPassInfo.renderArea.extent = swapChainExtent;

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

            renderPassInfo.clearValueCount = clearValues.size();
            renderPassInfo.pClearValues = clearValues.data();

            updateUniformBuffer(glm::vec3(80.0f, 80.0f, 80.0f), 10.0f);

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

                pushUBO.model = glm::mat4();
                pushUBO.model = glm::scale(pushUBO.model, glm::vec3(1.0f));

                // Submit via push constant (rather than a UBO)
                vkCmdPushConstants(
                    commandBuffers[i],
                    pipelineLayout,
                    VK_SHADER_STAGE_VERTEX_BIT,
                    0,
                    sizeof(pushUBO),
                    &pushUBO
                );


                vkCmdBindPipeline(commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline);

                vkCmdBindDescriptorSets(commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr);                   
                //Binding vertex buffers                    
                VkBuffer vertexBuffers[] = {obj2->vertexBuffer};
                VkDeviceSize offsets[] = {0};
                vkCmdBindVertexBuffers(commandBuffers[i], 0, 1, vertexBuffers, offsets);
                vkCmdBindIndexBuffer(commandBuffers[i], obj2->indexBuffer, 0, VK_INDEX_TYPE_UINT32);
                std::cout <<"bound index: " <<obj2->indices.size() <<std::endl;

                vkCmdDrawIndexed(commandBuffers[i], obj2->indices.size(), 1,0,0,0);

                std::cout <<"before crowd cmd recording " <<std::endl;
                //render crowd
                vertexBuffers[0] = obj->vertexBuffer;               
                vkCmdBindVertexBuffers(commandBuffers[i], 0, 1, vertexBuffers, offsets);
                vkCmdBindIndexBuffer(commandBuffers[i], obj->indexBuffer, 0, VK_INDEX_TYPE_UINT32);


                int drawCmdCounter = 0;
                while(drawCmdCounter < GPULoad)
                {
                     pushUBO.model = glm::mat4();
                     pushUBO.model = glm::translate(pushUBO.model, glm::vec3(drawCmdCounter*5.0f, 0.0f,0.0f));
                     // Submit via push constant (rather than a UBO)
                     vkCmdPushConstants(
                        commandBuffers[i],
                        pipelineLayout,
                        VK_SHADER_STAGE_VERTEX_BIT,
                        0,
                        sizeof(pushUBO),
                        &pushUBO
                     );

                     vkCmdDrawIndexed(commandBuffers[i], obj->indices.size(), 1,0,0,0);
                     drawCmdCounter++;
                }            

            vkCmdEndRenderPass(commandBuffers[i]);
        if (vkEndCommandBuffer(commandBuffers[i]) != VK_SUCCESS) {
            throw std::runtime_error("failed to record command buffer!");
        }        
    }
}

1 个答案:

答案 0 :(得分:0)

在调用堆栈中,它看起来像是层内的崩溃。

1)(始终)使用updated SDK!你知道,我可以看到你使用的是过时的SDK。在撰写本文时,有四个较新版本,可能还有bambillion错误修正。

2)尝试关闭图层来运行它。这将验证它是图层中的错误。

3)如果1)没有帮助,2)你确定它是图层,那么你可以尝试trunk version层(或者至少扫描相关内容的最新提交),然后查找现有问题或报告新问题。

4)通过设置SDK/Source/lib变量,您可以在VK_LAYER_PATH中使用图层的调试版本。这样就可以对图层本身进行断点/步骤调试。