2
\$\begingroup\$

Brief introduction: I'm programming a game and, till now, I've runned it on my desktop. This morning I decided to try it on my laptop (a i3-4005u with a gt920m) to see cpu/gpu usage and, with my surprise, it couldn't even reach 60 fps... then I discovered that it didn't use the nvidia gpu but the intel's integrated one. I looked a bit on Google and found the problem: https://stackoverflow.com/questions/10535950/forcing-nvidia-gpu-programmatically-in-optimus-laptops.

The usage of the GPU (the Nvidia one now) was still to high for such the game I'm making (kind of 2D platform). Trying it on my desktop (gtx 780) I discovered that it uses even 50% of its power (MSI Afterburner).

A screenshot:

game screenshot

To generate the light map I use a render-to-texture and here is the problem: rendering the lights uses all the power (profiled with visual studio). The only difference between rendering the lights and the background is the active RenderTargetView and the only different between the default back buffer and the light map RTV is the format so I changed it:

textureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; //it was DXGI_FORMAT_R32G32B32A32_FLOAT

After that the gpu usage dropped to 3-4% (and the game looks the same). Now I'm wondering why things changed. Can you help me?

Still now rendering the lights is the most expensive things and I can't understand why (the shader is simpler than the sprites' one. I can post the code if you want, but is a basic "load data from texture and output")

enter image description here

The first draw call is for lights, then there is the background's one. I really can't understand what's going on.

P.S I also found that using a borderless window instead of the fullscreen mode by default adds a 10% of usage on the gpu, while fullscreen mode uses all the cpu power (100% of usage). Can you help me again understanding why?

\$\endgroup\$
2
\$\begingroup\$

The answer to the first part is easy, R32G32B32A32_FLOAT is a massively expensive format to use for GPUs. It uses 128 bits per pixel compared to R8G8B8A8_UNORM which uses only 32. So by changing it you've quartered the amount of memory bandwidth required which will have a large positive effect on older GPUs.

Why fullscreen is slower could be several things. Is it definitely running in the same resolution? Are you using the same swapchain settings? Is vsync enabled? We really need a before & after GPU profile to get a better idea.

\$\endgroup\$
  • \$\begingroup\$ Thanks for the answer. So, in a game, which are the advantages of using that format? \$\endgroup\$ – Liuka Aug 23 '16 at 8:43
  • 1
    \$\begingroup\$ The advantage of the FLOAT formats are that they can store values greater than 1. So R16G16B16A16_FLOAT (64 bits) is commonly used for HDR rendering and is resolved on to R8G8B8A8_UNORM at the end of the scene rendering stage. R32G32B32A32_FLOAT is rarely used as it is slow, but some advanced graphical techniques that require high precision do use it. All this is for 3D high-end rendering. 2D games rarely have a reason to use anything other than R8G8B8A8_UNORM. \$\endgroup\$ – Muzza Aug 23 '16 at 8:47
  • \$\begingroup\$ For boderless and fullscreen I noticed that every program in fullscreen use all the cpu available so it's probably something I can't control (the only solution is to use Sleep after calling present(), so I think I'll go this way). Boderless high usage I think is because of syncing with the desktop refresh ratio, but I'm not sure. \$\endgroup\$ – Liuka Aug 23 '16 at 8:48
  • \$\begingroup\$ so is it better that I check that I'm using that format for all my textures? And best format for depth buffer(not using stencil right now)? \$\endgroup\$ – Liuka Aug 23 '16 at 8:52
  • \$\begingroup\$ Textures for 2D games would typically be R8G8B8A8_UNORM yes, although it's also common to use compressed formats like BC1/BC2/BC3. You'll get performance problems if you were trying to use R32G32B32A32_FLOAT textures. \$\endgroup\$ – Muzza Aug 23 '16 at 9:02
0
\$\begingroup\$

For the second part of the question I found the problem which causes the high time for the lights' draw call: I wasn't properly clearing the ShaderResourceView slot (actually I was doing it wrong) where the light map was bound, so when I set it as RendertargetView it took time to unbound it. Now everything's ok. Need just to call

ID3D11ShaderResourceView* null = 0;

_graphic->context()->PSSetShaderResources(_slot, 1, &null); //with _slot 1 and not 0... :)

Now draw time is about 140ns, nearly like background.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.