Skip to content

ORG-FE/vulcgo

Repository files navigation

vulcgo

Vulkan rendering library for Go. Низкоуровневый, но эргономичный API поверх Vulkan: instance, device, swapchain, синхронизация и компиляция шейдеров спрятаны в C-ядре, горячий путь кадра пишется в один командный поток без cgo-налога за каждый draw.

Что есть

  • 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.
  • lintgo 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
}

KTX2: поддерживаемые форматы

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).

About

Vulkan rendering library for Go

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors