Russian Qt Forum

Qt => Вопросы новичков => Тема начата: Pritcher от Май 05, 2015, 18:46



Название: [РЕШЕНО] Оптимизации рендеринга QGraphicsView на разных платформах
Отправлено: Pritcher от Май 05, 2015, 18:46
Привет!
Я разрабатываю пиксельный графический редактор. Все реализуется с помощью QGraphicsScene & QGraphicsView с вьюпортом QOpenGLWidget. Есть необходимость выделять текущий пиксель (находящийся под курсором). Для этого я в методе QGraphicsView::drawForeground отрисовываю точку методом QPainter::drwaPoint. Помимо этого есть док, в котором отображаются координаты текущего положение курсора. Итого в методе QGraphicsScene::mouseMoveEvent происходит emit сигнала для сообщения о смене положения курсора.
На Linux такое решение поставленной задачи не приносит хлопот, всё отрисовывается так, как и задумывалось. На Windows 7 же без принудительного вызова update() по рабочей области в методе mouseMoveEvent вызов drawForeground не происходит, а => нет отрисовки пикселя. У меня на стационарном ПК стоит старенький Athlon 5000+ 2х2.6 Гц, Win7 и все эти операции занимают у моего проца около 70%. Товарищи смеются, а у меня никаких идей, как можно было бы сократить нагрузку. Может, кто-нибудь предложит что-нибудь конструктивное?
На моём ноуте Linux, i5 4x2.6, жрёт максимум 5%.
У товарища на ноутбуке Win8 i3 4х2.5 — 13,5%.

P.S. Пробовал ставить фиксированный фпс (50-60 апдейтов в секунду), вызывая QGraphicsView::setViewportUpdateMode( QGraphicsView::NoViewportUpdate ), особых изменений не было.
Крутой нагрузки в методе drawForeground нет, лишь проверка на попадание курсора в рабочую область и отрисовка около 100 различных примитивов с помощью QPainter (пиксельная сетка, тайловая сетка, тайловые номера).
При этом опытным путем выяснено, что основная нагрузка именно на update(), вызываемом в mouseMoveEvent.

P.S.S. Изначально курсор был отдельным элементом QGraphicsItem, но от этой идеи пришлось отказаться, т.к. при масштабировании квадратик курсора размером в 1 пиксель имел сторону несколько бОльшую, чем квадратик, отображаемый как пиксель QImage. Таким способом можно было бы отказаться от постоянной перерисовки всей сцены, но проблему с одинаковыми сторонами не решил.


