PDA

View Full Version : FBO + multisample and blitting



Filip
05-03-2008, 06:04 PM
Just bought myself a new MBP with Leopard and a shiny 8600gt. Trying to port some SDL/GLEW-based code but my app doesnt't seem to find the fbo multisample and blitting functions... Weird. I googled and got the (hopefully wrong) impression that these functions are not exposed in the current OS/driver. Please tell me it's not true!

OneSadCookie
05-05-2008, 09:24 PM
They are supported on ATI Radeon X1k and Radeon HD 2k cards on 10.5.2 + LGU1, but not on NVidia. http://homepage.mac.com/arekkusu/bugs/GLInfo.html

Filip
05-06-2008, 06:18 AM
Thanks for your answer. Sad that it had to be that way though... *sob* . So we'll have to hope for better drivers then.
I remember this annoying thing with GL and Apple since I last tried to make something useful on the mac a few years back. Then it was the support for FBOs in general and before that it was the extremely late support for vertex and fragment programs.... I really thought those days where over now but I guess I was hoping in vain.
In this case it's extra confusing since Apple was instrumental in the development of the actual extensions ( I mean, just read in the opengl registry...)

Zengar
05-06-2008, 07:14 AM
Apple has some nice extensions though!

Filip
05-06-2008, 09:51 AM
Do you mean that there are some special Apple extensions for multisampled storage and blitting in a renderbuffer? Or that Apple has some nice special extensions for other things? I'm all ears, that sounds interesting...

When you read that it was representatives from Apple and nVidia that wrote the extensions you get a little surprised that the extensions only work on windows with nVidia cards and on mac with ATI-cards... ironic isn't it?

Time to go back to software rendering :)

Zengar
05-06-2008, 05:07 PM
I meant extensions like APPLE_object_purgeable and APPLE_vertex_array_object. It is indeed puzzling that framebuffer_blit only works with ATI, as it was Nvidia who implemented it first on Windows. Still, Mac is not really famous as a graphics development platform, so I don' t think Apple puts such things on high priority.

Filip
05-07-2008, 12:21 PM
Ok, sounds interesting, I guess I should take a look on those. The problem for me is that I'm trying to develop OpenGL software and that platform dependant specialties is boring and unnecessary overhead that I would preferably not have to deal with.

It's not a big deal, I can make a special code path for mac that doesn't allow multisampling. It's just that I love the Mac as a platform and that it feels so incredibly irritating to not be able to make it "best of breed"

arekkusu
05-07-2008, 03:04 PM
You'd need that path anyway, for hardware that doesn't support multisampling. Like the GMA 950.

Filip
05-07-2008, 03:50 PM
True, I guess it's just me wanting simplicity that might not ever be achievable... Anyway, I'll better stop whining and start producing instead. Thank you all :)

James W. Walker
05-07-2008, 05:10 PM
If you want Apple to improve something, request it at bugreport.apple.com (even if it's not technically a bug). Of course that won't make it happen immediately, but maybe when the next big cat comes around...

Filip
05-09-2008, 12:57 AM
Bug/driver issue reported to apple as bug. In the meantime, what do you think would be the fastest workaround to use instead of glBlitFramebufferEXT ? I can live without multisampling in the framebuffer at the moment (during dev) but I still need fast copies from renderbuffer to renderbuffer. Do I have to revert to having textures instead of renderbuffers and use glCopyTexSubImage2D ?

Filip
07-07-2008, 03:47 PM
Just wanted to bump this item. I haven't heard anything from Apple and the 1.5.4 update sadly didn't fix the issue.

Filip
09-22-2008, 03:45 AM
10.5.5 seems to have added the extensions I need. Time to test if they work....

Filip
10-22-2008, 06:43 AM
<s>Ok, I have made a few tests now and blitting now works on nvidia as well. But there are still problems. I can not use multisampling in an FBO and blit to another FBO using float (GL_RGBA16F_ARB) as pixel format. It effectively kills the machine and creates garbled graphics on the screen (even outside the rendering window!) So there is some kind of really nasty bug in there.... In addition it seems like float fbo -> float fbo blitting is messed up as well. Obviously this needs further research.

As for now:

float FBO --(rendered as texture on quad)--> regular framebuffer = ok!
MS float FBO --(blit)--> RGBA8 FBO (rendered as texture on quad) --> regular framebuffer = ok!

float FBO --(blit)--> float FBO --(rendered as texture on quad)--> regular framebuffer = kills machine!
MS float FBO --(blit)--> float FBO (rendered as texture on quad) --> regular framebuffer = Kills machine!

It a little hard to debug since it requires a restart :(
</s>

I have to make more investigations in my own code before I draw any further conclusions. I'll be back!

Filip
10-24-2008, 05:11 AM
Ported my code to windows and it ran flawlessly. Getting more and more disappointed on Apple. :(

arekkusu
10-24-2008, 11:00 AM
So tell them (http://bugreporter.apple.com/).

Filip
10-27-2008, 08:49 AM
Ok, bug submitted.

Filip
11-05-2008, 03:15 AM
I have attached a minimal example of a program that fails on my nvidia-based macs. Feel free to test it and report back :)

The same code has been sent to apple as part of bug report...



#include <stdlib.h>
#include <GLUT/glut.h>

GLuint fbo1;
GLuint fbo1ColorBuffer;
GLuint fbo1DepthBuffer;

GLuint fboFinal;
GLuint fboFinalDepthTexture;
GLuint fboFinalColorTexture;

GLuint textureTarget = GL_TEXTURE_2D;
GLuint bufferWidth = 512;
GLuint bufferHeight = 512;
GLfloat gNearPlane = 0.1f;
GLfloat gFarPlane = 100.0f;
GLuint gWindowWidth = 800;
GLuint gWindowHeight = 800;

GLenum internalType = GL_RGBA16F_ARB;

int useBlit = 1;

/************************************************** ****************************/
void initFBO1(void)
{
/* Generate names */
glGenFramebuffersEXT(1, &amp;fbo1);
glGenRenderbuffersEXT(1, &amp;fbo1ColorBuffer);
glGenRenderbuffersEXT(1, &amp;fbo1DepthBuffer);

/* Bind FBO */
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo1);

/* Bind depth buffer, store as renderbuffer, not texture */
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo1DepthBuffer);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,
bufferWidth, bufferHeight);

/* attach to the fbo */
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT,
fbo1DepthBuffer);

