Sign in to follow this  
nitro404

OpenGL [SDL] Super slow framerate on Windows 7, GLEW shaders unavailable

Recommended Posts

nitro404    103
Hello!

I've been working on a project off and on in SDL for a number of months now, and I've had an issue from the start that I recently had some time to try and debug. I've been developing on Windows XP until this past week, so it was not really an issue until now.

Basically, my SDL bases game works perfectly fine on any Windows XP machine (ie. normal frame rate, shaders work no problem), but I initially noticed that if I ran the executable on Windows 7, the frame rate would only be 10-15 for no reason (on super high-end machines, ie. Phenom II X6 / 5970) but this was strictly a Windows 7 issue as indicated by testing on several different machines. Upon further investigation I realized that if I run the game from within Visual Studio 2008 on a Windows 7 machine it works perfectly (ie. 7000+ FPS w/o vsync), but as soon as I ran it from the executable instead, the frame rate would once again be between 10 and 15, and if shaders were being used via GLEW, the program would simply exit because GLEW 2.0 was unavailable.

tldr; SDL OpenGL game, works fine on XP, on Win7 works fine in VS2008 but EXE limited to 10 fps and shaders wont work

Honestly not sure what the issue could possibly be and has been baffling me for some time. If anyone has any suggestions or input, it would be greatly appreciated. It almost seems like SDL is somehow switching to software mode or some limited version of OpenGL. Also worth mentioning that the only things being rendered is some text (generated and rendered via lists) and a very simple skybox with 1024x1024 textures for each side.

My game is using SDLmain and a number of libraries, including:
SDL
SDL_ttf
GLEW
FreeImage
Qt
FMOD Ex
FBX SDK
Bullet Physics

Thanks for reading. Some code, if it helps any:

Main.cpp:
[CODE]
#include "Game.h"
int main(int argc, char * argv[]) {
Game * game = new Game();
if(!game->init()) { return -1; }
game->run();
delete game;
return 0;
}
[/CODE]

OpenGL Setup:
[CODE]
bool Game::init() {
if(m_initialized) { return false; }
settings->load();
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_JOYSTICK) == -1) { return false; }
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, settings->verticalSync ? 1 : 0);
m_graphics = SDL_SetVideoMode(settings->windowWidth, settings->windowHeight, 0, SDL_OPENGL | (settings->fullScreen ? SDL_FULLSCREEN : 0));
SDL_WM_SetCaption("Game", NULL);
QString iconPath;
iconPath.append(QString("%1/Icons/Block.bmp").arg(settings->dataDirectoryName));
QByteArray iconPathBytes = iconPath.toLocal8Bit();
m_icon = SDL_LoadBMP(iconPathBytes.data());
SDL_WM_SetIcon(m_icon, NULL);
glShadeModel(GL_SMOOTH);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glDepthFunc(GL_LEQUAL);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glMatrixMode(GL_MODELVIEW);
glViewport(0, 0, settings->windowWidth, settings->windowHeight);
if(glewInit() != GLEW_OK) { return false; }
if(!GLEW_VERSION_2_0) { return false; }

etc.
[/CODE]

Game Loop:
[CODE]
void Game::run() {
if(!m_initialized) { return; }
m_running = true;
SDL_Event event;
static unsigned int lastTime = SDL_GetTicks();
unsigned int currentTime = SDL_GetTicks();
do {
if(SDL_PollEvent(&event)) {
switch(event.type) {
case SDL_KEYDOWN:
if(!console->isActive()) {
menu->handleInput(event);
}
if(!menu->isActive()) {
console->handleInput(event);
}
break;
case SDL_MOUSEMOTION:
if(!console->isActive() &&
!menu->isActive() &&
SDL_GetAppState() & SDL_APPMOUSEFOCUS &&
SDL_GetAppState() & SDL_APPINPUTFOCUS &&
SDL_GetAppState() & SDL_APPACTIVE) {
camera->handleInput(event);
}
break;
case SDL_QUIT:
m_running = false;
break;
default:
break;
}
}
if(m_running) {
currentTime = SDL_GetTicks();
update(currentTime - lastTime);
draw();
lastTime = currentTime;
}
} while(m_running);
}
[/CODE]

