nx_gpu_capture_lib.nx source
↩ module page · 90 lines · 4702 B
1// Canonical JSON tuple: ["NXGT1","epoch","world-and-cast-render-pass",[nine counters],[[frame,"start","end","duration"],...]]
2// Counter order: observed, unavailable, attempted, completed, busy, failed, cancelled, inflight, result_dropped.
3// Sender sorts completed records by frame. No heap allocation or recursion; caller supplies policy and scratch.
4import "nx_gpu_timestamp_lib.nx"
5const GTC_COUNTERS: i64=9
6const GTC_SAFE_INTEGER: i64=9007199254740991
7const GTC_EPOCH_MAX: i64=64
8const GTC_SCHEMA: i64=-1
9const GTC_COVERAGE: i64=-2
10const GTC_INTERVAL: i64=-3
11const GTC_FRAME_ORDER: i64=-4
12const GTC_LIMIT: i64=-5
13func gtc_ws(b: *u8,n: i64,p: *i64) -> i64 {
14 while p[0]<n { let c: i64=b[p[0]] as i64; if c!=32 && c!=9 && c!=10 && c!=13 { break }; p[0]=p[0]+1 }; return 0
15}
16func gtc_ch(b: *u8,n: i64,p: *i64,c: i64) -> i64 {
17 gtc_ws(b,n,p); if p[0]>=n { return 0 }; if b[p[0]]!=c as u8 { return 0 }; p[0]=p[0]+1; return 1
18}
19// Canonical transport strings contain no escapes or control bytes. This is a schema constraint, not a general JSON decoder.
20func gtc_string(b: *u8,n: i64,p: *i64,span: *i64) -> i64 {
21 if gtc_ch(b,n,p,34)==0 { return 0 }; let s: i64=p[0]
22 while p[0]<n { let c: i64=b[p[0]] as i64; if c==34 { span[0]=s; span[1]=p[0]-s; p[0]=p[0]+1; return 1 }; if c<32 || c==92 || c>126 { return 0 }; p[0]=p[0]+1 }; return 0
23}
24func gtc_literal(b: *u8,n: i64,p: *i64,span: *i64,lit: *u8,ln: i64) -> i64 {
25 if gtc_string(b,n,p,span)==0 { return 0 }; if span[1]!=ln { return 0 }; var i: i64=0
26 while i<ln { if b[span[0]+i]!=lit[i] { return 0 }; i=i+1 }; return 1
27}
28func gtc_integer(b: *u8,n: i64,p: *i64,pair: *i64) -> i64 {
29 gtc_ws(b,n,p); let s: i64=p[0]
30 while p[0]<n { let c: i64=b[p[0]] as i64; if c<48 || c>57 { break }; p[0]=p[0]+1 }
31 if gts_u64(((b as i64)+s) as *u8,p[0]-s,pair)==0 { return -1 }
32 if pair[1]>GTC_SAFE_INTEGER/GTS_LIMB_BASE { return -1 }
33 let v: i64=pair[0]+pair[1]*GTS_LIMB_BASE
34 if v>GTC_SAFE_INTEGER { return -1 }; return v
35}
36// Scratch: cursor1 + span2 + timestamp span6 + limb6 + counters9 =24 words. Modified even on refusal.
37// Return record count >=0 on success; named negative verdict on failure. Body bytes are never modified.
38func gtc_validate(b: *u8,n: i64,max_rows: i64,scratch: *i64) -> i64 {
39 if n<0 || max_rows<0 { return GTC_LIMIT }
40 let p: *i64=scratch; p[0]=0
41 let span: *i64=((scratch as i64)+8) as *i64
42 let ts: *i64=((scratch as i64)+24) as *i64
43 let limbs: *i64=((scratch as i64)+72) as *i64
44 let counts: *i64=((scratch as i64)+120) as *i64
45 if gtc_ch(b,n,p,91)==0 { return GTC_SCHEMA }
46 if gtc_literal(b,n,p,span,"NXGT1" as *u8,5)==0 { return GTC_SCHEMA }
47 if gtc_ch(b,n,p,44)==0 { return GTC_SCHEMA }
48 if gtc_string(b,n,p,span)==0 { return GTC_SCHEMA }
49 if span[1]<1 || span[1]>GTC_EPOCH_MAX { return GTC_SCHEMA }
50 var i: i64=0
51 while i<span[1] { let c: i64=b[span[0]+i] as i64; if (c<97 || c>122) && (c<48 || c>57) && c!=45 && c!=95 { return GTC_SCHEMA }; i=i+1 }
52 if gtc_ch(b,n,p,44)==0 { return GTC_SCHEMA }
53 if gtc_literal(b,n,p,span,"world-and-cast-render-pass" as *u8,26)==0 { return GTC_SCHEMA }
54 if gtc_ch(b,n,p,44)==0 { return GTC_SCHEMA }
55 if gtc_ch(b,n,p,91)==0 { return GTC_SCHEMA }
56 i=0
57 while i<GTC_COUNTERS {
58 if i>0 { if gtc_ch(b,n,p,44)==0 { return GTC_SCHEMA } }
59 counts[i]=gtc_integer(b,n,p,limbs); if counts[i]<0 { return GTC_SCHEMA }; i=i+1
60 }
61 if gtc_ch(b,n,p,93)==0 { return GTC_SCHEMA }
62 if counts[0]!=counts[1]+counts[2] { return GTC_COVERAGE }
63 if counts[2]!=counts[3]+counts[4]+counts[5]+counts[6]+counts[7] { return GTC_COVERAGE }
64 if counts[8]>counts[3] { return GTC_COVERAGE }
65 if gtc_ch(b,n,p,44)==0 { return GTC_SCHEMA }
66 if gtc_ch(b,n,p,91)==0 { return GTC_SCHEMA }
67 var rows: i64=0; var previous: i64=-1
68 gtc_ws(b,n,p)
69 while p[0]<n {
70 if b[p[0]]==93 as u8 { break }
71 if rows>=max_rows { return GTC_LIMIT }
72 if rows>0 { if gtc_ch(b,n,p,44)==0 { return GTC_SCHEMA } }
73 if gtc_ch(b,n,p,91)==0 { return GTC_SCHEMA }
74 let frame: i64=gtc_integer(b,n,p,limbs)
75 if frame<0 { return GTC_SCHEMA }; if frame>=counts[0] { return GTC_COVERAGE }; if frame<=previous { return GTC_FRAME_ORDER }; previous=frame
76 i=0
77 while i<3 {
78 if gtc_ch(b,n,p,44)==0 { return GTC_SCHEMA }
79 if gtc_string(b,n,p,span)==0 { return GTC_SCHEMA }
80 ts[i*2]=span[0]; ts[i*2+1]=span[1]; i=i+1
81 }
82 if gtc_ch(b,n,p,93)==0 { return GTC_SCHEMA }
83 if gts_interval(((b as i64)+ts[0]) as *u8,ts[1],((b as i64)+ts[2]) as *u8,ts[3],((b as i64)+ts[4]) as *u8,ts[5],limbs)==0 { return GTC_INTERVAL }
84 rows=rows+1; gtc_ws(b,n,p)
85 }
86 if rows>counts[3]-counts[8] { return GTC_COVERAGE }
87 if gtc_ch(b,n,p,93)==0 { return GTC_SCHEMA }
88 if gtc_ch(b,n,p,93)==0 { return GTC_SCHEMA }
89 gtc_ws(b,n,p); if p[0]!=n { return GTC_SCHEMA }; return rows
90}