2026-04-24 - 2026-07-24
Overview
73 pull requests merged by 1 user
Merged
#156 test(bench): measure net perf gain from #40 to master in Sponza (#155)
Merged
#154 fix(window): silence per-frame and setup-path Vulkan validation errors (#153)
Merged
#152 perf(window): block message loop while paused on Win32 (#134)
Merged
#151 perf(webgpu): byteCount-bounded readback for over-provisioned buffers (#133)
Merged
#150 perf(rt): batch the WebGPU TLAS instance upload into one writeBuffer (#131)
Merged
#149 perf(webgpu): range-flush only live TLAS metadata slots (#130)
Merged
#148 perf(ui): reuse handles vector in WebGPU custom Dispatch (#132)
Merged
#147 perf(ui): per-shelf dirty spans for tight font-atlas uploads (#129)
Merged
#146 perf(ui): memoize the input-field caret prefix width (#128)
Merged
#143 perf(ui): LRU-evict the shaped-run cache instead of clearing it (#123)
Merged
#145 perf(ui): subgroup prefix-sum stream compaction in the UI compute shaders (#124)
Merged
#144 perf(ui): skip the destination read-modify-write on empty tiles (#127)
Merged
#142 perf(ui): hoist loop-invariant per-item/per-glyph math out of the per-pixel loop (#125)
Merged
#141 perf(ui): transparent shaped-run cache lookup, no string copy on hit (#122)
Merged
#140 perf(tlas): dirty-track the per-frame TLAS instance+metadata upload (#118)
Merged
#139 perf(buffer): reuse staging via a per-frame-in-flight ring in UploadDeviceLocal (#120)
Merged
#138 perf(mesh): dirty-range vertex upload for deforming-mesh Refit (#119)
Merged
#137 perf(sync): scope frame-loop barriers to swapchain image + real per-pass stages (#115)
Merged
#136 perf(image): release static texture staging after upload (#114)
Merged
#135 perf(device): pop retired deletions off the front in O(ready) (#116)
Merged
#112 test(mesh): pin static-build deletion count for #67 staging-release (#110)
Merged
#109 perf(mesh): place RT geometry device-local via #89 upload strategy (#73)
Merged
#111 perf(rt): allocate TLAS metadata buffer in BAR/VRAM, not system RAM (#75)
Merged
#108 perf(window): use HOST_CACHED readback staging in SaveFrame (#74)
Merged
#107 perf(rt): place SBT in device-local memory via upload-strategy helper (#72)
Merged
#106 perf(decompress): release compressed staging after submit, not for the resource's life (#67)
Merged
#105 perf(rt): allocate TLAS instance buffer in BAR/VRAM, not system RAM (#65)
Merged
#104 perf(mesh): release per-mesh scratch buffer for static BLAS (#66)
Merged
#103 perf(mesh): skip immutable index re-upload on RT refit UPDATE (#68)
Merged
#102 fix(device): fence-keyed deferred resource-deletion queue (#101)
Merged
#99 perf(ui): flush only the written descriptor range, not the whole heap (#61)
Merged
#100 perf(image): batch final mip-chain layout transition (#70)
Merged
#98 perf(rt): high-water-mark growth for TLAS host-input buffers (#64)
Merged
#97 perf(pipeline): shared, disk-persisted VkPipelineCache (#69)
Merged
#96 perf(buffer): capacity-reuse in VulkanBuffer::Resize (#63)
Merged
#95 feat(device): runtime upload-strategy helper PreferDirectDeviceWrite (#89)
Merged
#93 perf(ui): additive DispatchFused to collapse consecutive UI passes (#47)
Merged
#94 perf(vulkan-buffer): skip flush/invalidate on coherent memory (#60)
Merged
#92 perf(font): cache per-codepoint advances in font units (#57)
Merged
#91 perf(ui): gate per-pixel clip compares behind a flags bit (#50)
Merged
#90 perf(input-field): O(n) cursor hit test via Font::NearestCursorByte (#56)
Merged
#88 perf(ui): scope inter-dispatch barrier to the swapchain image (#48)
Merged
#87 fix(device): preferred mask + required-only fallback for GetMemoryType (#59)
Merged
#85 perf(ui): cooperative shared-memory tile culling in UI compute shaders
Merged
#86 fix(image): scope sampled-image upload barriers to the real consumer stage (#54)
Merged
#84 perf(text): fold Ensure+Lookup into FontAtlas::EnsureAndGet (#53)
Merged
#83 perf(font): upload only the dirty sub-rect of the glyph atlas (#51)
Merged
#81 feat(window): multi-frame-in-flight frame pacing (#40)
Merged
#82 perf(text): cache shaped runs in ShapeText (#52)
Merged
#80 perf(shaders): drop nonuniformEXT on text font slots
Merged
#79 perf(window): drop dead present-mode queries from swapchain recreate (#45)
Merged
#77 perf(window): cache per-frame heap-bind structs across frames
Merged
#78 perf(window): hoist invariant per-frame Vulkan info structs to members
Merged
#76 perf(window): ring buffer for CRAFTER_TIMING frame times (#44)
Merged
#39 feat(rt): BuildProcedural — accept a device AABB buffer as build input (#37)
Merged
#38 feat(vulkan-rt): BLAS build options — fast-build/fast-trace + in-place refit (#36)
Merged
#35 feat(vulkan-rt): Mesh::BuildProcedural — AABB (procedural) BLAS build path (#33)
Merged
#34 feat(input): wire native mouse-wheel scroll on Wayland + Win32, normalize all backends to ±1/detent
Merged
#31 feat(webgpu-rt): atomic pixel accumulator + raysPerPixel — >1 ray per pixel per bounce (#30)
Merged
#28 feat(webgpu): HDR post-process primitives for bloom (#27)
Merged
#26 fix(webgpu-rt): dynamic rayQuery TLAS leaf-start so picks hit for realistic instance counts (#25)
Merged
#24 docs(vulkan-rt): document dynamic descriptor_heap-index hit-shader fault (#23)
Merged
#22 fix(vulkan-rt): configurable recursion depth + per-shader TLAS push for compute (#21)
Merged
#20 fix(vulkan-rt): merge TLAS push constant into existing block (#18)
Merged
#19 feat(vulkan): re-enable GPU-Assisted Validation
Merged
#16 fix(vulkan-rt): work around NVIDIA descriptor-heap AS-read device-loss (#15)
Merged
#14 feat(webgpu-rt): any-hit + AABB (procedural) geometry support
Merged
#12 fix(webgpu): reshape wavefront TRACE/SHADE to 2-D to survive >4.19M rays
Merged
#10 docs(vulkan-rt): native descriptor-heap AS read is an NVIDIA driver fault (#7)
Merged
#9 fix(webgpu): request adapter's storage-buffer limit, not hardcoded 16
Merged
#6 fix(vulkan): clear startup validation errors on native triangle
Merged
#4 WebGPU RT: wavefront/streaming tracer (replaces megakernel)
Merged
#2 WebGPU RT: enable TLAS spatial sort via bitonic network (plan phase 3)
82 issues closed from 2 users
Closed
#155 Measure peformance improvements
Closed
#153 Vulkan validation errors: per-frame acquire-barrier dstAccessMask/stage mismatch + setup-path cmd-buffer/buffer lifecycle
Closed
#134 [perf] Win32 StartSync busy-spins one core at 100% when not updating (Window.cpp)
Closed
#133 [perf] WebGPU full-buffer readback copies entire allocation even for a small prefix (WebGPUBuffer.cppm)
Closed
#131 [perf] WebGPU GPU-owned instance runs upload one writeBuffer per element (RenderingElement3D-WebGPU.cpp)
Closed
#130 [perf] WebGPU metadata flush uploads full 256 KB padded buffer every frame (RenderingElement3D-WebGPU.cpp)
Closed
#132 [perf] UIRenderer::Dispatch heap-allocates a std::vector per custom dispatch (UI-WebGPU.cpp)
Closed
#129 [perf] FontAtlas dirty-rect uses one union bounding box (FontAtlas.cpp)
Closed
#128 [perf] DrawInputField recomputes caret X via full-prefix walk every frame (InputField.cpp)
Closed
#123 [perf] shapedRuns_ eviction is all-or-nothing clear() at cap (UI-Shared.cpp)
Closed
#124 [perf] Single-lane serial stream compaction stalls 63/64 threads — use subgroup prefix-sum (ui-fused.comp.glsl)
Closed
#127 [perf] Unconditional destination imageLoad/imageStore before early-out (ui-quads.comp.glsl)
Closed
#125 [perf] Hoist per-item/per-glyph loop-invariant math into shared memory at load (ui-images/text/fused)
Closed
#122 [perf] ShapeText heap-allocates the cache-key std::string on every call, including hits (UI-Shared.cpp)
Closed
#118 [perf] TLAS instance+metadata upload: O(n) rebuild + whole-buffer flush every frame (RenderingElement3D.cpp)
Closed
#120 [perf] Staged UploadDeviceLocal allocates+frees a fresh staging buffer every call (VulkanBuffer.cppm)
Closed
#119 [perf] Mesh::Refit re-uploads the full vertex buffer every frame (Mesh.cpp)
Closed
#115 [perf] Frame-loop barriers use ALL_COMMANDS scope (inter-pass + acquire/present) (Window.cpp)
Closed
#114 [perf] Per-image dedicated alloc + leaked persistent staging buffer (ImageVulkan.cppm)
Closed
#116 [perf] ReclaimDeletions compacts the whole deletion queue every frame (Device.cpp)
Closed
#126 [perf] Per-glyph-constant SDF AA scale recomputed per pixel (ui-text.comp.glsl)
Closed
#121 [perf] Per-frame whole-buffer flush of TLAS instance+metadata buffers (RenderingElement3D.cpp)
Closed
#117 [perf] Acquire/present barriers use ALL_COMMANDS scope (Window.cpp)
Closed
#113 [perf] No buffer suballocator — vkAllocateMemory per buffer (VulkanBuffer.cppm)
Closed
#110 MeshDecompressStagingRelease test fails on master: deletionQueue.size() != 1 after compressed Build
Closed
#73 [perf] Mesh vertex/index/aabb are HOST_VISIBLE — place device-local (direct on ReBAR, staged otherwise)
Closed
#75 [perf] TLAS metadataBuffer is HOST_VISIBLE, CPU-written + shader-read every frame
Closed
#74 [perf] SaveFrame readback uses HOST_COHERENT (write-combined) — should be HOST_CACHED
Closed
#72 [perf] RT shader binding table is HOST_VISIBLE, GPU-read every traceRays
Closed
#67 [perf] compressedStaging reallocated and kept per compressed Build
Closed
#65 [perf][MEDIUM] TLAS instance buffer is HOST_VISIBLE, read directly as AS build input
Closed
#66 [perf] Per-mesh dedicated scratch buffer (VRAM waste)
Closed
#68 [perf][LOW] Refit re-uploads immutable index buffer on UPDATE
Closed
#71 [perf][LOW] Compressed-asset Update re-Resizes both staging buffers every call
Closed
#101 [infra] Fence-keyed deferred resource-deletion queue (UAF since #40; unblocks #63/#66)
Closed
#61 [perf][LOW] Per-descriptor write flushes all numFrames heap copies whole-size
Closed
#70 [perf][LOW] Per-mip layout transitions issued one-at-a-time
Closed
#64 [perf] TLAS instance/metadata buffers reallocated on instance-count change
Closed
#69 [perf][LOW] No VkPipelineCache passed to vkCreateComputePipelines
Closed
#63 [perf] VulkanBuffer::Resize always destroys+reallocates
Closed
#62 [perf] Per-allocation vkAllocateMemory, no suballocator
Closed
#89 [perf] Runtime upload-strategy helper: direct HOST_VISIBLE|DEVICE_LOCAL vs staging (ReBAR-aware)
Closed
#47 [perf][MEDIUM] Add DispatchFused (additive) to collapse consecutive UI passes to one load/store
Closed
#58 [perf][MEDIUM] Descriptor heaps force HOST_VISIBLE|DEVICE_LOCAL with no fallback
Closed
#60 [perf][LOW] FlushDevice always flushes even on coherent memory
Closed
#57 [perf][LOW] GetLineWidth/ScaleForSize recompute scale + per-glyph HMetrics uncached
Closed
#50 [perf][LOW] uiResolveScreenPixel runs clip-rect compares even when unclipped
Closed
#56 [perf][LOW] InputField hit-test is O(n^2): re-measures whole prefix per char
Closed
#48 [perf][LOW] Narrow per-dispatch UI barrier to an image-subresource barrier (full removal: #47)
Closed
#59 [perf][LOW] GetMemoryType returns first match, no preferred/fallback distinction
Closed
#46 [perf][HIGH] UI tiles scan the full item list — no spatial culling
Closed
#54 [perf][MEDIUM] TransitionImageLayout hardcodes RAY_TRACING stage for all shader reads
Closed
#53 [perf][LOW] Ensure()+Lookup() do two hash-map probes per glyph
Closed
#51 [perf][MEDIUM] Full 1 MiB font atlas re-upload on any single new glyph
Closed
#40 [perf][HIGH] Frame-in-flight: per-frame fences + per-frame semaphores (remove per-frame vkQueueWaitIdle)
Closed
#52 [perf][MEDIUM] Per-frame text re-shaping for static strings
Closed
#49 [perf][LOW] nonuniformEXT on dynamically-uniform font slots (text shader)
Closed
#45 [perf][LOW] Resize path: dead present-mode queries + presentModes vector
Closed
#42 [perf][LOW] Descriptor-heap bind recorded unconditionally every frame
Closed
#43 [perf][LOW] Invariant Vulkan structs rebuilt every frame
Closed
#44 [perf][LOW] CRAFTER_TIMING frame-time history uses erase(begin()) every frame
Closed
#41 [perf][MEDIUM] Single shared semaphore pair prevents multiple frames in flight
Closed
#37 BuildProcedural: accept a device buffer as AABB build input (no host round-trip)
Closed
#36 Accelration structure build options
Closed
#33 Vulkan: Mesh::BuildProcedural — AABB (procedural) BLAS build path to match WebGPU
Closed
#32 Mouse scroll never reaches Input on native: Wayland PointerListenerHandleAxis is an empty stub, Win32 lacks WM_MOUSEWHEEL
Closed
#30 Wavefront RT: atomic pixel accumulator to allow >1 ray per pixel per bounce
Closed
#29 Smoke doesn't move
Closed
#27 Bloom / HDR post-process primitives for the WebGPU backend
Closed
#25 WebGPU rayQuery TLAS traversal hardcodes leaf-start (16383) — picks always miss below 8193 instances
Closed
#23 Dynamic descriptor_heap indexing faults the device in ray-tracing (closest-hit) shaders on NVIDIA
Closed
#21 Vulkan RT: recursion depth hardcoded to 1, and the descriptor-heap AS-read workaround is never pushed for compute dispatches
Closed
#18 #16 Doesn't work when shaders already define a push constant
Closed
#17 Reneable GPU-AV
Closed
#15 Find workaround to #7 driver issue
Closed
#13 WebGPU anyhit and volume
Closed
#11 WebGPU wavefront: 1-D indirect TRACE/SHADE dispatch overflows maxComputeWorkgroupsPerDimension at ~4K → black screen
Closed
#7 VK_ERROR_DEVICE_LOST on native RT
Closed
#8 WebGPU RT: device storage-buffer limit hardcoded to 16, breaks pipelines with >1 user storage buffer
Closed
#5 Bunch of errors when starting native vulkan triangle
Closed
#3 WebGPU RT: complete the wavefront rewrite (single deliverable — remaining phases)
Closed
#1 WebGPU RT: wavefront rewrite of the software ray tracer
83 issues created by 1 user
Opened
#1 WebGPU RT: wavefront rewrite of the software ray tracer
Opened
#3 WebGPU RT: complete the wavefront rewrite (single deliverable — remaining phases)
Opened
#5 Bunch of errors when starting native vulkan triangle
Opened
#7 VK_ERROR_DEVICE_LOST on native RT
Opened
#8 WebGPU RT: device storage-buffer limit hardcoded to 16, breaks pipelines with >1 user storage buffer
Opened
#11 WebGPU wavefront: 1-D indirect TRACE/SHADE dispatch overflows maxComputeWorkgroupsPerDimension at ~4K → black screen
Opened
#13 WebGPU anyhit and volume
Opened
#15 Find workaround to #7 driver issue
Opened
#17 Reneable GPU-AV
Opened
#18 #16 Doesn't work when shaders already define a push constant
Opened
#21 Vulkan RT: recursion depth hardcoded to 1, and the descriptor-heap AS-read workaround is never pushed for compute dispatches
Opened
#23 Dynamic descriptor_heap indexing faults the device in ray-tracing (closest-hit) shaders on NVIDIA
Opened
#25 WebGPU rayQuery TLAS traversal hardcodes leaf-start (16383) — picks always miss below 8193 instances
Opened
#27 Bloom / HDR post-process primitives for the WebGPU backend
Opened
#29 Smoke doesn't move
Opened
#30 Wavefront RT: atomic pixel accumulator to allow >1 ray per pixel per bounce
Opened
#32 Mouse scroll never reaches Input on native: Wayland PointerListenerHandleAxis is an empty stub, Win32 lacks WM_MOUSEWHEEL
Opened
#33 Vulkan: Mesh::BuildProcedural — AABB (procedural) BLAS build path to match WebGPU
Opened
#36 Accelration structure build options
Opened
#37 BuildProcedural: accept a device buffer as AABB build input (no host round-trip)
Opened
#40 [perf][HIGH] Frame-in-flight: per-frame fences + per-frame semaphores (remove per-frame vkQueueWaitIdle)
Opened
#41 [perf][MEDIUM] Single shared semaphore pair prevents multiple frames in flight
Opened
#42 [perf][LOW] Descriptor-heap bind recorded unconditionally every frame
Opened
#43 [perf][LOW] Invariant Vulkan structs rebuilt every frame
Opened
#44 [perf][LOW] CRAFTER_TIMING frame-time history uses erase(begin()) every frame
Opened
#45 [perf][LOW] Resize path: dead present-mode queries + presentModes vector
Opened
#46 [perf][HIGH] UI tiles scan the full item list — no spatial culling
Opened
#47 [perf][MEDIUM] Add DispatchFused (additive) to collapse consecutive UI passes to one load/store
Opened
#48 [perf][LOW] Narrow per-dispatch UI barrier to an image-subresource barrier (full removal: #47)
Opened
#49 [perf][LOW] nonuniformEXT on dynamically-uniform font slots (text shader)
Opened
#50 [perf][LOW] uiResolveScreenPixel runs clip-rect compares even when unclipped
Opened
#51 [perf][MEDIUM] Full 1 MiB font atlas re-upload on any single new glyph
Opened
#52 [perf][MEDIUM] Per-frame text re-shaping for static strings
Opened
#53 [perf][LOW] Ensure()+Lookup() do two hash-map probes per glyph
Opened
#54 [perf][MEDIUM] TransitionImageLayout hardcodes RAY_TRACING stage for all shader reads
Opened
#55 [robustness] Font atlas has no eviction/repack; ShelfPlace fails permanently once full
Opened
#56 [perf][LOW] InputField hit-test is O(n^2): re-measures whole prefix per char
Opened
#57 [perf][LOW] GetLineWidth/ScaleForSize recompute scale + per-glyph HMetrics uncached
Opened
#58 [perf][MEDIUM] Descriptor heaps force HOST_VISIBLE|DEVICE_LOCAL with no fallback
Opened
#59 [perf][LOW] GetMemoryType returns first match, no preferred/fallback distinction
Opened
#60 [perf][LOW] FlushDevice always flushes even on coherent memory
Opened
#61 [perf][LOW] Per-descriptor write flushes all numFrames heap copies whole-size
Opened
#62 [perf] Per-allocation vkAllocateMemory, no suballocator
Opened
#63 [perf] VulkanBuffer::Resize always destroys+reallocates
Opened
#64 [perf] TLAS instance/metadata buffers reallocated on instance-count change
Opened
#65 [perf][MEDIUM] TLAS instance buffer is HOST_VISIBLE, read directly as AS build input
Opened
#66 [perf] Per-mesh dedicated scratch buffer (VRAM waste)
Opened
#67 [perf] compressedStaging reallocated and kept per compressed Build
Opened
#68 [perf][LOW] Refit re-uploads immutable index buffer on UPDATE
Opened
#69 [perf][LOW] No VkPipelineCache passed to vkCreateComputePipelines
Opened
#70 [perf][LOW] Per-mip layout transitions issued one-at-a-time
Opened
#71 [perf][LOW] Compressed-asset Update re-Resizes both staging buffers every call
Opened
#72 [perf] RT shader binding table is HOST_VISIBLE, GPU-read every traceRays
Opened
#73 [perf] Mesh vertex/index/aabb are HOST_VISIBLE — place device-local (direct on ReBAR, staged otherwise)
Opened
#74 [perf] SaveFrame readback uses HOST_COHERENT (write-combined) — should be HOST_CACHED
Opened
#75 [perf] TLAS metadataBuffer is HOST_VISIBLE, CPU-written + shader-read every frame
Opened
#89 [perf] Runtime upload-strategy helper: direct HOST_VISIBLE|DEVICE_LOCAL vs staging (ReBAR-aware)
Opened
#101 [infra] Fence-keyed deferred resource-deletion queue (UAF since #40; unblocks #63/#66)
Opened
#110 MeshDecompressStagingRelease test fails on master: deletionQueue.size() != 1 after compressed Build
Opened
#113 [perf] No buffer suballocator — vkAllocateMemory per buffer (VulkanBuffer.cppm)
Opened
#114 [perf] Per-image dedicated alloc + leaked persistent staging buffer (ImageVulkan.cppm)
Opened
#115 [perf] Frame-loop barriers use ALL_COMMANDS scope (inter-pass + acquire/present) (Window.cpp)
Opened
#116 [perf] ReclaimDeletions compacts the whole deletion queue every frame (Device.cpp)
Opened
#117 [perf] Acquire/present barriers use ALL_COMMANDS scope (Window.cpp)
Opened
#118 [perf] TLAS instance+metadata upload: O(n) rebuild + whole-buffer flush every frame (RenderingElement3D.cpp)
Opened
#119 [perf] Mesh::Refit re-uploads the full vertex buffer every frame (Mesh.cpp)
Opened
#120 [perf] Staged UploadDeviceLocal allocates+frees a fresh staging buffer every call (VulkanBuffer.cppm)
Opened
#121 [perf] Per-frame whole-buffer flush of TLAS instance+metadata buffers (RenderingElement3D.cpp)
Opened
#122 [perf] ShapeText heap-allocates the cache-key std::string on every call, including hits (UI-Shared.cpp)
Opened
#123 [perf] shapedRuns_ eviction is all-or-nothing clear() at cap (UI-Shared.cpp)
Opened
#124 [perf] Single-lane serial stream compaction stalls 63/64 threads — use subgroup prefix-sum (ui-fused.comp.glsl)
Opened
#125 [perf] Hoist per-item/per-glyph loop-invariant math into shared memory at load (ui-images/text/fused)
Opened
#126 [perf] Per-glyph-constant SDF AA scale recomputed per pixel (ui-text.comp.glsl)
Opened
#127 [perf] Unconditional destination imageLoad/imageStore before early-out (ui-quads.comp.glsl)
Opened
#128 [perf] DrawInputField recomputes caret X via full-prefix walk every frame (InputField.cpp)
Opened
#129 [perf] FontAtlas dirty-rect uses one union bounding box (FontAtlas.cpp)
Opened
#130 [perf] WebGPU metadata flush uploads full 256 KB padded buffer every frame (RenderingElement3D-WebGPU.cpp)
Opened
#131 [perf] WebGPU GPU-owned instance runs upload one writeBuffer per element (RenderingElement3D-WebGPU.cpp)
Opened
#132 [perf] UIRenderer::Dispatch heap-allocates a std::vector per custom dispatch (UI-WebGPU.cpp)
Opened
#133 [perf] WebGPU full-buffer readback copies entire allocation even for a small prefix (WebGPUBuffer.cppm)
Opened
#134 [perf] Win32 StartSync busy-spins one core at 100% when not updating (Window.cpp)
Opened
#153 Vulkan validation errors: per-frame acquire-barrier dstAccessMask/stage mismatch + setup-path cmd-buffer/buffer lifecycle
Opened
#155 Measure peformance improvements