SDL 导致整个计算机图形冻结
SDL causes graphic freezes in entire computer
我使用的是 SDL 2.0.8 和 SDL_image 2.0.3。我写了一个小程序,可以在屏幕上呈现 2 个纹理。
当我启动该程序时,我的计算机非常滞后,以至于我无法关闭该程序 window。我把这个程序给了我的朋友,当他打开它时,他遇到了和我一样的延迟。我们认为我的代码中有问题。我们分析了代码,没有发现任何错误。然后我想起去年我写过类似的代码,一切都很好 运行ning 。我下载它是因为我把它放在云端,我们 运行 它。该计划也很滞后。这对我们来说太奇怪了。我们的显卡有 100% 的利用率,因为我没有设置 framerate lock 或 vsync。
我的电脑:
- AMD 锐龙 7 2700x @4.3GHz
- AMD Radeon R9 390
- 16 GB 内存 DDR4 3000MHz
我朋友的电脑:
- AMD 锐龙 7 1700 @3.6GHz
- 英伟达 GTX 770
- 16 GB 内存 DDR4 3200MHz
我可以补充一点,在循环中注释渲染函数可以消除延迟。
编辑:
只有当显卡利用率在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;
};
更新到最新后Windows10版本问题没有出现
我使用的是 SDL 2.0.8 和 SDL_image 2.0.3。我写了一个小程序,可以在屏幕上呈现 2 个纹理。
当我启动该程序时,我的计算机非常滞后,以至于我无法关闭该程序 window。我把这个程序给了我的朋友,当他打开它时,他遇到了和我一样的延迟。我们认为我的代码中有问题。我们分析了代码,没有发现任何错误。然后我想起去年我写过类似的代码,一切都很好 运行ning 。我下载它是因为我把它放在云端,我们 运行 它。该计划也很滞后。这对我们来说太奇怪了。我们的显卡有 100% 的利用率,因为我没有设置 framerate lock 或 vsync。
我的电脑:
- AMD 锐龙 7 2700x @4.3GHz
- AMD Radeon R9 390
- 16 GB 内存 DDR4 3000MHz
我朋友的电脑:
- AMD 锐龙 7 1700 @3.6GHz
- 英伟达 GTX 770
- 16 GB 内存 DDR4 3200MHz
我可以补充一点,在循环中注释渲染函数可以消除延迟。
编辑:
只有当显卡利用率在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;
};
更新到最新后Windows10版本问题没有出现