Класс QVulkanInstance
Класс QVulkanInstance представляет собой родной экземпляр Vulkan, позволяющий выполнять рендеринг Vulkan на QSurface. Подробнее...
| Заголовок: | #include <QVulkanInstance> |
| CMake: | find_package(Qt6 COMPONENTS Gui REQUIRED) target_link_libraries(mytarget PRIVATE Qt6::Gui) |
| qmake: | QT += gui |
| С момента: | Qt 5.10 |
Публичные типы
| DebugFilter | |
| Перечисление | Флаг { NoDebugOutputRedirect } |
| Флаги | Флаги |
Публичные функции
| QVulkanInstance() | |
| ~QVulkanInstance() | |
| QVersionNumber | apiVersion() const |
| bool | create() |
| void | destroy() |
| QVulkanDeviceFunctions * | deviceFunctions(VkDevice device) |
| VkResult | errorCode() const |
| QByteArrayList | extensions() const |
| QVulkanInstance::Flags | flags() const |
| QVulkanFunctions * | functions() const |
| PFN_vkVoidFunction | getInstanceProcAddr(const char *name) |
| void | installDebugOutputFilter(QVulkanInstance::DebugFilter filter) |
| bool | isValid() const |
| QByteArrayList | layers() const |
| void | presentAboutToBeQueued(QWindow *window) |
| void | presentQueued(QWindow *window) |
| void | removeDebugOutputFilter(QVulkanInstance::DebugFilter filter) |
| void | resetDeviceFunctions(VkDevice device) |
| void | setApiVersion(const QVersionNumber &vulkanVersion) |
| void | setExtensions(const QByteArrayList &extensions) |
| void | setFlags(QVulkanInstance::Flags flags) |
| void | setLayers(const QByteArrayList &layers) |
| void | setVkInstance(VkInstance existingVkInstance) |
| QVersionNumber | supportedApiVersion() const |
| QVulkanInfoVector<QVulkanExtension> | supportedExtensions() const |
| QVulkanInfoVector<QVulkanLayer> | supportedLayers() const |
| bool | supportsPresent(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, QWindow *window) |
| VkInstance | vkInstance() const |
Статические публичные члены
| VkSurfaceKHR | surfaceForWindow(QWindow *window) |
Подробное описание
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(). Объект остается активным до завершения приложения.
Каждый основанный на Vulkan QWindow должен быть связан с 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.2 с теми же подписями, что описаны в документации 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 переменную среды.
Пример
Ниже представлен базовый алгоритм создания QWindow с поддержкой Vulkan:
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.
Документация по типам членов
QVulkanInstance::DebugFilter
Тип для функций обратного вызова отбора отладки.
См. также installDebugOutputFilter() и removeDebugOutputFilter().
[since 5.10] перечисление QVulkanInstance::Flagфлаги QVulkanInstance::Flags
Это перечисление описывает флаги, которые могут быть переданы в setFlags(). Они контролируют поведение create().
| Константа | Значение | Описание |
|---|---|---|
QVulkanInstance::NoDebugOutputRedirect |
0x01 |
Отключает перенаправление вывода отладки Vulkan (VK_EXT_debug_report) в qDebug. |
Это перечисление было добавлено или изменено в Qt 5.10.
Тип Flags — это псевдоним для QFlags<Flag>. Он хранит логическое ИЛИ комбинацию значений Flag.
Документация по функциям членов
QVulkanInstance::QVulkanInstance()
Создаёт новый экземпляр.
Примечание: Инициализация Vulkan не выполняется в конструкторе.
QVulkanInstance::~QVulkanInstance()
Деструктор.
Примечание: current() вернёт nullptr после уничтожения экземпляра.
QVersionNumber QVulkanInstance::apiVersion() const
Возвращает запрошенную версию Vulkan API, с которой приложение ожидает работать, или нулевую версию, если 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(VkDevice device)
Возвращает объект QVulkanDeviceFunctions, который предоставляет набор основных команд Vulkan на уровне устройства и гарантированно функционален на всех платформах.
Примечание: Функции Vulkan в возвращаемом объекте должны вызываться только с device или дочерним объектом (VkQueue, VkCommandBuffer) device в качестве первого параметра. Это связано с тем, что эти функции разрешаются через vkGetDeviceProcAddr, чтобы избежать потенциальной нагрузки внутренней диспетчеризации.
Примечание: Возвращаемый объект принадлежит и управляется QVulkanInstance. Не уничтожайте и не изменяйте его.
Примечание: Объект кэшируется, поэтому повторный вызов этой функции с тем же device — быстрая операция. Однако, когда устройство уничтожается, приложение должно уведомить QVulkanInstance путём вызова resetDeviceFunctions().
Функции из основного API Vulkan 1.0 всегда будут доступны. Когда дело доходит до более высоких версий Vulkan, таких как 1.1 и 1.2, объект QVulkanDeviceFunctions также попытается разрешить основные API функции для них, но если физическое устройство Vulkan во время выполнения не поддерживает их, вызов любой такой недоступной функции приведёт к неопределённому поведению. Для правильной поддержки версий Vulkan, превышающих 1.0, может потребоваться установить соответствующую версию API экземпляра, вызвав setApiVersion() перед create(). Кроме того, приложения должны проверять версию физического устройства apiVersion в VkPhysicalDeviceProperties.
См. также функции() и resetDeviceFunctions().
VkResult 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. Не уничтожайте и не изменяйте его.
Функции из основного API Vulkan 1.0 будут всегда доступны. Когда речь идёт о более высоких версиях Vulkan, таких как 1.1 и 1.2, объект QVulkanFunctions будет пытаться разрешить функции ядра API для них также, но если реализация Vulkan-инстанции во время выполнения не поддерживает их, вызов любой такой недоступной функции приведёт к неопределённому поведению. Кроме того, для правильной активации поддержки версий Vulkan выше 1.0, необходимо установить соответствующую версию API, вызвав setApiVersion() перед create(). Чтобы запросить версию Vulkan-реализации на уровне экземпляра, вызовите supportedApiVersion().
См. также deviceFunctions() и supportedApiVersion().
PFN_vkVoidFunction QVulkanInstance::getInstanceProcAddr(const char *name)
Разрешает функцию Vulkan с заданным именем name.
Для основных команд Vulkan предпочтительнее использовать обертки функций, извлекаемые из functions() и deviceFunctions().
void QVulkanInstance::installDebugOutputFilter(QVulkanInstance::DebugFilter filter)
Устанавливает функцию filter, которая вызывается для каждого сообщения отладки Vulkan. Если функция обратного вызова возвращает true, сообщение останавливается (отфильтровывается) и не будет отображаться в отладке.
Примечание: Фильтрация эффективна только при условии, что NoDebugOutputRedirect не установлен. Установка фильтров не влияет на другое.
Примечание: Эту функцию можно вызвать до create().
См. также removeDebugOutputFilter().
bool QVulkanInstance::isValid() const
Возвращает true, если create() был выполнен успешно и экземпляр действителен.
QByteArrayList QVulkanInstance::layers() const
Возвращает включенные слои экземпляра, если create() был вызван и выполнен успешно. В противном случае возвращает запрошенные слои.
См. также setLayers().
[since 5.15] void QVulkanInstance::presentAboutToBeQueued(QWindow *window)
Эта функция должна вызываться рендерером приложения перед постановкой операции представления в очередь для window.
Хотя на некоторых платформах эта функция будет ничем не заниматься, на некоторых она может выполнять синхронизацию, зависящую от системного окна. Например, в Wayland это добавит запрос wl_surface.frame, чтобы предотвратить блокировку драйвера для минимизированных окон.
Эта функция была добавлена в Qt 5.15.
void QVulkanInstance::presentQueued(QWindow *window)
Эта функция должна вызываться рендерером приложения после постановки операции представления в очередь для window.
Хотя на некоторых платформах эта функция будет ничем не заниматься, на некоторых она может выполнять синхронизацию, зависящую от системного окна. Например, в X11 это обновит _NET_WM_SYNC_REQUEST_COUNTER.
void QVulkanInstance::removeDebugOutputFilter(QVulkanInstance::DebugFilter filter)
Удаляет функцию filter, ранее установленную с помощью installDebugOutputFilter().
Примечание: Эту функцию можно вызвать до create().
См. также installDebugOutputFilter().
void QVulkanInstance::resetDeviceFunctions(VkDevice device)
Деактивирует и уничтожает объект QVulkanDeviceFunctions для данного устройства device.
Эта функция должна вызываться, когда VkDevice, для которого был вызван deviceFunctions(), уничтожается, в то время как приложение намерено продолжить работу, возможно, создавая новый логический Vulkan-устройство позже.
Нет необходимости вызывать это перед уничтожением QVulkanInstance, так как очистка выполняется автоматически.
См. также deviceFunctions().
void QVulkanInstance::setApiVersion(const QVersionNumber &vulkanVersion)
Указывает самую высокую версию API Vulkan, которую приложение предназначено использовать.
По умолчанию vulkanVersion равна 0, что соответствует Vulkan 1.0.
Примечание: Эту функцию можно вызывать только до create() и она не имеет эффекта, если вызвана после.
Примечание: Обратите внимание, что в Vulkan 1.1 поведение с точки зрения поля версии API Vulkan меняется. В Vulkan 1.0 указание неподдерживаемой vulkanVersion приводило к ошибке create() с VK_ERROR_INCOMPATIBLE_DRIVER, как предписывалось спецификацией. Начиная с Vulkan 1.1, спецификация запрещает это; драйвер должен принимать любую версию без отмены создания экземпляра.
Разработчикам приложений рекомендуется ознакомиться с apiVersion заметками в спецификации Vulkan.
См. также apiVersion() и supportedApiVersion().
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(VkInstance existingVkInstance)
Заставляет QVulkanInstance принять существующую рукоятку VkInstance вместо создания новой.
Примечание: existingVkInstance должен иметь как минимум VK_KHR_surface и соответствующие расширения, специфичные для WSI, VK_KHR_*_surface включены. Для обеспечения работоспособности перенаправления сообщений отладки также необходимо VK_EXT_debug_report.
Примечание: Эту функцию можно вызывать только до create() и она не имеет эффекта, если вызвана после.
См. также vkInstance().
QVersionNumber QVulkanInstance::supportedApiVersion() const
Возвращает версию функциональности экземпляра, поддерживаемую реализацией Vulkan.
На практике это либо значение, возвращаемое vkEnumerateInstanceVersion, если эта функция доступна (с Vulkan 1.1 и новее), либо 1.0.
Приложения, которые хотят разветвить использование функций и API Vulkan в зависимости от версии Vulkan, доступной во время выполнения, могут использовать эту функцию для определения версии, которую следует передать в setApiVersion() перед вызовом create().
Примечание: Эту функцию можно вызвать до create().
См. также setApiVersion().
QVulkanInfoVector<QVulkanExtension> QVulkanInstance::supportedExtensions() const
Возвращает список поддерживаемых расширений уровня экземпляра.
Примечание: Эту функцию можно вызвать до create().
QVulkanInfoVector<QVulkanLayer> QVulkanInstance::supportedLayers() const
Возвращает список поддерживаемых слоёв уровня экземпляра.
Примечание: Эту функцию можно вызвать до create().
bool QVulkanInstance::supportsPresent(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, QWindow *window)
Возвращает true, если семейство очередей с queueFamilyIndex внутри physicalDevice поддерживает представление для window.
Вызывайте эту функцию при исследовании очередей данного устройства Vulkan, чтобы определить, какая очередь может использоваться для выполнения презентации.
[static] VkSurfaceKHR QVulkanInstance::surfaceForWindow(QWindow *window)
Создаёт или возвращает уже существующую VkSurfaceKHR ручку для данного window.
Возвращает дескриптор поверхности Vulkan или 0 при ошибке.
VkInstance QVulkanInstance::vkInstance() const
Возвращает дескриптор VkInstance, который оборачивает этот QVulkanInstance, или nullptr если create() ещё не был успешно вызван и ни один существующий экземпляр не был предоставлен через setVkInstance().
См. также setVkInstance().
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-6.1/qvulkaninstance.html