着色器时间统一 - clock_gettime被截断

时间:2012-03-01 05:47:19

标签: time glsl clock mantissa

使用clock_gettime将此函数作为double的时间:

// return current time in milliseconds
static double time_get_ms(void)
{
    struct timespec res;

#ifdef ANDROID
    clock_gettime(CLOCK_REALTIME_HR, &res);
#else
    clock_gettime(CLOCK_REALTIME, &res);
#endif
    return (double)(1000.0*res.tv_sec + res.tv_nsec/1e6);
}

将其发送到着色器需要转换为浮动。尾数溢出并在去往着色器的途中被截断。

示例:

双倍= 1330579093642.441895

作为一个浮点数= 1330579111936.000000

由于截断,浮点值长时间停留在单个数字上。

对于浮点数来说,res.tv_sec中的秒值似乎也很大,在通往GPU的过程中它也会被截断。

尝试测量自应用程序启动以来的时间,我很快就遇到了同样的问题。

那么将运行时值转换为着色器的最佳方法是什么? Linux世界中的某种跨平台(所以IOS,Android,Linux)。

1 个答案:

答案 0 :(得分:4)

您的尾数中已经没有32位浮点精度。着色器将无法更好地处理这种精度不足,因为除非您使用GL 4.x并支持双精度,否则着色器也只能处理32位浮点数。

如果你正在运行一个应用程序,以至于毫秒溢出浮点精度(这需要~10 7 毫秒,或大约2.7小时左右),那么你必须找到一种方法优雅地处理这种情况。具体如何操作取决于着色器使用此时间值的确切内容。

大多数着色器不需要实际时间(以毫秒为单位)。绝大多数需要时间(或类似时间)的着色器过程都是周期性的。在这种情况下,您可以简单地向它们传递一个值,表示它们在特定周期内的距离。该值在范围[0,1]上,在循环开始时为0,在中间为0.5,在结束时为1。

如果您的着色器过程无法参数化,如果它确实需要绝对时间,那么您的下一个赌注是传递两个浮点参数。基本上,你需要保留溢出位。这将使涉及GPU时间的所有数学变得复杂,因为您必须使用两个值并知道如何将它们一起移植以进行时间更新。同样,你如何做到这一点取决于你在着色器中做了什么。

或者,如果硬件支持GL 3.x +,则可以用32位无符号整数发送时间。这将为您提供更多的精度,因此它可以延长问题的时间。如果你把你的时间发送到十分之一毫秒,那么你应该能够在溢出之前获得大约5天左右的时间。同样,这会使你的所有GPU数学变得复杂,因为你不能只进行一次int-to-float转换。