Поддержка vulkan в видеокартах что это
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 нет сильных проверок входящих данных на правильность. Ему сказали что-то сделать — он сделает. Даже если это приведёт к ошибке приложения, драйвера или видеокарты. Это сделали ради производительности. Тем не менее, можно без проблем подключить проверочные слои, а также расширения к экземпляру и/или устройству, если это необходимо.
С выпуском Windows 95 и модели защищенной памяти разработчики не имели такого же доступа к ресурсам, как в MS-DOS. DirectX впервые появился в виде набора конкретных API для разработки мультимедийных приложений, таких как игры.
Термин «DirectX» начинается со слова «Direct», ссылаясь на прямой доступ к ресурсам системы. Некоторые примеры включают Direct3D для графики и DirectSound для аудио. Часть «Х» относится к API в общей коллекции; таким образом объединив все API-интерфейсы под названием DirectX. Вышеупомянутое название также вдохновило название популярной видеоигр компании Xbox.
Вышеприведенное иллюстрирует тесную связь между DirectX и консолью Microsoft. Его последняя версия, DirectX 12, имеет большие улучшения. Тем не менее он поддерживается только Windows 10 и новейшей игровой консолью компании Xbox One.
Direct3D является жемчужиной DirectX и полезен для создания 3D-объектов на нашем экране. Он также позволяет просматривать игры в полноэкранном режиме, а также использовать аппаратные ускорители. Последний метод позволяет реализовать некоторые функции более эффективно, чем они работают в программном обеспечении. Это может быть достигнуто за счет более эффективного использования аппаратного обеспечения нашего компьютера. В этом случае это будет наша видеокарта.
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.
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.
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.
Очереди (queue) и семейства очередей (queue family)
Устройство может (или не может) делать следующие 4 вещи: рисовать графику, производить разные вычисления, копировать данные, а также работать с разреженной памятью (sparse memory management). Эти возможности представлены в виде семейств очередей: каждое семейство поддерживает определённые (может быть все сразу) возможности. И если идентичные семейства были разделены, Vulkan всё равно представит их как одно семейство, чтобы мы не так сильно страдали с кодом и выбирали нужное семейство.
После того, как вы выбрали нужное (или нужные) семейства, из них можно получить очереди. Очереди — это место, куда будут поступать команды для устройства (потом устройство их будет брать из очередей и выполнять). Очередей и семейств, кстати, не сильно много. У NVIDIA обычно 1 семейство со всеми возможностями на 16 очередей. После того, как вы закончили с подбором семейств и количеством очередей, можно создавать устройство.
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.
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.
Управление памятью и ресурсы
Память в Vulkan распределяется хостом и только хостом (за исключением swapchain). Если изображение (или другие данные) нужно поместить в устройство — выделяется память. Сначала создаётся ресурс определённых размеров, затем запрашивается его требования к памяти, выделяется для него память, затем ресурс ассоциируется с участком этой памяти и только потом можно копировать в этот ресурс необходимые данные. Также, есть память, которая может быть непосредственно изменена с хоста (host visible), есть локальная память устройства (память видеокарты, например) ну и также другие виды памяти, по своему влияющие на скорость доступа к ним.
В Vulkan можно также написать своё распределение памяти хоста, настроив Callback функции. Но учтите, что требования к памяти, это не только её размер, но и выравнивание (alignment).
Сами ресурсы бывают двух видов: буферы (buffers) и изображения (images). И те и другие разделяются по назначению, но если буфер — просто коллекция различных данных (вершинный, индексный или буфер констант), то изображение всегда имеет свой формат.
Выделяйте участок памяти, в который можете поместить сразу несколько ресурсов. Количество выделений ограничено, и вам может не хватить. Зато количество ассоциаций не ограничено.
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.
Вулкан AMD
В 2015 году Kronos Group разработала свой собственный API. Vulkan — это низкоуровневый API, используемый для разработки графически требующих приложений. Его первая стабильная версия дебютировала в августе 2016 года.
Следует четко указать, что «низкий уровень» не относится к качеству. Вместо этого этот термин описывает способность Вулкана работать на аппаратном уровне.
Хронос окружает себя одними из самых больших имен в ИТ-индустрии. Некоторые из них — Google, Intel, Sony, Nvidia и AMD. Последние два дали API, свести к минимуму время разработки Vulkan.
OpenGL — популярный API среди графических дизайнеров. Фактически он был разработан Хроносом, и он также включает в себя многие характеристики Вулкана. Однако его прием игровыми дизайнерами был непредвиденным.
Одним из самых сильных активов Vulkan является тот факт, что он с открытым исходным кодом. Кроме того, совместимость Vulkan с несколькими платформами вместе с общей производительностью — это два дополнительных актива, которые делают его более прибыльным, чем DirectX.
Здесь вы можете найти полный список с именами, которые содержат Khronos. Мантия обеспечила основную базу, на которой был разработан Вулкан. Наконец Vulkan в настоящее время находится в версии 1.1.
Совместимость с несколькими платформами
Что касается платформ, большое преимущество 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 Educational Resources
Начало работы и основные понятия
Vulkan разделяет два понятия — это устройство (device) и хост (host). Устройство будет выполнять все команды, отправленные ему, а хост будет их отправлять. Фактически, наше приложение и есть хост — у Vulkan такая терминология.
Для работы с Vulkan нам понадобится хэндлы на его экземпляр (instance), и может быть даже не один, а также на устройство (device), опять же, не всегда может хватать одного.
Vulkan может быть легко загружен динамически. В SDK (разработали LunarG), если был объявлен макрос VK_NO_PROTOTYPES и загружать библиотеку Vulkan своими руками (не линковщиком, а определёнными средствами в коде), то прежде всего нужна будет функция vkGetInstanceProcAddr, с помощью которой можно узнать адреса основных функций Vulkan — те которые работают без экземпляра, включая функцию его создания, и функции, которые работают с экземпляром, включая функцию его разрушения и функцию создания устройства. После создания устройства можно получить функции, которые работают с ним (а также его дочерними хэндлами) через vkGetDeviceProcAddr.
Интересный факт: в Vulkan всегда нужно заполнить определённую структуру данными, чтобы создать какой-либо объект. И всё в Vulkan работает примерно таким образом: заранее подготовил — можно использовать часто и с высокой производительностью. В информацию об экземпляре можно также поместить информацию о вашем приложении, версии движка, версии используемого API и другую информацию.
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. О них мы поговорим в следующей главе.
Как уже было сказано, 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 позволит убедиться, что программа работает успешно. При закрытии пустого окна программа должна завершиться успешным кодом возврата ( 0 ). У вас должен получиться готовый makefile, похожий на приведенный ниже:
Вы можете использовать эту структуру каталогов в качестве шаблона для проектов Vulkan. Для этого скопируйте ее, переименуйте, например, в HelloTriangle и удалите весь код из main.cpp .
Итак, теперь вы готовы к настоящему приключению.
3. Настройка окружения
Расширения (extensions)
Развитие и будущее
Было бы упущением, не говоря уже о ходе разработки двух API. С одной стороны, у нас есть ветеран DirectX с более чем 20-летним развитием. С другой стороны, Вулкану едва будет 3 года с 2015 года. Тот факт, что Vulkan является открытым исходным кодом, может немного повлиять на его темпы роста. Конечно игроки Khronos, похоже серьезно относятся к разработке API, так как уровни улучшения впечатляют.
Все мы можем создавать новые инструменты и модификации и предоставлять их сообществу, помогая API расти быстрее. Наконец следует упомянуть, что DirectX не имеет вышеуказанной функции. Несмотря на свои годы развития, около 40 игр в настоящее время используют Vulkan, занимая большую часть рынка. Некоторые из них — Quake, Roblox, Talos и Dota 2. Что касается производительности, Vulkan приближается к DirectX, и в некоторых случаях он превосходит его. Самые захватывающие примеры работы Вулкана — игра Doom.
Vulkan расширил свою поддержку названий AAA, таких как Wolfenstein II, не пренебрегая названиями VR, такими как Doom VFR и Serious Sam VR. Здесь вы можете увидеть подробный список поддерживаемых игр. Хотя здесь вы найдете игры с поддержкой DirectX 12.
Оба API значительно улучшили производительность. Лучшее использование нескольких графических карт и меньшее использование ЦП повысит общую производительность наших систем. По слухам, новые видеокарты от Nvidia будут выпущены к концу лета и значительно превзойдут сегодняшние высокопроизводительные графические карты. В целом, общее состояние вещей кажется довольно гибким. В любом случае, изменения в разработке игр скоро будут у нас, и оба API несомненно будут играть важную роль.
2. Краткий обзор
Команды, их исполнение и синхронизация
Командный буфер бывает двух видов: первичный и вторичный. Первичный отправляется прямо в очередь. Вторичный же не может быть отправлен — он запускается в первичном. Записываются команды в таком же порядке, в каком были вызваны функции. В очередь они поступают в таком же порядке. А вот исполнятся они могут почти в «хаотичном» порядке. Чтобы не было полного хаоса в приложении разработчики Vulkan предусмотрели средства синхронизации.
Теперь, самое важное: хост не ожидает завершения исполнения команд и командных буферов. По крайней мере до того момента, пока не укажете это явным способом. После отправления командных буферов в очередь управление сразу возвращается приложению.
Есть 4 примитива синхронизации: забор (fence), семафор (semaphore), событие (event) и барьер (barrier).
Забор самый простой метод синхронизации — он позволяет хосту ожидать выполнение определённых вещей. Например, завершения выполнения командного буфера. Но используется забор редко.
Семафор — способ синхронизации внутри устройства. Никак нельзя посмотреть его состояние или подождать его на хосте, нельзя также ждать его внутри командного буфера, но можем указать, какой семафор должен подать сигнал при завершении исполнения всех команд буфера, и какой семафор ждать перед тем, как начать выполнение команд в буфере. Только ждать будет не весь буфер, а его определённая стадия.
Как уже было сказано, не обязательно команды в очереди будут исполнятся по порядку. Если быть точнее, то последующие команды не будут ждать завершения предыдущих. Они могут выполнятся параллельно, или исполнение предыдущей команды может завершиться намного позже последующих. И это вполне нормально. Но некоторые команды зависят от исполнения других. Вы можете разделить их на два берега: «до» и «после», и также указать, какие стадии берега «до» должны обязательно выполнится (т.е. команды могут завершиться не полностью или не все), прежде чем начнут выполняться указанные стадии команд берега «после». Например, отрисовка изображения может приостановиться, чтобы сделать определённые вещи, а потом снова продолжить делать рисовать. Также может быть и цепочка зависимостей, но не будем уходить глубоко в леса Сибири Vulkan.
События — элемент «тонкой» настройки. Подать сигнал можно как с хоста, так и с устройства, ждать можно также и на устройстве, и на хосте. Событие определяет зависимость двух сетов команд (до и после) в командном буфере. И для события есть также специальная псевдо-стадия, которая позволяет ждать хост.
Барьер опять может быть использован только в устройстве, а ещё точнее — в командном буфере, объявляя зависимости первого и второго сета команд. Также можно дополнительно указать барьеры памяти, которые бывают трёх видов: глобальный барьер, барьер буфера и барьер изображения. Они не дадут ненароком прочитать данные, которые в данный момент записываются и/или наоборот, в зависимости от указанных параметров.
Предпосылки возникновения Vulkan
Как и предыдущие графические API, Vulkan задуман как кроссплатформенная абстракция над GPU. Основная проблема большинства таких API заключается в том, что в период их разработки использовалось графическое оборудование, ограниченное фиксированным функционалом. Разработчики должны были предоставить данные о вершинах в стандартном формате и в плане освещения и теней полностью зависели от производителей графических процессоров.
По мере развития архитектуры видеокарт в ней стало появляться все больше программируемых функций. Все новые функции необходимо было каким-то образом объединить с существующими API. Это привело к неидеальным абстракциям и множеству гипотез со стороны графического драйвера о том, как воплотить замысел программиста в современных графических архитектурах. Поэтому для повышения производительности в играх выпускается большое количество обновлений драйверов. Из-за сложности таких драйверов среди поставщиков часто возникают расхождения, например, в синтаксисе, принятом для шейдеров. Помимо этого, в последнее десятилетие также наблюдался приток мобильных устройств с мощным графическим оборудованием. Архитектуры этих мобильных GPU могут сильно отличаться в зависимости от требований по размерам и энергопотреблению. Одним из таких примеров является тайловый рендеринг, который может дать большую производительность за счет лучшего контроля над функционалом. Еще одним ограничением, связанным с возрастом API, является ограниченная поддержка многопоточности, что может привести к появлению узкого места со стороны ЦП.
Vulkan помогает решить эти проблемы, поскольку изначально создан для современных графических архитектур. Это снижает потери на стороне драйвера за счет того, что разработчики могут четко описать свои цели с помощью подробного API. Vulkan позволяет параллельно создавать и отсылать команды в нескольких потоках. Также снижаются расхождения компиляции шейдеров за счет перехода на стандартизованный формат байтового кода и использования одного компилятора. И наконец, Vulkan реализует главную возможность современных видеокарт, объединяя графические и вычислительные возможности в едином API.
Предварительная информация о API
Прежде чем мы начнем говорить о DirectX и Vulkan, нам нужно сначала понять, что такое API. Аббревиатура означает «Интерфейс прикладного программирования».
Интерфейс предназначен для обеспечения связи между двумя объектами. Одним из примеров является графический интерфейс Windows, который играет роль посредника между операционной системой и пользователем.
Интерфейс обеспечивает удобную среду. С помощью этой среды мы используем операционную систему, не зная, как ее функции реализованы в фоновом режиме. Интерфейс прикладного программирования (API) заполняет роль посредника. Однако на этот раз пользователь может быть ПК или другой программой и не обязательно человеком. API-интерфейсы гораздо более распространены, чем можно было бы подумать, предлагая программистам необходимые инструменты для создания своего программного обеспечения.
Ориентировочный пример, в котором мы используем API, — это когда мы автоматически регистрируемся в новом социальном средстве или онлайн-сервисе, используя наши ранее существующие учетные записи из Facebook или Google (вместо создания новой учетной записи вручную).
В таких случаях веб-сайт использует API, через который он связывается с конкретной услугой (например, Facebook или Twitter), чтобы собирать нашу личную информацию (имя (имена), адрес электронной почты, контактные номера и т. д.) Для создания нашего нового аккаунта.
Тем не менее существует множество других применений API для всех видов взаимодействия между приложениями и компьютерами, такими как системы баз данных, операционные системы и библиотеки программного обеспечения.
В таких случаях использование API-интерфейсов применимо к нашему компьютерному оборудованию и в частности, к нашей графической карте (видеокартам).
DirectX и Vulkan фактически улучшают связь между приложением (игрой) и графическим процессором, чтобы повысить производительность графики.
Поддержка нескольких графических карт
Здесь Khronos Group столкнулась со значительным разрывом между двумя API-интерфейсами с поддержкой использования нескольких графических карт (использование явного многоканального GPU). Мы можем использовать разные карты, если их чипы имеют аналогичную архитектуру и используют один и тот же драйвер. Это позволит различным картам обрабатывать другую часть экрана.
Microsoft здесь еще на один шаг впереди, позволяя использовать несколько графических карт даже у другого производителя, что часто бывает, поскольку большинство систем имеют независимый и интегрированный графический процессор. Важно подчеркнуть тот факт, что эти реализации отличаются от возможностей SLI и Crossfire от Nvidia и AMD, которые реализованы с помощью драйверов, и в частности, в случае SLI требуют идентичные графические карты.
Проход отрисовки, графический конвейер и фреймбуфер
Итак, получаем следующую матрёшку:
Для того, чтобы можно было использовать команды отрисовки, нужен графический конвейер. В графическом конвейере необходимо указать проход отрисовки (Render Pass), который содержит информацию о подпроходах (subpass), их зависимостей друг от друга и прикреплениях (attachment). Прикрепление — информация о изображении, которое будет использоваться во framebuffer'ах. Framebuffer создаётся специально для определённого прохода отрисовки. Чтобы начать проход, нужно указать как сам проход (а также, если нужно, подпроход), так и framebuffer. После начала прохода можно рисовать. Можно также переключаться между подпроходами. После того, как рисование завершено, можно завершить проход.
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
An updated Vulkan Ray Tracing Tutorial using the final Vulkan Ray Tracing extensions
Read about how the 2020.6 release of the NVIDIA Nsight Graphics tool supports Vulkan Ray Tracing
Шейдеры
Шейдеры — это небольшие программы, которые запускаются на наших видеокартах. Они отвечают за определенные функции различных объектов в 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 NVIDIA Presentations
We'll provide useful examples and resources to make a basic integration of Vulkan ray tracing and traversal in an existing Vulkan raster sample. With the help of an existing online tutorial, we'll review the main steps of a simple ray tracer. From the location of SDKs and drivers to the debugging tools such as Nsight to set up the appropriate environment, we'll lay the foundation for the step-by-step addition and activation of ray tracing. We'll also cover specific topics related to ray tracing, such as any hit shader, intersection shader, reflections, animations, shader record, multiple hot shaders, callable shaders, and ray query.
We'll cover NVIDIA’s best practices for DirectX12 and Vulkan API usage. We'll describe how to make the most out of these low-level APIs across our range of GPUs and explain how to avoid common performance pitfalls while achieving optimal smooth frame rates.
NVIDIA GPUs are incredibly powerful and with the arrival of DXR and Vulkan Ray Tracing, it's now possible to do Ray Tracing at interactive framerates. Even so, it can be a challenge to ensure that you are fully utilizing the GPU efficiently. In this session, you'll learn about the available tools and features available to developers that can help you take advantage of this incredible innovation to improve the graphics in your game.
Большинство из нас, геймеров, слышали о Microsoft DirectX. Однако, немногие из нас знакомы с его утилитами и как они влияют на видеоигры. В настоящее время, фактически, приобретя конкурента в форме Vulkan, вещи относящиеся к двум API, как правило, становятся еще более сложными. В этом руководстве мы увидим, что такое API, Vulkan и DirectX, и мы покажим метод, с помощью которого они влияют на наши игры.
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.
Устройство
Vulkan разделяет понятия физического устройства и логического. Физическим устройством может быть ваша видеокарта (и не одна) или процессор, поддерживающий графику. Логическое устройство создаётся на основе физического: собирается информацию о физических устройствах, выбирается нужное, подготавливается другая необходимая информация и создаётся устройство. Может быть несколько логических устройств на основе одного физического, но вот объединять для единой работы физические устройства (пока?) нельзя.
Итак, что же за информацию мы собираем? Это, конечно же, поддерживаемые форматы, память, возможности и, конечно же, семейства очередей.
Как они влияют на игры
До этого момента мы рассмотрели некоторые основы, касающиеся API, Microsoft и Khronos. Но как они влияют на игры?
Эти два API значительно улучшили производительность. До сих пор DirectX, по-видимому, обеспечивал лучшую производительность, чем Vulcan, что на самом деле он не так далеко позади.
Microsoft утверждает, что DirectX 12 снижает потребление на 50% при использовании DirectX 11. С другой стороны, Vulkan также демонстрирует лучшую гибкость, чем его предшественник. Говоря о предшественниках, DirectX 11 и OpenGL были созданы с учетом одноядерных процессоров; что означает, что они не были точно настроены с использованием новых, многоядерных процессоров.
В результате одно ядро управляет большинством различных процессов, в то время как остальные работают с низкой скоростью, а иногда и вовсе отключены. Оба API (DirectX 12 и Vulkan) поддерживают процессоры с несколькими ядрами и потоками, чтобы максимально эффективно использовать свои возможности. Более того, они передают большую часть требуемых задач от процессора к графической карте (видеокартам), предлагая более сбалансированный опыт.
Взаимодействие между этими двумя элементами может существенно повлиять на будущие сборки ПК. Графические карты в значительной степени важнее, чем процессоры, когда дело доходит до игр. С дальнейшим развитием игровых API маловероятно, что процессоры могут стать еще менее важными, когда дело доходит до него. Таким образом, даже с простым процессором мы можем получить хорошую производительность без каких-либо узких мест.
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.
Как вы относитесь к двум API?
Вы уже узнали всю информацию, которую мы предоставили на Vulkan и DirectX? Со временем их соперничество усиливается, какой из двух API вы считаете более полезным для развития игры? Мы с нетерпением ждем ваших комментариев.
Я работаю техническим переводчиком ижевской IT-компании CG Tribe, которая предложила мне внести свой вклад в сообщество и начать публиковать переводы интересных статей и руководств.
- Изображения
- Image view и image sampler
- Комбинированный image sampler
9. Загрузка моделей
10. Создание мип-карт
FAQ
Политика конфиденциальности
1. Вступление
Как нарисовать треугольник?
Мы кратко рассмотрим шаги, необходимые для отрисовки треугольника. Это позволит вам получить общее представление о процессе. Подробное описание каждой концепции будет дано в следующих главах.
Шаг 1 — Экземпляр (instance) и физические устройства
Работа с Vulkan начинается с настройки Vulkan API через VkInstance (экземпляр). Экземпляр создается с помощью описания вашей программы и всех расширений, которые вы хотите использовать. После создания экземпляра вы можете запросить, какое оборудование поддерживает Vulkan, и выбрать один или несколько VkPhysicalDevices для выполнения операций. Вы можете сделать запрос по таким параметрам, как размер VRAM и возможности устройств, чтобы выбрать желаемые устройства, если вы предпочитаете использовать специализированные видеокарты.
Шаг 2 — Логическое устройство и семейства очередей
После того, как вы выберете подходящее hardware устройство для использования, вам необходимо создать VkDevice (логическое устройство), где вы более подробно опишете, какие возможности (VkPhysicalDeviceFeatures) будете использовать, например, рендеринг в несколько viewport-ов (multi viewport rendering) и 64-битные числа с плавающей точкой. Вам также необходимо установить, какие семейства очередей вы бы хотели использовать. Многие операции, совершаемые с помощью Vulkan, например, команды рисования и операции в памяти, выполняются асинхронно после отправки в VkQueue. Очереди выделяются из семейства очередей, где каждое семейство поддерживает определенный набор операций. Например, для операций с графикой, вычислительных операций и передачи данных памяти могут существовать отдельные семейства очередей. Кроме того их доступность может использоваться в качестве ключевого параметра при выборе физического устройства. Некоторые устройства с поддержкой Vulkan не предлагают никаких графических возможностей, однако, все современные видеокарты с поддержкой Vulkan, как правило, поддерживают все необходимые нам операции с очередями.
Шаг 3 — Window surface и цепочки показа (swap chain)
Если вас интересует не только внеэкранный рендеринг, вам необходимо создать окно для отображения отрендеренных изображений. Окна можно создать с помощью API исходной платформы или библиотек, таких как GLFW и SDL. В руководстве мы будем использовать GLFW, подробнее о которой мы расскажем в следующей главе.
Нам необходимо еще два компонента, чтобы рендерить в окно приложения: window surface ( VkSurfaceKHR ) и цепочка показа ( VkSwapchainKHR ). Обратите внимание на постфикс KHR , который обозначает, что эти объекты являются частью расширения Vulkan. Vulkan API полностью независим от платформы, поэтому нам необходимо использовать стандартизованное расширение WSI (Window System Integration) для взаимодействия с менеджером окон. Surface – это кроссплатформенная абстракция окон для визуализации, которая, как правило, создается с помощью ссылки на собственный дескриптор окна, например HWND в Windows. К счастью, библиотека GLFW имеет встроенную функцию для работы со специфичными деталями платформы.
Цепочка показа — это набор целей рендеринга. Ее задача — обеспечивать, чтобы изображение, которое рендерится в текущий момент, отличалось от отображаемого на экране. Это позволяет отслеживать, чтобы отображались только готовые изображения. Каждый раз, когда нам нужно создать кадр, мы должны сделать запрос, чтобы цепочка показа предоставила нам изображение для рендеринга. После того, как кадр создан, изображение возвращается в цепочку показа, чтобы в какой-то момент отобразиться на экране. Количество целей рендеринга и условий для отображения готовых изображений на экране зависит от текущего режима. Среди таких режимов можно выделить двойную буферизацию (vsync) и тройную буферизацию. Мы рассмотрим их в главе, посвященной созданию цепочки показа.
Некоторые платформы позволяют рендерить непосредственно на экран через расширения VK_KHR_display и VK_KHR_display_swapchain без взаимодействия с каким-либо менеджером окон. Это позволяет создать surface, которая представляет собой весь экран и может использоваться, например, для реализации вашего собственного менеджера окон.
Шаг 4 — Image views и фреймбуферы
Чтобы рисовать в изображение (image), полученное из цепочки показа, мы должны обернуть его в VkImageView и VkFramebuffer. Image view ссылается на определенную часть используемого изображения, а фреймбуфер ссылается на image views, которые используются как буферы цвета, глубины и шаблонов (stencil). Поскольку в цепочке показа может быть множество разных изображений, мы заранее создадим image view и фреймбуфер для каждого из них и выберем необходимое изображение во время рисования.
Шаг 5 — Проходы рендера
Проходы рендера в Vulkan описывают тип изображений, используемых во время операций рендеринга, то, как они используются, и то, как необходимо обрабатывать их содержимое. Перед отрисовкой треугольника мы сообщим Vulkan, что мы хотим использовать одиночное изображение в качестве буфера цвета и что нам нужно очистить его перед рисованием. Если проход рендера описывает только тип изображений, используемых в качестве буферов, то VkFramebuffer фактически связывает определенные изображения с этими слотами.
Шаг 6 — Графический конвейер (pipeline)
Графический конвейер в Vulkan настраивается с помощью создания объекта VkPipeline. Он описывает конфигурируемое состояние видеокарты, например, размер viewport или операцию буфера глубины, а также программируемое состояние, используя объекты VkShaderModule. Объекты VkShaderModule создаются из байтового кода шейдера. Драйверу также необходимо указать, какие цели рендеринга будут использоваться в конвейере. Мы задаем их, ссылаясь на проход рендера.
Одна из наиболее отличительных особенностей Vulkan по сравнению с существующими API-интерфейсами заключается в том, что почти все системные настройки графического конвейера должны задаваться заранее. Это значит, что если вы хотите переключиться на другой шейдер или немного изменить vertex layout, вам необходимо полностью пересоздать графический конвейер. Поэтому вам придется заранее создать множество объектов VkPipeline для всех комбинаций, необходимых для операций рендеринга. Только некоторые базовые настройки, такие как размер viewport и цвет очистки, могут быть изменены динамически. Все состояния должны быть описаны явно. Так, например, не существует смешивания цветов (color blend state) по умолчанию.
К счастью, поскольку процесс больше напоминает опережающую компиляцию, вместо компиляции «на лету», у драйвера появляется больше возможностей для оптимизации, а производительность оказывается более предсказуемой, так как значительные изменения состояния, например, переключение на другой графический конвейер, указываются явно.
Шаг 7 — Пул команд и буферы команд
- Начать проход рендера
- Привязать графический конвейер
- Нарисовать 3 вершины
- Закончить проход рендера
Шаг 8 — Основной цикл
После того, как мы отправили команды рисования в буфер команд, основной цикл кажется достаточно простым. Сначала мы получаем изображение из цепочки показа с помощью vkAcquireNextImageKHR . Затем мы можем выбрать соответствующий буфер команд для этого изображения и запустить его с помощью vkQueueSubmit. В конце, мы возвращаем изображение в цепочку показа для вывода на экран с помощью vkQueuePresentKHR .
Операции, отправляемые в очереди, выполняются асинхронно. Поэтому мы должны использовать объекты синхронизации — семафоры —, чтобы обеспечить правильный порядок запуска. Необходимо настроить запуск буфера команд рисования таким образом, чтобы он осуществлялся только после того, как изображение будет извлечено из цепочки показа, в противном случае может возникнуть ситуация, когда мы начнем рендерить изображение, которое все еще считывается для отображения на экране. Вызов vkQueuePresentKHR , в свою очередь, должен дождаться завершения рендеринга, для которого мы будем использовать второй семафор. Он будет уведомлять об окончании отрисовки.
Этот краткий обзор позволяет получить общее представление о предстоящей работе по рисованию вашего первого треугольника. В реальности же шагов гораздо больше. Среди них выделение буферов вершин, создание uniform-буферов и загрузка изображений текстур — все это мы рассмотрим в следующих главах, а пока начнем с простого. Чем дальше мы будем двигаться, тем сложнее будет материал. Обратите внимание, что мы решили пойти хитрым путем, изначально встраивая координаты вершины в вершинный шейдер вместо использования буфера вершин. Такое решение связано с тем, что для управления буферами вершин сначала требуется знакомство с буферами команд.
Подведем краткий итог. Для отрисовки первого треугольника нам необходимо:
- Создать VkInstance
- Выбрать поддерживаемую видеокарту (VkPhysicalDevice)
- Создать VkDevice и VkQueue для рисования и отображения
- Создать окно, window surface и цепочку показа
- Обернуть изображения цепочки показа в VkImageView
- Создать проход рендера, который определяет цели рендеринга и их использование
- Создать фреймбуфер для прохода рендера
- Настроить графический конвейер
- Распределить и записать команды рисования в буфер для каждого изображения цепочки показа
- Отрисовать кадры в полученные изображения, отправляя правильный буфер команд и возвращая изображения обратно в цепочку показа
Концепты API
В заключение к текущей главе будет приведен краткий обзор того, как структурируются Vulkan API на более низком уровне.
Стандарт оформления кода
Все функции, перечисления и структуры Vulkan обозначены под заголовком vulkan.h , который включен в Vulkan SDK, разработанный LunarG. Установка SDK будет рассмотрена в следующей главе.
Функции имеют префикс vk в нижнем регистре, перечисляемые типы (enum) и структуры имеют префикс Vk , а перечисляемые значения имеют префикс VK_ . API активно использует структуры, чтобы предоставить параметры функциям. Например, создание объектов обычно происходит по следующей схеме:
Многие структуры в Vulkan требуют прямого указания типа структуры в члене sType . Член pNext может указывать на структуру расширения и в нашем руководстве всегда будет иметь тип nullptr . Функции, создающие или уничтожающие объект, будут иметь параметр VkAllocationCallbacks, который позволяет вам использовать собственный аллокатор памяти и который в руководстве также будет иметь тип nullptr .
Почти все функции возвращают VkResult, который является либо VK_SUCCESS , либо кодом ошибки. В спецификации указано, какие коды ошибок может возвратить каждая функция и что они обозначают.
Слои валидации
Как уже было сказано, Vulkan был разработан для обеспечения высокой производительности при низких нагрузках на драйвер. Поэтому он включает в себя очень ограниченные возможности автоматического обнаружения и исправления ошибок. Если вы сделаете ошибку, драйвер даст сбой или еще хуже, продолжит работать на вашей видеокарте, но выйдет из строя на других видеокартах.
Поскольку операции в Vulkan расписываются очень подробно, и слои валидации достаточно обширные, вам будет намного проще установить причину черного экрана по сравнению с OpenGL и Direct3D.
Остался всего один шаг, прежде чем мы начнем писать код, и это — настройка рабочей среды.
- Изображения
- Image view и image sampler
- Комбинированный image sampler
9. Загрузка моделей
10. Создание мип-карт
FAQ
Политика конфиденциальности
Шейдеры
Vulkan поддерживает 6 видов шейдеров: вершинный, контроль тесселяции, анализ тесселяции, геометрический, фрагментный (он же пиксельный) и вычислительный. Написать их можно на читаемом SPIR-V, а потом собрать в байт код, который в приложении мы запечатаем в модуль, т.е. создадим shader-модуль из этого кода. Конечно же, мы можем написать его на привычном GLSL и потом конвертировать в SPIR-V (транслятор уже есть). И, конечно же, вы можете написать свой транслятор и даже ассемблер — исходники и спецификации выложены в OpenSource, ничто не мешает написать вам сборщик для своего High Level SPIR-V. А может кто-то уже написал.
Байт код потом транслируется в команды, специфичные для каждой видеокарты, но делается это намного быстрее, чем из сырого GLSL кода. Подобная практика применяется и в DirectX — HLSL сначала преобразуются в байт код, и этот байт код может быть сохранён и потом использован, чтобы не компилировать шейдеры снова и снова.
2. Краткий обзор
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).
Оформление API и основы
Пожалуй, стоит начать с самого простого. Так как над Vulkan API работали Khronous Group, синтаксис весьма похож на OpenGL. Во всём API есть префикс vk. К примеру функции (порой даже с очень длинными названиями) выглядят так: vkDoSomething(. ), имена структур или хэндлов: VkSomething, а все константные выражения (макросы, макровызовы и элементы перечислений): VK_SOMETHING. Также, есть особый вид функций — команды, которым добавляется префикс Cmd: vkCmdJustDoIt(. ).
Писать на Vulkan можно как на C, так и на C++. Но второй вариант даст, конечно же, больше удобства. Есть (и будут создаваться) порты на другие языки. Кто-то уже сделал порт на Delphi, кто-то желает (зачем?) порт на Python.
Итак, как же создать рендер контекст? Никак. Здесь его нет. Вместо это придумали другие вещи с другими названиями, которые даже будут напоминать DirectX.
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 . Должно появиться следующее:
В этой папке есть и другие программы, которые могут оказаться полезными для разработки. Программы 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 .
Нажмите 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!
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 Phases → Link 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).
Конфигурация 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) вы увидите следующее:
Относительно недавно вышел новый Vulkan API — можно сказать, наследник OpenGL, хотя основан Vulkan на API Mantle от AMD.
Конечно, развитие и поддержка OpenGL не прекратилось, а также в свет вышел и DirectX 12. Что там с DirectX 12 и почему его поставили только на Windows 10 — я, к сожалению (а может и к счастью) не знаю. Но вот кроссплатформенный Vulkan меня заинтересовал. В чём же особенности Vulkan и как правильно его использовать я постараюсь рассказать вам в этой статье.
Итак, для чего нужен Vulkan и где он может быть использован? В играх и приложениях, работающие с графикой? Конечно! Вычислять, как это делает CUDA или OpenCL? Без проблем. Обязательно ли для этого нам нужно окно или дисплей? Конечно нет, вы можете сами указать, куда транслировать ваш результат или не транслировать его вообще. Но обо всём по порядку.
Конвейеры
Ниже показаны два конвейера Vulkan:
Т.е. в Vulkan есть два конвейера: графический и вычислительный. С помощью графического, мы, конечно же, можем рисовать, а вычислительный… вычислять. Что же ещё? Результаты вычислений могут потом отправится в графический конвейер. Так можно с лёгкостью сэкономить время на системе частиц, например.
Изменить порядок или изменить сами стадии конвейера нельзя. Исключение составляют программируемые стадии (шейдеры). Также можно отправлять разновидные данные в шейдеры (и не только) через дескрипторы.
Для конвейера можно создать кэш, который может быть использован (снова и снова) и в других конвейерах и даже после перезапуска приложения.
Конвейер необходимо настроить и ассоциировать с командным буфером, прежде чем последний будет использовать команды конвейера.
Так как конвейер, это фактически вся информация о том, как нужно работать с поступающими данными, то смена конвейера (а это информация о шейдерах, дескрипторах, растеризации и прочее) может дорого обойтись по времени. Поэтому разработчики предоставили возможность наследования конвейера. При смене конвейера на дочерний, родительский или между дочерними уйдёт меньше затрат производительности. Но это также и удобство для разработчиков, как например ООП.
1. Вступление
Окна и дисплеи
А закончит эту статью рассказ о WSI (Window System Integration) и цепочке переключений (swapchain). Для того, чтобы выводить что-либо в окно или на экран — нужны специальные расширения.
Для окон это базовое расширение плоскости и расширение плоскости, специфичной для каждой из систем (win32, xlib, xcb, android, mir, wayland). Для дисплея (т.е. FullScreen) нужно расширение display, но в целом и то и другое используют расширение swapchain.
Цепочка переключений не связана с графическим конвейером, поэтому простой Clear Screen выходит без настройки всего этого. Всё достаточно просто. Есть определённый движок показа (presentation engine), в котором есть очередь изображений. Одно изображение показывается на экран, другие дожидаются своей очереди. Количество изображений мы также можем указать. Есть также несколько режимов, которые позволят дождаться сигнала вертикальной синхронизации.
Метод работы примерно таков: мы запрашиваем индекс свободного изображения, вызываем командный буфер, который скопирует результат из Framebuffer в это изображение, и отправляем команду о отправки изображения в очередь. Звучит легко, но с учётом того, что потребуется синхронизация — всё чуточку сложнее, так как единственное, чего ожидает хост — это индекс изображения, которое вскоре будет доступно. Командный буфер ждёт сигнала семафора, который будет свидетельствовать о доступности изображения, и потом сам подать сигнал через семафор о том, что выполнение буфера, в следствии и копирование, завершено. И изображение действительно поступит в очередь по сигналу последнего семафора. Всего два семафора: о доступности изображения для копирования и о доступности изображения для показа (т.е. о завершении копирования).
Кстати говоря, я проверил, что один и тот же командный буфер действительно отправлялся в очередь несколько раз. Можете подумать сами, что это значит.
В этой статье я попытался рассказать о наиболее важных частях Vulkan API, но многое всё ещё не рассказано и это вы можете узнать сами. Стабильного вам FPS и приятного кодинга.
Виртуальная реальность
Необходимо сказать, что Vulkan является примером больших улучшений в области виртуальной реальности. Приложение VR должно отображать определенную 3D-сцену с двух разных точек зрения — по одному для каждого глаза.
До этого момента вышесказанное было возможно, отправив все необходимые команды на нашу графическую карту, чтобы сформировать трехмерное изображение для одной перспективы. Подход такой же для перспективы нашего второго глаза.
Версия 1.1 Vulkan предлагает набор команд рендеринга для формирования нескольких, немного разных выходов (изображений), которые в конечном итоге дают лучшую производительность в приложениях VR.
Слои (layers)
В основном, предназначение слоёв — проверить входящие данные на ошибки и отслеживать работу Vulkan. Работают они очень просто: допустим, вызываем функцию, и попадает она в самый верхний слой, заданный при создании устройства или экземпляра ранее. Он всё проверяет на правильность, после этого передаёт вызов в следующий. И так будет, пока дело не дойдёт до ядра Vulkan. Конечно же, можно создать собственные слои. Например, Steam выпустила слой SteamOverlay (хотя и не знаю, что он вообще делает). Тем не менее, слои будут молчать, но не доведут до краха приложения. Как узнать, правильно ли всё сделано? Для этого есть специальное расширение!
Читайте также: