News

Оптимизация вывода текста - 2

Added by Иван Кузьмицкий about 4 years ago

Текстуры, подготовленные для HostPorts.Rider.DrawString, кэшируются в модуле StrTexCache. Ключ для узла - цепочка символов, переданная в DrawString. Производительность улучшилась радикально, можно говорить об ускорении рендера текста на 150 слов в двадцать раз, причём без дальнейшей деградации при увеличении слов в тексте.
Конечно, за скорость приходится платить дополнительными расходами памяти для кэша. Но при наличии специального сборщика, неиспользуемые узлы со временем удаляются из дерева, уменьшая расход памяти.

Оптимизация вывода текста

Added by Иван Кузьмицкий about 4 years ago

Текстовая надпись в x86sdlhostPorts.DrawString создаётся в три этапа:
1) Генерация растра с помощью SDL_TTF
2) Создание текстуры из растра.
3) Натягивание текстуры на прямоугольник.

Генерация растра и создание текстуры - самые тяжёлые операции. Было принято решение оптимизировать этап создания текстуры. Для этого однократно создаётся большая текстура (например, 512х512), а растр из SDL_TTF внедряется в неё как субтекстура с помощью glTexSubImage. Субтекстурирование гораздо быстрее (по моим замерам, в два раза), чем glTexImage, поэтому общий прирост производительности оказался значительным, примерно в 1.6 раза.

До оптимизации: время рендера кадра 0.0053 сек, строка в 30 символов рендерится 3000 раз\сек.
После оптимизации: время рендера кадра 0.0033 сек, строка в 30 символов рендерится 5000 раз\сек.

Дальше надо думать, как ускорить генерацию самого растра.

P.S. Убрал ненужную конвертацию из формата ARGB в BGRA при создании растра шрифта. Это значительно ускоряет дело при рендере текста больших размеров, так как скорость тут падала пропорционально площади текстуры. Прикинул прирост производительности: на маленьких (размер 8-10) шрифтах 15%, на больших (> 40) уже в разы.

Управляемая частота кадров

Added by Иван Кузьмицкий about 4 years ago

До этого момента обновление сцены было жёстко привязано к некоторым событиям - например клик\движение мыши или нажатие кнопки на клавиатуре. Это приводило к тому, что при небольшом замедлении отрисовки кадра в очереди накапливалось много событий, которые отрабатывались уже после того, как пользователь завершал ввод (эффект инерции, перетаскиваемое окно продолжало двигаться после отпускания мышки, ведь в очереди накопилось несколько позиций курсора).

Теперь же каждый кадр отрисуется не раньше, чем наступит его время, определяемое константой limitFPS. Это даст возможность обрабатывать события в промежутках между отрисовкой сцены, сохраняя постоянную частоту кадров.

Асинхронное перетаскивание

Added by Иван Кузьмицкий over 4 years ago

Оконный менеджер WmClassic перетаскивал окна и изменял размеры окон синхронно, внутри своего фрейма с использованием f.Input в цикле. Перерисовка всей сцены в таком режиме производилась непосредственно, внутри цикла, посыланием сообщения наверх через шину контекста.
Такой же способ перерисовки использовался при всех манипуляциях с окнами и меню. В некоторых ситуациях это приводило к тому, что перерисовка при закрытии окна уничтожало фрейм, внутри которого шла обработка нажатия мыши.

Решил провести эксперимент по отказу от синхронной перерисовки. Идеальный полигон для этого - механизм перетаскивания окон. Решение основано на идее ответственности контейнера за перетаскивание. Оконный контейнер сам определяет моменты начала и окончания перетаскивания и генерирует соответствующие сообщения. Таким образом, получилось избавиться от синхронного цикла. А перерисовка сцены происходит автоматически, в обработчике событий главного окна, по принципу "пришло сообщение, обновили сцену".

Перерисовка по шине контекста не убрана до конца, это хороший способ затыкания дыр (убрать его совсем невозможно, каркас был слишком сильно завязан на особенности ОС). Но использовать его как генеральный метод нельзя.

Ещё одно изменение касается поведения главного меню. Раньше окно подменю самостоятельно обозначало момент собственного закрытия, потом определением этого момента занималось отображение главного меню, а в итоге управлением окнами меню возложено полностью на модуль WmClassic. Это позволило избавиться от противоречивых ситуаций (например, главное меню при потере фокуса закрывало подменю после того, как произошла перерисовка, отчего требовалось дополнительное обновление сцены).

Альфа-версия

Added by Иван Кузьмицкий over 4 years ago

