Класс QVulkanInstance
Класс QVulkanInstance представляет собой нативный экземпляр Vulkan, позволяющий выполнять рендеринг Vulkan на QSurface. Подробнее...
| Заголовок: | #include <QVulkanInstance> |
| qmake: | QT += gui |
| С момента: | Qt 5.10 |
Типы
| Перечисление | Flag { NoDebugOutputRedirect } |
| Флаги | Flags |
Открытые функции
| QVulkanInstance() | |
| ~QVulkanInstance() | |
| QVersionNumber | apiVersion() const |
| bool | create() |
| void | destroy() |
| QVulkanDeviceFunctions * | deviceFunctions(int device) |
| int | errorCode() const |
| QByteArrayList | extensions() const |
| QVulkanInstance::Flags | flags() const |
| QVulkanFunctions * | functions() const |
| PFN_vkVoidFunction | getInstanceProcAddr(const char *name) |
| bool | isValid() const |
| QByteArrayList | layers() const |
| void | presentQueued(QWindow *window) |
| void | resetDeviceFunctions(int device) |
| void | setApiVersion(const QVersionNumber &vulkanVersion) |
| void | setExtensions(const QByteArrayList &extensions) |
| void | setFlags(QVulkanInstance::Flags flags) |
| void | setLayers(const QByteArrayList &layers) |
| void | setVkInstance(int existingVkInstance) |
| QVulkanInfoVector<QVulkanExtension> | supportedExtensions() |
| QVulkanInfoVector<QVulkanLayer> | supportedLayers() |
| bool | supportsPresent(int physicalDevice, uint32_t queueFamilyIndex, QWindow *window) |
| int | vkInstance() const |
Статические открытые члены
| VkSurfaceKHR | surfaceForWindow(QWindow *window) |
Подробное описание
Класс QVulkanInstance представляет собой нативный экземпляр Vulkan, позволяющий выполнять рендеринг Vulkan на QSurface.
Vulkan — кроссплатформенный явный графический и вычислительный API. Этот класс предоставляет поддержку загрузки библиотеки Vulkan и создания instance кроссплатформенным способом. Для ознакомления с экземплярами Vulkan см. раздел 3.2 спецификации.
Примечание: Поддержка экземпляров Vulkan и окон с поверхностями, совместимыми с Vulkan, на конкретных платформах обеспечивается соответствующими плагинами платформы. Однако не все из них поддерживают Vulkan. При работе на таких платформах метод create() завершится неудачей и всегда вернёт false.
Примечание: Поддержка Vulkan может быть автоматически отключена для данного сборки Qt из-за отсутствия необходимых заголовков Vulkan во время компиляции. В этом случае, если вывод configure указывает, что поддержка Vulkan отключена, классы QVulkan* будут недоступны.
Примечание: Некоторые функции изменили свою сигнатуру между различными ревизиями заголовков Vulkan. При построении Qt, если в системе присутствуют заголовки только со старыми, конфликтующими сигнатурами, поддержка Vulkan будет отключена. Рекомендуется использовать заголовки Vulkan 1.0.39 или более поздних версий.
Инициализация
Аналогично QOpenGLContext, фактическое создание экземпляра Vulkan происходит только при вызове create(). Это позволяет использовать QVulkanInstance как обычную переменную-член, сохраняя контроль над временем выполнения инициализации.
Запрос поддерживаемых слоёв и расширений на уровне экземпляра возможен с помощью вызова supportedLayers() и supportedExtensions(). Это гарантирует загрузку библиотеки Vulkan и, следовательно, может быть вызвано безопасно до create() также.
Экземпляры хранят состояние Vulkan на уровне приложения, и создание VkInstance объекта инициализирует библиотеку Vulkan. На практике, обычно один экземпляр создаётся в самом начале функции main(). Объект остается активным до выхода из приложения.
Каждое окно QWindow на основе Vulkan должно быть связано с QVulkanInstance путём вызова QWindow::setVulkanInstance(). Таким образом, типичная схема приложения выглядит следующим образом:
int main(int argc, char **argv)
{
QGuiApplication app(argc, argv);
QVulkanInstance inst;
if (!inst.create())
return 1;
...
window->setVulkanInstance(&inst);
window->show();
return app.exec();
} Конфигурация
QVulkanInstance автоматически включает минимальный набор расширений, необходимых для нового экземпляра. На практике это означает семейство расширений VK_KHR_*_surface.
По умолчанию вывод отладки Vulkan, например, сообщения от слоёв проверки, выводятся в qDebug(). Это можно отключить, передав флаг NoDebugOutputRedirect в setFlags() перед вызовом create().
Для включения дополнительных слоёв и расширений, предоставьте список с помощью setLayers() и setExtensions() перед вызовом create(). Если данный слой или расширение не сообщается как доступное для экземпляра, запрос игнорируется. После успешного вызова create(), значения, возвращаемые функциями, такими как layers() и extensions(), отражают фактически включенные слои и расширения. При необходимости, например, для того, чтобы избежать запроса расширений, которые конфликтуют и, следовательно, приведут к неудаче создания экземпляра Vulkan, список фактически поддерживаемых слоёв и расширений можно проверить с помощью supportedLayers() и supportedExtensions() перед вызовом create().
Например, чтобы включить стандартные слои проверки, можно сделать следующее:
QVulkanInstance inst;
// Enable validation layer, if supported. Messages go to qDebug by default.
inst.setLayers(QByteArrayList() << "VK_LAYER_LUNARG_standard_validation");
bool ok = inst.create();
if (!ok)
... // Vulkan not available
if (!inst.layers().contains("VK_LAYER_LUNARG_standard_validation"))
... // validation layer not available Или, как альтернатива, чтобы принять решения до попытки создания экземпляра Vulkan:
QVulkanInstance inst;
if (inst.supportedLayers().contains("VK_LAYER_LUNARG_standard_validation"))
...
bool ok = inst.create();
... Использование существующего экземпляра
По умолчанию QVulkanInstance создаёт новый экземпляр Vulkan. При работе с внешними движками и рендерерами это может иногда нежелательно. Если уже есть доступный VkInstance дескриптор, вызовите setVkInstance() перед вызовом create(). Таким образом, не будут создаваться дополнительные экземпляры, и QVulkanInstance не будет владеть дескриптором.
Примечание: Компонент, создающий внешний экземпляр, должен убедиться, что на нём включены необходимые расширения. Это: VK_KHR_surface, WSI-специфическое VK_KHR_*_surface соответствующее данной платформе, и VK_EXT_debug_report в случае, если требуется перенаправление отладочного вывода QVulkanInstance.
Доступ к основным командам Vulkan
Для доступа к VkInstance обработке, которые QVulkanInstance оборачивает, вызовите vkInstance(). Для разрешения функций Vulkan, вызовите getInstanceProcAddr(). Для основных команд Vulkan ручное разрешение не требуется, так как они предоставляются через объекты QVulkanFunctions и QVulkanDeviceFunctions, доступные через functions() и deviceFunctions().
Примечание: QVulkanFunctions и QVulkanDeviceFunctions генерируются из XML-спецификаций API Vulkan при построении библиотек Qt. Поэтому для них нет документации. Они содержат функции Vulkan 1.0 с теми же сигнатурами, что и в документации API Vulkan.
Получение нативного Vulkan-поверхности для окна
Две распространённые операции, специфичные для системы окон, - это получение поверхности (рукоятки VkSurfaceKHR) для окна и проверка, поддерживает ли данный семейство очереди представление на данной поверхности. Чтобы избежать WSI-специфичных деталей в приложениях, они абстрагированы в QVulkanInstance и базовых слоях QPA.
Для создания Vulkan-поверхности для окна или получения существующей, вызовите surfaceForWindow(). Большинство платформ создадут поверхность только через VK_KHR_*_surface при первом вызове surfaceForWindow(), но могут быть платформо-специфические различия во внутреннем поведении. После создания последующие вызовы surfaceForWindow() просто возвращают ту же самую ручку. Это хорошо подходит для структуры типичных подклассов QWindow, поддерживающих Vulkan.
Чтобы проверить, может ли данное семейство очереди внутри физического устройства использоваться для представления на данной поверхности, вызовите supportsPresent(). Это обобщает как общие vkGetPhysicalDeviceSurfaceSupportKHR проверки, так и WSI-специфичные vkGetPhysicalDevice*PresentationSupportKHR.
Отладка
Помимо возвращения false из create() или 0 из surfaceForWindow(), критические ошибки также будут выводиться в отладочный вывод через qWarning(). Дополнительные логирования можно запросить, включив отладочный вывод для категории логирования qt.vulkan. Фактический код ошибки Vulkan при создании экземпляра можно получить, вызвав errorCode() после неудачного вызова create().
В некоторых особых случаях может потребоваться переопределить имя библиотеки Vulkan. Это можно сделать, установив переменную окружения QT_VULKAN_LIB.
Пример
Ниже приведён базовый план создания Vulkan-совместимого QWindow:
class VulkanWindow : public QWindow
{
public:
VulkanWindow() {
setSurfaceType(VulkanSurface);
}
void exposeEvent(QExposeEvent *) {
if (isExposed()) {
if (!m_initialized) {
m_initialized = true;
// initialize device, swapchain, etc.
QVulkanInstance *inst = vulkanInstance();
QVulkanFunctions *f = inst->functions();
uint32_t devCount = 0;
f->vkEnumeratePhysicalDevices(inst->vkInstance(), &devCount, nullptr);
...
// build the first frame
render();
}
}
}
bool event(QEvent *e) {
if (e->type == QEvent::UpdateRequest)
render();
return QWindow::event(e);
}
void render() {
...
requestUpdate(); // render continuously
}
private:
bool m_initialized = false;
};
int main(int argc, char **argv)
{
QGuiApplication app(argc, argv);
QVulkanInstance inst;
if (!inst.create()) {
qWarning("Vulkan not available");
return 1;
}
VulkanWindow window;
window.showMaximized();
return app.exec();
} Примечание: Помимо экспонирования, правильно работающая реализация окна также должна обрабатывать дополнительные события, такие как изменение размера и QPlatformSurfaceEvent, чтобы обеспечить правильное управление цепочкой обмена. Кроме того, на некоторых платформах может потребоваться освобождение ресурсов, когда они больше не отображаются.
Использование C++ привязок для Vulkan
Также возможно объединение Qt-включателей Vulkan с C++ обёрткой Vulkan, например Vulkan-Hpp. Предварительное условие здесь заключается в том, что C++ слой должен уметь принимать родные ручки (VkInstance, VkSurfaceKHR) в своих классах без получения владения (так как владение остаётся у QVulkanInstance и QWindow). Также следует учесть следующее:
- Некоторые обёртки требуют включения обработки исключений. Qt не использует исключения. Чтобы включить обработку исключений для приложения, добавьте
CONFIG += exceptionsв файл.pro. - Некоторые обёртки вызывают функции Vulkan напрямую, предполагая, что
vulkan.hпредоставляет прототипы и приложение подключается к библиотеке Vulkan, экспортирующей все необходимые символы. Qt может не подключаться напрямую к библиотеке Vulkan. Поэтому на некоторых платформах может потребоваться добавитьLIBS += -lvulkanили аналогичное в файл.proприложения. - Заголовки для классов QVulkan могут включать
vulkan.hс включённымVK_NO_PROTOTYPES. Это может вызвать проблемы в заголовках C++ обёрток, которые полагаются на прототипы. Поэтому в коде приложения может потребоваться включитьvulkan.hppили аналогичное перед любым из заголовков QVulkan.
См. также QVulkanFunctions и QSurface::SurfaceType.
Документация по типам членов
enum QVulkanInstance::Flagflags QVulkanInstance::Flags
Этот перечисление описывает флаги, которые могут быть переданы в setFlags(). Они управляют поведением create().
| Константа | Значение | Описание |
|---|---|---|
QVulkanInstance::NoDebugOutputRedirect |
0x01 |
Отключает перенаправление отладочного вывода Vulkan (VK_EXT_debug_report) в qDebug. |
Это перечисление было введено или изменено в Qt 5.10.
Тип Flags — это typedef для QFlags<Flag>. Он хранит логическое ИЛИ комбинацию значений Flag.
Документация по функциям-членам
QVulkanInstance::QVulkanInstance()
Создаёт новый экземпляр.
Примечание: Инициализация Vulkan не выполняется в конструкторе.
QVulkanInstance::~QVulkanInstance()
Деструктор.
Примечание: current() вернёт nullptr после уничтожения экземпляра.
QVersionNumber QVulkanInstance::apiVersion() const
Возвращает запрошенную версию API Vulkan, с которой приложение ожидает работать, или нулевую версию, если setApiVersion() не вызывалась до create().
См. также setApiVersion().
bool QVulkanInstance::create()
Инициализирует библиотеку Vulkan и создаёт новый или использует существующий экземпляр Vulkan.
Возвращает true при успехе, false при ошибке или если Vulkan не поддерживается.
При успехе указатель на этот QVulkanInstance можно получить через статическую функцию current().
Экземпляр Vulkan и библиотека доступны до тех пор, пока существует этот QVulkanInstance или пока не вызван destroy().
void QVulkanInstance::destroy()
Уничтожает базовый экземпляр платформы, тем самым уничтожая VkInstance (если он владел). Объект QVulkanInstance по-прежнему можно использовать, вызвав create() снова.
QVulkanDeviceFunctions *QVulkanInstance::deviceFunctions(int device)
Возвращает объект QVulkanDeviceFunctions, который предоставляет набор команд Vulkan уровня устройства и гарантированно работает на всех платформах.
Примечание: Функции Vulkan в возвращённом объекте должны вызываться только с device или дочерним объектом (VkQueue, VkCommandBuffer) device в качестве первого параметра. Это происходит потому, что эти функции разрешаются с помощью vkGetDeviceProcAddr, чтобы избежать потенциальной нагрузки от внутренней диспетчеризации.
Примечание: Возвращаемый объект принадлежит и управляется QVulkanInstance. Не уничтожайте и не изменяйте его.
Примечание: Объект кэшируется, поэтому повторный вызов этой функции с тем же device является быстрой операцией. Однако при уничтожении устройства приложение должно уведомить QVulkanInstance, вызвав resetDeviceFunctions().
См. также functions() и resetDeviceFunctions().
int QVulkanInstance::errorCode() const
Возвращает код ошибки Vulkan после неудачного вызова create(), VK_SUCCESS в противном случае.
Это значение обычно является возвращаемым значением из vkCreateInstance() (при создании нового экземпляра Vulkan вместо использования существующего), но также может быть VK_NOT_READY, если плагин платформы не поддерживает Vulkan.
QByteArrayList QVulkanInstance::extensions() const
Возвращает включённые расширения экземпляра, если create() был вызван и завершился успешно. В противном случае возвращает запрошенные расширения.
См. также setExtensions().
QVulkanInstance::Flags QVulkanInstance::flags() const
Возвращает запрошенные флаги.
См. также setFlags().
QVulkanFunctions *QVulkanInstance::functions() const
Возвращает соответствующий объект QVulkanFunctions, который экспонирует основной набор команд Vulkan, исключая функции уровня устройства, и гарантированно работает на всех платформах.
Примечание: Возвращаемый объект принадлежит и управляется QVulkanInstance. Не уничтожайте и не изменяйте его.
См. также deviceFunctions().
PFN_vkVoidFunction QVulkanInstance::getInstanceProcAddr(const char *name)
Разрешает функцию Vulkan с заданным именем name.
Для основных команд Vulkan предпочтительнее использовать функции-обертки, доступные через functions() и deviceFunctions().
bool QVulkanInstance::isValid() const
Возвращает true, если create() выполнилось успешно и экземпляр является валидным.
QByteArrayList QVulkanInstance::layers() const
Возвращает включённые слои экземпляра, если create() был вызван и выполнился успешно. В противном случае возвращает запрошенные слои.
См. также setLayers().
void QVulkanInstance::presentQueued(QWindow *window)
Эта функция должна вызываться рендером приложения после помещения операции представления для window в очередь.
Хотя на некоторых платформах она будет ничего не делать, на других она может выполнять синхронизацию, зависящую от системного окна. Например, в X11 она обновит _NET_WM_SYNC_REQUEST_COUNTER.
void QVulkanInstance::resetDeviceFunctions(int device)
Деактивирует и уничтожает объект QVulkanDeviceFunctions для данного device.
Эта функция должна вызываться, когда VkDevice, для которого был вызван deviceFunctions(), уничтожается, а приложение продолжает работу, возможно, создавая новый логический Vulkan-устройство в дальнейшем.
Нет необходимости вызывать её перед уничтожением QVulkanInstance, так как очистка выполняется автоматически.
См. также deviceFunctions().
void QVulkanInstance::setApiVersion(const QVersionNumber &vulkanVersion)
Устанавливает версию API Vulkan, с которой ожидается работа приложения.
По умолчанию vulkanVersion не задана, и проверка версии во время создания экземпляра Vulkan не выполняется.
Примечание: эту функцию можно вызывать только до create(), и она не имеет эффекта, если вызвана после.
См. также apiVersion().
void QVulkanInstance::setExtensions(const QByteArrayList &extensions)
Устанавливает список дополнительных расширений экземпляра extensions для включения. Безопасно указывать и неподдерживаемые расширения, так как они игнорируются при отсутствии поддержки во время выполнения. Расширения, связанные с поверхностью, необходимые Qt, всегда будут добавлены автоматически, нет необходимости включать их в этот список.
Примечание: эту функцию можно вызывать только до create(), и она не имеет эффекта, если вызвана после.
См. также extensions().
void QVulkanInstance::setFlags(QVulkanInstance::Flags flags)
Настраивает поведение create() на основе предоставленных flags.
Примечание: эту функцию можно вызывать только до create(), и она не имеет эффекта, если вызвана после.
См. также flags().
void QVulkanInstance::setLayers(const QByteArrayList &layers)
Указывает список слоёв экземпляра layers для включения. Безопасно указывать и неподдерживаемые слои, так как они игнорируются при отсутствии поддержки во время выполнения.
Примечание: эту функцию можно вызывать только до create(), и она не имеет эффекта, если вызвана после.
См. также layers().
void QVulkanInstance::setVkInstance(int existingVkInstance)
Заставляет QVulkanInstance принять существующий дескриптор VkInstance вместо создания нового.
Примечание: existingVkInstance должен иметь как минимум VK_KHR_surface и соответствующие расширения, специфичные для WSI, VK_KHR_*_surface включены. Для обеспечения корректного перенаправления отладочного вывода также необходимо VK_EXT_debug_report.
Примечание: эту функцию можно вызывать только до create(), и она не имеет эффекта, если вызвана после.
См. также vkInstance().
QVulkanInfoVector<QVulkanExtension> QVulkanInstance::supportedExtensions()
Возвращает список поддерживаемых расширений на уровне экземпляра.
Примечание: эту функцию можно вызывать до create().
QVulkanInfoVector<QVulkanLayer> QVulkanInstance::supportedLayers()
Возвращает список поддерживаемых слоёв на уровне экземпляра.
Примечание: эту функцию можно вызывать до create().
bool QVulkanInstance::supportsPresent(int physicalDevice, uint32_t queueFamilyIndex, QWindow *window)
Возвращает true, если семейство очередей с queueFamilyIndex в physicalDevice поддерживает представление для window.
Вызывайте эту функцию при проверке очередей данного Vulkan-устройства, чтобы определить, какая очередь может использоваться для выполнения представления.
VkSurfaceKHR QVulkanInstance::surfaceForWindow(QWindow *window)
Создаёт или извлекает уже существующий VkSurfaceKHR дескриптор для данного window.
Возвращает дескриптор Vulkan-поверхности или 0 при ошибке.
int QVulkanInstance::vkInstance() const
Возвращает дескриптор VkInstance, который оборачивает этот QVulkanInstance, или null если create() ещё не был успешно вызван и никакой существующий экземпляр не был предоставлен через setVkInstance().
См. также setVkInstance().
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/archives/qt-5.11/qvulkaninstance.html