Opengl 在渲染和等待结果时切换帧缓冲区

Opengl 在渲染和等待结果时切换帧缓冲区,opengl,Opengl,我的问题是,我希望在渲染时切换帧缓冲区,并在切换回帧缓冲区时立即使用帧缓冲区。实际上,这会导致一个空的帧缓冲区,这并不是您可以想象的预期结果 在我发现要显示的帧缓冲区在开始渲染另一个帧缓冲区的帧缓冲区之前进行渲染是可行的之前,我已经使用了帧缓冲区 渲染路径不工作 渲染到FBO0 开始渲染到FBO1 切换回FBO0 将FBO1渲染为FB0 工作路径 渲染成FBO1 渲染为FBO0 将FBO1渲染为FBO0 因为它看起来像一个同步问题,我想知道如何防止这种情况?是否有任何命令可确保已完成对上

我的问题是,我希望在渲染时切换帧缓冲区,并在切换回帧缓冲区时立即使用帧缓冲区。实际上,这会导致一个空的帧缓冲区,这并不是您可以想象的预期结果

在我发现要显示的帧缓冲区在开始渲染另一个帧缓冲区的帧缓冲区之前进行渲染是可行的之前,我已经使用了帧缓冲区

渲染路径不工作
  • 渲染到FBO0
  • 开始渲染到FBO1
  • 切换回FBO0
  • 将FBO1渲染为FB0
工作路径
  • 渲染成FBO1
  • 渲染为FBO0
  • 将FBO1渲染为FBO0
因为它看起来像一个同步问题,我想知道如何防止这种情况?是否有任何命令可确保已完成对上一个renderbuffer的渲染?虽然它目前正在工作,但这并不是我所说的安全解决方案,因为我认为如果要呈现到FBO1中的内容越来越大,以后可能会出现同样的问题

代码 以下是开始渲染的代码:

GLFramebuffer.BindFramebuffer(FramebufferTarget.FRAMEBUFFER, _FramebufferHandle);
#if DEBUG
FramebufferStatus status = GLFramebuffer.CheckFramebufferStatus(FramebufferTarget.FRAMEBUFFER);
if (status != FramebufferStatus.FRAMEBUFFER_COMPLETE)
{
    GLFramebuffer.BindFramebuffer(FramebufferTarget.FRAMEBUFFER, FramebufferHandle.Default);
    throw new OpenGLException(GLFramebuffer.GetStatusString(status));
}
#endif
RenderStack.Push(Tuple.Create(this, attachments));
GL.Viewport(0, 0, Width, Height);
Tuple<Framebuffer, FramebufferAttachement[]> peeked;
if (RenderStack.Count == 0 || (peeked = RenderStack.Peek()).Item1 != this)
{
    if (RenderStack.Any(p => p.Item1 == this))
    {
        throw new InvalidOperationException("Framebuffer is not the top framebuffer, you must call 'StopRendering()' on all previous used buffers");
    }
    else throw new InvalidOperationException("Framebuffer is not in the rendering stack, please use 'StartRendering(...)' to use the current framebuffer");
}
AssertDisposed();

RenderStack.Pop();
if (RenderStack.Count == 0)
{
    GLFramebuffer.BindFramebuffer(FramebufferTarget.FRAMEBUFFER, FramebufferHandle.Default);
}
else
{
    Rebind(peeked);
}
以及停止渲染的代码:

GLFramebuffer.BindFramebuffer(FramebufferTarget.FRAMEBUFFER, _FramebufferHandle);
#if DEBUG
FramebufferStatus status = GLFramebuffer.CheckFramebufferStatus(FramebufferTarget.FRAMEBUFFER);
if (status != FramebufferStatus.FRAMEBUFFER_COMPLETE)
{
    GLFramebuffer.BindFramebuffer(FramebufferTarget.FRAMEBUFFER, FramebufferHandle.Default);
    throw new OpenGLException(GLFramebuffer.GetStatusString(status));
}
#endif
RenderStack.Push(Tuple.Create(this, attachments));
GL.Viewport(0, 0, Width, Height);
Tuple<Framebuffer, FramebufferAttachement[]> peeked;
if (RenderStack.Count == 0 || (peeked = RenderStack.Peek()).Item1 != this)
{
    if (RenderStack.Any(p => p.Item1 == this))
    {
        throw new InvalidOperationException("Framebuffer is not the top framebuffer, you must call 'StopRendering()' on all previous used buffers");
    }
    else throw new InvalidOperationException("Framebuffer is not in the rendering stack, please use 'StartRendering(...)' to use the current framebuffer");
}
AssertDisposed();