Альфа-версия (или даже пре-альфа) предназначена для тестирования внутри сообщества. Хотя всё ещё очень сырое, но основные механизмы работают. Есть меню, можно открыть документ, набрать текст, откомпилировать модуль и выполнить команду в коммандере.

Основным мотивом к выпуску альфы послужили модальные диалоги. Здесь их просто нет, поэтому нужно решать - либо мы избавляемся от модальности навсегда, либо продолжаем поддерживать модальность и дальше.

Вопрос модальности поднимался тут: http://forum.oberoncore.ru/viewtopic.php?p=78971#p78971

Диалог открытия файла

Added by Иван Кузьмицкий over 4 years ago

Реализованы некоторые контролы из HostCFrames, что позволило сделать собственный диалог открытия файла. Но он не модальный, что ломает всю логику ядра, завязанную на GetIntSpec.

Короче, надо думать. Либо полностью отказываться от модальности и внести изменения во Views и другие модули ядра. Либо эмулировать модальность средствами каркаса, пилить отдельный модальный режим для окна.

Прокрутка заработала

Added by Иван Кузьмицкий over 4 years ago

Модуль StdScroller практически без изменений скопирован в WmScrollers. Добавлена только возможность обёртки указанного отображения. Рисование скроллера (кнопки, ползунок) и обработка действий производится в x86sdlhostCFrames.

Как это сделано. Отображение слота оборачивается скроллером и открывается в окне WmWindows.Window. Все сообщения проходят в документ и ниже - в текст, который реагирует на прокрутку эталонно. никаких дополнительных архитектурных решений не требуется. Скроллер при отрисовке требует фрейм из x86sdlhostCFramesи возвращает его каркасу.

Единственное, что потребуется в дальнейшем - вынос рисования всех фреймов из x86sdlhostCFrames в отдельные модули, чтобы не перегружать x86sdlhostCFrames (в нём содержатся конструкторы всех стандартных контролов).

Осмысление текущих проблем

Added by Иван Кузьмицкий over 4 years ago

Финальный заход на открытие файла + компиляция + сохранение файла упёрся в очевидные проблемы.

Цепочка HostCmds.Open -> HostDialog.GetIntSpec -> виндовый диалог выбора файла. Надо делать собственный, но формы ещё не отработаны и нужных контролов нет.

Так что примерный план дальнейшего движения такой.

1) Есть скроллер, его приспособлю к документу, сразу и проверю в работе.
2) Открытие формы.
3) Делаю новый контрол ListBox.
4) Адаптирую CpcFileBrowser.

Для поднятия альфа-версии нового ББ этого будет достаточно.

HostMenus перестал существовать

Added by Иван Кузьмицкий over 4 years ago

Рендер менюшек делается средствами оконного менеджера, сейчас это модуль WmMenus.

Эталонные структуры и алгоритмы меню (избавленные от следов WinApi) согнаны в модуль System\Menus (возможно, правильнее было бы в StdMenus).
Более ничего в HostMenus не осталось, он удалён.

Акселератор меню отрабатывает шорткаты перед тем, как сообщение попадёт в главное окно. В эталоне происходило немного по-другому: акселератор по комбинации нажатых пользователем клавиш отыскивал код пункта меню и формировал сообщение для окна. Сообщение отрабатывалось в обработчике собыий окна, где задействовались необходимые команды каркаса. Другими словами, не-оконные команды запускались из фокусного окна, что не очень логично.

Перетаскивание работает

Added by Иван Кузьмицкий over 4 years ago

Переделал x86sdlhostMechanisms.TrackToDrop в новом свете. Появилась, кстати, новая сущность x86sdlhostAppWin.Window, это задел на поддержку SDL-мультиоконности.

Перетаскивание учитывает возможность появления нескольких SDL-окон, поэтому в цикле перетаскивания сначала определяется окно SDL, а затем в связанный с ним объект x86sdlhostAppWin.Window форвардится PollDrop. Сообщение PollDrop проходит по шине сквозь все объекты оконного менеджера, попадая в слот x86sdlhostSlots.Slot, и уже от него сваливается в окно каркаса Windows.Window.
По окончании дропа инициируется отложенная перерисовка окна, отложенная - потому что после дропа необходимо сначала дать возможность отработать контейнеру системного слоя ББ, а уже потом перерисовывать.

Таким образом, мы получили расширяемую и контролируемую коммуникацию объектов каркаса сквозь SDL-окна и обслуживающую инфраструктуру.

1 2 (1-10/17)

Also available in: Atom