Share this post


Link to post
Share on other sites
fastcall22    10846
[code]if(SDL_PollEvent(&event))[/code]

Should be:

[code]while ( SDL_PollEvent( &event ) )[/code]

It's likely that your event queue accumulates more and and more windows events until your game slows down to a crawl -- you need to process all of the window messages between each frame, not just one per frame. (Not sure if this will fix your problem, but it will certainly help...)

Share this post


Link to post
Share on other sites
nitro404    103
Oh dear, I feel ashamed for implementing that wrong. Thanks for the reply! Although this did not fix my previous issues (slow framerate, shaders unsupported), it did fix my input handling and bizarre behaviours I was experiencing with my camera which I had yet to solve, so thanks!

Still looking for a solution, though. I just can't figure what's so different with the execution of the game between being run from Visual Studio 2008 vs. from the compiled release executable.

Share this post


Link to post
Share on other sites
nitro404    103
Not as far as I know, I'm using glLists for my SkyBox, and standard OpenGL stuff for the rest, see code below. The only strange thing I'm doing is using SDL_ttf which uses SDL_Surface to blit text which I convert to an OpenGL texture. Irregardless, I don't think any of this should be an issue if it works perfectly fine from Visual Studio 2008, right?

Edit: Furthermore, there are no problems on Windows XP when running from either VS2008 or EXE. So why is it such a problem on Windows 7? I'm using platform independent libraries (ie. no STL), so I'm still completely baffled.

SkyBox Load:
[code]
bool SkyBox::load() {
if(m_loaded) { return true; }

for(int i=0;i<6;i++) {
m_textures[i] = Game::resources->getTexture(m_textureNames[i]);
if(m_textures[i] == NULL) { return false; }
if(!m_textures[i]->load()) { return false; }
}

m_skyBoxList = glGenLists(6);

float width = (float) (m_textures[0]->getWidth() - 1) / (float) m_textures[0]->getWidth();

// left side
glNewList(m_skyBoxList, GL_COMPILE);
glBegin(GL_POLYGON);
glTexCoord2d(1 - width, width);
glVertex3d(-0.5, 0.5, 0.5);
glTexCoord2d(1 - width, 1 - width);
glVertex3d(-0.5, -0.5, 0.5);
glTexCoord2d(width, 1 - width);
glVertex3d(-0.5, -0.5, -0.5);
glTexCoord2d(width, width);
glVertex3d(-0.5, 0.5, -0.5);
glEnd();
glEndList();

// right side
glNewList(m_skyBoxList + 1, GL_COMPILE);
glBegin(GL_POLYGON);
glTexCoord2d(1 - width, width);
glVertex3d(0.5, 0.5, -0.5);
glTexCoord2d(1 - width, 1 - width);
glVertex3d(0.5, -0.5, -0.5);
glTexCoord2d(width, 1 - width);
glVertex3d(0.5, -0.5, 0.5);
glTexCoord2d(width, width);
glVertex3d(0.5, 0.5, 0.5);
glEnd();
glEndList();

// front side
glNewList(m_skyBoxList + 2, GL_COMPILE);
glBegin(GL_POLYGON);
glTexCoord2d(1 - width, width);
glVertex3d(-0.5, 0.5, -0.5);
glTexCoord2d(1 - width, 1 - width);
glVertex3d(-0.5, -0.5, -0.5);
glTexCoord2d(width, 1 - width);
glVertex3d(0.5, -0.5, -0.5);
glTexCoord2d(width, width);
glVertex3d(0.5, 0.5, -0.5);
glEnd();
glEndList();

// back side
glNewList(m_skyBoxList + 3, GL_COMPILE);
glBegin(GL_POLYGON);
glTexCoord2d(1 - width, width);
glVertex3d(0.5, 0.5, 0.5);
glTexCoord2d(1 - width, 1 - width);
glVertex3d(0.5, -0.5, 0.5);
glTexCoord2d(width, 1 - width);
glVertex3d(-0.5, -0.5, 0.5);
glTexCoord2d(width, width);
glVertex3d(-0.5, 0.5, 0.5);
glEnd();
glEndList();

// top side
glNewList(m_skyBoxList + 4, GL_COMPILE);
glBegin(GL_POLYGON);
glTexCoord2d(width, 1 - width);
glVertex3d(-0.5, 0.5, 0.5);
glTexCoord2d(width, width);
glVertex3d(-0.5, 0.5, -0.5);
glTexCoord2d(1 - width, width);
glVertex3d(0.5, 0.5, -0.5);
glTexCoord2d(1 - width, 1 - width);
glVertex3d(0.5, 0.5, 0.5);
glEnd();
glEndList();

// bottom side
glNewList(m_skyBoxList + 5, GL_COMPILE);
glBegin(GL_POLYGON);
glTexCoord2d(width, 1 - width);
glVertex3d(-0.5, -0.5, -0.5);
glTexCoord2d(width, width);
glVertex3d(-0.5, -0.5, 0.5);
glTexCoord2d(1 - width, width);
glVertex3d(0.5, -0.5, 0.5);
glTexCoord2d(1 - width, 1 - width);
glVertex3d(0.5, -0.5, -0.5);
glEnd();
glEndList();

m_loaded = true;

return true;
}
[/code]

