PDA

View Full Version : GL_EXT_framebuffer_multisample



devdept
03-01-2009, 05:40 AM
Hi All,

We are collectiong a number of issues on this hardware using the GL_EXT_framebuffer_multisample extension. The first one is the following:

1) If we create a multisample pixel format and don't call glEnable(GL_MULTISAMPLE_ARB) the FSAA is active and cannot be deactivated even adding a glDisable(GL_MULTISAMPLE_ARB) call

We are following these instructions http://www.opengl.org/wiki/index.php/GL_EXT_framebuffer_multisample and using a RGB 24bit bitmap, not a RGBA 32bit one.

Why?

Thanks,

Alberto

ZbuffeR
03-01-2009, 07:05 AM
Is this behaviour tied to one particular hardware, driver, or vendor ?

devdept
03-01-2009, 08:23 AM
Hi ZbuffeR,


No, we and the customer are experiencing this issue on multiple nvidia cards. Do you think that posting the code would help to spot any discutible command sequence?


Thanks,

Alberto

Don't Disturb
03-01-2009, 09:45 AM
EXT_framebuffer_multisample is not related to ARB_multisample. The former allows you to create multisampled framebuffer objects, the latter is legacy cruft that I recommend you don't use at all.

martinsm
03-01-2009, 10:12 AM
1) If we create a multisample pixel format and don't call glEnable(GL_MULTISAMPLE_ARB) the FSAA is active and cannot be deactivated even adding a glDisable(GL_MULTISAMPLE_ARB) call

As Don't Disturb already said - this is very normal. glEnable/Disable(GL_MULTISAMPLE_ARB) doesn't influence rendering to multisample renderbuffers in any way.

glEnable/Disable(GL_MULTISAMPLE_ARB) only enables multisampling on 0 framebuffer if you have created OpenGL context with multisampling (GL/WGL/GLX_ARB_multisample extension).

devdept
03-01-2009, 01:05 PM
Guys, you're right. The truth is we have problems in both areas.

Lets start with FSAA. We use this code to get a multisample pixel format. As far as I know you need to call glEnable/Disable(GL_MULTISAMPLE_ARB) to activate deactivate it, why we always see FSAA even after calling glDisable(GL_MULTISAMPLE_ARB) on NVidia geForce 8400???



if (IsExtensionSupported(new string[] {"GL_ARB_multisample", "GLX_ARB_multisample", "WGL_ARB_multisample"}) == false)

return 0;

int[] iAttributes = new int []
{
WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
WGL_COLOR_BITS_ARB, 24,
WGL_ALPHA_BITS_ARB, 8,
WGL_DEPTH_BITS_ARB, 24,
WGL_STENCIL_BITS_ARB, 0,
WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
WGL_SAMPLES_ARB, 0,
0, 0
};

for (samples = 16; samples > 0; samples /= 2)
{

iAttributes[17] = samples;

int pixelFormat;
uint numFormats;
float[] fAttributes = new float[2];

bool bStatus = ChoosePixelFormatARB(testHdc, iAttributes, fAttributes, 1, out pixelFormat, out numFormats);

if (bStatus && numFormats > 0)
{
return pixelFormat;
}

}

return 0;

martinsm
03-01-2009, 02:35 PM
There is possibility that you have this setting forcefully enabled in driver settings.

devdept
03-02-2009, 12:46 AM
No, just checked. I currently see:

Antialiasing - Gamma correction = Off
Antialiasing - Mode = Application controlled
Antialiasing - Setting = Application controlled
Antialiasing - Transpaarency = Off

I also downloaded another sample app for antialiasing and works like ours if you call glDisable(GL_MULTISAMPLE_ARB): you still see some sort of antialiasing on the OpenGL viewport. This sample app also support CSAA (GL_NV_multisample_coverage) and disabling this one we get a standard jagged viewport. Should we prefer this AA on NVidia cards instead of the GL_ARB_multisample?

Thanks,

Alberto

P.S.: Even the NVidia driver is updated to the latest version and we work on Windows Vista

devdept
03-02-2009, 04:36 AM
The second issue is a problem (overlapped copy of a different area of the viewport) on getting a bitmap from the MSAA pixel format. Here is the code, do you see something strange? On the ATI hardware this works perfectly...


uint fb = glGenFramebuffersEXT();
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);

cb = glGenRenderbuffersEXT();
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, cb);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, width, height);

db = glGenRenderbuffersEXT();
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, db);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, width, height);

glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, cb);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, db);

int status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);

ReportFboStatus();

if (isFsaaAvailable && GL_EXT_framebuffer_multisample)
{

uint fb1 = glGenFramebuffersEXT();
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb1);

