zoukankan      html  css  js  c++  java
  • 记一个Adreno平台下GPU精度造成的问题

    记一个Adreno平台下GPU精度造成的问题

    项目中有一个美术需求是这样的,使用时间作为参数控制uv,采样一张Texture,达到看起来流动的效果。OK,看上去很简单,动手实现一下。

    Naive Implementation

    half2 uv = _Time.g * speed + offset;
    half4 col = tex2D(_GlowTex, uv);
    

    很好实现,不过运行起来却遇到了问题,在Adreno平台下(小米6),时间久了特效就会卡顿住,在帧率还是30帧的情况下,特效看起来只有3-4帧的样子,一看就是由于_Time.g太大之后导致浮点数精度不足导致的问题。

    Better Implementation

    float2 uv = _Time.g * speed + offset;
    half4 col = tex2D(_GlowTex, uv + i.uv);
    

    Problem Solved!然而当我在真机上确认时,发现还是出现了卡顿的情况,吓得我连忙确认是不是Shader没有重新编译(Unity一些版本如果只改cginc文件,shader不会重新编译),然而查下来确实用的是最新的shader。

    Dig Deeper

    这一定是Unity Shader Compiler(HLSLcc)的锅,来翻翻HLSLcc生成的目标平台shader代码,安卓平台下就是glsl。

    #version 300 es
    precision highp float;
    ...
    vec2 u_xlat5;
    ...
    u_xlat5.xy = _Time.g * speed.xy + offset.xy;
    u_xlat16_5.xy = texture(_GlowTex, u_xlat5.xy).xw;
    ...
    

    崩溃,分明是用的highp精度的浮点数作为uv,为什么结果还是不对?

    Solve the Problem?

    问题最终的解决,来自我胡乱写了一行代码

    float time = fmod(_Time.g, 2e5);
    float2 uv = time * speed + offset;
    half4 col = tex2D(_GlowTex, uv + i.uv);
    

    这样做了之后,问题奇迹般的解决了!但是为什么呢?首先glsl中没有fmod这个intrinsic,HLSLcc自己实现了一份,大概就是乘上一个数的倒数计算后再乘上这个数:

        u_xlat0.x = _Time.g * 4.99999987e-06;
    #ifdef UNITY_ADRENO_ES3
        u_xlatb5 = !!(u_xlat0.x>=(-u_xlat0.x));
    #else
        u_xlatb5 = u_xlat0.x>=(-u_xlat0.x);
    #endif
        u_xlat0.x = fract(abs(u_xlat0.x));
        u_xlat0.x = (u_xlatb5) ? u_xlat0.x : (-u_xlat0.x);
        u_xlat0.x = u_xlat0.x * 200000.0;
    

    下面就是我猜测的原因了(手边暂时没有方法验证,有办法的大佬请告诉我):

    1. Adreno的shader compiler把fmod计算放到vertex shader中进行了,或者干脆没放到shader中。因为这个计算的结果每个fragment都是一样的,没必要每个fragment都算一次,而计算这个值的地方,不一定用的highp精度的浮点数。
    2. Adreno的shader compiler根本没准守glsl精度的规范。

    近一两年Adreno平台经常发生一些bug,之前也遇到shader代码太长导致的花屏问题,再这样下去被mali超过也说不定。

  • 相关阅读:
    .net Application的目录
    (转载).NET中RabbitMQ的使用
    (转载)RabbitMQ消息队列应用
    说说JSON和JSONP
    SQL Server中的事务与锁
    StackExchange.Redis Client(转载)
    正则语法的查询,这是纯转载的,为了方便查询
    Regex的性能问题
    解决json日期格式问题的办法
    BenchmarkDotNet(性能测试)
  • 原文地址:https://www.cnblogs.com/hamwj1991/p/12445225.html
Copyright © 2011-2022 走看看