7
\$\begingroup\$

In all of the code samples that I have looked at, the game loop looks something like this:

while(true)
{
   InputAndUpdate();
   Draw();

   SwapBuffers();
}

However doesn't this destroy parallelism between the CPU and the GPU? After the swap buffers call, the GPU will be sitting there idly while the CPU is handling input and updating. Then when the CPU has finished issuing draw commands, it waits until the GPU is finished rendering. Why isn't it done like this? :

while(true)
{
   Draw(); //First issue the draw commands
   InputAndUpdate(); //Update while the GPU is busy rendering

   SwapBuffers(); //Now block and wait for the GPU to finish
}
\$\endgroup\$
2
  • \$\begingroup\$ This is something I've never considered. +1 interesting question. \$\endgroup\$ May 22, 2011 at 12:05
  • \$\begingroup\$ The first one. If doing the second you increase the input lag by a full frame, possibly more depending on how you get input in the first place and V-sync. Always make sure not to increase the input lag \$\endgroup\$ May 22, 2011 at 14:23

2 Answers 2

5
\$\begingroup\$

This would be true unless you have an extra back buffer to render into (double-buffering). That allows the CPU to carry on and do stuff without having to wait for the actual buffer swap to occur (which would normally be the case as you couldn't start modifying the back buffer until it had been copied to the front buffer without risk of corrupting what you just rendered). When a draw call or swap is made, the request goes into a buffer of commands that the GPU can process, allowing the CPU to get on with doing other things while the GPU runs behind. This is how modern hardware gets parallelism. I believe D3D has a limit on just how many frames you can render ahead before a "Swap" will block (you'd need multiple back buffers to achieve this - also the more you buffer up the more latency you can potentially introduce between the input method and what is appearing on screen).

The concept of a game loop like either example above is quite dated. With the introduction of multiple processing units on the CPU you could potentially be doing rendering on one thread while doing some "update" work on one or more others. You might want to look into the concept of job queues to help maximise all the CPU processing power available.

\$\endgroup\$
-1
\$\begingroup\$

the solution you sied doesn't accualy make CPU and GPU to work parrarel, it just changes the order they are waiting for each other, since as the other answer implys draw always put it's results into a backbuffer and using swapbuffers you only change what is monitor shoing with the latest thing drawn, to take full potential of both CPU and GPU you have to call draw and update in two diffrent threads and use another second buffer for what CPU is doing (so that when CPu is generating update results in buffer 2 GPU read from Buffer 1 and when CPU is working with Buffer 1 GPu use Buffer 2 just like swap buffers GPU uses to prevent changes in frame already drawn)

\$\endgroup\$
6
  • \$\begingroup\$ @Gajet are you suggesting to double-buffer all game data on the cpu-side too? \$\endgroup\$ May 22, 2011 at 18:55
  • \$\begingroup\$ somthing like that, but not all data, only the thing that can move. so that both GPU&CPU read from CPUbuffer[0] and each do their calculations, and save their results in memory buffer/CPUBuffer[1], and when both their works finished they start reading from CPUBuffer[1] \$\endgroup\$
    – Ali1S232
    May 22, 2011 at 19:12
  • \$\begingroup\$ This is overkill, impractical and ends up in a messy code-base since the game entity will have normal and double-buffered properties relevant to rendering. There are much easier solutions for the communication from game-thread to the render-thread, like command queues. -1 for suggesting this \$\endgroup\$ May 22, 2011 at 19:42
  • \$\begingroup\$ agreed but i think it's the only way you can fully use the power of CPU and GPU simultaneously, command queues fir example won't work since every time CPU finnished a generating frame data it should give all it's data to GPU, and this means you have to wait CPU finishes working and then copy all the buffer at that time, keep in mind that nothing in the world should change while GPU is drawing the world, so if you use command queues there won't be any change in CPU and GPU waiting for each other. \$\endgroup\$
    – Ali1S232
    May 22, 2011 at 19:48
  • \$\begingroup\$ The fact that one waits for the other to finish does not mean that they don't run in parallel, they do, but the first one that finishes has to wait, since rendering and game-update must be synced. But they fully run in parallel. So the double-buffer suggestion solves a problem that is not there. \$\endgroup\$ May 22, 2011 at 20:18

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .