Vulkan rendering library for Go. Низкоуровневый, но эргономичный API поверх Vulkan: instance, device, swapchain, синхронизация и компиляция шейдеров спрятаны в C-ядре, горячий путь кадра пишется в один командный поток без cgo-налога за каждый draw.
- Репозиторий: github.com/org-fe/vulcgo
- Автор: c0redev (https://unitdev.run)
- Лицензия: MIT
gpu— ядро: device, буферы/текстуры/сэмплеры через VMA, шейдеры (GLSL компилируется в рантайме через shaderc), пайплайны, compute, offscreen render targets, depth-only targets (shadow map), readback буферов, ввод (клавиатура/мышь), debug names, командный батч с авто-барьерами, асинхронная загрузка ресурсов (gpu.Loader), загрузка текстур из файлов (png/jpeg/gif/webp черезgpu.LoadTexture/LoadTextureAsync).graph— тонкая надстройка: кадр собирается из compute/render-пассов, барьеры расставляет ядро.render2d— batch renderer (тысячи спрайтов одним draw call) + текст.render3d— mesh + lambert-рендерер с глубиной, MSAA и shadow mapping (depth-only offscreen pass + compare-сэмплер). Загрузка OBJ (LoadOBJ/LoadOBJAsync) и glTF 2.0 (.gltf/.glb,LoadGLTF/LoadGLTFAsync): позиции/нормали/UV, индексы ubyte/ushort/uint, baseColorTexture, node matrix/TRS, скелетная анимация (skins, JOINTS_0/WEIGHTS_0, CPU-eval суставов в SSBO, skinned vertex/fragment шейдеры с joint-матрицами) и анимации (LINEAR/STEP/CUBICSPLINE черезModel.Update/Model.Animate).postfx— HDR bloom + ACES tone mapping: сцена рендерится в RGBA16F target, затем bright-pass, размытие по Гауссу и композит в swapchain.gpu/astc— декодер ASTC 4x4 LDR (UASTC) в RGBA8, вендоренный однофайловый декодер Binomial basis_universal через cgo.gpu/etc1s— CPU-транскодер Basis Universal ETC1S (CRN) в RGBA8, вендоренный через cgo. Используется внутриgpu.LoadKTX2для KTX2/Basis ETC1S.gpu/ktx2.go— чтение KTX2/Basis Universal: UASTC (ASTC 4x4) и ETC1S транскодируются в RGBA8-sRGB (LoadKTX2/LoadKTX2File/LoadKTX2Async), поддержка ZSTD supercompression и генерация mip-цепочки.vmath— vec/mat/quat/transform/camera.lint—go vet-анализатор, ловит типовые ошибки использования vulcgo.
vulcgo — cgo-библиотека: при go build компилируется C++17 ядро
(gpu/core.cpp). Нужны системные зависимости:
- Go 1.26+
- Vulkan SDK (loader + заголовки),
pkg-config --exists vulkan - GLFW 3,
pkg-config --exists glfw3 - shaderc (runtime-компиляция GLSL),
-lshaderc_shared - C++17 компилятор (g++/clang++)
Установка зависимостей на Ubuntu/Debian:
sudo apt-get install -y \
libvulkan-dev \
libvulkan-volk-dev \
vulkan-validationlayers-dev \
libglfw3-dev \
shaderc \
libshaderc-dev \
build-essentialДля компиляции C++ ядра отдельно (CI/dev) понадобятся вендоренные заголовки
VMA и stb, которые уже лежат в third_party/, дополнительно ставить не надо.
go get github.com/org-fe/vulcgo
В коде импортируй нужные пакеты:
import (
"github.com/org-fe/vulcgo/gpu"
"github.com/org-fe/vulcgo/render3d"
)Перед сборкой убедись, что pkg-config --exists vulkan и
pkg-config --exists glfw3 возвращают 0. Без Vulkan-loader и заголовков
go build упадёт на этапе компиляции cgo.
package main
import (
"log"
"github.com/org-fe/vulcgo/gpu"
"github.com/org-fe/vulcgo/graph"
)
func main() {
dev, err := gpu.New(gpu.Config{Width: 800, Height: 600, Title: "tri", VSync: true})
if err != nil {
log.Fatal(err)
}
defer dev.Close()
for !dev.ShouldClose() {
dev.Poll()
g, err := graph.New(dev)
if err != nil {
log.Fatal(err)
}
// команды кадра через g.PassRender(enc) ...
if err := g.End(); err != nil {
log.Fatal(err)
}
}
}Полные примеры в examples/: gpu-triangle, gpu-2d, gpu-3d,
gpu-compute (явный BufferBarrier), gpu-offscreen (multi-pass через
offscreen target), gpu-shadows (depth-only target + семплирование),
gpu-readback (чтение GPU-буфера в CPU), gpu-postfx (HDR bloom + shadow
через postfx), gpu-async (асинхронная загрузка OBJ через gpu.Loader),
gpu-textures (асинхронная загрузка png-текстуры через gpu.Loader),
gpu-ktx2 (загрузка KTX2: ETC1S + UASTC, mip-цепочка).
Живой рендер требует физического GPU и работающего Vulkan-драйвера. Сама
сборка и go test ./... GPU не требуют.
Encoder пишет команды кадра в плоский []byte (unsafe, без аллокаций на
кадр). Весь поток уходит в ядро одним gpu_submit, который разворачивает
его в vkCmd*. Поэтому стоимость cgo платится один раз на кадр, а не на
каждый draw/push.
go vet ./...
Или как отдельная утилита:
go run ./lint/cmd/vulcgo-lint ./...
Ловит: gpu.New/graph.New без defer Close (утечка устройства),
graph.New без парного End.
Все пакеты возвращают единый тип verr.Error с кодом (verr.Code).
Проверка по коду — через verr.IsCode:
if err != nil {
if verr.IsCode(err, verr.CodeShader) {
// шейдер не скомпилился
}
log.Fatal(err)
}Коды ядра (verr.CodeDevice, verr.CodeResource, …) зеркалят GPU_ERR_*
из core.h; надстройки добавляют CodeParse, CodeUnsupported,
CodeNotFound, CodeInvalid, CodeIO.
Единый паттерн по всем пакетам: Load (из io.Reader), LoadFile
(из пути), LoadAsync (через gpu.Loader для неблокирующей загрузки).
Последний аргумент — число mip-уровней (0 = без mipmap, 1 = исходный размер).
tex, err := gpu.LoadTexture(dev, file, 1) // png/jpeg/gif/webp -> RGBA8-sRGB
tex, err := gpu.LoadKTX2(dev, file, 1) // KTX2/Basis (UASTC или ETC1S)
mesh, err := render3d.LoadOBJ(dev, reader) // Wavefront OBJ
model, err := render3d.LoadGLTF(dev, "scene.glb") // glTF 2.0, кости+анимацииАсинхронно (не блокирует кадр):
loader := gpu.NewLoader(dev, 4)
gpu.LoadTextureAsync(loader, dev, "tex.png", 1)
render3d.LoadOBJAsync(loader, dev, "mesh.obj")
// Poll возвращает (name, val, err, ok); ok=false — очередь пуста
for name, val, err, ok := loader.Poll(); ok; name, val, err, ok = loader.Poll() {
if err != nil {
log.Printf("%s: %v", name, err)
continue
}
// val — готовый *gpu.Texture / *render3d.Mesh
}gpu.LoadKTX2 декодирует оба суперкомпрессионных режима Basis Universal:
- UASTC (
supercompressionScheme = 2, ZSTD) → ASTC 4x4 → RGBA8-sRGB. CPU-декод через вендоренныйbasisu_astc_helpers(gpu/astc). - ETC1S (
supercompressionScheme = 1, BasisLZ) → RGBA8-sRGB. CPU-транскод через вендоренный Basis Universal transcoder (gpu/etc1s).
Нативные (не-Basis) vkFormat != 0 не поддерживаются — вернёт
verr.CodeUnsupported.
MIT. C-ядро вендорит VMA (MIT) и stb (MIT/public domain). ASTC-декодер — вендоренный однофайловый декодер Binomial basis_universal (MIT). ETC1S-транскодер — вендоренный Basis Universal transcoder (MIT/public domain).