2

使用clock_gettime将此函数获取时间作为双倍:

// 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)。

4

1 回答 1

4

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

如果您运行应用程序的时间过长以至于毫秒溢出浮点精度(这将需要大约 10 7毫秒,或大约 2.7 小时左右),那么您必须找到一种方法让它优雅地处理这种情况。究竟如何做到这一点取决于您的着色器使用此时间值的确切用途。

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

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

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

于 2012-03-01T06:12:10.167 回答