Vulkan use vulkan as the graphics backend windows linux android

Vulkan Skia has a Vulkan implementation of its GPU backend. The Vulkan backend can be built alongside the OpenGL backend. The client can select between

Содержание

  1. Vulkan
  2. Windows and Linux
  3. Android
  4. Using the Vulkan Backend
  5. Vulkan. Руководство разработчика. Настройка окружения
  6. 1. Вступление
  7. 2. Краткий обзор
  8. 3. Настройка окружения
  9. Windows
  10. Vulkan SDK
  11. Настройка Visual Studio
  12. Linux
  13. Vulkan Packages
  14. Компилятор шейдеров
  15. Настройка проекта для makefile
  16. MacOS
  17. Vulkan SDK
  18. Настройка Xcode

Vulkan

Skia has a Vulkan implementation of its GPU backend. The Vulkan backend can be built alongside the OpenGL backend. The client can select between the OpenGL and Vulkan implementation at runtime. The Vulkan backend has reached feature parity with the OpenGL backend. At this time we find that many Vulkan drivers have bugs that Skia triggers for which we have no workaround. We are reporting bugs to vendors as we find them.

Windows and Linux

To build the Vulkan backend, set skia_use_vulkan=true in args.gn .

Android

The Vulkan backend can run on any device with Vulkan drivers, including all Android N+ devices. To build the Vulkan backend, set ndk_api = 24 in args.gn to target Android N.

Using the Vulkan Backend

To create a GrContext that is backed by Vulkan the client creates a Vulkan device and queue, initializes a GrVkBackendContext to describe the context, and then calls GrContext::MakeVulkan:

When using the Vulkan backend, GrVkImageInfo is used to construct GrBackendTexture and GrBackendRenderTarget objects that in turn are used to create SkSurface and SkImage objects that refer to VkImages created by the Skia client.

The GrBackendObject returned by SkImage::getTextureHandle(), SkSurface::getTextureHandle(), and SkSurface::getRenderTargetHandle() should be interpreted as a GrVkImageInfo*. This allows a client to get the backing VkImage of a SkImage or SkSurface.

GrVkImageInfo specifies a VkImage and associated state (tiling, layout, format, etc). After getting a GrVkImageInfo* via getTextureHandle() or getRenderTargetHandle(), the client should check the fImageLayout field to know what layout Skia left the VkImage in before using the VkImage. If the client changes the layout of the VkImage, GrVkImageInfo::updateImageLayout(VkImageLayout layout) should be called before resuming Skia rendering.

The client is responsible for any synchronization or barriers needed before Skia performs I/O on a VkImage imported into Skia via GrVkImageInfo. Skia will assume it can start issuing commands referencing the VkImage without the need for additional synchronization.

Источник

Vulkan. Руководство разработчика. Настройка окружения

Я переводчик ижевской компании CG Tribe и здесь я буду публиковать перевод руководства к Vulkan API. Ссылка на источник — vulkan-tutorial.com. Это моя вторая публикация, которая посвящена переводу раздела Development Environment.

  1. Изображения
  2. Image view и image sampler
  3. Комбинированный image sampler

8. Буфер глубины

9. Загрузка моделей

10. Создание мип-карт

FAQ

Политика конфиденциальности

1. Вступление

2. Краткий обзор

3. Настройка окружения

  1. Vulkan SDK
  2. GLFW
  3. GLM
  4. Настройка Xcode

В этой главе мы настроим рабочую среду и установим несколько полезных библиотек. Инструменты, которые мы будем использовать, являются кроссплатформенными (разумеется, за исключением компилятора). Однако их установка в Windows, Linux и MacOS отличается, поэтому в руководстве каждая из этих ОС будет рассматриваться отдельно.

Windows

Если вы занимаетесь разработкой для Windows, то, скорее всего, вы используете Visual Studio. Для полной поддержки С++17 необходимо использовать Visual Studio 2017 или 2019. Шаги, описанные ниже, подходят для VS 2017.

Vulkan SDK

Самым важным компонентом для разработки программ с Vulkan является SDK. Он включает в себя заголовочные файлы, стандартные слои валидации, инструменты отладки и загрузчик функций Vulkan. Загрузчик ищет методы драйвера в рантайме (во время исполнения) так же, как это делает библиотека GLEW для OpenGL.

SDK можно загрузить с сайта LunarG. Для этого используйте кнопки внизу страницы. Вам необязательно создавать аккаунт, однако с ним у вас будет доступ к дополнительной документации.

Устанавливая SDK, запомните место установки.
Следующим шагом проверьте, поддерживает ли Vulkan ваша видеокарта и драйвер. Перейдите в папку с SDK, откройте папку Bin и запустите демо-проект vkcube.exe . Должно появиться следующее:

Если вы получили сообщение об ошибке, убедитесь, что ваша видеокарта поддерживает Vulkan, а драйвер обновлен до последней версии. См. главу Введение, в которой даны ссылки на драйверы крупных производителей.

В этой папке есть и другие программы, которые могут оказаться полезными для разработки. Программы glslangValidator.exe и glslc.exe используются для компиляции шейдеров из GLSL в байт-код. Подробно эта тема будет рассмотрена в главе Шейдерные модули. В папке Bin также находятся dll библиотеки загрузчика Vulkan и слоёв валидации, в папке Lib — статические библиотеки, а в папке Include – заголовочные файлы Vulkan. Вы можете изучить и другие файлы, но для руководства они нам не понадобятся.

Как уже было сказано, Vulkan – это API, независимый от платформы, в котором нет инструментов создания окна для отображения результатов рендеринга. Чтобы использовать преимущества кроссплатформенности Vulkan и избежать ужасов Win32, мы будем использовать библиотеку GLFW для создания окна. Есть и другие доступные библиотеки, например, SDL, но GLFW лучше тем, что она абстрагирует не только создание окна, но и некоторые другие платформенно-зависимые функции.

Последнюю версию библиотеки GLFW можно найти на официальном сайте. В руководстве мы будем использовать 64-битные сборки, но вы, разумеется, можете выбрать и 32-битные. В этом случае убедитесь, что вы ссылаетесь на файлы Vulkan SDK в папке Lib32 , а не в Lib . После скачивания распакуйте архив в удобное место. Мы создали новую папку Libraries в папке Visual Studio.

В отличие от DirectX 12, в Vulkan нет библиотеки для операций линейной алгебры, поэтому ее придется скачать отдельно. GLM – это удобная библиотека, разработанная для использования с графическими API, она часто используется с OpenGL.

Библиотека GLM – это header only библиотека. Скачайте последнюю версию и сохраните ее в удобном месте. У вас должна получиться подобная структура каталогов:

Настройка Visual Studio

После установки всех библиотек мы можем настроить проект Visual Studio для Vulkan и написать немного кода, чтобы убедиться, что все работает.

Откройте Visual Studio и создайте новый проект Windows Desktop Wizard . Введите имя проекта и нажмите OK .

В поле Application type выберите Console Application (.exe) , чтобы видеть сообщения отладки. Также выберите Empty Project , чтобы Visual Studio не добавила шаблонный код.

Нажмите OK , чтобы создать проект, и добавьте .cpp файл. Наверняка вы и так знаете, как это сделать, но мы не стали пропускать эти действия, чтобы инструкция получилась полной.

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

Откройте диалог с настройками проекта и убедитесь, что в меню выбрано All Configurations . Это нужно из-за того, что большинство настроек применяются как в режиме Debug , так и в Release .

Перейдите в C++ -> General -> Additional Include Directories и выберите в выпадающем списке.

Добавьте include директории для Vulkan, GLFW и GLM:

Перейдите в Linker → General → Additional Library Directories и добавьте расположения lib-файлов для Vulkan и GLFW:

Перейдите в Linker → Input и выберите Edit в выпадающем списке Additional Dependencies .

Введите имена lib-файлов Vulkan и GLFW:

И измените настройки стандарта на C++:

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

Не забудьте выбрать для компиляции 64-битный режим.

Нажмите F5 , чтобы скомпилировать и запустить проект. Вы увидите командную строку и окно, подобное этому:

Проверьте, чтобы число расширений не равнялось нулю («X extensions supported» в консоли).

Поздравляем, вы готовы к работе с Vulkan!

Linux

Инструкции ниже предназначены для пользователей Ubuntu, но вы можете следовать им, изменив команды apt на подходящие вам команды менеджера пакетов. Вам нужен компилятор с поддержкой С++17 (GCC 7+ или Clang 5+). Вам также понадобится утилита make.

Vulkan Packages

Самыми важными компонентами для разработки с использованием Vulkan под Linux являются загрузчик Vulkan, слои валидации и несколько утилит командной строки для проверки совместимости вашего компьютера с Vulkan:

  • sudo apt install vulkan-tools : утилиты командной строки, особенно можно выделить vulkaninfo и vkcube . Запустите их, чтобы проверить, поддерживает ли ваш ПК Vulkan.
  • sudo apt install libvulkan-dev : устанавливает загрузчик Vulkan. Загрузчик ищет методы драйвера в рантайме (во время исполнения) так же, как это делает библиотека GLEW для OpenGL.
  • sudo apt install vulkan-validationlayers-dev : устанавливает стандартные слои валидации, которые необходимы при отладке программ с Vulkan. О них мы поговорим в следующей главе.

Также не забудьте запустить vkcube , после чего на экране должно появиться следующее:

Если вы получили сообщение об ошибке, убедитесь, что ваша видеокарта поддерживает Vulkan, а драйвер обновлен до последней версии. См. главу Введение, в которой даны ссылки на драйверы крупных производителей.

Как уже было сказано, Vulkan – это API, независимый от платформы, в котором нет инструментов создания окна для отображения результатов рендеринга. Чтобы использовать преимущества кроссплатформенности Vulkan и избежать ужасов X11, мы будем использовать библиотеку GLFW для создания окна. Есть и другие доступные библиотеки, например, SDL, но GLFW лучше тем, что она абстрагирует не только создание окна, но и некоторые другие платформенно-зависимые функции.

Мы будем устанавливать GLFW с помощью следующей команды:

В отличие от DirectX 12, в Vulkan нет библиотеки для операций линейной алгебры, поэтому ее придется скачать отдельно. GLM – это удобная библиотека, разработанная для использования с графическими API, она часто используется с OpenGL.

Библиотека GLM – это header only библиотека. Ее можно установить из пакета libglm-dev :

Компилятор шейдеров

Теперь, когда настройка почти завершена, осталось установить программу для компиляции шейдеров из GLSL в байт-код.

Два наиболее известных компилятора шейдеров — это glslangValidator от Khronos Group и glslc от Google. По использованию glslc похож на GCC и Clang, поэтому мы остановим выбор на нем. Скачайте бинарники и скопируйте glslc в /usr/local/bin . Обратите внимание, что, в зависимости от ваших прав доступа, вам может понадобиться команда sudo . Для тестирования запустите glslc , после чего должно появиться предупреждение:

glslc: error: no input files

Мы подробно рассмотрим glslc в главе о шейдерных модулях.

Настройка проекта для makefile

После установки всех библиотек мы можем настроить проект makefile для Vulkan и написать немного кода, чтобы убедиться, что все работает.

Создайте новую папку в удобном месте и назовите ее VulkanTest . Создайте файл с именем main.cpp и вставьте в него код, приведенный ниже. Вам необязательно пытаться понять его сейчас, важно узнать, соберется ли и запустится ли программа. В следующей главе мы начнем описание с самых азов.

Следующим шагом будет написание makefile для компиляции и запуска. Создайте новый пустой файл с именем Makefile . Предполагается, что у вас уже есть начальный опыт работы с makefiles. Если нет, то это руководство поможет вам быстро войти в курс дела.

Сначала необходимо определить несколько переменных, чтобы упростить оставшуюся часть файла. Определите переменную CFLAGS , которая укажет базовые флаги компилятора:

Мы используем современный С++ ( -std=c++17 ). Также мы задаем уровень оптимизации О2. Можно удалить уровень -О2 для более быстрой компиляции программ, но для релизной сборки его все равно нужно будет вернуть.

Аналогично определите базовые флаги линкера в переменной LDFLAGS :

Флаг -lglfw подключает библиотеку GLFW, -lvulkan — загрузчик Vulkan, а остальные флаги — низкоуровневые библиотеки и зависимости самой GLFW.

Теперь вам будет несложно определить правило для компиляции VulkanTest . Не забудьте, что для отступов необходимо использовать табы вместо пробелов.

Проверьте, работает ли сборка. Сохраните makefile и запустите make из папки с main.cpp и Makefile . В результате должен получиться исполняемый файл VulkanTes t.

Теперь необходимо задать еще два правила — test и clean . Test запускает исполняемый файл, а clean удаляет его.

Запуск команды make test позволит убедиться, что программа работает успешно. При закрытии пустого окна программа должна завершиться успешным кодом возврата ( ). У вас должен получиться готовый makefile, похожий на приведенный ниже:

Вы можете использовать эту структуру каталогов в качестве шаблона для проектов Vulkan. Для этого скопируйте ее, переименуйте, например, в HelloTriangle и удалите весь код из main.cpp .
Итак, теперь вы готовы к настоящему приключению.

MacOS

Инструкции ниже предназначены для тех, кто использует Xcode и менеджер пакетов Homebrew. Имейте в виду, что версия MacOS не должна быть ниже 10.11, а ваше устройство должно поддерживать Metal API.

Vulkan SDK

Самым важным компонентом для разработки программ с Vulkan является SDK. Он включает в себя заголовочные файлы, стандартные слои валидации, инструменты отладки и загрузчик функций Vulkan. Загрузчик ищет методы драйвера в рантайме (во время исполнения) так же, как это делает библиотека GLEW для OpenGL.

SDK можно загрузить с сайта LunarG. Для этого используйте кнопки внизу страницы. Вам необязательно создавать аккаунт, однако с ним у вас будет доступ к дополнительной документации.

Версия SDK для MacOS использует библиотеку MoltenVK. MacOS не имеет прямой поддержки Vulkan, а MoltenVK используется как прослойка для передачи вызовов в Apple Metal. Благодаря этому вы можете воспользоваться преимуществами отладки и производительности Apple Metal.

После загрузки MoltenVK извлеките содержимое в любую папку (имейте в виду, что вам необходимо будет ссылаться на нее при создании проекта в Xcode). Внутри извлеченной папки, в папке Applications , должны находиться исполняемые файлы, которые позволят запустить несколько демо-проектов с использованием SDK. Запустите исполняемый файл vkcube , и вы увидите следующее:

Как уже было сказано, Vulkan – это API, независимый от платформы, в котором нет инструментов создания окна для отображения результатов рендеринга. Мы будем использовать библиотеку GLFW для создания окна. Есть и другие доступные библиотеки, например, SDL, но GLFW лучше тем, что она абстрагирует не только создание окна, но и некоторые другие платформенно-зависимые функции.

Для установки GLFW на MacOS мы будем использовать менеджер пакетов Homebrew:

В Vulkan нет библиотеки для операций линейной алгебры, поэтому ее придется скачать отдельно. GLM – это удобная библиотека, разработанная для использования с графическими API, она часто используется с OpenGL.

Библиотека GLM – это header only библиотека. Ее можно установить из пакета glm :

Настройка Xcode

После установки всех библиотек мы можем настроить проект Xcode для Vulkan. Всякий раз при упоминании папки vulkansdk , мы будем иметь в виду папку, в которую вы извлекли Vulkan SDK.

Запустите Xcode и создайте новый проект Xcode. В появившемся окне выберите Application > Command Line Tool.

Выберите Next , введите имя проекта и в пункте Language выберите C++ .

Нажмите Next , чтобы создать проект (в актуальном XCode12 вам потребуется ещё выбрать место для папки проекта — Прим. пер.). Когда проект будет создан, измените код в файле main.cpp на следующий:

Имейте в виду, вам необязательно пытаться понять весь код сейчас. Мы просто хотим использовать некоторые вызовы API, чтобы убедиться, что все работает правильно.

Xcode покажет некоторые ошибки, например, библиотеки, которые не были найдены. Необходимо настроить проект так, чтобы устранить эти ошибки. Выберите ваш проект в панели Project Navigator. Откройте вкладку Build Settings и выполните следующее:

  • Найдите поле Header Search Paths и добавьте ссылку на /usr/local/include (это место, куда Homebrew устанавливает заголовочные файлы, поэтому здесь должны быть файлы glm и glfw3) и ссылку на vulkansdk/macOS/include для заголовочных файлов Vulkan.
  • Найдите поле Library Search Paths и добавьте ссылку на /usr/local/lib (это еще одно место, куда Homebrew устанавливает библиотечные файлы, поэтому здесь должны быть файлы glm и glfw3) и ссылку на vulkansdk/macOS/lib .

В результате у вас должно получиться следующее (разумеется, пути будут отличаться в зависимости от расположения ваших файлов):

(На скриншоте на каждый параметр приходится по одному пути. Но, если следовать этому мануалу, вы получите по два пути на параметр. — Прим. пер.)

Теперь перейдем во вкладку Build PhasesLink Binary With Libraries и добавим фреймворки glfw3 и vulkan . Чтобы упростить задачу, мы будем добавлять в проект динамические библиотеки (если вы хотите использовать статические библиотеки, вы можете изучить документацию к ним).

  • Для glfw откройте папку /usr/local/lib (для этого вызовите Spotlight – Command+Space и введите в строку поиска /usr/local/lib – Прим. пер.), где вы найдете файл с именем, похожим на libglfw.3.x.dylib (“x” — это номер версии библиотеки; он зависит от даты загрузки пакета из Homebrew). Перетащите файл во вкладку Linked Frameworks and Libraries в Xcode.
  • Для vulkan перейдите в vulkansdk/macOS/lib . Сделайте то же самое с файлами libvulkan.1.dylib и libvulkan.1.x.xx.dylib (здесь “x” — это номер версии загруженного SDK).

После добавления библиотек в той же вкладке Copy Files измените Destination на “Frameworks”, очистите поле Subpath и уберите флажок напротив “Copy only when installing”. Нажмите на “+” и добавьте все три фреймворка. (Также уберите флажок напротив Code Sign On Copy, если он там есть. — Прим. пер.)

Конфигурация Xcode должна иметь следующий вид:

Осталось настроить несколько переменных среды. В панели инструментов Xcode перейдите в Product > Scheme > Edit Scheme. и во вкладке Arguments добавьте две переменные среды:

• VK_ICD_FILENAMES = vulkansdk/macOS/share/vulkan/icd.d/MoltenVK_icd.json
• VK_LAYER_PATH = vulkansdk/macOS/share/vulkan/explicit_layer.d

У вас должно получиться следующее:

Итак, настройка завершена! После запуска проекта (не забудьте установить конфигурацию сборки Debug или Release) вы увидите следующее:

Число расширений должно быть больше нуля («X extensions supported» в консоли). Остальные логи берутся из библиотек. Вы можете получать разные сообщения в зависимости от вашей конфигурации.

Поздравляем! Теперь вы готовы к реальной работе с Vulkan.

Источник

Я переводчик ижевской компании CG Tribe и здесь я буду публиковать перевод руководства к Vulkan API. Ссылка на источник — vulkan-tutorial.com. Это моя вторая публикация, которая посвящена переводу раздела Development Environment.

1. Вступление


См. статью автора kiwhy — habr.com/ru/post/462137

2. Краткий обзор


См. статью — habr.com/ru/post/524992

3. Настройка окружения


Windows

  1. Vulkan SDK
  2. GLFW
  3. GLM
  4. Настройка Visual Studio

Linux

  1. Vulkan Packages
  2. GLFW
  3. GLM
  4. Компилятор шейдеров
  5. Настройка проекта для makefile

MacOS

  1. Vulkan SDK
  2. GLFW
  3. GLM
  4. Настройка Xcode

В этой главе мы настроим рабочую среду и установим несколько полезных библиотек. Инструменты, которые мы будем использовать, являются кроссплатформенными (разумеется, за исключением компилятора). Однако их установка в Windows, Linux и MacOS отличается, поэтому в руководстве каждая из этих ОС будет рассматриваться отдельно.

Windows


Если вы занимаетесь разработкой для Windows, то, скорее всего, вы используете Visual Studio. Для полной поддержки С++17 необходимо использовать Visual Studio 2017 или 2019. Шаги, описанные ниже, подходят для VS 2017.

Vulkan SDK

Самым важным компонентом для разработки программ с Vulkan является SDK. Он включает в себя заголовочные файлы, стандартные слои валидации, инструменты отладки и загрузчик функций Vulkan. Загрузчик ищет методы драйвера в рантайме (во время исполнения) так же, как это делает библиотека GLEW для OpenGL.

SDK можно загрузить с сайта LunarG. Для этого используйте кнопки внизу страницы. Вам необязательно создавать аккаунт, однако с ним у вас будет доступ к дополнительной документации.

Устанавливая SDK, запомните место установки.
Следующим шагом проверьте, поддерживает ли Vulkan ваша видеокарта и драйвер. Перейдите в папку с SDK, откройте папку Bin и запустите демо-проект vkcube.exe. Должно появиться следующее:

Если вы получили сообщение об ошибке, убедитесь, что ваша видеокарта поддерживает Vulkan, а драйвер обновлен до последней версии. См. главу Введение, в которой даны ссылки на драйверы крупных производителей.

В этой папке есть и другие программы, которые могут оказаться полезными для разработки. Программы glslangValidator.exe и glslc.exe используются для компиляции шейдеров из GLSL в байт-код. Подробно эта тема будет рассмотрена в главе Шейдерные модули. В папке Bin также находятся dll библиотеки загрузчика Vulkan и слоёв валидации, в папке Lib — статические библиотеки, а в папке Include – заголовочные файлы Vulkan. Вы можете изучить и другие файлы, но для руководства они нам не понадобятся.

GLFW

Как уже было сказано, Vulkan – это API, независимый от платформы, в котором нет инструментов создания окна для отображения результатов рендеринга. Чтобы использовать преимущества кроссплатформенности Vulkan и избежать ужасов Win32, мы будем использовать библиотеку GLFW для создания окна. Есть и другие доступные библиотеки, например, SDL, но GLFW лучше тем, что она абстрагирует не только создание окна, но и некоторые другие платформенно-зависимые функции.

Последнюю версию библиотеки GLFW можно найти на официальном сайте. В руководстве мы будем использовать 64-битные сборки, но вы, разумеется, можете выбрать и 32-битные. В этом случае убедитесь, что вы ссылаетесь на файлы Vulkan SDK в папке Lib32, а не в Lib. После скачивания распакуйте архив в удобное место. Мы создали новую папку Libraries в папке Visual Studio.

GLM

В отличие от DirectX 12, в Vulkan нет библиотеки для операций линейной алгебры, поэтому ее придется скачать отдельно. GLM – это удобная библиотека, разработанная для использования с графическими API, она часто используется с OpenGL.

Библиотека GLM – это header only библиотека. Скачайте последнюю версию и сохраните ее в удобном месте. У вас должна получиться подобная структура каталогов:

Настройка Visual Studio

После установки всех библиотек мы можем настроить проект Visual Studio для Vulkan и написать немного кода, чтобы убедиться, что все работает.

Откройте Visual Studio и создайте новый проект Windows Desktop Wizard. Введите имя проекта и нажмите OK.

В поле Application type выберите Console Application (.exe), чтобы видеть сообщения отладки. Также выберите Empty Project, чтобы Visual Studio не добавила шаблонный код.

Нажмите OK, чтобы создать проект, и добавьте .cpp файл. Наверняка вы и так знаете, как это сделать, но мы не стали пропускать эти действия, чтобы инструкция получилась полной.

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

#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>

#define GLM_FORCE_RADIANS
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
#include <glm/vec4.hpp>
#include <glm/mat4x4.hpp>

#include <iostream>

int main() {
    glfwInit();

    glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
    GLFWwindow* window = glfwCreateWindow(800, 600, "Vulkan window", nullptr, nullptr);

    uint32_t extensionCount = 0;
    vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);

    std::cout << extensionCount << " extensions supportedn";

    glm::mat4 matrix;
    glm::vec4 vec;
    auto test = matrix * vec;

    while(!glfwWindowShouldClose(window)) {
        glfwPollEvents();
    }

    glfwDestroyWindow(window);

    glfwTerminate();

    return 0;
}

Откройте диалог с настройками проекта и убедитесь, что в меню выбрано All Configurations. Это нужно из-за того, что большинство настроек применяются как в режиме Debug, так и в Release.

Перейдите в C++ -> General -> Additional Include Directories и выберите <Edit...> в выпадающем списке.

Добавьте include директории для Vulkan, GLFW и GLM:

Перейдите в Linker → General → Additional Library Directories и добавьте расположения lib-файлов для Vulkan и GLFW:

Перейдите в Linker → Input и выберите Edit в выпадающем списке Additional Dependencies.

Введите имена lib-файлов Vulkan и GLFW:

И измените настройки стандарта на C++:

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

Не забудьте выбрать для компиляции 64-битный режим.

Нажмите F5, чтобы скомпилировать и запустить проект. Вы увидите командную строку и окно, подобное этому:

Проверьте, чтобы число расширений не равнялось нулю («X extensions supported» в консоли).

Поздравляем, вы готовы к работе с Vulkan!

Linux

Инструкции ниже предназначены для пользователей Ubuntu, но вы можете следовать им, изменив команды apt на подходящие вам команды менеджера пакетов. Вам нужен компилятор с поддержкой С++17 (GCC 7+ или Clang 5+). Вам также понадобится утилита make.

Vulkan Packages

Самыми важными компонентами для разработки с использованием Vulkan под Linux являются загрузчик Vulkan, слои валидации и несколько утилит командной строки для проверки совместимости вашего компьютера с Vulkan:

  • sudo apt install vulkan-tools: утилиты командной строки, особенно можно выделить vulkaninfo и vkcube. Запустите их, чтобы проверить, поддерживает ли ваш ПК Vulkan.
  • sudo apt install libvulkan-dev: устанавливает загрузчик Vulkan. Загрузчик ищет методы драйвера в рантайме (во время исполнения) так же, как это делает библиотека GLEW для OpenGL.
  • sudo apt install vulkan-validationlayers-dev: устанавливает стандартные слои валидации, которые необходимы при отладке программ с Vulkan. О них мы поговорим в следующей главе.

Также не забудьте запустить vkcube, после чего на экране должно появиться следующее:

Если вы получили сообщение об ошибке, убедитесь, что ваша видеокарта поддерживает Vulkan, а драйвер обновлен до последней версии. См. главу Введение, в которой даны ссылки на драйверы крупных производителей.

GLFW

Как уже было сказано, Vulkan – это API, независимый от платформы, в котором нет инструментов создания окна для отображения результатов рендеринга. Чтобы использовать преимущества кроссплатформенности Vulkan и избежать ужасов X11, мы будем использовать библиотеку GLFW для создания окна. Есть и другие доступные библиотеки, например, SDL, но GLFW лучше тем, что она абстрагирует не только создание окна, но и некоторые другие платформенно-зависимые функции.

Мы будем устанавливать GLFW с помощью следующей команды:

sudo apt install libglfw3-dev

GLM

В отличие от DirectX 12, в Vulkan нет библиотеки для операций линейной алгебры, поэтому ее придется скачать отдельно. GLM – это удобная библиотека, разработанная для использования с графическими API, она часто используется с OpenGL.

Библиотека GLM – это header only библиотека. Ее можно установить из пакета libglm-dev:

sudo apt install libglm-dev

Компилятор шейдеров

Теперь, когда настройка почти завершена, осталось установить программу для компиляции шейдеров из GLSL в байт-код.

Два наиболее известных компилятора шейдеров — это glslangValidator от Khronos Group и glslc от Google. По использованию glslc похож на GCC и Clang, поэтому мы остановим выбор на нем. Скачайте бинарники и скопируйте glslc в /usr/local/bin. Обратите внимание, что, в зависимости от ваших прав доступа, вам может понадобиться команда sudo. Для тестирования запустите glslc, после чего должно появиться предупреждение:

glslc: error: no input files

Мы подробно рассмотрим glslc в главе о шейдерных модулях.

Настройка проекта для makefile

После установки всех библиотек мы можем настроить проект makefile для Vulkan и написать немного кода, чтобы убедиться, что все работает.

Создайте новую папку в удобном месте и назовите ее VulkanTest. Создайте файл с именем main.cpp и вставьте в него код, приведенный ниже. Вам необязательно пытаться понять его сейчас, важно узнать, соберется ли и запустится ли программа. В следующей главе мы начнем описание с самых азов.

#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>

#define GLM_FORCE_RADIANS
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
#include <glm/vec4.hpp>
#include <glm/mat4x4.hpp>

#include <iostream>

int main() {
    glfwInit();

    glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
    GLFWwindow* window = glfwCreateWindow(800, 600, "Vulkan window", nullptr, nullptr);

    uint32_t extensionCount = 0;
    vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);

    std::cout << extensionCount << " extensions supportedn";

    glm::mat4 matrix;
    glm::vec4 vec;
    auto test = matrix * vec;

    while(!glfwWindowShouldClose(window)) {
        glfwPollEvents();
    }

    glfwDestroyWindow(window);

    glfwTerminate();

    return 0;
}

Следующим шагом будет написание makefile для компиляции и запуска. Создайте новый пустой файл с именем Makefile. Предполагается, что у вас уже есть начальный опыт работы с makefiles. Если нет, то это руководство поможет вам быстро войти в курс дела.

Сначала необходимо определить несколько переменных, чтобы упростить оставшуюся часть файла. Определите переменную CFLAGS, которая укажет базовые флаги компилятора:

CFLAGS = -std=c++17 -O2

Мы используем современный С++ (-std=c++17). Также мы задаем уровень оптимизации О2. Можно удалить уровень -О2 для более быстрой компиляции программ, но для релизной сборки его все равно нужно будет вернуть.

Аналогично определите базовые флаги линкера в переменной LDFLAGS:

LDFLAGS = -lglfw -lvulkan -ldl -lpthread -lX11 -lXxf86vm -lXrandr -lXi

Флаг -lglfw подключает библиотеку GLFW, -lvulkan — загрузчик Vulkan, а остальные флаги — низкоуровневые библиотеки и зависимости самой GLFW.

Теперь вам будет несложно определить правило для компиляции VulkanTest. Не забудьте, что для отступов необходимо использовать табы вместо пробелов.

VulkanTest: main.cpp
    g++ $(CFLAGS) -o VulkanTest main.cpp $(LDFLAGS)

Проверьте, работает ли сборка. Сохраните makefile и запустите make из папки с main.cpp и Makefile. В результате должен получиться исполняемый файл VulkanTest.

Теперь необходимо задать еще два правила — test и clean. Test запускает исполняемый файл, а clean удаляет его.

.PHONY: test clean

test: VulkanTest
    ./VulkanTest

clean:
    rm -f VulkanTest

Запуск команды make test позволит убедиться, что программа работает успешно. При закрытии пустого окна программа должна завершиться успешным кодом возврата (0). У вас должен получиться готовый makefile, похожий на приведенный ниже:

CFLAGS = -std=c++17 -O2
LDFLAGS = -lglfw -lvulkan -ldl -lpthread -lX11 -lXxf86vm -lXrandr -lXi

VulkanTest: main.cpp
    g++ $(CFLAGS) -o VulkanTest main.cpp $(LDFLAGS)

.PHONY: test clean

test: VulkanTest
	./VulkanTest

clean:
    rm -f VulkanTest

Вы можете использовать эту структуру каталогов в качестве шаблона для проектов Vulkan. Для этого скопируйте ее, переименуйте, например, в HelloTriangle и удалите весь код из main.cpp.
Итак, теперь вы готовы к настоящему приключению.

MacOS

Инструкции ниже предназначены для тех, кто использует Xcode и менеджер пакетов Homebrew. Имейте в виду, что версия MacOS не должна быть ниже 10.11, а ваше устройство должно поддерживать Metal API.

Vulkan SDK

Самым важным компонентом для разработки программ с Vulkan является SDK. Он включает в себя заголовочные файлы, стандартные слои валидации, инструменты отладки и загрузчик функций Vulkan. Загрузчик ищет методы драйвера в рантайме (во время исполнения) так же, как это делает библиотека GLEW для OpenGL.

SDK можно загрузить с сайта LunarG. Для этого используйте кнопки внизу страницы. Вам необязательно создавать аккаунт, однако с ним у вас будет доступ к дополнительной документации.

Версия SDK для MacOS использует библиотеку MoltenVK. MacOS не имеет прямой поддержки Vulkan, а MoltenVK используется как прослойка для передачи вызовов в Apple Metal. Благодаря этому вы можете воспользоваться преимуществами отладки и производительности Apple Metal.

После загрузки MoltenVK извлеките содержимое в любую папку (имейте в виду, что вам необходимо будет ссылаться на нее при создании проекта в Xcode). Внутри извлеченной папки, в папке Applications, должны находиться исполняемые файлы, которые позволят запустить несколько демо-проектов с использованием SDK. Запустите исполняемый файл vkcube, и вы увидите следующее:

GLFW

Как уже было сказано, Vulkan – это API, независимый от платформы, в котором нет инструментов создания окна для отображения результатов рендеринга. Мы будем использовать библиотеку GLFW для создания окна. Есть и другие доступные библиотеки, например, SDL, но GLFW лучше тем, что она абстрагирует не только создание окна, но и некоторые другие платформенно-зависимые функции.

Для установки GLFW на MacOS мы будем использовать менеджер пакетов Homebrew:

brew install glfw

GLM

В Vulkan нет библиотеки для операций линейной алгебры, поэтому ее придется скачать отдельно. GLM – это удобная библиотека, разработанная для использования с графическими API, она часто используется с OpenGL.

Библиотека GLM – это header only библиотека. Ее можно установить из пакета glm:

brew install glm

Настройка Xcode

После установки всех библиотек мы можем настроить проект Xcode для Vulkan. Всякий раз при упоминании папки vulkansdk, мы будем иметь в виду папку, в которую вы извлекли Vulkan SDK.

Запустите Xcode и создайте новый проект Xcode. В появившемся окне выберите Application > Command Line Tool.

Выберите Next, введите имя проекта и в пункте Language выберите C++.

Нажмите Next, чтобы создать проект (в актуальном XCode12 вам потребуется ещё выбрать место для папки проекта — Прим. пер.). Когда проект будет создан, измените код в файле main.cpp на следующий:

#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>

#define GLM_FORCE_RADIANS
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
#include <glm/vec4.hpp>
#include <glm/mat4x4.hpp>

#include <iostream>

int main() {
    glfwInit();

    glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
    GLFWwindow* window = glfwCreateWindow(800, 600, "Vulkan window", nullptr, nullptr);

    uint32_t extensionCount = 0;
    vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);

    std::cout << extensionCount << " extensions supportedn";

    glm::mat4 matrix;
    glm::vec4 vec;
    auto test = matrix * vec;

    while(!glfwWindowShouldClose(window)) {
        glfwPollEvents();
    }

    glfwDestroyWindow(window);

    glfwTerminate();

    return 0;
}

Имейте в виду, вам необязательно пытаться понять весь код сейчас. Мы просто хотим использовать некоторые вызовы API, чтобы убедиться, что все работает правильно.

Xcode покажет некоторые ошибки, например, библиотеки, которые не были найдены. Необходимо настроить проект так, чтобы устранить эти ошибки. Выберите ваш проект в панели Project Navigator. Откройте вкладку Build Settings и выполните следующее:

  • Найдите поле Header Search Paths и добавьте ссылку на /usr/local/include (это место, куда Homebrew устанавливает заголовочные файлы, поэтому здесь должны быть файлы glm и glfw3) и ссылку на vulkansdk/macOS/include для заголовочных файлов Vulkan.
  • Найдите поле Library Search Paths и добавьте ссылку на /usr/local/lib (это еще одно место, куда Homebrew устанавливает библиотечные файлы, поэтому здесь должны быть файлы glm и glfw3) и ссылку на vulkansdk/macOS/lib.

В результате у вас должно получиться следующее (разумеется, пути будут отличаться в зависимости от расположения ваших файлов):

(На скриншоте на каждый параметр приходится по одному пути. Но, если следовать этому мануалу, вы получите по два пути на параметр. — Прим. пер.)

Теперь перейдем во вкладку Build PhasesLink Binary With Libraries и добавим фреймворки glfw3 и vulkan. Чтобы упростить задачу, мы будем добавлять в проект динамические библиотеки (если вы хотите использовать статические библиотеки, вы можете изучить документацию к ним).

  • Для glfw откройте папку /usr/local/lib (для этого вызовите Spotlight – Command+Space и введите в строку поиска /usr/local/lib – Прим. пер.), где вы найдете файл с именем, похожим на libglfw.3.x.dylib (“x” — это номер версии библиотеки; он зависит от даты загрузки пакета из Homebrew). Перетащите файл во вкладку Linked Frameworks and Libraries в Xcode.
  • Для vulkan перейдите в vulkansdk/macOS/lib. Сделайте то же самое с файлами libvulkan.1.dylib и libvulkan.1.x.xx.dylib (здесь “x” — это номер версии загруженного SDK).

После добавления библиотек в той же вкладке Copy Files измените Destination на “Frameworks”, очистите поле Subpath и уберите флажок напротив “Copy only when installing”. Нажмите на “+” и добавьте все три фреймворка. (Также уберите флажок напротив Code Sign On Copy, если он там есть. — Прим. пер.)

Конфигурация Xcode должна иметь следующий вид:

Осталось настроить несколько переменных среды. В панели инструментов Xcode перейдите в Product > Scheme > Edit Scheme... и во вкладке Arguments добавьте две переменные среды:

• VK_ICD_FILENAMES = vulkansdk/macOS/share/vulkan/icd.d/MoltenVK_icd.json
• VK_LAYER_PATH = vulkansdk/macOS/share/vulkan/explicit_layer.d

У вас должно получиться следующее:

Итак, настройка завершена! После запуска проекта (не забудьте установить конфигурацию сборки Debug или Release) вы увидите следующее:

Число расширений должно быть больше нуля («X extensions supported» в консоли). Остальные логи берутся из библиотек. Вы можете получать разные сообщения в зависимости от вашей конфигурации.

Поздравляем! Теперь вы готовы к реальной работе с Vulkan.

Vulkan SDK for Android

Vulkan SDK banner


This project is not supported. For the latest tutorials and samples please go to:

  • Vulkan-Samples

Introduction

The Vulkan Software Development Kit is a collection of resources to help you build Vulkan applications
for a platform with a Mali GPU and an ARM processor.
You can use it for creating new applications, training, and exploration of implementation possibilities.

Setting up development environment

Minimum NDK requirements

Minimum android-ndk-r12 is required. The NDK can be downloaded from Android Studio 2.2 or later.
It is recommended to use the NDK provided in Android Studio.

OS requirements

The Vulkan SDK has been tested to build on Linux (Android Studio) and Windows (Android Studio).
Partial support for running on Linux desktop is also included.

