This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Struggling with EXT_multisampled_render_to_texture on Mali-G76

Hi!
I'm trying to get working multisampled FBO on Samsung Galaxy S10+ with Mali-G76 (Android 10).

Minimal example from spec fails with GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT (8D56) for me.
Tried it with 256x256, 1024x768, 4 samples, GL_MAX_SAMPLES_EXT is 4.
I'm building app with gl2.h and gl2ext.h and ndk-r19c.

OpenGL version: OpenGL ES 3.2 v1.r19p0-01rel0.###other-sha0123456789ABCDEF0### Compatibility profile

My desired setup is:
- bind texture to COLOR_ATTACHMENT_0 (with glFramebufferTexture2DMultisampleEXT)

- bind d24s8 multisampled renderbuffer to both DEPTH_ATTACHMENT and STENCIL_ATTACHMENT (create with glRenderBufferStorageMultisample, bind with glFramebufferRenderBuffer)

Is there any detail I missed about using this extension?

Parents
  • Just for reference, here's a patch on top of the gles3jni example from https://github.com/android/ndk-samples (the same type of code works for the hello-gl2 sample as well) demonstrating how to load the right function pointers, plus how using the non-EXT glRenderbufferStorageMultisample can result in this error (see the #if for good vs non-working code):

    diff --git a/gles3jni/app/src/main/cpp/RendererES3.cpp b/gles3jni/app/src/main/cpp/RendererES3.cpp
    index df71a85..c7366a5 100644
    --- a/gles3jni/app/src/main/cpp/RendererES3.cpp
    +++ b/gles3jni/app/src/main/cpp/RendererES3.cpp
    @@ -15,6 +15,8 @@
      */
     
     #include "gles3jni.h"
    +#include <GLES2/gl2ext.h>
     #include <EGL/egl.h>
     
     #define STR(s) #s
    @@ -117,6 +119,55 @@ bool RendererES3::init() {
         glVertexAttribPointer(OFFSET_ATTRIB, 2, GL_FLOAT, GL_FALSE, 2*sizeof(float), 0);
         glEnableVertexAttribArray(OFFSET_ATTRIB);
         glVertexAttribDivisor(OFFSET_ATTRIB, 1);
    +#if 1
    +       GLsizei width  = 256;
    +       GLsizei height = 256;
    +       GLint samples;
    +       glGetIntegerv(GL_MAX_SAMPLES_EXT, &samples);
    +
    +    PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT =            (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)eglGetProcAddress("glRenderbufferStorageMultisampleEXT");
    +    PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC glFramebufferTexture2DMultisampleEXT =(PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC)eglGetProcAddress("glFramebufferTexture2DMultisampleEXT");
    +
    +       /* Create multisampled depth renderbuffer */
    +       GLuint depthbuffer;
    +       glGenRenderbuffers(1, &depthbuffer);
    +       glBindRenderbuffer(GL_RENDERBUFFER, depthbuffer);
    +#if 0 // OK
    +       glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, samples, 
    +               GL_DEPTH_COMPONENT16, width, height);
    +#else // Fails
    +       glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, 
    +               GL_DEPTH_COMPONENT16, width, height);
    +#endif
    +       glBindRenderbuffer(GL_RENDERBUFFER, 0);
    +
    +       /* Create RGBA texture with single mipmap level */
    +       GLuint texture;
    +       glGenTextures(1, &texture);
    +       glBindTexture(GL_TEXTURE_2D, texture);
    +       glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, 
    +               GL_UNSIGNED_SHORT_4_4_4_4, NULL);
    +       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    +       glBindTexture(GL_TEXTURE_2D, 0);
    +
    +       /* Create framebuffer object, attach texture and depth renderbuffer */
    +       GLuint framebuffer;
    +       glGenFramebuffers(1, &framebuffer);
    +       glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
    +       glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 
    +               GL_RENDERBUFFER, depthbuffer);
    +       glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, 
    +               GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0, samples);
    +
    +       /* handle unsupported cases */
    +       if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != 
    +                       GL_FRAMEBUFFER_COMPLETE)
    +       {
    +        ALOGE("FBO incomplete: %x", glCheckFramebufferStatus(GL_FRAMEBUFFER));
    +       } else ALOGE("FBO OK");
    +
    +    checkGlError("FBO");
    +#endif
     
         ALOGV("Using OpenGL ES 3.0 renderer");
         return true;
    

    It might be good to double-check any function pointer loader you might be using isn't grabbing the wrong function.

