首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SSBO与图像加载/存储的区别

SSBO与图像加载/存储的区别
EN

Stack Overflow用户
提问于 2013-10-27 17:16:09
回答 3查看 4K关注 0票数 7

“着色存储缓冲对象”(SSBO)与图像加载存储操作有什么区别?

什么时候应该使用一种而不是另一种?

它们都可以有原子操作,我假设它们都存储在相同类型的内存中。不管它们是否存储在同一类型的内存中,它们是否具有相同的性能特征?

编辑:最初的问题是SSBO和统一缓冲区对象之间的问题,它是在SSBO和Image存储之间提出的。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-10-28 23:33:06

着色器存储缓冲区对象和图像纹理之间的区别,以及为什么要使用它们的原因是,它们可以使用接口块。

图像只是纹理,这意味着数据结构中只有向量4。不仅仅是vec4,它还可以有其他格式,而且数据结构可以是一种数据类型中的许多种。

其中,SSBO是通用的。它们可以在一个接口块中使用int's、float's、vec3 3的数组的组合。

因此,SSBO比单纯的图像纹理更加灵活。

票数 9
EN

Stack Overflow用户

发布于 2013-10-27 17:19:07

Object,您的问题或多或少已经得到了明确的回答。上面写着:

SSBO非常类似于统一的缓冲区对象。着色存储块由接口块(GLSL)以几乎与均匀块相同的方式定义。存储SSBO的缓冲区对象绑定到SSBO绑定点,就像用于制服的缓冲区对象绑定到UBO绑定点一样。以此类推。 它们之间的主要区别是:

  1. SSBO可以大得多。最小所需UBO大小为16 on;最小所需SSBO大小为16 on,典型大小将按GPU内存大小的顺序排列。

  1. SSBO是可写的,甚至是原子性的;UBO是统一的​s。SSBO的读写使用不连贯的内存访问,因此它们需要适当的屏障,就像图像加载存储操作一样。

  1. SSBO可以具有无界存储,直到缓冲区范围界限;UBO必须具有特定的、固定的存储大小。这意味着在SSBO中可以有任意长度的数组。数组的实际大小,基于缓冲区绑定的范围,可以在运行时使用无界数组变量的长度​函数在着色器中查询。
票数 4
EN

Stack Overflow用户

发布于 2021-10-12 18:08:27

正如其他人所提到的,SSBO具有更大的存储空间,并且支持原子操作,公认的答案还提到,SSBO是泛型的,因为它们允许用户组合不同的类型。但就我个人而言,我只想指出,我认为这通常是不好的,在SSBO中使用接口块或结构并不总是理想的。下面是一个例子:

假设在C++中有这样一个结构:

代码语言:javascript
复制
struct Foo {
    glm::vec4 position;
    glm::vec4 velocity;
    glm::vec4 padding_and_range;  // range is a float padded to a vec4
};

它对应于glsl中的SSBO缓冲区:

代码语言:javascript
复制
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结构是复杂的(需要大量的填充)。除此之外,您通常需要在这样的循环中填充缓冲区数据:

代码语言:javascript
复制
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);

而不是简单地一次将数据写入其中,而是使用glNamedBufferDataglNamedBufferSubData

处理结构的一种更好的方法是将每个struct元素存储到一个单独的SSBO中,这样每个SSBO缓冲区数组都是紧密打包的,并且是同构的。尽管性能可能不会更好,但它有助于保持代码的整洁和可读性。Rarher比使用struct更需要使用:

代码语言:javascript
复制
layout(std430, binding = 0) buffer FooPosition {
  vec4 position[];
};

layout(std430, binding = 1) buffer FooVelocity {
  vec4 velocity[];
};

layout(std430, binding = 2) buffer FooRange {
  float range[];
};
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19620945

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档