The NVIDIA descriptor-heap AS-read workaround (#15) rewrote heap acceleration-structure reads into a load of the TLAS device address from a push-constant block. It always *synthesized a new* push-constant block, so any ray-tracing shader that already declared one ended up with two — which SPIR-V forbids ("at most one push constant block statically used per entry point"), and vkCreateShaderModule's spirv-val check rejected: Entry point id '4' uses more than one PushConstant interface. WorkaroundNvidiaAS::Patch now detects an existing PushConstant variable and, when present, appends a single ulong member (the TLAS address) to that block instead of adding a second one, reading the address through the shader's own push-constant variable. The append offset is the end of the user's block, computed from the members' explicit Offset/ArrayStride/ MatrixStride decorations (correct under both scalar and std140 layout) and rounded up to 8. Shaders with no push constant of their own keep getting a freshly synthesized single-member block at offset 0, exactly as before. That offset is published via Device::workaroundTlasPushOffset and RTPass feeds it to vkCmdPushDataEXT so the address lands where the rewritten load reads it (0 for the synthesized case, preserving prior behaviour). Verified on the affected driver (NVIDIA 610.43.02, RTX 4090): VulkanTriangle ray-traces correctly and validation-clean both with and without a user-declared raygen push constant. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| CustomShader | ||
| Decompression | ||
| HelloDom | ||
| HelloUI | ||
| HelloWindow | ||
| InputSystem | ||
| RTStress | ||
| RTVolume | ||
| Sponza | ||
| VulkanTriangle | ||
| README.md | ||
Examples
Each example is a self-contained crafter-build project that depends on
the parent Crafter.Graphics via LocalProject. To build and run any
of them:
cd examples/<name>
crafter-build -r
Index
HelloWindow
Minimum viable program: open a window, run the event loop. No Vulkan
rendering. Useful as a smoke test for Device::Initialize + Window +
the platform backend.
VulkanTriangle
Ray-traced single triangle through vkCmdTraceRaysKHR. Shows the full
ray-tracing setup: DescriptorHeapVulkan with image and buffer slots,
PipelineRTVulkan from raygen / miss / closesthit SPIR-V, BLAS via
Mesh::Build, TLAS via RenderingElement3D::BuildTLAS, direct
vkWriteResourceDescriptorsEXT for swapchain views, RTPass on
window.passes. Smallest test of the bindless ray-tracing path.
HelloUI
Compute-shader UI demo using all three UI tiers:
- Tier 3 components:
DrawButton,DrawSlider,DrawProgressBar, composed viaRect::SubRectfor resize-safe layout. - Tier 2 standard shaders:
DispatchQuadsfor the background and components,DispatchCirclesfor a cursor-tracking dot,DispatchTextfor the button label (with the FontAtlas wired up toUIRenderer). - Tier 1 is available too — any custom
ComputeShaderregistered on the same heap can be dispatched alongside the standard ones.
Hit-testing and animation are user code (see the EventListener
subscriptions on window.onMouseMove / onMouseLeftClick); the
library does not track widgets or focus.
Drop a TTF in this directory as font.ttf before running (the example
loads it via Font("font.ttf")).
InputSystem
Guided tour of Crafter::Input: name actions ("Jump", "Move", "Fire",
"Look", "Zoom"), bind them to keys / mouse / gamepad (with composite
bindings for WASD-as-Vector2 and analog sticks), and consume them as
events. Demonstrates:
- The compile-time
Key(CrafterKeys::Space)helper that folds to a per-platform raw scancode — bindings stay cross-platform-readable in source while runtime data stores raw codes only. - All four action types (Button, Axis1D, Vector2) with multiple bindings per action (any-of semantics).
Map::StartRebind— press R, then press any input to remap "Jump" at runtime. Captured input is filtered out for that frame.BindingToString/BindingFromStringround-trip — print the default bindings as the on-disk format.- Gamepad hot-plug events: plug a controller in mid-run and the bindings start firing immediately.
Console-driven (no UI rendering needed); focus the window and watch stdout.
CustomShader
Tier 1 demo: a user-authored compute shader (inverse-circle.comp.glsl)
running alongside the shipped drawQuads. The custom shader inverts RGB
under each item-circle — exactly the kind of effect attempt #2's closed
shader couldn't express. Shows:
- Defining your own item POD struct in C++ + matching
std430struct in GLSL. #include "../../shaders/ui-shared.glsl"for the bindless heap declarations +UIDispatchHeaderpush-constant contract.ComputeShader::Loadfor the.spv,UIRenderer::RegisterBufferfor your SSBO,FillHeaderto populate the standard prefix, andUIRenderer::Dispatchto launch — the same pattern the standard shaders use under the hood.- The inter-dispatch SHADER_WRITE → SHADER_READ|WRITE barrier is
inserted automatically, so the custom shader sees the colored stripes
drawn by the prior
DispatchQuadsand reads/writes the swapchain image safely.