/* Color buffer */
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo1ColorBuffer);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, internalType,
bufferWidth, bufferHeight);

/* attach to the fbo */
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT,
GL_RENDERBUFFER_EXT,
fbo1ColorBuffer);

/* Unbind FBO */
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

}
/************************************************** ****************************/
void initFBOFinal(void)
{
/* Generate names */
glGenFramebuffersEXT(1, &amp;fboFinal);
glGenTextures(1, &amp;fboFinalColorTexture);
glGenTextures(1, &amp;fboFinalDepthTexture);

/* Bind FBO */
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboFinal);

/* Bind depth buffer, store as texture */
//glActiveTexture(GL_TEXTURE0);
glBindTexture(textureTarget, fboFinalDepthTexture);
glTexParameterf( textureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameterf( textureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexParameteri( textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri( textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(textureTarget, 0, GL_DEPTH_COMPONENT, bufferWidth,
bufferHeight, 0, GL_DEPTH_COMPONENT, GL_INT, NULL);

glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
textureTarget, fboFinalDepthTexture, 0);


/* Color buffer */
//glActiveTexture(GL_TEXTURE1);
glBindTexture(textureTarget, fboFinalColorTexture);
glTexParameterf( textureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameterf( textureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexParameteri( textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri( textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(textureTarget, 0, internalType, bufferWidth, bufferHeight,
0, GL_RGBA, GL_FLOAT, NULL);


glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
textureTarget, fboFinalColorTexture, 0);

/* Unbind FBO */
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

}
/************************************************** ****************************/
void initGL(void)
{
glEnable(textureTarget);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glCullFace(GL_BACK);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glDepthMask(GL_TRUE);
}

void reshapeOrtho(unsigned int width, unsigned int height)
{
glViewport(0, 0, (GLint) width, (GLint) height);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluOrtho2D(0, width, 0, height);


}
/************************************************** ****************************/
void display(void)
{
/* spin the teapot to see that all is alive */

static float angle = 0.0f;
angle += 0.1f;

GLuint renderTarget = fboFinal;
if (useBlit)
{
renderTarget = fbo1;
}

/* render to fboFinal */
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, renderTarget);
glPushMatrix();
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -2.0f);
glRotatef(angle, 1.0f, 1.0f, 1.0f);
glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glEnable(GL_COLOR_MATERIAL);
glColor3f(1.0f, 1.0f, 1.0f);
glDisable(textureTarget);
glutSolidTeapot(1.0f);


if (useBlit)
{
printf("Blitting\n");
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, fbo1);
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fboFinal);

glBlitFramebufferEXT(0, 0, bufferWidth, bufferHeight,
0, 0, bufferWidth, bufferHeight,
GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT,
GL_NEAREST);

glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
}



/* render to regular back frame buffer */
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

/* Draw fboFinal color to a texture on a quad */
glPopMatrix();

reshapeOrtho(gWindowWidth, gWindowHeight);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glTranslatef(32.0f, 32.0f, 0.0f);
glColor3f(1.0f, 1.0f, 1.0f);
glActiveTexture(GL_TEXTURE0);
glEnable(textureTarget);
glBindTexture(textureTarget, fboFinalColorTexture);

glBegin(GL_QUADS);
glTexCoord2f( 1.0f, 1.0f );
glVertex3f( bufferWidth, bufferHeight, 0.0f);
glTexCoord2f( 0.0f, 1.0f );
glVertex3f(0, bufferHeight, 0.0f);
glTexCoord2f( 0.0f, 0.0f );
glVertex3f(0,0, 0.0f);
glTexCoord2f( 1.0f, 0.0f );
glVertex3f( bufferWidth,0, 0.0f);
glEnd();

glPopMatrix();

/* return to perspective */
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);


glutSwapBuffers();
}
/************************************************** ****************************/
void reshape(int width, int height)
{
printf("Reshape called\n");
gWindowWidth = width;
gWindowHeight = height;
if (width ==0)
width = 1;
GLfloat h = (GLfloat) height / (GLfloat) width;
glViewport(0, 0, (GLint) width, (GLint) height);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
GLfloat aspect = 1.0f/h;
glLoadIdentity();
gluPerspective(90, aspect, gNearPlane, gFarPlane);
glMatrixMode(GL_MODELVIEW);

}
/************************************************** ****************************/
void idle(void)
{
glutPostRedisplay();
}
/************************************************** ****************************/
int main(int argc, char** argv)
{
glutInit(&amp;argc, argv);

glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(800, 800);

glutCreateWindow("GLUT FBO test");

initGL();
initFBO1();
initFBOFinal();

glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutIdleFunc(idle);

glutMainLoop();
return EXIT_SUCCESS;
}
/************************************************** ****************************/

Filip
12-17-2008, 07:29 AM
Ok, seems like it is solved in 10.5.6.