Warm tip: This article is reproduced from serverfault.com, please click

What could be blocking glGetTexImage in Unreal Engine?

发布于 2020-12-04 18:20:33

This question is a bit abstract, but I am pretty stumped here so I figured I'd ask.

Context

I am using OpenGL to render content from an emulator and then I read the framebuffer from the GPU memory and write it to the CPU. The issue I'm having happens when I read the framebuffer from the GPU memory using glGetTexImage. Here is the code in question if you really want to go deep.

Problem

Something is blocking my call to glGetTexImage (copies a texture from gpu memory to cpu memory) in Unreal Engine. I am using a separate renderer and thread than Unreal Engine is using so I figure it wouldn't conflict. I think it has something to do with how the engine synchronizes with the rendering thread. I have some evidence below.

Evidence and Theory

The y-axis is the time each call takes in milliseconds and the x-axis is realtime. The green graph is my call to glGetTexImage. The Blue line is the time it takes the gamethread to process a frame and the redline is the time it takes the render thread to process a frame. In this example I'm totally GPU bound the game thread is just stalling for the render thread according to the profiler (not shown). Based on the graph it looks like glGetTexImage is stalled until about one or two frames are rendered. I know that in Unreal Engines documentation it says that

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

Profiling Data

Any guidance would be helpful

I don't really expect any one to know what's going wrong here exactly if you have any ideas though or advice I'd be greatful to hear it. I don't know what mechanism is in play that stops the call to glGetTexImage until Unreal Engine has rendered one or two frames. The two renderers are completely mutually exclusive in their operation I'm really not sure how one can effect the operation of another. It could be a side effect based on how my graphics driver works or something. I tried using DirectX11 and Vulkan for the Unreal Engine renderer and they both cause the same problem. If anyone has any ideas what's going on or knows of any good debugging tools that will diagnose what's blocking the call I'd really appreciate it.

Questioner
J. Rehbein
Viewed
0
Nicol Bolas 2020-12-05 02:32:38

Any OpenGL function which takes a pointer to client memory must be finished accessing that pointer before returning control to your CPU. So when you call glGetTexImage on an image you have rendered to, the GPU must conclude that rendering process in its entirety, then copy the rendered data into your memory.

Despite the fact that you have different threads sending work to the GPU, the GPU itself may only be able to do one set of work at any particular time. It therefore may interleave execution of work as it sees fit, and the competition of work from one source may have to wait for the completion of work from another source.

So if UE and yourself are throwing some rendering commands at the GPU, the UE work may have gotten there first. Which means that when you wait for your work to finish, you are also waiting for the UE work to finish.

And even if the GPU does allow for multiple queues of work to be completed simultaneously, UE's work is still going to consume some GPU resources from your work. It's going to be using shader execution units and ROPs that your work might have used.

In short, I would be more surprised if the glGetTexImage call wasn't affected by UE's work.

If you need to avoid stalling your CPU thread, then you need to do an asynchronous read from the render target. This means doing a pixel transfer into a buffer object, then waiting until the transfer is done by checking a fence sync object, and only after all of that, reading the data from the buffer.