We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
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 profileMy 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?
Hi Ramil,
I notice you're using glRenderBufferStorageMultisample which is, confusingly, different to glRenderBufferStorageMultisampleEXT. I'd try switching to the EXT variant here and hopefully that helps.
Cheers,Christian
Thanks for reply, I actually use glRenderBufferStorageMultisamleEXT, sorry, my bad, that's a typo.
Ah, OK. :) Did I interpret it right you're using pretty much the same code as in the spec example? I can try to repro on my side; in general I know this functionality works (as there are games relying on it) -- but wondering if some obscure things is causing an issue with that specific code. (Eg GL_UNSIGNED_SHORT_4_4_4_4 jumps out to me as 'not common' -- so could try something different there.)
I'll let you know what I find; please shout if your code is different to the spec example.
Thank you!I've tried with GL_UNSIGNED_SHORT_4_4_4_4 when trying to do copy-paste from spec and GL_UNSIGNED_BYTE before that for our regular rgba8888 case.Anothing thing that came to my mind: I'm using EGL with EGL_SAMPLES, 4 for main backbuffer which maybe also uses this extension.If copy-pasted example from spec works fine for you - that will be very interesting to find out the truth! :)
I've tested the spec example on a few devices and drivers now, including a S10 with R19, but so far not been able to hit any problems (glCheckFramebufferStatus return GL_FRAMEBUFFER_COMPLETE). Is it possible to share a reproducer APK for this? Happy to have a look to try to debug what goes wrong.
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.
I'll check it and answer tomorrow.Thank you a lot!
Hello.I copy-pasted retrieving glRenderbufferStorageMultisampleEXT pointer as PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC into example and it fixes my issue.The problem was in our engine macro GET_GL_FUNC(func_name, extSuffix) which first looks up function without suffix and only when it is not found looks up EXT version.Thank you for help!
Super, thanks for confirming this was the issue! :)