I’ve got a problem I just can’t work out here. In our game, we’re rendering an isometric tile map, generally 50x50 tiles, with multiple possible layers - so around 2500-5000 quads to render the entire map. This would obviously run terribly without instancing, so I set it up to use a single texture array to render all the sprites (118 sprites currently), with each quad receiving an instanced _SpriteIndex property to point to an entry in this texture array.
This works perfectly fine zoomed out - the entire board can render at a smooth 60FPS. It also works fine close up - though it does drop below sixty. In the middle of those two zoom levels, however, it can slow down to even single digit FPS numbers. The GPU time per frame spikes, GPU usage hits 100%, and the game slows to a crawl, even with no change in number of draw calls or triangles drawn. I thought this problem could be mipmapping, but disabling mipmapping seems to have no effect.
Here is a version of the shader we are using, with only the necessary portions:
Shader "Sprites/MinimalExample"
{
Properties
{
}
SubShader
{
Tags
{
"Queue" = "Transparent"
"IgnoreProjector" = "True"
"RenderType" = "Transparent"
"PreviewType" = "Plane"
}
Cull Off
Lighting Off
ZWrite Off
Blend One OneMinusSrcAlpha
Pass
{
CGPROGRAM
#pragma vertex SpriteVert
#pragma fragment SpriteFrag
#pragma target 2.0
#pragma multi_compile_instancing
#pragma require 2darray
#include "UnityCG.cginc"
UNITY_INSTANCING_BUFFER_START(PerDrawSprite)
UNITY_DEFINE_INSTANCED_PROP(float, _SpriteIndex_Instanced)
UNITY_INSTANCING_BUFFER_END(PerDrawSprite)
#define _SpriteIndex UNITY_ACCESS_INSTANCED_PROP(PerDrawSprite, _SpriteIndex_Instanced)
UNITY_DECLARE_TEX2DARRAY(_MainTexArray);
struct appdata_t
{
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f
{
float4 vertex : SV_POSITION;
float2 texcoord : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
v2f SpriteVert(appdata_t IN)
{
v2f OUT;
UNITY_SETUP_INSTANCE_ID(IN);
OUT.vertex = UnityObjectToClipPos(IN.vertex);
OUT.texcoord = IN.texcoord;
UNITY_TRANSFER_INSTANCE_ID(IN, OUT);
return OUT;
}
fixed4 SpriteFrag(v2f IN) : SV_Target
{
UNITY_SETUP_INSTANCE_ID(IN);
float4 c = UNITY_SAMPLE_TEX2DARRAY(_MainTexArray, float3(IN.texcoord, _SpriteIndex));
c.rgb *= c.a;
return c;
}
ENDCG
}
}
}
Replacing _SpriteIndex with a constant makes the issue go away, so it seems that sampling from the texture array is the root of this issue. Does anyone know what the problem is, or have any leads I can follow?
This is Unity 2018.4.1f1.