cb1 = glGenRenderbuffersEXT();
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, cb1);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, width, height);

GL_RENderbufferStorageMultisampleEXT(GL_RENDERBUFF ER_EXT, samples, GL_RGB8, width, height);

db1 = glGenRenderbuffersEXT();
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, db1);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, width, height);

GL_RENderbufferStorageMultisampleEXT(GL_RENDERBUFF ER_EXT, samples, GL_DEPTH_COMPONENT24, width, height);

glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, cb1);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, db1);

int status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);

ReportFboStatus();

//Bind the MS FBO
glBindFramebufferEXT(gl.READ_FRAMEBUFFER_EXT, fb1);
//Bind the standard FBO
glBindFramebufferEXT(gl.DRAW_FRAMEBUFFER_EXT, fb);
gl.BlitFramebufferEXT(0, 0, posterWidth, posterHeight, 0, 0, posterWidth, posterHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);

}

DrawScene();

glReadPixels(0, 0, width, height, GL_BGR, GL_UNSIGNED_BYTE, bitmapData.Scan0);

glDeleteTexture(cb);
glDeleteRenderbuffersEXT(db);

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glDeleteFramebuffersEXT(fb);

if (isFsaaAvailable && GL_EXT_framebuffer_multisample)
{
glDeleteTexture(colorBuf);
glDeleteRenderbuffersEXT(depthBuf);

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glDeleteFramebuffersEXT(fb);
}

martinsm
03-02-2009, 05:17 AM
Is really fb1 framebuffer created correctly? Does glCheckFramebufferStatusEXT returns GL_FRAMEBUFFER_COMPLETE_EXT ?
GL_EXT_framebuffer_multisample says that if

The value of RENDERBUFFER_SAMPLES_EXT is the same for all attached images
is false, then GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT error will be returned.

And you are attaching multisampled color renderbuffer and non-multisample depth renderbuffer to framebuffer.
Create depth renderbuffer with same samples as color renderbuffer.

Also - do you use glReadPixels when fb1 is active? Because this also is forbbiden. Quoting EXT_framebuffer_multisample spec:

"ReadPixels generates INVALID_OPERATION if READ_FRAMEBUFFER_BINDING (section 4.4) is non-zero, the read framebuffer is framebuffer complete, and the value of SAMPLE_BUFFERS for the read framebuffer is greater than zero.

devdept
03-02-2009, 05:41 AM
Is really fb1 framebuffer created correctly? Does glCheckFramebufferStatusEXT returns GL_FRAMEBUFFER_COMPLETE_EXT ?
GL_EXT_framebuffer_multisample says that if

The value of RENDERBUFFER_SAMPLES_EXT is the same for all attached images
is false, then GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT error will be returned.Yes, both FBO return GL_FRAMEBUFFER_COMPLETE_EXT.


And you are attaching multisampled color renderbuffer and non-multisample depth renderbuffer to framebuffer.
Create depth renderbuffer with same samples as color renderbuffer.
How you can say this?


Also - do you use glReadPixels when fb1 is active? Because this also is forbbiden. Quoting EXT_framebuffer_multisample spec:

"ReadPixels generates INVALID_OPERATION if READ_FRAMEBUFFER_BINDING (section 4.4) is non-zero, the read framebuffer is framebuffer complete, and the value of SAMPLE_BUFFERS for the read framebuffer is greater than zero. Should I destroy this before the glReadPixel()?


Thanks,

Alberto

martinsm
03-02-2009, 05:54 AM
How you can say this?
What exactly I say wrong there? EXT_framebuffer_multisample specification says that all attachments should have same samples. It is strange that you are getting fb_complete_ext. That is why I suggest you to try to create depth renderbuffer with same sample count.


Should I destroy this before the glReadPixel()?
If you don't read pixels from multisampled fbo then it doesn't matter. I'm just asking from which framebuffer are you reading pixels. Because you can not read them from multisampled fbo.

devdept
03-02-2009, 06:29 AM
GL_RenderbufferStorageMultisampleEXT(GL_RENDERBUFF ER_EXT, samples, GL_RGB8, width, height);

GL_RenderbufferStorageMultisampleEXT(GL_RENDERBUFF ER_EXT, samples, GL_DEPTH_COMPONENT24, width, height);

These two calls has the same samples value, it is a variable.

We need to read pixels to get an antialiased bitmap and do:


//Bind the MS FBO
glBindFramebufferEXT(gl.READ_FRAMEBUFFER_EXT, fb1);
//Bind the standard FBO
glBindFramebufferEXT(gl.DRAW_FRAMEBUFFER_EXT, fb);
gl.BlitFramebufferEXT(0, 0, posterWidth, posterHeight, 0, 0, posterWidth, posterHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);

