Как увеличить скорость отрисовки на canvas?
Модератор: Модераторы
В редактор эл. схем, типа KiCAD, Geda, интересная для меня тема, хочу повозиться, да и опыта практического набраться не мешало бы. Это такая тема, которую я смутно представляю, решил на реальном примере, восполнить пробелы в опыте и знаниях.
Вот http://wiki.lazarus.freepascal.org/Turbo_Circuit возможно будет полезно. Но там сделано на основе fpvectorial - не советую его юзать - недопилен.
>>Это такая тема, которую я смутно представляю, решил на реальном примере, восполнить пробелы в опыте и знаниях.
Эту тему вообще мало кто хорошо представляет, но все горазды советовать, особенно на лоре))
>>Это такая тема, которую я смутно представляю, решил на реальном примере, восполнить пробелы в опыте и знаниях.
Эту тему вообще мало кто хорошо представляет, но все горазды советовать, особенно на лоре))
Последний раз редактировалось zub 03.03.2014 14:05:27, всего редактировалось 2 раза.
Можно использовать в работе, в том же KiCAD, или свою телегу запилить, это уже вопрос отдельный, сейчас мне бы главное начать, но чтобы начать, необходимо понять некоторые фундаментальные вещи )
Т.к. "компонет" обычно не сложная графическая еденица - можешь оптимизацией вообще не заморачиваться, делай всё в лоб, будет нормально работать. Потом по мере появления проблем будешь оптимизировать - переделывать. Изначально "правильного" пути тебе никто не подскажет))
Не не, немного не поняли. Как рисовать компонент, я знаю, меня интересуют концептуальные вещи. Т.е например, можно не париться, и рисовать всё как есть в границах ClientWindow, добавить масштабирование, путём умножения всего и вся на коэффициент, но ведь это будет не правильно? Например, вы в своём CAD как выводите информацию? Вы сразу определили какую-то область, на которой всё рисуете, а дальше просто всю эту область масштабируете?
- debi12345
- долгожитель
- Сообщения: 5761
- Зарегистрирован: 10.05.2006 23:41:15
- Откуда: Ташкент (Узбекистан)
Уберите вы этот guiif = interface, используйте обычные классы
Да, так значительно (те самые 5% проигрыша) быстрее, но придется делать неуклюжую вещь -
объявлять и имплементить все позднее переопределяемые методы пустыми в парент-классе - иначе полиморфизма не получишь.
Странно что использование безметодового (абстрактного) класса (=интерфейса) приводит к таким тормозам. Скорее всего дело именно в "безметодовости" (невозможности прописать VMT-зависимости на этапе компиляции).
Добавлено спустя 5 минут 6 секунд:
function test(TestImpl:Boolean;param:TParamType):TParamType;virtual;abstract;
ABSTRACT - в-о-о-т где его применение оказывается ! Не пользовался ранее - возьму на заметку
xterro
Я использую OpenGL, соответственно масштаб и сдвиг модели сидит в матрице прецирования.
Допустим есть отрезок 0,0;1,1 - в зкаде всегда и выводится по этим координатам, независимо от зума и сдвига. Но зум и сдвиг участвует в формировании матрицы проецирования. Искллючение состовляют мелкие детали вдали от начала координат (с удалением больше 10e6), там я вычитаю из координат примитивов некую величину - центр виевфрустума - т.е. сдвигаю всё к началу координат, иначе появляется погрешность внутренних глных вычислений.
Канвас такое сделать не позволит, там координаты надо будет корректировать во время вывода. Но имхо какиелибо вычисления в момент отображения информации - зло, их надо по возможности избегать - считать зарание и хранить. ИМХО умножение и сложение (масштаб и сдвиг) можно оставить на момент вывода, а вот более сложные требующие умножения на матрицы - вращения, скосы, проекции считать заранее.
Кроме того если картинка не менялась, но ее требуется перерисовать - лучше не рисовать всё заново а восстановить каким либо быстрым способом (естественно перед этим ее нужно было сохранить в соответствующем виде) зкад умеет восстанавливать текстурами, AUX и ACCUM буферами, сохранением копии в памяти и полной перерисовкой - подходящий способ можно указать в настройках. В случае PaintBox насколько я понимаю этот пункт не понадобится
Ну и нужна отбраковка невидимых примитивов, хранение примитивов в какихлибо древовидных структурах для быстрого геометрического поиска и "пакетной" отбраковки невидимых примитивов.
еще - тут всплывали пунктирные линии предоставляемве канвасом. OpenGL предоставляет подобное, но я их использую только для отображения выделенных примитивов, если нужна какаянибудь штрихпунктирная линия - координаты всех штрихов расчитываю и рисую отдельными примитивами - сложно, но зато плный контроль как выглядит результат и практически любые типы штрихов, вплоть до надписей вставленных в линию
Я использую OpenGL, соответственно масштаб и сдвиг модели сидит в матрице прецирования.
Допустим есть отрезок 0,0;1,1 - в зкаде всегда и выводится по этим координатам, независимо от зума и сдвига. Но зум и сдвиг участвует в формировании матрицы проецирования. Искллючение состовляют мелкие детали вдали от начала координат (с удалением больше 10e6), там я вычитаю из координат примитивов некую величину - центр виевфрустума - т.е. сдвигаю всё к началу координат, иначе появляется погрешность внутренних глных вычислений.
Канвас такое сделать не позволит, там координаты надо будет корректировать во время вывода. Но имхо какиелибо вычисления в момент отображения информации - зло, их надо по возможности избегать - считать зарание и хранить. ИМХО умножение и сложение (масштаб и сдвиг) можно оставить на момент вывода, а вот более сложные требующие умножения на матрицы - вращения, скосы, проекции считать заранее.
Кроме того если картинка не менялась, но ее требуется перерисовать - лучше не рисовать всё заново а восстановить каким либо быстрым способом (естественно перед этим ее нужно было сохранить в соответствующем виде) зкад умеет восстанавливать текстурами, AUX и ACCUM буферами, сохранением копии в памяти и полной перерисовкой - подходящий способ можно указать в настройках. В случае PaintBox насколько я понимаю этот пункт не понадобится
Ну и нужна отбраковка невидимых примитивов, хранение примитивов в какихлибо древовидных структурах для быстрого геометрического поиска и "пакетной" отбраковки невидимых примитивов.
еще - тут всплывали пунктирные линии предоставляемве канвасом. OpenGL предоставляет подобное, но я их использую только для отображения выделенных примитивов, если нужна какаянибудь штрихпунктирная линия - координаты всех штрихов расчитываю и рисую отдельными примитивами - сложно, но зато плный контроль как выглядит результат и практически любые типы штрихов, вплоть до надписей вставленных в линию
- debi12345
- долгожитель
- Сообщения: 5761
- Зарегистрирован: 10.05.2006 23:41:15
- Откуда: Ташкент (Узбекистан)
Да, так значительно (те самые 5% проигрыша) быстрее
Один нюанс - это на одном только вызове. Если подряд выстроить много таких вызовов (например реализовав классы TPixel и TRect и работая через их методы при рисовании примитивов) - получим уже серьезные тормоза.
3 обращения = 1.05 pwr3 -1 = 16%
5 обращений = 1.05 pwr 5 -1= 28%
10 обращений = 1.05 pwr 10 -1 = 63%
debi12345
>>TRect
Если все реализовать с головой никаких тормозов не будет, ну начертили вы 500 ректов - вызвали 500 раз виртуальный TMyImplGUI.DrawRect... Как тут уже замечали виртуальный вызов против внешнего вызова OpenGL - ничто по затратам.
>>TPixel
Так делать програмиста отучит общая тормознутость "прямого" "пиксельного" доступа к видеопамяти, а не невидимые на ее фоне затраты на виртуальный вызов.
Купите уже зажигалку, а не экономте на спичках))
>>TRect
Если все реализовать с головой никаких тормозов не будет, ну начертили вы 500 ректов - вызвали 500 раз виртуальный TMyImplGUI.DrawRect... Как тут уже замечали виртуальный вызов против внешнего вызова OpenGL - ничто по затратам.
>>TPixel
Так делать програмиста отучит общая тормознутость "прямого" "пиксельного" доступа к видеопамяти, а не невидимые на ее фоне затраты на виртуальный вызов.
Купите уже зажигалку, а не экономте на спичках))
Допустим есть отрезок 0,0;1,1 - в зкаде всегда и выводится по этим координатам, независимо от зума и сдвига.
Как раз интересный момент затронули, появился вопрос. В OpenGL координаты у нас от -1 до 1 по X и по Y, но пользователь привык к обычным координатам, с началом скажем в нижнем левом углу, и привык к циферкам типа X:800 Y:540. Соответственно и в файле данных(т.е куда сохраняем нашу картинку) координаты тоже должны храниться в каком то таком виде. Не будут же они храниться в виде скажем: -0,2;0,5? Или например обработка кликов мышки, там всё в координатах окна, т.е кликнули, получили цифра, скажем 400, 300 и как теперь проверить, что кликнули по линии, перевести как-то в координаты OpenGL? Как вы решали этот вопрос?
- debi12345
- долгожитель
- Сообщения: 5761
- Зарегистрирован: 10.05.2006 23:41:15
- Откуда: Ташкент (Узбекистан)
Ну и нужна отбраковка невидимых примитивов, хранение примитивов в какихлибо древовидных структурах для быстрого геометрического поиска
Хм, для облегчения этих страданий пил юзает даже игровые движки :
http://forum.cadstudio.ru/index.php?topic=25124.0.html
http://forum.cadstudio.ru/index.php?topic=20948.0.html
!
против внешнего вызова OpenGL -
АФАЙК, эти вызовы асинхронные - принимаемые в GL-конвенйер, то есть без ожидания, мгновенные, не сильно дольше чем "i:= i+1". Или ошибаюсь ?
xterro
Координаты там абсолютно любые 0,0;1,1- просто пример, почитайте как настраивается матрица проецирования в "режиме" GLOrtho. Можно настроить для совпаденеия пиксел в пиксел, можно "бесплатно" учесть зум и сдвиг
debi12345
Игровые движки для СAD мало пригодны, смысл получить не статическую красивую картинку, а полностью редактируемый чертеж - много своей специфики.
>>АФАЙК, эти вызовы асинхронные
Асинхронные, но не бесплатные, копят данные но рано или поздно начинают их жевать. Кстати сделанны через указатель на процедуру в opengl.pas от fpc
>>10 обращений = 1.05 pwr 10 -1 = 63%
Хитрый расчет, если следовать ему LCL вообще должен стоять и не выполняться. представте сколько там вложенных виртуальных вызовов)) то что 5% было получено для maxint идущих подряд вызовов ни о чем не говорит?))
Координаты там абсолютно любые 0,0;1,1- просто пример, почитайте как настраивается матрица проецирования в "режиме" GLOrtho. Можно настроить для совпаденеия пиксел в пиксел, можно "бесплатно" учесть зум и сдвиг
debi12345
Игровые движки для СAD мало пригодны, смысл получить не статическую красивую картинку, а полностью редактируемый чертеж - много своей специфики.
>>АФАЙК, эти вызовы асинхронные
Асинхронные, но не бесплатные, копят данные но рано или поздно начинают их жевать. Кстати сделанны через указатель на процедуру в opengl.pas от fpc
>>10 обращений = 1.05 pwr 10 -1 = 63%
Хитрый расчет, если следовать ему LCL вообще должен стоять и не выполняться. представте сколько там вложенных виртуальных вызовов)) то что 5% было получено для maxint идущих подряд вызовов ни о чем не говорит?))
- debi12345
- долгожитель
- Сообщения: 5761
- Зарегистрирован: 10.05.2006 23:41:15
- Откуда: Ташкент (Узбекистан)
Хотя, чтобы не быть голословным, заменив "i:= i +1" на "Load_GL_EXT_abgr;", получил проигрыш в несчастный 1%. Хотя конкретно эта GL-команда - не конвейерная.
Но согласитесь что желательно искать решения для максимального (в данном случае - молотильного) алгоритма, тогда и в будущем (ускорение отрисовки за счет умощнения аппаратуры и т.п.) не возникнет проблем масштабируемости. А они уже возникли у ТС - слабый проц (делающий 5% заметным по времени) и мощная (делающая накопленные "5% pmr дофига" относительно более чувствительным импактом) видяха.
Добавлено спустя 5 минут 59 секунд:
Не стоять, а подтормаживать :
10 вызовов = 65% = меньше 2 раз
30 вызовов (близко к реальности) = 3 раза (тоже близко к реальности на молочении)
100 вызовов = 130 раз
Добавлено спустя 7 минут 10 секунд:
Хотя что-то я стормозил - тестировал-то на 10млн вызовов. И только на них набралось 5%
На 30-ти вообще нет никакой разницы.
то что 5% было получено для maxint идущих подряд вызовов
Но согласитесь что желательно искать решения для максимального (в данном случае - молотильного) алгоритма, тогда и в будущем (ускорение отрисовки за счет умощнения аппаратуры и т.п.) не возникнет проблем масштабируемости. А они уже возникли у ТС - слабый проц (делающий 5% заметным по времени) и мощная (делающая накопленные "5% pmr дофига" относительно более чувствительным импактом) видяха.
Добавлено спустя 5 минут 59 секунд:
Хитрый расчет, если следовать ему LCL вообще должен стоять и не выполняться
Не стоять, а подтормаживать :
10 вызовов = 65% = меньше 2 раз
30 вызовов (близко к реальности) = 3 раза (тоже близко к реальности на молочении)
100 вызовов = 130 раз
Добавлено спустя 7 минут 10 секунд:
Хотя что-то я стормозил - тестировал-то на 10млн вызовов. И только на них набралось 5%
Соглашусь - Когда не остается возможности алгоритмической оптимизации не грех попытаться помочь компилятору сгенерировать более оптимальный код, но только постоянно свяряясь с профайлером, чтоб не обречь себя ради мнимой выгоды на мучительные воспоминания - что же я хотел сделать в этом куске кода?))
Да проигрышь в несколько процентов и выигрышь в читаемости кода (по мне тоже не бог весть какой) признаю. Но это полная ерунда по сравнению с отсутствием аппаратной акселерации у MiniQ
Вы так ръяно отстаиваите принципы MSE, но думаю она бы в подобной ситуации проиграла еще больше (не используя OpenGL) - т.к. на злополучной железке выступала бы против Qt который рисует контролы для LCL))
Да проигрышь в несколько процентов и выигрышь в читаемости кода (по мне тоже не бог весть какой) признаю. Но это полная ерунда по сравнению с отсутствием аппаратной акселерации у MiniQ
Вы так ръяно отстаиваите принципы MSE, но думаю она бы в подобной ситуации проиграла еще больше (не используя OpenGL) - т.к. на злополучной железке выступала бы против Qt который рисует контролы для LCL))
- debi12345
- долгожитель
- Сообщения: 5761
- Зарегистрирован: 10.05.2006 23:41:15
- Откуда: Ташкент (Узбекистан)
Вы так ръяно отстаиваите принципы MSE
Даже не думал об этом. Однако по инерции мышления применять ООП для молотильного и рисовального кода рука не поднималась - а оказывается (как выявило сегодняшнее практическое тестирование) не так страшен черт как его малюют. Ведь BLENDER весь написан на C++ ООП - и ничего, воркабален
.
но думаю она бы в подобной ситуации проиграла еще больше
Ну, Мартин использует кое-какие трюки и все тщательно тестирует на перформанс (до сих пор сидя на слабой машине), начиная с двойной буферизации.
