Программирование игр, создание игрового движка, OpenGL, DirectX, физика, форум
GameDev.ru / Программирование / Статьи / Маленькая статья про Vulkan

Маленькая статья про Vulkan

Автор:

Это небольшая статья для тех, кто хочет разобраться в основных концепциях нового графического API и его отличиях от предыдущего поколения. Я буду говорить о Vulkan vs OpenGL, но многие вещи можно применить и к другим API нового и старого поколений.

Command Buffers


Самое главное отличие Vulkan от OpenGL – явная асинхронность работы с GPU. Если в GL драйвер сам решал, когда начинать нагружать видеокарту, то здесь это делает явно само приложение. Когда вы хотите нарисовать треугольник, запустить вычислительный шейдер, скопировать данные в память устройства вам нужно записать command buffer и отправить его в очередь на исполнение. Командные буферы можно использовать повторно, запускать из них вторичные буферы, собирать в цепочки с помощью семафоров. Тут есть достаточно широкий простор для оптимизации рендера.

Graphics Pipeline


Графический конвейер – центральная часть 3D API. Сама структура конвейера не изменилась – те же шейдерные стадии, тесты глубины, параметры блендинга и т.д. Но если в GL параметры пайплайна – глобальная машина состояний, которую нужно настраивать под каждый вызов отрисовки, то в Vulkan он выделен в отдельный объект. Сначала вы создаёте pipeline-объекты, а потом в буфере команд просто устанавливаете нужный, подключаете descriptor sets с ресурсами (UBO, SSBO, текстурами, семплерами), атрибуты вершин и рисуете. Основная задача такого подхода – локализовать очень затратную операцию создания пайплайна на стадии инициализации, и в дальнейшем быстро переключаться между готовыми к применению наборами параметров. Это намного эффективнее ситуации в GL, когда драйвер каждый кадр вынужден много раз проверять корректность запросов приложения. Также в API есть возможность наследования и pipeline cache, которые позволяют ускорять создание конвейера за счет переиспользования уже имеющихся или сохранённых в предыдущей сессии пайплайнов. 

Renderpass


В Vulkan есть еще один связанный с графикой объект, о котором нужно упомянуть, и который отличает его от других nextgen API – это renderpass. Изначально он был добавлен для облегчения жизни на мобильных тайловых GPU, в которых для всех draw call-ов сначала отрабатывает вершинная часть конвейера, а затем для каждого тайла фреймбуффера фрагментный конвейер для полигонов, попавших в тайл. Рендерпасс позволяет явно группировать вызовы отрисовки, которые должны обрабатываться вместе, в отдельные сабпассы. Это не актуально на десктопном железе, но, как пишут AMD, с помощью renderpass здесь тоже можно применить некоторые оптимизации. Кроме этого рендерпассы выполняют еще несколько полезных функций – управление текстурами фреймбуффера(очистка, смена image layout), синхронизация  сабпассов, резолв мультисемплинга.

Синхронизация


В силу асинхронной природы работы GPU в Vulkan не гарантируется последовательное выполнение даже для команд в одном буфере, не говоря уже о разных буферах и разных очередях, поэтому все зависимости должны указываться приложением явно. Кроме прописывания зависимостей в рендерпассе есть еще четыре механизма синхронизации – semaphore, fence, event, pipeline barrier. Семафоры – самый часто используемый механизм. Сигнализируют о том, что буфер команд завершил работу и разрешают следующему буферу продолжить выполнение. Для уведомления программы о том же событии используются fences. Events – тонкий инструмент для синхронизации конкретного места в command buffer. Могут и ожидаться и устанавливаться/сбрасываться как в буфере, так и на хосте. Барьер синхронизирует последующие команды буфера с предыдущими.

Управление памятью


Тема, которая многих пугает – ручное управление памятью на устройстве. В Vulkan вы сначала создаёте буфер или текстуру, а потом назначаете для них область памяти с параметрами размера и выравнивания, получеными из функции vkGet[Buffer/Image]MemoryRequirements. Можно не заморачиваться и просто передавать эти параметры в функцию аллокации, а можно при желании выделить большой кусок памяти сразу и утрамбовывать туда свои данные самым эффективным способом. Это единственное место, в котором участвуют указатели в памяти устройства – дальше вся работа ведётся с хендлами текстур и буферов.

Вот вроде все основные моменты. Что-то осталось за кадром (вроде устройств, очередей, слоёв, расширений, многопоточности, SPIR-V шейдеров), но это сервисные вещи, о которых можно почитать в туториалах.

Заключение


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

Куда копать дальше.
Vulkan in 30 minutes – Краткий обзор функций API.
LunarG Vulkan SDK – Маст хев для разработки, в комплекте неплохие примеры кода на каждую фичу.

1 сентября 2016

#Vulkan

2001—2017 © GameDev.ru — Разработка игр