I was debuging on some shader effect with unity , and found out that the image on final screen was slightly different , espicially between adreno and mali gpu platforms.
After some boring debug steps , I focus on the uv value interpolated from VS stage. They are supposed to be the same value , at least almost the same .
here is my testcase:
I use unity engine, and write a unlit shader, with a few modification that just print the UV value to framebuffer.
For test convenience, I add some shader variant keyword to dynamicly implement diffent VS stage's uv computations.
build the unity project and run on some different android devices.
From each device ,we get several image files which are just copy from the rumtime RenderTexture buffer.
We compare these images ,using opencv library which can give a similarity result from two input images.
finally ,we get the result.
below is the simple unity shader , just out put uv as colors.
Shader "Unlit/InAccurateDemo"{ Properties { _MainTex ("Texture", 2D) = "white" {} } SubShader { Tags { "RenderType"="Opaque" } LOD 100
Pass { CGPROGRAM #pragma shader_feature __ VS_TRANS_UV #pragma shader_feature __ VS_FRAC #pragma shader_feature __ SHOW_UV_ONLY
#pragma vertex vert #pragma fragment frag #include "UnityCG.cginc"
struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; };
struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; };
sampler2D _MainTex; float4 _MainTex_ST;
v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex);
// use this variant ,just to apply the transformation, the specified value is _MainTex : (2.876, 3.668, 0.1138, 12.662)#if VS_TRANS_UV o.uv = TRANSFORM_TEX(v.uv, _MainTex); #else o.uv = v.uv;#endif
#if VS_FRAC o.uv = frac(o.uv); // it seems to provide a higer accurate value with the frac function#endif
return o; }
float4 frag (v2f i) : SV_Target {#if SHOW_UV_ONLY return float4(frac(i.uv),0,1); // only output uv to render target as colors#else float4 col = tex2D(_MainTex, i.uv); return col;#endif } ENDCG } }}
here is the final compare result:
we use an Adreno (TM) 640 device as the standard device, compared to other 9 andriod devices.
BaseGPU:Adreno (TM) 640(ComparedWith) | Adreno (TM) 510 | Adreno (TM) 530 | Mali-G76 | Mali-G76 | Mali-G71 | Mali-G51 | Mali-T830 | Mali-T830 | Mali-T830 | Demo_1.jpg CompareValue:1.0 , 1.0 , 0.999 , 0.999 , 0.999 , 0.999 , 0.997 , 0.997 , 0.997 SHOW_UV_ONLYDemo_3.jpg CompareValue:1.0 , 1.0 , 0.999 , 0.999 , 0.999 , 0.999 , 0.998 , 0.998 , 0.998 SHOW_UV_ONLY VS_FRACDemo_5.jpg CompareValue:1.0 , 1.0 , 0.998 , 0.998 , 0.998 , 0.998 , 0.996 , 0.996 , 0.996 SHOW_UV_ONLY VS_TRANS_UVDemo_7.jpg CompareValue:1.0 , 1.0 , 0.998 , 0.998 , 0.998 , 0.998 , 0.997 , 0.997 , 0.997 SHOW_UV_ONLY VS_FRAC VS_TRANS_UV
Demo_0.jpg CompareValue:1.0 , 1.0 , 0.997 , 0.997 , 0.997 , 0.997 , 0.996 , 0.996 , 0.996 Demo_2.jpg CompareValue:1.0 , 1.0 , 0.997 , 0.997 , 0.997 , 0.997 , 0.996 , 0.996 , 0.996 VS_FRACDemo_4.jpg CompareValue:1.0 , 1.0 , 0.996 , 0.996 , 0.996 , 0.996 , 0.994 , 0.994 , 0.994 VS_TRANS_UVDemo_6.jpg CompareValue:1.0 , 1.0 , 0.996 , 0.996 , 0.996 , 0.996 , 0.993 , 0.993 , 0.993 VS_FRAC VS_TRANS_UV
from the result above , we see the RT image 's similarity is 100% among all adreno gpus.
when comparing to mali serial gpus, they images 's similarity is slightly different, with the old midgard gpu even worse.
we add the uv transform operation, the similarity value is even lower.
but a frac function seems to make a compesation.
So, does anyone know why this differency happens, and how to get a perfect same RT on both gpu platforms.
thank you ~~~
I really appreciate it~~