[РЕШЕНО] Приложение с Open GL отнимает 50% ЦП. Как забороть?

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Ответить
Аватара пользователя
yeger
новенький
Сообщения: 49
Зарегистрирован: 17.03.2011 11:26:34

[РЕШЕНО] Приложение с Open GL отнимает 50% ЦП. Как забороть?

Сообщение yeger »

Добрый день всем.
Столкнулся с проблемой, что приложение с Open GL отнимает 50% ЦП.
На "служебных" проектах - не критично, а если мини-игрушку сделать - то уже хочется "полегче".
Версия: 0.9.28.2
FPC: 2.2.4

Посмотрел пример из папки примеров - то же самое, также "загружает" проц. С чего бы? У меня карта не плохая (GTS-250 GeForce), для сравнения WoW ест меньше...
Последний раз редактировалось yeger 27.06.2011 17:18:03, всего редактировалось 1 раз.
Аватара пользователя
carrots
постоялец
Сообщения: 138
Зарегистрирован: 28.03.2008 01:13:02

Сообщение carrots »

А сколько fps? Возможно видео карта так быстро справляется что процессору приходится на половине своей мощности давать ей новое задание(или на полной мощности одного из двух ядер). Если очень большое количество кадров на секунду и нужно экономить процессор - можно просто ограничить их. (если вы дадите большую нагрузку на видео карту, а на процессор нет - процессор станет более свободным)
Аватара пользователя
yeger
новенький
Сообщения: 49
Зарегистрирован: 17.03.2011 11:26:34

Сообщение yeger »

Fps смотрел в примере - 51.
В своем приложении не смотрел, так как грузят одинаково, от 35 до 50%, думаю fps около того же.
Поискал как ограничить fps (думаю 30 хватит вполне) не нашел, подскажите, как менять?
Аватара пользователя
FedeX
постоялец
Сообщения: 422
Зарегистрирован: 27.03.2006 09:25:34
Откуда: украина, житомир

Сообщение FedeX »

Скорее всего у вас двухядерный процессор? А тестовое OpenGL приложение осуществляет рендеринг прямо в цикле обработки сообщений, или же постоянно после отрисовки шлёт своему окну сообщение "перерисоваться", что полностью занимает работой одно ядро процессора. Для мультимедийных приложений это норма, но чтобы не перегревать проц, не разряжать аккумулятор в ноутбуке и просто не делать дармовую работу используют вертикальную синхронизацию. Это позволяет запретить приложению делать лишние прорисовки в внеэкранном буфере, до тех пор пока этот буфер не отобразиться на экране. Насколько помню в OpenGL эта функциональность доступна только в виде платформозависимых расширений, под Windows это расширение WGL_EXT_swap_control и функция wglSwapIntervalEXT . Как подключать и использовать расширения смотрите в документации по OpenGL. В примерах конечно же этого не используют.
Аватара пользователя
yeger
новенький
Сообщения: 49
Зарегистрирован: 17.03.2011 11:26:34

Сообщение yeger »

Прямо в цикле обработки сообщений, да, "перекинуто" по примеру "Application.AddOnIdleHandler(@OnAppIdle)" и соответственно "OnAppIdle" переписана.
wglSwapIntervalEXT(0); Вызывает ошибку при выполнении, т.к. видимо при создании контекста надо вызывать. А у меня просто выведен компонент "TOpenGLControl".

Печально.
Аватара пользователя
FedeX
постоялец
Сообщения: 422
Зарегистрирован: 27.03.2006 09:25:34
Откуда: украина, житомир

Сообщение FedeX »

>wglSwapIntervalEXT(0); Вызывает ошибку при выполнении

а вы проинициализировали расширение? насколько помню функцию wglSwapIntervalEXT можно вызывать когда угодно
zub
долгожитель
Сообщения: 2889
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

wglSwapIntervalEXT описаный в TOpenGLControl не работает, т.к. инициализируется TOpenGLControl`ом без созданого и текущего контекста OpenGL, его необходимо повторно проинициализировать когда контекст создан и назначен текущим:

Код: Выделить всё

       Pointer(@wglSwapIntervalEXT) := wglGetProcAddress('wglSwapIntervalEXT');
       if @wglSwapIntervalEXT<>nil then
                                                        wglSwapIntervalEXT(0);
Аватара пользователя
yeger
новенький
Сообщения: 49
Зарегистрирован: 17.03.2011 11:26:34

Сообщение yeger »

Код: Выделить всё

Pointer(wglSwapIntervalEXT) := wglGetProcAddress('wglSwapIntervalEXT');
if @wglSwapIntervalEXT<>nil then  wglSwapIntervalEXT(0);

Помогло не намного. Было около 50-55%, стало 40-45%, рассчитывал на 10-15...
Но, уже какой-то результат. Спасибо.
zub
долгожитель
Сообщения: 2889
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

А нужна ли постоянная перерисовка? тотально разгрузить проц поможет перерисовка только тогда когда "надо"
Аватара пользователя
yeger
новенький
Сообщения: 49
Зарегистрирован: 17.03.2011 11:26:34

Сообщение yeger »

Не очень иллюстративно...
Например, убрал перерисовку из OnAppIdle, сделал только при изменении размера и нажатии чего-то на мыши. Сравнение до- после ничего не дало.
zub
долгожитель
Сообщения: 2889
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

>>Сравнение до- после ничего не дало.
значит чтото неправильно делаете не в отрисовке, например забыт done:=true в обработчике Idle. приложите код.
Аватара пользователя
yeger
новенький
Сообщения: 49
Зарегистрирован: 17.03.2011 11:26:34

Сообщение yeger »

"забыт done:=true в обработчике Idle" - совершенно верно. 8-)

Все заработало лучше чем ожидалось. Теперь загрузка процессора, что называется "скачет" 0-45%, что вполне меня устраивает.

Спасибо за ответы.
Аватара пользователя
jhonyxakep
новенький
Сообщения: 24
Зарегистрирован: 23.08.2010 14:45:35

Сообщение jhonyxakep »

Совет на будущее - делайте отрисовку по таймеру. Сам недавно столкнулся с проблемой нагрузки на процессор.
Ответить