Search code examples
c++sdl

SDL causes graphic freezes in entire computer


I'm using SDL 2.0.8 and SDL_image 2.0.3. I've written a small program which renders on screen 2 textures.

When I start the programme my computer is lagging so much that I can't close the programme window. I gave this programme to my friend and when he opened it, he got the same lag as me. We thought that something in my code is bad. We analyzed the code and we saw literally nothing wrong. Then I remembered that I wrote similar code last year and everything was running well. I downloaded it because I had it in the cloud and we ran it. This programme was also lagging. That was totally weird for us. Our graphics cards had 100% utilization because I didn't set framerate lock or vsync.

My computer:

  • AMD Ryzen 7 2700x @4.3GHz
  • AMD Radeon R9 390
  • 16 GB RAM DDR4 3000MHz

My friend's computer:

  • AMD Ryzen 7 1700 @3.6GHz
  • NVidia GTX 770
  • 16 GB RAM DDR4 3200MHz

I can add that commenting render function in loop removes lags.

EDIT:

It happens only when graphics card utilization is around 100%. Probably when the processor is too weak to run it so fast that graphics card is fully loaded, problem would not ocurr.

Here is code:

Main.cpp

#define _CRT_SECURE_NO_WARNINGS
#include "Client.h"

int main(int argc, char** argv)
{
    // Redict strerr to file
    freopen("ErrorFile.log", "w", stderr);
    Client * c = new Client();
    c->start(40);
    system("pause");
    return 0;
}

Client.h

#pragma once
#include "Graphics.h"
#include <time.h>

class Client
{
public:
    Client()
    {
        gptr = new Graphics();
    }
    ~Client()
    {
        delete gptr;
        gptr = NULL;
    }
    // -Triggers needed components and starts client
    void start(int tickrate)
    {
        gptr->init();
        loop(tickrate);
    }
private:
    void loop(int tickrate)
    {
        clock_t start;
        clock_t timer;
        start = clock();
        while (!quit)
        {
            timer = clock();
            while (start + tickrate <= timer)
            {
                //TODO Mechanics update
                start += tickrate;
            }
            while (SDL_PollEvent(&gptr->e) != 0)
            {
                if (gptr->e.type == SDL_QUIT)
                    quit = true;
            }
            gptr->render();
        }
    }
private:
    Graphics * gptr;
    bool quit = false;
};

Graphics.h

#pragma once
#include "Texture.h"

class Graphics
{
public:
    void init()
    {
        if (SDL_Init(SDL_INIT_VIDEO) < 0)
        {
            fprintf(stderr, "Cannot init SDL. Error: %s\n", SDL_GetError());
            exit(-1);
        }
        //Set texture filtering to linear
        if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1"))
        {
            printf("Warning: Linear texture filtering not enabled!");
        }
        window = SDL_CreateWindow("Client", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 800, 600, SDL_WINDOW_SHOWN);
        if (window == NULL)
        {
            fprintf(stderr, "Cannot create window. Error: %s\n", SDL_GetError());
            exit(-1);
        }
        renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
        if (renderer == NULL)
        {
            fprintf(stderr, "Cannot create renderer. Error: %s\n", SDL_GetError());
            exit(-1);
        }
        SDL_RenderClear(renderer);
        //Init PNG loading
        int imgFlags = IMG_INIT_PNG;
        if (!(IMG_Init(imgFlags) & imgFlags))
        {
            fprintf(stderr, "Cannot init PNG loading. Error: %s\n", IMG_GetError());
            exit(-1);
        }
        loadMedia();
    }
    void render()
    {
        SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF);
        SDL_RenderClear(renderer);
        textures[MAP].render(renderer, 0, 0);
        textures[CHARACTER].render(renderer, 0, 0);
        SDL_RenderPresent(renderer);
    }
private:
    bool loadMedia()
    {
        bool success = true;

        if (!textures[MAP].loadTexture("res/map.png", renderer))
            success = false;
        if (!textures[CHARACTER].loadTexture("res/link.png", renderer))
            success = false;

        return success;
    }
public:
    SDL_Event e;
private:
    SDL_Renderer * renderer;
    Texture textures[TOTAL_TEXTURES];
    SDL_Window * window;
};

Texture.h

#pragma once
#include <SDL.h>
#include <SDL_image.h>
#include <cstdio>

enum TextureEnum
{
    MAP,
    CHARACTER,
    TOTAL_TEXTURES
};

class Texture
{
public:
    Texture()
    {
        texture = NULL;
        width = 0;
        height = 0;
    }
    bool loadTexture(const char* path, SDL_Renderer * renderer)
    {
        bool success = true;
        free();
        SDL_Surface* loadedSurface = IMG_Load(path);
        if (loadedSurface == NULL)
        {
            fprintf(stderr, "Cannot load image %s. SDL_image Error: %s\n", path, IMG_GetError());
            printf("Cannot load image %s. SDL_image Error: %s\n", path, IMG_GetError());
            SDL_FreeSurface(loadedSurface);
            success = false;
        }
        else
        {
            SDL_SetColorKey(loadedSurface, SDL_TRUE, SDL_MapRGB(loadedSurface->format, 0, 0xFF, 0xFF));
            texture = SDL_CreateTextureFromSurface(renderer, loadedSurface);
            width = loadedSurface->w;
            height = loadedSurface->h;
            if (texture == NULL)
            {
                fprintf(stderr, "Cannot create texture from %s. SDL Error: %s\n", path, SDL_GetError());
                printf("Cannot create texture from %s. SDL Error: %s\n", path, SDL_GetError());
                success = false;
            }
        }
        SDL_FreeSurface(loadedSurface);
        return success;
    }
    void free()
    {
        if (texture != NULL)
        {
            SDL_DestroyTexture(texture);
            texture == NULL;
            width = 0;
            height = 0;
        }
    }
    void render(SDL_Renderer * renderer, int x, int y)
    {
        SDL_Rect quad = { x, y, width, height };
        SDL_RenderCopy(renderer, texture, NULL, &quad);
    }
private:
    SDL_Texture * texture;
    int width;
    int height;
};

Solution

  • After updating to the newest Windows 10 version problem did not ocurr.