1use {
2 std::{
3 collections::{BTreeMap, HashSet, HashMap},
4 cell::{Cell, RefCell},
5 },
6 crate::{
7 makepad_error_log::*,
8 makepad_live_compiler::*,
9 makepad_live_id::*,
10 shader_ast::*,
11 analyse::*,
12 shader_parser::{ShaderParser, ShaderParserDep},
13 builtin::{Builtin, generate_builtins},
14 }
15};
16
17
18pub struct ShaderRegistry {
19 pub all_fns: HashMap<FnPtr, FnDef>,
20 pub draw_shader_defs: HashMap<DrawShaderPtr, DrawShaderDef>,
21 pub structs: HashMap<StructPtr, StructDef>,
22 pub builtins: HashMap<Ident, Builtin>,
23 pub enums: HashMap<LiveType, ShaderEnum>,
24}
25
26pub struct ShaderEnum {
27 pub enum_name: LiveId,
28 pub variants: Vec<LiveId>
29}
30
31impl ShaderRegistry {
32 pub fn new() -> Self {
33 Self {
34 structs: HashMap::new(),
35 enums: HashMap::new(),
36 draw_shader_defs: HashMap::new(),
37 all_fns: HashMap::new(),
38 builtins: generate_builtins()
39 }
40 }
41}
42
43#[derive(Debug)]
44pub enum LiveNodeFindResult {
45 NotFound,
46 Component(LivePtr),
47 Struct(StructPtr),
48 Function(FnPtr),
49 PossibleStatic(StructPtr, FnPtr),
50 LiveValue(ValuePtr, TyLit),
51 Error(LiveError)
52}
53
54pub enum DrawShaderQuery {
55 DrawShader,
56 Geometry,
57}
58
59impl ShaderRegistry {
60
61 pub fn flush_registry(&mut self){
62 self.all_fns.clear();
63 self.draw_shader_defs.clear();
64 self.structs.clear();
65 }
66
67 pub fn register_enum(&mut self, live_type: LiveType, shader_enum: ShaderEnum) {
68 self.enums.insert(live_type, shader_enum);
69 }
70
71 pub fn compute_const_table(&self, draw_shader_ptr: DrawShaderPtr) -> DrawShaderConstTable {
72
73 let draw_shader_def = self.draw_shader_defs.get(&draw_shader_ptr).unwrap();
74
75 let mut offsets = BTreeMap::new();
76 let mut table = Vec::new();
77 let mut offset = 0;
78 let mut table_index = BTreeMap::new();
79
80 for callee in draw_shader_def.all_fns.borrow().iter() {
81 let fn_decl = self.all_fns.get(callee).unwrap();
82 let sub_table = fn_decl.const_table.borrow();
84 table.extend(sub_table.as_ref().unwrap().iter());
85
86 for ct_span in fn_decl.const_table_spans.borrow().as_ref().unwrap().iter() {
87 table_index.insert(
88 ct_span.token_id,
89 ConstTableItem {
90 offset: offset + ct_span.offset,
91 slots: ct_span.slots
92 }
93 );
94 }
95 offsets.insert(*callee, offset);
96 offset += sub_table.as_ref().unwrap().len();
97 }
98
99 let size = table.len();
100 let align_gap = 4 - (size - ((size >> 2) << 2));
101 for _ in 0..align_gap {
102 table.push(0.0);
103 }
104 DrawShaderConstTable {
105 table,
106 offsets,
107 table_index
108 }
109 }
110
111 pub fn fn_ident_from_ptr(&self, live_registry: &LiveRegistry, fn_node_ptr: FnPtr) -> Ident {
112 let node = live_registry.ptr_to_node(fn_node_ptr.0);
113 Ident(node.id)
114 }
115
116 pub fn draw_shader_method_ptr_from_ident(&self, draw_shader_def: &DrawShaderDef, ident: Ident) -> Option<FnPtr> {
117 for fn_node_ptr in &draw_shader_def.methods {
118 let fn_decl = self.all_fns.get(fn_node_ptr).unwrap();
119 if fn_decl.ident == ident {
120 return Some(*fn_node_ptr);
121 }
122 }
123 None
124 }
125
126 pub fn struct_method_ptr_from_ident(&self, struct_def: &StructDef, ident: Ident) -> Option<FnPtr> {
127 for fn_node_ptr in &struct_def.methods {
128 let fn_decl = self.all_fns.get(fn_node_ptr).unwrap();
129 if fn_decl.ident == ident {
130 return Some(*fn_node_ptr);
131 }
132 }
133 None
134 }
135
136 pub fn draw_shader_method_decl_from_ident(&self, draw_shader_def: &DrawShaderDef, ident: Ident) -> Option<&FnDef> {
137 for fn_node_ptr in &draw_shader_def.methods {
138 let fn_decl = self.all_fns.get(fn_node_ptr).unwrap();
139 if fn_decl.ident == ident {
140 return Some(fn_decl)
141 }
142 }
143 None
144 }
145
146 pub fn struct_method_decl_from_ident(&self, struct_def: &StructDef, ident: Ident) -> Option<&FnDef> {
147 for fn_node_ptr in &struct_def.methods {
148 let fn_decl = self.all_fns.get(fn_node_ptr).unwrap();
149 if fn_decl.ident == ident {
150 return Some(fn_decl)
151 }
152 }
153 None
154 }
155
156 pub fn find_live_node_by_path(&self, live_registry: &LiveRegistry, base_ptr: LivePtr, ids: &[LiveId]) -> LiveNodeFindResult {
157
158 let doc = &live_registry.ptr_to_doc(base_ptr);
159
160 let ret = walk_recur(live_registry, None, base_ptr.file_id, base_ptr.generation, base_ptr.index as usize, &doc.nodes, ids);
161 return ret;
162 fn walk_recur(live_registry: &LiveRegistry, struct_ptr: Option<LivePtr>, file_id: LiveFileId, generation:LiveFileGeneration, index: usize, nodes: &[LiveNode], ids: &[LiveId]) -> LiveNodeFindResult {
164 let node = &nodes[index];
165
166 if ids.len() != 0 && !node.value.is_class() && !node.value.is_clone() && !node.value.is_object() {
167 return LiveNodeFindResult::NotFound;
168 }
169
170 let now_ptr = LivePtr {file_id, index: index as u32, generation};
171 match node.value {
173 LiveValue::Bool(_) => {
174 return LiveNodeFindResult::LiveValue(ValuePtr(now_ptr), TyLit::Bool)
175 },
176 LiveValue::Int64(_)=> {
177 return LiveNodeFindResult::LiveValue(ValuePtr(now_ptr), TyLit::Int)
178 }
179 LiveValue::Float32(_) => {
180 return LiveNodeFindResult::LiveValue(ValuePtr(now_ptr), TyLit::Float)
181 }
182 LiveValue::Float64(_) => {
183 return LiveNodeFindResult::LiveValue(ValuePtr(now_ptr), TyLit::Float)
184 }
185 LiveValue::Color(_) => {
186 return LiveNodeFindResult::LiveValue(ValuePtr(now_ptr), TyLit::Vec4)
187 }
188 LiveValue::Vec2(_) => {
189 return LiveNodeFindResult::LiveValue(ValuePtr(now_ptr), TyLit::Vec2)
190 }
191 LiveValue::Vec3(_) => {
192 return LiveNodeFindResult::LiveValue(ValuePtr(now_ptr), TyLit::Vec3)
193 }
194 LiveValue::Vec4(_) => {
195 return LiveNodeFindResult::LiveValue(ValuePtr(now_ptr), TyLit::Vec4)
196 }
197 LiveValue::Expr{..} => {
198 match live_eval(live_registry, index, &mut (index + 1), nodes){
200 Ok(value) => {
201 if let Some(ty) = Ty::from_live_eval(value){
202 if let Some(ty_lit) = ty.maybe_ty_lit(){
203 return LiveNodeFindResult::LiveValue(ValuePtr(now_ptr), ty_lit)
204 }
205 }
206 return LiveNodeFindResult::Error(
207 LiveError {
208 origin: live_error_origin!(),
209 message: format!("Type of eval result not valid for shader"),
210 span: nodes[index].origin.token_id().unwrap().into()
211 }
212 );
213 }
214 Err(err)=>{
215 error!("Cannot find node in expression");
216 return LiveNodeFindResult::Error(err)
217 }
218 }
219 }
220 LiveValue::DSL {token_start, ..} => {
221 let origin_doc = live_registry.token_id_to_origin_doc(node.origin.token_id().unwrap());
223 match origin_doc.tokens[token_start as usize].token {
224 LiveToken::Ident(live_id!(fn)) => {
225 if let Some(struct_ptr) = struct_ptr {
226 return LiveNodeFindResult::PossibleStatic(StructPtr(struct_ptr), FnPtr(now_ptr));
227 }
228 return LiveNodeFindResult::Function(FnPtr(now_ptr));
229 }
230 _ => LiveNodeFindResult::NotFound
231 }
232 }
233 LiveValue::Class {..} => {
234 if ids.len() == 0 {
235 return LiveNodeFindResult::Component(now_ptr);
236 }
237 match nodes.child_by_name(index, ids[0].as_instance()) {
238 Some(child_index) => {
239 return walk_recur(live_registry, None, file_id, generation, child_index, nodes, &ids[1..])
240 }
241 None => {
242 return LiveNodeFindResult::NotFound;
243 }
244 }
245 }
246 LiveValue::Clone(clone) => {
247 if ids.len() == 0 {
248 if clone == live_id!(struct) {
249 return LiveNodeFindResult::Struct(StructPtr(now_ptr));
250 }
251 return LiveNodeFindResult::Component(now_ptr);
252 }
253 match nodes.child_by_name(index, ids[0].as_instance()) {
254 Some(child_index) => {
255 let struct_ptr = if clone == live_id!(struct) {
256 Some(now_ptr)
257 }
258 else {
259 None
260 };
261 return walk_recur(live_registry, struct_ptr, file_id, generation, child_index, nodes, &ids[1..])
262 }
263 None => {
264 return LiveNodeFindResult::NotFound;
265 }
266 }
267 }
268 LiveValue::Object => {
269 if ids.len() == 0 {
270 return LiveNodeFindResult::NotFound;
271 }
272 match nodes.child_by_name(index, ids[0].as_instance()) {
273 Some(child_index) => {
274 return walk_recur(live_registry, None, file_id, generation, child_index, nodes, &ids[1..])
275 }
276 None => {
277 return LiveNodeFindResult::NotFound;
278 }
279 }
280 }
281 _ => {
282 return LiveNodeFindResult::NotFound;
283 }
284 }
285 }
286 }
287
288 pub fn analyse_deps(&mut self, live_registry: &LiveRegistry, deps: &[ShaderParserDep]) -> Result<(), LiveError> {
289 for dep in deps {
291 match dep {
292 ShaderParserDep::Struct(dep) => {
296 self.analyse_struct(live_registry, *dep) ?;
297 },
298 ShaderParserDep::Function(struct_ptr, fn_ptr) => {
299 self.analyse_plain_fn(live_registry, *struct_ptr, *fn_ptr) ?
300 }
301 }
302 }
303 Ok(())
304 }
305
306
307 pub fn analyse_plain_fn(&mut self, live_registry: &LiveRegistry, struct_ptr: Option<StructPtr>, fn_ptr: FnPtr) -> Result<(), LiveError> {
309
310 if self.all_fns.get(&fn_ptr).is_some() {
311 return Ok(());
312 }
313 let fn_node = live_registry.ptr_to_node(fn_ptr.0);
315 match fn_node.value {
316 LiveValue::DSL {token_start, token_count, expand_index} => {
317 let id = fn_node.id;
318 let mut parser_deps = Vec::new();
319 let origin_doc = &live_registry.token_id_to_origin_doc(fn_node.origin.token_id().unwrap());
321
322 let parser = ShaderParser::new(
323 live_registry,
324 self,
325 origin_doc.get_tokens(token_start as usize, token_count as usize),
326 &mut parser_deps,
327 if let Some(struct_ptr) = struct_ptr {Some(FnSelfKind::Struct(struct_ptr))}else {None},
328 expand_index.unwrap() as usize,
329 fn_node.origin.token_id().unwrap().file_id().unwrap(),
330 token_start as usize
331 );
333
334 let fn_def = parser.expect_plain_fn_def(
335 fn_ptr,
336 Ident(id),
337 ) ?;
338 self.all_fns.insert(fn_ptr, fn_def);
339
340 self.analyse_deps(live_registry, &parser_deps) ?;
341
342 let mut fa = FnDefAnalyser {
344 live_registry,
345 closure_return_ty: None,
346 fn_def: self.all_fns.get(&fn_ptr).unwrap(),
347 scopes: &mut Scopes::new(),
348 shader_registry: self,
349 is_inside_loop: false,
350 options: ShaderAnalyseOptions {
351 no_const_collapse: true
352 }
353 };
354 fa.analyse_fn_decl() ?;
355 fa.analyse_fn_def() ?;
356
357 Ok(())
358 }
359 _ => panic!()
360 }
361 }
362
363
364 pub fn analyse_struct(&mut self, live_registry: &LiveRegistry, struct_ptr: StructPtr) -> Result<(), LiveError> {
366
367 if self.structs.get(&struct_ptr).is_some() {
368 return Ok(());
369 }
370
371 let (doc, struct_node) = live_registry.ptr_to_doc_node(struct_ptr.0);
372
373 match struct_node.value {
374 LiveValue::Clone(clone) => {
375 if clone != live_id!(struct) {
376 panic!()
377 }
378 let mut struct_def = StructDef {
379 span: struct_node.origin.token_id().unwrap().into(),
380 struct_refs: RefCell::new(None),
381 fields: Vec::new(),
382 methods: Vec::new()
383 };
384
385 let mut parser_deps = Vec::new();
386
387 let mut node_iter = doc.nodes.first_child(struct_ptr.node_index());
389 while let Some(node_index) = node_iter {
390 let prop_ptr = struct_ptr.with_index(node_index);
391 let prop = &doc.nodes[node_index];
392
393 match prop.value {
394 LiveValue::DSL {token_start, token_count, expand_index} => {
395 let id = prop.id;
396 let origin_doc = &live_registry.token_id_to_origin_doc(prop.origin.token_id().unwrap());
397
398 let parser = ShaderParser::new(
399 live_registry,
400 self,
401 origin_doc.get_tokens(token_start as usize, token_count as usize),
402 &mut parser_deps,
403 Some(FnSelfKind::Struct(struct_ptr)),
404 expand_index.unwrap() as usize,
405 prop.origin.token_id().unwrap().file_id().unwrap(),
406 token_start as usize
407 );
409 match origin_doc.tokens[token_start as usize].token {
410 LiveToken::Ident(live_id!(fn)) => {
411
412 let fn_def = parser.expect_method_def(
413 FnPtr(prop_ptr),
414 Ident(id),
415 ) ?;
416 if let Some(fn_def) = fn_def {
420 struct_def.methods.push(fn_def.fn_ptr);
421 self.all_fns.insert(fn_def.fn_ptr, fn_def);
422 }
423 }
424 _ => {
425 return Err(LiveError {
426 origin: live_error_origin!(),
427 span: prop.origin.token_id().unwrap().into(),
428 message: format!("Unexpected DSL node")
429 })
430 }
436 }
437 },
438 LiveValue::Id(type_name) if live_registry.get_node_prefix(prop.origin) == Some(live_id!(field)) => {
439 if let Some(ty_lit) = TyLit::from_id(type_name) {
442 struct_def.fields.push(StructFieldDef {
443 var_def_ptr: VarDefPtr(prop_ptr),
444 span:prop.origin.token_id().unwrap().into(),
445 ident: Ident(prop.id),
446 ty_expr: ty_lit.to_ty().to_ty_expr()
447 })
448 }
449 else {
450 return Err(LiveError {
452 origin: live_error_origin!(),
453 span: prop.origin.token_id().unwrap().into(),
454 message: format!("Type not found for struct field {}", type_name)
455 })
456 }
457 },
458 _ => {
459 return Err(LiveError {
460 origin: live_error_origin!(),
461 span: prop.origin.token_id().unwrap().into(),
462 message: format!("Cannot use {:?} in struct", prop.value)
463 })
464 }
465 }
466 node_iter = doc.nodes.next_child(node_index);
467 }
468 self.structs.insert(struct_ptr, struct_def);
470
471 self.analyse_deps(live_registry, &parser_deps) ?;
472
473 let mut sa = StructAnalyser {
475 live_registry,
476 struct_def: self.structs.get(&struct_ptr).unwrap(),
477 scopes: &mut Scopes::new(),
478 shader_registry: self,
479 options: ShaderAnalyseOptions {
480 no_const_collapse: true
481 }
482 };
483 sa.analyse_struct() ?;
484 }
487 _ => ()
488 }
489
490 Ok(())
491 }
492
493 pub fn analyse_draw_shader<F>(&mut self, live_registry: &LiveRegistry, draw_shader_ptr: DrawShaderPtr, mut ext_self: F) -> Result<(),
495 LiveError>
496 where F: FnMut(&LiveRegistry, &ShaderRegistry, TokenSpan, DrawShaderQuery, LiveType, &mut DrawShaderDef)
497 {
498 let mut draw_shader_def = DrawShaderDef::default();
499
500 draw_shader_def.add_uniform(id_lut!(camera_projection), id_lut!(pass), Ty::Mat4, TokenSpan::default());
502 draw_shader_def.add_uniform(id_lut!(camera_view), id_lut!(pass), Ty::Mat4, TokenSpan::default());
503 draw_shader_def.add_uniform(id_lut!(camera_inv), id_lut!(pass), Ty::Mat4, TokenSpan::default());
504 draw_shader_def.add_uniform(id_lut!(dpi_factor), id_lut!(pass), Ty::Float, TokenSpan::default());
505 draw_shader_def.add_uniform(id_lut!(dpi_dilate), id_lut!(pass), Ty::Float, TokenSpan::default());
506 draw_shader_def.add_uniform(id_lut!(time), id_lut!(pass), Ty::Float, TokenSpan::default());
507 draw_shader_def.add_uniform(id_lut!(view_transform), id_lut!(view), Ty::Mat4, TokenSpan::default());
508 draw_shader_def.add_uniform(id_lut!(draw_zbias), id_lut!(draw), Ty::Float, TokenSpan::default());
509
510 let (doc, class_node) = live_registry.ptr_to_doc_node(draw_shader_ptr.0);
511
512 match &class_node.value {
513 LiveValue::Class {live_type, ..} => {
514
515 ext_self(
516 live_registry,
517 self,
518 class_node.origin.token_id().unwrap().into(),
519 DrawShaderQuery::DrawShader,
520 *live_type,
521 &mut draw_shader_def
522 );
523
524 let mut parser_deps = Vec::new();
525
526 let mut node_iter = doc.nodes.first_child(draw_shader_ptr.node_index());
527 let mut method_set = HashSet::new();
528 while let Some(node_index) = node_iter {
529 let prop = &doc.nodes[node_index];
530 let prop_ptr = draw_shader_ptr.with_index(node_index);
531 if prop.id == live_id!(debug_id){
532 node_iter = doc.nodes.next_child(node_index);
533 continue;
534 }
535 match prop.value {
536 LiveValue::Bool(_) |
537 LiveValue::Id(_) |
538 LiveValue::Int64(_) |
539 LiveValue::Float32(_) |
540 LiveValue::Float64(_) |
541 LiveValue::Color(_) |
542 LiveValue::Vec2(_) |
543 LiveValue::Vec3(_) |
544 LiveValue::Vec4(_) |
545 LiveValue::Expr{..} => {
546 if prop.origin.prop_type() != LivePropType::Field{
548 return Err(LiveError {
553 origin: live_error_origin!(),
554 span: prop.origin.token_id().unwrap().into(),
555 message: format!("Can only support field colon : values don't use =")
556 })
557 }
558 if prop.id == live_id!(size){
559
560 }
561 let first_def = prop.origin.first_def().unwrap();
562 let before = live_registry.get_node_prefix(prop.origin);
563
564 let ty = match ShaderTy::from_live_node(live_registry, node_index, &doc.nodes){
565 Ok(ty)=>ty,
566 Err(_)=>{
567 node_iter = doc.nodes.next_child(node_index);
569 continue;
570 }
572 };
573 let ty_expr = ty.to_ty_expr();
574 match before {
575 Some(live_id!(geometry)) => {
576 draw_shader_def.fields.push(DrawShaderFieldDef {
577 kind: DrawShaderFieldKind::Geometry {
578 is_used_in_pixel_shader: Cell::new(false),
579 var_def_ptr: Some(VarDefPtr(prop_ptr)),
580 },
581 span: first_def.into(),
582 ident: Ident(prop.id),
583 ty_expr
584 });
585 },
586 Some(live_id!(instance)) => {
587 let decl = DrawShaderFieldDef {
588 kind: DrawShaderFieldKind::Instance {
589 is_used_in_pixel_shader: Cell::new(false),
590 live_field_kind: LiveFieldKind::Live,
591 var_def_ptr: Some(VarDefPtr(prop_ptr)),
592 },
593 span: first_def.into(),
594 ident: Ident(prop.id),
595 ty_expr
596 };
597 if let Some(index) = draw_shader_def.fields.iter().position( | field | {
600 if let DrawShaderFieldKind::Instance {var_def_ptr, ..} = field.kind {
601 if var_def_ptr.is_none() {
602 return true
603 }
604 }
605 false
606 }) {
607 draw_shader_def.fields.insert(index, decl);
608 }
609 else {
610 draw_shader_def.fields.push(decl);
611 }
612
613 },
614 Some(live_id!(uniform)) => {
615 draw_shader_def.fields.push(DrawShaderFieldDef {
616 kind: DrawShaderFieldKind::Uniform {
617 var_def_ptr: Some(VarDefPtr(prop_ptr)),
618 block_ident: Ident(live_id!(user)),
619 },
620 span: first_def.into(),
621 ident: Ident(prop.id),
622 ty_expr
623 });
624 },
625 Some(live_id!(varying)) => {
626 draw_shader_def.fields.push(DrawShaderFieldDef {
627 kind: DrawShaderFieldKind::Varying {
628 var_def_ptr: VarDefPtr(prop_ptr),
629 },
630 span: first_def.into(),
631 ident: Ident(prop.id),
632 ty_expr
633 });
634 },
635 Some(live_id!(texture)) => {
636 draw_shader_def.fields.push(DrawShaderFieldDef {
637 kind: DrawShaderFieldKind::Texture {
638 var_def_ptr: Some(VarDefPtr(prop_ptr)),
639 },
640 span: first_def.into(),
641 ident: Ident(prop.id),
642 ty_expr
643 });
644 }
645 None => {
646 if let LiveValue::Bool(val) = prop.value {
647 match prop.id {
648 live_id!(debug) => {
649 draw_shader_def.flags.debug = val;
650 }
651 live_id!(draw_call_compare) => {
652 draw_shader_def.flags.draw_call_nocompare = val;
653 }
654 live_id!(draw_call_always) => {
655 draw_shader_def.flags.draw_call_always = val;
656 }
657 _ => {} }
659 }
660 },
661 _ => {
662 return Err(LiveError {
663 origin: live_error_origin!(),
664 span: first_def.into(),
665 message: format!("Unexpected variable prefix {:?}", before)
666 })
667 }
668 };
669 }
670 LiveValue::Class {live_type, ..} => {
671 if prop.id == live_id!(geometry) {
672 ext_self(
673 live_registry,
674 self,
675 prop.origin.token_id().unwrap().into(),
676 DrawShaderQuery::Geometry,
677 live_type,
678 &mut draw_shader_def
679 );
680 }
681 }
682 LiveValue::DSL {token_start, token_count, expand_index} => {
683 let origin_doc = live_registry.token_id_to_origin_doc(prop.origin.token_id().unwrap());
684
685 let parser = ShaderParser::new(
686 live_registry,
687 self,
688 origin_doc.get_tokens(token_start as usize, token_count as usize),
689 &mut parser_deps,
690 Some(FnSelfKind::DrawShader(draw_shader_ptr)),
691 expand_index.unwrap() as usize,
692 prop.origin.token_id().unwrap().file_id().unwrap(),
693 token_start as usize
694 );
696
697 let token = &origin_doc.tokens[token_start as usize];
698 match token.token {
699 LiveToken::Ident(live_id!(fn)) => {
700 let fn_def = parser.expect_method_def(
701 FnPtr(prop_ptr),
702 Ident(prop.id),
703 ) ?;
704 if let Some(fn_def) = fn_def {
705 method_set.insert(prop.id);
706 draw_shader_def.methods.push(fn_def.fn_ptr);
707 self.all_fns.insert(fn_def.fn_ptr, fn_def);
708 }
709 }
710 _ => {
711 return Err(LiveError {
712 origin: live_error_origin!(),
713 span: token.span.into(),
714 message: format!("Unexpected in shader body {}", token)
715 })
716 }
744 }
745
746 },
747 _ => ()
748 }
749 node_iter = doc.nodes.next_child(node_index);
750 }
751 for i in 0..draw_shader_def.fields.len() {
753 for j in (i + 1)..draw_shader_def.fields.len() {
754 let field_a = &draw_shader_def.fields[i];
755 let field_b = &draw_shader_def.fields[j];
756 if field_a.ident == field_b.ident && !field_a.ident.0.is_empty() {
757 return Err(LiveError {
761 origin: live_error_origin!(),
762 span: field_a.span.into(),
763 message: format!("Field double declaration {}",field_a.ident)
764 })
765 }
766 }
767 }
768
769 self.draw_shader_defs.insert(draw_shader_ptr, draw_shader_def);
770
771 if !method_set.contains(&live_id!(vertex)) {
772 return Err(LiveError {
773 origin: live_error_origin!(),
774 span: class_node.origin.token_id().unwrap().into(),
775 message: format!("analyse_draw_shader missing vertex method")
776 })
777 }
778
779 if !method_set.contains(&live_id!(pixel)) {
780 return Err(LiveError {
781 origin: live_error_origin!(),
782 span: class_node.origin.token_id().unwrap().into(),
783 message: format!("analyse_draw_shader missing pixel method")
784 })
785 }
786
787 self.analyse_deps(live_registry, &parser_deps) ?;
788
789 let draw_shader_def = self.draw_shader_defs.get(&draw_shader_ptr).unwrap();
790 let mut sa = DrawShaderAnalyser {
791 live_registry,
792 shader_registry: self,
793 draw_shader_def: draw_shader_def,
794 scopes: &mut Scopes::new(),
795 options: ShaderAnalyseOptions {
796 no_const_collapse: true
797 }
798 };
799 sa.analyse_shader() ?;
800 return Ok(())
802 }
803 x => return Err(LiveError {
804 origin: live_error_origin!(),
805 span: class_node.origin.token_id().unwrap().into(),
806 message: format!("analyse_draw_shader could not find shader class {:?}", x)
807 })
808 }
809 }
810
811}