SkyBox Draw:
[code]
void SkyBox::draw() {
if(!m_loaded) { return; }

glDisable(GL_DEPTH_TEST);

glLoadIdentity();

glRotated(Game::camera->getRotation().x, 1, 0, 0);
glRotated(Game::camera->getRotation().y, 0, 1, 0);

for(int i=0;i<6;i++) {
m_textures[i]->activate();
glCallList(m_skyBoxList + i);
}

glEnable(GL_DEPTH_TEST);
}
[/code]

Game Draw:
[code]
void Game::draw() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// set up 3d rendering
glEnable(GL_TEXTURE_2D);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(70.0f, (GLfloat) settings->windowWidth / (GLfloat) settings->windowHeight, 0.1f, 10000.0f);
glMatrixMode(GL_MODELVIEW);

// render skybox
if(skyBox != NULL) {
skyBox->draw();
}

// render world
if(mainShader != NULL) { mainShader->activate(); }

glPushMatrix();
camera->setup();

glScalef(100, 100, 100);

glBegin(GL_POLYGON);

// left
glVertex3f(-1.0f, 0.0f, 0.0f);
glVertex3f(-1.0f, 0.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, 0.0f);

// right
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.0f, -1.0f, 0.0f);
glVertex3f(0.0f, -1.0f, -1.0f);
glVertex3f(0.0f, 0.0f, -1.0f);

// front
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(-1.0f, 0.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 0.0f);
glVertex3f(0.0f, -1.0f, 0.0f);

// back
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(-1.0f, 0.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(0.0f, -1.0f, -1.0f);

// top
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 0.0f, -1.0f);
glVertex3f(-1.0f, 0.0f, -1.0f);
glVertex3f(-1.0f, 0.0f, 0.0f);

// bottom
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, 0.0f);

glEnd();
glPopMatrix();

if(mainShader != NULL) { mainShader->deactivate(); }

// set up 2d rendering
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, settings->windowWidth, settings->windowHeight, 0);

// render hud / gui elements
displayFPS();
menu->draw();
console->draw();

SDL_GL_SwapBuffers();
}
[/code]

Font Draw / Load:
[code]
void Font::drawTextHelper(int x, int y, const char * text) const {
if(!m_loaded) { return; }

glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);

glBindTexture(GL_TEXTURE_2D, m_texture);

glMatrixMode(GL_MODELVIEW);
glPushMatrix();

glLoadIdentity();

