Перейти к основному содержимому

Vulkan и низкоуровневая графика на C++

Разработчику Архитектору

Что такое Vulkan

Vulkan — кроссплатформенный низкоуровневый API к GPU от Khronos Group. Он описывает, как CPU ставит работу GPU в очередь — буферы, изображения, шейдеры, синхронизация, показ кадра в окне. Vulkan не рисует треугольник одной функцией — вы явно создаёте десятки объектов до первого кадра.

Для C++ Vulkan естественен — тонкий C-интерфейс, явное владение ресурсами, минимум скрытой логики в драйвере. Хорошо сочетается с RAII (Идиомы, Память).

Обзор игрового контекста — Разработка игр. Vulkan в индустрии — /encyclopedia/9-spinoff/9-04-razrabotka-igr/114.


Карта 2D/3D-стека в разделе C++

УровеньИнструментыСтатьи
2D, учебные игрыSFML, SDL, RaylibSFML — 2D-графика и мультимедиа на C++, SDL — мультимедиа и окна на C++, Raylib — быстрые 2D/3D прототипы на C++
2D/3D "из коробки"Siv3D, RaylibSiv3D — 2D/3D и мультимедиа на C++, Raylib — быстрые 2D/3D прототипы на C++
3D APIOpenGL, DirectX, VulkanOpenGL — 3D-графика на C++, DirectX — графика и мультимедиа на Windows, эта статья
Desktop UIQtQt - кроссплатформенный фреймворк на C++

Vulkan — нижний слой: окно даёт SDL или GLFW, рендер — ваш код и шейдеры SPIR-V.


Ключевые понятия

ТерминОпределение
InstanceТочка входа в Vulkan; версии API, validation layers
Physical / Logical deviceВидеокарта и ваш "хэндл" к ней с очередями
QueueОчередь команд GPU (graphics, compute, transfer)
SwapchainНабор изображений для double/triple buffering
Render passОписание этапов рендера и layout вложений
PipelineШейдеры + фиксированные настройки растеризации
Command bufferЗаписанная последовательность команд GPU
Semaphore / FenceСинхронизация GPU↔GPU и CPU↔GPU
SPIR-VБинарный формат шейдеров для Vulkan

Сравнение с OpenGL (выше уровень абстракции) и DirectX 12 (похожая философия на Windows).


Первая цель на Vulkan

Опорная мысль: Vulkan — явное описание работы GPU, а не один вызов "нарисуй".

Минимум на старте:

  1. Окно (GLFW/SDL) и VkSurface.
  2. Swapchain и очистка экрана цветом.
  3. Цикл кадров без ошибок validation layers.

После этого — вершины, индексы, uniform buffer с MVP (OpenGL и шейдеры — та же математика).

Практика с критериями — Практические задания, блок "Графика".


Vulkan и OpenGL — зачем менять API

КритерийOpenGLVulkan
Состояние GPUЧасто неявное; драйвер "догадывается"Явное; задаёте вы
ПотокиОдин контекст на поток — неудобноНесколько очередей, параллельная запись команд
CPU overheadВыше на типичных сценахНиже при правильной архитектуре
Первый треугольникБыстрееДольше (больше объектов)
macOSDeprecated → MetalMoltenVK (Vulkan поверх Metal)

Vulkan не заменяет движок (Unreal, Godot). Он нужен, когда вы пишете свой рендер, инструмент визуализации, эмулятор GPU или учебный проект "как устроен кадр изнутри".

Для 2D-игры достаточно Raylib или SFML.


Модель объектов Vulkan

Типичная инициализация — цепочка зависимостей:

