当前位置: 首页 > 知识库问答 >
问题:

Vulkan UBO传递错误

上官高逸
2023-03-14

我想将包含两个4x4矩阵的统一缓冲区对象传递给顶点着色器。我在C中声明了结构,如下所示:

struct PerRenderUBO
{
    glm::mat4 viewProjection;
    glm::mat4 projection; //unused
};

在GLSL中:

layout(std140, set = 0, binding = 0) uniform UBO {
    mat4 viewProjection;
    mat4 projection; //unused
} perRenderUBO;

但是,一旦我在UBO结构中声明了多个成员,一些对象就会由于错误的viewProjection矩阵而绘制错误。如果我注释掉PerRenderUBO结构和GLSL声明中的“projection”数据成员,所有内容都会正确渲染(尽管我甚至没有在着色器中使用投影)

这让我相信数据对齐肯定有问题。我已经用std140注释声明了布局。sizeof(PerRenderUBO)返回128。我试图将“投影”声明为float,但问题仍然存在。

以下是描述符集创建的最重要部分:

/** Create Layout **/
vk::DescriptorSetLayoutBinding perRenderUBOBinding;
perRenderUBOBinding.binding = 0;
perRenderUBOBinding.descriptorCount = 1;
perRenderUBOBinding.descriptorType = vk::DescriptorType::eUniformBuffer;
perRenderUBOBinding.stageFlags = vk::ShaderStageFlagBits::eVertex;
perRenderUBOBinding.pImmutableSamplers = nullptr;

std::vector<vk::DescriptorSetLayoutBinding> bindings{perRenderUBOBinding};

vk::DescriptorSetLayoutCreateInfo createInfo;
createInfo.bindingCount = bindings.size();
createInfo.pBindings = bindings.data();
this->perRenderUBOLayout = vkDevice->createDescriptorSetLayout(createInfo);

/** Create host-visible and host-coherent buffer **/
vk::BufferCreateInfo bufferCreateInfo;
bufferCreateInfo.size = sizeof(PerRenderUBO);
bufferCreateInfo.usage = vk::BufferUsageFlagBits::eUniformBuffer;
bufferCreateInfo.sharingMode = vk::SharingMode::eExclusive;
bufferCreateInfo.queueFamilyIndexCount = queueFamilyIndices.size();
bufferCreateInfo.pQueueFamilyIndices = queueFamilyIndices.data();
this->buffer = vkDevice->createBuffer(bufferCreateInfo);

vk::MemoryRequirements memoryRequirements = vkDevice->getBufferMemoryRequirements(this->buffer);
//allocates device memory as proposed in the specification (10.2 Device Memory)
this->bufferDeviceMemory = allocate(memoryRequirements, vk::MemoryPropertyFlags{vk::MemoryPropertyFlagBits::eHostVisible} | vk::MemoryPropertyFlags{vk::MemoryPropertyFlagBits::eHostCoherent});
vkDevice->bindBufferMemory(this->buffer, this->bufferDeviceMemory, 0);


this->descriptorPool = ...//create a descriptor pool for 1 uniform buffer
this->descriptorSet = ...//allocate descriptor set for above layout

vk::DescriptorBufferInfo bufferInfo;
bufferInfo.buffer = this->buffer;
bufferInfo.offset = 0;
bufferInfo.range = sizeof(PerRenderUBO);

vk::WriteDescriptorSet writeDescriptorSet;
writeDescriptorSet.dstSet = *this->descriptorSet;
writeDescriptorSet.dstBinding = 0;
writeDescriptorSet.dstArrayElement = 0;
writeDescriptorSet.descriptorType = vk::DescriptorType::eUniformBuffer;
writeDescriptorSet.descriptorCount = 1;
writeDescriptorSet.pBufferInfo = &bufferInfo;
writeDescriptorSet.pImageInfo = nullptr;
writeDescriptorSet.pTexelBufferView = nullptr;

vkDevice->updateDescriptorSets({writeDescriptorSet}, {});

在执行主draw命令buffer之前,我更新了PerRenderUBO的缓冲区,如下所示:

std::vector<PerRenderUBO> data; //contains 1 instance of PerRenderUBO
vk::DeviceSize offset = 0;
vk::DeviceSize size = data.size() * sizeof(PerRenderUBO);

void* memory = vkDevice->mapMemory(this->bufferDeviceMemory, offset, size);
std::memcpy(memory, data.data(), size);
this->deviceMemory->unmap();

我已经检查了好几次缓冲区大小和偏移量,一切看起来都很好。此外,由于每个绘图命令都绑定了相同的描述符集,并且一些对象渲染正确,我认为缓冲区中的数据本身必须正确。我错过了什么?

共有1个答案

闻人英韶
2023-03-14

一些对象绘制不正确,一些对象绘制正确,这可能表明同步或缓冲区未按时更新存在问题。

首先,您需要通知驱动程序主机更新了缓冲区的哪些部分。我没有看到这样的代码,你也没有提到任何相关内容。这是通过刷新内存来完成的——需要调用vkFlushMappedMemoryRanges()函数。

您可能还需要设置一个屏障,告知驾驶员缓冲区已被主机访问。但据我记忆所及,这种障碍是在命令缓冲区提交时隐式设置的。

 类似资料:
  • 这里变量x(在主)的值是6,这是正确的,但当我写同样的事情在system.out.println== 当我尝试在print语句中放入x时,它工作得很好。但我想知道它给出错误的原因。 错误:

  • 主要内容:1、值传递,2、引用传递,3、输出传递通过前面的学习我们知道,在调用带有参数的函数时,需要将参数传递给函数。在介绍这几种传递方式之前,我们先来介绍一下形式参数(形参)和实际参数(实参)这两个概念: 形式参数:在定义函数阶段参数列表中定义的参数称之为形式参数,简称形参,可以将它看作变量的名称,它没有具体的值,只是用来接收函数调用时传递过来的数据; 实际参数:在函数被调用时传递给函数的参数称之为实际参数,简称实参,可以将它看作变量的值,用

  • 我也在尝试使用node。js和firebase管理员向iOS设备发送推送通知。然而,我遇到了这个错误: 错误发送消息:{错误:请求包含一个无效的参数。在Firebase MessagingError。错误(本机)在Firebase MessagingError。Firebase Error[作为构造函数](/user_code/node_modules/fire base-admin/lib/ut

  • 我试着让我的相机为我的android应用程序工作,但我一直得到以下错误 02-07 22:30:48.217 131 97-13197/com.example.romsm.lap E/AndroidRuntime:致命异常:main java.lang.RuntimeException:将结果ResultInfo{who=null,request=1,result=-1,data=intent{a

  • 我认为这个问题可能是:我认为它崩溃是因为responseListener。如有任何帮助,我将不胜感激

  • 我正在尝试使用axios对我的react应用程序进行授权,该请求与postman一起工作,但当我开始react时,它会给我400个错误请求 控制台返回这个