使用Vulkan绘制多个纹理对象时闪烁的屏幕

时间:2017-03-10 09:44:47

标签: c++ vulkan

我是Vulkan的新手,所以请不要让我忘记。我一直在构建一个可以加载fbx格式的3D模型的程序。我一次渲染多个纹理对象时遇到了问题。我一直在根据一本名为Learning Vulkan的书来构建这个程序,并在这里和那里做了一些小改动。

编辑: 我现在已经从VulkanDrawable将渲染函数移动到VulkanRenderer。我将每个VulkanDrawable的绘图命令缓冲区收集到一个向量中,并尝试将其提交到队列但是收到错误,程序在将其中一个对象绘制到屏幕上几分之一秒后崩溃。程序失败,出现以下错误,我似乎无法修复:[VK_DEBUG_REPORT]错误:[ObjectTracker] Code149:无效的命令缓冲区对象0x21。 以下是请求的代码段。

这是VulkanRenderer中的函数(也可能是bug):

bool VulkanRenderer::render(){
while(!glfwWindowShouldClose(window))
{
    glfwPollEvents();

    uint32_t& currentColorImage = swapChainObject->scPublicVariables.currentColorBuffer;
    VkSwapchainKHR& swapchain = swapChainObject->scPublicVariables.swapchain;

    //Get the index of the next available swapchain image
    VkResult result = swapChainObject->fpAcquireNextImageKHR(deviceObject->device,
                                                             swapchain,
                                                             UINT64_MAX,
                                                             presentCompleteSemaphore,
                                                             VK_NULL_HANDLE,
                                                             &currentColorImage);

    //getDrawBuffer function inside VulkanDrawable looks like this (all in header file):
    //inline VkCommandBuffer* getDrawBuffer(int index){return &vecCmdDraw[index];}

    //This is a temporary solution and probably wrong as well. I am gathering pointers to
    //the drawing buffers that I want to execute.
    std::vector<VkCommandBuffer*> buffers{drawableObjects[0]->getDrawBuffer(currentColorImage),
                                          drawableObjects[1]->getDrawBuffer(currentColorImage)};

    //Create submit information
    VkSubmitInfo submitInfo = {};
    submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
    submitInfo.pNext = nullptr;
    submitInfo.waitSemaphoreCount = 1;
    submitInfo.pWaitSemaphores = &presentCompleteSemaphore;
    submitInfo.pWaitDstStageMask = &submitPipelineStages;
    submitInfo.commandBufferCount = (uint32_t)sizeof(buffers) / sizeof(VkCommandBuffer);
    //This *buffers.data looks dodgy but it won't compile otherwise
    submitInfo.pCommandBuffers = *buffers.data();
    submitInfo.signalSemaphoreCount = 1;
    submitInfo.pSignalSemaphores = &drawingCompleteSemaphore;

    CommandBufferManager::submitCommandBuffer(deviceObject->queue, *buffers.data(), &submitInfo);

    //Present image in the window
    VkPresentInfoKHR present = {};
    present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
    present.pNext = nullptr;
    present.swapchainCount = 1;
    present.pSwapchains = &swapchain;
    present.pImageIndices = &currentColorImage;
    present.pWaitSemaphores = &drawingCompleteSemaphore;
    present.waitSemaphoreCount = 1;
    present.pResults = nullptr;

    //queue the image for presentation
    result = swapChainObject->fpQueuePresentKHR(deviceObject->queue, &present);
  }
}

这是submitCommandBuffer函数(fence是默认的VK_NULL_HANDLE):

//Submits given command buffer to given queue with provided submit info and fence.  
void CommandBufferManager::submitCommandBuffer(const VkQueue &queue,
                                           const VkCommandBuffer *cmdBuffer,
                                           const VkSubmitInfo *submitInfo,
                                           const VkFence &fence){
VkResult result;
//If submit information is provided, use it.
if(submitInfo)
{
    result = vkQueueSubmit(queue, 1, submitInfo, fence);
    assert(!result);

    result = vkQueueWaitIdle(queue);
    assert(!result);
    return;
}

//If not, create default submit info
VkSubmitInfo defaultSubmitInfo = {};
defaultSubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
defaultSubmitInfo.pNext = nullptr;
defaultSubmitInfo.waitSemaphoreCount = 0;
defaultSubmitInfo.pWaitSemaphores = nullptr;
defaultSubmitInfo.signalSemaphoreCount = 0;
defaultSubmitInfo.pSignalSemaphores = nullptr;
defaultSubmitInfo.pWaitDstStageMask = nullptr;
defaultSubmitInfo.commandBufferCount = (uint32_t) sizeof(cmdBuffer) / sizeof(VkCommandBuffer);
defaultSubmitInfo.pCommandBuffers = cmdBuffer;

result = vkQueueSubmit(queue, 1, &defaultSubmitInfo, fence);
assert(!result);

result = vkQueueWaitIdle(queue);
assert(!result);
}

