Russian Qt Forum
Ноябрь 26, 2024, 10:06 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Нагрузка на процессор и QWidgetBackingStore  (Прочитано 6967 раз)
kamil
Гость
« : Январь 18, 2016, 14:28 »

Столкнулся с проблемой, в приложении есть QGraphicsView, вывод которого идет через QOpenglWidget, для разгрузки процессора.
QGraphicsView обновляется на частоте примерно 30Гц, и если обновляется только он, то нагрузка на процессор 10-15%:

Но если еще и обновлять другие элементы ui, например QLabel на той же частоте, то нагрузка возрастает до процентов 40%:

Если, например QGraphicsView удалить из ui, то даже при обновлении QLabel нагрузка не превысит 5%.

С чем может быть связано такое странное поведение?

То, что я смог увидеть в профайлере это то, что функция convertRGBA8888FromARGB32PM_sse4(unsigned int*, unsigned int const*, int, QPixelLayout const*, unsigned int const*) начинает вызываться намного чаще. Эта функция, в свою очередь вызывается из QWidgetBackingStore::sync(). В документации по поводу QWidgetBackingStore::sync() сказано:

Synchronizes the backing store, i.e. dirty areas are repainted and flushed.

Но не понятно почему он начинает вызываться чаще, если в ui есть QGraphicsView.
Может у кого есть соображения по этому поводу?

Mac OS X 10.11.2
Qt 5.5.1 Clang x64
« Последнее редактирование: Январь 18, 2016, 21:12 от kamil » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #1 : Январь 18, 2016, 15:35 »

Напрашивается вывод что обновление QLabel ведет к обновлению всего окна, или самой его затратной части - сцены. Покажите как (какими вызовами) обновляете то и это
Записан
kamil
Гость
« Ответ #2 : Январь 18, 2016, 16:59 »

Да, это первая мысль, которая приходит в голову.

Для обновления всего используется один таймер, который вызывается с частотой примерно 30 Гц.
Слот update() viewport'a QGraphicsView, соединен с сигналом timeout таймера.
Слот, в котором вызывается QLabel::setText("..."), тоже подсоединен к сигналу timeout таймера.

А для чего вообще нужен QWidgetBackingStore? Из описания в документации я не до конца понял.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #3 : Январь 19, 2016, 09:26 »

А для чего вообще нужен QWidgetBackingStore? Из описания в документации я не до конца понял.
Это кеш окна, сначала содержимое формируется в нем, а потом выводится на экран. При использовании OpenGL да, перерисовка кнопки ведет к перерисовке всего окна. Я спрашивал у Qt почему, мне посоветовали использовать QOpenGLWindow если хочу макс производительности. Так я и сделал. Хотя это было минимум с год назад, может проблема уже и решена.

Для обновления всего используется один таймер, который вызывается с частотой примерно 30 Гц.
Слот update() viewport'a QGraphicsView, соединен с сигналом timeout таймера.
Слот, в котором вызывается QLabel::setText("..."), тоже подсоединен к сигналу timeout таймера.
Попробуйте setUpdatesEnabled(false) для QGraphicsView. В какой момент делать setUpdatesEnabled(true) - хз, пока просто посмотрите что с загрузкой. Ну и "радикальное" решение - не использовать OpenGL, если нет массивной геометрии он не особо выгоден.
Записан
kamil
Гость
« Ответ #4 : Январь 19, 2016, 14:56 »

Цитировать
Ну и "радикальное" решение - не использовать OpenGL, если нет массивной геометрии он не особо выгоден.

Без OpenGL, к сожалению не прокатит. В QGraphicsView идет отрисовка HUD поверх видео, если делать это на процессоре, то одно ядро загрузиться как минимум процентов на 40%, и это на i5.

Если отключть обновления setUpdatesEnabled(false) QGraphicsView, то нагрузка все равно слишком высока, не смотря на то, что отрисовка на QGraphicsView не идет, QWidgetBackingStore::sync() все так же есть больше всех остальных. Что это может значить?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #5 : Январь 20, 2016, 13:32 »

