【发布时间】:2015-09-10 11:20:06
【问题描述】:
我最近决定开始使用 SDL 作为我的库之一来编写 C++ 游戏。在我编写程序和学习 SDL 的过程中,我偶然发现了我的程序中的一个特殊错误,并决定在 SSCCE 中复制它以确保我没有发疯。
问题似乎是当我将 SDL_RENDERER_PRESENTVSYNC 作为标志传递给 SDL_CreateRenderer 时,我得到不一致的渲染。为了比较,我运行了 50 次带有标志的程序,50 次没有标志,并且在每种情况下对我的程序进行了唯一的更改。没有标志,显示器工作 100% 的时间。开启标志后,它在 50 次中仅成功渲染了 13 次。
这是程序:
#include <SDL2/SDL.h>
#include <iostream>
int main(int argc, char** argv)
{
if(SDL_Init(SDL_INIT_VIDEO) != 0)
{
std::cerr << "Unable to initialize SDL: " << SDL_GetError() << std::endl;
return -1;
}
SDL_Window* win = SDL_CreateWindow("Testing",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
640, 480, SDL_WINDOW_SHOWN);
SDL_Renderer* renderer = SDL_CreateRenderer(win, -1,
SDL_RENDERER_ACCELERATED |
SDL_RENDERER_PRESENTVSYNC);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
for(int x = 0; x < 640; x+=32)
{
for(int y = 0; y < 480; y+=32)
{
SDL_Rect rect = {x+1, y+1, 31, 31};
SDL_RenderFillRect(renderer, &rect);
}
}
SDL_RenderPresent(renderer);
SDL_Delay(500);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(win);
SDL_Quit();
return 0;
}
如果有所作为,我将在 Ubuntu 15.04、GCC/G++ 4.9.2 上编译和测试该程序,并针对 SDL 2.0.2 进行编译和链接。
对 SDL 如此陌生,并且对 C++ 和 C 来说仍然相对较新(我来自 Java 背景),我认为我很可能犯了一个我没有发现的简单错误,但我可以不要想我可能做了什么。
【问题讨论】:
-
无法复制。当它“失败”时,你究竟看到了什么?
-
@keltar 当它失败时,窗口确实出现了,但它应该呈现的区域只是窗口弹出之前背景中的任何内容的副本,这与我得到的行为相同没有应用渲染/绘图。
-
你的显卡驱动是什么?是否启用合成?如果您要求驱动程序强制 vsync 会发生什么?
-
@keltar 我在笔记本电脑上使用板载英特尔显卡。作为笔记本电脑,没有单独安装的显卡。 lshw 显示我的驱动程序是 i915。根据 compiz 的说法,启用了合成。 OpenGL 被设置为同步到 VBLANK,由同一个工具。不太清楚如何要求驱动程序强制 vsync。应该注意,图形不是(还)我的专业领域。
-
我的意思是,在您的情况下,将环境变量
vblank_mode设置为0(禁用 vsync)或1(即使应用程序没有请求它也强制 vsync)。不幸的是,我从未遇到过您的问题,因此无法告诉您确切的原因或解决方案,但有人多次告诉我,GPU vsync 和 compiz vsync 的组合纯粹是疯狂。我建议在不合成的情况下尝试它。在快速更新的应用程序中这不是问题,但是如果您只想绘制一帧 - 它会变得很棘手;可能由于某种原因,当 compiz 还没有准备好获取图像时,您的翻转发生得太早了。