glTranslated(x, y, 0);
glListBase(m_font - 32);
glCallLists(strlen(text), GL_BYTE, text);

glPopMatrix();
}

bool Font::load() {
if(m_loaded) { return true; }

QString fontPath = QString("%1/Fonts/%2").arg(Game::settings->dataDirectoryName).arg(m_fileName);

QFileInfo fontFile(fontPath);
if(!fontFile.exists()) { return false; }

QByteArray bytes = fontPath.toLocal8Bit();

TTF_Font * fontData;
if(!(fontData = TTF_OpenFont(bytes.data(), m_size))) {
return false;
}

SDL_Color colour = {255, 255, 255, 255};

SDL_Surface * character;
QVector characters;
int maxWidth = -1;
int maxHeight = -1;
char data[2];
data[1] = '\0';
for(int i=0;i<128;i++ ) {
data[0] = (char) (i + 32);
character = TTF_RenderText_Blended(fontData, data, colour);
characters.push_back(character);
if(maxWidth < 0 || maxWidth < character->w) { maxWidth = character->w; }
if(maxHeight < 0 || maxHeight < character->h) { maxHeight = character->h; }
}

m_horizontalSpacing = maxWidth;
m_verticalSpacing = maxHeight;

int width = 1, tempWidth = maxWidth * 16;
int height = 1, tempHeight = maxHeight * 8;
while(width < tempWidth) { width *= 2; }
while(height < tempHeight) { height *= 2; }

SDL_Surface * temp = SDL_CreateRGBSurface(0, width, height, 32,
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
#else
0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
#endif
);

SDL_Rect sourceArea, destArea;
int x = 0;
int y = 0;
for(int i=0;i<128;i++) {
sourceArea.x = 0;
sourceArea.y = 0;
sourceArea.w = characters[i]->w;
sourceArea.h = characters[i]->h;

destArea.x = maxWidth * x;
destArea.y = maxHeight * y;
destArea.w = characters[i]->w;
destArea.h = characters[i]->h;

SDL_SetAlpha(characters[i], 0, 0);
SDL_BlitSurface(characters[i], &sourceArea, temp, &destArea);

x++;
if(x == 16) {
x = 0;
y++;
}
}

glGenTextures(1, &m_texture);
glBindTexture(GL_TEXTURE_2D, m_texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, temp->w, temp->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, temp->pixels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);

m_font = glGenLists(128);

x = 0;
y = 0;
float w = (float) maxWidth / (float) (temp->w);
float h = (float) maxHeight / (float) (temp->h);
for(int i=0;i<128;i++) {

glNewList(m_font + i, GL_COMPILE);

glBegin(GL_QUADS);
glTexCoord2f((w * x), ((h * y))); glVertex2i(0, 0);
glTexCoord2f((w * x) + w, ((h * y))); glVertex2i(maxWidth, 0);
glTexCoord2f((w * x) + w, ((h * y) + h)); glVertex2i(maxWidth, maxHeight);
glTexCoord2f((w * x), ((h * y) + h)); glVertex2i(0, maxHeight);
glEnd();

glTranslated(maxWidth, 0, 0);

glEndList();

x++;
if(x == 16) {
x = 0;
y++;
}
}

for(int i=0;i<128;i++) {
SDL_FreeSurface(characters[i]);
}
SDL_FreeSurface(temp);

m_loaded = true;

return true;
}
[/code]

Share this post