Renderpass:

void VulkanRenderer::createRenderPass(bool includeDepth, bool clear)
{
//This function depends on the VulkanSwapchain to get the
//color image and VulkanRenderer to get the depth image
VkResult result;

//Attach color and depth buffers as an attachment to render pass instance.
VkAttachmentDescription attachments[2];
attachments[0].format = swapChainObject->scPublicVariables.format;
attachments[0].samples = NUM_SAMPLES;
//If clear is required, use it, else don't care.
attachments[0].loadOp = clear ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attachments[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
attachments[0].flags = VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT;

//If depth buffer is presented, define the properties for depth buffer attachment
if(includeDepth)
{
    attachments[1].format = Depth.format;
    attachments[1].samples = NUM_SAMPLES;
    attachments[1].loadOp = clear ? VK_ATTACHMENT_LOAD_OP_CLEAR :
                                    VK_ATTACHMENT_LOAD_OP_DONT_CARE;
    attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
    attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
    attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
    attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
    attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
    attachments[1].flags = VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT;
}

//Define color buffer attachment binding points and layout information
VkAttachmentReference colorReference = {};
colorReference.attachment = 0;
colorReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;

//Define depth buffer attachment binding points and layout information
VkAttachmentReference depthReference = {};
depthReference.attachment = 1;
depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;

//Specify attachments - color, depth, resolve, preserve etc.
VkSubpassDescription subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.flags = 0;
subpass.inputAttachmentCount = 0;
subpass.pInputAttachments = nullptr;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &colorReference;
subpass.pResolveAttachments = nullptr;
subpass.pDepthStencilAttachment = includeDepth ? &depthReference : nullptr;
subpass.preserveAttachmentCount = 0;
subpass.pPreserveAttachments = nullptr;

//Specify the attachment and subpass associated with render pass
VkRenderPassCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
createInfo.pNext = nullptr;
createInfo.attachmentCount = includeDepth ? 2 : 1;
createInfo.pAttachments = attachments;
createInfo.subpassCount = 1;
createInfo.pSubpasses = &subpass;
createInfo.dependencyCount = 0;
createInfo.pDependencies = nullptr;

//Create the render pass
result = vkCreateRenderPass(deviceObject->device, &createInfo, nullptr, &renderPass);
assert(result == VK_SUCCESS);
}
编辑:忘了添加命令缓冲区记录和api转储的部分内容:

Thread 0, Frame 0:
vkBeginCommandBuffer(commandBuffer, pBeginInfo) returns VkResult VK_SUCCESS (0):
    commandBuffer:                  VkCommandBuffer = 0x1fc0bf0
    pBeginInfo:                     const VkCommandBufferBeginInfo* = 0x1f9c070:
        sType:                          VkStructureType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO (42)
        pNext:                          const void* = NULL
        flags:                          VkCommandBufferUsageFlags = 0
        pInheritanceInfo:               const VkCommandBufferInheritanceInfo* = UNUSED

Thread 0, Frame 0:
vkCmdBeginRenderPass(commandBuffer, pRenderPassBegin, contents) returns void:
    commandBuffer:                  VkCommandBuffer = 0x1fc0bf0
    pRenderPassBegin:               const VkRenderPassBeginInfo* = 0x1fc2810:
        sType:                          VkStructureType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO (43)
        pNext:                          const void* = NULL
        renderPass:                     VkRenderPass = 0x1f76d00
        framebuffer:                    VkFramebuffer = 0x1f77b00
        renderArea:                     VkRect2D = 0x1fc2830:
            offset:                         VkOffset2D = 0x1fc2830:
                x:                              int32_t = 0
                y:                              int32_t = 0
            extent:                         VkExtent2D = 0x1fc2838:
                width:                          uint32_t = 800
                height:                         uint32_t = 800
        clearValueCount:                uint32_t = 2
        pClearValues:                   const VkClearValue* = 0x1fc2860
            pClearValues[0]:                const VkClearValue = 0x1fc2860 (Union):
                color:                          VkClearColorValue = 0x1fc2860 (Union):
                    float32:                        float[4] = 0x1fc2860
                        float32[0]:                     float = 1
                        float32[1]:                     float = 1
                        float32[2]:                     float = 1
                        float32[3]:                     float = 1
                    int32:                          int32_t[4] = 0x1fc2860
                        int32[0]:                       int32_t = 1065353216
                        int32[1]:                       int32_t = 1065353216
                        int32[2]:                       int32_t = 1065353216
                        int32[3]:                       int32_t = 1065353216
                    uint32:                         uint32_t[4] = 0x1fc2860
                        uint32[0]:                      uint32_t = 1065353216
                        uint32[1]:                      uint32_t = 1065353216
                        uint32[2]:                      uint32_t = 1065353216
                        uint32[3]:                      uint32_t = 1065353216
                depthStencil:                   VkClearDepthStencilValue = 0x1fc2860:
                    depth:                          float = 1
                    stencil:                        uint32_t = 1065353216
            pClearValues[1]:                const VkClearValue = 0x1fc2870 (Union):
                color:                          VkClearColorValue = 0x1fc2870 (Union):
                    float32:                        float[4] = 0x1fc2870
                        float32[0]:                     float = 1
                        float32[1]:                     float = 0
                        float32[2]:                     float = 0
                        float32[3]:                     float = 0
                    int32:                          int32_t[4] = 0x1fc2870
                        int32[0]:                       int32_t = 1065353216
                        int32[1]:                       int32_t = 0
                        int32[2]:                       int32_t = 0
                        int32[3]:                       int32_t = 0
                    uint32:                         uint32_t[4] = 0x1fc2870
                        uint32[0]:                      uint32_t = 1065353216
                        uint32[1]:                      uint32_t = 0
                        uint32[2]:                      uint32_t = 0
                        uint32[3]:                      uint32_t = 0
                depthStencil:                   VkClearDepthStencilValue = 0x1fc2870:
                    depth:                          float = 1
                    stencil:                        uint32_t = 0
    contents:                       VkSubpassContents = VK_SUBPASS_CONTENTS_INLINE (0)

Thread 0, Frame 0:
vkCmdBindPipeline(commandBuffer, pipelineBindPoint, pipeline) returns void:
    commandBuffer:                  VkCommandBuffer = 0x1fc0bf0
    pipelineBindPoint:              VkPipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS (0)
    pipeline:                       VkPipeline = 0x1fa4ae0

Thread 0, Frame 0:
vkCmdBindDescriptorSets(commandBuffer, pipelineBindPoint, layout, firstSet, descriptorSetCount, pDescriptorSets, dynamicOffsetCount, pDynamicOffsets) returns void:
    commandBuffer:                  VkCommandBuffer = 0x1fc0bf0
    pipelineBindPoint:              VkPipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS (0)
    layout:                         VkPipelineLayout = 0x1fa2fe0
    firstSet:                       uint32_t = 0
    descriptorSetCount:             uint32_t = 1
    pDescriptorSets:                const VkDescriptorSet* = 0x1fc2970
        pDescriptorSets[0]:             const VkDescriptorSet = 0x1fa1f70
    dynamicOffsetCount:             uint32_t = 0
    pDynamicOffsets:                const uint32_t* = NULL

Thread 0, Frame 0:
vkCmdBindVertexBuffers(commandBuffer, firstBinding, bindingCount, pBuffers, pOffsets) returns void:
    commandBuffer:                  VkCommandBuffer = 0x1fc0bf0
    firstBinding:                   uint32_t = 0
    bindingCount:                   uint32_t = 1
    pBuffers:                       const VkBuffer* = 0x1fc2a40
        pBuffers[0]:                    const VkBuffer = 0x1f98020
    pOffsets:                       const VkDeviceSize* = 0x7ffc731014c0
        pOffsets[0]:                    const VkDeviceSize = 0

Thread 0, Frame 0:
vkCmdSetViewport(commandBuffer, firstViewport, viewportCount, pViewports) returns void:
    commandBuffer:                  VkCommandBuffer = 0x1fc0bf0
    firstViewport:                  uint32_t = 0
    viewportCount:                  uint32_t = 1
    pViewports:                     const VkViewport* = 0x1f95c58
        pViewports[0]:                  const VkViewport = 0x1f95c58:
            x:                              float = 0
            y:                              float = 0
            width:                          float = 800
            height:                         float = 800
            minDepth:                       float = 0
            maxDepth:                       float = 1

Thread 0, Frame 0:
vkCmdSetScissor(commandBuffer, firstScissor, scissorCount, pScissors) returns void:
    commandBuffer:                  VkCommandBuffer = 0x1fc0bf0
    firstScissor:                   uint32_t = 0
    scissorCount:                   uint32_t = 1
    pScissors:                      const VkRect2D* = 0x1f95c70
        pScissors[0]:                   const VkRect2D = 0x1f95c70:
            offset:                         VkOffset2D = 0x1f95c70:
                x:                              int32_t = 0
                y:                              int32_t = 0
            extent:                         VkExtent2D = 0x1f95c78:
                width:                          uint32_t = 800
                height:                         uint32_t = 800

Thread 0, Frame 0:
vkCmdDraw(commandBuffer, vertexCount, instanceCount, firstVertex, firstInstance) returns void:
    commandBuffer:                  VkCommandBuffer = 0x1fc0bf0
    vertexCount:                    uint32_t = 36
    instanceCount:                  uint32_t = 1
    firstVertex:                    uint32_t = 0
    firstInstance:                  uint32_t = 0

Thread 0, Frame 0:
vkCmdEndRenderPass(commandBuffer) returns void:
    commandBuffer:                  VkCommandBuffer = 0x1fc0bf0

Thread 0, Frame 0:
vkEndCommandBuffer(commandBuffer) returns VkResult VK_SUCCESS (0):
    commandBuffer:                  VkCommandBuffer = 0x1fc0bf0

Thread 0, Frame 0:
vkAcquireNextImageKHR(device, swapchain, timeout, semaphore, fence, pImageIndex) returns VkResult VK_SUCCESS (0):
    device:                         VkDevice = 0x1d86dd0
    swapchain:                      VkSwapchainKHR = 0x1f23c60
    timeout:                        uint64_t = 18446744073709551615
    semaphore:                      VkSemaphore = 0x1d8a560
    fence:                          VkFence = 0
    pImageIndex:                    uint32_t* = 0

Thread 0, Frame 0:
vkQueueSubmit(queue, submitCount, pSubmits, fence) returns VkResult VK_SUCCESS (0):
    queue:                          VkQueue = 0x1eba560
    submitCount:                    uint32_t = 1
    pSubmits:                       const VkSubmitInfo* = 0x1efeaa8
        pSubmits[0]:                    const VkSubmitInfo = 0x1efeaa8:
            sType:                          VkStructureType = VK_STRUCTURE_TYPE_SUBMIT_INFO (4)
            pNext:                          const void* = NULL
            waitSemaphoreCount:             uint32_t = 1
            pWaitSemaphores:                const VkSemaphore* = 0x1fc3820
                pWaitSemaphores[0]:             const VkSemaphore = 0x1d8a560
            pWaitDstStageMask:              const VkPipelineStageFlags* = 0x1fc3780
                pWaitDstStageMask[0]:           const VkPipelineStageFlags = 1024 (VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT)
            commandBufferCount:             uint32_t = 3
            pCommandBuffers:                const VkCommandBuffer* = 0x1fc3730
                pCommandBuffers[0]:             const VkCommandBuffer = 0x1fa98a0
                pCommandBuffers[1]:             const VkCommandBuffer = 0x1fb01c0
                pCommandBuffers[2]:             const VkCommandBuffer = 0x1fb7d70
            signalSemaphoreCount:           uint32_t = 1
            pSignalSemaphores:              const VkSemaphore* = 0x1fc36e0
                pSignalSemaphores[0]:           const VkSemaphore = 0x1d8a710
    fence:                          VkFence = 0

Thread 0, Frame 0:
vkQueuePresentKHR(queue, pPresentInfo) returns VkResult VK_SUCCESS (0):
    queue:                          VkQueue = 0x1eba560
    pPresentInfo:                   const VkPresentInfoKHR* = 0x1fc2810:
        sType:                          VkStructureType = UNKNOWN (1000001001)
        pNext:                          const void* = NULL
        waitSemaphoreCount:             uint32_t = 1
        pWaitSemaphores:                const VkSemaphore* = 0x1fc36e0
            pWaitSemaphores[0]:             const VkSemaphore = 0x1d8a710
        swapchainCount:                 uint32_t = 1
        pSwapchains:                    const VkSwapchainKHR* = 0x1fc3730
            pSwapchains[0]:                 const VkSwapchainKHR = 0x1f23c60
        pImageIndices:                  const uint32_t* = 0x1d8a418
            pImageIndices[0]:               const uint32_t = 0
        pResults:                       VkResult* = NULL

Thread 0, Frame 1:
vkAcquireNextImageKHR(device, swapchain, timeout, semaphore, fence, pImageIndex) returns VkResult VK_SUCCESS (0):
    device:                         VkDevice = 0x1d86dd0
    swapchain:                      VkSwapchainKHR = 0x1f23c60
    timeout:                        uint64_t = 18446744073709551615
    semaphore:                      VkSemaphore = 0x1d8a560
    fence:                          VkFence = 0
    pImageIndex:                    uint32_t* = 1
[VK_DEBUG_REPORT] ERROR: [ObjectTracker] Code149:Invalid Command Buffer Object 0x21. For more information refer to Vulkan Spec Section '5.4. Command Buffer Submission' which states 'If commandBufferCount is not 0, pCommandBuffers must be a pointer to an array of commandBufferCount valid VkCommandBuffer handles' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkSubmitInfo)