Android requirements

Not all Android devices support Vulkan. To make sure your Android device has the Vulkan API supported download the Hardware CapsViewer for Vulkan app to verify your device’s status.

License

The software is provided under an MIT license. Contributions to this project are accepted under the same license.

Trademarks

Vulkan is a registered trademark of the Khronos Group Inc.

Building

Check out submodules

This repo uses GLM and STB as submodules, before building, make sure you pull those in.

git submodule init
git submodule update

Build and run samples from Android Studio

  • Open Android Studio 3.4 or newer
  • Open an existing Android Studio project
  • Import a sample project
  • You might be prompted to update or install the Gradle wrapper. Do so if asked.
  • You might be prompted to download and/or update Android SDK tools if Android Studio has not downloaded these before.
  • Under Tools -> Android -> SDK manager, install cmake, lldb and NDK components if these are not installed already.
  • In the top menu, run Build -> Make Project.
  • In the bottom of the screen, the Messages tab should display a build log which shows that libnative.so has been built and that build was successful.
  • Run the app on the device by pressing the Play button on the top toolbar.
  • To debug the code, Run -> Debug app. In the project view, you will find app/cpp/native/hellotriangle.cpp or similar. You can set breakpoints and step through the code.

Build samples for desktop Linux

mkdir build
cd build
cmake ..
make -j8

will build samples with a PNG backend. Running the binary on desktop should dump out PNG images.
This is useful when developing samples and for creating screenshots.

X11 or Wayland backends can be used instead on Linux by passing in extra parameters to cmake:

cmake .. -DPLATFORM=wayland   # or xcb for X11

Documentation

For online tutorials, documentation and explanation of the samples,
see Vulkan SDK documentation.

To build the same documentation for yourself for offline use, build Doxygen documentation with ./build_documentation.sh.
This requires Doxygen to be installed on your machine.

Adding new samples

The build system for samples is designed to be as general as possible. To create a new sample based on hellotriangle:

cd samples
$EDITOR CMakeLists.txt             # add_subdirectory(newsample)
mkdir newsample
cp -r hellotriangle/{CMakeLists.txt,app,build.gradle,settings.gradle} newsample/
$EDITOR CMakeLists.txt             # Edit add_sample
$EDITOR app/AndroidManifest.xml    # Edit manifest:package
$EDITOR app/res/values/strings.xml # Edit resources:string

Source files go in newsample/,
GLSL source files go in newsample/shaders and general assets (if needed) go in
newsample/assets.

Samples must implement the VulkanApplication interface as well as implementing MaliSDK::create_application().

#include "framework/application.hpp"
#include "framework/context.hpp"
#include "framework/common.hpp"
#include "framework/assets.hpp"
#include "platform/platform.hpp"

class MyVulkanApplication : public VulkanApplication
{
    // ...
};

VulkanApplication* MaliSDK::create_application()
{
    return new MyVulkanApplication();
}

Содержание

  1. Vulkan Backend
  2. API Concept Map
  3. Notes
  4. Memory Management
  5. Staging Textures
  6. Vulkan
  7. Windows and Linux
  8. Android
  9. Using the Vulkan Backend
  10. PyTorch Vulkan Backend User Workflow¶
  11. Introduction¶
  12. Building PyTorch with Vulkan backend¶
  13. Optional usage of vulkan wrapper¶
  14. Desktop build¶
  15. Vulkan SDK¶
  16. Android build¶
  17. Model preparation¶
  18. Using Vulkan backend in code¶
  19. C++ API¶
  20. Python API¶
  21. Android Java API¶
  22. Building android test app with Vulkan¶
  23. Что такое Vulkan и DirectX и как они влияют на видеоигры
  24. Предварительная информация о API
  25. Microsoft DirectX
  26. Вулкан AMD
  27. Как они влияют на игры
  28. Поддержка нескольких графических карт
  29. Шейдеры
  30. Совместимость с несколькими платформами
  31. Виртуальная реальность
  32. Развитие и будущее
  33. Как вы относитесь к двум API?
  34. Vulkan GPU backend #252
  35. Comments
  36. jcoder58 commented Feb 17, 2017 •
  37. mattleibow commented Feb 18, 2017
  38. jcoder58 commented Feb 18, 2017
  39. mattleibow commented Feb 18, 2017 •
  40. jcoder58 commented Feb 18, 2017 •
  41. mattleibow commented Feb 18, 2017 •
  42. mattleibow commented Feb 18, 2017
  43. jcoder58 commented Feb 19, 2017
  44. mattleibow commented Feb 19, 2017
  45. Kavignon commented Dec 12, 2017
  46. mattleibow commented Dec 4, 2018
  47. MarchingCube commented Nov 16, 2019
  48. BradChase2011 commented Nov 16, 2019 •
  49. mattleibow commented Nov 16, 2019
  50. mattleibow commented May 2, 2020
  51. mattleibow commented May 12, 2020
  52. BradChase2011 commented May 13, 2020
  53. mattleibow commented May 14, 2020
  54. mattleibow commented May 14, 2020
  55. mattleibow commented May 14, 2020
  56. mattleibow commented May 15, 2020
  57. mattleibow commented May 16, 2020
  58. mattleibow commented May 16, 2020
  59. BradChase2011 commented May 18, 2020
  60. garrynewman commented Jun 3, 2020
  61. emmauss commented Sep 19, 2020
  62. garrynewman commented Sep 19, 2020
  63. mattleibow commented Sep 21, 2020
  64. MarchingCube commented Oct 19, 2020
  65. BradChase2011 commented Oct 31, 2020 •

Vulkan Backend

The Vulkan backend is a multi-platform backend implemented using the Vulkan API. Vulkan is supported on Windows, Linux, and Android. Vulkan’s API is very close to Veldrid’s and as such this is a fairly simple, straightforward backend.

Vulkan GraphicsDevices are created from a VkSurfaceSource, which is a platform-specific object used to create a Vulkan surface (VkSurfaceKHR). The following helper functions are available:

API Concept Map

Veldrid Concept Vulkan Concept Notes
GraphicsDevice VkDevice, VkPhysicalDevice, VkCommandPool, VkDescriptorPool, VkQueue
CommandList VkCommandBuffer
DeviceBuffer VkBuffer
BufferUsage VkBufferUsageFlagBits
Texture VkImage
TextureUsage VkImageUsageFlagBits
TextureView VkImageView
Sampler VkSampler
Pipeline VkPipeline
Blend State VkPipelineColorBlendStateCreateInfo
Depth Stencil State VkPipelineDepthStencilStateCreateInfo
Rasterizer State VkPipelineRasterizationStateCreateInfo
PrimitiveTopology VkPrimitiveTopology, VkPipelineInputAssemblyStateCreateInfo
Vertex Layouts VkPipelineVertexInputStateCreateInfo
Shader VkShaderModule
ShaderSetDescription None
Framebuffer VkFramebuffer
ResourceLayout VkDescriptorSetLayout
ResourceSet VkDescriptorSet
Swapchain VkSwapchainKHR

Notes

Veldrid’s API is modeled after modern graphics API’s like Vulkan. As a result, this backend is simple, straightforward, and has very good performance. Driver support for Vulkan remains somewhat less common than other graphics API’s, but new GPUs from all major vendors support Vulkan. In time, Vulkan will likely be supported by all major systems.

Memory Management

Memory management must be custom-handled in Vulkan. The VkDeviceMemoryManager class allocates and reclaims all memory needed in the Vulkan backend. In general, the allocation handling is as follows:

Staging Textures

Staging Textures are actually implemented using VkBuffers, rather than VkImages. This has no observable effect on the implementation, and is actually the recommended approach.

Linear VkImages would be another option, but they are extremely limited in most Vulkan implementations, and cannot support all of the possible permutations of a staging Texture (dimensions, mips, array layers, etc.). For example, almost all Vulkan implementations require that Linear images be 2D (not even 1D), have one mip level, have one array layer, and are a small subset of pixel formats. Since staging Textures are conceptually just a contiguous, tightly-packed block of memory, a VkBuffer works perfectly and has none of the above limitations. Simple arithmetic can convert between the buffer’ linear address space into a Texture’s 1D, 2D, or 3D address space. Vulkan has a variety of commands that perform copies between VkBuffers and VkImages.

Источник

Vulkan

Skia has a Vulkan implementation of its GPU backend. The Vulkan backend can be built alongside the OpenGL backend. The client can select between the OpenGL and Vulkan implementation at runtime. The Vulkan backend has reached feature parity with the OpenGL backend. At this time we find that many Vulkan drivers have bugs that Skia triggers for which we have no workaround. We are reporting bugs to vendors as we find them.

Windows and Linux

Android

The Vulkan backend can run on any device with Vulkan drivers, including all Android N+ devices. To build the Vulkan backend, set ndk_api = 24 in args.gn to target Android N.

Using the Vulkan Backend

To create a GrContext that is backed by Vulkan the client creates a Vulkan device and queue, initializes a GrVkBackendContext to describe the context, and then calls GrContext::MakeVulkan:

When using the Vulkan backend, GrVkImageInfo is used to construct GrBackendTexture and GrBackendRenderTarget objects that in turn are used to create SkSurface and SkImage objects that refer to VkImages created by the Skia client.

The GrBackendObject returned by SkImage::getTextureHandle(), SkSurface::getTextureHandle(), and SkSurface::getRenderTargetHandle() should be interpreted as a GrVkImageInfo*. This allows a client to get the backing VkImage of a SkImage or SkSurface.

GrVkImageInfo specifies a VkImage and associated state (tiling, layout, format, etc). After getting a GrVkImageInfo* via getTextureHandle() or getRenderTargetHandle(), the client should check the fImageLayout field to know what layout Skia left the VkImage in before using the VkImage. If the client changes the layout of the VkImage, GrVkImageInfo::updateImageLayout(VkImageLayout layout) should be called before resuming Skia rendering.

The client is responsible for any synchronization or barriers needed before Skia performs I/O on a VkImage imported into Skia via GrVkImageInfo. Skia will assume it can start issuing commands referencing the VkImage without the need for additional synchronization.

Источник

PyTorch Vulkan Backend User Workflow¶

Introduction¶

PyTorch 1.7 supports the ability to run model inference on GPUs that support the Vulkan graphics and compute API. The primary target devices are mobile GPUs on Android devices. The Vulkan backend can also be used on Linux, Mac, and Windows desktop builds to use Vulkan devices like Intel integrated GPUs. This feature is in the prototype stage and is subject to change.

Building PyTorch with Vulkan backend¶

To use PyTorch with Vulkan backend, we need to build it from source with additional settings. Checkout the PyTorch source code from GitHub master branch.

Optional usage of vulkan wrapper¶

By default, Vulkan library will be loaded at runtime using the vulkan_wrapper library. If you specify the environment variable USE_VULKAN_WRAPPER=0 libvulkan will be linked directly.

Desktop build¶

Vulkan SDK¶

Download VulkanSDK from https://vulkan.lunarg.com/sdk/home and set environment variable VULKAN_SDK

Unpack VulkanSDK to VULKAN_SDK_ROOT folder, install VulkanSDK following VulkanSDK instructions for your system.

After successful build, open another terminal and verify the version of installed PyTorch.

At the time of writing of this recipe, the version is 1.8.0a0+41237a4. You might be seeing different numbers depending on when you check out the code from master, but it should be greater than 1.7.0.

Android build¶

To prepare pytorch_android aars that you can use directly in your app:

Model preparation¶

Install torchvision, get the default pretrained float model.

Python script to save pretrained mobilenet_v2 to a file:

PyTorch 1.7 Vulkan backend supports only float 32bit operators. The default model needs additional step that will optimize operators fusing

The result model can be used only on Vulkan backend as it contains specific to the Vulkan backend operators.

Using Vulkan backend in code¶

C++ API¶

.cpu() function called on Vulkan tensor will copy its data to CPU tensor (default)

Operators called with a tensor on a Vulkan device as an input will be executed on a Vulkan device. If an operator is not supported for the Vulkan backend the exception will be thrown.

List of supported operators:

Those operators allow to use torchvision models for image classification on Vulkan backend.

Python API¶

torch.is_vulkan_available() is exposed to Python API.

.vulkan() at the moment of writing of this tutorial is not exposed to Python API, but it is planned to be there.

Android Java API¶

For Android API to run model on Vulkan backend we have to specify this during model loading:

In this case, all inputs will be transparently copied from CPU to the Vulkan device, and model will be run on Vulkan device, the output will be copied transparently to CPU.

Building android test app with Vulkan¶

Or if you need only specific abi you can set it as an argument:

Add prepared model mobilenet2-vulkan.pt to test applocation assets:

After successful installation, the application with the name ‘MBQ’ can be launched on the device.

Источник

Что такое Vulkan и DirectX и как они влияют на видеоигры

penci holder

Большинство из нас, геймеров, слышали о Microsoft DirectX. Однако, немногие из нас знакомы с его утилитами и как они влияют на видеоигры. В настоящее время, фактически, приобретя конкурента в форме Vulkan, вещи относящиеся к двум API, как правило, становятся еще более сложными. В этом руководстве мы увидим, что такое API, Vulkan и DirectX, и мы покажим метод, с помощью которого они влияют на наши игры.

Предварительная информация о API

Прежде чем мы начнем говорить о DirectX и Vulkan, нам нужно сначала понять, что такое API. Аббревиатура означает «Интерфейс прикладного программирования».

Интерфейс предназначен для обеспечения связи между двумя объектами. Одним из примеров является графический интерфейс Windows, который играет роль посредника между операционной системой и пользователем.

Интерфейс обеспечивает удобную среду. С помощью этой среды мы используем операционную систему, не зная, как ее функции реализованы в фоновом режиме. Интерфейс прикладного программирования (API) заполняет роль посредника. Однако на этот раз пользователь может быть ПК или другой программой и не обязательно человеком. API-интерфейсы гораздо более распространены, чем можно было бы подумать, предлагая программистам необходимые инструменты для создания своего программного обеспечения.

directx 11 windows 7 1Ориентировочный пример, в котором мы используем API, — это когда мы автоматически регистрируемся в новом социальном средстве или онлайн-сервисе, используя наши ранее существующие учетные записи из Facebook или Google (вместо создания новой учетной записи вручную).

В таких случаях веб-сайт использует API, через который он связывается с конкретной услугой (например, Facebook или Twitter), чтобы собирать нашу личную информацию (имя (имена), адрес электронной почты, контактные номера и т. д.) Для создания нашего нового аккаунта.

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

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

DirectX и Vulkan фактически улучшают связь между приложением (игрой) и графическим процессором, чтобы повысить производительность графики.

1 23 1024x589Microsoft DirectX

С выпуском Windows 95 и модели защищенной памяти разработчики не имели такого же доступа к ресурсам, как в MS-DOS. DirectX впервые появился в виде набора конкретных API для разработки мультимедийных приложений, таких как игры.

Термин «DirectX» начинается со слова «Direct», ссылаясь на прямой доступ к ресурсам системы. Некоторые примеры включают Direct3D для графики и DirectSound для аудио. Часть «Х» относится к API в общей коллекции; таким образом объединив все API-интерфейсы под названием DirectX. Вышеупомянутое название также вдохновило название популярной видеоигр компании Xbox.

Вышеприведенное иллюстрирует тесную связь между DirectX и консолью Microsoft. Его последняя версия, DirectX 12, имеет большие улучшения. Тем не менее он поддерживается только Windows 10 и новейшей игровой консолью компании Xbox One.

vulkan amd 1024x514Direct3D является жемчужиной DirectX и полезен для создания 3D-объектов на нашем экране. Он также позволяет просматривать игры в полноэкранном режиме, а также использовать аппаратные ускорители. Последний метод позволяет реализовать некоторые функции более эффективно, чем они работают в программном обеспечении. Это может быть достигнуто за счет более эффективного использования аппаратного обеспечения нашего компьютера. В этом случае это будет наша видеокарта.

Вулкан AMD

В 2015 году Kronos Group разработала свой собственный API. Vulkan — это низкоуровневый API, используемый для разработки графически требующих приложений. Его первая стабильная версия дебютировала в августе 2016 года.

Следует четко указать, что «низкий уровень» не относится к качеству. Вместо этого этот термин описывает способность Вулкана работать на аппаратном уровне.

Хронос окружает себя одними из самых больших имен в ИТ-индустрии. Некоторые из них — Google, Intel, Sony, Nvidia и AMD. Последние два дали API, свести к минимуму время разработки Vulkan.

OpenGL — популярный API среди графических дизайнеров. Фактически он был разработан Хроносом, и он также включает в себя многие характеристики Вулкана. Однако его прием игровыми дизайнерами был непредвиденным.

Одним из самых сильных активов Vulkan является тот факт, что он с открытым исходным кодом. Кроме того, совместимость Vulkan с несколькими платформами вместе с общей производительностью — это два дополнительных актива, которые делают его более прибыльным, чем DirectX.

Здесь вы можете найти полный список с именами, которые содержат Khronos. Мантия обеспечила основную базу, на которой был разработан Вулкан. Наконец Vulkan в настоящее время находится в версии 1.1.

Как они влияют на игры

До этого момента мы рассмотрели некоторые основы, касающиеся API, Microsoft и Khronos. Но как они влияют на игры?

Эти два API значительно улучшили производительность. До сих пор DirectX, по-видимому, обеспечивал лучшую производительность, чем Vulcan, что на самом деле он не так далеко позади.

Microsoft утверждает, что DirectX 12 снижает потребление на 50% при использовании DirectX 11. С другой стороны, Vulkan также демонстрирует лучшую гибкость, чем его предшественник. Говоря о предшественниках, DirectX 11 и OpenGL были созданы с учетом одноядерных процессоров; что означает, что они не были точно настроены с использованием новых, многоядерных процессоров.

В результате одно ядро ​​управляет большинством различных процессов, в то время как остальные работают с низкой скоростью, а иногда и вовсе отключены. Оба API (DirectX 12 и Vulkan) поддерживают процессоры с несколькими ядрами и потоками, чтобы максимально эффективно использовать свои возможности. Более того, они передают большую часть требуемых задач от процессора к графической карте (видеокартам), предлагая более сбалансированный опыт.

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

Поддержка нескольких графических карт

Здесь Khronos Group столкнулась со значительным разрывом между двумя API-интерфейсами с поддержкой использования нескольких графических карт (использование явного многоканального GPU). Мы можем использовать разные карты, если их чипы имеют аналогичную архитектуру и используют один и тот же драйвер. Это позволит различным картам обрабатывать другую часть экрана.

Microsoft здесь еще на один шаг впереди, позволяя использовать несколько графических карт даже у другого производителя, что часто бывает, поскольку большинство систем имеют независимый и интегрированный графический процессор. Важно подчеркнуть тот факт, что эти реализации отличаются от возможностей SLI и Crossfire от Nvidia и AMD, которые реализованы с помощью драйверов, и в частности, в случае SLI требуют идентичные графические карты.

Шейдеры

Шейдеры — это небольшие программы, которые запускаются на наших видеокартах. Они отвечают за определенные функции различных объектов в 3D-среде. Тени, туман и освещение в игре являются результатом шейдера.

Vulkan использует промежуточное представление для шейдеров под названием SPIR-V. Его двоичная форма похожа на байт-код DirectX DX.

SPIR-V версия 1.3 отличается SPIR-V opt, инструментом для уменьшения размера шейдеров. Максимальный размер достигает + 40% от байт-кода DX соответствующего представления для DirectX.

Кроме того, некоторые структуры в HLSL (высокоуровневый шейдерный язык), которые были разработаны Microsoft, не поддерживались непосредственно некоторыми видеокартами.