DrawScene();

gl.ReadPixels(0, 0, width, height, GL_BGR, GL_UNSIGNED_BYTE, bitmapData.Scan0);

What do you think? Should we destroy the ms FBO *before* the glReadPixel() call?


Thanks,

Alberto

martinsm
03-02-2009, 11:02 AM
Oh, sorry. now I see how you are creating renderbuffers. I missed some lines reading code in that small code box :)
In this case you don't need to call glRenderbufferStorageEXT before glRenderbufferStorageMultisampleEXT. Last one automatically creates correct framebuffer storage. I somehow saw only glRenderbufferStorageEXT call not the MultisampleEXT one.


What do you think? Should we destroy the ms FBO *before* the glReadPixel() call?
If you are reading pixels from non-multisampled fbo, then it doesn't matter if you destroy multisampled fbo before or after. As long as correct fbo is bound when you are calling glReadPixels then everything should be fine.

Have you tried checking error value with glGetError function after every OpenGL call? I recommend using GLintercept which do it for you automatically.

devdept
03-02-2009, 01:04 PM
I think the best solution would be to use CSAA for NVidia and MSAA for others.

I gave a look to NVidia developer site and I found only references to CSAA approach. I would also hope the code above to get an anti-aliased bitmap will work with CSAA instead of MSAA.


Thanks also for the hint on glRenderbufferStorageEXT()!

Alberto

