AnsweredAssumed Answered

Permanent texture corruption caused by glBindImageTexture()

Question asked by theagentd on Aug 8, 2020

Hello!

 

 

My name is Daniel and I work as a graphics programmer at Avalanche Studios. However, in my free time I help out Puppygames as a side project (contractually approved by Avalanche Studios of course). This account is only for Puppygames related issues.

 

We are developing a game called Battledroid: Skirmish using OpenGL. We recently encountered a corruption and crash issue on an AMD RX Vega 56 card. To summarize, certain render target textures seem to become permanently corrupted, at which point clearing them will not fix the issue. The only reliable way to fix the issue seems to be recreating them, but the issue immediately starts to occur again with the new texture. The issue seems to be related to binding the render target textures as load-store images. This bug is unfortunately critical and will prevent our game from working on AMD.

 

The issue seems to have started when we added a pass called the "merge pass", which is a compute shader that reads the current color (GL_RGBA16F) and linearized depth texture (GL_R32F) using imageLoad(), adds a bunch of stuff (transparency, volumetric lighting, skybox, etc) and then writes out new a new color and a new depth value to the same textures using imageStore() with the same coordinates. The issue manifests as permanently corrupted "tiles" in the color texture and/or the linear depth texture that persists through glClear() and fullscreen pixel shader overwrites. See the attached images and the video for examples of the issue.

 

The shader pass itself does not seem to be the issue; it's the act of binding the texture as a load-store image that causes corruption. Completely disabling the compute shader but leaving the following two lines (or just the first one) causes the corruption to appear:

glBindImageTexture(1, renderTargets.getLinearDepthBuffer().getID(), 0, false, 0, GL_READ_WRITE, GL_R32F);
glBindImageTexture(1, 0, 0, false, 0, GL_READ_WRITE, GL_R32F);

I was unable to take a RenderDoc capture on the Vega 56 card, as it freezes during capture. However, I was able to do a RenderDoc capture on an Nvidia card (which renders the scene correctly), which I was then able to open with the Vega 56 card. The capture does show the corruption, and I've attempted to disable as many unrelated shader passes as possible to narrow down the issue. Please let me know where to send the capture, as I do not wish to publicly share it.

 

This bug also seems to result in random freezes, especially when resizing the window (which deletes and recreates textures). It also seems to potentially be causing issues in other rendering as well (water geometry and a skybox reflection fullscreen pass), but those issues could be side effects of the above described issue, as the corruption occurs even with those features disabled.

 

I am also available for live chatting if you require more information and faster iterations.

 

 

Thank you for reading!

Daniel

Outcomes