mafulechkaOct. 2, 2019, 4:53 a.m.

Запуск Qt Quick на Vulkan, Metal и Direct3D

Content

Теперь, когда приближается первая бета-версия Qt 5.14, пришло время поговорить об одной из самых важных новых функций. Сложно охватить все детали, касающиеся улучшений графического стека и пути к Qt 6 в одной статье, поэтому в частях 1 и 2 будет описан фон и более подробно рассмотрено, что будет поставляться с версией 5.14. Позже, в другой серии статей, рассмотрим технические детали и будущие направления.

На странице новых функций 5.14 упоминается: добавлен первый предварительный просмотр независимого от графического API рендера сценографа в качестве дополнительной функции. Это позволяет запускать соответствующие приложения Qt Quick поверх Vulkan, Metal или Direct3D 11 вместо OpenGL .

Что это значит на практике?

Одна из главных целей в Qt 6 - отойти от прямого использования OpenGL в большинстве мест в Qt и, при наличии соответствующих абстракций, позволить работать с более широким разнообразием графики API, такой, как Vulkan, Metal и Direct3D. Естественно, OpenGL (и OpenGL ES) остается опцией. Основной мотивацией этого является не повышение производительности, а обеспечение Qt Everywhere и в будущем, даже на платформах и устройствах, где OpenGL либо недоступен, либо нежелателен. В то же время, возможность использовать современные низкоуровневые API-интерфейсы также может открыть возможности, когда речь идет об улучшении производительности (например, при более низком использовании ЦП (CPU) из-за меньших накладных расходов API) и новых способах работы в движках рендеринга за Qt Quick и другими модулями, как недавно анонсированный Qt Quick 3D.

Кроме того, возможность отображать пользовательские интерфейсы с помощью основной платформы наиболее поддерживаемого графического API является отличной новостью для приложений, которые выполняют собственный родной 2D или 3D графический рендеринг при использовании Qt для визуализации пользовательского интерфейса. В таком случае Qt часто находится не «за рулем», когда дело доходит до решения, какой графический API использовать. Например, если настольное приложение на macOS хочет использовать Metal для своего собственного 3D-контента, полагаясь на Qt Quick для рендеринга 2D элементов пользовательского интерфейса, тогда очень полезно, если Qt Quick также рендерит через Metal. Это будет звучать знакомо для тех, кто следил за развитием графики в Qt 5.x. Концептуально это ничем не отличается от того, когда поддержка работы в контекстах профилей ядра OpenGL была представлена в рендерере Qt Quick. Сам по себе Qt Quick в этом не нуждается, но для того, чтобы позволить интегрировать внешний код рендеринга, связанный с основными функциями профиля, Qt Quick должен быть осведомлен и способен с ним справиться. Так что в этом смысле история является естественным продолжением того, что имелось в Qt 5, и теперь расширяется, чтобы охватить графические API, отличные от OpenGL.

Все сказанное выше может вызвать два очевидных вопроса:

• Как это относится к Qt 5.x? Разве это не весь материал Qt 6?
• Почему бы просто не использовать <имя какого-либо решения для перевода графического API> ( ) и стандартизировать (<имя API>) ?

Так что там в Qt 5.14?

Развертывание полного пересмотра графических битов во всех (или, по крайней мере, в большинстве) мест в Qt, действительно, предназначено для Qt 6. Однако, остановка работы над 5.x и попытка изобрести, разработать и реорганизовывать все за один раз, надеясь, что все будет хорошо, не очень привлекательна на практике. Как говорили (и продолжают говорить) разработчики Qt, первая итерация любого API, вероятно, будет неоптимальной. Потому вместо этого разработчики Qt используют разработанный параллельный подход , сосредоточив внимание на одной определенной технологии пользовательского интерфейса в Qt - Qt Quick.

Ожидается, что Qt 5.14 будет поставляться с предварительным просмотром нового пути рендеринга Qt Quick. По умолчанию это неактивно и, поэтому для приложений нет видимых изменений, внутри они проходят тот же прямой путь кода на основе OpenGL, что и в более ранних версиях. Тем не менее, те, кто хочет опробовать новый подход, могут подписаться: либо установив переменную среды, либо запросив ее через C ++ API в main ().

Взглянув на снимок документации Qt 5.14, обнаружим следующее:

