首页 > 解决方案 > SDL 导致整个计算机中的图形冻结

问题描述

我正在使用 SDL 2.0.8 和 SDL_image 2.0.3。我编写了一个在屏幕 2 纹理上呈现的小程序。

当我启动程序时,我的计算机非常滞后,以至于我无法关闭程序窗口。我把这个程序给了我的朋友,当他打开它时,他得到了和我一样的延迟。我们认为我的代码中的某些内容很糟糕。我们分析了代码,并没有发现任何错误。然后我记得我去年写了类似的代码,一切运行良好。我下载了它,因为我在云中拥有它并且我们运行它。该计划也滞后。这对我们来说很奇怪。我们的显卡有 100% 的利用率,因为我没有设置帧率锁定或垂直同步。

我的电脑:

我朋友的电脑:

我可以在循环中添加评论渲染函数来消除滞后。

编辑:

仅当显卡利用率约为 100% 时才会发生这种情况。可能当处理器太弱而无法快速运行以致显卡满载时,不会出现问题。

这是代码:

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;
};

标签: c++sdl

解决方案


更新到最新的 Windows 10 版本后没有出现问题。


推荐阅读