raysan5 / raylib

A simple and easy-to-use library to enjoy videogames programming
http://www.raylib.com
zlib License
21.81k stars 2.21k forks source link

[core] Low FPS even though DrawFPS says 60fps #958

Closed Guigui220D closed 5 years ago

Guigui220D commented 5 years ago

Please, before submitting a new issue verify and check:

Issue description

When trying some examples of raylib from the site, they all work well except sometimes the frames per second are weirdly low. It really depends on the example. For example the "3d camera_first_person" example from the site, with the 3d colored towers, works perfectly well with normal FPS, but when I remove the loop that draws all towers and only leave the walls and the ground it lags, although the fps counter says 60. The "friction" example really lags as well. I've not tried other examples. Removing the FPS limit makes it smoother but still visible lag spikes. Lowering the FPS limit makes the lagging worse.

Environment

Laptop with Windows 10 OpenGL 3.3 I7-8550U Intel with UHD Graphics 620

Code Example

/*******************************************************************************************
*
*   raylib [core] example - 3d camera first person
*
*   This example has been created using raylib 1.3 (www.raylib.com)
*   raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
*
*   Copyright (c) 2015 Ramon Santamaria (@raysan5)
*
********************************************************************************************/

#include "raylib.h"

#define MAX_COLUMNS 20

int main(void)
{
    // Initialization
    //--------------------------------------------------------------------------------------
    const int screenWidth = 800;
    const int screenHeight = 450;

    InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera first person");

    // Define the camera to look into our 3d world (position, target, up vector)
    Camera camera = { 0 };
    camera.position = (Vector3){ 4.0f, 2.0f, 4.0f };
    camera.target = (Vector3){ 0.0f, 1.8f, 0.0f };
    camera.up = (Vector3){ 0.0f, 1.0f, 0.0f };
    camera.fovy = 60.0f;
    camera.type = CAMERA_PERSPECTIVE;

    // Generates some random columns
    float heights[MAX_COLUMNS] = { 0.0f };
    Vector3 positions[MAX_COLUMNS] = { 0 };
    Color colors[MAX_COLUMNS] = { 0 };

    for (int i = 0; i < MAX_COLUMNS; i++)
    {
        heights[i] = (float)GetRandomValue(1, 12);
        positions[i] = (Vector3){ GetRandomValue(-15, 15), heights[i]/2, GetRandomValue(-15, 15) };
        colors[i] = (Color){ GetRandomValue(20, 255), GetRandomValue(10, 55), 30, 255 };
    }

    SetCameraMode(camera, CAMERA_FIRST_PERSON); // Set a first person camera mode

    SetTargetFPS(60);                           // Set our game to run at 60 frames-per-second
    //--------------------------------------------------------------------------------------

    // Main game loop
    while (!WindowShouldClose())                // Detect window close button or ESC key
    {
        // Update
        //----------------------------------------------------------------------------------
        UpdateCamera(&camera);                  // Update camera
        //----------------------------------------------------------------------------------

        // Draw
        //----------------------------------------------------------------------------------
        BeginDrawing();

            ClearBackground(RAYWHITE);

            BeginMode3D(camera);

                DrawPlane((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector2){ 32.0f, 32.0f }, LIGHTGRAY); // Draw ground
                DrawCube((Vector3){ -16.0f, 2.5f, 0.0f }, 1.0f, 5.0f, 32.0f, BLUE);     // Draw a blue wall
                DrawCube((Vector3){ 16.0f, 2.5f, 0.0f }, 1.0f, 5.0f, 32.0f, LIME);      // Draw a green wall
                DrawCube((Vector3){ 0.0f, 2.5f, 16.0f }, 32.0f, 5.0f, 1.0f, GOLD);      // Draw a yellow wall

                // Draw some cubes around
                for (int i = 0; i < MAX_COLUMNS; i++)
                {
                    DrawCube(positions[i], 2.0f, heights[i], 2.0f, colors[i]);
                    DrawCubeWires(positions[i], 2.0f, heights[i], 2.0f, MAROON);
                }

            EndMode3D();

            DrawRectangle( 10, 10, 220, 70, Fade(SKYBLUE, 0.5f));
            DrawRectangleLines( 10, 10, 220, 70, BLUE);

            DrawText("First person camera default controls:", 20, 20, 10, BLACK);
            DrawText("- Move with keys: W, A, S, D", 40, 40, 10, DARKGRAY);
            DrawText("- Mouse move to look around", 40, 60, 10, DARKGRAY);

        EndDrawing();
        //----------------------------------------------------------------------------------
    }

    // De-Initialization
    //--------------------------------------------------------------------------------------
    CloseWindow();        // Close window and OpenGL context
    //--------------------------------------------------------------------------------------

    return 0;
}

This is the example with the towers. It works normally with normal FPS, but when I comment out

// Draw some cubes around
for (int i = 0; i < MAX_COLUMNS; i++)
{
                    DrawCube(positions[i], 2.0f, heights[i], 2.0f, colors[i]);
                    DrawCubeWires(positions[i], 2.0f, heights[i], 2.0f, MAROON);
}

It becomes laggy. I addeda DrawFPS after all the DrawText.

Quantumplation commented 5 years ago