devdept
03-02-2009, 02:18 PM
Yes, as suspected while using CSAA on NVIDIA works perfectly, we cannot use the code above (http://www.opengl.org/wiki/index.php/GL_EXT_framebuffer_multisample) to get an AntiAliased bitmap.

Do you know why or any workaround?

Thanks,

Alberto

martinsm
03-02-2009, 02:43 PM
What's CSAA?
Your code works fine on my 8400M GS. I can get antialised image with MSAA FBO -> blit -> noMSAA FBO -> readPixels with no problems.

devdept
03-03-2009, 12:10 AM
What's CSAA?
http://developer.nvidia.com/object/coverage-sampled-aa.html

Don't you have a residual AntiAliasing even with glDisable(GL_MULTISAMPLE_EXT)?


Thanks,

Alberto

martinsm
03-03-2009, 02:32 AM
Sorry, my english is not so good - what does "residual antialiasing" means?

Here is test program with source code that will render triangle to simple renderbuffer, msaa renderbuffer and csaa renderbuffer. Then it will read image from each framebuffer and save to tga file. I've included also tga images in Release folder that was generated on my laptop with Geforce 8400M GS.

Download it here: http://www.box.net/shared/ol8rz1qg8p

devdept
03-03-2009, 03:06 AM
Thanks martinism, I will study your program and let you know.


Sorry, my english is not so good - what does "residual antialiasing" means?
I was meaning that with MSAA on this geForce 8400 you can switch AA off once you created a MultiSample pixel format.

martinsm
03-03-2009, 03:10 AM
Hm.. yes, actually it disables multisampling. I thought it should not...

devdept
03-03-2009, 03:48 AM
Take a closer look to the picture, is it AntiAliased or not?

On our machines the MSAA never switches off completely.

martinsm
03-03-2009, 04:40 AM
Yes, it is not antialiased.
Here are three files which I get when I put glDisable(GL_MULTISAMPLE) before glBegin call: http://www.box.net/shared/l2p0yh9p3p

Here are mangified fragments of these files: http://img201.imageshack.us/img201/953/msaa.png

Dark Photon
03-03-2009, 05:41 AM
Yes, it is not antialiased.
Here are three files which I get when I put glDisable(GL_MULTISAMPLE) before glBegin call: http://www.box.net/shared/l2p0yh9p3p

Here are mangified fragments of these files: http://img201.imageshack.us/img201/953/msaa.png

There are two pieces to MSAA/CSAA. One is the multisample "rasterization". The other is the multisample "downsample filtering". From what I've seen, glDisable(GL_MULTISAMPLE) only switches off the former, not the latter, which seems to be a function of the rendering surface you've allocated.

See this past post (http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Board=3&Number=232174&Searchpage=1&Main=46189&Words=msaa+Dark+Photon&topic=0&Search=true#Post232174) for images.

devdept
03-03-2009, 05:48 AM
Hi Dark Photon,

I saw the images of the post you provided (they show exactly what I am talking about). Do you confirm that on NVidia GPU using CSAA is a better choice and the only way to disable FSAA using gl.Disable(GL_MULTISAMPLE_EXT)?

We saw some samples searching the net that provide MSAA code for ATI and CSAA for NVidia. This way you can enable/disable corectly the AntiAliasing.

Thanks,

Alberto

devdept
03-03-2009, 11:41 AM
martinism,

I see in your example you are using GL_RGBA8, can the reason be that we are trying to read a RGB and not RGBA bitmap?

Is RGBA mandatory in this case?


Thanks,

Alberto

martinsm
03-03-2009, 03:10 PM
It doesn't matter. I changed everything to 3 components (GL_RGB8, GL_BGR, ...). Nothing changed - msaa still works, and can be turned off with glDisable.

devdept
03-04-2009, 01:33 AM
You are right, studing your code and rewriting ours now we managed to get RGB and AntiAliased bitmaps.

THANKS SO MUCH.

The only open issue remains the antialiasing not switching on completely on MSAA. In your program is impossible to see because in this case we need to see the viewport not only to generate a raster image.

Thanks again,

Alberto

Dark Photon
03-04-2009, 05:13 AM
I saw the images of the post you provided (they show exactly what I am talking about). Do you confirm that on NVidia GPU using CSAA is a better choice and the only way to disable FSAA using gl.Disable(GL_MULTISAMPLE_EXT)?

I haven't tried that. However, AFAIK how downsampling is done by vendors is <u>not</u> standardized at all, so capitalizing on what you're seeing could break the next driver version...

Best to use a single-sample FBO if you don't want any MSAA/CSAA/SSAA.

devdept
03-04-2009, 05:27 AM
Sorry Dark Photon,

I don't understand your post. We need a way to have full screen antialising on and off. As you reported in the post you referenced above, there is no way to disable it completely on NVidia geForce.

What's wrong in using CSAA for NVidia and MSAA in ATI?


Thanks,

Alberto

Dark Photon
03-04-2009, 06:16 AM
I don't understand your post....What's wrong in using CSAA for NVidia and MSAA in ATI?

Nothing. Feel free. HOWEVER, your argument for using CSAA on NVidia over MSAA was simply that you don't get any apparent antialiasing effects when you disable multisample rasterization. But how they do the downsampling could change the next driver version, which would hit you if you're still rendering to a multisampled framebuffer. They could change their filter taps and you're hosed. Besides CSAA limits you to GeForce 8+.


We need a way to have full screen antialising on and off. As you reported in the post you referenced above, there is no way to disable it completely on NVidia geForce.

I didn't say that. What I said is that glDisable( GL_MULTISAMPLE ) apparently doesn't do it if your framebuffer is multisampled.

You could always reallocate the window to have the correct number of samples when switching AA on/off. You could also render to FBO (single or multisample as needed for AA) and blit that to the window when done.

devdept
03-04-2009, 06:24 AM
Ok, thanks. BTW do you know exacly the difference between CSAA and MSAA and why with MSAA on NVidia you get a 'residual' antialiasing when you magnify the viewport contents?

Thanks again,

Alberto

Dark Photon
03-04-2009, 06:34 AM
Ok, thanks. BTW do you know exacly the difference between CSAA and MSAA...

Not first-hand (I don't work for NVidia ;-), but from what I've read, CSAA and MSAA are fundamentally the same thing. The only catch is that with MSAA you have a separate color "value" per subsample (e.g. 4X MSAA = 4 RGBA colors per pixel), and with CSAA you store a color "index" instead (4X MSAA = 4 color indices). These indices look up into a per-pixel color table which is smaller than the number of samples (e.g. 4X CSAA might have say maximum 2 color values per pixel in that color table, and each of the 4 subsamples could have a color index of 0 or 1).

This saves memory space and bandwidth. It works just as good as MSAA in nearly all cases (when the color table doesn't overflow). But it fails when more colors are needed to represent the subsample colors than space exists for in the per-pixel color table (e.g. where you have a number of edges running through a single pixel, and thus you prob need more than a few subsample colors).


and why with MSAA on NVidia you get a 'residual' antialiasing when you magnify the viewport contents
AFAIK, that's totally an NVidia-driver-internal-behavior thing.

It appears when multisample rasterization is disabled with MSAA, they don't disable MSAA downsample filtering, and the filter taps for a pixel touch samples in adjacent pixels.

Why this same thing doesn't happen for CSAA is NVidia-internals as well. Maybe they are disabling downsample filtering with rasterization in CSAA but not MSAA. Maybe they're not but just using a different filter kernel in CSAA than in MSAA that doesn't have taps in the samples for adjacent pixels. Who knows.

We're in the land of vendor- and driver-specific behavior. I say driver for a number of reasons, not the least of which is a few months back NVidia totally changed their FSAA mode linup in their drivers. You don't want to do something that makes you dependent on vendor or driver-specific oddities.

devdept
03-04-2009, 06:56 AM
Thanks so much again Dark Photon, your explanation is perfect!