OpenGL:着色器存储缓冲区映射/绑定

香味

我目前正在开发一个程序,该程序支持与深度无关(也称为与顺序无关)的alpha混合为此,我实现了一个按像素的链接列表,使用标题的纹理(每个像素指向链接列表中第一个条目的点)和纹理缓冲区对象作为链接列表本身。虽然这可以正常工作,但我还是想与着色器存储缓冲区交换纹理缓冲区对象

我想我差不多了,但是花了大约一个星期的时间,我才能真正使用着色器存储缓冲区。我的问题是:

  • 为什么我不能映射着色器存储缓冲区?

  • 为什么再次绑定着色器存储缓冲区是一个问题?

为了进行调试,我只显示着色器存储缓冲区的内容(尚不包含链接列表)。我通过以下方式创建了着色器存储缓冲区:

glm::vec4* bufferData = new glm::vec4[windowOptions.width * windowOptions.height];
glm::vec4* readBufferData = new glm::vec4[windowOptions.width * windowOptions.height];

for(unsigned int y = 0; y < windowOptions.height; ++y)
{
    for(unsigned int x = 0; x < windowOptions.width; ++x)
    {
        // Set the whole buffer to red
        bufferData[x + y * windowOptions.width] = glm::vec4(1,0,0,1);
    }
}

GLuint ssb;
// Get a handle
glGenBuffers(1, &ssb);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssb);
// Create buffer
glBufferData(GL_SHADER_STORAGE_BUFFER, windowOptions.width * windowOptions.height * sizeof(glm::vec4), bufferData, GL_DYNAMIC_COPY);
// Now bind the buffer to the shader
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssb);

在着色器中,着色器存储缓冲区定义为:

layout (std430, binding = 0) buffer BufferObject
{
    vec4 points[];
};

在渲染循环中,我执行以下操作:

glUseProgram(defaultProgram);

for(unsigned int y = 0; y < windowOptions.height; ++y)
{
    for(unsigned int x = 0; x < windowOptions.width; ++x)
    {
        // Create a green/red color gradient
        bufferData[x + y * windowOptions.width] =
            glm::vec4((float)x / (float)windowOptions.width,
            (float)y / (float)windowOptions.height, 0.0f, 1.0f);
    }
}

glMemoryBarrier(GL_ALL_BARRIER_BITS);  // Don't know if this is necessary, just a precaution
glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, windowOptions.width * windowOptions.height * sizeof(glm::vec4), bufferData);
// Retrieving the buffer also works fine
// glMemoryBarrier(GL_ALL_BARRIER_BITS);
// glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, windowOptions.width * windowOptions.height * sizeof(glm::vec4), readBufferData);

glMemoryBarrier(GL_ALL_BARRIER_BITS);  // Don't know if this is necessary, just a precaution

// Draw a quad which fills the screen
// ...

这段代码有效,但是当我用以下代码替换glBufferSubData时,

glm::vec4* p = (glm::vec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, windowOptions.width * windowOptions.height, GL_WRITE_ONLY);
for(unsigned int x = 0; x < windowOptions.width; ++x)
{
    for(unsigned int y = 0; y < windowOptions.height; ++y)
    {
        p[x + y * windowOptions.width] = glm::vec4(0,1,0,1);
    }
}
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);

映射失败,返回GL_INVALID_OPERATION似乎着色器存储缓冲区仍绑定到某些对象,因此无法进行映射。我读了一些有关glGetProgramResourceIndexhttp://www.opengl.org/wiki/GlGetProgramResourceIndex)和glShaderStorageBlockBindinghttp://www.opengl.org/wiki/GlShaderStorageBlockBinding)的书,但我确实不了解。

我的第二个问题是,为什么我既不能打电话

glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssb);

,也不

glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssb);

glBufferSubDataglMemoryBarrier之后的渲染循环中此代码不应更改任何事情,因为这些调用与创建着色器存储缓冲区的过程相同。如果无法绑定不同的着色器存储缓冲区,则只能使用一个。但是我知道支持多个着色器存储缓冲区,所以我认为我还缺少其他内容(例如“释放”缓冲区)。

克里斯蒂安·劳

首先,glMapBufferRange失败是因为GL_WRITE_ONLY它不是有效的参数。那是旧的glMapBuffer,但是glMapBufferRange使用标志的集合来进行更细粒度的控制。在您的情况下,您需要GL_MAP_WRITE_BIT而且,由于您似乎完全覆盖了整个缓冲区,而无需关心先前的值,因此可能需要进行其他优化GL_MAP_INVALIDATE_BUFFER_BIT因此,将该调用替换为:

glm::vec4* p = (glm::vec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 
                    windowOptions.width * windowOptions.height, 
                    GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);

问题中没有很好地描述另一个错误。但是先解决此问题,也许它会帮助解决以下错误。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

