Externen Buffer rendern



  • Hi, der ist beliebig groß, mommentan benutz ich immer 800x600.
    Gefüllt wird der per raytracing, daher auch floatingpoint für tonemapping, wobei es mir theoretisch erstmal auch reicht wenn ich einen rgb8 buffer schnell zeichnen könnte.

    Ps. Es reicht wenn ich 60 bilder pro sekunde ohne große cpu last zeichnen könnte, mit der Methode "eine textur pro frame basteln" läuft aber selbst mit vsync 1 kern auf vollast.

    Gruss



  • 800 * 600 * RGBA * sizeof(float) * 60fps = 460mb/s.

    Wenn jetzt Deine Grafikkarte floats intern nicht IEEE-konform darstellt, hat der Treiber ganz schoen was zu tun...



  • Und wie könnte man das sonst bewerkstelligen?

    Edit: Wie machen das denn VLC, Mediaplayer & co? Die müßten doch das gleiche Problem haben.

    Gruss



  • Die brauchen keine floats und haben damit nur 1/4 Traffic und keine Konvertierung.



  • Es ist ja schön und so das die das alles können und das du mir sagst das die das anders und besser machen. Könntest du mir jetzt vielleicht auch noch sagen wie die das machen? Denn an meinem ursprünglichen Problem ändert das Reichlich wenig. Es ist noch immer langsamm für jedes Frame eine Neue Textur zu generieren. Oder ist das der einzige weg?



  • Es ist ja schön und so das die das alles können und das du mir sagst das die das anders und besser machen.

    Du hast mich misverstanden: Waehrend Du einen Float-Buffer zur Grafikkarte uebertragen moechtest, machen die von Dir genannten Applikation das gerade nicht.
    Was bei Dir der tatsaechliche Flaschenhals ist kann ich leider nicht weisssagen, habe aber zwei moegliche Ursachen genannt.
    Eine dritte ist, dass Du den Buffer bereits GPU-seitig verwenden willst waehrend dieser uebertragungsbedingt noch gelockt ist.
    Um die genauen Ursachen zu ermitteln wirst Du einen geeigneten Profiler benutzen oder wenigstens relevante Stellen Deines Codes zeigen muessen.



  • Ich hab oben geschrieben, dass mir ein schnelles übertragen eines RGB byte buffers auch erstmal reichen würde. Mommentan mach ich das in etwa einfach so:

    glGenTextures(1, &dynamicTextureID);
    glBindTexture(GL_TEXTURE_2D, dynamicTextureID);
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_FLOAT, surface->getPixels());
    
    glColor3f(1, 0, 1);
    glBegin(GL_QUADS);
    	glTexCoord2f(0.0f, 0.0f);
    	glVertex3f(0, 0, 1.0f);
    
    	glTexCoord2f(1.0f, 0.0f);
    	glVertex3f(width, 0, 1.0f);
    
    	glTexCoord2f(1.0f, 1.0f);
    	glVertex3f(width, height, 1.0f);
    
    	glTexCoord2f(0.0f, 1.0f);
    	glVertex3f(0, height, 1.0f);
    glEnd();
    
    glDeleteTextures( 1, &dynamicTextureID );
    

    Wie gesagt ich MUSS nicht float zur grafikkarte senden, ich kann auch gerne nen normalen RGB buffer mit bytes rüberschicken, aber viel schneller war das bei meiner bisherigen methode halt auch nicht.


  • Mod

    setz auf internal und external format GL_BGRA_EXT, RGBA wird (oder wurde zumindestens frueher) immer intern zu BGRA umgewandelt weshalb es recht langsam war, dafuer wurde dann GL_BGRA_EXT eingefuehrt.
    kann sein dass es heutzutage (und vielleicht je nach graka+treiber) anders ist. aber frueher war es so 😉

    zudem, es koennte schneller sein wenn du kleinere texturen verwenden wuerdest, 16bit oder dxt texturen (falls du vorher zeit hast das zu convertieren).



  • Da sich die Groesse Deiner Textur vermutlich nicht veraendert ist es nicht notwendig jedesmal eine neue Textur zu erzeugen (und damit die Garbage-Collection des Treibers zu belaestigen).

    Der Zeichenvorgang des Quad (Zeile 6) wird zwangslaeufig so lange verzoegert bis der Texture-Upload (Zeile 3) abgeschlossen ist - hier koennte ein Double-Buffer-Mechnismus helfen:
    Du hast zwei Texturen und zeichnest das Quad mit der Textur die im letzten Frame uebertragen worden ist (und die "aktuelle" erst im naechsten). Das Rendering kann so parallel zum Upload passieren.



  • So ich hab mal ein bischen rumgespielt, einmal mit einem PBO und einmal mit glDrawPixels. Und zu meinem erstaunen war glDrawPixels schneller, was dem wiederspricht was man sonst überall ließt. Daher glaube ich das ich den pbo irgendwie falsch benutze. Ich bin auch noch nicht so 100%ig sicher was die extensions genau machen und habs mehr oder weniger von nem tutorial übernommen. Mach ich da noch irgendwie grobe fehler bei der benutzung der PBOS?

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    
    static int pboIndex = 0;
    int nextPboIndex = 0;
    
    pboIndex = (pboIndex + 1) % 2;
    nextPboIndex = (pboIndex + 1) % 2;
    
    // bind the texture and PBO
    glBindTexture(GL_TEXTURE_2D, textureID);
    glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo[pboIndex]);
    
    // copy pixels from PBO to texture object
    // Use offset instead of ponter.
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, 0);
    
    // bind PBO to update pixel values
    glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo[nextPboIndex]);
    
    // map the buffer object into client's memory
    // Note that glMapBufferARB() causes sync issue.
    // If GPU is working with this buffer, glMapBufferARB() will wait(stall)
    // for GPU to finish its job. To avoid waiting (stall), you can call
    // first glBufferDataARB() with NULL pointer before glMapBufferARB().
    // If you do that, the previous data in PBO will be discarded and
    // glMapBufferARB() returns a new allocated pointer immediately
    // even if GPU is still working with the previous data.
    glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, width * height * 4, 0, GL_STREAM_DRAW_ARB);
    GLubyte* ptr = (GLubyte*)glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB);
    if(ptr)
    {
    	memcpy(ptr, surface->getPixels(), width*height*4);
    	// update data directly on the mapped buffer
    	glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB); // release pointer to mapping buffer
    }
    
    // it is good idea to release PBOs with ID 0 after use.
    // Once bound with 0, all pixel operations behave normal ways.
    glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
    
    //////////////////////////////////////////////////////////////////////////
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    // die dynamisch veränderte textur als aktuelle setzen
    glBindTexture(GL_TEXTURE_2D, textureID);
    
    glBegin(GL_QUADS);
    	glTexCoord2f(0.0f, 0.0f);
    	glVertex3f(10, 10, 1.0f);
    
    	glTexCoord2f(1.0f, 0.0f);
    	glVertex3f(width-10, 10, 1.0f);
    
    	glTexCoord2f(1.0f, 1.0f);
    	glVertex3f(width-10, height-10, 1.0f);
    
    	glTexCoord2f(0.0f, 1.0f);
    	glVertex3f(10, height-10, 1.0f);
    glEnd();
    
    glBindTexture(GL_TEXTURE_2D, 0);
    
    //glDrawPixels(width, height, GL_RGBA, GL_UNSIGNED_BYTE, surface->getPixels());
    

    Gruss
    foofel



  • Ich hab mit drawPixels bei 800X600 500fps, ich glaub das reicht mir 🙂

    Gruss


Anmelden zum Antworten