RenderStack.Pop();
if (RenderStack.Count == 0)
{
    GLFramebuffer.BindFramebuffer(FramebufferTarget.FRAMEBUFFER, FramebufferHandle.Default);
}
else
{
    Rebind(peeked);
}
这些方法只是包装好的,因此
GLFramebuffer.DrawBuffers
等于
glDrawBuffers

不工作的渲染路径

  • 渲染到FBO0
  • 开始渲染到FBO1
  • 切换回FBO0
  • 将FBO1渲染为FBO0
实际上应该可以工作,因为发出将FBO1内容呈现给FBO0的命令会在FBO0和FBO1上发生的操作上创建一个所谓的隐式同步点,以便在进一步合并其数据之前完成

要么您使用的OpenGL实现有一个bug,要么您做错了什么。我们需要看一些代码。

这个

不工作的渲染路径

  • 渲染到FBO0
  • 开始渲染到FBO1
  • 切换回FBO0
  • 将FBO1渲染为FBO0
实际上应该可以工作,因为发出将FBO1内容呈现给FBO0的命令会在FBO0和FBO1上发生的操作上创建一个所谓的隐式同步点,以便在进一步合并其数据之前完成

要么您使用的OpenGL实现有一个bug,要么您做错了什么。我们需要看一些代码。

这个

不工作的渲染路径

  • 渲染到FBO0
  • 开始渲染到FBO1
  • 切换回FBO0
  • 将FBO1渲染为FBO0
实际上应该可以工作,因为发出将FBO1内容呈现给FBO0的命令会在FBO0和FBO1上发生的操作上创建一个所谓的隐式同步点,以便在进一步合并其数据之前完成

要么您使用的OpenGL实现有一个bug,要么您做错了什么。我们需要看一些代码。

这个

不工作的渲染路径

  • 渲染到FBO0
  • 开始渲染到FBO1
  • 切换回FBO0
  • 将FBO1渲染为FBO0
实际上应该可以工作,因为发出将FBO1内容呈现给FBO0的命令会在FBO0和FBO1上发生的操作上创建一个所谓的隐式同步点,以便在进一步合并其数据之前完成


要么您使用的OpenGL实现有一个bug,要么您做错了什么。我们需要看一些代码。

关于“内存模型”的OpenGL Wiki建议您使用
glMemoryBarrier
来“在一个渲染命令和一些后续OpenGL操作之间建立可见性”,但我敢说这是胡说八道。使用FBO渲染到纹理在任何人想到像
glMemoryBarrier
这样的东西之前已经工作了几十年。您确定没有通过将“渲染到纹理”意外绑定到两个FBO来调用UB,并且确定没有使用错误的目标或其他东西吗?通常情况下,这必须正常工作,OpenGL会自动同步。“内存模型”上的OpenGL Wiki建议您使用
glMemoryBarrier
来“在一个渲染命令和后来的OpenGL操作之间建立可见性”,但我敢说这是胡说八道。使用FBO渲染到纹理在任何人想到像
glMemoryBarrier
这样的东西之前已经工作了几十年。您确定没有通过将“渲染到纹理”意外绑定到两个FBO来调用UB,并且确定没有使用错误的目标或其他东西吗?通常情况下,这必须正常工作,OpenGL会自动同步。“内存模型”上的OpenGL Wiki建议您使用
glMemoryBarrier
来“在一个渲染命令和后来的OpenGL操作之间建立可见性”,但我敢说这是胡说八道。使用FBO渲染到纹理在任何人想到像
glMemoryBarrier
这样的东西之前已经工作了几十年。您确定没有通过将“渲染到纹理”意外绑定到两个FBO来调用UB,并且确定没有使用错误的目标或其他东西吗?通常情况下,这必须正常工作,OpenGL会自动同步。“内存模型”上的OpenGL Wiki建议您使用
glMemoryBarrier
来“在一个渲染命令和后来的OpenGL操作之间建立可见性”,但我敢说这是胡说八道。使用FBO渲染到纹理在任何人想到像
glMemoryBarrier
这样的东西之前已经工作了几十年。您确定没有通过将“渲染到纹理”意外绑定到两个FBO来调用UB,并且确定没有使用错误的目标或其他东西吗?正常情况下,这必须正常工作,OpenGL会自动同步。@FelixK。您没有包括
RenderStack::Push
方法。但我的直觉告诉我,在将帧缓冲区推送和弹出到自定义渲染堆栈之间的某个地方