kayahr
kayahr

Reputation: 22050

How to determine the maximum number of supported multisample samples

I'm using SDL 2 for an OpenGL based application and I'm currently implementing anti-aliasing with code like this:

SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, samples);

But I don't want to hardcode the antialising level so I want to let the user choose the value from a list of valid values. The problem is I have no idea how to find out which values are supported on the users machine. On my gaming machine I can choose a maximum value of 16 but on my laptop I can only choose 4. Any higher setting triggers the error message Couldn't find matching GLX visual.

So how can I find out what maximum value I can use for the SDL_GL_MULTISAMPLESAMPLES attribute?

Upvotes: 3

Views: 4839

Answers (4)

Mateusz Grzejek
Mateusz Grzejek

Reputation: 12088

In OpenGL, one could stumble across the "multi-sampling" term in two main contexts:

1. Default framebuffer (window) creation. This one gets done either via a dedicated library like GLFW or a native system API. In case of the latter, for example, functions like wglChoosePixelFormatARB (Windows/WGL) or glXChooseVisual (Linux/GLX) can be used to determine the supported cofiguration and create the drawable with the desired format. GLFW, on the other hand, gives you a dedicated function to request the number of samples: glfwWindowHint(GLFW_SAMPLES, num_of_samples_requested). Similar functions exist in other frameworks like SDL.

To get the allowed limits for sample count, you either need to use appropriate sys/library functions or enumerate over typical sample counts (1, 2, 4, 8, etc.) and check if they are allowed.

Creating a system window with MS-enabled framebuffer equals using multisample anti-aliasing when rendering to that window (i.e. framebuffer '0').

2. Texture creation/management. In this context we understand textures with one of the _MULTISAMPLE formats (GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_2D_ARRAY_MULTISAMPLE). Each logical image in such a texture then contains multiple samples per pixel, also enabling multi-sampled rendering. The difference is that they are usual (in a way) GL textures, so you can

  • copy the data between them (but only if the number of samples match - otherwise functions like glCopyImageSubData will fail with GL_INVALID_OPERATION),
  • fetch those multiple samples in a shader,
  • resolve them via glBlitFramebuffer() using two textures/buffers: a multi-sampled source and a non-MS target (*).

To get limits for sample count for textures, you can use a dedicated glGet parameters: GL_MAX_COLOR_TEXTURE_SAMPLES (color textures) and GL_MAX_DEPTH_TEXTURE_SAMPLES (depth or combined depth-stencil textures/buffers) for desktop GL and GL_MAX_SAMPLES for the ES 2.0+.

An important difference is also the limit: if you query GL_MAX_COLOR_TEXTURE_SAMPLES on a relatively modern GPU, you can even see a value like 32. For system windows, though, limits are sometimes more restricted and I remember having troubles with going higher than 4 samples on certain HW/drivers.


(*) This is exactly what happens under the hood for system windows as well - in case of double-bufferred, MSAA-enabled drawable, one of the buffers (back buffer) is a multi-sampled one and the other one (front buffer) is not. When a buffer swap happens, contents of the back buffer are copied to the front buffer, causing effectively an automatic resolving blit.

Upvotes: 0

Multivac
Multivac

Reputation: 56

just ask (wglChoosePixelFormatARB | glXChooseVisual )! if they don`t support you desired sample count, they dont return a pixelformat.

        const int piAttribIList[] =
    {
        WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
        WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
        WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
        WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
        WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
        WGL_COLOR_BITS_ARB, 32,
        WGL_DEPTH_BITS_ARB, 24,
        WGL_STENCIL_BITS_ARB, 8,
        WGL_SAMPLE_BUFFERS_ARB, 1,
        WGL_SAMPLES_EXT, 4,
        0 // zero term
    };
    const float pfAttribFList[] = { 0.0f };

    int piFormats;
    unsigned int nNumFormats;
    assert(wglChoosePixelFormatARB(m_Ptr->m_hDC, piAttribIList, pfAttribFList, 1, &piFormats, &nNumFormats));

if nNumFormats is > 0 then WGL_SAMPLES_EXT, 4, is supported

if nNUmFOrmats is 0 WGL_SAMPLES_EXT == 4 is not supported

there is no need to create fake contexts

on my opengl, latest nvidia drvier. glGetIntegerv ( GL_MAX_SAMPLES, &maxSamples ); gives me 32 but i cant create a context with 32 mutlisample maybe 32 is true for offscreenframebuffers.

Upvotes: 2

S.Clem
S.Clem

Reputation: 521

This is a 4 years old question, but in case people lands here: There is a way to get this piece of information. You have to use glGetIntegerv ( GL_MAX_SAMPLES, &maxSamples ); but unfortunately, you can only do this once your window has been created. So you have to create a temporary window without multisampling, get all required information from openGL, then close this window and create the real one.

If you want to hide this temporary window creation to the user, you can create it using the SDL_WINDOW_HIDDEN flag. A "loading screen" can also do the trick:

  • Open a "loading application data..." screen that does not require antialiasing.
  • Use it to call glGetIntegerv and other things like that.
  • Load your application data, textures...
  • Close this window and open the final one with antialiasing. :)

Upvotes: 4

TPS
TPS

Reputation: 2137

As multisampling is a pixel format attribute I don't think there is a way to query it from OpenGL. You will probably need to do this on an operating specific level although I am not sure how you would fit that in with using SDL.

Upvotes: 3

Related Questions