Не все приложения будут работать из коробки при работе с установленным QSG_RHI. Пользовательские реализации QQuickItem с узлами графа сцены, выполняющими прямые вызовы OpenGL или содержащими код шейдера GLSL в пользовательских материалах не будут работать при включении рендеринга на основе RHI. То же самое относится к элементам ShaderEffect с исходным кодом GLSL. Решения для создания нестандартных материалов и эффектов современным способом, в основном, уже есть, но они требуют соответствующей миграции приложений. Ранние пользователи могут экспериментировать с этим уже в 5.14 и 5.15, но широкое принятие и миграция, естественно, не ожидается до Qt 6.0. С другой стороны, многие существующие приложения QML, скорее всего будут работать, даже, если базовый движок рендеринга будет проходить через совершенно другой API, такие, как Vulkan или Metal.

Почему бы не перевод слоя XYZ?

Прежде всего, важно отметить, что возможность использования API и слоев трансляции шейдеров таких, как MoltenVK, MoltenGL, ANGLE, Zink и других, все еще существует даже, если они не всегда доступны из коробки. Например, MoltenVK позволяет также отображать пользовательские интерфейсы Qt Quick через Vulkan на macOS. Если приложение Qt Quick желает использовать только Vulkan и все еще хочет работать на macOS, MoltenVK - вариант (до тех пор, пока надлежащим образом сконфигурированная сборка Qt используется развернутой, MoltenVK доступен в системах пользователей и т. д.).

Сделать такой слой перевода обязательной зависимостью, а значит включить и развернуть его с помощью Qt уже совсем другая история.

Излишне говорить, что изменение Qt Everywhere на Qt Only, где внешние зависимости Allow (Qt Only Where External Dependencies Allow) не является идеальным.

Qt нацелен большее количество платформ и сред, чем обычно думают. Он может полагаться только на обязательные сторонние зависимости, которые компилируются и работают в «экзотических» средах, и их легко адаптировать в случае возникновения особых потребностей (например, INTEGRITY, QNX, специализированные встроенные среды Linux, системы с неработающими или находящимися в разработке графическими стеками, редкая необходимость адаптации к частным частям, или, иногда, необходимость взаимодействия, возможно, в зависимости от поставщика, нестандартным способом с различными графическими или композиционными API, которые вы считали давно мертвыми, и т. д. Все это требует гибкости и настраиваемости на каждом уровне стека рендеринга Qt).

Выполнять перевод между языками затенения (или промежуточными форматами) во время выполнения не совсем идеально. Ожидается, что шейдерный конвейер в Qt 6 будет больше фокусироваться на работе в автономном режиме или, самое позднее, во время сборки приложения. Когда слой перевода находится посередине, скрывая реальность (какой API, какой язык используется на самом деле), эти усилия быстро становятся бесполезными на практике, поскольку нет возможности подготовить или ввести шейдеры, или байт-код для реального базового API.

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

Случаи, когда движки рендеринга Qt дополняются пользовательским, собственным кодом рендеринга, как правило, работают лучше всего, когда обе стороны используют одни и те же API напрямую. Использование слоя перевода не всегда является блокирующим в этом отношении, если они позволяют получить доступ к базовым нативным объектам (представьте, например, как Direct3D - Qt Quick взаимодействие стало возможным благодаря расширениям EGL при работе с Qt 5 поверх ANGLE в Windows) и, когда это так, это может создать еще одну проблему, с которой придется столкнуться.

Есть лицензионные последствия и проблемы. Вспомните, что Apache 2.0 несовместим с GPLv2. Полагаться на коммерческие решения в любом случае не может быть и речи.

Исходя из опыта (некоторые с ANGLE и немного с MoltenVK), использование таких решений никогда не было таким уж простым, как хотелось бы изначально. В какой-то момент усилия, необходимые для поддержания всех опций в рабочем состоянии, могут стать слишком большими, тогда эти усилия лучше потратить на то, чтобы сделать все «правильно» напрямую с помощью нативного API. Внутренне зависимая от платформы природа некоторых из этих решений по переводу также не идеальна, если нужно использовать другую для каждой целевой платформы Qt, то ситуация быстро становится несостоятельной.

