介绍

突然好奇如果在Shader里对同一纹理多次采样是否会影响性能,所以简单进行了测试

结论

先说下结论在Shader里对同一纹理多次采样不会影响性能,前提是只要是uv相同的贴图采样,surface和vertex frag编译之后都会优化掉多余的采样次数。

流程

无实际意义,只是为了测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
fixed4 frag (v2f i) : SV_Target
{
// sample the texture
fixed col = tex2D(_MainTex, i.uv).r;
fixed col2 = tex2D(_MainTex, i.uv).g;
fixed col3 = tex2D(_MainTex, i.uv).b;
fixed col4 = tex2D(_MainTex, i.uv).a;
fixed2 col5 = tex2D(_MainTex, i.uv).rg;
fixed2 col6 = tex2D(_MainTex, i.uv).rb;

fixed4 final_color = col.rrrr + col2.rrrr + col3.rrrr + col4.rrrr + col5.rgrg + col6.rgrg;
// apply fog
return final_color;
}

选择为OpenGLES 然后Compile

局部编译后代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#ifdef FRAGMENT
#version 300 es

precision highp float;
precision highp int;
#define UNITY_SUPPORTS_UNIFORM_LOCATION 1
#if UNITY_SUPPORTS_UNIFORM_LOCATION
#define UNITY_LOCATION(x) layout(location = x)
#define UNITY_BINDING(x) layout(binding = x, std140)
#else
#define UNITY_LOCATION(x)
#define UNITY_BINDING(x) layout(std140)
#endif
UNITY_LOCATION(0) uniform mediump sampler2D _MainTex;
in highp vec2 vs_TEXCOORD0;
layout(location = 0) out mediump vec4 SV_Target0;
mediump vec4 u_xlat16_0;
mediump vec4 u_xlat16_1;
void main()
{
u_xlat16_0 = texture(_MainTex, vs_TEXCOORD0.xy);
u_xlat16_1.x = u_xlat16_0.y + u_xlat16_0.x;
u_xlat16_1.x = u_xlat16_0.z + u_xlat16_1.x;
u_xlat16_1.x = u_xlat16_0.w + u_xlat16_1.x;
u_xlat16_1 = u_xlat16_0.xyxy + u_xlat16_1.xxxx;
SV_Target0 = u_xlat16_0.xzxz + u_xlat16_1;
return;
}

#endif

可以看到编译后的代码只有一次采样,其他的采样都被优化掉了

如果任意修改其中的一个采样UV

1
2
3
4
5
6
7
8
9
10
11
12
13
14
 fixed4 frag (v2f i) : SV_Target
{
// sample the texture
fixed col = tex2D(_MainTex, i.uv + _Time.x * 10).r;
fixed col2 = tex2D(_MainTex, i.uv).g;
fixed col3 = tex2D(_MainTex, i.uv).b;
fixed col4 = tex2D(_MainTex, i.uv).a;
fixed2 col5 = tex2D(_MainTex, i.uv).rg;
fixed2 col6 = tex2D(_MainTex, i.uv).rb;

fixed4 final_color = col.rrrr + col2.rrrr + col3.rrrr + col4.rrrr + col5.rgrg + col6.rgrg;
// apply fog
return final_color;
}

编译后的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#ifdef FRAGMENT
#version 300 es

precision highp float;
precision highp int;
#define HLSLCC_ENABLE_UNIFORM_BUFFERS 1
#if HLSLCC_ENABLE_UNIFORM_BUFFERS
#define UNITY_UNIFORM
#else
#define UNITY_UNIFORM uniform
#endif
#define UNITY_SUPPORTS_UNIFORM_LOCATION 1
#if UNITY_SUPPORTS_UNIFORM_LOCATION
#define UNITY_LOCATION(x) layout(location = x)
#define UNITY_BINDING(x) layout(binding = x, std140)
#else
#define UNITY_LOCATION(x)
#define UNITY_BINDING(x) layout(std140)
#endif
uniform vec4 _Time;
UNITY_LOCATION(0) uniform mediump sampler2D _MainTex;
in highp vec2 vs_TEXCOORD0;
layout(location = 0) out mediump vec4 SV_Target0;
vec2 u_xlat0;
mediump vec4 u_xlat16_0;
mediump vec4 u_xlat16_1;
mediump float u_xlat16_2;
void main()
{
u_xlat0.xy = _Time.xx * vec2(10.0, 10.0) + vs_TEXCOORD0.xy;
u_xlat16_0.x = texture(_MainTex, u_xlat0.xy).x;
u_xlat16_1 = texture(_MainTex, vs_TEXCOORD0.xy);
u_xlat16_2 = u_xlat16_0.x + u_xlat16_1.y;
u_xlat16_2 = u_xlat16_1.z + u_xlat16_2;
u_xlat16_2 = u_xlat16_1.w + u_xlat16_2;
u_xlat16_0 = u_xlat16_1.xyxy + vec4(u_xlat16_2);
SV_Target0 = u_xlat16_1.xzxz + u_xlat16_0;
return;
}

#endif

可以看到编译后的代码有两次采样,其中一次采样的UV是修改后的,另一次采样的UV是原来的UV,这样就会导致两次采样的结果不一样,所以编译器就不会优化掉其中的一次采样。