向vulkan管道添加额外的UBO将停止所有几何图形渲染

问题描述 投票:1回答:1

我已经按照www.vulkan-tutorial.com的教程进行操作,我正在尝试将Uniform缓冲区分为2个单独的缓冲区,一个用于View和Projection,另一个用于Model。但是,我发现一旦在布局中添加了另一个缓冲区,即使我的着色器不使用它的内容,也不会渲染任何几何图形。我没有从验证层得到任何东西。

我发现,如果两个UBO是相同的缓冲区,则没有问题。但是,如果我将它们分配给不同的缓冲区,则屏幕上将不会显示任何内容。添加了描述符集生成代码。

这是我的布局生成代码。所有值均正确提交,绑定分别为0、1和2,这反映在着色器代码中。我目前甚至不使用着色器中缓冲区中的数据-因此,它与我实际放入缓冲区中的数据无关。

编辑:已在RenderDoc中打开。没有额外的缓冲区,我可以看到普通的VP缓冲区及其值。他们看起来不错。如果我添加了额外的缓冲区,它不会显示,但是第一个缓冲区的数据全为零。

描述符集布局生成:

    std::vector<VkDescriptorSetLayoutBinding> layoutBindings;

        /*
        newShader->features includes 3 "features", with bindings 0,1,2.
        They are - uniform buffer, uniform buffer, sampler
        vertex bit, vertex bit, fragment bit

        */

    for (auto a : newShader->features)
    {
        VkDescriptorSetLayoutBinding newBinding = {};
        newBinding.descriptorType = (VkDescriptorType)layoutBindingDescriptorType(a.featureType);
        newBinding.binding = a.binding;
        newBinding.stageFlags = (VkShaderStageFlags)layoutBindingStageFlag(a.stage);
        newBinding.descriptorCount = 1;
        newBinding.pImmutableSamplers = nullptr;

        layoutBindings.push_back(newBinding);
    }

    VkDescriptorSetLayoutCreateInfo layoutCreateInfo = {};

    layoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;

    layoutCreateInfo.bindingCount = static_cast<uint32_t>(layoutBindings.size());

    layoutCreateInfo.pBindings = layoutBindings.data();

描述符集生成:

//Create a list of layouts
    std::vector<VkDescriptorSetLayout> layouts(swapChainImages.size(), voa->shaderPipeline->shaderSetLayout);

    //Allocate room for the descriptors
    VkDescriptorSetAllocateInfo allocInfo = {};
    allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
    allocInfo.descriptorPool = voa->shaderPipeline->descriptorPool;
    allocInfo.descriptorSetCount = static_cast<uint32_t>(swapChainImages.size());
    allocInfo.pSetLayouts = layouts.data();

    voa->descriptorSets.resize(swapChainImages.size());

    if (vkAllocateDescriptorSets(vdi->device, &allocInfo, voa->descriptorSets.data()) != VK_SUCCESS) {
        throw std::runtime_error("failed to allocate descriptor sets!");
    }

    //For each set of commandBuffers (frames in flight +1)
    for (size_t i = 0; i < swapChainImages.size(); i++) {

        std::vector<VkWriteDescriptorSet> descriptorWrites;


        //Buffer Info construction
        for (auto a : voa->renderComponent->getMaterial()->shader->features)
        {
            //Create a new descriptor write
            uint32_t index = descriptorWrites.size();

            descriptorWrites.push_back({});

            descriptorWrites[index].dstBinding = a.binding;

            if (a.featureType == HE2_SHADER_FEATURE_TYPE_UNIFORM_BLOCK)
            {
                VkDescriptorBufferInfo bufferInfo = {};

                if (a.bufferSource == HE2_SHADER_BUFFER_SOURCE_VIEW_PROJECTION_BUFFER) 
                {
                    bufferInfo.buffer = viewProjectionBuffers[i];
                    bufferInfo.offset = 0;
                    bufferInfo.range = sizeof(ViewProjectionBuffer);
                }
                else if (a.bufferSource == HE2_SHADER_BUFFER_SOURCE_MODEL_BUFFER)
                {
                    bufferInfo.buffer = modelBuffers[i];
                    bufferInfo.offset = voa->ID * sizeof(ModelBuffer);
                    bufferInfo.range = sizeof(ModelBuffer);
                }

                //The following is the same for all Uniform buffers
                descriptorWrites[index].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
                descriptorWrites[index].dstSet = voa->descriptorSets[i];

                descriptorWrites[index].dstArrayElement = 0;
                descriptorWrites[index].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
                descriptorWrites[index].descriptorCount = 1;
                descriptorWrites[index].pBufferInfo = &bufferInfo;
            }
            else if (a.featureType == HE2_SHADER_FEATURE_TYPE_SAMPLER2D)
            {
                VulkanImageReference ref = VulkanTextures::images[a.imageHandle];

                VkDescriptorImageInfo imageInfo = {};
                imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
                imageInfo.imageView = ref.imageView;
                imageInfo.sampler = defaultSampler;

                descriptorWrites[index].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
                descriptorWrites[index].dstSet = voa->descriptorSets[i];

                descriptorWrites[index].dstArrayElement = 0;
                descriptorWrites[index].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
                descriptorWrites[index].descriptorCount = 1;
                descriptorWrites[index].pImageInfo = &imageInfo;
            }
            else
            {
                throw std::runtime_error("Unsupported feature type present in shader");
            }
        }

        vkUpdateDescriptorSets(vdi->device, static_cast<uint32_t>(descriptorWrites.size()), descriptorWrites.data(), 0, nullptr);
    }

