首页 > 解决方案 > 在 Vulkan 中渲染时 0x69FD41DC (nvoglv32.dll) 出现未处理的异常

问题描述

我的代码在我绘制单个对象时有效,但是Unhandled exception at 0x69FD41DC (nvoglv32.dll) in program.exe: Fatal program exit requested.当我想在 vulkan 中绘制多个对象时,我有一个函数可以创建所有必要的二进制顶点数据并将其存储到 vertexBuffer 对象的向量中,然后在命令缓冲区中绑定每个该向量的顶点缓冲区成员并绘制我的对象。

主要功能如下:-

int main(int argc, char* argv[])
{
    windowClass window;
    enigma vulkanObject(window.windowHandler);
    vulkanObject.loadModel("model/Pig.gltf");      // load first object
    vulkanObject.loadModel("model/Duck.gltf");     // load second object
    vulkanObject.createDepthResources();
    vulkanObject.createRenderPass();
    vulkanObject.createGraphicsPipeline();
    vulkanObject.createFrameBuffer();
    vulkanObject.createCommandBuffers();
    vulkanObject.createSemaphores();


auto previousTime = std::chrono::high_resolution_clock::now();
float lag = 0.0f;
while (vulkanObject.running == true)
{
    auto currentTime = std::chrono::high_resolution_clock::now();
    auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(currentTime - previousTime).count() / 1000.0f;
    previousTime = currentTime;
    lag += elapsed;
    vulkanObject.handleEvents();

    while (lag >= MS_PER_FRAME)
    {
        vulkanObject.updateUniformBuffer(vulkanObject.view);
        lag -= MS_PER_FRAME;
    }
    vulkanObject.drawFrame();
}


return 0;
}

我的属性缓冲区类:

class attributeBuffer
{
public:
    attributeBuffer();
    ~attributeBuffer();

    VkBuffer vertex;
    VkBuffer normals;
    VkBuffer texCoord;
    VkBuffer index;

    VkDeviceMemory vertexMem;
    VkDeviceMemory normalMem;
    VkDeviceMemory texCoordMem;
    VkDeviceMemory indexMem;
};

在我的父类中,我为缓冲区类创建了一个向量,如下所示:

    std::vector<attributeBuffer> vertexBuffer;

我将所有数据存储到缓冲区的函数:

