Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Opengl es 移动GPU上的扩展浮点精度_Opengl Es_Opengl Es 2.0_Gpu_Floating Point Precision_Post Processing - Fatal编程技术网

Opengl es 移动GPU上的扩展浮点精度

Opengl es 移动GPU上的扩展浮点精度,opengl-es,opengl-es-2.0,gpu,floating-point-precision,post-processing,Opengl Es,Opengl Es 2.0,Gpu,Floating Point Precision,Post Processing,我正在尝试使用OpenGLES2.0在gpu上计算图像的梯度向量场。我找到了它的一个cpu实现,并将其与我的gpu实现进行了比较。这里的挑战是cpu实现依赖于java类型的浮点(32位),而我的gpu实现使用的是lowp浮点(8位)。我知道我可以使用mediump或highp来获得更好的结果,但我仍然希望继续使用lowp float来确保我的代码能够在最差的硬件上运行 计算梯度向量场的前几个步骤非常简单: 计算归一化灰度(红色+绿色+蓝色)/3.0 计算边缘贴图(右像素左像素)/2.0和(上像素

我正在尝试使用OpenGLES2.0在gpu上计算图像的梯度向量场。我找到了它的一个cpu实现,并将其与我的gpu实现进行了比较。这里的挑战是cpu实现依赖于java类型的浮点(32位),而我的gpu实现使用的是lowp浮点(8位)。我知道我可以使用mediump或highp来获得更好的结果,但我仍然希望继续使用lowp float来确保我的代码能够在最差的硬件上运行

计算梯度向量场的前几个步骤非常简单:

  • 计算归一化灰度(红色+绿色+蓝色)/3.0
  • 计算边缘贴图(右像素左像素)/2.0和(上像素下像素)/2.0
  • 计算拉普拉斯(稍微复杂一点,但现在不需要了解细节)
  • 目前,不做任何花哨的事情,我能够准确地模拟步骤1,这样cpu实现的图像结果与gpu的图像结果相同

    不幸的是,我已经陷入了第2步,因为我的边贴图计算在gpu上不够精确

    所以我尝试实现一个扩展精度浮点,灵感来自

    我对opengl es相当陌生,所以我甚至不确定我在这里做的事情是否正确,但下面是我打算编写的操作,以解决我目前遭受的精度损失

        vec2 split(float a)
    {
        float   t   =   a * (2e-8+1.0);
        float   aHi =   t - (t -a);
        float   aLo =   a - aHi;
    
        return vec2(aHi,aLo);
    }
    
    vec2 twoProd(float a, float b)
    {
        float   p   = a * b;
        vec2    aS  = split(a);
        vec2    bS  = split(b);
        float   err = ( ( (aS.x * bS.x) - p) + (aS.x * bS.y) + (aS.y * bS.x) ) + (aS.y * bS.y);
    
        return vec2(p,err);
    }
    
    vec2 FMAtwoProd(float a,float b)
    {
        float   x   =   a * b;
        float   y   =   a * b - x;
    
        return vec2(x,y);
    }
    
    vec2 div(vec2 a, vec2 b)
    {
        float   q   = a.x / b.x;
        vec2    res = twoProd( q , b.x );
        float   r   = ( a.x - res.x ) - res.y ;
    
        return vec2(q,r);
    }
    
    vec2 div(vec2 a, float b)
    {
        return div(a,split(b));
    }
    
    vec2 quickTwoSum(float a,float b)
    {
        float   s   =   a + b;
        float   e   =   b - (s-a);
    
        return vec2(s,e);
    }
    
    vec2 twoSum(float a,float b)
    {
        float   s   =   a + b;
        float   v   =   s - a;
        float   e   =   ( a - (s - v)) + ( b - v );
    
        return vec2(s,e);
    }
    
    vec2 add(vec2 a, vec2 b)
    {
        vec2    s   =   twoSum(a.x , b.x);
        vec2    t   =   twoSum(a.y , b.y);
    
        s.y     +=  t.x;
        s       =   quickTwoSum(s.x,s.y);
        s.y     +=  t.y;
        s       =   quickTwoSum(s.x,s.y);
    
        return s;
    }
    
    vec2 add(vec2 a,float b)
    {
        return add(a,split(b));
    }
    
    vec2 mult2(vec2 a,vec2 b)
    {
        vec2    p   =   twoProd(a.x,b.x);
        p.y     +=  a.x * b.y;
        p.y     +=  a.y * b.x;
        p       =   quickTwoSum(p.x,p.y);
    
        return p;
    }
    
    vec2 mult(vec2 a,float b)
    {
        return mult2(a, split(b));
    }
    
    显然,我在这里肯定做错了什么,或者错过了一些基本的概念,因为无论是使用简单运算还是扩展浮点运算,我都得到了相同的结果

    这里的挑战是cpu实现依赖于java类型的浮点(32位),而我的gpu实现使用的是lowp浮点(8位)

    lowp
    实际上并不意味着用于浮点运算的位数。它更多地涉及必须可表达的值的范围和最小可分辨值(精度)-您可以使用它来计算最小位数,但GLSL从来没有这样讨论过

    目前,不做任何花哨的事情,我能够准确地模拟步骤1,这样cpu实现的图像结果与gpu的图像结果相同

    这是幸运的,因为您描述中的一个直接问题来自这样一个事实,
    lowp
    只保证表示范围[-2.02.0]内的值。如果试图通过将低精度浮点值除以3(如步骤1所示)来规范化该值,则该操作可能有效,也可能无效。在最坏的情况下,这将不起作用,因为浮点值永远不会达到3.0。但是,在某些GPU上,它可能会起作用,因为
    lowp
    mediump
    之间可能没有区别,或者GPU的
    lowp
    可能超过GLSL ES 1.00规范中概述的最低要求

    。。。尽管如此,我还是希望继续使用lowp float来确保我的代码能够在最差的硬件上运行

    如果您的目标是尽可能低的终端硬件,请记住ES 2.0需要在所有着色器阶段提供
    mediump
    支持。
    lowp
    可能带给您的唯一好处是某些GPU的性能有所提高,但任何可以承载ES 2.0的GPU都支持中精度浮点运算,并且您的算法需要的范围大于
    lowp
    保证