gpt4 book ai didi

c++ - c++ 未指定结构布局时,为什么 glBufferData 可以为 UBO 和 SSBO 缓冲结构

转载 作者:太空狗 更新时间:2023-10-29 20:10:36 28 4
gpt4 key购买 nike

我正在浏览 this关于如何在 openGL 中使用统一缓冲区对象的页面,看到了以下结构:

struct shader_data_t
{
float camera_position[4];
float light_position[4];
float light_diffuse[4];
} shader_data;

被缓冲到一个 openGL 统一缓冲对象中使用

GLuint ubo = 0;
glGenBuffers(1, &ubo);
glBindBuffer(GL_UNIFORM_BUFFER, ubo);
glBufferData(GL_UNIFORM_BUFFER, sizeof(shader_data), &shader_data, GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);

并在着色器中用作

...
layout (std140) uniform shader_data
{
vec4 camera_position;
vec4 light_position;
vec4 light_diffuse;
};
...

但是,我不明白openGl是如何知道在glBufferData转换struct指针和void指针时如何将struct中的数据映射到uniforms的,这应该让openGL不知道struct的内存布局。 c++ 结构布局是实现定义的,虽然 UBO 的作者和其他用户用虚拟变量手动填充他们的 c++ 结构以匹配着色器中的标准化 std140 布局,是什么阻止了 c++ 编译器添加更多填充和破坏布局?在 C++ 标准中是否有一个强有力的保证不会插入更多的填充或者这是一个“实际可移植”的交易?

最佳答案

OpenGL 非常清楚地定义了std140 接口(interface) block 的字节布局。在 C++ 端,您所要做的就是提供符合该布局的数据。如果您可以定义一个编译器将与 std140 匹配的结构,那么就可以了。你是怎么做到的?

您必须了解编译器用于布局类型的规则。

C++11 定义了一个名为“standard layout types”的概念。如果您遵循某些规则,您的类型就是标准布局。现在,这对于确切了解它们在内存中的布局意义不大。 C++ 唯一告诉你关于布局的标准布局类型是忽略空基类(只要它保持标准布局)并且第一个 NSDM 将在类的最开头。也就是说,前面永远不会有填充。

标准说的另一件事是,相同访问类别的 NSDM 将按顺序分配,较晚的具有比较早的更大的偏移量。由于您不允许在标准布局类型中拥有不同访问类别的不同 NSDM,因此您可以依赖它们按指定顺序进行布局。

但仅此而已,就 C++ 标准而言。 [class.mem]/13 指出实现可以出于各种原因在成员之间添加填充。

然而,非正式地,“标准布局类型”的规则为您提供了一个很好的指南,让您知道何时不会添加此类填充。遵循标准布局规则,对于大多数系统,您可以假设您的类的布局将在所用类型的大小和对齐方式允许的情况下尽可能紧凑。

实现必须配合吗?不,但真的没有理由假设他们不会。最坏的情况是最坏的情况,您始终可以检查实现如何布局类型。

关于c++ - c++ 未指定结构布局时,为什么 glBufferData 可以为 UBO 和 SSBO 缓冲结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38428666/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com