C++ graphics library using Wayland and Vulkan.
  • C 43.3%
  • C++ 42.6%
  • JavaScript 13.2%
  • GLSL 0.9%
Find a file
2026-05-18 02:07:48 +02:00
additional browser DOM support 2026-05-18 02:07:48 +02:00
examples browser DOM support 2026-05-18 02:07:48 +02:00
implementations browser DOM support 2026-05-18 02:07:48 +02:00
interfaces browser DOM support 2026-05-18 02:07:48 +02:00
lib new UI system 2026-05-01 23:35:37 +02:00
shaders UI rewrite 3rd attempt 2026-05-02 21:08:20 +02:00
.gitignore push 2025-04-16 00:45:27 +02:00
LICENSE removed pipeline arg 2025-05-07 19:21:51 +02:00
project.cpp browser DOM support 2026-05-18 02:07:48 +02:00
README.md UI rewrite 3rd attempt 2026-05-02 21:08:20 +02:00

Crafter.Graphics

Vulkan-based graphics library built around C++20 modules and the bindless VK_EXT_descriptor_heap extension. Provides window management, ray tracing, and a compute-shader-driven UI on a single, opinionated stack.

What's in here

  • Window — Wayland and Win32 backends, swapchain ring, frame pacing, input events. Pick a backend at build time via the target triple.
  • Device — single-Vulkan-instance bring-up. The library targets VK_EXT_descriptor_heap exclusively; pipelines are created with VK_PIPELINE_CREATE_2_DESCRIPTOR_HEAP_BIT_EXT so there are no descriptor-set layouts and push constants travel via vkCmdPushDataEXT.
  • DescriptorHeapVulkan — bindless slot allocator. AllocateImageSlots / AllocateBufferSlots / AllocateSamplerSlots, with byte-offset helpers for direct descriptor writes.
  • VulkanBuffer<T, Mapped> — typed buffer with optional host mapping and a FlushDevice that issues the right host-write barrier.
  • ImageVulkan<Pixel> — image + staging buffer, mip-chain support, one-shot uploads via a command buffer.
  • PipelineRTVulkan / ShaderBindingTableVulkan / RTPass — ray-tracing pipeline, SBT, and a RenderPass that dispatches it.
  • ComputeShader — the Tier 1 wrapper used by the UI system. Loads a .spv, builds a heap-bound compute pipeline, dispatches with vkCmdPushDataEXT. Use it directly for any custom compute.
  • UI — three-tier UI system; see below.
  • FontAtlas — single-channel SDF atlas (1024×1024, 32pt base, shelf-packed, lazy Ensure per codepoint, dirty-flush via Update).
  • Mesh / RenderingElement3D / Animation — BLAS/TLAS construction and 3D scene plumbing for the ray-tracing path.

UI system (three tiers)

The UI is deliberately layered to balance no-boilerplate against no-lock-in:

  • Tier 1 — ComputeShader. Load any .spv, dispatch with push constants, library inserts inter-dispatch barriers. The escape hatch: if the standard shaders don't fit, write your own compute and dispatch it next to them.
  • Tier 2 — UIRenderer + standard shaders. Four shipped compute shaders (drawQuads, drawCircles, drawImages, drawText), POD item structs (QuadItem, CircleItem, ImageItem, GlyphItem), a shared GLSL contract in shaders/ui-shared.glsl, and helpers (RegisterBuffer, RegisterImage, RegisterSampler, FillHeader, Dispatch*, ShapeText). You build your own per-shader SSBOs (manual batching) and call one Dispatch* per shader type per frame. Item array order = draw order.
  • Tier 3 — stateless presentation functions. DrawButton, DrawCheckbox, DrawSlider, DrawProgressBar. Each is a small function that appends items to your buffers — they don't dispatch. Colors come in as small inline *Colors aggregates, no library Theme type. The source is the customization API: if a component doesn't fit, copy its body and edit it. No virtual hooks, no extension points.

What's not in the UI: widget tree, layout engine (just a Rect::SubRect carving helper), theming, hit-testing, focus management. State for interactive components (hover, drag, focus) lives in user-owned POD structs, not the library.

UI dispatch model

Standard shaders dispatch one workgroup per 8×8 screen tile — each thread iterates every item in the SSBO in array order, accumulating into a local dst, and stores once. Total cost is O(W·H·N); works well up to a few hundred items at 1080p. Splitting one buffer into multiple dispatches doesn't help — the same total work plus barrier overhead. If you need to render thousands of UI items, you want a different shader (tile binning, per-item-list resolve), not more dispatches.

Build

The repository is built with crafter-build (a project-config based build system; the project description lives in project.cpp):

crafter-build           # build the library
crafter-build -r        # build and run (in an example directory)

The build picks the window backend automatically: Wayland on Linux, Win32 on Windows / mingw. Cross-compile via the standard --target=... flag.

Examples

See examples/. Quick map:

  • HelloWindow — minimal window, no rendering.
  • VulkanTriangle — ray-traced triangle, the smallest test of the bindless + ray-tracing path.
  • HelloUI — UI smoke test using all three tiers (background quad, slider, progress bar, button with text label, cursor-tracking circle).
  • CustomShader — Tier 1 demo: a user-authored compute shader inverting RGB under a list of item-circles, dispatched alongside the standard drawQuads. The "could attempt #2 do this?" test.

License

LGPL 3.0. See per-file headers and LICENSE.