1use {
2 crate::{
3 makepad_live_compiler::{
4 LiveRegistry,
5 TokenSpan,
6 LivePtr,
7 LiveValue,
8 LiveTypeInfo,
9 LiveFieldKind,
10 LiveModuleId,
11 LiveType,
12 LiveNode,
13 LiveNodeSliceApi
14 },
15 makepad_live_tokenizer::{LiveErrorOrigin, live_error_origin},
16 makepad_shader_compiler::*,
17 makepad_live_id::*,
18 makepad_math::*,
19 cx::Cx,
20 texture::{Texture},
21 geometry::GeometryId,
22 area::Area,
23 geometry::{GeometryFields},
24 live_traits::*,
25 draw_shader::*
26 },
27};
28
29#[cfg(any(target_arch = "wasm32", target_os="android", target_os="linux"))]
37pub const fn shader_enum(i: u32) -> u32 {
38 match i {
39 1 => 0x3f800000,
40 2 => 0x40000000,
41 3 => 0x40400000,
42 4 => 0x40800000,
43 5 => 0x40a00000,
44 6 => 0x40c00000,
45 7 => 0x40e00000,
46 8 => 0x41000000,
47 9 => 0x41100000,
48 10 => 0x41200000,
49 11 => 0x41300000,
50 12 => 0x41400000,
51 13 => 0x41500000,
52 14 => 0x41600000,
53 15 => 0x41700000,
54 16 => 0x41800000,
55 17 => 0x41880000,
56 18 => 0x41900000,
57 19 => 0x41980000,
58 20 => 0x41a00000,
59 21 => 0x41a80000,
60 22 => 0x41b00000,
61 23 => 0x41b80000,
62 24 => 0x41c00000,
63 25 => 0x41c80000,
64 26 => 0x41d00000,
65 27 => 0x41d80000,
66 28 => 0x41e00000,
67 29 => 0x41e80000,
68 30 => 0x41f00000,
69 31 => 0x41f80000,
70 _ => panic!()
71 }
72}
73
74#[cfg(not(any(target_arch = "wasm32", target_os="android", target_os="linux")))]
75pub const fn shader_enum(i: u32) -> u32 {
76 if i<1 || i > 31 {
77 panic!();
78 }
79 i
80}
81
82pub const DRAW_CALL_USER_UNIFORMS: usize = 256;
83pub const DRAW_CALL_TEXTURE_SLOTS: usize = 4;
84pub const DRAW_CALL_VAR_INSTANCES: usize = 32;
85
86#[derive(Clone)]
87#[repr(C)]
88pub struct DrawVars {
89 pub area: Area,
90 pub (crate) var_instance_start: usize,
91 pub (crate) var_instance_slots: usize,
92 pub (crate) options: CxDrawShaderOptions,
93 pub draw_shader: Option<DrawShader>,
94 pub (crate) geometry_id: Option<GeometryId>,
95 pub user_uniforms: [f32; DRAW_CALL_USER_UNIFORMS],
96 pub texture_slots: [Option<Texture>; DRAW_CALL_TEXTURE_SLOTS],
97 pub var_instances: [f32; DRAW_CALL_VAR_INSTANCES]
98}
99
100impl Default for DrawVars{
101 fn default()->Self{
102 Self{
103 area: Default::default(),
104 var_instance_start: Default::default(),
105 var_instance_slots: Default::default(),
106 options: Default::default(),
107 draw_shader: Default::default(),
108 geometry_id: Default::default(),
109 user_uniforms: [0f32; DRAW_CALL_USER_UNIFORMS],
110 texture_slots: Default::default(),
111 var_instances: [0f32; DRAW_CALL_VAR_INSTANCES]
112 }
113 }
114}
115
116impl LiveHookDeref for DrawVars{}
117
118impl LiveNew for DrawVars {
119 fn new(_cx: &mut Cx) -> Self {
120 Self::default()
121 }
122
123 fn live_type_info(_cx: &mut Cx) -> LiveTypeInfo {
124 LiveTypeInfo {
125 module_id: LiveModuleId::from_str(&module_path!()).unwrap(),
126 live_type: std::any::TypeId::of::<Self>(),
127 live_ignore: true,
128 fields: Vec::new(),
129 type_name: id_lut!(DrawVars)
130 }
131 }
132}
133
134impl LiveApply for DrawVars {
135 fn apply(&mut self, _cx: &mut Cx, _applyl: &mut Apply, _index: usize, _nodes: &[LiveNode]) -> usize {
136 panic!()
137 }
138}
139
140impl LiveApplyReset for DrawVars {
141 fn apply_reset(&mut self, _cx: &mut Cx, _applyl: &mut Apply, _index: usize, _nodes: &[LiveNode]) {
142 }
144}
145
146impl LiveHook for DrawVars {}
147
148impl DrawVars {
149
150 pub fn set_texture(&mut self, slot: usize, texture: &Texture) {
151 self.texture_slots[slot] = Some(texture.clone());
152 }
153
154 pub fn empty_texture(&mut self, slot: usize) {
155 self.texture_slots[slot] = None;
156 }
157
158 pub fn redraw(&self, cx: &mut Cx) {
159 self.area.redraw(cx);
160 }
161
162 pub fn area(&self) -> Area {
163 self.area
164 }
165
166 pub fn can_instance(&self) -> bool {
167 self.draw_shader.is_some()
168 }
169
170 pub fn as_slice<'a>(&'a self) -> &'a [f32] {
171 unsafe {
172 std::slice::from_raw_parts((&self.var_instances[self.var_instance_start - 1] as *const _ as *const f32).offset(1), self.var_instance_slots)
173 }
174 }
175
176 pub fn init_shader(&mut self, cx: &mut Cx, apply: &mut Apply, draw_shader_ptr: DrawShaderPtr, geometry_fields: &dyn GeometryFields) {
177 self.draw_shader = None;
178
179 if cx.draw_shaders.error_set.contains(&draw_shader_ptr) {
180 return
181 }
182
183 if let Some(item) = cx.draw_shaders.ptr_to_item.get(&draw_shader_ptr) {
184 self.draw_shader = Some(DrawShader {
185 draw_shader_generation: cx.draw_shaders.generation,
186 draw_shader_ptr,
187 draw_shader_id: item.draw_shader_id
188 });
189 self.options = item.options.clone();
190 }
191 else {
192 let fingerprint = DrawShaderFingerprint::from_ptr(cx, draw_shader_ptr);
194
195 if let Some(fp) = cx.draw_shaders.fingerprints.iter().find( | fp | fp.fingerprint == fingerprint) {
197 self.options = CxDrawShaderOptions::from_ptr(cx, draw_shader_ptr);
198 cx.draw_shaders.ptr_to_item.insert(draw_shader_ptr, CxDrawShaderItem {
199 draw_shader_id: fp.draw_shader_id,
200 options: self.options.clone()
201 });
202 self.draw_shader = Some(DrawShader {
203 draw_shader_generation: cx.draw_shaders.generation,
204 draw_shader_ptr,
205 draw_shader_id: fp.draw_shader_id
206 });
207 return;
208 }
209
210 if cx.draw_shaders.error_fingerprints.iter().find( | fp | **fp == fingerprint).is_some() {
212 return;
213 }
214
215 fn live_type_to_shader_ty(live_type: LiveType) -> Option<ShaderTy> {
216 if live_type == LiveType::of::<f32>() {Some(ShaderTy::Float)}
217 else if live_type == LiveType::of::<Vec2>() {Some(ShaderTy::Vec2)}
218 else if live_type == LiveType::of::<Vec3>() {Some(ShaderTy::Vec3)}
219 else if live_type == LiveType::of::<Vec4>() {Some(ShaderTy::Vec4)}
220 else if live_type == LiveType::of::<Mat4>() {Some(ShaderTy::Mat4)}
221 else {None}
222 }
223 let live_registry_cp = cx.live_registry.clone();
226 let live_registry = live_registry_cp.borrow();
227
228 let result = cx.shader_registry.analyse_draw_shader(&live_registry, draw_shader_ptr, | live_registry, shader_registry, span, draw_shader_query, live_type, draw_shader_def | {
229 match draw_shader_query {
230 DrawShaderQuery::DrawShader => {
231 fn recur_expand(
232 live_registry: &LiveRegistry,
233 shader_registry: &ShaderRegistry,
234 level: usize,
235 after_draw_vars: &mut bool,
236 live_type: LiveType,
237 draw_shader_def: &mut DrawShaderDef,
238 span: TokenSpan
239 ) {
240 if let Some(lf) = live_registry.live_type_infos.get(&live_type) {
241
242 let mut slots = 0;
243 for field in &lf.fields {
244 if let LiveFieldKind::Deref = field.live_field_kind {
245 if field.live_type_info.live_type != LiveType::of::<DrawVars>() {
246 recur_expand(live_registry, shader_registry, level + 1, after_draw_vars, field.live_type_info.live_type, draw_shader_def, span);
247 continue
248 }
249 else{
250 *after_draw_vars = true;
251 continue
252 }
253 }
254 if *after_draw_vars {
255 let live_type = field.live_type_info.live_type;
258 if shader_registry.enums.get(&live_type).is_some() {
259 slots += 1;
260 draw_shader_def.add_instance(field.id, ShaderTy::Enum(live_type), span, field.live_field_kind);
263 }
264 else {
265 let ty = live_type_to_shader_ty(live_type).expect("Please only put shader-understandable instance fields after draw_vars");
266 slots += ty.slots();
267 draw_shader_def.add_instance(field.id, ty, span, field.live_field_kind);
268 }
269 }
270 }
271 if level >0 && slots % 2 == 1 {
273 draw_shader_def.add_instance(LiveId(0), ShaderTy::Float, span, LiveFieldKind::Calc);
274 }
275 }
276 }
277 recur_expand(live_registry, shader_registry, 0, &mut false, live_type, draw_shader_def, span);
278 }
279 DrawShaderQuery::Geometry => {
280 if live_type == geometry_fields.live_type_check() {
281 let mut fields = Vec::new();
282 geometry_fields.geometry_fields(&mut fields);
283 for field in fields {
284 draw_shader_def.add_geometry(field.id, field.ty, span);
285 }
286 }
287 else {
288 eprintln!("lf.get_type() != geometry_fields.live_type_check()");
289 }
290 }
291 }
292 });
293 match result {
295 Err(e) => {
296 cx.draw_shaders.error_set.insert(draw_shader_ptr);
297 cx.draw_shaders.error_fingerprints.push(fingerprint);
298 let err = live_registry.live_error_to_live_file_error(e);
300 if std::env::args().find(|v| v == "--message-format=json").is_some(){
301 crate::log::log_with_level(
302 &err.file,
303 err.span.start.line,
304 err.span.start.column,
305 err.span.end.line,
306 err.span.end.column,
307 err.message,
308 crate::log::LogLevel::Error
309 );
310 }
311 else{
312 log!("Error {}", err);
313 }
314 }
315 Ok(()) => {
316 let draw_shader_id = cx.draw_shaders.shaders.len();
318
319 let const_table = cx.shader_registry.compute_const_table(draw_shader_ptr);
321
322 let mut mapping = CxDrawShaderMapping::from_draw_shader_def(
323 cx.shader_registry.draw_shader_defs.get(&draw_shader_ptr).unwrap(),
324 const_table,
325 DRAW_SHADER_INPUT_PACKING
326 );
327
328 mapping.update_live_and_user_uniforms(cx, apply);
329
330 let live_registry_rc = cx.live_registry.clone();
331 let live_registry = live_registry_rc.borrow();
332 let class_node = live_registry.ptr_to_node(draw_shader_ptr.0);
333
334 let shader_type_name = match &class_node.value {
335 LiveValue::Class {live_type, ..} => {
336 let lti = live_registry.live_type_infos.get(live_type).unwrap();
338 lti.type_name
339 }
340 _ => LiveId(0)
341 };
342 cx.draw_shaders.fingerprints.push(DrawShaderFingerprint {
343 draw_shader_id,
344 fingerprint
345 });
346 cx.draw_shaders.shaders.push(CxDrawShader {
347 class_prop: class_node.id,
348 type_name: shader_type_name,
349 os_shader_id: None,
350 mapping: mapping
351 });
352 self.options = CxDrawShaderOptions::from_ptr(cx, draw_shader_ptr);
354 cx.draw_shaders.ptr_to_item.insert(draw_shader_ptr, CxDrawShaderItem {
355 draw_shader_id,
356 options: self.options.clone()
357 });
358 cx.draw_shaders.compile_set.insert(draw_shader_ptr);
359 self.draw_shader = Some(DrawShader {
361 draw_shader_generation: cx.draw_shaders.generation,
362 draw_shader_id,
363 draw_shader_ptr
364 });
365
366 }
370 }
371 }
372 }
373
374 pub fn update_area_with_self(&mut self, cx: &mut Cx, index: usize, nodes: &[LiveNode]) {
375 if let Some(draw_shader) = self.draw_shader {
376 if let Some(inst) = self.area.valid_instance(cx) {
377 if draw_shader.draw_shader_generation != cx.draw_shaders.generation {
378 return;
379 }
380 let sh = &cx.draw_shaders[draw_shader.draw_shader_id];
381 let draw_list = &mut cx.draw_lists[inst.draw_list_id];
382 let draw_item = &mut draw_list.draw_items[inst.draw_item_id];
383 let draw_call = draw_item.kind.draw_call_mut().unwrap();
384
385 let repeat = inst.instance_count;
386 let stride = sh.mapping.instances.total_slots;
387 let instances = &mut draw_item.instances.as_mut().unwrap()[inst.instance_offset..];
388 let inst_slice = self.as_slice();
389 let mut uniform_updated = false;
390 let mut node_iter = nodes.first_child(index);
391 while let Some(node_index) = node_iter {
392 let id = nodes[node_index].id;
393
394 for input in &sh.mapping.live_instances.inputs {
396 if input.id == id {
397 for j in 0..repeat {
398 for i in 0..input.slots {
399 instances[input.offset + i + j * stride] = inst_slice[input.offset + i]
400 }
401 }
402 draw_call.instance_dirty = true;
403 }
404 }
405 for input in &sh.mapping.user_uniforms.inputs {
406 if input.id == id {
407 uniform_updated = true;
409 for i in 0..input.slots {
410 draw_call.user_uniforms[input.offset + i] = self.user_uniforms[input.offset + i]
411 }
412 }
413 draw_call.uniforms_dirty = true;
414 }
415 node_iter = nodes.next_child(node_index);
416 }
417 cx.passes[draw_list.pass_id.unwrap()].paint_dirty = true;
419 if uniform_updated{
420
421 self.area.redraw(cx);
424 }
425 }
426 }
427 }
428
429 pub fn update_rect(&mut self, cx: &mut Cx, rect: Rect) {
430 if let Some(draw_shader) = self.draw_shader {
431 if let Some(inst) = self.area.valid_instance(cx) {
432 if draw_shader.draw_shader_generation != cx.draw_shaders.generation {
433 return;
434 }
435 let sh = &cx.draw_shaders[draw_shader.draw_shader_id];
436 let draw_list = &mut cx.draw_lists[inst.draw_list_id];
437 let draw_item = &mut draw_list.draw_items[inst.draw_item_id];
438 let draw_call = draw_item.kind.draw_call_mut().unwrap();
439
440 let repeat = inst.instance_count;
441 let stride = sh.mapping.instances.total_slots;
442 let instances = &mut draw_item.instances.as_mut().unwrap()[inst.instance_offset..];
443
444 for input in &sh.mapping.instances.inputs {
445 if input.id == live_id!(rect_pos) {
446 for j in 0..repeat {
447 instances[input.offset + 0 + j * stride] = rect.pos.x as f32;
448 instances[input.offset + 1 + j * stride] = rect.pos.y as f32;
449 }
450 }
451 if input.id == live_id!(rect_size) {
452 for j in 0..repeat {
453 instances[input.offset + 0 + j * stride] = rect.size.x as f32;
454 instances[input.offset + 1 + j * stride] = rect.size.y as f32;
455 }
456 }
457 }
458 draw_call.instance_dirty = true;
459 cx.passes[draw_list.pass_id.unwrap()].paint_dirty = true;
460 }
461 }
462 }
463
464 pub fn update_instance_area_value(&mut self, cx: &mut Cx, id: &[LiveId]) {
465 if let Some(draw_shader) = self.draw_shader {
466 if let Some(inst) = self.area.valid_instance(cx) {
467 if draw_shader.draw_shader_generation != cx.draw_shaders.generation {
468 return;
469 }
470 let sh = &cx.draw_shaders[draw_shader.draw_shader_id];
471 let draw_list = &mut cx.draw_lists[inst.draw_list_id];
472 let draw_item = &mut draw_list.draw_items[inst.draw_item_id];
473 let draw_call = draw_item.kind.draw_call_mut().unwrap();
474
475 let repeat = inst.instance_count;
476 let stride = sh.mapping.instances.total_slots;
477 let instances = &mut draw_item.instances.as_mut().unwrap()[inst.instance_offset..];
478 let slice = self.as_slice();
479 for input in &sh.mapping.instances.inputs {
480 if input.id == id[0] {
481 for j in 0..repeat {
482 for k in 0..input.slots{
483 instances[input.offset + k + j * stride] = slice[input.offset + k];
484 }
485 }
486 }
487 }
488 draw_call.instance_dirty = true;
489 cx.passes[draw_list.pass_id.unwrap()].paint_dirty = true;
490 }
491 }
492 }
493
494 pub fn get_instance(&self, cx: &mut Cx, inst: &[LiveId], value: &mut [f32]){
537 if let Some(draw_shader) = self.draw_shader {
538 let sh = &cx.draw_shaders[draw_shader.draw_shader_id];
539 let self_slice = self.as_slice();
540 for input in &sh.mapping.instances.inputs {
541 let offset = input.offset;
542 let slots = input.slots;
543 if input.id == inst[0] {
544 for i in 0..value.len().min(slots) {
545 value[i] = self_slice[offset + i]
546 }
547 }
548 }
549 }
550 }
551
552 pub fn set_var_instance(&mut self, cx:&Cx, instance: &[LiveId], value: &[f32]) {
553 if let Some(draw_shader) = self.draw_shader {
554 let sh = &cx.draw_shaders[draw_shader.draw_shader_id];
555 for input in &sh.mapping.var_instances.inputs {
556 let offset = (self.var_instances.len() - sh.mapping.var_instances.total_slots) + input.offset;
557 let slots = input.slots;
558 if input.id == instance[0] {
559 for i in 0..value.len().min(slots) {
560 self.var_instances[offset + i] = value[i];
561 }
562 }
563 }
564 }
565 }
566
567 pub fn get_uniform(&self, cx: &mut Cx, uniform: &[LiveId], value: &mut [f32]){
568 if let Some(draw_shader) = self.draw_shader {
569 let sh = &cx.draw_shaders[draw_shader.draw_shader_id];
570 for input in &sh.mapping.user_uniforms.inputs {
571 let offset = input.offset;
572 let slots = input.slots;
573 if input.id == uniform[0] {
574 for i in 0..value.len().min(slots) {
575 value[i] = self.user_uniforms[offset + i];
576 }
577 }
578 }
579 }
580 }
581
582 pub fn set_uniform(&mut self, cx:&Cx, uniform: &[LiveId], value: &[f32]) {
583 if let Some(draw_shader) = self.draw_shader {
584 let sh = &cx.draw_shaders[draw_shader.draw_shader_id];
585 for input in &sh.mapping.user_uniforms.inputs {
586 let offset = input.offset;
587 let slots = input.slots;
588 if input.id == uniform[0] {
589 for i in 0..value.len().min(slots) {
590 self.user_uniforms[offset + i] = value[i]
591 }
592 }
593 }
594 }
595 }
596
597
598 pub fn init_slicer(
599 &mut self,
600 cx: &mut Cx,
601 ) {
602 if let Some(draw_shader) = self.draw_shader {
603 let sh = &cx.draw_shaders[draw_shader.draw_shader_id];
604 self.var_instance_start = self.var_instances.len() - sh.mapping.var_instances.total_slots;
605 self.var_instance_slots = sh.mapping.instances.total_slots;
606 }
607 }
608
609 pub fn before_apply_init_shader(&mut self, cx: &mut Cx, apply: &mut Apply, index: usize, _nodes: &[LiveNode], geometry_fields: &dyn GeometryFields) {
610
611 let draw_shader_ptr = if let Some(file_id) = apply.from.file_id() {
612 let generation = cx.live_registry.borrow().file_id_to_file(file_id).generation;
613 DrawShaderPtr(LivePtr::from_index(file_id, index, generation))
614 }
615 else {
616 return
617 };
618 self.init_shader(cx, apply, draw_shader_ptr, geometry_fields)
619 }
620
621 pub fn apply_slots(cx: &mut Cx, slots: usize, output: &mut [f32], offset: usize, apply: &mut Apply, index: usize, nodes: &[LiveNode]) -> usize {
622 match slots {
623 1 => {
624 let mut v: f32 = 0.0;
625 let index = v.apply(cx, apply, index, nodes);
626 output[offset + 0] = v;
627 return index;
628 }
629 2 => {
630 let mut v: Vec2 = Vec2::default();
631 let index = v.apply(cx, apply, index, nodes);
632 output[offset + 0] = v.x;
633 output[offset + 1] = v.y;
634 return index;
635 }
636 3 => {
637 let mut v: Vec3 = Vec3::default();
638 let index = v.apply(cx, apply, index, nodes);
639 output[offset + 0] = v.x;
640 output[offset + 1] = v.y;
641 output[offset + 2] = v.z;
642 return index;
643 }
644 4 => {
645 let mut v: Vec4 = Vec4::default();
646 let index = v.apply(cx, apply, index, nodes);
647 output[offset + 0] = v.x;
648 output[offset + 1] = v.y;
649 output[offset + 2] = v.z;
650 output[offset + 3] = v.w;
651 return index;
652 }
653 _ => {
654 return nodes.skip_node(index)
655 }
656 }
657 }
658
659 pub fn apply_value(&mut self, cx: &mut Cx, apply: &mut Apply, index: usize, nodes: &[LiveNode]) -> usize {
660
661 if nodes[index].origin.node_has_prefix() && nodes[index].value.is_id() {
662 return nodes.skip_node(index)
663 }
664
665 if let Some(draw_shader) = self.draw_shader {
666 let id = nodes[index].id;
667 if draw_shader.draw_shader_generation != cx.draw_shaders.generation {
668 return nodes.skip_node(index);
669 }
670 let sh = &cx.draw_shaders[draw_shader.draw_shader_id];
671 for input in &sh.mapping.user_uniforms.inputs {
672 let offset = input.offset;
673 let slots = input.slots;
674 if input.id == id {
675 return Self::apply_slots(cx, slots, &mut self.user_uniforms, offset, apply, index, nodes);
676 }
677 }
678 for input in &sh.mapping.var_instances.inputs {
679
680 let offset = (self.var_instances.len() - sh.mapping.var_instances.total_slots) + input.offset;
681 let slots = input.slots;
682 if input.id == id {
683 return Self::apply_slots(cx, slots, &mut self.var_instances, offset, apply, index, nodes);
684 }
685 }
686 }
687 else { return nodes.skip_node(index);
689 }
690
691 if nodes[index].origin.node_has_prefix() {
692 return nodes.skip_node(index)
693 }
694
695 let unknown_shader_props = match nodes[index].id {
696 live_id!(debug) => false,
697 live_id!(debug_id) => false,
698 live_id!(draw_call_group) => false,
699 _ => true
700 };
701
702 if unknown_shader_props && nodes[index].value.is_value_type() {
703 cx.apply_error_no_matching_field(live_error_origin!(), index, nodes);
704 }
705 nodes.skip_node(index)
706 }
707
708 pub fn after_apply_update_self(&mut self, cx: &mut Cx, apply: &mut Apply, index: usize, nodes: &[LiveNode], geometry_fields: &dyn GeometryFields) {
709 if apply.from.is_from_doc() {
711 self.init_slicer(cx);
712 }
713 self.geometry_id = geometry_fields.get_geometry_id();
714 self.update_area_with_self(cx, index, nodes);
715 }
716
717}