Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Opengl 我是否应该在统一缓冲区或着色器存储缓冲区对象内部使用“vec3”?_Opengl_Opengl Es_Glsl_Vulkan - Fatal编程技术网

Opengl 我是否应该在统一缓冲区或着色器存储缓冲区对象内部使用“vec3”?

Opengl 我是否应该在统一缓冲区或着色器存储缓冲区对象内部使用“vec3”?,opengl,opengl-es,glsl,vulkan,Opengl,Opengl Es,Glsl,Vulkan,vec3类型是一种非常好的类型。它只需要3个浮点数,我的数据只需要3个浮点数。我想在UBO和/或SSBO的结构中使用一个: layout(std140) uniform UBO { vec4 data1; vec3 data2; float data3; }; layout(std430) buffer SSBO { vec4 data1; vec3 data2; float data3; }; 然后,在我的C或C++代码中,我可以这样做来创建匹配的数据结构: str

vec3
类型是一种非常好的类型。它只需要3个浮点数,我的数据只需要3个浮点数。我想在UBO和/或SSBO的结构中使用一个:

layout(std140) uniform UBO
{
  vec4 data1;
  vec3 data2;
  float data3;
};

layout(std430) buffer SSBO
{
  vec4 data1;
  vec3 data2;
  float data3;
};

然后,在我的C或C++代码中,我可以这样做来创建匹配的数据结构:

struct UBO
{
  vector4 data1;
  vector3 data2;
  float data3;
};

struct SSBO
{
  vector4 data1;
  vector3 data2;
  float data3;
};
这是个好主意吗?不永远不要这样做

声明UBOs/SSBO时,假设所有3元素向量类型都不存在。这包括具有3行的列主矩阵或具有3列的行主矩阵。假设唯一的类型是标量、2和4元素向量(以及矩阵)。如果你这样做,你会省去很多悲伤

如果您想要vec3+浮点的效果,则应手动打包:

是的,您必须使用
data2and3.w
来获取其他值。处理它

如果您想要
vec3
s的数组,那么将它们设置为
vec4
s的数组。使用三元素向量的矩阵也是如此。只需从SSBO/UBO中删除整个3元素向量概念;从长远来看,你会过得更好

您应该避免使用vec3的原因有两个:

它不会像C/C++那样做

如果使用<代码> STD140版式,那么您可能需要定义与GLSL中定义匹配的C或C++数据结构。这使得两者很容易混合搭配。而std140的

layout至少可以在大多数情况下做到这一点。但是,在<>代码> VEC3 S.

时,它的布局规则与C和C++编译器的布局规则不符。

考虑下面的C++定义,用于<代码> VEC3类型:

struct vec3a { float a[3]; };
struct vec3f { float x, y, z; };
这两种类型都是完全合法的。这些类型的
sizeof
和布局将与
std140
要求的大小和布局匹配。但是它与
std140
强加的对齐行为不匹配

考虑这一点:

//GLSL
layout(std140) uniform Block
{
    vec3 a;
    vec3 b;
} block;

//C++
struct Block_a
{
    vec3a a;
    vec3a b;
};

struct Block_f
{
    vec3f a;
    vec3f b;
};
<>大多数C++编译器,<代码> sieOS/<代码>,<代码> Bubja A< /C>和 BuffixF将是24。这意味着
b
偏移量将为12

然而,在std140布局中,
vec3
始终与4个单词对齐。因此,
Block.b
的偏移量为16

现在,您可以尝试使用C++11的
alignas
功能(或C11类似的
\u alignas
功能)来解决这个问题:

如果编译器支持16字节对齐,这将起作用。或者至少在
Block\u a
Block\u f
的情况下,它可以工作

但在这种情况下它不起作用:

//GLSL
layout(std140) Block2
{
    vec3 a;
    float b;
} block2;

//C++
struct Block2_a
{
    vec3a_16 a;
    float b;
};

struct Block2_f
{
    vec3f_16 a;
    float b;
};
根据
std140
的规则,每个
vec3
必须从16字节边界开始。但是
vec3
不消耗16字节的存储空间;它只消耗12。由于
float
可以从4字节边界开始,因此
vec3
后跟
float
将占用16字节

但是C++对齐规则不允许这样的事情发生。如果类型与X字节边界对齐,则使用该类型将消耗X字节的倍数

因此,要匹配std140的布局,需要根据使用的确切位置选择类型。如果后跟一个
浮点
,则必须使用
vec3a
;如果后面跟的是超过4字节对齐的类型,则必须使用
vec3a_16

或者,您不能在着色器中使用
vec3
s,从而避免所有这些增加的复杂性

请注意,基于
alignas(8)
vec2
不会出现此问题。C/C++结构和数组也不会使用正确的对齐说明符(尽管较小类型的数组也有自己的问题)。此问题仅在使用裸
vec3
时发生

实现支持是模糊的 即使你做的每件事都是对的,但大家都知道,实现不正确地实现了
vec3
的古怪布局规则。一些实现有效地将C++对齐规则强加给GLSL。因此,如果使用<代码> VEC3<代码>,它会像C++那样对待一个16字节对齐的类型。在这些实现中,
vec3
后跟
float
将像
vec4
后跟
float
一样工作

是的,这是实施者的错。但是,由于无法修复实现,因此必须解决它。最合理的方法是完全避免使用
vec3


请注意,对于Vulkan(以及使用SPIR-V的OpenGL),SDK的GLSL编译器可以做到这一点,因此您不必为此担心。

好吧,我最近对其进行了反向工程,至少
glslagvalidator
按照预期将其紧密打包在SPIR-V中(成员偏移量分别为0、16和28)。若只是关于对齐,那个么更好的例子是vec3跟随标量浮点。@NicolBolas,还有歧义(我想你们会知道的,因为我相信你们是关于它的GitHub问题的始作俑者)。在OGL规范中,它比VK更清楚(因为它至少定义了所使用的大多数术语),我认为“前一个成员消耗的基本机器单元”对于
vec3
,仍然意味着3nb(“对齐”不应该改变这一点,这不是这个词的意思)@AzP:std430的布局规则的唯一变化是标量和两个元素向量的数组和结构的基本对齐方式。它对
vec3
s没有任何改变,因为它们的基本对齐方式始终是
vec4
的对齐方式。读了这篇文章后,我学到了一件重要的事情:规范允许
float
在内存中紧跟
vec3
,因此它们总共占用16个字节。这似乎是
vec3
vec4
在对齐方面的主要(如果不是唯一)区别特征。即尺寸!=仅当向量的三个分量也不是数组时,才进行基本对齐
struct alignas(16) vec3a_16 { float a[3]; };
struct alignas(16) vec3f_16 { float x, y, z; };

struct Block_a
{
    vec3a_16 a;
    vec3a_16 b;
};

struct Block_f
{
    vec3f_16 a;
    vec3f_16 b;
};
//GLSL
layout(std140) Block2
{
    vec3 a;
    float b;
} block2;

//C++
struct Block2_a
{
    vec3a_16 a;
    float b;
};

struct Block2_f
{
    vec3f_16 a;
    float b;
};