facett-map3d-flight/.nornir/assets/extrude-gpu.svg
<svg xmlns="http://www.w3.org/2000/svg" width="900" height="400" viewBox="0 0 900 400" font-family="monospace" font-size="12">
<rect width="900" height="400" fill="#0e1116"/>
<text x="20" y="30" fill="#e6edf3" font-size="15" font-weight="bold">facett-map3d-flight · GPU-compute building extrusion (roadmap §3b)</text>
<defs>
<marker id="a" markerWidth="9" markerHeight="9" refX="7" refY="3" orient="auto">
<path d="M0 0 L7 3 L0 6 z" fill="#6fd3f5"/>
</marker>
</defs>
<!-- marshaller pipeline -->
<g stroke="#6fd3f5" fill="#12313a">
<rect x="20" y="70" width="150" height="56" rx="6"/>
<rect x="215" y="70" width="190" height="56" rx="6"/>
<rect x="450" y="70" width="180" height="56" rx="6"/>
<rect x="675" y="70" width="200" height="56" rx="6"/>
</g>
<g fill="#e6edf3" text-anchor="middle">
<text x="95" y="92">Footprint[]</text><text x="95" y="110" fill="#8fb3c0">ring · height · min_h</text>
<text x="310" y="92">BuildingMarshal</text><text x="310" y="110" fill="#8fb3c0">contour · caps · Meta</text>
<text x="540" y="92">extrude.wgsl</text><text x="540" y="110" fill="#8fb3c0">cs_extrude · per-bldg</text>
<text x="775" y="92">Mesh3 + indirect draw</text><text x="775" y="110" fill="#8fb3c0">walls + caps · readback</text>
</g>
<g stroke="#6fd3f5" fill="none" marker-end="url(#a)">
<line x1="170" y1="98" x2="211" y2="98"/>
<line x1="405" y1="98" x2="446" y2="98"/>
<line x1="630" y1="98" x2="671" y2="98"/>
</g>
<!-- the two storage buffers + cap indexer -->
<rect x="215" y="160" width="415" height="86" rx="6" stroke="#f2b84b" fill="#2a2410"/>
<text x="422" y="182" fill="#f2b84b" text-anchor="middle" font-weight="bold">CPU marshalling (no geometry generated)</text>
<g fill="#e6edf3" text-anchor="middle" font-size="11">
<text x="422" y="204">contour: [f32;2] open+CCW rings · caps: u32 ear-clip indices</text>
<text x="422" y="222">BuildingMeta { vertex_start/count · cap_start/count · out bases ·</text>
<text x="422" y="238">height · min_height · building_type } (40 B, bytemuck::Pod)</text>
</g>
<line x1="310" y1="126" x2="360" y2="156" stroke="#f2b84b" fill="none" marker-end="url(#a)"/>
<!-- shared ear-clip reuse -->
<rect x="20" y="160" width="160" height="86" rx="6" stroke="#8fd39a" fill="#132a17"/>
<text x="100" y="184" fill="#8fd39a" text-anchor="middle" font-weight="bold">cap_triangulation</text>
<g fill="#e6edf3" text-anchor="middle" font-size="11">
<text x="100" y="206">facett-map3d §3a</text>
<text x="100" y="222">robust ear-clip</text>
<text x="100" y="238">(REUSED, one earcut)</text>
</g>
<line x1="180" y1="203" x2="211" y2="203" stroke="#8fd39a" fill="none" marker-end="url(#a)"/>
<!-- the compute op detail -->
<rect x="450" y="270" width="425" height="66" rx="6" stroke="#6fd3f5" fill="#12313a"/>
<text x="662" y="292" fill="#6fd3f5" text-anchor="middle" font-weight="bold">cs_extrude — per building, in parallel</text>
<g fill="#e6edf3" text-anchor="middle" font-size="11">
<text x="662" y="312">top ring (+Y) · bottom ring (−Y) · n wall quads (flat outward normal)</text>
<text x="662" y="328">6n verts · 4n−4 tris · caps from precomputed indices</text>
</g>
<line x1="540" y1="126" x2="600" y2="266" stroke="#6fd3f5" fill="none" marker-end="url(#a)"/>
<!-- oracle parity -->
<rect x="20" y="300" width="400" height="66" rx="6" stroke="#c98bdb" fill="#241030"/>
<text x="220" y="322" fill="#c98bdb" text-anchor="middle" font-weight="bold">oracle: extrude_prism_mesh (CPU, LANDED)</text>
<text x="220" y="342" fill="#8fb3c0" text-anchor="middle" font-size="11">RED-when-broken GPU-LESS: marshal + cpu_extrude == oracle</text>
<text x="220" y="358" fill="#8fb3c0" text-anchor="middle" font-size="11">GPU dispatch parity self-skips w/ sentinel when no adapter</text>
<text x="150" y="392" fill="#7f8b98" font-size="10">The CPU extrude path is untouched + stays the fallback (L2 additive); the marshaller reuses the one ear-clip (L5).</text>
</svg>