My app works OK on:
-Windows Desktop GL
-Apple iOS iPad mini 2
-Samsung Galaxy Note 4 (ARM Mali-T760)
-Sony Xperia XZ2 Adreno 630
However when running on:
Huawei Mate 20 X (ARM Mali-G76) version OpenGL ES 3.2 v1.r16p0-01rel0.95d2435cbe2284d49b9bbcf5b1624fdd
Then I'm getting problems.
ARM Mali results:
after touching the screen to rotate the camera
I'm suspecting a driver bug.
This problem appears to be related to 'glInvalidateFramebuffer', if I replace all glInvalidateFramebuffer calls with glClear (or just remove the glInvalidateFramebuffer calls), then it starts to work ok.
Please check this link which includes APK files and images:
I'll take a look at this properly in the morning when I'm in the office, but just to check a few things based on the images.
It looks like are you are setting a scissor box which is smaller than the whole image and are just redrawing that (the square part on the screen which is getting drawn)?
A call to glClear behaves like a draw call so it will be impacted by the scissor box, so assuming you e.g. have EGL_BUFFER_PRESERVE set the parts outside of the scissor will be reliably preserved from the previous frame.
Most importantly a call to glInvalidateFramebuffer is *not* restricted by the scissor box - it will always invalidate the entire framebuffer. If you are then only redrawing the part of the frame inside the scissor then the contents outside of that are undefined. There is no guarantee what is rendered unless you redraw an invalidated region.
I'm not sure that's what you are doing here, but it would fit the behavior shown in the images.
My code more or less looks like this:
I have 2 renderings per frame:
-#1 deferred fullscreen
-#2 deferred to small rectangle on the left side, this rendering is partial (doesn't actually draw to default FBO)
Rendering #1, deferred fullscreen:
-set custom RT#0 (fbo attachment 0) for color, RT#1 (fbo attachment 1) for normals
-set custom RT#2 (fbo attachment 0) for light
-calculate per pixel light based on depth and RT#1 normals
-set custom RT#3 (fbo attachment 0) for lit-color
-combine RT#0 color with RT#2 light
-set default FBO
-copy RT#3 lit-color results into default FBO
start Rendering #2, deferred to small viewport in left rectangle:
-for this rendering I reuse the same RT's from Rendering #1, (HOWEVER reusing might be in different order, like instead of RT#0, RT#1, RT#2.., there's RT#2, RT#1, RT#0)
-set custom RT#3 (fbo attachment 0) for lit-color
And I've noticed that the problem on Mali already happens, without even copying results from Rendering #2 into the default FBO.
My guess is that the 'glInvalidateFramebuffer' calls from Rendering #2 affect somehow the Rendering #1, because I reuse the same RT's for both renderings.
Also I operate on viewports instead of scissor rectangle if that matters.
I've just made another test, that makes sure to disable any scissor before clearing RT's. And when I replace all glInvalidateFramebuffer with glClear or glClearBufferfv to purple color, then my app works OK, and I don't see any purple pixels. So it really looks like there's some bug with glInvalidateFramebuffer in the driver.
I would expect the behavior of a sub-frame render to be the same (whether you are using scissors or viewports).
Calling glInvalidateFramebuffer() will invalidate the memory contents of the entire surface - irrespective of what scissor or viewport is set - so any region outside of that will contain garbage unless it is explicitly redrawn. If you are reusing attachments across framebuffers then an invalidate in one framebuffer will render the contents of that attachment invalid in all other framebuffers that are using it (i.e. the invalidate applies to the memory content of the attachment not the framebuffer container).
Calling glClear on the other hand will honour both scissor and viewport, leaving the part outside untouched.
The behavior of the two is very different in these cases, so don't expect the rendering to be the same. That said, I'll check the APK now - the devil is in the detail in these cases.
glClear and glClearBufferfv are not affected by the viewport, only by scissor.
I use only default FBO (0) and 1 custom FBO, for which I change all attachments depending on what I need.
Esenthel said:I use only default FBO (0) and 1 custom FBO, for which I change all attachments depending on what I need.
It's unrelated to this issue - is there any particular reason for not just using multiple pre-generated FBOs? It would be lower overhead on the CPU.
My engine is cross platform, including directx 11 support, and there there's no concept of a frame buffer, you just attach render targets to 0,1,2.. slots. I find this approach much more natural. So I've built the render target management around that concept. Also I have a lot of post process effects, for which most of the time I need different kind of render targets attached. Creating an FBO for each combination would result in a lot of FBO'S created. Also it would make the render targets have to be strictly attached to those FBO'S. It would apply some restrictions about what render targets I can use and what not. But with my approach, I allocate render targets on demand when I need them, I keep them in a pool of render targets, once an effect is finished, then I mark render target as available for reuse, so it can be used for another post process effect. This way there's no restriction on what render targets can be used for a post process effect, I just reuse the first one available that matches desired resolution and format.
View all questions in Graphics and Gaming forum