着色器存储缓冲区对象:字节序?

来自分类Dev

不同大小的着色器存储缓冲区内容“转移”到阵列缓冲区

来自分类Dev

OpenGL计算着色器中的样本深度缓冲区

来自分类Dev

运行OpenGL着色器以修改现有的纹理/帧缓冲区

来自分类Dev

OpenGL 3.0:无法在着色器中使用帧缓冲区对象(黑色)

来自分类Dev

OpenGL 3.0:无法在着色器中使用帧缓冲区对象(黑色)

来自分类Dev

OpenGL-从顶点着色器访问缓冲区中的下3个顶点

来自分类Dev

有效清除着色器存储缓冲区

来自分类Dev

有效清除着色器存储缓冲区

来自分类Dev

从片段着色器访问深度缓冲区

来自分类Dev

无法从Compute着色器读取深度缓冲区

来自分类Dev

金属着色器在缓冲区中插入值

来自分类Dev

OpenGL计算着色器缓冲区分配失败

来自分类Dev

Vulkan - 读取缓冲区中浮点着色器颜色值到 uchar 值的奇怪映射

来自分类Dev

GLSL-使用部分着色器存储缓冲区作为计数器的正确性

来自分类Dev

GLSL-使用部分着色器存储缓冲区作为计数器的正确性

来自分类Dev

顶点着色器如何访问与另一个shaderprogram属性绑定的顶点缓冲区数据?

来自分类Dev

opengl:基于着色器的渲染到帧缓冲区,然后进行固定管线渲染

来自分类Dev

将结构发送到着色器存储缓冲区时,为什么会得到垃圾数据?

来自分类Dev

在两个单独的着色器程序之间共享混合和Z缓冲区?

来自分类Dev

我可以从Metal着色器获取缓冲区的大小吗?

来自分类Dev

threejs片段着色器,使用回收的帧缓冲区

来自分类Dev

用于着色器资源视图到深度模板缓冲区资源的哪种格式?

来自分类Dev

OSX +屏幕外渲染+ CoreGL +帧缓冲区+着色器=头痛吗?

来自分类Dev

打开gl计算着色器和帧缓冲区

来自分类Dev

如何使用动态缓冲区声明定义金属着色器?

来自分类Dev

具有来自shadertoy的多个缓冲区的端口着色器

来自分类Dev

在两个单独的着色器程序之间共享混合和Z缓冲区?

来自分类Dev

打开gl计算着色器和帧缓冲区

Related 相关文章

  1. 1

    着色器存储缓冲区对象:字节序?

  2. 2

    不同大小的着色器存储缓冲区内容“转移”到阵列缓冲区

  3. 3

    OpenGL计算着色器中的样本深度缓冲区

  4. 4

    运行OpenGL着色器以修改现有的纹理/帧缓冲区

  5. 5

    OpenGL 3.0:无法在着色器中使用帧缓冲区对象(黑色)

  6. 6

    OpenGL 3.0:无法在着色器中使用帧缓冲区对象(黑色)

  7. 7

    OpenGL-从顶点着色器访问缓冲区中的下3个顶点

  8. 8

    有效清除着色器存储缓冲区

  9. 9

    有效清除着色器存储缓冲区

  10. 10

    从片段着色器访问深度缓冲区

  11. 11

    无法从Compute着色器读取深度缓冲区

  12. 12

    金属着色器在缓冲区中插入值

  13. 13

    OpenGL计算着色器缓冲区分配失败

  14. 14

    Vulkan - 读取缓冲区中浮点着色器颜色值到 uchar 值的奇怪映射

  15. 15

    GLSL-使用部分着色器存储缓冲区作为计数器的正确性

  16. 16

    GLSL-使用部分着色器存储缓冲区作为计数器的正确性

  17. 17

    顶点着色器如何访问与另一个shaderprogram属性绑定的顶点缓冲区数据?

  18. 18

    opengl:基于着色器的渲染到帧缓冲区,然后进行固定管线渲染

  19. 19

    将结构发送到着色器存储缓冲区时,为什么会得到垃圾数据?

  20. 20

    在两个单独的着色器程序之间共享混合和Z缓冲区?

  21. 21

    我可以从Metal着色器获取缓冲区的大小吗?

  22. 22

    threejs片段着色器,使用回收的帧缓冲区

  23. 23

    用于着色器资源视图到深度模板缓冲区资源的哪种格式?

  24. 24

    OSX +屏幕外渲染+ CoreGL +帧缓冲区+着色器=头痛吗?

  25. 25

    打开gl计算着色器和帧缓冲区

  26. 26

    如何使用动态缓冲区声明定义金属着色器?

  27. 27

    具有来自shadertoy的多个缓冲区的端口着色器

  28. 28

    在两个单独的着色器程序之间共享混合和Z缓冲区?

  29. 29

    打开gl计算着色器和帧缓冲区

热门标签

归档