void enigma::loadModel(std::string file)
{   
    gltf stagingModel;

    stagingModel.loadAsset(file);              // Reads and parses gltf files
    model.push_back(std::move(stagingModel));
    matrix = matrix * stagingModel.scale;

for (int j = 0; j < stagingModel.mesh.size(); j++)
{
    vertexBuffer.push_back(attributeBuffer());    // appends a buffer object to the buffer vector




// the following code creates the required vertex attribute and buffers as well as the binding points


            for (int i = 0; i < 2; i++)
            {
                VkVertexInputAttributeDescription stagingAttrib = {};

                stagingAttrib.binding = i;
                stagingAttrib.location = i;

                stagingAttrib.format = VK_FORMAT_R32G32B32_SFLOAT;
                stagingAttrib.offset = 0;

                vertexAttributes.push_back(stagingAttrib);

                VkVertexInputBindingDescription bindingDescription = {};

                bindingDescription.binding = i;
                bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;

                if (i == 0)
                {
                    bindingDescription.stride = stagingModel.mesh[j].position.accessor.componentType * stagingModel.mesh[j].position.accessor.type;
                }
                else
                {
                    bindingDescription.stride = stagingModel.mesh[j].normal.accessor.componentType * stagingModel.mesh[j].normal.accessor.type;
                }

                vertexBinding.push_back(bindingDescription);
            }


            VkDeviceSize bufferSize = 0;
            VkDeviceSize bufferStart = 0;

            for (int i = 0; i < 2; i++)
            {
                if (i == 0)
                {
                    bufferSize = stagingModel.mesh[j].position.accessor.count * stagingModel.mesh[j].position.accessor.componentType * stagingModel.mesh[j].position.accessor.type;
                    bufferStart = stagingModel.mesh[j].position.accessor.accessorByteOffset + stagingModel.mesh[j].position.bufferView.byteOffset;

                    VkBuffer stagingBuffer;
                    VkDeviceMemory stagingBufferMemory;

                    createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingBuffer, stagingBufferMemory);

                    void * data;
                    std::vector<glm::vec3> stagingBin;
                    stagingBin.resize(stagingModel.mesh[j].position.getVec3Bin(stagingModel.bin).size());
                    stagingBin = stagingModel.mesh[j].position.getVec3Bin(stagingModel.bin);
                    vkMapMemory(device, stagingBufferMemory, 0, bufferSize, 0, &data);
                    memcpy(data, &stagingBin[0], (size_t)bufferSize);
                    vkUnmapMemory(device, stagingBufferMemory);

                    createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, vertexBuffer[j].vertex, vertexBuffer[j].vertexMem);
                    copyBuffer(stagingBuffer, vertexBuffer[j].vertex, bufferSize);
                }
                else if (i == 1)
                {
                    bufferSize = stagingModel.mesh[j].normal.accessor.count * stagingModel.mesh[j].normal.accessor.componentType * stagingModel.mesh[j].normal.accessor.type;
                    bufferStart = stagingModel.mesh[j].normal.accessor.accessorByteOffset + stagingModel.mesh[j].normal.bufferView.byteOffset;

                    VkBuffer stagingBuffer;
                    VkDeviceMemory stagingBufferMemory;

                    createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingBuffer, stagingBufferMemory);

                    void * data;
                    std::vector<glm::vec3> stagingBin;
                    stagingBin.resize(stagingModel.mesh[j].normal.getVec3Bin(stagingModel.bin).size());
                    stagingBin = stagingModel.mesh[j].normal.getVec3Bin(stagingModel.bin);
                    vkMapMemory(device, stagingBufferMemory, 0, bufferSize, 0, &data);
                    memcpy(data, &stagingBin[0], (size_t)bufferSize);
                    vkUnmapMemory(device, stagingBufferMemory);

                    createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, vertexBuffer[j].normals, vertexBuffer[j].normalMem);
                    copyBuffer(stagingBuffer, vertexBuffer[j].normals, bufferSize);
                }

            }

            if (stagingModel.mesh[j].indice.accessor.bufferViewIndex != -1)
            {

                VkBuffer stagingBuffer;
                VkDeviceMemory stagingBufferMemory;
                VkDeviceSize indexBufferSize = stagingModel.mesh[j].indice.accessor.count * stagingModel.mesh[j].indice.accessor.componentType;
                VkDeviceSize indexBufferByteOffset = stagingModel.mesh[j].indice.accessor.accessorByteOffset + stagingModel.mesh[j].indice.bufferView.byteOffset;

                createBuffer(indexBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingBuffer, stagingBufferMemory);

                void* data;
                vkMapMemory(device, stagingBufferMemory, 0, indexBufferSize, 0, &data);
                memcpy(data, &stagingModel.bin[indexBufferByteOffset], (size_t)indexBufferSize);
                vkUnmapMemory(device, stagingBufferMemory);

                createBuffer(indexBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, vertexBuffer[j].index, vertexBuffer[j].indexMem);

                copyBuffer(stagingBuffer, vertexBuffer[j].index, indexBufferSize);

                vkDestroyBuffer(device, stagingBuffer, nullptr);
                vkFreeMemory(device, stagingBufferMemory, nullptr);

            }

      }
}

我的命令缓冲区功能如下:

void enigma::createCommandBuffers()
{

commandBuffers.resize(swapChainFramebuffers.size());
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++)
{

    uint64_t vertexCount = 0;
    VkCommandBufferBeginInfo beginInfo = {};
    beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
    beginInfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
    beginInfo.pInheritanceInfo = nullptr;

    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, 0 };
    renderPassInfo.renderArea.extent = swapChainExtend;

    std::vector<VkClearValue> clearValues;
    clearValues.resize(2);
    clearValues[0].color = { 1.0f, 1.0f, 1.0f , 1.0f };
    clearValues[1].depthStencil = { 1.0f, 0 };

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

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

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

    VkDeviceSize offsets[] = { 0 };



// the following loop iterates through all objects and records their drawing commands//
    for (int x = 0; x < model.size(); x++)
    {
        for (int count = 0; count < model[x].mesh.size(); count++)
        {
            if (model[x].isInterleaved)
            {
                std::cout << "interleaved" << std::endl;
            }
            else
            {
                vkCmdBindVertexBuffers(commandBuffers[i], 0, 1, &vertexBuffer[count].vertex, offsets);
                vkCmdBindVertexBuffers(commandBuffers[i], 1, 1, &vertexBuffer[count].normals, offsets);

                if (model[x].mesh[count].indice.accessor.componentType == 2)
                {
                    vkCmdBindIndexBuffer(commandBuffers[i], vertexBuffer[count].index, 0, VK_INDEX_TYPE_UINT16);
                }
                else if (model[x].mesh[count].indice.accessor.componentType == 4)
                {
                    vkCmdBindIndexBuffer(commandBuffers[i], vertexBuffer[count].index, 0, VK_INDEX_TYPE_UINT32);
                }
            }

            VkDescriptorSet finalSet = descriptorSet[0];
            vkCmdBindDescriptorSets(commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &finalSet, 0, nullptr);
            vkCmdDrawIndexed(commandBuffers[i], static_cast<uint32_t>(model[x].mesh[count].indice.accessor.count), 1, 0, 0, 0);
        }
    }

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

    }
}

