4
\$\begingroup\$

I have been writing an SDL OpenGL game in c++ for a couple of years now, writing my own engine for the most part (using Box2d for physics). I'm primarily a mac user, so I've been using xCode to write it, and just recently, I installed Windows 10 on a partition of my mac via Bootcamp and decided to work on the windows port (i know, 'windows port', bizarre right?) anyways after a few nights of blood sweat and tears I got everything set up in Visual Studio 2015, and made Visual C++ compiler happy in some areas where it is more strict than g++, and the game finally ran, woo! only to find out very quickly that it runs at less than half the speed. on mac it has no issue running at 50 fps, which is where i happen to cap it, and on windows it struggles to break 20 fps even 10 fps at times. what gives? in theory shouldn't it run about the same? since it is on the exact same hardware and the exact same code? I've heard that windows doesn't support opengl as well as mac does, so is it possible it is some kind of hardware acceleration thing?

its worth noting that my draw method is significantly slower than my update method, here are the averages on both systems

on OSX: draw() = ~7 ticks, update() = ~1 ticks

on Windows: draw() = ~45 ticks, update() = ~5 ticks

My iMac has a 3.2GHz quad-core Intel Core i5 processor and a AMD Radeon R9 M390 with 2GB video memory.

Here are a couple of snippets of relevant code, my game is hundreds of classes/files at this point but if anybody has any other ideas on which other parts of my code base would be helpful to see, I'm more than happy to post more snippets.

in init():

SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 8);

and later in init()

SDL_DisplayMode current;
SDL_GetCurrentDisplayMode(0, &current);

if (preferences->fullscreen) {
    width = current.w;
    height = current.h;
    sdlWindow = SDL_CreateWindow("Test", 0, 0, width, height, SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN_DESKTOP);
}
else {
    width = defaultWindowedWidth;
    height = defaultWindowedHeight;
    sdlWindow = SDL_CreateWindow("Test", 1000, 1000, width, height, SDL_WINDOW_OPENGL);
}

SDL_GL_CreateContext(sdlWindow);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);

thats the relevant code from my init() function, heres my draw() method

