【问题标题】:Shader Time Uniform - clock_gettime being truncated着色器时间统一 - clock_gettime 被截断
【发布时间】:2012-03-19 15:41:36
【问题描述】:

使用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)。

【问题讨论】:

    标签: time glsl clock mantissa


    【解决方案1】:

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

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

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

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

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

    【讨论】:

      猜你喜欢
      • 2021-05-23
      • 1970-01-01
      • 2021-08-24
      • 1970-01-01
      • 2018-01-18
      • 2020-08-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多