Разбор объектов

  • Instance — глобальный контекст API; здесь включают validation layers для отладки.
  • Physical device — конкретная видеокарта; у неё семейства очередей (graphics, present, transfer).
  • Logical device — интерфейс приложения к GPU; из него берут vkQueueSubmit, vkQueuePresent.
  • Surface — связь с HWND / Wayland / Android; без surface нет swapchain. Создают через GLFW, SDL (SDL — мультимедиа и окна на C++) или native API.
  • Swapchain — 2–3 изображения; рисуете в один буфер, экран показывает другой (double buffering).
  • Render pass — какие attachment (color, depth), какие layout памяти GPU между этапами.
  • Pipeline — vertex/fragment shader + rasterization, blend, depth test. Смена pipeline дорогая — сортируют draw calls по state.
  • Command buffers — записанные команды: vkCmdBeginRenderPass → draw → vkCmdEndRenderPass.

Один кадр рендеринга

Упрощённый порядок каждой итерации игрового цикла:

  1. Дождаться fence — GPU закончил прошлый кадр.
  2. acquireNextImage — индекс следующего изображения swapchain.
  3. Записать command buffer (или переиспользовать) — clear, draw, memory barriers.
  4. Submit в graphics queue с semaphore.
  5. Present — показ на экран, согласование semaphores с present queue.

Синхронизация — отдельная дисциплина. Гонки CPU/GPU дают артефакты или ошибки validation. В debug всегда включайте VK_LAYER_KHRONOS_validation — слой объясняет забытые барьеры и layout.

Многопоточная запись command buffers — Особенности языка / потоки.


Шейдеры и SPIR-V

Исходники — GLSL или HLSL; компилятор (glslang, DXC) → SPIR-V (.spv). В C++ загружают бинарник в VkShaderModule.

Роли:

  • Vertex shader — позиции, UV, нормали;
  • Fragment shader — цвет пикселя;
  • Descriptor sets — uniform buffer (MVP), текстуры, samplers.

Дескрипторы типизированы через descriptor set layout — аналог "слота текстуры N" в старых API, но строже.

Теория шейдеров — OpenGL и шейдеры. HLSL в экосистеме Microsoft — DirectX.


Память на GPU

VkBuffer и VkImage живут в device memory. Типы:

  • host-visible — CPU может map и писать (staging);
  • device-local — быстрый доступ GPU (статическая геометрия).

Паттерны:

  • статика — upload через staging buffer → vkCmdCopyBuffer → device-local;
  • динамика — ring buffer в host-visible с аккуратными барьерами.

Утечки vkDestroy* и descriptor pools так же опасны, как new без deleteПамять.

VMA (Vulkan Memory Allocator) упрощает аллокации в реальных проектах.


C++ вокруг Vulkan

Официальный API — C. В C++ проектах:

  • Vulkan-Hpp — типобезопасные хэндлы, optional, RAII-обёртки;
  • volk — динамическая загрузка vkGetInstanceProcAddr;
  • VMA — аллокатор памяти.

Минимальный стек: CMake + GLFW + Vulkan SDK + validation layers.

cmake_minimum_required(VERSION 3.16)
project(vulkan_triangle CXX)
set(CMAKE_CXX_STANDARD 17)

find_package(Vulkan REQUIRED)
find_package(glfw3 REQUIRED)

add_executable(triangle main.cpp)
target_link_libraries(triangle PRIVATE Vulkan::Vulkan glfw)
  • VULKAN_SDK — переменная окружения к установленному SDK (LunarG).
  • find_package(Vulkan) — импорт target Vulkan::Vulkan в CMake 3.7+.

Сборка — Конфигурация и сборка в C++, CMake — первая программа.


Когда Vulkan избыточен

  • 2D-игра или UI — SDL, SFML, Raylib, Qt Quick;
  • коммерческий 3D — Unreal / Unity;
  • научная визуализация — иногда хватает OpenGL.

Vulkan оправдан при жёстком FPS, multithreaded recording, custom deferred/hybrid pipeline или обучении архитектуре GPU.


Частые ошибки новичка

СимптомПричинаЧто сделать
Чёрный экранпустой command buffer / неверный viewportbegin/end render pass, scissor
Артефактыневерные barriers / layoutvalidation layers, править по одному
Зависанияfence/semaphore out of order"1 кадр в полёте", потом масштабировать
Просадки FPSпересоздание pipeline каждый кадркэш PSO, batching

Связь с другими темами C++