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