gpt4 book ai didi

c++ - glClientWaitSync 不适用于 MacOS

转载 作者:太空宇宙 更新时间:2023-11-04 13:25:38 26 4
gpt4 key购买 nike

在我的渲染引擎中,我使用 glMapSubBuffer 以及孤立和栅栏实现了三重缓冲来更新着色器缓冲区。在 Windows 中一切正常,但当我在 Mac 上运行引擎时出现问题。当我调用 glClientWaitSync为了等待我的缓冲区空闲,它总是返回 GL_TIMEOUT_EXPIRED ,所以我无法更新我的缓冲区,引擎进入无限循环等待它们被释放。

我认为问题在于我如何实现三重缓冲,也因为我在使用它后并没有获得太多性能。

基本上我已经这样做了:

  1. 对于每个着色器,我检查它是否有缓冲区,如果有,我使用一个类来处理这些缓冲区的更新,这些缓冲区包含我在分析着色器时创建的 3 个缓冲区,并将 3 个栅栏设置为 0。 (每个缓冲区一个)
  2. 在我的渲染循环中,我为每个着色器设置数据,将模型分组以节省着色器切换,因此我使用每个着色器循环进行渲染。
  3. 然后,我为每个着色器调用一个绑定(bind)其缓冲区的函数,以便使用 Material 和模型的数据更新它们。我调用此函数传递一个索引,该索引指示要绑定(bind)着色器的 3 个缓冲区中的哪一个。该索引在主程序执行的每个绘图调用中更新。我用来绑定(bind)更新缓冲区的函数是函数 A(见下文)

  4. 更新缓冲区后,我使用 glDrawElementsInstanced(GL_TRIANGLES, mesh->GetFacesIndicesCount(), GL_UNSIGNED_INT, 0, _instances.size()); 绘制对象然后我为刚刚与下面给出的函数 B 一起使用的缓冲区创建栅栏

  5. 然后,对于刚刚使用的同一个着色器,可能会有更多数据,因此我重新执行第 3 点和第 4 步的步骤,直到着色器必须绘制的数据完成。

功能 A:

bool BindForUpdate(AUint bufferIndex)
{
if (!_created)
return false;

if(_fences[bufferIndex] != nullptr)
{
// This is the point where the rendering goes into infinite loop
unsinged int result = glClientWaitSync(_fences[bufferIndex], 0, BUFFERS_UPDATE_TIMEOUT);
while (result == GL_TIMEOUT_EXPIRED || result == GL_WAIT_FAILED)
result = glClientWaitSync(_fences[bufferIndex], 0, BUFFERS_UPDATE_TIMEOUT);

glDeleteSync(_fences[bufferIndex]);
}

glBindBufferBase(GL_UNIFORM_BUFFER, _bindingPoint, _ubos[bufferIndex]);

glBufferData(GL_UNIFORM_BUFFER, _bufferDataSize * _bufferLength, nullptr, GL_STREAM_DRAW);

_updateDataBuffer = (unsigned char*)glMapBufferRange(GL_UNIFORM_BUFFER, 0, _bufferDataSize, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT);

if (_updateDataBuffer == nullptr)
return false;
return true;
}

函数 B:

void SyncBuffers(unsinged int bufferIndex)
{
_fences[bufferIndex] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
}

我认为问题正是我进行三重缓冲的方式,因为我在同一个渲染周期中多次使用同一个缓冲区,因为每个渲染周期使用哪个缓冲区的索引改变一次,而不是每次我绑定(bind)着色器缓冲区。

我该如何解决这个问题?


我只是尝试在每次调用 glDrawElementsInstanced(GL_TRIANGLES, mesh->GetFacesIndicesCount(), GL_UNSIGNED_INT, 0, _instances.size()); 后更改缓冲区索引而不是每次渲染调用只更改一次,但仍然是同样的问题。


我尝试强制 OpenGL 在 glDrawElementsInstanced 之后释放缓冲区打电话glFlush它工作了很短的时间。我有 OS X 10.10,它与 glFlush 一起工作(仍然存在问题,因为有时 glFlush 在执行过程中会出现异常),但后来我更新到 OS X 10.11 和 glFlush每次都开始给出异常,导致程序崩溃。

而且,最重要的是,我认为这根本不是解决这个问题的正确方法。

最佳答案

您应该使用 GL_SYNC_FLUSH_COMMANDS_BIT 调用 glClientWaitSync(),至少在等待循环之前的第一次调用中。否则,GL 可能永远不会真正处理挂起的命令,等待将永远持续下去。

请注意,这可能比使用 glFlush 更有效。引自 OpenGL 4.5 core profile specification 的第 4.1.2 节:

if the SYNC_FLUSH_COMMANDS_BIT bit is set in flags, and sync is unsignaled when ClientWaitSync is called, then the equivalent of Flush will be performed before blocking on sync.

因此只有当栅栏还没有发出信号时才会发出同花顺。理想情况下,您将以实际等待同步的方式编写代码,这将是异常(exception),而不是规则。

关于c++ - glClientWaitSync 不适用于 MacOS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33473449/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com