Unreal Engine 中有什么可能阻止 glGetTexImage?

What could be blocking glGetTexImage in Unreal Engine?

这个问题有点抽象,但我在这里很困惑,所以我想问一下。

上下文

我正在使用 OpenGL 从模拟器渲染内容,然后我从 GPU 内存读取帧缓冲区并将其写入 CPU。当我使用 glGetTexImage 从 GPU 内存读取帧缓冲区时,我遇到了这个问题。 Here is the code如果你真的想深入,有问题。

问题

某些东西阻止了我在 Unreal Engine 中对 glGetTexImage 的调用(将纹理从 gpu 内存复制到 cpu 内存)。我使用的渲染器和线程与 Unreal Engine 使用的不同,所以我认为它不会冲突。我认为这与引擎如何与渲染线程同步有关。我在下面有一些证据。

证据与理论

y 轴是每次调用所花费的时间(以毫秒为单位),x 轴是实时的。绿图是我对glGetTexImage的呼唤。蓝线是游戏线程处理一帧所花费的时间,红线是渲染线程处理一帧所花费的时间。在此示例中,我完全受制于 GPU,根据分析器(未显示),游戏线程只是为了渲染线程而停止。根据图表,看起来 glGetTexImage 停滞了,直到渲染了大约 一个或两个帧 。我知道 Unreal Engines documentation 中说

In Unreal Engine 4 (UE4), the entire renderer operates in its own thread that is a frame or two behind the game thread.

任何指导都会有所帮助

我真的不希望任何人知道这里到底出了什么问题,如果您有任何想法或建议,我将很高兴听到。我不知道在 Unreal Engine 渲染一两帧之前停止调用 glGetTexImage 的机制在起作用。这两个渲染器在它们的操作中是完全互斥的,我真的不确定一个如何影响另一个的操作。根据我的图形驱动程序的工作方式或其他原因,这可能是一种副作用。我尝试将 DirectX11 和 Vulkan 用于 Unreal Engine 渲染器,它们都会导致同样的问题。如果有人对正在发生的事情有任何想法,或者知道任何好的调试工具可以诊断出是什么阻止了调用,我将非常感激。

任何采用指向客户端内存的指针的 OpenGL 函数必须在将控制权返回给您的 CPU 之前完成对该指针的访问。因此,当您在已渲染的图像上调用 glGetTexImage 时,GPU 必须完整地结束渲染过程,然后将渲染数据复制到您的内存中。

尽管您有不同的线程向 GPU 发送工作,但 GPU 本身在任何特定时间可能只能执行一组工作。因此,它可能会在它认为合适的时候交错执行工作,来自一个来源的工作的竞争可能不得不等待另一个来源的工作完成。

因此,如果 UE 和您自己向 GPU 发出一些渲染命令,则 UE 工作可能先到达那里。这意味着当您等待工作完成时,您也在也在等待 UE 工作完成。

而且即使 GPU 允许同时完成多个工作队列,UE 的工作仍然会从您的工作中消耗一些 GPU 资源。它将使用您的工作可能使用过的着色器执行单元和 ROP。

简而言之,如果 glGetTexImage 调用 没有 受到 UE 工作的影响,我会更惊讶。

如果您需要避免停止 CPU 线程,则需要从渲染目标执行异步读取。这意味着执行 pixel transfer into a buffer object, then waiting until the transfer is done by checking a fence sync object,并且只有在所有这些之后,才从缓冲区读取数据。