Если отключть обновления setUpdatesEnabled(false) QGraphicsView, то нагрузка все равно слишком высока, не смотря на то, что отрисовка на QGraphicsView не идет, QWidgetBackingStore::sync() все так же есть больше всех остальных. Что это может значить?
Убедитесь что до вызовов paint дело не доходит при setUpdatesEnabled(false). Если грузит и без paint - ну значит слишком много жрет "compositing" (QOpenGLWidget сначала рендерится в текстуру, а потом окно "собирается" в общую текстуру и уже выводится OpenGL). Тогда переходите на QOpenGLWindow, там мелкие проблемы с ивентами, но с производительностью все "как доктор прописал". Вот только обычные виджеты поверх QOpenGLWindow - увы, нельзя
Записан
kamil
Гость
« Ответ #6 : Январь 23, 2016, 18:56 »

Да, похоже надо переходить на QOpenGLWindow. Только вот не до конца понятно из документации как в качестве viewport для QGraphicsView назначить QOpenGLWindow.
Я правильно понимаю что надо внутри конструктора QGraphicsView создать QWidget используя QWidget::createWindowContainer() и потом передать получившийся контейнер в setViewport(widget)?
Я попробовал так подсунуть, но на месте виджета черная картинка.

UPD:
Все, уже нашел что установить QOpenGLWindow в качестве viewport не получится.
Как тогда наиболее безболезненно перетащить в QOpenGLWindow QGraphicsVideoItem? Как это вообще можно сделать?

UPD2:
Если использовать устаревший QGLWidget то нагрузка становится нормальной, но при изменении размера виджета, область под  QGraphicsView вначале закрашивается черным, а потом только новым содержимым, может кто знает, можно ли это побороть. Если можно, то вариант с устаревшим QGLWidget меня устроит.
« Последнее редактирование: Январь 23, 2016, 20:49 от kamil » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #7 : Январь 24, 2016, 13:18 »

Все, уже нашел что установить QOpenGLWindow в качестве viewport не получится.
Если нетрудно покажите где это написано
Как тогда наиболее безболезненно перетащить в QOpenGLWindow QGraphicsVideoItem? Как это вообще можно сделать?
Никогда не использовал QGraphicsVideoItem, не подскажу. Можно попробовать перед рисованием сделать контекст QOpenGLWindow текущим (в перекрытом QGraphicsVideoItem::paint)
Если можно, то вариант с устаревшим QGLWidget меня устроит.
Там тоже несладко, "зато" перспектив ноль, а в след версии Qt от такого legacy может и избавятся
Записан
kamil
Гость
« Ответ #8 : Январь 24, 2016, 15:57 »

Все, уже нашел что установить QOpenGLWindow в качестве viewport не получится.
Если нетрудно покажите где это написано

http://blog.qt.io/blog/2014/11/20/qt-weekly-20-completing-the-offering-qopenglwindow-and-qrasterwindow/:

Pascal Henze
Can i use QOpenGLWindow as viewport of a QGraphicsView to enable openGL drawing in a QGraphicsScene ?

Laszlo AgocsLaszlo Agocs
No, you can only use QGLWidget or QOpenGLWidget as a viewport for widgets.

Вроде как в официальном блоге qt. Но может с 21.11.2014 что-то изменилось, я не знаю.


Если можно, то вариант с устаревшим QGLWidget меня устроит.
Там тоже несладко, "зато" перспектив ноль, а в след версии Qt от такого legacy может и избавятся

Согласен, что это не самый лучший вариант, так что буду пробовать делать с QOpenGLWindow.

UPD:
Хорошо, а как для начала правильно выводить QGraphicsItem в QOpengGLWindow? Через QPainter painter(this), или есть что попроще?
« Последнее редактирование: Январь 24, 2016, 16:21 от kamil » Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.13 секунд. Запросов: 23.