Opengl Can';使用gimage2D在GLSL计算着色器中访问fbo附加纹理

Opengl Can';使用gimage2D在GLSL计算着色器中访问fbo附加纹理,opengl,glsl,compute-shader,Opengl,Glsl,Compute Shader,我最近想为OpenGL开发一个计算着色器。在这个实验中,我想访问一个附加到FrameBufferObject的颜色纹理。尝试使用布局(rgba32f)readonly image2D将纹理传递到计算着色器时,未传入任何内容。我重写了计算着色器以使用取样器2D。采样器工作得很好 我还测试了gimage2D计算着色器,只使用了一个纹理,没有附加到任何东西。这也起到了预期的作用 我还没有找到任何文档说明在使用gimage2D的计算着色器中无法访问附加到FBO的纹理。我还没有找到任何文档说明计算着色器无

我最近想为OpenGL开发一个计算着色器。在这个实验中,我想访问一个附加到FrameBufferObject的颜色纹理。尝试使用布局(rgba32f)readonly image2D将纹理传递到计算着色器时,未传入任何内容。我重写了计算着色器以使用取样器2D。采样器工作得很好

我还测试了gimage2D计算着色器,只使用了一个纹理,没有附加到任何东西。这也起到了预期的作用

我还没有找到任何文档说明在使用gimage2D的计算着色器中无法访问附加到FBO的纹理。我还没有找到任何文档说明计算着色器无法写入FBO

我想我的问题是,为什么不能在计算着色器中使用gimage2D访问附加到FBO的纹理?是否有文件对此进行了解释?

首先,关于您的声明: “我想我的问题是,为什么不能在计算着色器中使用gimage2D访问附加到FBO的纹理?”

您不使用
gimage2D
,如果在GLSL文档中看到前缀为
g
的类型,则该类型是泛型类型。(例如,
gvec
gsampler…
,等等)这意味着函数对每种
vec
采样器…
都有重载。在这种情况下,
gimage2D
是表示“…此函数接受
image2D
iimage2D
uimage2D
”的简短方式

没有实际的
gimage2D
类型,发明
g
前缀仅仅是为了保持GLSL文档的简短和可读性;)

我想您已经知道了这一点,因为问题中列出的唯一实际代码是使用
image2D
,但我不确定编写的方式


至于你的实际问题,你应该调查一下。 请特别注意:
GL\u帧缓冲区\u屏障\u位

计算着色器与渲染管道的各个阶段分开调度;他们有自己的单级管道。这意味着,如果将某些内容绘制到FBO附件中,则计算机着色器可能会在开始绘制之前运行,或者计算着色器可能会使用数据的(无效)缓存视图,因为渲染管道中所做的更改对计算管道不可见。内存障碍将有助于同步两者之间共享的资源的渲染管道和计算管道

渲染管道有很多隐式同步和多级数据流,为着色器提供了非常简单的顺序(例如,
glDraw*
initiated vertex->geometry->fragment),但计算管道实际上消除了所有这些,而支持显式同步。在计算着色器和图像加载/存储时,你需要考虑各种各样的危害,而不是传统的顶点/几何/镶嵌/片段。 换句话说,在计算着色器中声明某种
连贯的
,同时在着色器级别声明适当的屏障将负责计算着色器调用之间的同步,由于计算管道与渲染管道是分开的,因此它不会在计算着色器和片段着色器之间同步图像加载/存储。为此,您需要
glMemoryBarrier(…)
命令级别同步对内存资源的访问
glDraw*(…)
(渲染管道的入口点)是一个独立于
glDispatch*(…)
(计算管道的入口点)的命令,您需要确保这些独立命令的顺序正确,以便图像加载/存储显示一致的行为

如果没有内存屏障,就无法保证命令的执行顺序;只是它们产生的结果与您发布它们的顺序一致。在为每个着色器阶段严格定义输入/输出的渲染管道中,GL实现可以智能地重新排列命令,同时相对轻松地维护此属性。通常,对于计算着色器以及图像加载/存储,I/O完全由运行时流决定,如果没有一些帮助(内存障碍),这是不可能的


TL;DR:如果您使用取样器而不是图像加载/存储,那么它工作的原因可以归结为一致性保证(或缺乏一致性保证)。图像加载/存储简单地不能保证从图像读取的内容与写入图像的内容一致(严格顺序),而是要求您显式同步对图像的访问。这实际上是有益的,因为它允许您同时读/写相同的图像,而不会导致未定义的行为,但这需要您付出额外的努力才能使其正常工作。

首先,关于您的陈述: “我想我的问题是,为什么不能在计算着色器中使用gimage2D访问附加到FBO的纹理?”

您不使用
gimage2D
,如果在GLSL文档中看到前缀为
g
的类型,则该类型是泛型类型。(例如,
gvec
gsampler…
,等等)这意味着函数对每种
vec
采样器…
都有重载。在这种情况下,
gimage2D
是表示“…此函数接受
image2D
iimage2D
uimage2D
”的简短方式

没有实际的
gimage2D
类型,发明
g
前缀仅仅是为了保持GLSL文档的简短和可读性;)

我想您已经知道了这一点,因为问题中列出的唯一实际代码是使用
image2D
,但我不确定编写的方式


至于你呢