命令缓冲区记录:

void VulkanDrawable::recordCommandBuffer(int currentImage, VkCommandBuffer *cmdDraw){

//VulkanDevice* deviceObject = rendererObject->getDevice();

//Specify clear color values
VkClearValue clearValues[2];
clearValues[0].color.float32[0] = 1.0f;
clearValues[0].color.float32[1] = 1.0f;
clearValues[0].color.float32[2] = 1.0f;
clearValues[0].color.float32[3] = 1.0f;

//Specify depth/stencil clear value
clearValues[1].depthStencil.depth = 1.0f;
clearValues[1].depthStencil.stencil = 0;

VkRenderPassBeginInfo renderPassBegin = {};
renderPassBegin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassBegin.pNext = nullptr;
renderPassBegin.renderPass = rendererObject->renderPass;
renderPassBegin.framebuffer = rendererObject->framebuffers[currentImage];
renderPassBegin.renderArea.offset.x = 0;
renderPassBegin.renderArea.offset.y = 0;
renderPassBegin.renderArea.extent.width = rendererObject->width;
renderPassBegin.renderArea.extent.height = rendererObject->height;
renderPassBegin.clearValueCount = 2;
renderPassBegin.pClearValues = clearValues;

//Start recording the render pass instance
vkCmdBeginRenderPass(*cmdDraw, &renderPassBegin, VK_SUBPASS_CONTENTS_INLINE);

//Bind the command buffer with the pipeline
vkCmdBindPipeline(*cmdDraw, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);

//Bind descriptor sets
vkCmdBindDescriptorSets(*cmdDraw, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout,0, 1,
                        descriptorSets.data(),0,nullptr);

//Bind vertex data to the command buffer
const VkDeviceSize offsets[1] = {0};
vkCmdBindVertexBuffers(*cmdDraw, 0, 1, &VertexBuffer.buffer, offsets);

//Define the dynamic viewport
initViewports(cmdDraw);

//Define the scissoring also
initScissors(cmdDraw);

//Draw
vkCmdDraw(*cmdDraw, verticeAmount, 1,0,0);
//vkCmdDrawIndexed(*cmdDraw, indiceAmount, 1,0,0,0);

//End render pass instance recording
vkCmdEndRenderPass(*cmdDraw);

}

感谢您的帮助。如果您有任何其他信息,请告知我们。

0 个答案:

没有答案