Таким образом, вместо того, чтобы полагаться на низкоуровневые API-трансляторы, Qt определяет свою собственную высокоуровневую абстракцию для 3D-графики (для внутреннего использования, на данный момент, не доступной для приложений). Затем, это поддерживается специфичными для API реализациями бэкенда, шаблоном, знакомым по многим компонентам в Qt. В некоторых случаях бэкенд является платформо-зависимым по своей природе (Metal, D3D), в то время, как в некоторых других один бэкэнд предназначен для одного API, но нескольких платформ (Vulkan, OpenGL). Это дополняется новым конвейером управления шейдерами, основанным на нескольких сторонних проектах, таких, как glslang и SPIRV-Cross. Более подробно обо всем этом будет рассказано в следующих статьях.

Это действительно работает?

Давайте рассмотрим пример, а именно хорошо известное демонстрационное приложение Qt5 Cinematic Experience от QUIt Coding. Мы используем слегка измененную версию, в которой обновляются несколько элементов ShaderEffect, чтобы они работали с обоими путями рендеринга сценографа Qt Quick.

При нормальном запуске приложения с установленным QSG_INFO=1 получаем:

Как показывают журналы, напечатанные в результатах отладки, это работает в OpenGL на рабочем столе Linux:

qt.scenegraph.general: threaded render loop
qt.scenegraph.general: Using sg animation driver
qt.scenegraph.general: Animation Driver: using vsync: 16.95 ms
qt.scenegraph.general: opengl texture atlas dimensions: 2048x1024
qt.scenegraph.general: GL_VENDOR: X.Org
qt.scenegraph.general: GL_RENDERER: AMD Radeon (TM) R9 M360 (VERDE, DRM 3.23.0, 4.15.0-62-generic, LLVM 8.0.1)
qt.scenegraph.general: GL_VERSION: 4.5 (Compatibility Profile) Mesa 19.2.0-devel (git-08f1cef 2019-07-25 bionic-oibaf-ppa)
qt.scenegraph.general: GL_EXTENSIONS: ...
qt.scenegraph.general: Max Texture Size: 16384
qt.scenegraph.general: Debug context: false

Как это изменится, если мы установим QSG_RHI=1?

qt.scenegraph.general: Using QRhi with backend OpenGL
  graphics API debug/validation layers: 0
  QRhi profiling and debug markers: 0
qt.scenegraph.general: threaded render loop
qt.scenegraph.general: Using sg animation driver
qt.scenegraph.general: Animation Driver: using vsync: 16.95 ms
qt.rhi.general: Created OpenGL context QSurfaceFormat(version 4.5, options QFlags<QSurfaceFormat::FormatOption>(DeprecatedFunctions), depthBufferSize 24, redBufferSize 8, greenBufferSize 8, blueBufferSize 8, alphaBufferSize 0, stencilBufferSize 8, samples -1, swapBehavior QSurfaceFormat::DoubleBuffer, swapInterval 1, colorSpace QSurfaceFormat::DefaultColorSpace, profile QSurfaceFormat::CompatibilityProfile)
qt.rhi.general: OpenGL VENDOR: X.Org RENDERER: AMD Radeon (TM) R9 M360 (VERDE, DRM 3.23.0, 4.15.0-62-generic, LLVM 8.0.1) VERSION: 4.5 (Compatibility Profile) Mesa 19.2.0-devel (git-08f1cef 2019-07-25 bionic-oibaf-ppa)
qt.scenegraph.general: MSAA sample count for the swapchain is 1. Alpha channel requested = no.
qt.scenegraph.general: rhi texture atlas dimensions: 2048x1024

Не сильно отличается, на первый взгляд. Все еще кажется, что это происходит через OpenGL. Тем не менее, внутренне нет прямого использования OpenGL и больше нет шейдерных источников GLSL в сцене Qt Quick. Вместо этого рендеринг проходит через QRhi, аппаратный интерфейс рендеринга Qt (частный API в модуле QtGui на данный момент).

Теперь давайте установим QSG_RHI_BACKEND=vulkan :

qt.scenegraph.general: Using QRhi with backend Vulkan
  graphics API debug/validation layers: 0
  QRhi profiling and debug markers: 0
