c++ VULKAN -统一缓冲区(动态)-渲染冻结和应用程序崩溃

mec1mxoz  于 2023-06-25  发布在  其他
关注(0)|答案(1)|浏览(202)

我昨晚让动力制服缓冲器工作了。
在下面的代码中,我初始化一个动态偏移量,初始化设置投影/视图,然后在一个循环中,将动态偏移量设置为i * bufferSize,ubo的pvm矩阵,然后绑定描述符集并绘制。
这东西就像一个魅力与一个非常随机的魔术数字我尝试(21)。但如果我尝试22或更高,这东西只是冻结和崩溃。只是好奇,我的方法是不是不正确?如果我连21圈都走不完,我一定是漏掉了什么。我也有GTX 3060
context的bufferSize是uniformBufferObject结构的大小,它只有三个mat 4(64 * 3 = 192)。

uint32_t dynamicOffset = 0;

        glm::mat4 proj = glm::perspective(fov, (float)screenWidth / (float)screenHeight, zNear, zFar);
        proj[1][1] *= -1;
        glm::mat4 view = glm::lookAt(glm::vec3(0.0f, 0.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
            
        for (int i = 0; i < 21; i++)
        {
            dynamicOffset = bufferSize * i;

            // Update and draw the cube
            uniformBufferObject[i].proj = proj;
            uniformBufferObject[i].view = view;
            uniformBufferObject[i].model = glm::mat4(1.0f);
            uniformBufferObject[i].model = glm::translate(uniformBufferObject[i].model, glm::vec3(0.0f, 0.0f, -3.0f));
            uniformBufferObject[i].model = glm::rotate(uniformBufferObject[i].model, 0.0f, glm::vec3(1.0f, 1.0f, 1.0f));
            uniformBufferObject[i].model = glm::scale(uniformBufferObject[i].model, glm::vec3(0.45f));
            
            vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipelineLayout, 0, 1, &descriptorSet, 1, &dynamicOffset);
            vkCmdDraw(commandBuffer, static_cast<uint32_t>(vertices.size()), 1, 0, 0);
}

尝试使用动态UBO渲染数百个球体,但当我尝试访问uniformBufferObject[where index = bufferSize(192)* 21(4032)]时,应用程序崩溃。
统一缓冲区创建代码如下:

void createUniformBuffer()
    {
        createBuffer(bufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, uniformBuffer, uniformBufferMemory);
        
        vkMapMemory(device, uniformBufferMemory, 0, bufferSize, 0, &uniformBufferMapped);
        uniformBufferObject = static_cast<UniformBufferObject*>(uniformBufferMapped);
    }

创建缓冲区函数:

void createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory) 
    {
        VkBufferCreateInfo bufferInfo{};
        bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
        bufferInfo.size = size;
        bufferInfo.usage = usage;
        bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;

        vkCreateBuffer(device, &bufferInfo, nullptr, &buffer);

        VkMemoryRequirements memRequirements;
        vkGetBufferMemoryRequirements(device, buffer, &memRequirements);

        VkMemoryAllocateInfo allocInfo{};
        allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
        allocInfo.allocationSize = memRequirements.size;
        allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties);

        vkAllocateMemory(device, &allocInfo, nullptr, &bufferMemory);

        vkBindBufferMemory(device, buffer, bufferMemory, 0);
    }

findMemoryType函数:

uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties) {
        VkPhysicalDeviceMemoryProperties memProperties;
        vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProperties);

        for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) {
            if ((typeFilter & (1 << i)) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties) {
                return i;
            }
        }
    }

ubo struct,descriptorsetlayout,descriptorpool,descriptorwrite:

struct UniformBufferObject 
        {
          glm::mat4 model;
          glm::mat4 view;
          glm::mat4 proj;
        };

        VkDescriptorSetLayoutBinding uboLayoutBinding{};
        uboLayoutBinding.binding = 0;
        uboLayoutBinding.descriptorCount = 1;
        uboLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
        uboLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;

        std::array<VkDescriptorPoolSize, 2> poolSizes{};
        poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
        poolSizes[0].descriptorCount = static_cast<uint32_t>(1);
        poolSizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
        poolSizes[1].descriptorCount = static_cast<uint32_t>(1);

        descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
        descriptorWrites[0].dstSet = descriptorSet;
        descriptorWrites[0].dstBinding = 0;
        descriptorWrites[0].dstArrayElement = 0;
        descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
        descriptorWrites[0].descriptorCount = 1;
        descriptorWrites[0].pBufferInfo = &bufferInfo;
vxf3dgd4

vxf3dgd41#

createBuffer(bufferSize, ...
假设这是与填充结构的循环相同的bufferSize,则需要
createBuffer(bufferSize * <whatever number of draws you want active>, ...
你分配了一个192字节的缓冲区,它正好在一个页面的开头,所以你可以写缓冲区的结尾,直到你碰到页面的结尾,然后出错。

相关问题