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