本文介绍了当C ++未指定结构布局时,为什么glBufferData可以缓冲UBO和SSBO的结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在浏览页介绍了如何在openGL中使用统一缓冲区对象,并看到了以下结构:

I was browsing this page on how to use Uniform Buffer Objects in openGL and saw the following struct:

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

使用以下方法缓冲到openGL统一缓冲对象中

being buffered into an openGL Uniform Buffer Object using

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;
};
...

但是,当glBufferData转换struct指针和void指针时,我不明白openGl如何知道如何将struct中的数据映射到统一对象,这会使openGL不了解该struct的内存布局. c ++结构布局是由实现定义的,而UBO的作者和其他用户使用伪变量手动填充其c ++结构以匹配着色器中的标准std140布局,是什么阻止了c ++编译器增加更多的填充并破坏了布局?在c ++标准中是否有强有力的保证不会插入更多的填充,或者这是实际可移植的"交易?

However, I don't understand how openGl knows how to map the data in the struct to the uniforms when glBufferData converts the struct pointer and a void pointer, which should make openGL unaware of the memory layout of the struct. c++ struct layout is implementation defined, and while the author and other users of UBOs manually pad their c++ structures with dummy variables to match the standardized std140 layout in the shader, what prevents the c++ compiler from adding more padding and breaking the layout? is there a strong guarantee in the c++ standard that more padding will not be inserted or is this a "practically portable" deal?

推荐答案

OpenGL非常清楚地定义了std140接口块的字节布局.您在C ++方面要做的就是提供与该布局一致的数据.如果您可以定义一个编译器将与std140匹配的结构,那么您就可以了.你怎么做到的?

OpenGL defines, very clearly, what the byte layout of a std140 interface block is. All you have to do on the C++ side is provide data in accord with that layout. If you can define a struct that your compiler will match with std140, then you're fine. How do you do that?

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

You have to know the rules that your compiler uses to lay out types.

C ++ 11定义了一个概念,即"标准布局类型".如果遵循某些规则,则您的类型是标准布局.现在,这对于真正了解它们在内存中的布局并没有多大意义. C ++告诉您有关布局的标准布局类型的唯一内容是,将忽略空的基类(只要它保持标准布局),并且第一个NSDM将在该类的最开始.也就是说,前面永远不会有填充.

C++11 defines a concept called "standard layout types". If you follow certain rules, your types are standard layout. Now, this doesn't really mean much for knowing exactly how they are laid out in memory. The only things C++ tells you about standard layout types with regard to layout is that empty base classes are ignored (so long as it remains standard layout) and that the first NSDM will be at the very beginning of the class. That is, there will never be padding at the front.

该标准说的另一件事是,将按顺序分配相同访问类的NSDM,而较新的则具有更大的偏移量.而且由于不允许您在标准布局类型中使用具有不同访问级别的不同NSDM,因此您可以依靠它们以指定的顺序进行布局.

The other thing the standard says is that NSDMs of the same access class will be allocated in order, with later ones having larger offsets than earlier ones. And since you're not allowed to have different NSDMs of different access classes in standard layout types, you can rely on them being laid out in the order specified.

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

But that's it, as far as the C++ standard is concerned. [class.mem]/13 states that implementations can add padding between members for various reasons.

但是,非正式地,标准布局类型"的规则为您提供了一个很好的指南,以了解何时不添加此类填充 .遵循标准布局的规则,对于大多数系统,您可以假定您的类的布局将与所使用类型的大小和对齐方式紧密包装在一起.

Informally however, the rules of "standard layout types" give you a good guideline to know when such padding won't be added. Follow the rules of standard layout, and you can assume, for most systems, that your class's layout will be as tightly packed as the sizes and alignments of the types being used permit.

实现必须要一起玩吗?不.但是实际上没有理由假设他们不会.最糟糕的是,您总是可以检查一下实现如何布局类型.

Do implementations have to play along? No. But there's really no reason to assume that they won't. And worst comes to worst, you can always check to see how implementations lay types out.

这篇关于当C ++未指定结构布局时,为什么glBufferData可以缓冲UBO和SSBO的结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-23 06:36