2012-03-01 6 views
2

이중 사용 위해 clock_gettime이 함수 점점 시간을 가지고 잘리지 : 쉐이더로 보내기쉐이더 시간 유니폼 - 위해 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); 
} 

이 떠 전환이 필요합니다. 가수가 오버 플로우되어 셰이더로가는 길에 잘립니다.

예 : double로

= float로서 1330579093642.441895

= 1330579111936.000000

플로트 값 의한 절단에 장시간 단수에 걸리면.

또한 res.tv_sec의 초 값도 float 값으로 큰 것으로 보이고 GPU로가는 도중 잘리고 있습니다.

응용 프로그램 실행 이후 시간을 측정하려고 시도하고 동일한 문제가 발생하는 경우가 많습니다.

그래서 셰이더에 실행 시간 값을 가져 오는 가장 좋은 방법은 무엇입니까? 리눅스 세계에서 플랫폼을 교차시키는 것 (IOS, Android, Linux).

답변

4

가수에 32 비트 부동 소수점 정밀도가 부족합니다. 셰이더는 GL4.x를 배정도 지원과 함께 사용하지 않는 한 셰이더가 32 비트 부동 소수점을 처리 할 수 ​​없으므로 정밀도가 부족할 수 있습니다. 당신이 너무 오래 밀리 초 (너무 ~ 10 7 밀리 초, 또는 약 2.7 시간을 필요로) 부동 소수점 정밀도 오버 플로우 것을 응용 프로그램을 실행하는 경우

, 당신은 우아하게이 문제를 해결할 수있는 방법을 찾을 수있다 상태. 정확히 어떻게하는지는 셰이더가이 시간 값을 정확히 사용하는지에 달려 있습니다.

대부분의 셰이더는 실제 시간 (밀리 초)을 필요로하지 않습니다. 시간 (또는 시간과 같은 것)을 필요로하는 대부분의 셰이더 프로세스는 주기적입니다. 어떤 경우에는 특정주기를 통해 얼마나 멀리 있는지 값을 전달할 수 있습니다. 이 값은 [0, 1] 범위에서 사이클의 시작 부분에서 0, 중간 부분에서 0.5, 끝 부분에서 1에 도달합니다.

쉐이더 프로세스를 매개 변수화 할 수없는 경우 절대 시간이 필요하면 다음 번에 두 개의 부동 소수점 매개 변수을 전달해야합니다. 기본적으로 오버플로 비트를 유지해야합니다. 이렇게하면 두 개의 값을 사용해야하고 시간 업데이트를 위해 이식하는 방법을 알고 있기 때문에 GPU에서 시간과 관련된 모든 수학이 복잡해집니다. 다시 말하지만,이 작업을 수행하는 방법은 쉐이더에서 수행중인 작업에 따라 다릅니다.

하드웨어가 GL 3.x +를 지원하는 경우, 32 비트 부호없는 정수로 시간을 보낼 수도 있습니다. 이렇게하면 정밀도가 조금 더 높아 지므로 문제가 오래 지속됩니다. 밀리 초의 10 분의 1로 시간을 보내면 오버플로되기 전에 약 5 일 정도의 시간을 가져야합니다. 다시 말하지만, 이것은 int-to-float 변환을 수행 할 수 없으므로 모든 GPU 수학을 복잡하게 만듭니다.