OpenGL PBO не работает на видеокарте nVidia

Я пытаюсь визуализировать кадры RGB с помощью openGL. Когда память выделяется на ЦП, код работает нормально. Однако, когда я выделяю память на графическом процессоре, используя концепцию объектов пиксельного буфера, у меня возникают проблемы при рендеринге кадров.

Проблема в том, что окошко дисплея полностью белое. Когда тот же код запускается на других видеокартах, код работает нормально. Однако, когда я запускаю его в любой системе с видеокартой nVidia, я сталкиваюсь с проблемой белого экрана.

Ниже мой код:

#include <stdio.h>
#include <stdlib.h>
#include "glew.h"
#include "glfw.h"
#include "glaux.h"

PFNGLGENBUFFERSARBPROC pglGenBuffersARB = 0;                     // VBO Name Generation Procedure
PFNGLBINDBUFFERARBPROC pglBindBufferARB = 0;                     // VBO Bind Procedure
PFNGLBUFFERDATAARBPROC pglBufferDataARB = 0;                     // VBO Data Loading Procedure
PFNGLBUFFERSUBDATAARBPROC pglBufferSubDataARB = 0;               // VBO Sub Data Loading Procedure
PFNGLDELETEBUFFERSARBPROC pglDeleteBuffersARB = 0;               // VBO Deletion Procedure
PFNGLGETBUFFERPARAMETERIVARBPROC pglGetBufferParameterivARB = 0; // return various parameters of VBO
PFNGLMAPBUFFERARBPROC pglMapBufferARB = 0;                       // map VBO procedure
PFNGLUNMAPBUFFERARBPROC pglUnmapBufferARB = 0;                   // unmap VBO procedure
#define glGenBuffersARB           pglGenBuffersARB
#define glBindBufferARB           pglBindBufferARB
#define glBufferDataARB           pglBufferDataARB
#define glBufferSubDataARB        pglBufferSubDataARB
#define glDeleteBuffersARB        pglDeleteBuffersARB
#define glGetBufferParameterivARB pglGetBufferParameterivARB
#define glMapBufferARB            pglMapBufferARB
#define glUnmapBufferARB          pglUnmapBufferARB

int index;
int pboSupported;
int pboMode;
GLuint  pixBuffObjs[2];
HDC hDC = NULL;
GLuint  texture;
char *FileName;
unsigned char *guibuffer;
AUX_RGBImageRec texture1;
unsigned long long pos=0;
GLuint myPBO;


void initGL(void)
{
        int maxSz;
        int maxwidth = 416;
        int maxheight = 240;

        if( !glfwInit() )
        {
            exit( EXIT_FAILURE );
        }


        // if( !glfwOpenWindow(4096, 2118, 0,0,0,0,0,0, GLFW_WINDOW ) )
        if( !glfwOpenWindow(maxwidth, maxheight, 0,0,0,0,0,0, GLFW_WINDOW  ) ) //GLFW_FULLSCREEN
        {
            glfwTerminate();
            exit( EXIT_FAILURE );
        }

        glfwSetWindowTitle("sample");

        glGenBuffersARB = (PFNGLGENBUFFERSARBPROC)wglGetProcAddress("glGenBuffersARB");
        glBindBufferARB = (PFNGLBINDBUFFERARBPROC)wglGetProcAddress("glBindBufferARB");
        glBufferDataARB = (PFNGLBUFFERDATAARBPROC)wglGetProcAddress("glBufferDataARB");
        glBufferSubDataARB = (PFNGLBUFFERSUBDATAARBPROC)wglGetProcAddress("glBufferSubDataARB");
        glDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC)wglGetProcAddress("glDeleteBuffersARB");
        glGetBufferParameterivARB = (PFNGLGETBUFFERPARAMETERIVARBPROC)wglGetProcAddress("glGetBufferParameterivARB");
        glMapBufferARB = (PFNGLMAPBUFFERARBPROC)wglGetProcAddress("glMapBufferARB");
        glUnmapBufferARB = (PFNGLUNMAPBUFFERARBPROC)wglGetProcAddress("glUnmapBufferARB");

        // check once again PBO extension
        if(glGenBuffersARB && glBindBufferARB && glBufferDataARB && glBufferSubDataARB &&
           glMapBufferARB && glUnmapBufferARB && glDeleteBuffersARB && glGetBufferParameterivARB)
        {
            pboSupported = 1;
            pboMode = 1;    // using 1 PBO
            printf( "Video card supports GL_ARB_pixel_buffer_object.");
            glGenBuffersARB(1, &pixBuffObjs[0]);
        }
        else
        {
            pboSupported = 0;
            pboMode = 0;    // without PBO
            printf("Video card does NOT support GL_ARB_pixel_buffer_object.");
        }

        glGetIntegerv(GL_MAX_TEXTURE_SIZE,&maxSz);

        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);       // This Will Clear The Background Color To Black
        glClearDepth(1.0);                          // Enables Clearing Of The Depth Buffer
        glDepthFunc(GL_LESS);                       // The Type Of Depth Test To Do
        glEnable(GL_DEPTH_TEST);                    // Enables Depth Testing
        glShadeModel(GL_SMOOTH);                    // Enables Smooth Color Shading


        glMatrixMode(GL_PROJECTION);
        //glLoadIdentity();



        hDC= wglGetCurrentDC();
