Render.ru

Попытка посчитать время шейдера...

#1
Всем привет.

Воодушевился с утра списком фичеров prman 11, в частности, его новой переменной, которая показывает время выполнения шейдера и которую можно вывести в отдельную картинку - и смотреть, где в сцене затыки со сложными шейдерами. Решил попробовать сделать что-то похожее, не дожидаясь prman 11 :)

Что для этого сделал:

1. Написал DSO с 2мя функциями: starttimer и stoptimer. Для таймера использовал GetSystemTime из Win32, поскольку использовать QueryPerformanceCounter посчитал оверкиллом.

2. Первая функция считывает время, вторая - повторно считывает и вычитает.

3. В шейдере вставил вызовы этих функций. Получившуюся разницу вывожу в качестве output varying float в другую картинку - 16bit TIFF.

Ограничения схемы понятны, поскольку на самом деле мы считаем совсем не то, что prman11, который может учитывать полные расходы на рендеринг, а не только shading - мы считаем только shading.

Проблемы:

1. Время не считается :) Собственно, и вся проблема.

Продолбался уже часов несколько. Полное впечатление, что собственно shading не занимает времени вообще :) что неправильно. Либо он как-то хитро кэшируется...

В общем, помогите, кто может и кому интересно. Всё лежит по адресу:

http://www.dream.com.ua/downloads/shadertimer.zip
21k
 
#2
Э-э-э...слушай, ну а не может быть это из-за того, что в prman'е шейдер выполняется не "последовательно", а "параллельно", ну то есть считаются все сэмплы данного бакета _одновременно_(ну там, сложить _все_ сэмплы, вычислить какие-нть углы для _всех_ сэмплов), а не сэмпл за сэмплом....может от этого?
 
#3
> Э-э-э...слушай, ну а не может быть это из-за того, что в
> prman'е шейдер выполняется не "последовательно", а
> "параллельно", ну то есть считаются все сэмплы данного бакета
> _одновременно_(ну там, сложить _все_ сэмплы, вычислить
> какие-нть углы для _всех_ сэмплов), а не сэмпл за
> сэмплом....может от этого?

Конечно же.

Вот я баран...

Ну в общем файл остался пока лежать в научение потомкам и для тех, кому нужен template для написания DSO для SL.
 
#4
Подожди, ну а что - получается что нельзя померять время? Всё равно же оно должно когда-то запускать таймер и в какое-то время его тормозить, так?
И, в таком случае, как тогда они считают это в 11?
 
#5
Имхо это результат работы оптимизатора. Ну типа проанализировал код, выяснил, что твоя dso-шка не портит никаких последующих данных (из тех, что юзает остальная часть шейдера) и свалил обе строки в кучу, да еще небось вызвав их по одному разу (вместо того, чтобы вызывать по каждому шейдинг сэмплу) по той же причине :)
 
#6
Посмотрел код: скорее всего так и есть... Может попробовать что-то типа

float a = starttimer(dumb);
...
Oi = a;
...
a = stoptimer(dumb);
 
#7
Даже так не работает.....вообще очень странные вещь происходят...
Если печатать полученное время прямо из шейдера, то PRMan как-то странно их печатает.....у меня был вставлен пустой цикл-тормоз для того, чтобы разобрать хоть что-то можно было в консоли, вот что из этого получилось:

/*------------------------------*/
float a = get();

[shader code...]
float j;
for (j = 0; j< 50000; j+=1) j=j;

float _timer1 = get() - a;
print (timer);
/*------------------------------*/
/* get() - это просто getCurrentTime()*/

Так вот - оно сначала ждало, а потом печатало 256 значений _сразу_, безо всяких задержек. То есть там действительно идёт параллельное исполнение, причём количество печатаемых чисел не зависит от bucket size - их всегда 256, как это возможно - хз, я не понимаю.
 
#8
Мне кажется, надо в этот шейдоп передавать какое-нибудь varying значение, типа P... Тогда оптимайзеру будет сложнее сообразить, что вызов шейдопа можно соптимизировать...
 
Сверху