C++ 布局说明符标量在EXT\u scalar\u block\u布局中有什么用途? 问题:
当访问GL\U EXT\U scalar\U block\U布局中的存储缓冲区时,C++ 布局说明符标量在EXT\u scalar\u block\u布局中有什么用途? 问题:,c++,glsl,vulkan,C++,Glsl,Vulkan,当访问GL\U EXT\U scalar\U block\U布局中的存储缓冲区时,scalar布局说明符有什么用途?(例如,见下文) 标量的用例是什么 背景 我最近使用Vulkan和NVidias VkRayTracing扩展编程了一个简单的光线跟踪器,并且正在跟踪。在关于最近命中着色器的部分中,需要访问存储在存储缓冲区中的一些数据(使用标志vk::BufferUsageFlagBits::eStorageBuffer) 在着色器中,使用扩展名GL\u EXT\u scalar\u block\
scalar
布局说明符有什么用途?(例如,见下文)
标量的用例是什么
背景
我最近使用Vulkan和NVidias VkRayTracing扩展编程了一个简单的光线跟踪器,并且正在跟踪。在关于最近命中着色器的部分中,需要访问存储在存储缓冲区中的一些数据(使用标志vk::BufferUsageFlagBits::eStorageBuffer
)
在着色器中,使用扩展名GL\u EXT\u scalar\u block\u layout
,这些缓冲区的访问方式如下:
layout(binding = 4, set = 1, scalar) buffer Vertices { Vertex v[]; } vertices[];
当我第一次使用这段代码时,验证层告诉我像Vertex
这样的结构有一个无效的布局,所以我更改了它们,使每个成员在16字节块上对齐:
struct Vertex {
vec4 position;
vec4 normal;
vec4 texCoord;
};
使用C++中相应的结构:
#pragma pack(push, 1)
struct Vertex {
glm::vec4 position_1unused;
glm::vec4 normal_1unused;
glm::vec4 texCoord_2unused;
};
#pragma pack(pop)
错误消失了,我得到了一个工作的光线跟踪器。但是我仍然不明白为什么这里使用scalar
关键字。我发现在谈论GL\u EXT\u scalar\u block\u布局扩展,但我真的不明白。也许我只是不习惯glsl术语?我看不出我为什么要用这个
此外,我刚刚尝试删除标量,它仍然工作,没有任何区别、警告或错误。如果您对此主题有任何澄清或进一步的资料,我们将不胜感激。std140和
std430
布局对对象的偏移/对齐大小进行了大量舍入std140
基本上使任何非标量类型与vec4
对齐std430稍微放松了这一点,但它仍然会对vec4
的对齐方式进行大量的取整
scalar
layout基本上是指按照对象的组件标量布局对象。聚合组件(向量、矩阵、数组和struct
s)的任何内容都不会影响布局。特别是:
所有类型的大小/对齐方式都仅限于它们实际使用的标量组件的最高对齐方式。因此,包含单个uint
的结构的大小/对齐方式与uint
的大小/对齐方式相同:4字节。在std140规则下,它的大小和对齐方式为16字节
注意,这种布局,因为C和C++将能够创建映射规则,这些规则映射到GLSL。
。
数组中元素的数组步长仅基于元素类型的大小/对齐方式(递归)。因此,uint
的数组具有4字节的数组跨距;在std140
规则下
对齐和填充只对标量起作用。如果在std140/430
中有一个包含uint
后跟uvec2
的结构,这将需要16个字节,在第一个uint
之后有4个字节的填充。在scalar
layout下,这样的结构只需要12个字节(与4个字节对齐),而uvec2
在概念上没有对齐。因此,只有当标量较小时才存在填充,如uint16
后跟uint
在您展示的特定案例中,scalar
布局是不必要的,因为您使用的所有类型都是vec4
s.非常感谢calrifies。然后我可能错过了vulkan设置中的其他部分,因为验证层抱怨Vector
的旧布局没有与16字节块对齐。但是,如果它是这样工作的,并且我理解为什么我很高兴:)在std430下,结构对齐不是等于它的任何成员的最大对齐吗?16字节的步幅是从哪里来的?