Crafter.Graphics/README.md

105 lines
4.8 KiB
Markdown
Raw Normal View History

2026-05-02 00:03:24 +02:00
# Crafter.Graphics
2026-05-02 21:08:20 +02:00
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.
2026-05-02 00:03:24 +02:00
2026-05-02 21:08:20 +02:00
## What's in here
2026-05-02 00:03:24 +02:00
2026-05-02 21:08:20 +02:00
- **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.
2026-05-02 00:03:24 +02:00
2026-05-02 21:08:20 +02:00
## UI system (three tiers)
2026-05-02 00:03:24 +02:00
2026-05-02 21:08:20 +02:00
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](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`):
2026-05-02 00:03:24 +02:00
```bash
2026-05-02 21:08:20 +02:00
crafter-build # build the library
crafter-build -r # build and run (in an example directory)
2026-05-02 00:03:24 +02:00
```
2026-05-02 21:08:20 +02:00
The build picks the window backend automatically: Wayland on Linux,
Win32 on Windows / mingw. Cross-compile via the standard `--target=...`
flag.
2026-05-02 00:03:24 +02:00
## Examples
2026-05-02 21:08:20 +02:00
See [examples/](examples/). Quick map:
2026-05-02 00:03:24 +02:00
2026-05-02 21:08:20 +02:00
- [HelloWindow](examples/HelloWindow/) — minimal window, no rendering.
- [VulkanTriangle](examples/VulkanTriangle/) — ray-traced triangle, the
smallest test of the bindless + ray-tracing path.
- [HelloUI](examples/HelloUI/) — UI smoke test using all three tiers
(background quad, slider, progress bar, button with text label,
cursor-tracking circle).
- [CustomShader](examples/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.
2026-05-02 00:03:24 +02:00
## License
2026-05-02 21:08:20 +02:00
LGPL 3.0. See per-file headers and `LICENSE`.