#if 1
        { // TSS
            HWND hCurrentWindow = GetActiveWindow();
            char szTitle[256]="sample";
            //SetWindowText(hCurrentWindow, );
            // SetWindowLongA (hCurrentWindow , GWL_STYLE, (GetWindowLongA (hCurrentWindow , GWL_STYLE) & ~(WS_CAPTION)));
            SetWindowLongA (hCurrentWindow, GWL_STYLE, (WS_VISIBLE));
        }
#endif
        glEnable(GL_TEXTURE_2D);
        glGenTextures(1, &texture);
        glBindTexture(GL_TEXTURE_2D, texture);

}

int GL_Disply()
{
    FILE *fptr=fopen("C:\\myRGB.rgb","rb");
    fseek(fptr,pos,SEEK_SET);
    fread(guibuffer,sizeof(unsigned char),sizeof(unsigned char)*416*240*3,fptr);
    pos+=416*240*3;
    texture1.sizeX =416;
    texture1.sizeY =240;
    texture1.data = guibuffer;

    glDepthFunc(GL_ALWAYS);
    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_BLEND);
    glDisable(GL_LIGHTING);

    //glEnable(GL_TEXTURE_2D);

    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);

    glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, myPBO);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texture1.sizeX, texture1.sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);


    glBegin(GL_QUADS);

    //glNormal3f( 0.0f, 0.0f, 0.0f);
    glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, -1.0f,  0.0f);
    glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, -1.0f,  0.0f);
    glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,  1.0f,  0.0f);
    glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,  1.0f,  0.0f);

    glEnd();

    glDisable(GL_BLEND); 
    glEnable(GL_DEPTH_TEST);

    // Swap front and back rendering buffers
    glfwSwapBuffers();
    //glDeleteTextures(1, &texture);
    fclose(fptr);

}
int main(int argc, char *argv[])
{
    initGL(); // GL initialization

    /*GPU memory allocation using C*/
    glGenBuffersARB(1, &myPBO);
    glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, myPBO);
    glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, 416*240*3, NULL, GL_STREAM_DRAW_ARB);
    guibuffer=(unsigned char*)glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB);

    for(index=0;index<200;index++)
    {
        printf("frame %d displayed\r",index);
        GL_Disply();
    }

    return 0;
}

Я отладил и проверил, возвращает ли glMapBufferARB адрес, он возвращает действительный адрес, т.е. нет проблем BadPtr. Я работал с 3 системами, имеющими 3 разные модели видеокарт nVidia, вывод такой же, то есть белый экран.

Однако я также пробовал код в системе с другими видеокартами, код работает. Кроме того, в версии OpenGL проблем нет.

Предложите некоторые изменения или что-то, что может заставить приведенный выше код работать.


person sam    schedule 17.10.2013    source источник


Ответы (1)


Ваш код недействителен и должен вызвать ошибку. Он не должен работать на разных графических процессорах. Традиционно, буферные объекты не могут использоваться GL, пока они отображаются в клиентской памяти. Вам необходимо отменить отображение PBO, прежде чем вы сможете использовать его в качестве источника для спецификации изображения текстуры. Обратите внимание, что вам не следует напрямую повторно отображать PBO сразу после вызова glTexImage, поскольку это снижает перфорацию. В идеале вы должны использовать кольцевой буфер PBO, чтобы позволить GL работать асинхронно.

Современный GL также предлагает функцию постоянных сопоставлений через расширение GL_ARB_buffer_storage (в core начиная с 4.4, так что оно действительно новое). Но это имеет тот недостаток, что вам нужно вручную синхронизировать обновления буфера с GL, при этом ничего не получая в этом случае использования.

person derhass    schedule 17.10.2013
comment
не могли бы вы сказать мне, в каком месте я должен выполнить отключение в приведенном выше коде. - person sam; 18.10.2013
comment
@sam: простейшим вариантом было бы отменить отображение прямо перед вызовом glTexImage и выполнить переназначение сразу после него. Но, как я уже сказал, производительность будет не такой удачной, как могло бы быть. - person derhass; 18.10.2013