SDL2-Ubuntu / Mac OS X上的仿真器运行缓慢

问题描述 投票:0回答:1

我使用SDL2用C ++编写了一个Space Invaders模拟器,仅用于创建游戏窗口和播放声音(sdl2_mixer)。在Windows上,模拟器可以60 FPS的速度运行(我可以将该值更改为所需的值,并且可以毫无问题地运行),但是如果我在Ubuntu或Mac OS X上构建它,则游戏将无法播放(可能是所需FPS的10%)。

对此有解释吗?

[我试图注释掉创建框架的部分(因此窗口上没有框架更新),并且游戏仍然很慢(音频仍在播放。)

  • Ubuntu上的渲染器名称:opengl

  • Windows上的渲染器名称:direct3d

  • Renderer标志在Windows上均在Windows上均为0x0a

编译:

g++ -std=c++11 main.cpp spaceinvadersmachine.cpp intel8080.cpp -lSDL2 -lSDL2_mixer -I/usr/include/SDL2 -I/usr/include/SDL2_mixer -Ofast -D_REENTRANT -o spaceinvaders.app

或:

g++ -std=c++11 main.cpp spaceinvadersmachine.cpp intel8080.cpp -lSDL2 -lSDL2_mixer -I/usr/include/SDL2 -I/usr/include/SDL2_mixer -O2 -D_REENTRANT -o spaceinvaders.app

这里有一些代码:

//主循环

while (!quitEmulator)
{
    // Handle events on queue
    while (SDL_PollEvent(&events) == 1)
    {
        switch (events.type)
        {
        case SDL_QUIT:
        {
            // Game's window has been closed
            quitEmulator = true;
            break;
        }
        case SDL_KEYDOWN:
        {
            // Set magnification to 1x
            if (events.key.keysym.sym == SDLK_1)
            {
                machine.magnificationFactor = 1.0;
                machine.magnificationRequest = true;
            }

            // Save game request
            if (events.key.keysym.sym == SDLK_2)
            {
                machine.saveGameRequest = true;
            }

            // Load game request
            if (events.key.keysym.sym == SDLK_3)
            {
                machine.loadGameRequest = true;
            }

            // Set magnification to 4x
            if (events.key.keysym.sym == SDLK_4)
            {
                machine.magnificationFactor = 2.0;
                machine.magnificationRequest = true;
            }

            // Set bases dipswitch request
            if (events.key.keysym.sym == SDLK_7)
            {
                machine.dipBasesRequest = true;
            }

            // Set bonus base dipswitch request
            if (events.key.keysym.sym == SDLK_8)
            {
                machine.dipBonusBaseRequest = true;
            }

            // Set magnification to 9x
            if (events.key.keysym.sym == SDLK_9)
            {
                machine.magnificationFactor = 3.0;
                machine.magnificationRequest = true;
            }

            // Set coin informations dipswitch request
            if (events.key.keysym.sym == SDLK_i)
            {
                machine.dipCoinInfoRequest = true;
            }

            // Game paused
            if (events.key.keysym.sym == SDLK_p)
            {
                gamePaused = !gamePaused;
                if (gamePaused)
                    cout << "INFO: Game paused!\n";
                else
                    cout << "INFO: Game resumed!\n";
            }

            // Reset request
            if (events.key.keysym.sym == SDLK_r)
            {
                machine.resetRequest = true;
            }

            // Change color mode
            if (events.key.keysym.sym == SDLK_c)
            {
                machine.coloredFrame = !machine.coloredFrame;

                if (machine.coloredFrame)
                    cout << "INFO: Color mode set to RGB\n";
                else
                    cout << "INFO: Color mode set to B/W\n";
            }

            break;
        }
        }
    }

    if (!gamePaused)
    {
        // Check keyboard inputs
        SDL_PumpEvents();
        machine.checkKeyboardInput();

        // Set bases dipswitch if requested
        if (machine.dipBasesRequest)
        {
            machine.setBasesDipswitch();
        }

        // Set bonus base dipswitch if requested
        if (machine.dipBonusBaseRequest)
        {
            machine.setBonusBaseDipswitch();
        }

        // Set coin informations dipswitch if requested
        if (machine.dipCoinInfoRequest)
        {
            machine.setCoinInfoDipswitch();
        }

        // Change magnification factor if requested
        if (machine.magnificationRequest)
        {
            machine.setMagnification();
        }

        // Check for interrupt
        if (CPUInterruptDeltaCycles >= cyclePerInterrupt)
        {
            CPUInterruptDeltaCycles = 0;

            machine.interruptRequest = true;

            if (machine.lastInterruptNumber == 1) // RST 1
            {
                machine.interruptNumber = 2; // RST 2
            }
            else // RST 2
            {
                machine.interruptNumber = 1; // RST 1
            }

            machine.lastInterruptNumber = machine.interruptNumber;
        }
        else
        {
            machine.interruptRequest = false;
        }

        // Execute next instruction
        CPU.executeROM(machine.interruptRequest, machine.interruptNumber);

        // Increments CPU's cycle counters
        CPUDeltaCycles += CPU.CPUCycles;
        CPUInterruptDeltaCycles += CPU.CPUCycles;

        // Check if OPCode is known
        if (CPU.unimplementedOPCode)
            quitEmulator = true;

        // Check for I/O
        machine.checkIO();

        // Check if a frame must be drawn
        // Save and Load if requested
        if (CPUDeltaCycles >= cyclePerFrame)
        {
            CPUDeltaCycles = 0;
            machine.createFrame();
            machine.showFrame();
            drewFrames += 1;

            while ((SDL_GetTicks() - lastFPSSynchronization) < frameTimeInterval)
            {
                // Waiting
                ;
            }

            lastFPSSynchronization = SDL_GetTicks();

            if (machine.saveGameRequest)
            {
                machine.saveGameRequest = false;
                machine.saveGame(CPUInterruptDeltaCycles);
            }

            if (machine.loadGameRequest)
            {
                machine.loadGameRequest = false;
                machine.loadGame(CPUInterruptDeltaCycles);

                // Remove pending keyboard events
                SDL_FlushEvent(SDL_KEYDOWN);
                SDL_FlushEvent(SDL_KEYUP);
                SDL_PumpEvents();
            }
        }

        // Reset if requested
        if (machine.resetRequest)
        {
            machine.resetRequest = false;
            machine.resetMachine();
        }
    }
}

//通过SDL显示帧

void spaceInvadersMachine::showFrame()
{
    loadedSurface = SDL_CreateRGBSurfaceFrom(frameBuffer32, SCREEN_HEIGHT, SCREEN_WIDTH, 32, 4 * SCREEN_HEIGHT, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);

    if (loadedSurface == NULL)
    {
        printf("Unable to load video RAM! Error: %s\n", SDL_GetError());
    }
    else
    {
        // Create texture from surface
        gTexture = SDL_CreateTextureFromSurface(gRenderer, loadedSurface);

        // Delete surface
        SDL_FreeSurface(loadedSurface);

        if (gTexture == NULL)
        {
            printf("Failed to create texture image! Error: %s\n", SDL_GetError());
        }
        else
        {
            // Clear screen
            SDL_RenderClear(gRenderer);

            // Render texture to screen
            SDL_RenderCopyEx(gRenderer, gTexture, NULL, &destinationRectangle, 90, NULL, SDL_FLIP_NONE);

            // Delete texture (avoid memory leak)
            SDL_DestroyTexture(gTexture);

            // Update screen
            SDL_RenderPresent(gRenderer);
        }
    }
}
c++ c++11 sdl-2
1个回答
0
投票

您正在每帧创建一个新的表面和新的纹理。是的,它将会很慢,创建纹理是一个荒谬的缓慢操作。不要经常这样做。

[如果您需要直接写入像素,请一次创建正确大小的纹理(使用SDL_TEXTUREACCESS_STREAMING,然后使用SDL_LockTextureSDL_UnlockTexture进行更新。我猜测Windows版本很快(偶然))因为您的驱动程序实现会注意到您在做一些奇怪的事情,并且悄悄地忽略了您要执行的操作,并且更快地完成了操作。

当然不用看代码,很难说这是它的[[only问题,但这很可能是一个瓶颈,甚至是瓶颈。

© www.soinside.com 2019 - 2024. All rights reserved.