“着色存储缓冲对象”(SSBO)与图像加载存储操作有什么区别?
什么时候应该使用一种而不是另一种?
它们都可以有原子操作,我假设它们都存储在相同类型的内存中。不管它们是否存储在同一类型的内存中,它们是否具有相同的性能特征?
编辑:最初的问题是SSBO和统一缓冲区对象之间的问题,它是在SSBO和Image存储之间提出的。
发布于 2013-10-28 23:33:06
着色器存储缓冲区对象和图像纹理之间的区别,以及为什么要使用它们的原因是,它们可以使用接口块。
图像只是纹理,这意味着数据结构中只有向量4。不仅仅是vec4,它还可以有其他格式,而且数据结构可以是一种数据类型中的许多种。
其中,SSBO是通用的。它们可以在一个接口块中使用int's、float's、vec3 3的数组的组合。
因此,SSBO比单纯的图像纹理更加灵活。
发布于 2013-10-27 17:19:07
在Object,您的问题或多或少已经得到了明确的回答。上面写着:
SSBO非常类似于统一的缓冲区对象。着色存储块由接口块(GLSL)以几乎与均匀块相同的方式定义。存储SSBO的缓冲区对象绑定到SSBO绑定点,就像用于制服的缓冲区对象绑定到UBO绑定点一样。以此类推。 它们之间的主要区别是:
发布于 2021-10-12 18:08:27
正如其他人所提到的,SSBO具有更大的存储空间,并且支持原子操作,公认的答案还提到,SSBO是泛型的,因为它们允许用户组合不同的类型。但就我个人而言,我只想指出,我认为这通常是不好的,在SSBO中使用接口块或结构并不总是理想的。下面是一个例子:
假设在C++中有这样一个结构:
struct Foo {
glm::vec4 position;
glm::vec4 velocity;
glm::vec4 padding_and_range; // range is a float padded to a vec4
};它对应于glsl中的SSBO缓冲区:
struct Foo {
vec4 position;
vec4 velocity;
vec4 padding_and_range; // range is a float padded to a vec4
};
layout(std430, binding = 0) readonly buffer SSBO {
Foo data[];
} foo;尽管SSBO缓冲区能够容纳一个struct Foo数组,但请注意,必须按照std430内存布局考虑填充,您必须将float range填充到vec4,然后使用foo.data[i].padding_and_range.w访问它。这很容易出错,更别提内存空间的浪费了,特别是当你的SSBO很大(要在计算着色器中使用)和Foo结构是复杂的(需要大量的填充)。除此之外,您通常需要在这样的循环中填充缓冲区数据:
Foo* foos = reinterpret_cast<Foo*>(glMapNamedBufferRange(ssbo, offset, size, GL_MAP_READ_BIT));
for (int i = 0; i < n_foos; i++) {
Foo& foo = foos[i];
foo.position = glm::vec4(1.0f);
foo.velocity = glm::vec4(2.0f);
foo.padding_and_range = glm::vec4(glm::vec3(0.0f), 3.5f);
}
glUnmapNamedBuffer(ssbo);而不是简单地一次将数据写入其中,而是使用glNamedBufferData或glNamedBufferSubData。
处理结构的一种更好的方法是将每个struct元素存储到一个单独的SSBO中,这样每个SSBO缓冲区数组都是紧密打包的,并且是同构的。尽管性能可能不会更好,但它有助于保持代码的整洁和可读性。Rarher比使用struct更需要使用:
layout(std430, binding = 0) buffer FooPosition {
vec4 position[];
};
layout(std430, binding = 1) buffer FooVelocity {
vec4 velocity[];
};
layout(std430, binding = 2) buffer FooRange {
float range[];
};https://stackoverflow.com/questions/19620945
复制相似问题