I'm experiencing the same thing, and am baffled: Doing less work / drawing less things, seems to create lag, even though FPS stays very close to 60.

Might be related to https://github.com/raysan5/raylib/issues/865

raysan5 commented 5 years ago

@Quantumplation As you noted, it could be related to system Sleep() mechanism, please, could you try recompiling raylib uncommenting SUPPORT_BUSY_WAIT_LOOP flag.

Guigui220D commented 5 years ago

It doesn't seem to have changed anything. I uncommented this line and did mingw32-make PLATFORM=PLATFORM_DESKTOP in src like it says here https://github.com/raysan5/raylib/wiki/Working-on-Windows, did I do right?

hbiblia commented 5 years ago

Hello

I have the same problem, it only happens when you are using OpenGL 3.x in an integrated video.

If you switch to a better video or use OpenGL2.x everything works fine.

Guigui220D commented 5 years ago

@hbiblia okay thank you! Thats all I needed to know

raysan5 commented 5 years ago

This issue seems related to video card drivers, specially with integrated video cards and devices including 2 video cards (nvidia + integrated). raylib seems to hit some slow path, managed by the driver... no easy solution... Closing by now.

Torantulino commented 4 years ago

This is still a major problem. Major lag at '60FPS', however upping the frame-rate to 240FPS results in smooth performance.

SolarLune commented 4 years ago

@Torantulino What's your hardware?

Torantulino commented 4 years ago

@SolarLune Laptop with: Geforce GTX 960M 7th Gen i5-7300HQ @ 2.5Ghz 8GB DDR4 RAM PCI-E Gen.3 SSD

pakeke-constructor commented 3 years ago

I am getting this as well, on a laptop.

Setting target fps of 60 yeilds about 5 FPS.

Here are my specs: GTX 1050ti + Intel UHD graphics 630 i7-8750h @ 2.2ghz 16gb ram

Edit: Intel UHD Graphics 630 is also running on my laptop. Thanks Jamesl for reminding me to mention this

jamesl-github commented 3 years ago

are you sure its using the 1050ti and not the GPU that's built into the CPU ?

TheRealMJP commented 2 years ago

Hello, I know this is closed and a bit old but I wanted to leave some info in case somebody else runs into this. I'm hitting what sounds like very similar behavior running on my Surface Pro 4, which just has an Intel Iris 540 integrated GPU. What seems to be happening is that the framerate of the app isn't actually low, it looks like the frame loop continues running at 60 fps and continues submitting frames through OpenGL without getting blocked. However it looks like the driver is not actually flushing commands to the GPU regularly, and instead does it every so often in irregular bursts:

image

Those blue vertical lines are the VSYNC happening every 16.6ms, and the peaks on the top bar when work actually gets enqueued on the GPU (the orange bar right below it is when DWM gets the flip request and composites the results for the window on the screen).

I believe this issue is specific to Intel's OpenGL driver. I can't reproduce this issue with a simple D3D11 application, however I can reproduce very similar behavior by modifying a basic OpenGL tutorial that I found.

I also think this is probably related to some kind of power management going awry. The issue seems to go away once the GPU load increases to a certain point, so I'm guessing the driver is trying to throttle things to keep power usage lower when there's not a lot going on.

I'll try to reach out to some Intel people after the holiday to see if this issue is something that has come up before.

raysan5 commented 2 years ago

@TheRealMJP Thank you very much for the detailed info!

TheRealMJP commented 2 years ago

This isn't really the greatest workaround, but I've found that at least for my game calling glFinish() right after EndDrawing() makes the problem go away. It does seem to increase CPU usage by a bit however.

seprab commented 2 years ago

Wow!!! @TheRealMJP I believe I'm facing the same issue as you on a similar machine. Surface 4 with Intel HD Graphics 520.

And the workaround also works for me!! Thank you so much.

dx2102 commented 2 years ago

@TheRealMJP THANKS! This works for my Surface Pro 4 too, and this issue doesn't happen on my desktop computer. Seems like this is an issue specific to this device. Maybe it's an INTEL driver issue. Bad luck...

I'm using Python and Pyray. The pause just simply got away after I added the "import OpenGL.GL as gl" and "gl.glFinish()" Python code.

jkaup commented 1 year ago

For anyone still running into the FPS drop issue after trying above workarounds, here's what turned out to be the case for me:

I would get 100+ FPS on a laptop with NVIDIA GeForce RTX 2070, using OpenGL 3.3.0 when the laptop was powered, but unplugging the laptop dropped the FPS to a fixed rate of 30 FPS.

It turned out this was due to the NVIDIA Battery Boost feature, which can be disabled from the Geforce Experience application under Settings -> Games -> Battery Boost -> Disable. After disabling, I would again get 100+ FPS even when unplugged.

Hope this helps someone scratching their heads with this issue, and glad to find out it was nothing to do with Raylib per se.

raysan5 commented 1 year ago

@jkaup thank you very much for the additional information! I'm sure it will be very useful for other users facing this issue!

chengts95 commented 9 months ago

I found a method to instruct the driver to utilize the high-performance GPU for running the application. Put this above the main function:

extern "C" {
  __declspec(dllexport) unsigned long NvOptimusEnablement = 0x00000001; 
}

AMD GPU drivers also have similar global variables.