SDL_GL_SwapBuffers () периодически медленно

У меня есть игра SDL / OpenGL, над которой я работаю ради удовольствия. В среднем я получаю приличное количество кадров в секунду, но движение действительно прерывистое, потому что SDL_GL_SwapBuffers () будет случайным образом занимать много времени для обработки. С текстурами, загруженными и записанными в буфер, иногда это занимает более 100 мс! Я вырезал большую часть своего кода, чтобы попытаться выяснить, было ли это что-то, что я сделал неправильно, но мне не повезло. Когда я запускаю эту программу, она все равно будет блокироваться до 70 мс.

Главный:

// Don't forget to link to opengl32, glu32, SDL_image.lib

// includes
#include <stdio.h>

// SDL
#include <cstdlib>
#include <SDL/SDL.h>

// Video
#include "videoengine.h"

int main(int argc, char *argv[])
{
    // begin SDL
    if ( SDL_Init(SDL_INIT_VIDEO) != 0 )
    {
        printf("Unable to initialize SDL: %s\n", SDL_GetError());
    }

    // begin video class
    VideoEngine videoEngine;

    // BEGIN MAIN LOOP
    bool done = false;
    while (!done)
    {
        int loopStart = SDL_GetTicks();

        printf("STARTING SWAP BUFFER : %d\n", SDL_GetTicks() - loopStart);
        SDL_GL_SwapBuffers();


        int total = SDL_GetTicks() - loopStart;
        if (total > 6)
            printf("END LOOP  : %d ------------------------------------------------------------>\n", total);
        else
             printf("END LOOP  : %d\n", total);

    }
    // END MAIN LOOP

    return 0;
}

Мой конструктор VideoEngine:

    VideoEngine::VideoEngine()
{
    UNIT = 16;
    SCREEN_X = 320;
    SCREEN_Y = 240;
    SCALE = 1;


    // Begin Initalization

        SDL_Surface *screen;

        SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );  // [!] SDL_GL_SetAttributes must be done BEFORE SDL_SetVideoMode

        screen = SDL_SetVideoMode( SCALE*SCREEN_X, SCALE*SCREEN_Y, 16, SDL_OPENGL );  // Set screen to the window with opengl
        if ( !screen )  // make sure the window was created
        {
            printf("Unable to set video mode: %s\n", SDL_GetError());
        }

        // set opengl state
        opengl_init();

    // End Initalization

}

void VideoEngine::opengl_init()
{
    // Set the OpenGL state after creating the context with SDL_SetVideoMode

        //glClearColor( 0, 0, 0, 0 );                             // sets screen buffer to black
        //glClearDepth(1.0f);                                     // Tells OpenGL what value to reset the depth buffer when it is cleared
        glViewport( 0, 0, SCALE*SCREEN_X, SCALE*SCREEN_Y );     // sets the viewport to the default resolution (SCREEN_X x SCREEN_Y) multiplied by SCALE. (x,y,w,h)
        glMatrixMode( GL_PROJECTION );                          // Applies subsequent matrix operations to the projection matrix stack.
        glLoadIdentity();                                       // Replaces the current matrix with the identity matrix
        glOrtho( 0, SCALE*SCREEN_X, SCALE*SCREEN_Y, 0, -1, 1 ); //describes a transformation that produces a parallel projection
        glMatrixMode( GL_MODELVIEW );                           // Applies subsequent matrix operations to the projection matrix stack.
        glEnable(GL_TEXTURE_2D);                                // Need this to display a texture
        glLoadIdentity();                                       // Replaces the current matrix with the identity matrix
        glEnable(GL_BLEND);                                     // Enable blending for transparency
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);      // Specifies pixel arithmetic
        //glDisable( GL_LIGHTING );                               // Disable lighting
        //glDisable( GL_DITHER );                                 // Disable dithering
        //glDisable( GL_DEPTH_TEST );                             // Disable depth testing

        //Check for error
        GLenum error = glGetError();
        if( error != GL_NO_ERROR )
        {
         printf( "Error initializing OpenGL! %s\n", gluErrorString( error ) );
        }

    return;
}

Я начинаю думать, возможно, у меня есть проблема с оборудованием? У меня никогда не было этой проблемы с игрой, хотя.

 Alden17 окт. 2012 г., 22:48
Не идеально, но значительно улучшилось. Я также заметил, что часть дрожания связана с тем, что при перемещении экрана один кадр дублировался. Спасибо!
 Alden17 окт. 2012 г., 22:17
Нет, я так не думаю после прочтения этого -stackoverflow.com/questions/589064/... Я думаю, что может происходить вызов SwapBuffers () без предоставления времени для обработки может привести к зависанию или зацикливанию. Я прочту еще немного и посмотрю, не смогу ли я найти что-нибудь, чтобы поддержать это.
 genpfault17 окт. 2012 г., 22:38
Бросать a SDL_Delay(1) после замены буфера посмотрите, что он делает с вашими временами кадров.
 Tim17 окт. 2012 г., 20:04
У вас есть какой-либо vsync включен?

Ответы на вопрос(1)

Решение Вопроса

SwapIntervalEXT расширение, так что вы можете быть уверены, что замена буфера происходит максимально быстро (VSYNC отключен). Кроме того, замена буфера не простая операция, OpenGL необходимо скопировать содержимое обратных буферов в передние буферы для случая, когда вы хотитеglReadPixels(), Это поведение можно контролировать с помощьюWGL_ARB_pixel_format, с помощьюWGL_SWAP_EXCHANGE_ARB (Вы можете прочитать обо всем этом в спецификациях; теперь я не уверен, есть ли альтернатива этому для Linux).

И, кроме того, есть система управления окнами. Это на самом деле может вызвать много проблем. Кроме того, если некоторые ошибки генерируются ...

Такое поведение, вероятно, нормально, если вы работаете на небольшом мобильном графическом процессоре.

SDL_GL_SwapBuffers() содержит только вызовglxSwapBuffers() / wglSwapBuffers() так что там нет времени.

 the swine20 окт. 2014 г., 09:49
@ BenVoigt вы правы, глядя на это, это не так. Тем не менее, это было в каком-то руководстве по оптимизации от NVIDIA, они довольно четко заявили, что это нужно установить явно.
 Ben Voigt18 окт. 2014 г., 18:23
Он назван буферами подкачки именно потому, что ни одна здравомыслящая реализация на самом деле не выполняет копирование.
 Ben Voigt19 окт. 2014 г., 18:50
Вы уверены, что вам не нужно явно запрашивать наличие правильных данных в буфере? ЭтоWGL_SWAP_METHOD_ARB Параметр имеет три параметра, и он не дает понять, какой из них используется по умолчанию.
 the swine19 окт. 2014 г., 10:10
@ BenVoigt Ну, видимо, WGL делает - читайтеWGL_SWAP_EXCHANGE_ARB связанные документы (Я не оспариваю ваш комментарий о здравомыслии, хотя). Причиной этого является возможность читать содержимое буфера даже после перестановки (не знаю, почему кто-то хотел это сделать), и это поведение по умолчанию. ВключаяWGL_SWAP_EXCHANGE_ARB вы признаете, что понимаете, что после перестановки буферы меняются местами, и вы больше не можете получить доступ к своим данным.

Ваш ответ на вопрос