在我的绘图函数中抛出异常,该函数如下所示:

void enigma::drawFrame()
{
uint32_t imageIndex;
vkAcquireNextImageKHR(device, swapChain, std::numeric_limits<uint64_t>::max(), imageAvailableSemaphore, VK_NULL_HANDLE, &imageIndex);

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

VkSemaphore waitSemaphores[] = { imageAvailableSemaphore };
VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
submitInfo.waitSemaphoreCount = 1;
submitInfo.pWaitSemaphores = waitSemaphores;
submitInfo.pWaitDstStageMask = waitStages;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffers[imageIndex];

VkSemaphore signalSemaphores[] = { renderFinishedSemaphore };
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = signalSemaphores;

if (vkQueueSubmit(graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE) != VK_SUCCESS)
{
    throw std::runtime_error("failed to submit draw command buffers!");
}

VkPresentInfoKHR presentInfo = {};
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
presentInfo.waitSemaphoreCount = 1;
presentInfo.pWaitSemaphores = signalSemaphores;

VkSwapchainKHR swapChains[] = { swapChain };
presentInfo.swapchainCount = 1;
presentInfo.pSwapchains = swapChains;
presentInfo.pImageIndices = &imageIndex;
presentInfo.pResults = nullptr;


vkQueuePresentKHR(presentQueue, &presentInfo);  //the exception is thrown here
}

验证层输出:

validation Layer: Object: VK_NULL_HANDLE (Type = 0) | Duplicate vertex input binding descriptions for binding 0
validation Layer: Object: VK_NULL_HANDLE (Type = 0) | Duplicate vertex input binding descriptions for binding 1
validation Layer: Object: VK_NULL_HANDLE (Type = 0) | Duplicate vertex input binding descriptions for binding 0
validation Layer: Object: VK_NULL_HANDLE (Type = 0) | Duplicate vertex input binding descriptions for binding 1
validation Layer: Object: VK_NULL_HANDLE (Type = 0) | Duplicate vertex input binding descriptions for binding 0
validation Layer: Object: VK_NULL_HANDLE (Type = 0) | Duplicate vertex input binding descriptions for binding 1
validation Layer: Object: VK_NULL_HANDLE (Type = 0) | Duplicate vertex input binding descriptions for binding 0
validation Layer: Object: VK_NULL_HANDLE (Type = 0) | Duplicate vertex input binding descriptions for binding 1
validation Layer: Object: VK_NULL_HANDLE (Type = 0) | fragment shader writes to output location 1 with no matching attachment
validation Layer: Object: 0x58 (Type = 19) | OBJ[0x6f] : CREATE Pipeline object 0x58
validation Layer: Object: 0x59 (Type = 24) | OBJ[0x70] : CREATE Framebuffer object 0x59
validation Layer: Object: 0x5a (Type = 24) | OBJ[0x71] : CREATE Framebuffer object 0x5a
validation Layer: Object: 0x5b (Type = 24) | OBJ[0x72] : CREATE Framebuffer object 0x5b
validation Layer: Object: 0x9b997b8 (Type = 6) | OBJ[0x73] : CREATE VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT object 0x9b997b8
validation Layer: Object: 0x9b3b948 (Type = 6) | OBJ[0x74] : CREATE VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT object 0x9b3b948
validation Layer: Object: 0x9bb1d78 (Type = 6) | OBJ[0x75] : CREATE VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT object 0x9bb1d78
validation Layer: Object: 0x9b997b8 (Type = 6) | The Pipeline State Object (0x58) expects that this Command Buffer's vertex binding Index 2 should be set via vkCmdBindVertexBuffers. This is because VkVertexInputBindingDescription struct at index 10 of pVertexBindingDescriptions has a binding value of 2.
validation Layer: Object: 0x9b997b8 (Type = 6) | The Pipeline State Object (0x58) expects that this Command Buffer's vertex binding Index 2 should be set via vkCmdBindVertexBuffers. This is because VkVertexInputBindingDescription struct at index 10 of pVertexBindingDescriptions has a binding value of 2.
validation Layer: Object: 0x9b997b8 (Type = 6) | The Pipeline State Object (0x58) expects that this Command Buffer's vertex binding Index 2 should be set via vkCmdBindVertexBuffers. This is because VkVertexInputBindingDescription struct at index 10 of pVertexBindingDescriptions has a binding value of 2.
validation Layer: Object: 0x9b997b8 (Type = 6) | The Pipeline State Object (0x58) expects that this Command Buffer's vertex binding Index 2 should be set via vkCmdBindVertexBuffers. This is because VkVertexInputBindingDescription struct at index 10 of pVertexBindingDescriptions has a binding value of 2.
validation Layer: Object: 0x9b997b8 (Type = 6) | The Pipeline State Object (0x58) expects that this Command Buffer's vertex binding Index 2 should be set via vkCmdBindVertexBuffers. This is because VkVertexInputBindingDescription struct at index 10 of pVertexBindingDescriptions has a binding value of 2.
validation Layer: Object: 0x9b3b948 (Type = 6) | The Pipeline State Object (0x58) expects that this Command Buffer's vertex binding Index 2 should be set via vkCmdBindVertexBuffers. This is because VkVertexInputBindingDescription struct at index 10 of pVertexBindingDescriptions has a binding value of 2.
validation Layer: Object: 0x9b3b948 (Type = 6) | The Pipeline State Object (0x58) expects that this Command Buffer's vertex binding Index 2 should be set via vkCmdBindVertexBuffers. This is because VkVertexInputBindingDescription struct at index 10 of pVertexBindingDescriptions has a binding value of 2.
validation Layer: Object: 0x9b3b948 (Type = 6) | The Pipeline State Object (0x58) expects that this Command Buffer's vertex binding Index 2 should be set via vkCmdBindVertexBuffers. This is because VkVertexInputBindingDescription struct at index 10 of pVertexBindingDescriptions has a binding value of 2.
validation Layer: Object: 0x9b3b948 (Type = 6) | The Pipeline State Object (0x58) expects that this Command Buffer's vertex binding Index 2 should be set via vkCmdBindVertexBuffers. This is because VkVertexInputBindingDescription struct at index 10 of pVertexBindingDescriptions has a binding value of 2.
validation Layer: Object: 0x9b3b948 (Type = 6) | The Pipeline State Object (0x58) expects that this Command Buffer's vertex binding Index 2 should be set via vkCmdBindVertexBuffers. This is because VkVertexInputBindingDescription struct at index 10 of pVertexBindingDescriptions has a binding value of 2.
validation Layer: Object: 0x9bb1d78 (Type = 6) | The Pipeline State Object (0x58) expects that this Command Buffer's vertex binding Index 2 should be set via vkCmdBindVertexBuffers. This is because VkVertexInputBindingDescription struct at index 10 of pVertexBindingDescriptions has a binding value of 2.
validation Layer: Object: 0x9bb1d78 (Type = 6) | The Pipeline State Object (0x58) expects that this Command Buffer's vertex binding Index 2 should be set via vkCmdBindVertexBuffers. This is because VkVertexInputBindingDescription struct at index 10 of pVertexBindingDescriptions has a binding value of 2.
validation Layer: Object: 0x9bb1d78 (Type = 6) | The Pipeline State Object (0x58) expects that this Command Buffer's vertex binding Index 2 should be set via vkCmdBindVertexBuffers. This is because VkVertexInputBindingDescription struct at index 10 of pVertexBindingDescriptions has a binding value of 2.
validation Layer: Object: 0x9bb1d78 (Type = 6) | The Pipeline State Object (0x58) expects that this Command Buffer's vertex binding Index 2 should be set via vkCmdBindVertexBuffers. This is because VkVertexInputBindingDescription struct at index 10 of pVertexBindingDescriptions has a binding value of 2.
validation Layer: Object: 0x9bb1d78 (Type = 6) | The Pipeline State Object (0x58) expects that this Command Buffer's vertex binding Index 2 should be set via vkCmdBindVertexBuffers. This is because VkVertexInputBindingDescription struct at index 10 of pVertexBindingDescriptions has a binding value of 2.
validation Layer: Object: 0x5c (Type = 5) | OBJ[0x76] : CREATE Semaphore object 0x5c
validation Layer: Object: 0x5d (Type = 5) | OBJ[0x77] : CREATE Semaphore object 0x5d

标签: c++3dvulkanvertex-buffer

解决方案


推荐阅读