HLSL широко используется DirectX с версии 9. Он использовался в качестве дополнения к существующему языку ассемблера шейдеров. С новой версией SPIR-V Vulkan также поддерживает ее.

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

Совместимость с несколькими платформами

Что касается платформ, большое преимущество Vulkan заключается в том, что он поддерживает Windows, Linux, Mac OS, Android и iOS. DirectX 12 с другой стороны, поддерживается только в Windows 10 и Xbox One. Чтобы использовать усовершенствования, предлагаемые DirectX 12, нам нужно либо обновить нашу операционную систему до Windows 10, либо получить новую консоль компании.

Если вы хотите попробовать DirectX 12, и вам не удалось получить Windows 10 во время бесплатного обновления, ознакомьтесь с нашим пошаговым руководством по свободным методам модернизации, которые доступны:

Возвращаясь к предыдущей теме, игровой порт, поддерживаемый API Vulkan, будет значительно проще по сравнению с портом, поддерживаемым DirectX.

С одной стороны, мы можем иметь названия на нескольких платформах, а с другой разные операционные системы имеют возможность размещать наши игры. Одна из причин, почему Linux не так популярен, как Windows, связана с тем, что последняя отличается от игр.

Распределение Linux может быть лучшим выбором для размещения наших игр, поскольку он может быть скорректирован для этой цели. Например Steam OS — это специализированная операционная система, предназначенная исключительно для игр.

Также подумайте: компания думает о создании программного обеспечения для разработки игр и хочет поддерживать API. Кто бы вы выбрали?

Оба имеют схожие мощности оба лучшие, чем их предшественники, и оба обеспечивают явное использование видеокарт. Vulkan поддерживает все платформы, включая Windows 10 и Xbox One, в то время как DirectX поддерживает только последние две.

vulkan performanceВиртуальная реальность

Необходимо сказать, что Vulkan является примером больших улучшений в области виртуальной реальности. Приложение VR должно отображать определенную 3D-сцену с двух разных точек зрения — по одному для каждого глаза.

До этого момента вышесказанное было возможно, отправив все необходимые команды на нашу графическую карту, чтобы сформировать трехмерное изображение для одной перспективы. Подход такой же для перспективы нашего второго глаза.

Версия 1.1 Vulkan предлагает набор команд рендеринга для формирования нескольких, немного разных выходов (изображений), которые в конечном итоге дают лучшую производительность в приложениях VR.

Развитие и будущее

Было бы упущением, не говоря уже о ходе разработки двух API. С одной стороны, у нас есть ветеран DirectX с более чем 20-летним развитием. С другой стороны, Вулкану едва будет 3 года с 2015 года. Тот факт, что Vulkan является открытым исходным кодом, может немного повлиять на его темпы роста. Конечно игроки Khronos, похоже серьезно относятся к разработке API, так как уровни улучшения впечатляют.

Все мы можем создавать новые инструменты и модификации и предоставлять их сообществу, помогая API расти быстрее. Наконец следует упомянуть, что DirectX не имеет вышеуказанной функции. Несмотря на свои годы развития, около 40 игр в настоящее время используют Vulkan, занимая большую часть рынка. Некоторые из них — Quake, Roblox, Talos и Dota 2. Что касается производительности, Vulkan приближается к DirectX, и в некоторых случаях он превосходит его. Самые захватывающие примеры работы Вулкана — игра Doom.

vulkan comparisonVulkan расширил свою поддержку названий AAA, таких как Wolfenstein II, не пренебрегая названиями VR, такими как Doom VFR и Serious Sam VR. Здесь вы можете увидеть подробный список поддерживаемых игр. Хотя здесь вы найдете игры с поддержкой DirectX 12.

Оба API значительно улучшили производительность. Лучшее использование нескольких графических карт и меньшее использование ЦП повысит общую производительность наших систем. По слухам, новые видеокарты от Nvidia будут выпущены к концу лета и значительно превзойдут сегодняшние высокопроизводительные графические карты. В целом, общее состояние вещей кажется довольно гибким. В любом случае, изменения в разработке игр скоро будут у нас, и оба API несомненно будут играть важную роль.

Как вы относитесь к двум API?

Вы уже узнали всю информацию, которую мы предоставили на Vulkan и DirectX? Со временем их соперничество усиливается, какой из двух API вы считаете более полезным для развития игры? Мы с нетерпением ждем ваших комментариев.

Источник

Vulkan GPU backend #252

Does SkiaSharp support the Vulkan GPU Backend? If not, any plans to add it? I’m working on a Vulkan app and am looking for a 2D solution for the UI.

Current PRs

The text was updated successfully, but these errors were encountered:

Most certainly we are going to be adding this. At this time no-one has asked, so we never got around to it, but it should be relatively simple to add. It just needs the few setup types, and then that gets handed over the the GRContext to continue as normal.

Feel free to have a go and send a PR 🙂

Feel free to have a go and send a PR 🙂

I’ll take a look at it. Is there anyway to build just the Desktop?

I usually just build externals-windows on Windows and externals-osx on macOS. This is the native bits, and then you can use the unit test projects to test. If you want to run a UI with it, you can use the samples. Just uninstall the SkiaSharp NuGet and add the project references.

If you are using Linux, then there is just the one x64 platform and libs.

Looking forward to seeing what you are doing.

Tried running WindowsSample and am getting:

libSkiaSharp.dll is installed in the x86/x64 folders. I have Microsoft Visual C++ 2015 Redistributable installed (reinstalled it to make sure it was the latest).

Also, the link to the Microsoft Visual C++ 2015 Redistributable in the readme is broken.

@jcoder58, If you are still working, we can chat on https://gitter.im/xamarin/XamarinComponents and get you started.

