Hi !
I'm having issues with dual-source blending (used for OIT) on my AMD integrated GPU when it's working fine on my Nvidia GPU.
First of all, some informations about my hardware and drivers.
Hardware:
Dedicated GPU: NVIDIA Geforce RTX 2060
CPU: AMD Ryzen™ 7 4800H
Integrated GPU: AMD Radeon™ Graphics
Driver version:
AMD Radeon™ Graphics: 26.20.14048.2
To setup the blending functions I used the following code:
glBlendFunci(0, GL_ONE, GL_ONE); glBlendFuncSeparatei(1, GL_ZERO, GL_ONE_MINUS_SRC_COLOR, GL_ONE, GL_ONE);
As a result on my AMD GPU, it looks like both of the draw buffers 0 & 1 are using the same blending function -> glBlendFunc(GL_ONE, GL_ONE);
I could also note that if I avoid using dual-source blending by doing two passes, it works just fine.
// First pass
glDrawBuffer(GL.COLOR_ATTACHMENT0);
glBlendFunc(GL_ONE, GL_ONE);
Draw();
// Second pass
glDrawBuffer(GL.COLOR_ATTACHMENT1);
glBlendFuncSeparate(GL_ZERO, GL_ONE_MINUS_SRC_COLOR, GL_ONE, GL_ONE);
Draw();
I suspect there is a bug in the drivers, is this a known issue ?
Have a nice day !
Solved! Go to Solution.
Update:
@dorisyan I found a solution to the issue I reported.
In my original post I described a rendering pass that I set up the following way:
glBlendFunci(0, GL_ONE, GL_ONE);
glBlendFuncSeparatei(1, GL_ZERO, GL_ONE_MINUS_SRC_COLOR, GL_ONE, GL_ONE);
But I fixed the issue by modifying the previous pass.
In the previous pass I needed to set the BlendFunc for another texture as in the next pass to:
glBlendFunc(GL_ONE, GL_ONE);
It looks like the issue came from this line. It should be okay to use glBlendFunc to setup a texture with more than one draw buffer, it works just fine on Nvidia but to fix my problem I had to use:
glBlendFunci(0, GL_ONE, GL_ONE);
glBlendFunci(1, GL_ONE, GL_ONE);
In a nutshell:
With the pseudo-code below, in the second pass, the dual source blending is not working with my AMD GPU.
// First pass
TextureA.Bind();
glBlendFunc(GL_ONE, GL_ONE);
Draw();
TextureA.Unbind();
// Second pass
TextureB.Bind();
glBlendFunci(0, GL_ONE, GL_ONE);
glBlendFuncSeparatei(1, GL_ZERO, GL_ONE_MINUS_SRC_COLOR, GL_ONE, GL_ONE);
glActiveTexture(GL_TEXTURE1);
glBindTexture(TextureA.Color0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(TextureA.Color1);
Draw();
TextureB.Unbind();
But if I use glBlendFunci in the first pass instead of glBlendFunc, the second pass goes well, no issue with my AMD GPU !
// First pass
TextureA.Bind();
glBlendFunci(0, GL_ONE, GL_ONE);
glBlendFunci(1, GL_ONE, GL_ONE);
Draw();
TextureA.Unbind();
// Second pass
TextureB.Bind();
glBlendFunci(0, GL_ONE, GL_ONE);
glBlendFuncSeparatei(1, GL_ZERO, GL_ONE_MINUS_SRC_COLOR, GL_ONE, GL_ONE);
glActiveTexture(GL_TEXTURE1);
glBindTexture(TextureA.Color0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(TextureA.Color1);
Draw();
TextureB.Unbind();
I don't quite understand why but my issue is fixed so yay \o/
Thanks for your report @Lilou , Could you please provide a minimal code which can reproduce this problem?
The trick is that at least linux Mesa AMD driver has this limitation - when using dual source blending, the used blending function has to be GL_FUNC_ADD or GL_FUNC_SUBTRACT. I do not know how the driver behaves in windows. See this https://gitlab.freedesktop.org/mesa/mesa/-/issues/4183 for details.
Update:
@dorisyan I found a solution to the issue I reported.
In my original post I described a rendering pass that I set up the following way:
glBlendFunci(0, GL_ONE, GL_ONE);
glBlendFuncSeparatei(1, GL_ZERO, GL_ONE_MINUS_SRC_COLOR, GL_ONE, GL_ONE);
But I fixed the issue by modifying the previous pass.
In the previous pass I needed to set the BlendFunc for another texture as in the next pass to:
glBlendFunc(GL_ONE, GL_ONE);
It looks like the issue came from this line. It should be okay to use glBlendFunc to setup a texture with more than one draw buffer, it works just fine on Nvidia but to fix my problem I had to use:
glBlendFunci(0, GL_ONE, GL_ONE);
glBlendFunci(1, GL_ONE, GL_ONE);
In a nutshell:
With the pseudo-code below, in the second pass, the dual source blending is not working with my AMD GPU.
// First pass
TextureA.Bind();
glBlendFunc(GL_ONE, GL_ONE);
Draw();
TextureA.Unbind();
// Second pass
TextureB.Bind();
glBlendFunci(0, GL_ONE, GL_ONE);
glBlendFuncSeparatei(1, GL_ZERO, GL_ONE_MINUS_SRC_COLOR, GL_ONE, GL_ONE);
glActiveTexture(GL_TEXTURE1);
glBindTexture(TextureA.Color0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(TextureA.Color1);
Draw();
TextureB.Unbind();
But if I use glBlendFunci in the first pass instead of glBlendFunc, the second pass goes well, no issue with my AMD GPU !
// First pass
TextureA.Bind();
glBlendFunci(0, GL_ONE, GL_ONE);
glBlendFunci(1, GL_ONE, GL_ONE);
Draw();
TextureA.Unbind();
// Second pass
TextureB.Bind();
glBlendFunci(0, GL_ONE, GL_ONE);
glBlendFuncSeparatei(1, GL_ZERO, GL_ONE_MINUS_SRC_COLOR, GL_ONE, GL_ONE);
glActiveTexture(GL_TEXTURE1);
glBindTexture(TextureA.Color0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(TextureA.Color1);
Draw();
TextureB.Unbind();
I don't quite understand why but my issue is fixed so yay \o/