Название: Re: Оптимизации рендеринга на разных платформах
Отправлено: Racheengel от Май 06, 2015, 01:11
Пикселы на QGraphicsScene это печально :( Надо свою отрисовку через QPainter делать.


Название: Re: Оптимизации рендеринга на разных платформах
Отправлено: Igors от Май 06, 2015, 09:29
Создать окно (а не просто виджет) наверху и двигать его, тогда этим займется ОС, сцена перерисовываться не будет. Правда это немалые хлопоты с фокусом, но все лучше чем перерисовка (потенциально огромной) сцены (у меня с OpenGL)


Название: Re: Оптимизации рендеринга на разных платформах
Отправлено: Pritcher от Май 06, 2015, 10:17
Создать окно (а не просто виджет) наверху и двигать его, тогда этим займется ОС, сцена перерисовываться не будет. Правда это немалые хлопоты с фокусом, но все лучше чем перерисовка (потенциально огромной) сцены (у меня с OpenGL)

Идея интересная!
Но вот сама реализация редактора на QGraphicsScene имеет место быть? Или же стоит реализовывать всё на QWidget, с рисованием на QImage (как это сделано, например,  в редакторе EasyPaint (http://qt-apps.org/content/show.php/EasyPaint?content=140877))?


Название: Re: Оптимизации рендеринга на разных платформах
Отправлено: Igors от Май 06, 2015, 10:33
Но вот сама реализация редактора на QGraphicsScene имеет место быть?
Перечитал первый пост. Если юзаете QOpenGLWidget - то можно просто создать обычный виджет (не окно) наверху. Собственно в этом и достоинство QOpenGLWidget - его можно совмещать, комбинировать с другими и/или обычными как угодно, это не вызывает перерисовок всей сцены (в отличие от QGLWidget или QOpenGLWindow). Точнее: рисование будет вызвано, но его можно пропустить, останется старый буфер.

С точки зрения пиксельного редактора - ну хз, я не вижу зачем здесь вообще OpenGL если операции растровые. Ну может как-то "на перспективу"


Название: Re: Оптимизации рендеринга на разных платформах
Отправлено: Pritcher от Май 06, 2015, 15:40
Перечитал первый пост. Если юзаете QOpenGLWidget - то можно просто создать обычный виджет (не окно) наверху. Собственно в этом и достоинство QOpenGLWidget - его можно совмещать, комбинировать с другими и/или обычными как угодно, это не вызывает перерисовок всей сцены (в отличие от QGLWidget или QOpenGLWindow). Точнее: рисование будет вызвано, но его можно пропустить, останется старый буфер.

С точки зрения пиксельного редактора - ну хз, я не вижу зачем здесь вообще OpenGL если операции растровые. Ну может как-то "на перспективу"

Хм, дельное замечание по поводу QOpenGLWidget. Я его применял по причине того, что рендеринг был быстрее, без него текущий пиксель не всегда успевал за курсором. Но это было на ранней стадии разработки, когда не было никаких оптимизаций и было немалое количество неверных решений. Сейчас же убрал этот вьюпорт, собрал с -O3 и загруженность процессора упала. Хоть и грузит всё ядро на моём проце, но уже одно и довольно терпимо в целом. Пиксель под курсором раньше был больше размером потому, что QRectF размером 1х1 в Qt почему-то больше, чем точка, рисуемая QPainter::drawPoint.

Спасибо за совет.


Название: Re: Оптимизации рендеринга на разных платформах
Отправлено: Pritcher от Май 06, 2015, 19:25
Ну что ж, вроде, смог снизить нагрузку на моём проце до 25% в самых "тяжелых" моментах.
Создал таймер с интервалом в 16 мсек, добавил в mousePressEvent:

Код
C
if ( _mouseTimer.remainingTime() )
   return;
_mouseTimer.start();


Название: Re: Оптимизации рендеринга на разных платформах
Отправлено: Igors от Май 07, 2015, 07:02
Ну что ж, вроде, смог снизить нагрузку на моём проце до 25% в самых "тяжелых" моментах.
Что-то "не то", все равно слишком много. Неясно Вы используете QOpenGLWidget или уже от него отказались. Если используете - поставьте печать на каждое его paintGL, увидите много интересного


Название: Re: [РЕШЕНО] Оптимизации рендеринга QGraphicsView на разных платформах
Отправлено: Fregloin от Май 07, 2015, 09:10
какая версия Qt у вас? Если 5я, то нет смысла заморачиваться с QGLWidget. Если 4я то тут я не помощник, хотя у меня сложные сцены рисовались побыстрее чем у вас в любом случае.
Попробуйте поиграться с параметрами кеширования сцены.


Название: Re: [РЕШЕНО] Оптимизации рендеринга QGraphicsView на разных платформах
Отправлено: Pritcher от Май 09, 2015, 09:15
]Что-то "не то", все равно слишком много. Неясно Вы используете QOpenGLWidget или уже от него отказались. Если используете - поставьте печать на каждое его paintGL, увидите много интересного

Что вы имеете в виду под "печатью"?

Отказался.
Дело в том, что у меня процессор в аналогичном редакторе выдаёт ровно такие же цифры в нагрузке, поэтому меня устраивает такая производительность. Протестировал на более современных системах, более 8% не выдаёт.

Когда делаю вьюпорт QOpenGLWidget, то нагрузка в любой момент, когда активно окно приложения, 70%.

Вот собственно мои действия, что привели к уменьшению нагрузки:
1) Оставил родной вьюпорт для QGraphicsView
2) Добавил таймер


какая версия Qt у вас? Если 5я, то нет смысла заморачиваться с QGLWidget. Если 4я то тут я не помощник, хотя у меня сложные сцены рисовались побыстрее чем у вас в любом случае.
Попробуйте поиграться с параметрами кеширования сцены.
У меня Qt 5-ой версии, иначе я не смог бы использовать QOpenGLWidget.
Спасибо за совет, попробую на досуге.