编辑:这是描述符集绑定代码

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

    //Very temporary Render loop. Binds every frame, very clumsy
    for (int j = 0; j < max; j++)
    {

        VulkanObjectAttachment* voa = objectAttachments[j];
        VulkanModelAttachment* vma = voa->renderComponent->getModel()->getComponent<VulkanModelAttachment>();

        if (vma->indices == 0) continue;

        vkCmdBindPipeline(commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, voa->shaderPipeline->pipeline);

        VkBuffer vertexBuffers[] = { vma->vertexBuffer };
        VkDeviceSize offsets[] = { 0 };

        vkCmdBindVertexBuffers(commandBuffers[i], 0, 1, vertexBuffers, offsets);

        vkCmdBindIndexBuffer(commandBuffers[i], vma->indexBuffer, 0, VK_INDEX_TYPE_UINT32);

        vkCmdBindDescriptorSets(commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, voa->shaderPipeline->pipelineLayout, 0, 1, &voa->descriptorSets[i], 0, nullptr);


        vkCmdDrawIndexed(commandBuffers[i], static_cast<uint32_t>(vma->indices), 1, 0, 0, 0);
    }

    vkCmdEndRenderPass(commandBuffers[i]);

缓冲区更新代码:

    ViewProjectionBuffer ubo = {};

    ubo.view = HE2_Camera::main->getCameraMatrix();

    ubo.proj = HE2_Camera::main->getProjectionMatrix();

    ubo.proj[1][1] *= -1;

    ubo.model = a->object->getModelMatrix();

    void* data;

    vmaMapMemory(allocator, a->mvpAllocations[i], &data);
    memcpy(data, &ubo, sizeof(ubo));
    vmaUnmapMemory(allocator, a->mvpAllocations[i]);
}

std::vector<ModelBuffer> modelBuffersData;

for (VulkanObjectAttachment* voa : objectAttachments)
{
    ModelBuffer mb = {};
    mb.model = voa->object->getModelMatrix();

    modelBuffersData.push_back(mb);


void* data; 
vmaMapMemory(allocator, modelBuffersAllocation[i], &data);
memcpy(data, &modelBuffersData, sizeof(ModelBuffer) * modelBuffersData.size());
vmaUnmapMemory(allocator, modelBuffersAllocation[i]);
c++ graphics vulkan
1个回答
0
投票

在我看来,您在此处设置的偏移量导致VkWriteDescriptorSet读取溢出内存:

else if (a.bufferSource == HE2_SHADER_BUFFER_SOURCE_MODEL_BUFFER)
{
    bufferInfo.buffer = modelBuffers[i];
    bufferInfo.offset = voa->ID * sizeof(ModelBuffer);
    bufferInfo.range = sizeof(ModelBuffer);
}

如果您仅在每帧更新缓冲区的一部分,则将执行以下操作:

bufferInfo.buffer = mvpBuffer[i];
bufferInfo.offset = sizeof(mat4[]{viewMat, projMat});
bufferInfo.range = sizeof(modelMat);

如果将模型放置在另一个缓冲区中,您可能想为描述符集创建一个不同的绑定,并且模型数据的bufferInfo看起来像这样:

bufferInfo.buffer = modelBuffer[i];
bufferInfo.offset = 0;
bufferInfo.range = sizeof(modelMat);
© www.soinside.com 2019 - 2024. All rights reserved.