Well, that didn’t go far. Skia doesn’t have the Vulkan backend in the C API :(.

That is what I am doing with SkiaSharp. the C API. And then the C# API on that.

You could have a stab at that, it is not too tough once you get the hang of it. I basically just have a C method that calls the real C++ method. You can just do what is needed, and then clean up later.

This is something that we will be looking at in the future.

I guess biggest factor will be actually testing with other OSes and checking if current API covers it.

Also the issue got a bit more publicity now (no.3 top upvoted issue) 😄

@mattleibow @MarchingCube Sorry for the late response guys, had other pressing matters. I have to wrap up some code, but hopefully I can test this on windows and droid (and AndroidTV) early/mid next week. Thanks a ton for the work! Cant wait to test!

@MarchingCube I see you got the family involved 😜 Rather than actual features, I am concerned that the API has changed a fair bit from now to the current head: https://github.com/google/skia/tree/master/include/gpu/vk

Rebased the PRs on the later m80 codebase. We can now work from there.

This has been pushed to the preview feed for initial testing:

@mattleibow I tried to use this, but SharpVk has a bug in their Droid version where it cant get a surface. I posted the fix for me on his issues page FacticiusVir/SharpVk#55. I run a modified version of his wrapper to be able to run on Droid. So what is the best way to be able to build the vulkan version of this using my SharpVk fork?

@BradChase2011 at this point, this PR only builds skia with Vulkan support for Win32.

To build an Android skia with Vulkan, you will have to change the property in the native/android/build.cake. And then build the new native library.

I’ll have a look at this soon an see what breaks. Or, you can try by opening a PR to change that property. I think it is skia_uses_vulkan or something.

Interesting. seems to build for android just fine so far. I thought this was just for Android N+ and I was thinking I had to do something. Hmmm.

I’ll create a new PR and then you can try that.

Added this PR that will build for Android and Linux: #1287

Fingers crossed it Just Works ™️

@BradChase2011 I just pushed out the Android/Linux PR as a NuGet to the preview feed as 2.80.0-pr.1287.3

I hacked a few things and is seems to at least create a GRContext on Android. I tested with a modified version of https://github.com/discosultan/VulkanCore.

Closing this now as all the supported platforms (Win32, Linux, Android) are building.

Awesome, thanks much! Ill give it another shot here as soon as I get a chance to jump back into playing with libraries. As far as I know SharpVk was the only wrapper I could find that has the latest bindings for Vulkan 1.2, it seems all the others stopped being updated on earlier versions.

I’ve been trying to get this to work for a couple of days but I’m failing. Is there an example of rendering to the backbuffer? The c++ examples I’ve found seem to create a texture to render to rather than going straight at the screen.

Should we be doing SKSurface.CreateAsRenderTarget or SKSurface.Create? Should we be manually filling out a GRVkImageInfo? Which properties need to be filled in? Is GRVkImageInfo.Alloc needed if you’re attaching to an existing texture?

Everything I try seems to end up with SKSurface.Create* returning null.

@garrynewman have you found a way to create a vulkan sksurface

Maybe @MarchingCube can help? I believe that they got that working pretty well all over.

@mattleibow @garrynewman Missed the notification until I started poking around in SkiaSharp again 🙂

@MarchingCube Thanks for the info! If you have extra time, I would love for some more info on how to get this running. We have a full UI library based on Vulkan and Skia for drawing vectors.

So a normal path we take right now is to take say an SVG, and then load it into a SKBitmap and SKCanvas and then DrawPicture and from there take the pixels, convert them into our format and push it over to the GPU Image.

I am having a hard time understanding how that changes into using the Vulkan version of drawing. Do you have a small example of setting up the different GR— objects? Or do you have any links to some good examples or any examples hah that helped you guys get moving forward?

I guess to be clear, we don’t write direct to the back buffer, we write to textures and then use those later on to write to the back buffer.

Anything you can add or link to would be GREATLY appreciated, I cant seem to find any info anywhere.

EDIT: I cant seem to figure out how to link an SKBitmap over to the GRBackendRenderTarget or whatever is needed to push it into an Image on the vulkan side.

Источник

Vulkan is a new-generation graphics and compute API for high-efficiency, cross-platform access to GPUs. As the industry’s only open standard modern GPU API, Vulkan is unique in enabling developers to write applications that are portable to multiple diverse platforms. Vulkan includes the latest graphics technologies including ray tracing and is integrated into NVIDIA’s production drivers for NVIDIA GeForce, RTX and Quadro solutions on Windows and Linux, NVIDIA Shield and the Jetson embedded computing platform using Android or Linux.

Vulkan logo

GeForce and Quadro Drivers
For Windows and Linux
Learn More

Vulkan 1.3

The latest version of the Vulkan specification was released in January 2022 and incorporates significant, proven, developer-requested features. NVIDIA shipped full functionality Vulkan 1.3 drivers for Windows and Linux on the day the specification launched. These drivers also support the extended set of functionality in the Vulkan Roadmap 2022 milestone. NVIDIA’s Nsight Graphics and Nsight Systems tools have been updated to support Vulkan 1.3, offering a robust environment with deep support for developers to build and optimize Vulkan games and applications.

Learn more about Vulkan 1.3

Vulkan at NVIDIA

NVIDIA consistently provides industry leadership to evolve new Vulkan functionality such as ray tracing and DLSS AI rendering and is often the first to make it available to developers. The NVIDIA Nsight suite of development tools, has integrated support for Vulkan, including debugging and optimizing of applications using full ray tracing functionality. NVIDIA ships Vulkan on PCs, embedded platforms, automotive, and the data center. And gamers enjoy ongoing support of the latest Vulkan API changes with older GPUs going back to Maxwell.

Learn More About Vulkan and NVIDIA

RTX Ray Tracing in Vulkan

Vulkan provides cross-platform access to RTX ray tracing acceleration. NVIDIA’s Vulkan drivers support the Vulkan Ray Tracing extensions on all RTX GPUs, and GeForce GTX 1660 with 6GB+ of memory and GeForce GTX 1060+ with 6GB+ of memory. Vulkan support is available now in NVIDIA’s RTX SDKs including Direct Illumination (RTXDI), RTX Global Illumination (RTXGI), RTXMU that reduces memory consumption of acceleration structures and NVIDIA Real-Time Denoisers (NRD).

Learn more

DLSS and Vulkan

Every Vulkan Developer can access NVIDIA DLSS on Windows and Linux with support for both x86 and ARM-based platforms. NVIDIA has also added DLSS support for Vulkan API games on Proton, and DLSS-enhanced DirectX titles running via Proton layered over Vulkan, enabling Linux gamers to use the dedicated AI Tensor Cores of their GeForce RTX GPUs to accelerate frame rates in titles such as DOOM Eternal, No Man’s Sky, and Wolfenstein: Youngblood.

Vulkan Video

Harness accelerated H.264 and H.265 video decoding with Vulkan Video – a collection of extensions that tap into the Vulkan API for efficient and scalable video processing.

Vulkan Video is the only high performance, vendor-neutral, cross platform video decode API that offers explicit control over low-level resource management.

Read about Vulkan Video. Check out NVIDIA’s open-source decode sample application here.

Learn More

Samples


NVIDIA provides a growing collection of Vulkan and OpenGL samples and tutorials with full source code available on GitHub. Developers can download the samples that interest them, from educational introductions to basic Vulkan workflows and extensions, through examples of how to render scenes with high geometric complexity and ray tracing,and on to professional application use-cases. The repository also contains utility code that can speed up Vulkan development.

Learn more with a full list of NVIDIA Vulkan Samples

Vulkan Developer Tools


Nsight Aftermath

The NVIDIA Nsight Aftermath SDK is a simple library that can be integrated into a game’s crash reporter to generate GPU «mini-dumps» when a GPU hang or exception occurs.

Learn More

Nsight Systems

NVIDIA Nsight Systems is a system-wide analysis tool for visualizing CPU / GPU interactions to help eliminate GPU idle, stutter and CPU bottlenecks. It can trace Vulkan on the CPU & GPU, interoperating GPU APIs, and many CPU or OS events.

Learn More

Nsight Graphics

NVIDIA Nsight Graphics enables developers to debug & profile Vulkan applications. With powerful low-level profiling features such as GPU Trace, it’s easier than ever to identify GPU performance issues and optimize with confidence.

Learn More

The Path to Ray Tracing in Vulkan

In November 2020, Khronos released the final versions of the Vulkan Ray Tracing extensions that seamlessly integrate ray tracing into the existing Vulkan framework. Vulkan is the industry’s first open, cross-vendor, cross-platform standard that can be used to access RTX ray tracing acceleration.

Alongside the release of ray tracing support in the Khronos Vulkan SDK in December 2020, NVIDIA now ships the Vulkan Ray Tracing extensions in our production Vulkan drivers . All RTX GPUs are supported, together with GeForce GTX 1660 with 6GB+ of memory and GeForce GTX 1060+ with 6GB+ of memory.

NVIDIA has also released Quake II RTX version 1.4 that uses Vulkan Ray Tracing to significantly enhance the visual quality of this well-loved classic running with ray-traced lighting, shadows, and reflections — making Quake II RTX the world’s first cross-vendor ray tracing Vulkan application! NVIDIA releases the full source code on GitHub serving as a great example for developers who want to dive into the details of how this remastering was achieved.

Getting Started with Vulkan Ray Tracing

A tutorial on how to use Vulkan Ray Tracing to create a complete mini-path tracer using the final Vulkan Ray Tracing extensions

A Vulkan-based glTF ray tracer viewer with open source on GitHub

An updated Vulkan Ray Tracing Tutorial using the final Vulkan Ray Tracing extensions

Blog on Vulkan Ray Tracing Best Practices for Hybrid Rendering as used in Wolfenstein: Youngblood

Read about how the 2020.6 release of the NVIDIA Nsight Graphics tool supports Vulkan Ray Tracing

The Vulkan backend is a multi-platform backend implemented using the Vulkan API. Vulkan is supported on Windows, Linux, and Android. Vulkan’s API is very close to Veldrid’s and as such this is a fairly simple, straightforward backend.

Vulkan GraphicsDevices are created from a VkSurfaceSource, which is a platform-specific object used to create a Vulkan surface (VkSurfaceKHR). The following helper functions are available:

  • CreateWin32: Creates a VkSurfaceSource for the given Win32 instance and window handle.
  • CreateXlib: Creates a VkSurfaceSource for the given Xlib display and window.

API Concept Map

Veldrid Concept Vulkan Concept Notes
GraphicsDevice VkDevice, VkPhysicalDevice, VkCommandPool, VkDescriptorPool, VkQueue
CommandList VkCommandBuffer
DeviceBuffer VkBuffer
BufferUsage VkBufferUsageFlagBits
Texture VkImage
TextureUsage VkImageUsageFlagBits
TextureView VkImageView
Sampler VkSampler
Pipeline VkPipeline
Blend State VkPipelineColorBlendStateCreateInfo
Depth Stencil State VkPipelineDepthStencilStateCreateInfo
Rasterizer State VkPipelineRasterizationStateCreateInfo
PrimitiveTopology VkPrimitiveTopology, VkPipelineInputAssemblyStateCreateInfo
Vertex Layouts VkPipelineVertexInputStateCreateInfo
Shader VkShaderModule
ShaderSetDescription None
Framebuffer VkFramebuffer
ResourceLayout VkDescriptorSetLayout
ResourceSet VkDescriptorSet
Swapchain VkSwapchainKHR

Notes

Veldrid’s API is modeled after modern graphics API’s like Vulkan. As a result, this backend is simple, straightforward, and has very good performance. Driver support for Vulkan remains somewhat less common than other graphics API’s, but new GPUs from all major vendors support Vulkan. In time, Vulkan will likely be supported by all major systems.

Memory Management

Memory management must be custom-handled in Vulkan. The VkDeviceMemoryManager class allocates and reclaims all memory needed in the Vulkan backend. In general, the allocation handling is as follows:

  • The manager tracks several «chunk allocators», one for each type of memory (the memoryTypeBits and VkMemoryPropertyFlags identify a «type» of memory).
  • Each chunk allocator tracks a set of contiguous allocations of real physical device memory.
  • When requested, an individual chunk allocator identifies a free chunk of memory (or allocates one), and subdivides it into an appropriate block for usage by the caller.
  • Chunk allocators also reclaim memory when a resource is disposed.

Staging Textures

Staging Textures are actually implemented using VkBuffers, rather than VkImages. This has no observable effect on the implementation, and is actually the recommended approach.

Linear VkImages would be another option, but they are extremely limited in most Vulkan implementations, and cannot support all of the possible permutations of a staging Texture (dimensions, mips, array layers, etc.). For example, almost all Vulkan implementations require that Linear images be 2D (not even 1D), have one mip level, have one array layer, and are a small subset of pixel formats. Since staging Textures are conceptually just a contiguous, tightly-packed block of memory, a VkBuffer works perfectly and has none of the above limitations. Simple arithmetic can convert between the buffer’ linear address space into a Texture’s 1D, 2D, or 3D address space. Vulkan has a variety of commands that perform copies between VkBuffers and VkImages.

From Wikipedia, the free encyclopedia

Vulkan

Vulkan logo.svg
Original author(s) AMD, DICE (original Mantle design)
Developer(s) Khronos Group (donated and derived variant, as Vulkan)
Initial release February 16, 2016; 6 years ago[1]
Stable release 1.3.240 (January 26, 2023; 9 days ago[2]) [±]
Repository
  • github.com/KhronosGroup/Vulkan-Headers Edit this at Wikidata
Written in C[3]
Operating system Android, Linux, Haiku, Fuchsia, BSD Unix,[4] QNX,[5] Windows, Nintendo Switch,[6][7][8] Stadia, Tizen,[9][10] macOS,[11] iOS,[11] iPadOS,[11] tvOS,[11] Raspberry Pi,[12] vxWorks[13]
Type 3D graphics and compute API[14]
License Apache License 2.0[15]
Website vulkan.org

Vulkan is a low-overhead, cross-platform API, open standard for 3D graphics and computing.[16][17][18] Vulkan targets high-performance real-time 3D graphics applications, such as video games and interactive media. Vulkan is intended to offer higher performance and more efficient CPU and GPU usage compared to older OpenGL and Direct3D 11 APIs. It provides a considerably lower-level API for the application than the older APIs, making Vulkan comparable to Apple’s Metal API and Microsoft’s Direct3D 12. In addition to its lower CPU usage, Vulkan is designed to allow developers to better distribute work among multiple CPU cores.[19]

Vulkan was first announced by the non-profit Khronos Group at GDC 2015.[14][20][21] The Vulkan API was initially referred to as the «next generation OpenGL initiative», or «OpenGL next»[22] by Khronos, but use of those names was discontinued when Vulkan was announced.[23]

Vulkan is derived from and built upon components of AMD’s Mantle API, which was donated by AMD to Khronos with the intent of giving Khronos a foundation on which to begin developing a low-level API that they could standardize across the industry.[14]

Vulkan is not backwards compatible with OpenGL,[24][18][note 1] although there are certain projects that implement OpenGL as a layer on top of Vulkan, such as Google’s ANGLE and Mesa’s Zink.[25]

Features[edit]

OpenGL and Vulkan are both rendering APIs. In both cases, the GPU executes shaders, while the CPU executes everything else.

Vulkan is intended to provide a variety of advantages over other APIs as well as its predecessor, OpenGL. Vulkan offers lower overhead, more direct control over the GPU, and lower CPU usage.[21] The overall concept and feature set of Vulkan is similar to concepts seen in Mantle and later adopted by Microsoft with Direct3D 12 and Apple with Metal.

Intended advantages of Vulkan over previous-generation APIs include the following:

Unified API[edit]

Vulkan provides a single API for both desktop and mobile graphics devices, whereas previously these were split between OpenGL and OpenGL ES respectively.

Cross platform[edit]

Vulkan is available on multiple modern operating systems. Like OpenGL, and in contrast to Direct3D 12, the Vulkan API is not locked to a single OS or device form factor. Vulkan runs on Android, Linux, BSD Unix, QNX, Nintendo Switch,
Raspberry Pi, Stadia, Fuchsia, Tizen, Windows 7, 8, 10, and 11; , Haiku, and MoltenVK provides freely-licensed[26][27][28][29] third-party support for macOS, iOS and tvOS by wrapping over Apple’s Metal API.[30]

Lower CPU usage[edit]

Vulkan reduces load on CPUs through the use of batching and other low-level optimizations, therefore reducing CPU workloads and leaving the CPU free to do more computation or rendering than would otherwise be possible.[31][32]

Multi-threading friendly design[edit]

Direct3D 11 and OpenGL 4 were initially designed for use with single-core CPUs and only received augmentation to be executed on multi-cores. Even when application developers use the augmentations, these APIs regularly do not scale well on multi-cores. Vulkan offers improved scalability on multi-core CPUs due to the modernized threading architecture.[33][34]

Pre-compiled shaders[edit]

OpenGL uses the high-level language GLSL for writing shaders, which forces each OpenGL driver to implement its own compiler for GLSL. This then executes at application runtime to translate the program’s shaders into the GPU’s machine code. In contrast, Vulkan drivers are supposed to ingest shaders already translated into an intermediate binary format called SPIR-V (Standard Portable Intermediate Representation), analogous to the binary format that HLSL shaders are compiled into in Direct3D. By allowing shader pre-compilation, application initialization speed is improved and a larger variety of shaders can be used per scene. A Vulkan driver only needs to perform GPU specific optimization and code generation, resulting in easier driver maintenance, and potentially smaller driver packages.[35] The developers of applications now can also more easily obfuscate proprietary shader code, due to shaders not being stored directly as source code.[34][18]

Others[edit]

  • Vulkan provides unified management of compute kernels and graphical shaders, eliminating the need to use a separate compute API in conjunction with a graphics API.
  • Ray tracing is provided in a set of cross-vendor extensions, which together are analogous to the OptiX and DirectX Raytracing APIs.[36] No such functionality is exposed in OpenGL.

OpenGL vs. Vulkan[edit]

OpenGL Vulkan[37]
One single global state machine Object-based with no global state
State is tied to a single context All state concepts are localized to a command buffer
Operations can only be executed sequentially Multi-threaded programming is possible
GPU memory and synchronization are usually hidden Explicit control over memory management and synchronization
Extensive error checking Vulkan drivers do no error checking at runtime;
there is a validation layer for developers

NVIDIA states that «OpenGL is still a great option for a lot of use cases, as it comes at a much lower complexity and maintenance burden than Vulkan, while in many cases still providing great overall performance.»[38]

AMD states that «Vulkan supports close-to-metal control, enabling faster performance and better image quality across Windows 7, Windows 8.1, Windows 10, and Linux. No other graphics API offers the same powerful combination of OS compatibility, rendering features, and hardware efficiency.»[39]

Versions[edit]

Vulkan 1.1[edit]

At SIGGRAPH 2016, Khronos announced that Vulkan would be getting support for automatic multi-GPU features, similar to what is offered by Direct3D 12.[40] Multi-GPU support included in-API removes the need for SLI or Crossfire which requires graphics cards to be of the same model. API multi-GPU instead allows the API to intelligently split the workload among two or more completely different GPUs.[41] For example, integrated GPUs included on the CPU can be used in conjunction with a high-end dedicated GPU for a slight performance boost.

On March 7, 2018, Vulkan 1.1 was released by the Khronos Group.[42] This first major update to the API standardized several extensions, such as multi-view, device groups, cross-process and cross-API sharing, advanced compute functionality, HLSL support, and YCbCr support.[43] At the same time, it also brought better compatibility with DirectX 12, explicit multi-GPU support, ray tracing support,[44][45] and laid the groundwork for the next generation of GPUs.[46] Alongside Vulkan 1.1, SPIR-V was updated to version 1.3.[43]

Vulkan 1.2[edit]

On January 15, 2020, Vulkan 1.2[47] was released by the Khronos Group.[48] This second major update to the API integrates 23 additional commonly-used proven Vulkan extensions into the base Vulkan standard. Some of the most important features are «timeline semaphores for easily managed synchronization», «a formal memory model to precisely define the semantics of synchronization and memory operations in different threads», and «descriptor indexing to enable reuse of descriptor layouts by multiple shaders». The additional features of Vulkan 1.2 improve its flexibility when it comes to implementing other graphics APIs on top of Vulkan, including «uniform buffer standard layout», «scalar block layout», and «separate stencil usage».[49]

Vulkan 1.3[edit]

On January 25, 2022, Vulkan 1.3 was released by the Khronos Group.[50] This third major update to the API integrates 23 additional commonly-used proven Vulkan extensions into the base Vulkan standard.[51] Vulkan 1.3 focuses on reducing fragmentation by making the new features not optional in order for a device to be considered Vulkan 1.3 capable.[50][52] The new features in Vulkan 1.3 include dynamic rendering, additional dynamic state, improved synchronization API, and device profiles.

Planned features[edit]

When releasing OpenCL 2.2, the Khronos Group announced that OpenCL would converge where possible with Vulkan to enable OpenCL software deployment flexibility over both APIs.[53][54] This has been now demonstrated by Adobe’s Premiere Rush using the clspv[55] open source compiler to compile significant amounts of OpenCL C kernel code to run on a Vulkan runtime for deployment on Android.[56]

History[edit]

The Khronos Group began a project to create a next generation graphics API in July 2014 with a kickoff meeting at Valve.[57] At SIGGRAPH 2014, the project was publicly announced with a call for participants.[14]

According to the US Patent and Trademark Office, the trademark for Vulkan was filed on February 19, 2015.[58]

Vulkan was formally named and announced at Game Developers Conference 2015, although speculation and rumors centered around a new API existed beforehand and referred to it as «glNext«.[59]

2015[edit]

In early 2015, LunarG (funded by Valve) developed and showcased a Linux driver for Intel which enabled Vulkan compatibility on the HD 4000 series integrated graphics, despite the open-source Mesa drivers not being fully compatible with OpenGL 4.0 until later that year.[60][61] There is still the possibility[62] of Sandy Bridge support, since it supports compute through Direct3D11.

On August 10, 2015, Google announced that future versions of Android would support Vulkan.[63] Android 7.x «Nougat» launched support for Vulkan on August 22, 2016. Android 8.0 «Oreo» has full support.

On December 18, 2015, the Khronos Group announced that the 1.0 version of the Vulkan specification was nearly complete and would be released when conforming drivers were available.[21]

2016[edit]

The full Vulkan specification and the open-source Vulkan SDK were released on February 16, 2016.[1]

2018[edit]

On February 26, 2018, Khronos Group announced that the Vulkan API became available to all on macOS and iOS through the MoltenVK library, which enables Vulkan to run on top of Metal.[64] Other new developments were shown at SIGGRAPH 2018.[65] Previously MoltenVK was a proprietary and commercially licensed solution, but Valve made an arrangement with developer Brenwill Workshop Ltd to open-source MoltenVK under the Apache 2.0 license and as a result the library is now available on GitHub. Valve also announced that Dota 2 can as of 26 February 2018 run on macOS using the Vulkan API, which is based on MoltenVK.[66]

2019[edit]

On February 25, 2019, the Vulkan Safety Critical (SC) Working Group was announced to bring Vulkan GPU acceleration to safety critical industries.[67]

Google’s Stadia streaming cloud gaming service uses Vulkan on Linux based servers with AMD GPUs.[68]

2020[edit]

On January 15, 2020, Vulkan 1.2 was released.

Alongside the Vulkan 1.2 release, the Khronos Group posted a blog post which considered that HLSL support in Vulkan had reached «production ready» status, given the improvements in Microsoft’s DXC compiler and Khronos’s glslang compiler, and new features in Vulkan 1.2 which enhance HLSL support.[69]

On February 3, 2020, the Raspberry Pi Foundation announced that it was working on an open source Vulkan driver for their Raspberry Pi, a popular single board computer.[70] On June 20, 2020, a graphics engineer revealed that he had created one after two years of work that was capable of running VkQuake3 at over 100FPS on the small computer.[71]

On March 17, 2020, Khronos Group released the Ray Tracing extensions, based on Nvidia’s proprietary extension, with some major extensions and many minor changes, which in turn was based on Nvidia’s OptiX API.[72][73] On November 23, 2020, these Ray Tracing extensions were finalized.[74]

On November 24, 2020, Raspberry Pi Foundation announced that their driver for the Raspberry Pi 4 is Vulkan 1.0 conformant.[75]

2022[edit]

On January 25, 2022, Vulkan 1.3 was released.

On March 1, 2022, Vulkan SC 1.0 was released, bringing Vulkan graphics and compute for the safety-critical industry while being based on the Vulkan 1.2 standard.[76]

On August 1, 2022, Raspberry Pi Foundation announced that their driver for the Raspberry Pi 4 is Vulkan 1.2 conformant.[77]

On September 1, 2022 Mesh Shading for Vulkan was released[78][79]

Support across vendors[edit]

Screenshot of vulkaninfo, showing information about supported Vulkan instances and vkcube, a program to test Vulkan implementation on a system

Initial specifications stated that Vulkan drivers can be implemented on any hardware that supports OpenGL ES 3.1 or OpenGL 4.x and up.[80] As Vulkan support requires new graphics drivers, this does not necessarily imply that every existing device that supports OpenGL ES 3.1 or OpenGL 4.x will have Vulkan drivers available.

Intel, Nvidia and AMD[edit]

All three major PC vendors provide free of charge Vulkan API implementations in the form of drivers for the Linux and Windows systems.[24] On Windows, Vulkan is supported by the newer lines of hardware like Intel Skylake and higher, AMD GCN 2.0 and higher, and Nvidia Kepler and higher. On Linux, the open-source Mesa driver supports AMD (GCN 1.0/1.1 unofficially, GCN 2.0 and above officially) and Intel (Ivy Bridge and later unofficially, Broadwell and later officially);[81] while support for Nvidia GPUs requires Nvidia’s official proprietary driver.[82]

Android and mobile GPUs[edit]

Most modern Android devices support Vulkan. Android 7.0 Nougat includes optional Vulkan 1.0 support,[83] Android 9.0 Pie includes optional Vulkan 1.1 support, and Android 10 requires all 64-bit devices support Vulkan 1.1.[84][85] On Linux and some ChromeOS devices, the open-source Mesa driver provides support for Arm Mali (Midgard and Bifrost), Qualcomm Adreno, and Broadcom VideoCore VI hardware.[81]

Apple[edit]

As of June 2022, there is no native support for Vulkan API provided by Apple devices.[86] Vulkan support is available via the open-source library MoltenVK, which provides a Vulkan implementation on top of the Metal graphics API provided on iOS and macOS devices, though it has some limitations in regards to certain advanced API features.[30] Vulkan 1.3 is supported.[87] In June 2022, version 1.3.217 of Vulkan added support for Metal objects, facilitating import and export between the two APIs.[88]

See also[edit]

  • List of 3D graphics libraries

Notes[edit]

  1. ^ The process of setting up a graphics rendering pipeline doesn’t differ drastically from OpenGL [ES] ones. E.g. shaders written in GLSL still can be reused: the source code can be compiled/translated by a standalone compiler into a new intermediate binary format called SPIR-V, which can then be consumed by the Vulkan API.

References[edit]

  1. ^ a b «Khronos Releases Vulkan 1.0 Specification». Khronos.org. Khronos Group Press Release. February 16, 2016. Archived from the original on October 20, 2021.
  2. ^ «Vulkan® 1.0 — A Specification». Retrieved January 26, 2023.
  3. ^ «KhronosGroup/Vulkan-Docs». GitHub. October 10, 2021. Archived from the original on October 20, 2021.
  4. ^ «Vulkan on FreeBSD». Vulkan GPU info. October 28, 2021.
  5. ^ «Vulkan on QNX». www.khronos.org. July 14, 2021. Archived from the original on October 20, 2021.
  6. ^ «Nintendo Switch Listed as Vulkan and OpenGL Conformant — My Nintendo News». My Nintendo News. Excite Global Media. December 19, 2016. Archived from the original on October 20, 2021.
  7. ^ Palumbo, Alessio (December 19, 2016). «Nintendo Switch Officially Supports Vulkan, OpenGL 4.5 & OpenGL ES». WCCF Tech. Archived from the original on October 20, 2021.
  8. ^ «Conformant Products». khronos.org. The Khronos Group. April 28, 2018. Archived from the original on January 28, 2017. Retrieved February 28, 2018.
  9. ^ Bright, Peter & Walton, Mark (February 16, 2016). «Vulkan now official, with 1.0 API release and AMD driver [Updated]». Ars Technica. Condé Nast. Archived from the original on October 20, 2021. Retrieved February 18, 2016.
  10. ^ Valich, Theo (February 17, 2016). «Mantle Cycle is Complete as Khronos Releases Vulkan 1.0». VR World. Archived from the original on October 20, 2021. Retrieved February 19, 2016.
  11. ^ a b c d «GitHub — KhronosGroup/MoltenVK: MoltenVK is an implementation of the high-performance, industry-standard Vulkan graphics and compute API, that runs on Apple’s Metal graphics framework, bringing Vulkan to iOS and macOS». GitHub. Archived from the original on October 20, 2021. Retrieved September 12, 2019.
  12. ^ «Vulkan on Raspberry Pi». www.raspberrypi.org. July 14, 2021. Archived from the original on October 20, 2021.
  13. ^ «VxWorks offers support for many standard graphic libraries, such as …, and Vulkan» (PDF). WinDriver.
  14. ^ a b c d «More on Vulkan and SPIR — V: The future of high-performance graphics» (PDF). Khronos Group. p. 10. Archived (PDF) from the original on August 11, 2016. Retrieved June 27, 2015. Thanks AMD!
  15. ^ «LICENSE file». October 3, 2018. Archived from the original on October 20, 2021. Retrieved October 30, 2020 – via GitHub.
  16. ^ «Vulkan». NVIDIA Developer. December 2, 2015. Archived from the original on October 20, 2021. Retrieved July 8, 2021.
  17. ^ «Vulkan®». GPUOpen. Archived from the original on October 20, 2021. Retrieved July 8, 2021.
  18. ^ a b c «Developing 3D Graphics with Vulkan on Mobile». Qualcomm Developer Network. Archived from the original on October 20, 2021. Retrieved July 8, 2021.
  19. ^ Hruska, Joel. «Next-generation Vulkan API could be Valve’s killer advantage in battling Microsoft». ExtremeTech. Archived from the original on March 13, 2015. Retrieved June 26, 2015.
  20. ^ «Vulkan: Graphics and compute Belong Together» (PDF). Khronos Group. March 2015. Archived (PDF) from the original on December 18, 2016. Retrieved March 5, 2015.
  21. ^ a b c «Vulkan – Graphics and compute belong together». Khronos Group. Archived from the original on October 20, 2021. Retrieved March 5, 2015.
  22. ^ Smith, Ryan. «Khronos Announces Next Generation OpenGL Initiative». Archived from the original on October 20, 2021. Retrieved September 24, 2016.
  23. ^ Batchelor, James (March 3, 2015). «glNext revealed as Vulkan graphics API». Develop.
  24. ^ a b Tim Anderson (March 3, 2015). «Here comes Vulkan: The next generation of the OpenGL graphics API». www.theregister.com. Archived from the original on October 20, 2021. Retrieved July 8, 2021.
  25. ^ «Zink — The Mesa 3D Graphics Library latest documentation». docs.mesa3d.org. Retrieved March 10, 2022.
  26. ^ «MoltenVK, popular Vulkan development tool for macOS, goes open-source». Neowin. Archived from the original on October 20, 2021. Retrieved February 28, 2018.
  27. ^ «Vulkan graphics will enable faster games and apps on Apple platforms». VentureBeat. February 26, 2018. Archived from the original on October 20, 2021. Retrieved February 28, 2018.
  28. ^ «Vulkan Is Now Available On macOS/iOS By MoltenVK Being Open-Sourced, Vulkan SDK for Mac — Phoronix». www.phoronix.com. Retrieved February 28, 2018.
  29. ^ «Vulkan lavapipe software rendering is working on Haiku». Haiku Community. September 24, 2021. Retrieved September 21, 2022.
  30. ^ a b «MoltenVK». Molten. Archived from the original on January 5, 2018. Retrieved April 5, 2016.
  31. ^ «Vulkan: High efficiency on mobile». Imagination Technologies. November 5, 2015. Archived from the original on November 9, 2015. Retrieved January 23, 2016.
  32. ^ «Khronos Group Announces The Next-Generation ‘Vulkan’ Graphics And Compute API». Tom’s Hardware. March 3, 2015. Archived from the original on October 20, 2021.
  33. ^ «Vulkan: Scaling to multiple threads». Imagination Technologies. November 24, 2015. Archived from the original on November 26, 2015. Retrieved January 23, 2016.
  34. ^ a b «Adreno Vulkan Developer Guide» (PDF). August 31, 2017. pp. 9–10, 22. Archived (PDF) from the original on October 20, 2021.
  35. ^ Kessenich, John. «An Introduction to SPIR-V» (PDF). Khronos Group. Archived from the original (PDF) on October 20, 2021. Retrieved March 5, 2015.
  36. ^ «Ray tracing in Vulkan». Khronos Group. December 15, 2020. Archived from the original on October 20, 2021.
  37. ^ «FOSDEM 2016 — Vulkan in Open-Source». FOSDEM. Archived from the original on October 20, 2021. Retrieved February 27, 2016.
  38. ^ «Transitioning from OpenGL to Vulkan». Nvidia. February 11, 2016. Archived from the original on October 20, 2021.
  39. ^ «AMD Vulkan API». AMD. Archived from the original on October 20, 2021.
  40. ^ «Vulkan Next will bring better support for VR and multiple GPUs». PC World. Archived from the original on October 20, 2021.
  41. ^ Smith, Daniel Williams, Ryan. «Ashes of the Singularity Revisited: A Beta Look at Direct3D 12 & Asynchronous Shading». AnandTech. Archived from the original on October 20, 2021.
  42. ^ «Khronos Group Releases Vulkan 1.1». The Khronos Group (Press release). March 7, 2018. Archived from the original on October 20, 2021. Retrieved March 21, 2018.
  43. ^ a b Larabel, Michael (March 7, 2018). «Vulkan 1.1 Released As The First Major Update To This Graphics/Compute API». Phoronix. Retrieved March 7, 2018.
  44. ^ Larabel, Michael (September 19, 2018). «Vulkan 1.1.85 Released With Raytracing, Mesh Shaders & Other New NVIDIA Extensions». Phoronix. Retrieved September 19, 2018.
  45. ^ Larabel, Michael (November 4, 2018). «Vulkan 1.1.91 Released With NV_ray_tracing, AMD Memory Overallocation Behavior». Phoronix. Retrieved November 4, 2018.
  46. ^ Bright, Peter (March 7, 2018). «Vulkan 1.1 out today, with multi-GPU support, better DirectX compatibility». Ars Terchnica. Archived from the original on October 20, 2021. Retrieved March 7, 2018.
  47. ^ «Vulkan 1.2 Specifications Released | Geeks3D». Archived from the original on October 20, 2021.
  48. ^ «Khronos Group Releases Vulkan 1.2». The Khronos Group (Press release). January 15, 2020. Archived from the original on October 20, 2021. Retrieved February 27, 2020.
  49. ^ «Vulkan 1.2 Arrives With An Eye On Greater Performance, Better Compatibility With Other 3D APIs On Top». Phoronix (Press release). January 15, 2020. Retrieved February 27, 2020.
  50. ^ a b «Khronos Strengthens Vulkan Ecosystem with Release of Vulkan 1.3, Public Roadmap and Profiles». January 25, 2022.
  51. ^ «Vulkan® 1.3.206 — A Specification (with all registered Vulkan extensions)». www.khronos.org.
  52. ^ «Vulkan 1.3 Specification Released». January 25, 2022.
  53. ^ «Breaking: OpenCL Merging Roadmap into Vulkan | PC Perspective». www.pcper.com. Archived from the original on November 1, 2017. Retrieved May 17, 2017.
  54. ^ «SIGGRAPH 2018: OpenCL-Next Taking Shape, Vulkan Continues Evolving — Phoronix». www.phoronix.com.
  55. ^ Clspv is a prototype compiler for a subset of OpenCL C to Vulkan compute shaders: google/clspv, August 17, 2019, archived from the original on October 20, 2021, retrieved August 20, 2019
  56. ^ «Vulkan Update SIGGRAPH 2019» (PDF). Archived from the original (PDF) on August 20, 2019.
  57. ^ SIGGRAPH 2015: 3D Graphics API State of the Union (Video). SIGGRAPH 2015. Khronos Group. September 16, 2015. Event occurs at 57:24. Retrieved November 12, 2015 – via YouTube.
  58. ^ «US Patent and Trademark Office». Archived from the original on May 11, 2013. Retrieved March 7, 2015.
  59. ^ Batchelor, James (March 3, 2015). «glNext revealed as Vulkan graphics API | Latest news from the game development industry | Develop». MCV. Develop. Retrieved March 5, 2015.
  60. ^ Larabel, Michael (March 5, 2015). «Valve Developed An Intel Linux Vulkan GPU Driver». Phoronix. Retrieved August 8, 2017.
  61. ^ Larabel, Michael (March 12, 2015). «Learning More About The Intel Vulkan Driver, Linux Vulkan Plans». Phoronix. Retrieved August 8, 2017.
  62. ^ «Evan Odabashian on Twitter». Archived from the original on August 19, 2020. Retrieved July 22, 2015.
  63. ^ Woods, Shannon (August 12, 2015). «Low-overhead rendering with Vulkan». Android Developers Blog. Archived from the original on October 20, 2021.
  64. ^ Bright, Peter (February 26, 2018). «Vulkan is coming to macOS and iOS, but no thanks to Apple». Ars Technica. Archived from the original on October 20, 2021. Retrieved February 26, 2018.
  65. ^ https://www.khronos.org/assets/uploads/developers/library/2018-siggraph/Vulkan-and-OpenGL-BOF-SIGGRAPH_Aug18.pdf[bare URL PDF]
  66. ^ Larabel, Michael (February 26, 2018). «Vulkan Is Now Available On macOS/iOS By MoltenVK Being Open-Sourced, Vulkan SDK for Mac». Phoronix. Retrieved February 26, 2018.
  67. ^ «Khronos Group Begins Work on a New Standards Initiative to Bring Vulkan GPU Acceleration to Safety Critical Industries». The Khronos Group. February 25, 2019. Archived from the original on October 20, 2021. Retrieved August 3, 2019.
  68. ^ Citation error. See inline comment how to fix.[verification needed]
  69. ^ «HLSL as a First Class Vulkan Shading Language». The Khronos Group. January 15, 2020. Archived from the original on October 20, 2021. Retrieved March 31, 2020.
  70. ^ February 2020, Nathaniel Mott 03 (February 3, 2020). «Raspberry Pi to Get Vulkan Graphics Driver (Eventually)». Tom’s Hardware. Archived from the original on August 19, 2020. Retrieved June 20, 2020.
  71. ^ June 2020, Zhiye Liu 20 (June 20, 2020). «Nvidia Engineer’s Vulkan Driver For Raspberry Pi Runs Quake III Over 100 FPS at 720p». Tom’s Hardware. Archived from the original on August 19, 2020. Retrieved June 20, 2020.
  72. ^ «Khronos Group Releases Vulkan Ray Tracing». The Khronos Group. March 17, 2020. Archived from the original on October 20, 2021.
  73. ^ «Vulkan Ray-Tracing Arrives With New Khronos Extension — Phoronix». www.phoronix.com. Retrieved March 17, 2020.
  74. ^ «Vulkan Ray Tracing Final Specification Release». The Khronos Group. November 23, 2020. Archived from the original on October 20, 2021.
  75. ^ «Vulkan update: we’re conformant!». Raspberry Pi Foundation. November 24, 2020.
  76. ^ «Vulkan SC — Vulkan graphics for the safety critical industry». The Khronos Group. February 22, 2019. Retrieved March 30, 2022.
  77. ^ «Vulkan update: version 1.2 conformance for Raspberry Pi 4». Raspberry Pi Foundation. August 1, 2022.
  78. ^ «Mesh Shading for Vulkan».
  79. ^ «VK_EXT_mesh_shader».
  80. ^ «Vulkan Overview» (PDF). Khronos Group. June 2015. Archived (PDF) from the original on December 8, 2015. Retrieved August 18, 2015. p. 19 «Vulkan Status»
  81. ^ a b «Mesamatrix: The OpenGL vs Mesa matrix». mesamatrix.net. Archived from the original on October 20, 2021.
  82. ^ «Vulkan Driver Support». NVIDIA Developer. February 10, 2016. Retrieved March 10, 2022.
  83. ^ «Android N’s second preview build supports Vulkan and new emoji». Ars Technica. April 13, 2016. Archived from the original on October 20, 2021.
  84. ^ «Support for Vulkan Graphics API 1.1 is coming in Android P». April 8, 2018. Archived from the original on October 20, 2021.
  85. ^ «What’s New in Android: Q Beta 3 & More». Archived from the original on October 20, 2021.
  86. ^ «The State of Vulkan on Apple Devices» (PDF). LunarG. June 2021. Archived (PDF) from the original on July 9, 2021.
  87. ^ «Release Release for Vulkan SDK 1.3.236 · KhronosGroup/MoltenVK». GitHub. Retrieved December 29, 2022.
  88. ^ Larabel, Michael (June 9, 2022). «Vulkan 1.3.217 Adds Extension To Interact With Apple Metal Objects». www.phoronix.com. Retrieved October 22, 2022.

Further reading[edit]

  • Vulkan Programming Guide: The Official Guide to Learning Vulkan (OpenGL), Nov 10, 2016, by Graham Sellers and John Kessenich ISBN 978-0-1344-64541
  • Learning Vulkan, Dec 2016, by Parminder Singh ISBN 978-1-78646-980-9
  • Introduction to Computer Graphics and the Vulkan API, Jul 1, 2017, by Kenwright ISBN 978-1-5486-16175
  • Vulkan Cookbook, Apr 28, 2017, by Pawel Lapinski ISBN 978-1-7864-68154

External links[edit]

  • Official website Edit this at Wikidata

Урок 50 — Введение в Vulkan

Думаю, вы как минимум слышали об Vulkan API —
новом графическом API от Khronos (некоммерческая организация разрабатывающая
OpenGL). Vulkan был анонсирован в феврале 2016, через 24 года после OpenGL, и
является полностью новым стандартом и уходом от текущей модели. Я не буду глубоко
вдаваться в отличия Vulkan, а только скажу, что он в разы более низкоуровневый
чем OpenGL, и даёт разработчику большой контроль над производительностью. Но с
большой силой приходит и большая ответственность. Разработчик должен взять под
контроль самые разные аспекты, например, буфер команд, синхронизацию и
управление памятью; ранее этим занимался драйвер. Но благодаря знанию структуры
приложения в деталях, разработчик может добиться максимальной производительности
используя Vulkan API нужным ему образом.

На мой взгляд, больше всего в Vulkan людей шокирует то, сколько требуется написать
кода просто для того, что бы вывести на экран первый треугольник. В первых уроках
по OpenGL для этого потребуется буквально пара строк, но здесь, для многих, желающих начать
цикл статей по Vulkan, это становится целым испытанием. Поэтому, как и всегда для
OGLDEV, я начну представлять материал по шагам. Мы выведем первый треугольник за
пару уроков, понемногу продвигаясь в каждом. Кроме того, я постараюсь не
вываливать дюжину вызовов API в одном длинном куске кода, а сразу начну
заворачивать в приложение с простым дизайном, который, я надеюсь, пригодится вам
для будущих приложений. Но в любом случае, это обучающее приложение, и не
стесняйтесь его изменять под себя.

Двигаясь по коду мы будем поочередно изучать ключевые компоненты Vulkan, поэтому
сейчас я просто хочу представить общую диаграмму:

Эта диаграмма ни в коем случае не претендует на полноту. Она содержит только
основные компоненты, которые будут использоваться в большинстве приложений. Связи
между компонентами обозначают зависимости в момент создания, либо перечисления.
Например, для создания поверхности требуется экземпляр объекта, а когда вы
перечисляете физические устройства системы, то также потребуется экземпляр. Два
цвета объясняют наш дизайн в общих чертах. Красный объединяет то, что я бы
назвал «ядром», а зелёный те части, которые будут «приложением». Позже мы
разберем для чего это нужно. Код самого приложения, которое вы будете писать,
будет наследоваться от «приложения», и все его части будут вам доступны для
использования. Очень надеюсь, что такой дизайн поможет нам в разработке следующих
частей этого цикла по Vulkan.

Подготовка системы

Первое что нам нужно, это проверить, что система поддерживает Vulkan, и
подготовить всё для разработки. Вы должны проверить, что ваша видеокарта поддерживает
Vulkan, и установить свежие драйвера. Так как Vulkan вышел в свет ещё совсем недавно,
то лучше проверять обновления драйверов как можно чаще, там могут быть исправления
ошибок. Поскольку существует огромное число GPU, я не могу подробно рассказать о
каждом. Обновление / установка драйверов под Windows не должна вызвать затруднений.
Под Linix могут потребоваться некоторые танцы с бубном. Для разработки я использую
Linux Fedora с видеокартой GT710 от NVIDIA на борту. NVIDIA предоставляет один
бинарный файл, который может быть установлен только из командной строки. У других
производителей всё может быть иначе. Под Linux вы можете использовать lspci для
скана системы и поиска своего GPU. Попробуйте добавить опции -v, -vv и -vvv
чтобы увидеть больше деталей.

Далее нам потребуется установить Vulkan SDK от компании Khronos, скачать который
можно по ссылке. SDK, помимо заголовочных файлов и
библиотек, включает в себя большое число примеров, которые вы можете использовать
для лучшего ознакомления с возможностями API. На момент написания урока актуальная
версия SDK 1.0.30.0, и я призываю вас регулярно проверять обновления, так как
SDK сейчас находится в активной разработке. В нескольких следующих разделах версия
будет указываться в командах в явном виде, так что не забывайте изменять её на
ту, которую вы устанавливаете.

Linux

Khronos предоставляет запускаемый файл предназначенный для Ubuntu. После запуска он
устанавливает всё что требуется, но при запуске под Fedora я столкнулся с некоторыми
сложностями. Я использовал следующие команды:

  • bash$ chmod +x vulkansdk-linux-x86_64-1.0.30.0.run
  • base$ ./vulkansdk-linux-x86_64-1.0.30.0.run –target VulkanSDK-1.0.30.0 –noexec
  • base$ ln -s ~/VulkanSDK-1.0.30/1.0.30.0 ~/VulkanSDK

Эти команды извлекают содержимое пакета без запуска внутренних скриптов. После распаковки
директория VulkanSDK-1.0.30.0 будет содержать каталог 1.0.30.0 с файлами пакета.
Предположим, что я запускал эти команды находясь в домашнем каталоге (известном как ~),
тогда мы получим символьную ссылку ~/VulkanSDK на каталог с содержимым пакета (с
каталогами source, samples, и т.д.). Ссылка упрощает переключение среды разработки на
более свежую версию. По ссылке можно получить библиотеки и заголовочные файлы. Чуть позднее
мы разберемся с тем, как их использовать. А пока что сделайте следующее:

  • bash$ cd VulkanSDK/1.0.30.0
  • bash$ ./build_examples.sh

Если всё прошло успешно, то примеры были собраны в examples/build. Для их запуска вы должны
cd в этот каталог. А теперь попробуйте запустить ./cube и ./vulkaninfo чтобы убедиться,
что Vulkan запускается на вашей системе, и получить информацию о драйвере.

Надеюсь, что всё прошло успешно, так что мы можем добавить немного символических ссылок, чтобы
удобнее обращаться к файлам, которые нам требуются для разработки. Зайдите под суперпользователем
(с помощью вызова su и ввода пароля) и запустите команды:

  • bash# ln -s /home/<your username>/VulkanSDK/x86_x64/include/vulkan /usr/include
  • base# ln -s /home/<your username>/VulkanSDK/x86_x64/lib/libvulkan.so.1 /usr/lib64
  • base# ln -s /usr/lib64/libvulkan.so.1 /usr/lib64/libvulkan.so

С помощью этих трёх команд мы добавили символические ссылки из /usr/include в каталог
заголовочных файлов Vulkan. Кроме того, мы добавили ссылки на динамические библиотеки,
которые будут использоваться при линковке. Теперь, если мы обновили SDK, то нам требуется только
изменить ссылку ~/VulkanSDK на местоположение новой версии. Отметим, что вызов команд из-под
рута требуется только один раз. После обновления SDK потребуется изменить ссылку только в
домашнем каталоге. Вы, конечно, можете дать ссылке любое имя, но код, который идет с
моими уроками, предполагает, что она находится в домашнем каталоге.

Windows

Установка под Windows ощутимо проще чем под Linux. Просто скачайте последнюю версию
здесь, дважды кликните по файлу установщика,
согласитесь со всем, что вам предложат, выберите директорию установки, и, в общем-то, всё.
Я бы предложил установить SDK в c:VulkanSDK для обеспечения совместимости с моим проектом
Visual Studio. Если вы устанавливаете куда-то ещё, то не забудьте обновить в проекте
директории с заголовочными файлами и библиотеками. Детали вы найдете в следующем разделе.

Сборка и запуск

Linux

Под Linux я в основном разрабатываю в Netbeans.
Код, который идет с уроками, содержит проекты сборки Netbeans для C/C++. Если
вы установили SDK как я написал выше, то эти проекты должны работать их коробки
(и, пожалуйста, сообщайте мне о любых проблемах). Если вы используете другую
систему сборки, убедитесь, что вы добавили:

  • В команду компиляции: -I<path to VulkanSDK/1.0.30.0/x86_64/include>
  • В команду линковки: -L<path to VulkanSDK/1.0.30.0/x86_64/lib> -lxcb -lvulkan’

Даже если вы не используете Netbeans, вы всё ещё можете скомпилировать урок
командой make. Netbeans самостоятельно генерирует Makefile. Этого будет
достаточно, чтобы проверить настройку системы. Для этого скачайте
исходники, разархивируйте их, зайдите в
каталог ogldev/tutorial50, а затем запустите команду make. Если вы всё
сделали правильно, то вы можете запустить dist/Debug/GNU-Linux-x86/tutorial50
из ogldev/tutorial50.

Windows

Если вы установили SDK в c:VulkanSDK, то мои проекты Visual Studio должны
работать прямо из коробки. Если же нет, или вы хотите создать новый проект
Visual Studio, то сделайте так:

Для обновления каталога с заголовочными файлами нажмите на проект в окошке
solution explorer, перейдите в Properties, а затем в
Configuration Properties -> C/C++ -> General. Теперь вы должны добавить
c:VulkanSDK<version>Include в Additional Include Directories.
Пример приведен ниже:

Для обновления каталога с файлами библиотеки нажмите правой кнопкой мыши на проект
в окошке solution explorer, перейдите в Properties и затем в
Configuration Properties -> Link -> General. Теперь вы должны добавить
c:VulkanSDK<version>Bin32 в поле Additional Library Directories.
Пример приведен ниже:

Пока вы ещё настраиваете линковщик зайдите в Input (сразу же под General), а
затем добавьте vulkan-1.lib в поле Additional Dependencies.

Общие комментарии

Прежде чем мы перейдем к коду, я бы хотел отметить некоторые мои решения о
дизайне приложений с использованием Vulkan.

  1. Многие функции в Vulkan (особенно те, которые создают объекты) принимают на
    вход параметр — структуру. Такая структура используется как обертка над большей
    частью параметров, которые нужны функции. Благодаря этому у функций ощутимо меньше
    входящих параметров. Разработчики Vulkan решили, что первым параметром у таких
    структур будет свойство sType. Оно имеет перечислимый тип, и для каждой структуры
    свой код. Это позволяет драйверу определять тип структуры, зная только её адрес.
    У каждого кода есть префикс VK_STRUCTURE_TYPE_. Например, код структуры
    используемой при создании экземпляра VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO.

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

  2. Ещё одно важное замечание об этих структурах — у них очень много свойств,
    которые нас пока не волнуют. Что бы код был компактнее (а уроки короче…) я
    всегда буду инициализировать структуры нулями (с помощью нотации struct = {})
    и в явном виде обозначать только те свойства, которые не могут быть нулями.
    Я объясню их в следующих уроках, когда эти свойства будут востребованы.

  3. В Vulkan функции либо являются процедурами, либо возвращают код ошибки в объекте
    VkResult. Код ошибки является перечислением, где VK_SUCCESS равно 0,
    а все остальные коды ошибок больше 0. По мере возможностей я добавляю проверку на
    ошибки. Если возникла ошибка, то я вывожу сообщение в консоль (а в Window в отдельном
    окошке) и выхожу. Обработка ошибок в реальном приложении слишком усложняет код, а
    моя задача сохранить простоту.

  4. Многие функции Vulkan (особенно те, которые создают объекты) принимают на вход
    функцию выделения памяти. Такой подход позволяет контролировать процесс выделения
    памяти Vulkan. На мой взгляд это тема для уже опытных разработчиков, поэтому мы
    не будем заморачиваться с этим и всегда будем передавать NULL. В этом случае
    драйвер будет использовать свою функцию по умолчанию.

  5. Vulkan не гарантирует экспорт своих функций в библиотеке. Это значит, что на
    некоторых платформах вы можете получить segmentation fault при вызове функции
    Vulkan так как она оказалась равна NULL. В этом случае вы вынуждены использовать
    vkGetInstanceProcAddr() для получения адреса функции перед её использованием
    (вспомним, что в OpenGL для этой проблемы мы использовали GLEW). В моем случае
    только vkCreateDebugReportCallbackEXT() была не доступна. Эта функция требуется
    только для дополнительной проверочной прослойки. Поэтому, я решил рискнуть и
    для всех функций которые я использую в уроке не получать адресов. Если поступят
    жалобы, то я обновлю код урока.

  6. Каждое серьезное приложение обязано позаботиться об освождении память, иначе
    не избежать утечек. В этом уроке я не стал усложнять и не уничтожаю никакие
    объекты. В любом случае они удалятся при завершении программы. В будущем я,
    возможно, ещё вернусь к этой теме, но пока просто запомните, что почти все
    функции вида <vkCreate()** имеют в пару **vkDestroy(). И будьте
    осторожны при удалении объектов пока программа ещё работает. Больше деталей вы
    найдете по ссылке.

Структура проекта

Далее приведен краткий перечень файлов, которые мы собираемся обозревать.

  1. tutorial50/tutorial50.cpp — здесь определена функция main().

  2. include/ogldev_vulkan.h — основной заголовочный и единственный файл в
    котором загружаются заголовочные файлы Vulkan. Вы можете включить проверочную
    прослойку раскоментив ENABLE_DEBUG_LAYERS. Этот файл содержит несколько
    вспомогательных функций и макросов, а так же определение класса VulkanWindowControl.

  3. Common/ogldev_vulkan.cpp — реализация функций, определённых в ogldev_vulkan.h.

  4. include/ogldev_vulkan_core.h — объявление главного класса OgldevVulkanCore в
    котором сосредоточена вся суть.

  5. Common/ogldev_vulkan_core.cpp — реализация класса OgldevVulkanCore.

  6. include/ogldev_xcb_control.h — объявление класса XCBControl, который
    создает окно в Linux.

  7. Common/ogldev_xcb_control.cpp — реализация XCBControl.

  8. include/ogldev_win32_control.h — объявление класса Win32Control, который
    создает окно в Windows.

  9. Common/ogldev_win32_control.cpp — реализация Win32Control.

Как в Netbeans, так и в Visual Studio файлы разделены между проектами tutorial50 и Common.

Прямиком к коду!

Я надеюсь, что вы справились с первой частью и теперь полностью готовы
погрузиться в Vulkan. Как я уже говорил, мы собираемся разработать наше первое
демо приложение в несколько этапов. Первым шагом будет настроить самые основные
объекты Vulkan: экземпляр, поверхность, физическое и логическое устройства.
Я буду объяснять следуя моему дизайну приложения, но вы вольны пропустить эту
часть и изучать только обращения к Vulkan.

В самом начале мы включаем заголовки Vulkan. В моем проекте все файлы Vulkan
включаются только в файле ogldev_vulkan.h. Поэтому во всём остальном проекте
включается только этот файл. Вот соответствующие куски кода:

#ifdef _WIN32
#define VK_USE_PLATFORM_WIN32_KHR
#include "vulkan/vulkan.h"
#include "vulkan/vk_sdk_platform.h"
#else
#define VK_USE_PLATFORM_XCB_KHR
#include <vulkan/vulkan.h>
#include <vulkan/vk_sdk_platform.h>
#endif

Обратите внимание на то, что мы добавили различные макросы для Windows и Linux.
Эти макросы включают дополнения для поддержки оконной системы для каждой ОС.
Причина, по которой включение заголовков отличается кавычками, в том, что в
Linux эти файлы устанавливаются в системный каталог (/usr/include/vulkan),
а в Windows в стандартный каталог.

Давайте начнем обзор с класса OgldevVulkanCore, который отвечает за создание
и работу с основными объектами.

class OgldevVulkanCore
{
public:
    OgldevVulkanCore(const char* pAppName);
    ~OgldevVulkanCore();

    bool Init(VulkanWindowControl* pWindowControl);

    const VkPhysicalDevice& GetPhysDevice() const;

    const VkSurfaceFormatKHR& GetSurfaceFormat() const;

    const VkSurfaceCapabilitiesKHR GetSurfaceCaps() const;

    const VkSurfaceKHR& GetSurface() const { return m_surface; }

    int GetQueueFamily() const { return m_gfxQueueFamily; }

    VkInstance& GetInstance() { return m_inst; }

    VkDevice& GetDevice() { return m_device; }

private:
    void CreateInstance();
    void CreateSurface();
    void SelectPhysicalDevice();
    void CreateLogicalDevice();

    // Объекты Vulkan
    VkInstance m_inst;
    VkDevice m_device;
    VkSurfaceKHR m_surface;
    VulkanPhysicalDevices m_physDevices;

    // Внутрение детали
    std::string m_appName;
    int m_gfxDevIndex;
    int m_gfxQueueFamily;
};

Помимо вектора объектов Vulkan m_physDevices (инициирован будет далее), класс
включает в себя три свойства Vulkan (m_inst, surface и m_device). Кроме
того, мы храним название приложения, индекс используемого физического устройства и
индекс набора очередей. Класс также содержит несколько методов чтения и функцию Init(), которая всё настраивает.
Давайте разберёмся, что же она делает.

void OgldevVulkanCore::Init(VulkanWindowControl* pWindowControl)
{
    std::vector<VkExtensionProperties> ExtProps;
    VulkanEnumExtProps(ExtProps);

    CreateInstance();

    #ifdef WIN32
    assert(0);
    #else
    m_surface = pWindowControl->CreateSurface(m_inst);
    assert(m_surface);
    #endif
    printf("Surface createdn");

    VulkanGetPhysicalDevices(m_inst, m_surface, m_physDevices);
    SelectPhysicalDevice();
    CreateLogicalDevice();
}

Эта функция принимает на вход объект VulkanWindowControl. Мы потом разберёмся с этим
объектом. Пока что достаточно сказать, что это ОС зависимый класс, задача которого — это
создание оконной поверхности, на которую будет происходить рендер. Совсем как и в OpenGL,
ядро Vulkan не содержит работы с окнами. Эта задача отдана расширениям, и у нас есть
полный набор для всех основных ОС. Участники Khronos могут публиковать свои собственные
расширения в общем регистре. Разработчики
драйверов сами решают какие из разрешений они хотят реализовывать. А уже пользователи
Vulkan могут во время работы приложения смотреть в список доступных разрешений и
решать что с ними делать.

Мы начнем с перечисления всех расширений. Происходит это в следующей функции —
декораторе:

void VulkanEnumExtProps(std::vector<vkextensionproperties>& ExtProps)
{
    uint NumExt = 0;
    VkResult res = vkEnumerateInstanceExtensionProperties(NULL, &NumExt, NULL);
    CHECK_VULKAN_ERROR("vkEnumerateInstanceExtensionProperties error %dn", res);

    printf("Found %d extensionsn", NumExt);

    ExtProps.resize(NumExt);

    res = vkEnumerateInstanceExtensionProperties(NULL, &NumExt, &ExtProps[0]);
    CHECK_VULKAN_ERROR("vkEnumerateInstanceExtensionProperties error %dn", res);

    for (uint i = 0 ; i < NumExt ; i++) {
        printf("Instance extension %d - %sn", i, ExtProps[i].extensionName);
    }
}

Функция выше обрамляет вызов vkEnumerateInstanceExtensionProperties() к
Vulkan API, который возвращает доступные в системе расширения. То, как мы
используем это функцию, очень распространённая методика в Vulkan. Первый вызов возвращает
количество расширений. Это число мы используем для задания размера вектора
расширений. Второй вызов уже возвращает сами расширения. Первый параметр
позволяет выбрать прослойку. Vulkan устроен таким образом, что производители
видеокарт могут добавлять логические прослойки для валидации, дополнительной
отладочной печати и другие. Во время работы приложения мы вольны выбирать, какой
из слоев включить. Например, во время разработки включить слой с проверками
данных, а в готовой версии приложения уже отключать. Так как нам нужны
все расширения, то мы передаем NULL в качестве слоя.

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

void OgldevVulkanCore::CreateInstance()
{
    VkApplicationInfo appInfo = {};
    appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
    appInfo.pApplicationName = m_appName.c_str();
    appInfo.engineVersion = 1;
    appInfo.apiVersion = VK_API_VERSION_1_0;

    const char* pInstExt[] = {
#ifdef ENABLE_DEBUG_LAYERS
        VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
#endif
        VK_KHR_SURFACE_EXTENSION_NAME,
#ifdef _WIN32
        VK_KHR_WIN32_SURFACE_EXTENSION_NAME,
#else
        VK_KHR_XCB_SURFACE_EXTENSION_NAME
#endif
    };

#ifdef ENABLE_DEBUG_LAYERS
    const char* pInstLayers[] = {
        "VK_LAYER_LUNARG_standard_validation"
    };
#endif

    VkInstanceCreateInfo instInfo = {};
    instInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
    instInfo.pApplicationInfo = &appInfo;
#ifdef ENABLE_DEBUG_LAYERS
    instInfo.enabledLayerCount = ARRAY_SIZE_IN_ELEMENTS(pInstLayers);
    instInfo.ppEnabledLayerNames = pInstLayers;
#endif
    instInfo.enabledExtensionCount = ARRAY_SIZE_IN_ELEMENTS(pInstExt);
    instInfo.ppEnabledExtensionNames = pInstExt;

    VkResult res = vkCreateInstance(&instInfo, NULL, &m_inst);
    CHECK_VULKAN_ERROR("vkCreateInstance %dn", res);

#ifdef ENABLE_DEBUG_LAYERS
    // Получаем адрес функции vkCreateDebugReportCallbackEXT
    my_vkCreateDebugReportCallbackEXT = reinterpret_cast<pfn_vkcreatedebugreportcallbackext>(vkGetInstanceProcAddr(m_inst, "vkCreateDebugReportCallbackEXT"));

    // Регистрируем функцию отладки
    VkDebugReportCallbackCreateInfoEXT callbackCreateInfo;
    callbackCreateInfo.sType       = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
    callbackCreateInfo.pNext       = NULL;
    callbackCreateInfo.flags       = VK_DEBUG_REPORT_ERROR_BIT_EXT |
                                     VK_DEBUG_REPORT_WARNING_BIT_EXT |
                                     VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
    callbackCreateInfo.pfnCallback = &MyDebugReportCallback;
    callbackCreateInfo.pUserData   = NULL;

    VkDebugReportCallbackEXT callback;
    res = my_vkCreateDebugReportCallbackEXT(m_inst, &callbackCreateInfo, NULL, &callback);
    CheckVulkanError("my_vkCreateDebugReportCallbackEXT error %dn", res);
#endif
}

Для инициализации библиотеки Vulkan мы должны создать экземпляр — объект
VkInstance. Этот объект хранит состояние приложения. Функция, которая
создает его, называется vkCreateInstance(), и ей требуется большая часть
свойств структуры VkInstanceCreateInfo. Интересующие нас параметры, это
список расширений и (дополнительно) список слоев, которые мы хотим включить.
Из расширений это расширение общей поверхности и расширение для ОС зависимой
поверхности. Слои и расширения определяются через их название — строку, а для
некоторых из них Khronos SDK предлагает макрос. VkInstanceCreateInfo также
принимает указатель на структуру VkApplicationInfo. Эта структура содержит
свойства приложения, а разработчик может задать название и некоторую
внутреннюю версию движка. Свойство VkApplicationInfo, на которое стоит обратить
внимание, это apiVersion. Это задает минимальную версию Vulkan, которая
требуется приложению. Если в системе установлена версия меньше, то этот
вызов бросит ошибку. Мы запрашиваем версию 1.0, так что всё должно быть в порядке.

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

PFN_vkCreateDebugReportCallbackEXT my_vkCreateDebugReportCallbackEXT = NULL;

VKAPI_ATTR VkBool32 VKAPI_CALL MyDebugReportCallback(
    VkDebugReportFlagsEXT       flags,
    VkDebugReportObjectTypeEXT  objectType,
    uint64_t                    object,
    size_t                      location,
    int32_t                     messageCode,
    const char*                 pLayerPrefix,
    const char*                 pMessage,
    void*                       pUserData)
{
    printf("%sn", pMessage);
    return VK_FALSE;    // Т.к. мы не хотим чтобы вызывающая функция упала.
}

Далее мы создадим оконную поверхность. Для этого мы воспользуемся объектом
VulkanWindowControl, указатель на который получает функция Init(). С этим
классом мы познакомимся позднее, поэтому не будем на нём сейчас останавливаться
(обратите внимание на то, что для создания поверхности используется экземпляр;
поэтому мы и создаём объекты в этом порядке).

После создания экземпляра и поверхности мы готовы к получению информации о
физических устройствах системы. Под физическим устройством мы понимаем либо
дискретную, либо интегрированную видеокарту. Например, ваш компьютер может
иметь две видеокарты NVIDIA с технологией SLI и графический GPU Intel HD,
встроенный в CPU. В этом случае у вас три физических устройства. Функция ниже
получает все физические устройства и некоторые их характеристики в виде
структуры VulkanPhysicalDevices. Структура, по сути, представляет собой
базу данных физических устройств и их свойств. Она состоит из нескольких
векторов (иногда векторов векторов) объектов Vulkan. Для получения доступа к
конкретному устройству вы должны получить индекс устройства и с ним обращаться
к вектору. То есть, для получения информации о физическом устройстве с индексом
2 обращайтесь к m_device[2] и m_devProps[2], и так далее. Причина, по
которой я выбрал такую структуру (а не один объект на устройство), в том, что
это совпадает с форматом API Vulkan. Вы предоставляете массив XYZ и получаете
все XYZ объекты для всех физических устройств. Вот определение этой схожей
с базой данных структуры:

struct VulkanPhysicalDevices {
    std::vector<VkPhysicalDevice> m_devices;
    std::vector<VkPhysicalDeviceProperties> m_devProps;
    std::vector< std::vector<VkQueueFamilyProperties> > m_qFamilyProps;
    std::vector< std::vector<VkBool32> > m_qSupportsPresent;
    std::vector< std::vector<VkSurfaceFormatKHR> > m_surfaceFormats;
    std::vector<VkSurfaceCapabilitiesKHR> m_surfaceCaps;
};

Теперь давайте рассмотрим функцию заполнения базы данных. Первых два параметра
представляют собой экземпляр и поверхность. Третий параметр это то, куда будут
записаны данные. Мы будем изучать функцию по частям.

void VulkanGetPhysicalDevices(const VkInstance& inst, const VkSurfaceKHR& Surface, VulkanPhysicalDevices& PhysDevices)
{
    uint NumDevices = 0;

    VkResult res = vkEnumeratePhysicalDevices(inst, &NumDevices, NULL);
    CHECK_VULKAN_ERROR("vkEnumeratePhysicalDevices error %dn", res);
    printf("Num physical devices %dn", NumDevices);

Вначале мы должны получить число физических устройств. И снова мы видим систему
из двух вызовов — первый для получения количества элементов, а второй для
получения уже самих значений.

    PhysDevices.m_devices.resize(NumDevices);
    PhysDevices.m_devProps.resize(NumDevices);
    PhysDevices.m_qFamilyProps.resize(NumDevices);
    PhysDevices.m_qSupportsPresent.resize(NumDevices);
    PhysDevices.m_surfaceFormats.resize(NumDevices);
    PhysDevices.m_surfaceCaps.resize(NumDevices);

Мы можем изменить размер базы данных таким образом, чтобы вмещать все элементы.

    res = vkEnumeratePhysicalDevices(inst, &NumDevices, &PhysDevices.m_devices[0]);
    CHECK_VULKAN_ERROR("vkEnumeratePhysicalDevices error %dn", res);

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

    for (uint i = 0 ; i < NumDevices ; i++) {
        const VkPhysicalDevice& PhysDev = PhysDevices.m_devices[i];
        vkGetPhysicalDeviceProperties(PhysDev, &PhysDevices.m_devProps[i]);

Мы начинаем с получения свойств текущего устройства. m_devProps — это вектор
VkPhysicalDeviceProperties. Эта структура содержит такую информацию об
устройстве, как название, версия, ID и прочее. При помощи следующих вызовов
printf мы выводим на печать некоторые из этих свойств:

        printf("Device name: %sn", PhysDevices.m_devProps[i].deviceName);
        uint32_t apiVer = PhysDevices.m_devProps[i].apiVersion;
        printf("    API version: %d.%d.%dn", VK_VERSION_MAJOR(apiVer),
                                          VK_VERSION_MINOR(apiVer),
                                          VK_VERSION_PATCH(apiVer));

После этого мы получаем свойства всех наборов очередей, которые есть у устройства.
GPU может выполнять всего четыре вида операций:

  1. Графические — 2D/3D рендер (как и OpenGL).

  2. Вычисление — общий вычислительный процесс, который никак не связан с рендером.
    Используется, например, для параллельных вычислений, без какого-либо отношения
    к 3D.

  3. Перемещение — копирование буферов и изображений.

  4. Управление фрагментированной памятью, т.е. которая не смежна. Эти команды
    помогают разобраться с ней.

Задачи, которые мы отправляем устройству, выполняются по очереди. Устройство
предоставвляет один или несколько наборов очередей, и каждый из них содержит
одну и более очередей. У каждого набора своя комбинация из четырёх типов
приведенных выше. Очереди в каждом наборе имеют общую функциональность.
Например, мой GPU имеет два набора: первый состоит из 16 очередей и принимает
все четыре типа команд. А второй только из одной очереди, которая поддерживает
лишь перемещение. Это полезно для архитектурно-зависимых трюков по улучшению
производительности приложения.

        uint NumQFamily = 0;

        vkGetPhysicalDeviceQueueFamilyProperties(PhysDev, &NumQFamily, NULL);

        printf("    Num of family queues: %dn", NumQFamily);

        PhysDevices.m_qFamilyProps[i].resize(NumQFamily);
        PhysDevices.m_qSupportsPresent[i].resize(NumQFamily);

        vkGetPhysicalDeviceQueueFamilyProperties(PhysDev, &NumQFamily, &(PhysDevices.m_qFamilyProps[i][0]));

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

        for (uint q = 0 ; q < NumQFamily ; q++) {
            res = vkGetPhysicalDeviceSurfaceSupportKHR(PhysDev, q, Surface, &(PhysDevices.m_qSupportsPresent[i][q]));
            CHECK_VULKAN_ERROR("vkGetPhysicalDeviceSurfaceSupportKHR error %dn", res);
        }

Пока мы ещё говорим про наборы очередей, давайте пройдёмся по каждому набору и
проверим, поддерживает ли он вывод на экран. vkGetPhysicalDeviceSurfaceSupportKHR()
принимает на вход физическое устройство, поверхность, индекс набора очередей и
возвращает флаг — может ли такая комбинация из устройства и набора выводить на
поверхность.

        uint NumFormats = 0;
        vkGetPhysicalDeviceSurfaceFormatsKHR(PhysDev, Surface, &NumFormats, NULL);
        assert(NumFormats > 0);

        PhysDevices.m_surfaceFormats[i].resize(NumFormats);

        res = vkGetPhysicalDeviceSurfaceFormatsKHR(PhysDev, Surface, &NumFormats, &(PhysDevices.m_surfaceFormats[i][0]));
        CHECK_VULKAN_ERROR("vkGetPhysicalDeviceSurfaceFormatsKHR error %dn", res);

        for (uint j = 0 ; j < NumFormats ; j++) {
            const VkSurfaceFormatKHR& SurfaceFormat = PhysDevices.m_surfaceFormats[i][j];
            printf("    Format %d color space %dn", SurfaceFormat.format , SurfaceFormat.colorSpace);
        }

На очереди формат поверхности. Каждая поверхность поддерживает не менее одного
формата. Формат просто определяет то, как данных используются поверхностью.
В целом, формат указывает на каналы каждого пикселя и тип канала
(float, int, …). Например, VK_FORMAT_R32G32B32_SFLOAT задает три канала
(красный, зелёный и синий) из 32-х битного типа с плавающей запятой. Формат
поверхности очень важен так как он определяет то, как данные будут использоваться
или конвертироваться в различных операциях (например отображение на экран).
Для получения формата нам нужны как поверхность, так и физическое устройство
так как они могут получиться несовместимыми. Мы снова используем вектор векторов
поскольку форматов поверхностей может быть доступно сразу несколько штук.
Формат нам понадобится позже, поэтому сейчас мы записываем его в базу данных.
Теперь давайте получим свойства поверхности:

        res = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(PhysDev, Surface, &(PhysDevices.m_surfaceCaps[i]));
        CHECK_VULKAN_ERROR("vkGetPhysicalDeviceSurfaceCapabilitiesKHR error %dn", res);

        VulkanPrintImageUsageFlags(PhysDevices.m_surfaceCaps[i].supportedUsageFlags);
    }
}

Структура VkSurfaceCapabilitiesKHR описывает свойства физического устройства
в рамках конкретной поверхности. Они включают в себя минимальное и максимальное
количество изображений, которые могут входить в цепочку изображений,
минимальный и максимальный размер участка, который может быть отрендерен,
поддерживаемые повороты и прочее. Для каждой пары физического устройства и
поверхности у нас по одной структуре, все они хранятся в векторе m_surfaceCaps.

Ух, наконец-то мы получили всю информацию о физических устройствах! (Ещё раз,
некоторые из этих свойств зависят от выбранной поверхности). Следующий шаг в
функции Init() — это выбор одного из физических устройств и одной из очередей
для начала обработки. Следующая функция занимается как раз этим:

void OgldevVulkanCore::SelectPhysicalDevice()
{
    for (uint i = 0 ; i < m_physDevices.m_devices.size() ; i++) {

        for (uint j = 0 ; j < m_physDevices.m_qFamilyProps[i].size() ; j++) {
            VkQueueFamilyProperties& QFamilyProp = m_physDevices.m_qFamilyProps[i][j];

            printf("Family %d Num queues: %dn", j, QFamilyProp.queueCount);
            VkQueueFlags flags = QFamilyProp.queueFlags;
            printf("    GFX %s, Compute %s, Transfer %s, Sparse binding %sn",
                    (flags & VK_QUEUE_GRAPHICS_BIT) ? "Yes" : "No",
                    (flags & VK_QUEUE_COMPUTE_BIT) ? "Yes" : "No",
                    (flags & VK_QUEUE_TRANSFER_BIT) ? "Yes" : "No",
                    (flags & VK_QUEUE_SPARSE_BINDING_BIT) ? "Yes" : "No");

            if (flags & VK_QUEUE_GRAPHICS_BIT) {
                if (!m_physDevices.m_qSupportsPresent[i][j]) {
                    printf("Present is not supportedn");
                    continue;
                }

                m_gfxDevIndex = i;
                m_gfxQueueFamily = j;
                printf("Using GFX device %d and queue family %dn", m_gfxDevIndex, m_gfxQueueFamily);
                break;
            }
        }
    }

    if (m_gfxDevIndex == -1) {
        printf("No GFX device found!n");
        assert(0);
    }
}

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

Всё что нам осталось, это инициализировать ядро и создать логическое устройство:

void OgldevVulkanCore::CreateLogicalDevice()
{
    float qPriorities = 1.0f;
    VkDeviceQueueCreateInfo qInfo = {};
    qInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
    qInfo.queueFamilyIndex = m_gfxQueueFamily;
    qInfo.queueCount = 1;
    qInfo.pQueuePriorities = &qPriorities;

    const char* pDevExt[] = {
        VK_KHR_SWAPCHAIN_EXTENSION_NAME
    };

    VkDeviceCreateInfo devInfo = {};
    devInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
    devInfo.enabledExtensionCount = ARRAY_SIZE_IN_ELEMENTS(pDevExt);
    devInfo.ppEnabledExtensionNames = pDevExt;
    devInfo.queueCreateInfoCount = 1;
    devInfo.pQueueCreateInfos = &qInfo;

    VkResult res = vkCreateDevice(GetPhysDevice(), &devInfo, NULL, &m_device);

    CHECK_VULKAN_ERROR("vkCreateDevice error %dn", res);

    printf("Device createdn");
}

Vulkan разделяет понятия физического устройства, как части реальной системы, от
логического устройства как абстракции над ним. Логическое устройство — это то,
что используется в приложении для создания большей части объектов зависящих от
устройства (очереди, цепочки изображений и прочее). Такая архитектура добавляет
гибкости в управлении устройствами. Логическое устройство позволяет нам давать
доступ только к отдельным аспектам физического устройства. Например, если
физическое устройство поддерживает и графику и вычисления, то мы можем дать
доступ только к графике через логическое устройство.

Для создания устройства нам понадобится одна структура VkDeviceCreateInfo и
ещё одна VkDeviceQueueCreateInfo. VkDeviceCreateInfo главная часть
определения устройства. В этой структуре мы назначаем указатель на массив
расширений, которые хотим использовать. Нам нужно включить цепочки изображений,
так как они определены в расширениях, а не в ядре. Цепочка изображений — это
массив изображений поверхностей, которые могут быть нарисованы. Нам также нужен
размер массива расширений. Далее нам нужен указатель на массив структур
VkDeviceQueueCreateInfo (и его размер). Для каждого набора очередей, который
мы хотим использовать, потребуется одна структура VkDeviceQueueCreateInfo.
Эта структура содержит индекс набора очередей (который мы получили ранее в
SelectPhysicalDevice()), число требуемых нам очередей, и для каждой очереди
мы можем указать приоритет. В этом уроке мы не будем задавать приоритеты, т.к.
очередь у нас одна и приоритет у неё 1.0.

На этом завершается инициализация класса OgldevVulkanCore, но для вызова
метода Init() нам нужен VulkanWindowControl — класс, который я добавил
для декорации управления оконной поверхности. Вспомним, что эта часть не относится
к ядру Vulkan, и так как для каждой ОС требуется свой код, то я решил разделить
на классы всю работу с окнами. Сам класс является интерфейсом и определён
следующим образом:

class VulkanWindowControl
{
protected:
    VulkanWindowControl() {};

    ~VulkanWindowControl() {};

public:

    virtual bool Init(uint Width, uint Height) = 0;

    virtual VkSurfaceKHR CreateSurface(VkInstance& inst) = 0;
};

Как вы можете заметить, этот класс крайне прост. У него нет никаких свойств.
Так как его конструктор и деструктор имеют модификатор доступа protected,
то нельзя создать экземпляры этого класса напрямую. Есть два публичных
метода. Один для инициализации объекта, и второй для создания поверхности Vulkan.
Таким образом для каждой ОС мы вольны в своих действиях, главное — это вернуть
объект VkSurfaceKHR. Таким образом, мы можем инициализировать этот класс перед
созданием VulkanCoreObject, но нам требуется инициализировать
VulkanCoreObject до вызова CreateSurface(). Не волнуйтесь, мы к этому ещё
вернемся при разборе функции main().

Реализаций класса VulkanWindowControl всего две: XCBControl для Linux и
Win32Control для Windows. Сначала мы рассмотрим версию для Linux.

class XCBControl : public VulkanWindowControl
{
public:
    XCBControl();

    ~XCBControl();

    virtual bool Init(uint Width, uint Height);

    virtual VkSurfaceKHR CreateSurface(VkInstance& inst);

 private:
    xcb_connection_t* m_pXCBConn;
    xcb_screen_t* m_pXCBScreen;
    xcb_window_t m_xcbWindow;
};

Самая популярная оконная система на Linux — это, конечно же, XWindow. Она
работает в клиент — серверной архитектуре. Сервер управляет экраном, клавиатурой
и мышью. Клиентами являются приложения, которые хотят что-то вывести на экран.
Они подключаются к серверу по протоколу X11 и отправляют запросы на создание
окна, управление клавиатурой / мышью и прочее. Самыми часто встречаемыми
реализациями протокола X11 являются Xlib и XCB, и они обе поддерживаются Vulkan.
XCB более современная, поэтому мы будем
использовать её под Linux. XCBControl реализует класс VulkanWindowControl
используя вызовы XCB. Напомню, что целью всего этого является создание окна ОС
и подсоединение его к поверхности Vulkan. В результате Vulkan должен быть
способен рендерить в это окно. Давайте начнем с создания окна:

void XCBControl::Init(uint Width, uint Height)
{
    m_pXCBConn = xcb_connect(NULL, NULL);

    int error = xcb_connection_has_error(m_pXCBConn);

    if  (error) {
        printf("Error opening xcb connection error %dn", error);
        assert(0);
    }

    printf("XCB connection openedn");

Первое что нам потребуется сделать — это подключиться к серверу XWindow. Я
уверен что вы используете графический режим, поэтому сервер уже запущен в
фоне. xcb_connect() открывает подключение к серверу. Она принимает два
параметра: название сервера и указатель на желаемый номер экрана (его для
нас заполнит библиотека XCB). XWindow очень гибок в настройке. Например, он
позволяет запустить сервер на одной машине, а клиента на другой. А можно
запустить сразу несколько серверов на одной машине. Для подключения к удаленному
серверу потребуется его IP и номер экрана в специальном формате строки. А для
запуска локально достаточно передать NULL в оба параметра.

Мы сохраняем в классе указатель на подключение, которое возвращает
xcb_connect(). Функция всегда что-то возвращает, поэтому мы обязательно
проверяем наличие ошибок с помощью функции xcb_connectionn_has_error() как
показано выше.

    const xcb_setup_t *pSetup = xcb_get_setup(m_pXCBConn);

    xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup);

    m_pXCBScreen = iter.data;

    printf("XCB screen %pn", m_pXCBScreen);

Сервер XWindow может управлять несколькими мониторами и запускать несколько
экранов на каждом из них. Как раз на экране и запускаются приложения. Он имеет
ширину, высоту, грубину цвета и прочие характеристики. Мы хотим получить доступ
к текущему экрану, для чего нам потребуются два действия. Первое — это
использовать функцию xcb_get_setup() для доступа к структуре xcb_setup_t
с данными о соединении. В ней содержится большое количество информации о
сервере. Среди прочего там есть список экранов. Для доступа к этому списку мы
создаем итератор с помощью функции xcb_setup_roots_iterator(). В сложных
приложениях тут должен быть код, который пробегает по списку экранов в поиске
подходящего для приложения. А мы просто возьмём первый в списке. Экран можно
получить следующим образом:

    m_xcbWindow = xcb_generate_id(m_pXCBConn);

Теперь мы готовы к созданию окна. Первым шагом мы генерируем XID — беззнаковое
целое число, идентификатор всех ресурсов XWindow. Когда клиент подсоединяется к
серверу, последний выделяет подмножество XID для этого клиента. Когда клиент
хочет создать некоторый объект на сервере, он выделяет себе XID из разрешенного
ему промежутка. Последующие вызовы функций могут использовать полученный XID.
Это довольно интересный подход. Обычно сервер говорит «эй, вот тебе новый объект и
его номер XYZ». А здесь клиент говорит «слушай, сервер, я хочу создать новый
объект и вот его номер». xcb_generate_id() генерирует XID для окна, а мы
сохраняем его в свойство m_xcbWindow.

    xcb_create_window(m_pXCBConn,             // соединение с сервером XWindow
      XCB_COPY_FROM_PARENT,                   // глубина цвета
      m_xcbWindow,                            // XID нового окна
      m_pXCBScreen->root,                     // родительское окно
      0,                                      // координата X
      0,                                      // координата Y
      Width,                                  // ширина окна
      Height,                                 // высота окна
      0,                                      // ширина границы
      XCB_WINDOW_CLASS_INPUT_OUTPUT,          // класс окна, не смог найти документации
      m_pXCBScreen->root_visual,              // определяет отображения цвета
      0,
      0);

Функция xcb_create_window(), которая создает окно, принимает, ни много ни
мало, 13 параметров. Я добавил немного комментариев к ним, большая часть из
них очевидны. Больше мы к этому не возвращаемся. Поищите информацию в интернете,
если оно вам надо.

    xcb_map_window(m_pXCBConn, m_xcbWindow);
    xcb_flush (m_pXCBConn);
}

