TL;DR:
Sometimes, in some unexpected cases, for some unknown reasons, a “GLSL link error” is thrown into console. It happens in WebGL or android builds. It’s not caught by a regular try-catch C# statements. Even with broad “catch (Exception e) {…}”.
Is there a way to catch or at least temporary suppress those errors from a script?
In detail:
I’m writing a small toolset that reliably detects shader features supported by the GPU. It does so by actually trying to render a small RT with a special shader which outputs a debug colors indicating whether the feature is supported or not.
In the process, I use a built-in shader fallback system. Specifically, I add multiple subshaders, first of which has some “#pragma require” restriction and renders an “OK” color. And the second one is extremely simple and outputs “not OK” color. But sometimes, on some low-end devices (not just mobile ones but also outdated PCs) a GLSL error is thrown into console, even though there’s that second subshader that should work on literally anything.
So I’d like to know, how can I catch (from c# script) those graphics-API-level errors.
Here’s the error text:
GLES20: vprog textures are used, but not supported.
-------- GLSL link error: No compiled vertex shader when at least one graphics shader is attached.
It appears very rarely in WebGL. So far - only a couple of users (of a few thousands) got it. But they do.
And here’s the shader.
It doesn’t do anything fancy - just forces a texture to be read at vertex stage.
If GPU can do that, the 1st subshader should render a green(ish) color.
Otherwise, the 2nd subshader renders a red color.
Shader "y-Debug/Hardware Test/TexLod-Vert" {
Properties {
[Header(CHANGE THE SHADER IF YOU SEE THIS TEXT)]
[Header(it should only be used from script)]
[Space(40)]
_MainTex ("Main Texture", 2D) = "white" {} // not used, declared just to make Blit happy
_TestTex ("Test Texture", 2D) = "white" {} // should be passed as black texture
[Space] [Header(Shader Blending)]
[Enum(UnityEngine.Rendering.CullMode)] _Cull ("Cull", Int) = 0
[Enum(None,0,Alpha,1,RGB,14,RGBA,15)] _ColorMask ("out Color Mask", Float) = 15
[Enum(Off, 0, On, 1)] _zWrite ("Z-Write", Int) = 0
[Enum(UnityEngine.Rendering.CompareFunction)] _zTest ("Z-Test", Int) = 8 // Always
}
CGINCLUDE
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#define DRL_YES_COLOR fixed4(0.3, 0.7, 0.2, 1.0)
#define DRL_NO_COLOR fixed4(0.9, 0.25, 0.2, 1.0)
struct appdata {
float3 vertex : POSITION;
half2 tex0 : TEXCOORD0;
};
struct v2f {
float4 pos : SV_POSITION;
fixed4 vColor : COLOR;
half2 mainUVs : TEXCOORD0;
};
sampler2D _TestTex;
fixed4 frag (v2f i) : SV_Target
{
fixed4 clr = tex2D(_TestTex, i.mainUVs); // should be black, effectively keeping only vertex color
return saturate(i.vColor + clr);
}
ENDCG
Category {
Tags {
"PreviewType"="Plane"
"RenderType"="Opaque"
"IgnoreProjector"="True"
"ForceNoShadowCasting"="True"
}
ColorMask [_ColorMask]
Cull [_Cull]
ZTest [_zTest]
ZWrite [_zWrite]
Lighting Off
SubShader { Pass {
CGPROGRAM
// with support
#pragma require samplelod
v2f vert (appdata v)
{
float3 vtx = v.vertex;
half3 clr = tex2Dlod(_TestTex, half4(v.tex0, 0.0h, 0.0h));
vtx.xy += (v.tex0 * 2.0h - 1.0h) * clr.rg; // expand quad verts outside
v2f o;
o.pos = UnityObjectToClipPos(vtx);
o.vColor = DRL_YES_COLOR;
o.mainUVs = v.tex0;
return o;
}
ENDCG
} }
SubShader { Pass {
CGPROGRAM
// no support
v2f vert (appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.vColor = DRL_NO_COLOR;
o.mainUVs = v.tex0;
return o;
}
ENDCG
} }
}
FallBack Off
}