WebGL反馈循环在帧缓冲和活动纹理之间形成。

4
我有一个WebGL项目,它使用两个渲染通道在纹理上创建效果。一切正常,直到最近Chrome开始抛出此错误:
[.WebGL-0000020DB7FB7E40] GL_INVALID_OPERATION: Feedback loop formed between Framebuffer and active Texture. 

尽管我没有更改代码,但这个问题刚刚开始出现,我猜测是由于新的更新引起的。
我在SO上找到了这个答案,其中指出错误“每当你从当前附加到帧缓冲区的纹理中读取时就会发生”。
然而,我已经检查了我的代码100次,我不认为我正在这样做。所以这是我设置的方式。
创建一个具有统一采样器的片段着色器。
uniform sampler2D sampler;

创建2个纹理

var texture0 = initTexture(); // This function does all the work to create a texture 
var texture1 = initTexture(); // This function does all the work to create a texture 

创建帧缓冲区。
var frameBuffer = gl.createFramebuffer();

然后我通过上传一个html图像到texture0并将texture0绑定到采样器来启动"2 pass processing"。

接下来,我绑定帧缓冲并调用 drawArrays:

gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture1, 0);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);

为了清理,我解除绑定帧缓冲:
gl.bindFramebuffer(gl.FRAMEBUFFER, null);

编辑:

在我的代码中添加断点后,我发现实际上只有当我绑定了空帧缓冲区时,错误才会被抛出。因此,drawArrays 调用并没有引起错误,而是在之后绑定空帧缓冲区时引起的。


您需要展示更多的代码,但是您所发布的代码很可能存在反馈循环。您最后创建的纹理是texture1,因此仍然绑定着它。将其附加到帧缓冲区上,然后进行绘制。如果您的着色器使用纹理,则看起来它正在尝试同时从texture1读取和写入。 - gman
也许我对它的工作方式有所误解,但是我的着色器只能从采样器中读取纹理。因此,如果将texture0绑定到采样器,我怎么可能读取texture1呢?我知道texture1仍然是活动纹理,我认为必须这样才能将其绑定到帧缓冲区。我应该在绑定后把它设置为“非活动”吗? - YAHsaves
@gman,另外请看我的编辑。不确定为什么,但似乎在绘制调用之后绑定空帧缓冲区是导致错误的原因。 - YAHsaves
我非常确定,这实际上是由于损坏的libANGLE实现所造成的绑定采样器追踪。 一旦将纹理绑定为采样器,即使在解除绑定后立即取消,浏览器也认为它正在被使用。 这个更改是在这个提交中实施的(https://chromium.googlesource.com/angle/angle/+/b1eb44bf8f33648b5194a71687cd087ec17cc990),还有其他几个修复程序; 最新的金丝雀版本似乎可以工作。 - Bartek Banachewicz
1
投票关闭。您还没有放置一个最小可重现示例。请添加一个。 - gman
我遇到了同样的问题,有人可以帮忙吗?我在CodePen上创建了一个链接:https://codepen.io/parthjasani/pen/yZdJWe?editors=1010 - Parth Jasani
1个回答

3

自从 Chrome 版本 83 开始,开始对帧缓冲和活动纹理反馈循环执行保守检查。这些检查可能过于保守,并影响了实际应该允许的使用情况。

在这些新检查中,Chrome 似乎禁止将渲染目标绑定到任何纹理槽,即使该槽没有被程序使用。

在进行两次渲染时,您可能已经做了以下操作:

  1. 初始化一个渲染目标并创建一个指向帧缓冲区的纹理。
  2. 渲染到渲染目标。

在第一步中,您可能会使用 gl.bindTexture(gl.TEXTURE_2D, yourTexture) 绑定纹理,然后在步骤 2 之前,需要使用 gl.bindTexture(gl.TEXTURE_2D, null) 解除绑定纹理。否则,Chrome 将失败,因为渲染目标被绑定为纹理,即使该纹理未被程序采样。


这只是Chrome中的一个明显的错误:https://bugs.chromium.org/p/angleproject/issues/detail?id=4638 希望他们很快能够修复。你可以绕过它,或者等几天再试。 - gman
@gman感谢您提供的漏洞报告链接。请问您知道修复程序何时会被推送到Chrome发布版本中吗?我们需要等待84版本吗?该漏洞影响我们的生产系统,但在我们的情况下,添加解决方法并不容易。 - Jan Wrobel
我不确定,但是同样的错误也影响了谷歌地图,所以我认为修复它可能是一个优先事项。 - gman
谢谢,这正是我遇到的问题。你的修复方法有效了,很高兴知道它将在未来版本的Chrome中得到修复。 - YAHsaves
似乎我的Firefox出现了一些“奇怪/新”的问题。通过明确指定READ_FRAMEBUFFER默认为DRAW来解决它。我认为,将默认帧缓冲区设置为绘制模式时,ANGEL会抱怨在同一对象上进行2次写入调用。 - nabr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接