Link to post
Share on other sites
nitro404    103
Found the solution to all my issues finally, after consulting some friends. Turns out Visual Studio 2008 on Windows 7 would use the operating system's version of OpenGL, and when I ran it from the EXE it used the local OpenGL32.dll which was either out of date, or built for the wrong platform. So, removing this DLL fixed all framerate issues, and now runs no problem after defaulting to the operating system's OpenGL32.dll. Hopefully this helps anyone else who runs into this issue!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Similar Content

    • By pseudomarvin
      I assumed that if a shader is computationally expensive then the execution is just slower. But running the following GLSL FS instead just crashes
      void main() { float x = 0; float y = 0; int sum = 0; for (float x = 0; x < 10; x += 0.00005) { for (float y = 0; y < 10; y += 0.00005) { sum++; } } fragColor = vec4(1, 1, 1 , 1.0); } with unhandled exception in nvoglv32.dll. Are there any hard limits on the number of steps/time that a shader can take before it is shut down? I was thinking about implementing some time intensive computation in shaders where it would take on the order of seconds to compute a frame, is that possible? Thanks.
    • By Arulbabu Donbosco
      There are studios selling applications which is just copying any 3Dgraphic content and regenerating into another new window. especially for CAVE Virtual reality experience. so that the user opens REvite or CAD or any other 3D applications and opens a model. then when the user selects the rendered window the VR application copies the 3D model information from the OpenGL window. 
      I got the clue that the VR application replaces the windows opengl32.dll file. how this is possible ... how can we copy the 3d content from the current OpenGL window.
      anyone, please help me .. how to go further... to create an application like VR CAVE. 
       
      Thanks
    • By cebugdev
      hi all,

      i am trying to build an OpenGL 2D GUI system, (yeah yeah, i know i should not be re inventing the wheel, but this is for educational and some other purpose only),
      i have built GUI system before using 2D systems such as that of HTML/JS canvas, but in 2D system, i can directly match a mouse coordinates to the actual graphic coordinates with additional computation for screen size/ratio/scale ofcourse.
      now i want to port it to OpenGL, i know that to render a 2D object in OpenGL we specify coordiantes in Clip space or use the orthographic projection, now heres what i need help about.
      1. what is the right way of rendering the GUI? is it thru drawing in clip space or switching to ortho projection?
      2. from screen coordinates (top left is 0,0 nd bottom right is width height), how can i map the mouse coordinates to OpenGL 2D so that mouse events such as button click works? In consideration ofcourse to the current screen/size dimension.
      3. when let say if the screen size/dimension is different, how to handle this? in my previous javascript 2D engine using canvas, i just have my working coordinates and then just perform the bitblk or copying my working canvas to screen canvas and scale the mouse coordinates from there, in OpenGL how to work on a multiple screen sizes (more like an OpenGL ES question).
      lastly, if you guys know any books, resources, links or tutorials that handle or discuss this, i found one with marekknows opengl game engine website but its not free,
      Just let me know. Did not have any luck finding resource in google for writing our own OpenGL GUI framework.
      IF there are no any available online, just let me know, what things do i need to look into for OpenGL and i will study them one by one to make it work.
      thank you, and looking forward to positive replies.
    • By fllwr0491
      I have a few beginner questions about tesselation that I really have no clue.
      The opengl wiki doesn't seem to talk anything about the details.
       
      What is the relationship between TCS layout out and TES layout in?
      How does the tesselator know how control points are organized?
          e.g. If TES input requests triangles, but TCS can output N vertices.
             What happens in this case?
      In this article,
      http://www.informit.com/articles/article.aspx?p=2120983
      the isoline example TCS out=4, but TES in=isoline.
      And gl_TessCoord is only a single one.
      So which ones are the control points?
      How are tesselator building primitives?
    • By Orella
      I've been developing a 2D Engine using SFML + ImGui.
      Here you can see an image
      The editor is rendered using ImGui and the scene window is a sf::RenderTexture where I draw the GameObjects and then is converted to ImGui::Image to render it in the editor.
      Now I need to create a 3D Engine during this year in my Bachelor Degree but using SDL2 + ImGui and I want to recreate what I did with the 2D Engine. 
      I've managed to render the editor like I did in the 2D Engine using this example that comes with ImGui. 
      3D Editor preview
      But I don't know how to create an equivalent of sf::RenderTexture in SDL2, so I can draw the 3D scene there and convert it to ImGui::Image to show it in the editor.
      If you can provide code will be better. And if you want me to provide any specific code tell me.
      Thanks!
  • Popular Now