Reply
  • Just for reference, here's a patch on top of the gles3jni example from https://github.com/android/ndk-samples (the same type of code works for the hello-gl2 sample as well) demonstrating how to load the right function pointers, plus how using the non-EXT glRenderbufferStorageMultisample can result in this error (see the #if for good vs non-working code):

    diff --git a/gles3jni/app/src/main/cpp/RendererES3.cpp b/gles3jni/app/src/main/cpp/RendererES3.cpp
    index df71a85..c7366a5 100644
    --- a/gles3jni/app/src/main/cpp/RendererES3.cpp
    +++ b/gles3jni/app/src/main/cpp/RendererES3.cpp
    @@ -15,6 +15,8 @@
      */
     
     #include "gles3jni.h"
    +#include <GLES2/gl2ext.h>
     #include <EGL/egl.h>
     
     #define STR(s) #s
    @@ -117,6 +119,55 @@ bool RendererES3::init() {
         glVertexAttribPointer(OFFSET_ATTRIB, 2, GL_FLOAT, GL_FALSE, 2*sizeof(float), 0);
         glEnableVertexAttribArray(OFFSET_ATTRIB);
         glVertexAttribDivisor(OFFSET_ATTRIB, 1);
    +#if 1
    +       GLsizei width  = 256;
    +       GLsizei height = 256;
    +       GLint samples;
    +       glGetIntegerv(GL_MAX_SAMPLES_EXT, &samples);
    +
    +    PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT =            (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)eglGetProcAddress("glRenderbufferStorageMultisampleEXT");
    +    PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC glFramebufferTexture2DMultisampleEXT =(PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC)eglGetProcAddress("glFramebufferTexture2DMultisampleEXT");
    +
    +       /* Create multisampled depth renderbuffer */
    +       GLuint depthbuffer;
    +       glGenRenderbuffers(1, &depthbuffer);
    +       glBindRenderbuffer(GL_RENDERBUFFER, depthbuffer);
    +#if 0 // OK
    +       glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, samples, 
    +               GL_DEPTH_COMPONENT16, width, height);
    +#else // Fails
    +       glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, 
    +               GL_DEPTH_COMPONENT16, width, height);
    +#endif
    +       glBindRenderbuffer(GL_RENDERBUFFER, 0);
    +
    +       /* Create RGBA texture with single mipmap level */
    +       GLuint texture;
    +       glGenTextures(1, &texture);
    +       glBindTexture(GL_TEXTURE_2D, texture);
    +       glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, 
    +               GL_UNSIGNED_SHORT_4_4_4_4, NULL);
    +       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    +       glBindTexture(GL_TEXTURE_2D, 0);
    +
    +       /* Create framebuffer object, attach texture and depth renderbuffer */
    +       GLuint framebuffer;
    +       glGenFramebuffers(1, &framebuffer);
    +       glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
    +       glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 
    +               GL_RENDERBUFFER, depthbuffer);
    +       glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, 
    +               GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0, samples);
    +
    +       /* handle unsupported cases */
    +       if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != 
    +                       GL_FRAMEBUFFER_COMPLETE)
    +       {
    +        ALOGE("FBO incomplete: %x", glCheckFramebufferStatus(GL_FRAMEBUFFER));
    +       } else ALOGE("FBO OK");
    +
    +    checkGlError("FBO");
    +#endif
     
         ALOGV("Using OpenGL ES 3.0 renderer");
         return true;
    

    It might be good to double-check any function pointer loader you might be using isn't grabbing the wrong function.

Children