Privacy policyContactsAbout siteOpinionsGitHubDonate
© EVILEG 2015-2018
Recommend hosting
TIMEWEB

Qt и Direct3D 12 - Первая встреча

D3D12, Direct3D, Qt, Qt Blog, QtD3D12Window

Перевод официальной новости, автор Laszlo Agocs

Лицо графических API изменяется. Qt Quick 2 был выпущен в 2012 году с Qt 5.0, и опирался на OpenGL и OpenGL ES 2.0. С тех пор были введены изменения и улучшения - был введён Qt Quick 2D Renderer, были проведены эксперименты с программной растеризацией, и добавлена система обеспечения для новейших версий OpenGL в весь графический стек Qt. Однако, как заметил Lars в своём выступлении на Всемирном саммите Qt 2015, ситуация изменяется: новые, низкоуровневые, более эффективные API, такие как Vulkan, Metal и Direct3D 12, собираются стать широко доступны. Некоторые из них ориентированы на конкретные платформы, делая их лучшим выбором в вопросе таргетирования на конкретные платформы, в то время как другие, как ожидается, будут поддерживать широкий спектр платформ. В тоже время, делая комплексные прогнозы, ускорение с графическим API не всегда является лучшим выбором: традиционно, рабочий стол пользовательского интерфейса на устаревшем железе иногда лучше запустить с устаревшей отрисовкой на базе CPU.

Таким образом, что не удивительно, одним из направлений исследований в будущих версиях Qt является создание графического стек, и в частности, Qt Quick, более гибким, с поддержкой различных графических API, а также с поддержкой программного рендеринга.

Такие исследовательские работы часто приводят к полезным эффектам, и эта запись об одном таком. Простой Qt модуль включающий интеграцию с Direct3D 12 в отдельном Qt окне - или в качестве альтернативы приложение основанное на QWidget - и делающий это процесс легким для начала экспериментов с современными методами D3D, в то время как Вы продолжаете наслаждаться знакомыми API, инструментами и средой разработки Qt и предлагаемой ей экосистемой.

What it is

QtD3D12Window module, находится в qt-labs репозитории, и является модулем Qt 5.6, который предоставляет QD3D12Window класс, похожий на QOpenGLWindow,  обрабатывается qmake правилом для компиляции HLSL шейдера через fxc, и имеет исчерпывающий комплект примеров для основного использования (наподобие Hello World samples от Microsoft).

What it is not

Прежде, чем пойти дальше, давайте разберёмся, чем этот модуль не является: он не является способом запускать существующие Qt приложения на Direct3D (то есть именно, что предоставляет ANGLE , когда дело доходит до D3D9 и 11), и в любом случае не поддерживает Qt Quick. Это также не является дополнением к Qt в его нынешнем виде, и не является полным движком и фреймворком в любом его виде (интерфейс QD3D12Window явно предлагает недостаточный функционал для сложных и многопоточных решений).

Window

Первым шагом для интеграции с пользовательским кодом рендеринга является новое графическое API, которое создаёт цель рендеринга в нативном окне основанном на QWindow. В настоящее время OpenGL является единственным выборов и глубокого интегрирован в Qt как внутренне (QPA интерфейсы, плагины платформы), так и внешне (публичные API, см. QOpenGL классы в QtGui). Ожидается, что это изменится в будущем, но сейчас, для нашего автономного эксперимента с D3D, мы сделаем всё самостоятельно. Платформенный плагин окна в Qt позволяет легко получить нативный дескриптор окна, как если бы мы использовали QWindow::winId(), который возвращает id окна в Windows в Qt приложение. Мы можем затем использовать DXGI для перечисления доступным адаптеров, и можем выбрать либо аппаратный, либо WARP адаптер, и создать цепочку подкачки (swap). QD3D12Window обработает всё это, причём, достаточно хорошо для основных типичных приложений.

Говоря о DXGI, отметим, что это первый подобный набег на графический адаптер и управление устройством: в то время как с OpenGL и его оконными интерфейсами обычно такие возможности ограничены, другие же API (особенно платформозависимые и привязанные к определённой модели драйвера) могут предлагать больше возможностей по поиску адаптеров и внесению изменений в настройки, удалению сбросу в течению жизненного цикла приложения. Такая функциональность на тех платформах, где доступны API, получит больше внимания в Qt в будущем.

При реализации QD3D12Window, выяснилось, что не требуется создавать какой-либо общий класс - благодаря тому, что QOpenGLWindow и QRasterWindow были введены в Qt 5.4: Общий базовый класс QPaintDeviceWindow  что, конечно вводит в заблуждение в случае с D3D, поскольку наше окно не используется для отрисовки, основанной на QPainter) предоставляет всю необходимую инфраструктуру, что позволяет сфокусироваться в подклассе на особенности графического API при разработке основного функционала, такого как метод update(). Это хорошие новости, что данная наработка позволяет легко экспериментировать с другими API в будущем (QMetalWindow, QVulkanWindow, и т.д.).

Class

QD3D12Window является зеркалом QOpenGLWindow, который в свою очередь основан на QOpenGLWidget/QGLWidget и методы initializeGL – resizeGL – paintGL, с GL переименованы на D3D, соответственно. Имеются две новых функции подклассов, которые могут быть реализованы: releaseD3D и afterPresent. Последняя вызывается каждый раз после выдачи Present call: большинство простых приложений будут ожидать GPU в этой функции. Первая же используется для того, чтобы приложение могло выжить при удалении устройства: когда графическое устройство становится недоступным, эта функция вызывается и выполняется при освобождении ресурсов во время инициализации/перерисовки/изменении размера. QD3D12Window будет затем запускать initializeD3D заново. В этом случае приложение может оставаться функциональным при обновлении драйвера или ожидании исполнения шейдеров.