Чтобы сделать окно видимым мы должны его отобразить и заставить сервер вывести
буфер на экран. Вот этим два вызова выше и занимаются.

VkSurfaceKHR XCBControl::CreateSurface(VkInstance& inst)
{
    VkXcbSurfaceCreateInfoKHR surfaceCreateInfo = {};
    surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
    surfaceCreateInfo.connection = m_pXCBConn;
    surfaceCreateInfo.window = m_xcbWindow;

    VkSurfaceKHR surface;

    VkResult res = vkCreateXcbSurfaceKHR(inst, &surfaceCreateInfo, NULL, &surface);
    CHECK_VULKAN_ERROR("vkCreateXcbSurfaceKHR error %dn", res);

    return surface;
}

Последняя функция из класса XCBControl, на которую мы обратим внимание, — это
CreateSurface(). По сути это декоратор функции Vulkan vkCreateXcbSurfaceKHR().
Мы заполняем структуру VkXcbSurfaceCreateInfoKHR указателем на соединение
с сервером XWindow и созданным ранее окном. В ответ мы получим поверхность Vulkan,
которую сразу же передаем назад вызвавшей функции.

Давайте теперь рассмотрим аналогичный класс для Windows:

class Win32Control : public VulkanWindowControl
{
public:
    Win32Control(const char* pAppName);