void draw() {
    SDL_ShowCursor(false);
    glViewport(0, 0, window->width, window->height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    if (game->player->type == 2) {
        glOrtho(camera->orthoLeft, camera->orthoRight, camera->orthoBottom, camera->orthoTop, camera->nearOrthoClippingPlane, camera->farOrthoClippingPlane);
    }
    else {
        gluPerspective(camera->fieldOfView, (GLfloat)window->width/window->height, camera->nearClippingPlane, camera->farClippingPlane);
    }
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    gluLookAt(camera->position.x, camera->position.y, camera->positionZ, camera->focus.x, camera->focus.y, camera->focusZ, 0, 1, 0);
game->draw();
    if (debug) {
        glDisable(GL_DEPTH_TEST);
        Debugger::draw(game);
        glEnable(GL_DEPTH_TEST);
    }
    if (game->player->type != 2) {
        game->drawVingette(window->width, window->height);
    }
    overlay->draw(window->width, window->height);
}

and my main()

int main(int argc, char ** argv) {
    if (init() == false) {
        return 1;
    }
    SDL_Event event;
    bool isRunning = true;
    Uint32 start;
    Uint32 drawBegin;
    Uint32 drawEnd;
    Uint32 updateBegin;
    Uint32 updateEnd;
    Uint32 timeElapsed;
    while(isRunning){
        start = SDL_GetTicks();
        while(SDL_PollEvent(&event)) {
            isRunning = handler(&event);
        }
        updateBegin = SDL_GetTicks();
        if (paused) {
            if (pauseMenu->unpaused) {
                paused = false;
            }
            pauseMenu->controls(getCurrentInputDevice());
        }
        else {
            if (getCurrentInputDevice()->pause->pressed()) {
                paused = true;
                pauseMenu->pause();
            }
            if (inventoryOpen) {
                if (inventoryMenu->closed) {
                    inventoryOpen = false;
                }
                inventoryMenu->controls(getCurrentInputDevice());
            }
            else {
                if (getCurrentInputDevice()->inventory->pressed() && game->level > 0 && !game->player->isDead) {
                    inventoryOpen = true;
                    inventoryMenu->open();
                }
            }
        }
        if (!paused && !inventoryOpen) {
            update();
        }

        gamepad->update();
        keyboard->update();
        musicPlayer->update();
        updateEnd = SDL_GetTicks();
        drawBegin = SDL_GetTicks();
        draw();
        drawEnd = SDL_GetTicks();
        std::cout << "Update:" << updateEnd - updateBegin << " Draw: " << drawEnd - drawBegin << std::endl;
        if (paused) {
            window->update();
            if (inventoryOpen) {
                inventoryMenu->update();
                inventoryMenu->draw();
            }
            pauseMenu->update();
            pauseMenu->draw();
        }
        else if (inventoryOpen) {
            inventoryMenu->update();
            inventoryMenu->draw();
        }
        if (debug || framesPerSecondDisplayed) {
            Drawing::applyTranslation(b2Vec2(window->width, window->height));
            averagedFramesPerSecondText->drawPhrase(std::to_string(averagedFramesPerSecond));
        }
        window->bufferSwap();
        glFlush();
        lastCoupleFramesPerSecond.push_back(framesPerSecond);
        if (lastCoupleFramesPerSecond.size() >= 10) {
            int sumOfFrameRates = 0;
            for (int i = 0; i < lastCoupleFramesPerSecond.size(); i++) {
                sumOfFrameRates = sumOfFrameRates + lastCoupleFramesPerSecond[i];
            }
            lastCoupleFramesPerSecond.clear();
            averagedFramesPerSecond = sumOfFrameRates/10;
        }
        timeElapsed = SDL_GetTicks() - start;
        if (1000 / desiredFramesPerSecond > timeElapsed) {
            SDL_Delay(1000 / desiredFramesPerSecond - timeElapsed);
            framesPerSecond = desiredFramesPerSecond;
        }
        else {
            framesPerSecond = 1000 / timeElapsed;
        }
    }
    quit();
    return 0;
}

thanks so much for reading!

P.S. It is possible that this whole thing is bootcamp related somehow, im going to have a buddy test the build on his geniune PC and see if it also runs slow. However, I know I've personally played plenty of steam games in windows on my mac before and seen no performance difference and definitely not struggling at 20fps, even saw some folks on forums claim that games run slightly faster in bootcamp windows on their macs than they do in OSX on the same machine, so its doubtful that it is bootcamp related.

\$\endgroup\$

closed as off-topic by Josh Feb 17 '16 at 15:32

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Questions about debugging a problem in your project must present a concise selection of code and context so as to allow a reader to diagnose the issue without needing to read all of your code or to engage in extensive back-and-forth dialog. For more information, see this meta thread." – Josh
If this question can be reworded to fit the rules in the help center, please edit the question.

  • 2
    \$\begingroup\$ Visual Studio has an built in performance analyzer, I think alt+f2, if you fire that up you can probably identify the bottlenecks. \$\endgroup\$ – Tim Feb 17 '16 at 7:33
  • 3
    \$\begingroup\$ I don't know if you're testing for OpenGL errors (glGetError), but if there are errors they can also affect performance. Boot Camp should not affect performance, on the contrary Windows OpenGL drivers perform generally better than OS X. \$\endgroup\$ – SurvivalMachine Feb 17 '16 at 8:31
  • 2
    \$\begingroup\$ “i know, 'windows port', bizarre right?” Not really anymore. Hanging out in indie game dev circles in New York, I hear far more frequently “iOS port“, “Android port“, “desktop port”, “mobile port”, “Linux port”, “Gear VR port”, “Xbox port”, & “PS4 port” than “Mac port”/“Windows port”. In the last decade, the number of platforms with distinct characteristics and vendors has both multiplied and become highly accessible to indie devs. And there are strong technical & political arguments for each & every platform to launch a game first upon. So no “Windows port” doesn't sound bizarre to me. \$\endgroup\$ – Slipp D. Thompson Feb 17 '16 at 9:37
  • 1
    \$\begingroup\$ yeah good point, i just meant that typically a desktop-only game would be developed for windows and than ported to mac, rather than the other way around, but I'm glad the times are changing. after setting up the same project in both xCode and Visual Studio, I have to say I much prefer xCode as my main developer environment \$\endgroup\$ – Dylan Feb 17 '16 at 9:49
  • 1
    \$\begingroup\$ I also am C++/OpenGL/SDL2, primary Mac and now secondary Windows. Getting an OpenGL context on Windows is a bother. Maybe you're getting a software emulation somehow? By default, all you get is OpenGL 1 or 1.1 or something. Look into glew.c. I have some notes in a blog entry: metareal.net/blog/?p=141 Maybe? \$\endgroup\$ – david van brink Feb 17 '16 at 18:47