I am currently implementing occlusion queries with auxiliary FBO in the freeGlut based application, when I encountered a problem.
The tutorial of FBOs (https://www.opengl.org/wiki/Framebuffer_Object_Examples#The_main_framebuffer) says following:
Can you bind the main framebuffer’s depth buffer as a depth buffer for your FBO? No. You must create a depth texture or a depth Render Buffer.
Does GL 3.0 allow using the main depth buffer? No.
How ever, when after occlusion queries, when I dump content of color and depth buffers, the result indicate the main and auxiliary depth buffers are some how shared :O
Main FBO:
Left image: color buffer, right image: 16 bit depth buffer as seen by a 8 bit viewer.
Auxiliary FBO:
Left image: color buffer, right image: 16 bit depth buffer as seen by a 8 bit viewer.
As seen from images above, the auxiliary FBO buffers has
a) aux FBO color buffer has either used main(?) depth buffer for depth test or the aux depth buffer is not cleared and content has copied from main FBO
b) aux FBO depth buffer has not been cleared before updating
have I done something wrong or have I hit by a driver bug??
The freeGlut and openGL initialization:
glutInitContextVersion( 3, 0 );
glutInitContextFlags( GLUT_DEBUG );
glutInitContextProfile( GLUT_CORE_PROFILE );
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH | GLUT_STENCIL | GLUT_ACCUM );
The auxiliary FBO initialization (based on this - https://www.opengl.org/wiki/Framebuffer_Object_Examples#Quick_example.2C_render_to_buffer_.28p-buffer_replacement.29):
s->exact_visibility->data.aux_framebuffer_id = 0;
glGenFramebuffers( 1, &s->exact_visibility->data.aux_framebuffer_id );
assert( s->exact_visibility->data.aux_framebuffer_id != 0 );
glBindFramebuffer( GL_FRAMEBUFFER, s->exact_visibility->data.aux_framebuffer_id );
#if defined(DEBUG_OCCLUSION_QUERY)
glGenRenderbuffers( 1, &s->exact_visibility->data.aux_colorbuffer_id );
glBindRenderbuffer( GL_RENDERBUFFER, s->exact_visibility->data.aux_colorbuffer_id );
glRenderbufferStorage( GL_RENDERBUFFER, GL_RGBA8, INITIAL_BUFFER_SIZE, INITIAL_BUFFER_SIZE );
glFramebufferRenderbuffer( GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, s->exact_visibility->data.aux_colorbuffer_id );
#endif
glGenRenderbuffers( 1, &s->exact_visibility->data.aux_depthbuffer_id );
glBindRenderbuffer( GL_RENDERBUFFER, s->exact_visibility->data.aux_depthbuffer_id );
#if defined(DEBUG_OCCLUSION_QUERY)
glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, INITIAL_BUFFER_SIZE, INITIAL_BUFFER_SIZE );
#else
glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT, INITIAL_BUFFER_SIZE, INITIAL_BUFFER_SIZE );
#endif
glFramebufferRenderbuffer( GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, s->exact_visibility->data.aux_depthbuffer_id );
GLenum const status = glCheckFramebufferStatus( GL_DRAW_FRAMEBUFFER );
switch( status )
{
case GL_FRAMEBUFFER_COMPLETE:
break;
...
Occlusion query rendering:
glBindFramebuffer( GL_FRAMEBUFFER, s->exact_visibility->data.aux_framebuffer_id );
glViewport( 0, 0, INITIAL_BUFFER_SIZE, INITIAL_BUFFER_SIZE );
/* X+ */
static struct vector3 const dir_Xp = { 1.0f, 0.0f, 0.0f };
static struct vector3 const up_Y = { 0.0f, 1.0f, 0.0f };
render_exact_set_camera( s, spot, &dir_Xp, &up_Y );
if( render_exact_direction( s, visible_meshes, visible_dyns, mesh_cell, dyn_cell ) != res_ok )
{
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
return res_failed;
}
...
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
Function render_exact_direction():
#if defined(DEBUG_OCCLUSION_QUERY)
{
GLint tmp1 = 0;
glGetIntegerv( GL_FRAMEBUFFER_BINDING, &tmp1 );
assert( tmp1 != 0 );
GLint tmp2 = 0;
glGetFramebufferAttachmentParameteriv( GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &tmp2 );
assert( tmp2 != 0 );
GLint tmp3 = 0;
glGetFramebufferAttachmentParameteriv( GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &tmp3 );
assert( tmp3 != 0 );
assert( tmp2 == tmp3 );
}
#endif
#if 0
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
glClear( GL_DEPTH_BUFFER_BIT );
glBindFramebuffer( GL_FRAMEBUFFER, s->exact_visibility->data.aux_framebuffer_id );
#endif
#if defined(DEBUG_OCCLUSION_QUERY)
glClearColor( 0.5f, 0.5f, 0.5f, 0.0f );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
#else
glClear( GL_DEPTH_BUFFER_BIT );
#endif
if( render_exact_hw_meshes( s, visible_meshes, mesh_cell ) != res_ok )
{
return res_failed;
}
...
And finally function exact_render_textured_mesh() called by function render_exact_hw_meshes()
...
#if defined(DEBUG_OCCLUSION_QUERY)
{
GLint tmp1 = 0;
glGetIntegerv( GL_FRAMEBUFFER_BINDING, &tmp1 );
assert( tmp1 != 0 );
GLint tmp2 = 0;
glGetFramebufferAttachmentParameteriv( GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &tmp2 );
assert( tmp2 != 0 );
GLint tmp3 = 0;
glGetFramebufferAttachmentParameteriv( GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &tmp3 );
assert( tmp3 != 0 );
assert( tmp2 == tmp3 );
}
#endif
render_draw_triangles( s, m->ntriangles, m->indices );
As seen from code samples, the auxiliary depth buffer IS cleared before rendering and to make thinks even nastier, if the main depth buffer is cleared too, the result is different (it shouldn’t affect the result). If the state menagement is to trust, it thinks that
a) auxiliary FBO is binded before rendering
b) a depth buffer is attached to FBO
and
c) the read and write depth buffers are the same
This effect is present in two desktops I have tested:
- Ubuntu 14.04, nvidia-331-updates, GeForce GTX 550 Ti/PCIe/SSE2
and - Ubuntu 14.04, nvidia-331, Quadro FX 1800M/PCIe/SSE2
Any thoughts what could be wrong?