- Home /
Segfault in glGenerateMipmap()
I use TextureArrays with GPU instancing to have fewer draw calls. TextureArrays allow me to sample different textures per instance by settings texture index in MaterialPropertyBlocks.
TextureArray is a render texture. I update it (add new textures there) during runtime. I can't use Graphics.Copy(...) for some reasons.
I need to calculate mipmaps for the TextureArray (RenderTexture.useMipMap is true).
But sometimes I get glitches and crashes on some devices. Seems that it happens only on devices with Mali-G77 and Mali-G78. According to stack traces, the crashes are from Mali drivers from glGenerateMipmap() function.
Does somebody see any problems with my code? Have somebody had similar issues with TextureArrays and mipmaps? Or with new Mali GPUs (g77 and g78)?
Unity3D version - 2020.3.19 Graphics API - OpenGL ES 3.2
Stack trace:
OS Version: Android 12 (SP1A.210812.016.G998BXXU4CVC4)
Report Version: 104
Exception Type: Unknown (SIGSEGV)
Application Specific Information:
Segfault
Thread 0 Crashed:
0 libGLES_mali.so 0x720e7ec71c <unknown> + 489869461276
1 libGLES_mali.so 0x720e7ebc48 <unknown> + 489869458504
2 libGLES_mali.so 0x720e7e60cc <unknown> + 489869435084
3 libGLES_mali.so 0x720e6d9ef8 <unknown> + 489868336888
4 libGLES_mali.so 0x720e6c98f0 <unknown> + 489868269808
5 libGLES_mali.so 0x720d720600 <unknown> + 489851848192
6 libGLES_mali.so 0x720d717a64 <unknown> + 489851812452
7 libGLES_mali.so 0x720d731574 <unknown> + 489851917684
8 libGLES_mali.so 0x720d792da8 <unknown> + 489852317096
9 libGLES_mali.so 0x720d792604 <unknown> + 489852315140
10 libGLES_mali.so 0x720d744974 glGenerateMipmap
11 libunity.so 0x71a5a6b5fc ApiGLES::GenerateMipmap
12 libunity.so 0x71a5a53754 GfxDeviceGLES::ProcessPendingMipGens
13 libunity.so 0x71a5a7a558 GfxFramebufferGLES::PrepareImpl
14 libunity.so 0x71a5a56df8 GfxDeviceGLES::BeforeDrawCall
15 libunity.so 0x71a5a5d23c GfxDeviceGLES::DrawNullGeometry
16 libunity.so 0x71a60c2ec4 GfxDeviceWorker::RunCommand
17 libunity.so 0x71a60c7684 GfxDeviceWorker::RunExt
18 libunity.so 0x71a60c764c GfxDeviceWorker::Run
19 libunity.so 0x71a60bf888 GfxDeviceWorker::RunGfxDeviceWorker
20 libunity.so 0x71a581f034 Thread::RunThreadWrapper
21 libc.so 0x754342dfcc __pthread_start
22 libc.so 0x75433cd830 __start_thread
Simplified code:
using System.Collections;
using UnityEngine;
using UnityEngine.Rendering;
public class TextureArrayIssue : MonoBehaviour
{
private RenderTexture _renderTexture;
private CommandBuffer _commandBuffer;
private Material _copyTextureMaterial;
private static readonly int _copySourceParamId = Shader.PropertyToID("_DR_CopySource");
private void Start()
{
_renderTexture = CreateRenderTextureArray();
_commandBuffer = new CommandBuffer();
_copyTextureMaterial = new Material(Shader.Find("Unlit/CopyTexture"));
StartCoroutine(PerformDeferredTextureAdding());
}
private static RenderTexture CreateRenderTextureArray()
{
var width = 256;
var height = 256;
var format = RenderTextureFormat.R8;
var slices = 128;
var useMipMap = true;
var sRGB = false;
var renderTextureDescriptor = new RenderTextureDescriptor(width, height, format, 0)
{
dimension = TextureDimension.Tex2DArray,
volumeDepth = slices,
useMipMap = useMipMap,
sRGB = sRGB,
};
var anisoLevel = 1;
var filterMode = FilterMode.Bilinear;
var wrapMode = TextureWrapMode.Repeat;
return new RenderTexture(renderTextureDescriptor)
{
anisoLevel = anisoLevel,
filterMode = filterMode,
wrapMode = wrapMode,
};
}
// I use this method to add textures in the TextureArray
public void AddTexture(Texture texture, int slice)
{
CustomBlit(texture, _renderTexture, slice);
}
private void CustomBlit(Texture srcTexture, RenderTexture dstTextureArray, int dstSlice)
{
// Graphics.Blit(texture, _renderTexture, 0, depthSlice) doesn't work properly with Texture2DArrays for Metal
// I use CommandBuffer to batch calls to GPU
_commandBuffer.SetGlobalTexture(_copySourceParamId, srcTexture);
_commandBuffer.SetRenderTarget(dstTextureArray.colorBuffer, dstTextureArray.depthBuffer,
0, CubemapFace.Unknown, dstSlice);
_commandBuffer.DrawProcedural(Matrix4x4.identity, _copyTextureMaterial, 0, MeshTopology.Triangles, 3);
}
private IEnumerator PerformDeferredTextureAdding()
{
while(true)
{
if(_commandBuffer.sizeInBytes > 0)
{
Graphics.ExecuteCommandBuffer(_commandBuffer);
_commandBuffer.Clear();
}
yield return null;
}
}
}
Since a segfault
means a invalid memory pointer it suggest that one of the resources you're trying to process contains an invalid one. Make sure all object are allocated or not released before making this call.
I don't know this particular subject much nor I've red your code deeply, but my "programmer sense" tells to change how you create a RT to this:
var tex = new RenderTexture(renderTextureDescriptor)
{
anisoLevel = anisoLevel,
filterMode = filterMode,
wrapMode = wrapMode,
};
tex.Create();// < tl;dr: you didn't call this
return tex;
Unity says the texture should be created automatically when we set it as active (for my case _commandBuffer.SetRenderTarget(...)) - https://docs.unity3d.com/ScriptReference/RenderTexture.Create.html, https://docs.unity3d.com/ScriptReference/Graphics.SetRenderTarget.html
But I will try to create the texture explicitly. Thanks!
Answer by MaxKramarov · Apr 11 at 01:35 PM
I could reproduce the crash. For that you need a device with Mail G78, OpenGL ES 3.2, and this code:
using UnityEngine;
using UnityEngine.Rendering;
public class UpdateTextureArray : MonoBehaviour
{
[SerializeField]
private Texture _srcTexture;
private RenderTexture _renderTexture;
private void Start()
{
RenderTextureDescriptor d = new RenderTextureDescriptor(256, 256, RenderTextureFormat.R8, 0)
{
dimension = TextureDimension.Tex2DArray,
volumeDepth = 128, // there is no crash if the depth is fewer than 128
useMipMap = true, // there is no crash if there are no mip maps
sRGB = false,
};
_renderTexture = new RenderTexture(d)
{
anisoLevel = 1,
filterMode = FilterMode.Bilinear,
wrapMode = TextureWrapMode.Repeat,
};
}
private void LateUpdate()
{
Graphics.Blit(_srcTexture, _renderTexture, 0, 0);
}
}
There are no crashes if any condition is true:
use Vulkan (instead of OpenGL ES)
use fewer texture array layers (than 128) (but GL_MAX_ARRAY_TEXTURE_LAYERS is 4096 for the devices)
don't use mipmaps for texture array
So I've "fixed" the crash by using 127 layers (instead of 128)
SystemInfo.graphicsDeviceVersion: OpenGL ES 3.2 v1.r32p1-01bet2-mbs2v39_0.f99ba4208fd3cd75b7876c6eee932fcf
This is a bug report material. Don't forget to send Unity a link :)
Unity has approved the issue - Unity has created an issue - https://issuetracker.unity3d.com/issues/mono-gles3-crash-with-signal-11-on-device-with-mali-g78-gpu-when-using-rendertexture-with-mipmap-generation
Your answer
Follow this Question
Related Questions
overlapping UV on mobile 1 Answer
Does deferred rendering work on iOS devices? 1 Answer
DX Crash, GFXDevice Crash 1 Answer
Why the scalling between these 2 resolutions is so bad? 1 Answer
Android shader not accepting fallback? 0 Answers