Лучше, конечно, показать на примере. Взглянем на hellotriangle, который показывает, что если вы использовали раньше  QOpenGLWindow или QOpenGLWidget, то использование QD3D12Window не будет для Вас сюрпризом.

Widgets

Итак, теперь на нашем окне Мы не имеем ничего, кроме содержания отрисованного D3D12. Это отлично, но что там делают традиционные элементы управления? Этого можно добиться с QD3D12Window, сделав дочернее окно через QWidget::createWindowContainer(). Это связано с обычными ограничениями, о которых Вам в первую очередь следует прочитать в документации. Тем не менее это будет отлично работать для самых простых целей.

Shaders

Обработка кода шейдеров и их компиляция является другой интересной темой. С  OpenGL в Qt и Qt Quick делается ставка на runtime компиляцию из-за того, что это является единственным общедоступным решением не зависящим от производителей и особенностей платформ. С другими графическими API в будущем, ожидается, что Qt больше сфокусируется на автономной компиляции, и интеграции в систему сборки настолько, насколько это возможно. Помимо очевидных преимуществ в производительности это значительно улучшает рабочий процесс разработки: получение компилятором информации об ошибках во время сборки при запуске через Ctrl+B, в Qt Creator сможете легко почувствовать, как новый способ превосходит "старый" путь отладки во время работы приложения.

QtD3D12Window модуль поставляется с простым правилом qmake, которое позволяет вызывать fxc.exe во время сборки. Все примеры используют его для создания заголовочных файлов, где компилируется байт-код, представляющий собой массив символов. Взгляните на .pro файл одного из них и настройку shader.

Это не является совершенно новым Qt: комплект ANGLE в qtbase выполняет компиляцию шейдеров тем же способом. Однако,  то что скрыто не может быть использовано в коде на прикладном уровне D3D, как файл hlsl.prf здесь, то может быть скопировано в папку mkspecs/features в Qt SDK, что сделает его доступным для любого Qt приложения.

Graphics Debugging

QD3D12Window автоматически включает уровень отладки D3D12. Это является невероятно полезным с точки зрения множества обычных ошибок, совершаемых при старте работы с D3D12, особенно, когда получаете полезные отладочные сообщения. Однако, вы можете отключить их, когда встанет вопрос о тестировании производительности.

Другим полезным инструментов является graphics debugger включённый в Visual Studio. Одним из способов запустить Qt приложение является выполнение devenv /debugexe qtapplication.exe из командной строки разработчика и нажатие Alt+F5. (в качестве альтернативы, создание файлов проекта Visual Studio с qmake -tp vc может также хорошо работать). Он оказался весьма полезным во время разработки простых примеров – например, его возможность посмотреть графические ресурсы и также посмотреть, правильно ли сформированы уровни MIPMAP.

Примеры

Как упоминалось раннее, модуль поставляется с комплектом примеров, которые охватывают основы и могут быть полезны для начала разработки с D3D12. Смотрите readme файл для ознакомления.

Источник Qt Blog .

Comments

Only authorized users can post comments.
Please, Log in or Sign up
P
Feb. 18, 2019, 3:39 p.m.
Poyar

C++ - Test 001. The first program and data types

  • Result:73points,
  • Rating points1
НБ
Feb. 15, 2019, 1:03 p.m.
Николай Булахтин

C++ - Test 002. Constants

  • Result:25points,
  • Rating points-10
Last comments
V
Feb. 14, 2019, 6:41 p.m.
Vlad15007

Спасибо огромное! Заработало!
А
Feb. 12, 2019, 9:26 a.m.
Александр90

Сам разборался, спасибо.
А
Feb. 12, 2019, 8:19 a.m.
Александр90

День добрый! Можешь выложить форму mainwindow.ui от урока? Заранее спасибо
Feb. 11, 2019, 10:51 a.m.
Евгений Легоцкой

Нет, у меня проблема с жёстким диском случилась, занимался восстановлением ПК, ещё пару вечеров придётся этим заниматься, увы.
Now discuss on the forum
Feb. 17, 2019, 5:28 p.m.
Евгений Легоцкой

Добрый день. Очень извиняюсь за долгий ответ Первое, что нашёл, так это необходимость перерисовать чекбокс. void CheckBoxDelegate::paint(QPainter *painter, const QStyleOptionViewItem ...
Feb. 15, 2019, 3:36 p.m.
Евгений Легоцкой

Ну я тут нашёл одно решение, но сам его не проверял. Вам нужно помещать фамилии скорее всего в ячейки заголовка, и потом просто перерисовывать их QHeaderView * header = m_ui->tableWidget...
Feb. 15, 2019, 7:53 a.m.
Евгений Легоцкой

Добрый день! Не работал с remoteobjects, поэтому глянул документацию, чтобы рассмотреть, что это за зверь. После просмотра документации сложилось стойкой впечатление, что это вполне возм...
m
Feb. 14, 2019, 6:28 p.m.
mr_roman

Нашел решение на Java. Удалось интегрировать в проект сервиса на Qt, теперь из Qt запускаю Java-код акселерометра.
Join us in social networks

For registered users on the site there is a minimum amount of advertising