    ~Win32Control();

    virtual void Init(uint Width, uint Height);

    virtual VkSurfaceKHR CreateSurface(VkInstance& inst);

 private:

    HINSTANCE   m_hinstance;
    HWND        m_hwnd;
    std::wstring m_appName;
};

Как вы видите, интерфейс для обеих ОС очень похож. По факту, Init() и
CreateSurface() идентичны так как они виртуальные функции. Мы также
добавили приватные свойства для записи специфических для Windows данных —
HINSTANE и HWND.

Win32Control::Win32Control(const char* pAppName)
{
    m_hinstance = GetModuleHandle(NULL);;
    assert(m_hinstance);
    m_hwnd = 0;
    **std::string s(pAppName)**;
    m_appName = **std::wstring(s.begin(), s.end())**;
}

Выше показан конструктор класса Win32Control, который я привожу только для
того, что бы вы знали как преобразовывается название окна из массива букв в
std::wstring. Мы делаем это для функции CreateWindowEx(), которой название
окна требуется в виде типа LPCTSTR. Стандартный класс wstring нам в этом
пригодится.

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

void Win32Control::Init(uint Width, uint Height)
{
    WNDCLASSEX wndcls = {};

    wndcls.cbSize = sizeof(wndcls);
    wndcls.lpfnWndProc = WindowProc;
    wndcls.hInstance = m_hinstance;
    wndcls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndcls.lpszClassName = L"ogldev";

    if (!RegisterClassEx(&wndcls)) {
        DWORD error = GetLastError();
        OGLDEV_ERROR("RegisterClassEx error %d", error);
    }

    m_hwnd = CreateWindowEx(0,
                            L"ogldev",                        // название
                            m_appName.c_str(),
                            WS_OVERLAPPEDWINDOW | WS_VISIBLE, // стиль окна
                            100, 100,                         // начальное положение
                            Width,
                            Height,
                            NULL,
                            NULL,
                            m_hinstance,
                            NULL);

    if (m_hwnd == 0) {
        DWORD error = GetLastError();
        OGLDEV_ERROR("CreateWindowEx error %d", error);
    }

    ShowWindow(m_hwnd, SW_SHOW);
}

