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 + 489869461276
1 libGLES_mali.so 0x720e7ebc48 + 489869458504
2 libGLES_mali.so 0x720e7e60cc + 489869435084
3 libGLES_mali.so 0x720e6d9ef8 + 489868336888
4 libGLES_mali.so 0x720e6c98f0 + 489868269808
5 libGLES_mali.so 0x720d720600 + 489851848192
6 libGLES_mali.so 0x720d717a64 + 489851812452
7 libGLES_mali.so 0x720d731574 + 489851917684
8 libGLES_mali.so 0x720d792da8 + 489852317096
9 libGLES_mali.so 0x720d792604 + 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;
}
}
}
↧