Skip to main content

cvkg_render_gpu/
lib.rs

1//! # CVKG Agentic Development Guidelines (v1.2)
2//!
3//! All AI agents contributing to this crate MUST follow ALL seven rules:
4//!
5//! ── Karpathy Guidelines (1–4) ────────────────────────────────────────────
6//! 1. THINK FIRST     — State assumptions. Surface ambiguity. Push back on complexity.
7//! 2. STAY SIMPLE     — Minimum code. No speculative features. No unasked-for abstractions.
8//! 3. BE SURGICAL     — Touch only what's required. Own your orphans. Don't improve neighbors.
9//! 4. VERIFY GOALS    — Turn tasks into checkable criteria. Loop until they pass. Never commit broken.
10//!
11//! ── CVKG Extended Protocols (5–7) ────────────────────────────────────────
12//! 5. TRIPLE-PASS     — Read the target, its surrounding context, and its full call graph
13//!                      at least THREE TIMES before making any edit or revision.
14//! 6. COMMENT ALL     — Every major pub fn, unsafe block, and non-trivial algorithm in
15//!                      every .rs/.ts/.h/.wgsl file MUST have a descriptive doc comment.
16//!                      Comments describe WHY and WHAT CONTRACT, not HOW mechanically.
17//! 7. MONITOR LOOPS   — Check every tool call / command for progress every 30 seconds.
18//!                      After 3 consecutive identical failures, stop, write BLOCKED.md,
19//!                      and move to unblocked work. Never silently accept a broken state.
20//!
21//! Sources:
22//!   Karpathy: https://github.com/multica-ai/andrej-karpathy-skills
23//!   CVKG Extended: Section 2 of the CVKG Design Specification
24#![allow(
25    clippy::type_complexity,
26    clippy::unwrap_or_default,
27    dead_code,
28    unused_variables,
29    unused_imports,
30    unused_mut,
31    unused_parens
32)]
33
34mod kvasir;
35mod material;
36
37// Re-export material types for downstream users
38pub use material::builtins;
39pub use material::{CompiledMaterial, MaterialCompiler, MaterialError, MaterialGraph, MaterialOp};
40
41pub mod accessibility;
42pub mod ai;
43mod api;
44mod draw;
45pub(crate) mod passes;
46pub mod pyramid;
47pub mod renderer;
48mod surtr_util;
49pub mod types;
50pub mod vertex;
51
52pub mod heim;
53pub use heim::SundrPacker;
54
55#[cfg(test)]
56mod tests {
57    use super::*;
58
59    use super::heim::SundrPacker;
60
61    #[test]
62    fn test_shelf_packer_basic() {
63        let mut packer = SundrPacker::new(100, 100);
64        assert_eq!(packer.pack(10, 10), Some((0, 0)));
65        assert_eq!(packer.pack(20, 15), Some((10, 0)));
66    }
67
68    #[test]
69    fn test_shelf_packer_wrap() {
70        let mut packer = SundrPacker::new(100, 100);
71        packer.pack(60, 10);
72        assert_eq!(packer.pack(50, 20), Some((0, 10)));
73    }
74
75    #[test]
76    fn test_parse_svg_animations() {
77        let svg = r##"
78            <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
79                <g id="spinner">
80                    <animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="2s" />
81                </g>
82                <circle id="pulse">
83                    <animate attributeName="opacity" from="0.5" to="1.0" dur="0.5s" />
84                </circle>
85                <!-- Edge cases: xlink:href, ms suffix, values list -->
86                <rect>
87                    <animate xlink:href="#myRect" attributeName="x" values="10; 20; 30" dur="500ms" />
88                </rect>
89            </svg>
90        "##;
91        let anims = draw::parse_svg_animations(svg.as_bytes());
92        assert_eq!(anims.len(), 3);
93
94        assert_eq!(anims[0].target_id, "spinner");
95        assert_eq!(anims[0].attribute_name, "transform");
96        assert_eq!(anims[0].duration, 2.0);
97        assert_eq!(anims[0].from_val, 0.0);
98        assert_eq!(anims[0].to_val, 360.0);
99
100        assert_eq!(anims[1].target_id, "pulse");
101        assert_eq!(anims[1].attribute_name, "opacity");
102        assert_eq!(anims[1].duration, 0.5);
103        assert_eq!(anims[1].from_val, 0.5);
104        assert_eq!(anims[1].to_val, 1.0);
105
106        assert_eq!(anims[2].target_id, "myRect");
107        assert_eq!(anims[2].attribute_name, "x");
108        assert_eq!(anims[2].duration, 0.5); // 500ms parsed as 0.5
109        assert_eq!(anims[2].from_val, 10.0);
110        assert_eq!(anims[2].to_val, 30.0);
111    }
112
113    #[test]
114    fn test_shelf_packer_full() {
115        let mut packer = SundrPacker::new(10, 10);
116        assert_eq!(packer.pack(11, 5), None);
117        assert_eq!(packer.pack(5, 11), None);
118    }
119}
120
121pub(crate) const WGSL_COMMON: &str = include_str!("shaders/common.wgsl");
122pub(crate) const WGSL_SHAPES: &str = include_str!("shaders/shapes.wgsl");
123pub(crate) const WGSL_MATERIAL_OPAQUE: &str = include_str!("shaders/material_opaque.wgsl");
124pub(crate) const WGSL_MATERIAL_GLASS: &str = include_str!("shaders/material_glass.wgsl");
125pub(crate) const WGSL_BIFROST: &str = include_str!("shaders/bifrost.wgsl");
126pub(crate) const WGSL_BLOOM: &str = include_str!("shaders/bloom.wgsl");
127pub(crate) const WGSL_COLOR_BLIND: &str = include_str!("shaders/color_blind.wgsl");
128pub(crate) const WGSL_TONEMAP: &str = include_str!("shaders/tonemap.wgsl");
129
130pub mod color_blindness;
131
132// Re-export ColorBlindMode for downstream users
133pub use color_blindness::ColorBlindMode;
134
135// ShieldWall — re-export AccessKit types so callers can build tree updates
136// without depending on accesskit directly.
137pub use accesskit::{
138    ActionHandler, ActionRequest, ActivationHandler, DeactivationHandler, Node, NodeId, Role, Tree,
139    TreeId, TreeUpdate,
140};
141pub use accesskit_winit::Adapter as ShieldWallAdapter;
142
143// Re-export ColorTheme and SceneUniforms for cvkg-render-gpu users
144pub use cvkg_core::{ColorTheme, SceneUniforms};
145
146pub use renderer::SurtrRenderer;
147pub use types::{SvgAnimation, SvgModel};
148pub use vertex::{InstanceData, Vertex};