Код выше, который создает окно, я нашел на MSDN, поэтому я не буду сильно
вдаваться в детали. Мы регистрируем окно через RegisterClassEx(). Окно будет
иметь связь с функцией WindowProc() — обработчиком событий. Прямо сейчас мы
используем стандартный обработчик, но в следующих уроках мы добавим больше
деталей. Окно создается функцией CreateWindowEx() и, наконец, отображается
через ShowWindow().

VkSurfaceKHR Win32Control::CreateSurface(VkInstance& inst)
{
    VkWin32SurfaceCreateInfoKHR surfaceCreateInfo = {};
    surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
    surfaceCreateInfo.hinstance = m_hinstance;
    surfaceCreateInfo.hwnd = m_hwnd;

    VkSurfaceKHR surface;

    VkResult res = vkCreateWin32SurfaceKHR(inst, &surfaceCreateInfo, NULL, &surface);
    CHECK_VULKAN_ERROR("vkCreateXcbSurfaceKHR error %dn", res);

    return surface;
}

CreateSurface() тоже очень похожа на аналог для Linux. Параметр
surfaceCreateInfo здесь представляет собой экземпляр (и, конечно же,
обработчики windows имеют другие типы).

int main(int argc, char** argv)
{
    VulkanWindowControl* pWindowControl = NULL;
#ifdef WIN32
    pWindowControl = new Win32Control(pAppName);
#else
    pWindowControl = new XCBControl();
#endif
    pWindowControl->Init(WINDOW_WIDTH, WINDOW_HEIGHT);

    OgldevVulkanCore core("tutorial 50");
    core.Init(pWindowControl);

    return 0;
}

Наконец мы подошли к связыванию всего кода в функции main(). Если есть желание,
то вы можете начать отсюда и постепенно добавлять блоки кода, проверяя какие
значения будет для них возвращать Vulkan. Всё в этой функции уже было подробно
рассмотрено. Мы выделяем память для реализации класса VulkanWindowControl
(для Linux или Windows), а затем создает и инициализируем объект
OgldevVulkanCore. Теперь у нас есть связанная с окном ОС поверхность Vulkan,
экземпляр Vulkan, устройство и база данных со всеми физическими устройствами.

Надеюсь что вам этот урок пригодился. Кстати, вместе с ним полагается футболка
с надписью «Я написал тону кода на Vulkan, а получил пустое окно». Действительно,
мы проделали большой путь, а ничего так и не отрендерели. Но не отчаивайтесь.
У нас есть базовая структура с несколькими объектами ядра Vulkan. В следующем
уроке мы продолжим работать над ним, так что не переключайтесь.

Понравилась статья? Поделить с друзьями:
  • Wacom intuos 3 drivers windows 10
  • Vulkan run time libraries что это за программа в windows 10
  • Wacom intuos 2 xd 0608 u драйвер windows 10
  • Vulkan rt что это за папка в windows 10
  • Wacom inkspace app для windows скачать