qt.scenegraph.general: threaded render loop
qt.scenegraph.general: Using sg animation driver
qt.scenegraph.general: Animation Driver: using vsync: 16.95 ms
WARNING: radv is not a conformant vulkan implementation, testing use only.
qt.rhi.general: Physical device 0: 'AMD RADV CAPE VERDE (LLVM 8.0.1)' 19.1.99
qt.rhi.general:   using this physical device
qt.rhi.general: queue family 0: flags=0xf count=1
qt.rhi.general: queue family 1: flags=0xe count=2
qt.rhi.general: 55 device extensions available
qt.scenegraph.general: MSAA sample count for the swapchain is 1. Alpha channel requested = no.
qt.scenegraph.general: rhi texture atlas dimensions: 2048x1024
qt.rhi.general: Creating new swapchain of 3 buffers, size 1280x720, presentation mode 2

По всей видимости теперь рендеринг происходит через Vulkan. Тем не менее, даже самые экзотические функции Qt Quick, такие, как рендеринг текста в дистанционном поле, эффекты шейдеров и частицы, присутствуют, как и ожидалось.

Запуск приложения в RenderDoc и захват кадра дает следующее. Qt Quick действительно строит объекты состояния конвейера Vulkan и буферы команд, а код шейдера предоставляется в виде байт-кода SPIR-V.

Во второй части этой серии будет рассмотрено, что Qt 5.14 может предложить для macOS и Windows. После этого перейдем к рассмотрению того, как все это работает под капотом и каковы будут последствия для приложений, требующих нестандартных материалов и эффектов.

We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.
Support the author Donate

Comments

Only authorized users can post comments.
Please, Log in or Sign up
Donate

Did the EVILEG help you? Support the development of the site!

PayPalYandex.Money
How to become an author?

Contribute to the evolution of the EVILEG community.

Learn how to become a site author.

Learn it
Timeweb

Let me recommend you the excellent hosting on which EVILEG is located.

For many years, Timeweb has been proving his stability.

For projects on Django I recommend VDS hosting

View Hosting
SK

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

  • Result:80points,
  • Rating points4
SK

Qt - Test 001. Signals and slots

  • Result:78points,
  • Rating points2
S
  • Sergej
  • July 10, 2020, 3:15 p.m.

Qt - Test 001. Signals and slots

  • Result:68points,
  • Rating points-1
Last comments

Qt/C++ - Lesson 023. Moving QGraphicsItem on QGraphicsScene with mouse help

Пережиток plain C, ограничение видимости. По идее можно и .c, .cpp файлы подключать через директиву include. Для компилятора разницы особой нет, какое расширение будет.
R

Qt/C++ - Lesson 023. Moving QGraphicsItem on QGraphicsScene with mouse help

Подскажите, пожалуйста, почему функция рандома определена только в спп файле и объявлена при этом статической?
V

Django - Tutorial 027. Implementation Google reCAPTCHA

Спасибо. Только использую декоратор не в urls.py а перед views
R

Qt WinAPI - Lesson 001. How to collect all DLL, which used in Qt project?

Вы меня не совсем правильно поняли, но все равно спасибо, принял все к сведению. Все сделал как вы сказали, все отлично работает, еще раз огромнейшее спасибо) Разве что только что были опять про…

Qt WinAPI - Lesson 001. How to collect all DLL, which used in Qt project?

Стоило перед использованием что ли инструкцию прочитать https://www.cyberforum.ru/blogs/131347/blog2457.html "После сборки при запуске требовались dll," Ясное дело стоило задепло…
Now discuss on the forum
m

Qt IOs магнитное поле

Всем привет! Пытаюсь получить данные магнитного поля, используя класс QMagnetometer. Все получается, если задать параметр returnGeoValues false (как по-умолчанию). При этом выдаются ra…
DK

Drug Drop problems

благодорю!

Как в Qt в qmenu добавить scrollarea

Вот это наследованный класс меню. Но посути это обычное меню. #pragma once#include <QtWidgets>class TransMenu : public QMenu { Q_OBJECTpublic: TransMenu(QWidget* parent = …
o

Нужен человек кто хорошо понимает паттерны и их использование

Добрый день. Если вопрос про паттерны, то рисуй диаграмму классов.

Сборка Qt / C++ проекта под windows и linux

Отбой. Забыл в исходнике обернуть каждый #include макросом. #ifdef Q_OS_WIN32#include "win_controller.h"#else#include "linux_controller.h"#endif
About
Services
© EVILEG 2015-2020
Recommend hosting TIMEWEB