1use {
2 std::{
3 ops::{Index, IndexMut},
4 collections::{
5 HashMap,
6 HashSet,
7 BTreeSet,
8 },
9 },
10 crate::{
11 makepad_live_compiler::{LiveValue, LiveFieldKind, LiveNode, LivePtr, LiveNodeSliceApi},
12 makepad_shader_compiler::*,
13 makepad_live_id::*,
14 live_traits::*,
15 draw_vars::DrawVars,
16 os::CxOsDrawShader,
17 cx::Cx
18 }
19};
20
21#[derive(Default, Debug, Clone, PartialEq)]
22pub struct CxDrawShaderOptions {
23 pub draw_call_group: LiveId,
24 pub debug_id: Option<LiveId>,
25}
26
27impl CxDrawShaderOptions {
28 pub fn from_ptr(cx: &Cx, draw_shader_ptr: DrawShaderPtr) -> Self {
29 let live_registry_cp = cx.live_registry.clone();
30 let live_registry = live_registry_cp.borrow();
31 let doc = live_registry.ptr_to_doc(draw_shader_ptr.0);
32 let mut ret = Self::default();
33 let mut node_iter = doc.nodes.first_child(draw_shader_ptr.node_index());
35 while let Some(node_index) = node_iter {
36 let node = &doc.nodes[node_index];
37 match node.id {
38 live_id!(draw_call_group) => if let LiveValue::Id(id) = node.value {
39 ret.draw_call_group = id;
40 }
41 live_id!(debug_id) => if let LiveValue::Id(id) = node.value {
42 ret.debug_id = Some(id);
43 }
44 _ => ()
45 }
46 node_iter = doc.nodes.next_child(node_index);
47 }
48 ret
49 }
50
51 pub fn _appendable_drawcall(&self, other: &Self) -> bool {
52 self == other
53 }
54}
55
56#[derive(Default)]
57pub struct CxDrawShaderItem {
58 pub draw_shader_id: usize,
59 pub options: CxDrawShaderOptions
60}
61
62#[derive(Default)]
63pub struct CxDrawShaders {
64 pub shaders: Vec<CxDrawShader>,
65 pub os_shaders: Vec<CxOsDrawShader>,
66 pub generation: u64,
67 pub ptr_to_item: HashMap<DrawShaderPtr, CxDrawShaderItem>,
68 pub compile_set: BTreeSet<DrawShaderPtr>,
69 pub fingerprints: Vec<DrawShaderFingerprint>,
70 pub error_set: HashSet<DrawShaderPtr>,
71 pub error_fingerprints: Vec<Vec<LiveNode >>,
72}
73
74impl CxDrawShaders{
75 pub fn reset_for_live_reload(&mut self){
76 self.ptr_to_item.clear();
77 self.fingerprints.clear();
78 self.error_set.clear();
79 self.error_fingerprints.clear();
80 }
81}
82
83impl Cx {
84 pub fn flush_draw_shaders(&mut self) {
85 self.draw_shaders.generation += 1;
86 self.shader_registry.flush_registry();
87 self.draw_shaders.shaders.clear();
88 self.draw_shaders.ptr_to_item.clear();
89 self.draw_shaders.fingerprints.clear();
90 self.draw_shaders.error_set.clear();
91 self.draw_shaders.error_fingerprints.clear();
92 }
93}
94
95impl Index<usize> for CxDrawShaders {
96 type Output = CxDrawShader;
97 fn index(&self, index: usize) -> &Self::Output {
98 &self.shaders[index]
99 }
100}
101
102impl IndexMut<usize> for CxDrawShaders {
103 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
104 &mut self.shaders[index]
105 }
106}
107
108#[derive(Copy, Clone, PartialEq, Debug)]
109pub struct DrawShader {
110 pub draw_shader_generation: u64,
111 pub draw_shader_id: usize,
112 pub draw_shader_ptr: DrawShaderPtr
113}
114
115impl DrawShader{
116 pub fn false_compare_id(&self)->u64{
117 ((self.draw_shader_id as u64)<<32) | self.draw_shader_ptr.0.index as u64
118 }
119}
120
121pub struct CxDrawShader {
122 pub class_prop: LiveId,
123 pub type_name: LiveId,
124 pub os_shader_id: Option<usize>,
125 pub mapping: CxDrawShaderMapping
126}
127
128#[derive(Debug, PartialEq)]
129pub struct DrawShaderFingerprint {
130 pub fingerprint: Vec<LiveNode>,
131 pub draw_shader_id: usize
132}
133
134impl DrawShaderFingerprint {
135 pub fn from_ptr(cx: &Cx, draw_shader_ptr: DrawShaderPtr) -> Vec<LiveNode> {
136 let live_registry_cp = cx.live_registry.clone();
137 let live_registry = live_registry_cp.borrow();
138 let doc = live_registry.ptr_to_doc(draw_shader_ptr.0);
139 let mut node_iter = doc.nodes.first_child(draw_shader_ptr.node_index());
140 let mut fingerprint = Vec::new();
141 while let Some(node_index) = node_iter {
142 let node = &doc.nodes[node_index];
143 match node.value {
144 LiveValue::DSL {token_start, token_count, ..} => {
145 fingerprint.push(LiveNode {
146 id: node.id,
147 origin: node.origin,
148 value: LiveValue::DSL {token_start, token_count, expand_index: None}
149 });
150 }
151 _ => ()
152 }
153 node_iter = doc.nodes.next_child(node_index);
154 }
155 fingerprint
156 }
157}
158
159#[derive(Clone, Debug)]
160pub struct DrawShaderInputs {
161 pub inputs: Vec<DrawShaderInput>,
162 pub packing_method: DrawShaderInputPacking,
163 pub total_slots: usize,
164}
165
166#[derive(Clone, Copy, Debug)]
167pub enum DrawShaderInputPacking {
168 Attribute,
169 UniformsGLSLTight,
170 UniformsGLSL140,
171 #[allow(dead_code)]
172 UniformsHLSL,
173 #[allow(dead_code)]
174 UniformsMetal
175}
176
177
178#[derive(Clone, Debug)]
179pub struct DrawShaderInput {
180 pub id: LiveId,
181 pub ty: ShaderTy,
182 pub offset: usize,
183 pub slots: usize,
184 pub live_ptr: Option<LivePtr>
185}
186
187#[cfg(any(target_arch = "wasm32"))]
188pub const DRAW_SHADER_INPUT_PACKING: DrawShaderInputPacking = DrawShaderInputPacking::UniformsGLSLTight;
189
190
191#[cfg(all(any(target_os = "android", target_os = "linux"),use_gles_3))]
192pub const DRAW_SHADER_INPUT_PACKING: DrawShaderInputPacking = DrawShaderInputPacking::UniformsGLSL140;
193#[cfg(all(any(target_os = "android", target_os = "linux"),not(use_gles_3)))]
194pub const DRAW_SHADER_INPUT_PACKING: DrawShaderInputPacking = DrawShaderInputPacking::UniformsGLSLTight;
195
196
197#[cfg(any(target_os = "macos", target_os = "ios", target_os="tvos"))]
198pub const DRAW_SHADER_INPUT_PACKING: DrawShaderInputPacking = DrawShaderInputPacking::UniformsMetal;
199#[cfg(any(target_os = "windows"))]
200pub const DRAW_SHADER_INPUT_PACKING: DrawShaderInputPacking = DrawShaderInputPacking::UniformsHLSL;
201
202impl DrawShaderInputs {
203 pub fn new(packing_method: DrawShaderInputPacking) -> Self {
204 Self {
205 inputs: Vec::new(),
206 packing_method,
207 total_slots: 0
208 }
209 }
210
211 pub fn push(&mut self, id: LiveId, ty: ShaderTy, live_ptr: Option<LivePtr>) {
212 let slots = ty.slots();
213 match self.packing_method {
214 DrawShaderInputPacking::Attribute => {
215 self.inputs.push(DrawShaderInput {
216 id,
217 offset: self.total_slots,
218 slots,
219 ty,
220 live_ptr
221 });
222 self.total_slots += slots;
223 }
224 DrawShaderInputPacking::UniformsGLSLTight => {
225 self.inputs.push(DrawShaderInput {
226 id,
227 offset: self.total_slots,
228 slots,
229 ty,
230 live_ptr
231 });
232 self.total_slots += slots;
233 }
234 DrawShaderInputPacking::UniformsGLSL140 => {
235 if (self.total_slots & 3) + slots > 4 { self.total_slots += 4 - (self.total_slots & 3); }
238 self.inputs.push(DrawShaderInput {
239 id,
240 offset: self.total_slots,
241 slots,
242 ty,
243 live_ptr
244 });
245 self.total_slots += slots;
246 }
247 DrawShaderInputPacking::UniformsHLSL => {
248 if (self.total_slots & 3) + slots > 4 { self.total_slots += 4 - (self.total_slots & 3); }
251 self.inputs.push(DrawShaderInput {
252 id,
253 offset: self.total_slots,
254 slots,
255 ty,
256 live_ptr
257 });
258 self.total_slots += slots;
259 }
260 DrawShaderInputPacking::UniformsMetal => {
261 let aligned_slots = if slots == 3 {4} else {slots};
262 if (self.total_slots & 3) + aligned_slots > 4 { self.total_slots += 4 - (self.total_slots & 3); }
265 self.inputs.push(DrawShaderInput {
266 id,
267 offset: self.total_slots,
268 slots,
269 ty,
270 live_ptr
271 });
272 self.total_slots += aligned_slots;
273 }
274 }
275 }
276
277 pub fn finalize(&mut self) {
278 match self.packing_method {
279 DrawShaderInputPacking::Attribute => (),
280 DrawShaderInputPacking::UniformsGLSLTight =>(),
281 DrawShaderInputPacking::UniformsHLSL |
282 DrawShaderInputPacking::UniformsMetal|
283 DrawShaderInputPacking::UniformsGLSL140
284 => {
285 if self.total_slots & 3 > 0 {
286 self.total_slots += 4 - (self.total_slots & 3);
287 }
288 }
289 }
290 }
291}
292
293#[derive(Clone)]
294pub struct DrawShaderTextureInput {
295 pub id: LiveId,
296 pub ty: ShaderTy
297}
298
299#[derive(Clone)]
300pub struct CxDrawShaderMapping {
301 pub flags: DrawShaderFlags,
302 pub const_table: DrawShaderConstTable,
303
304 pub geometries: DrawShaderInputs,
305 pub instances: DrawShaderInputs,
306 pub var_instances: DrawShaderInputs,
307 pub live_instances: DrawShaderInputs,
308 pub live_uniforms: DrawShaderInputs,
309 pub user_uniforms: DrawShaderInputs,
310 pub draw_list_uniforms: DrawShaderInputs,
311 pub draw_call_uniforms: DrawShaderInputs,
312 pub pass_uniforms: DrawShaderInputs,
313 pub textures: Vec<DrawShaderTextureInput>,
314 pub uses_time: bool,
315 pub instance_enums: Vec<usize>,
316 pub rect_pos: Option<usize>,
317 pub rect_size: Option<usize>,
318 pub draw_clip: Option<usize>,
319 pub live_uniforms_buf: Vec<f32>,
320}
321
322impl CxDrawShaderMapping {
323
324 pub fn from_draw_shader_def(draw_shader_def: &DrawShaderDef, const_table: DrawShaderConstTable, uniform_packing: DrawShaderInputPacking) -> CxDrawShaderMapping { let mut geometries = DrawShaderInputs::new(DrawShaderInputPacking::Attribute);
327 let mut instances = DrawShaderInputs::new(DrawShaderInputPacking::Attribute);
328 let mut var_instances = DrawShaderInputs::new(DrawShaderInputPacking::Attribute);
329 let mut live_instances = DrawShaderInputs::new(DrawShaderInputPacking::Attribute);
330 let mut user_uniforms = DrawShaderInputs::new(uniform_packing);
331 let mut live_uniforms = DrawShaderInputs::new(uniform_packing);
332 let mut draw_list_uniforms = DrawShaderInputs::new(uniform_packing);
333 let mut draw_call_uniforms = DrawShaderInputs::new(uniform_packing);
334 let mut pass_uniforms = DrawShaderInputs::new(uniform_packing);
335 let mut textures = Vec::new();
336 let mut instance_enums = Vec::new();
337 let mut rect_pos = None;
338 let mut rect_size = None;
339 let mut draw_clip = None;
340 for field in &draw_shader_def.fields {
341 let ty = field.ty_expr.ty.borrow().as_ref().unwrap().clone();
342 match &field.kind {
343 DrawShaderFieldKind::Geometry {..} => {
344 geometries.push(field.ident.0, ty, None);
345 }
346 DrawShaderFieldKind::Instance {var_def_ptr, live_field_kind, ..} => {
347 if field.ident.0 == live_id!(rect_pos) {
348 rect_pos = Some(instances.total_slots);
349 }
350 if field.ident.0 == live_id!(rect_size) {
351 rect_size = Some(instances.total_slots);
352 }
353 if field.ident.0 == live_id!(draw_clip) {
354 draw_clip = Some(instances.total_slots);
355 }
356 if var_def_ptr.is_some() {
357 var_instances.push(field.ident.0, ty.clone(), None,);
358 }
359 if let ShaderTy::Enum{..} = ty{
360 instance_enums.push(instances.total_slots);
361 }
362 instances.push(field.ident.0, ty, None);
363 if let LiveFieldKind::Live = live_field_kind {
364 live_instances.inputs.push(instances.inputs.last().unwrap().clone());
365 }
366 }
367 DrawShaderFieldKind::Uniform {block_ident, ..} => {
368 match block_ident.0 {
369 live_id!(draw_call) => {
370 draw_call_uniforms.push(field.ident.0, ty, None);
371 }
372 live_id!(draw_list) => {
373 draw_list_uniforms.push(field.ident.0, ty, None);
374 }
375 live_id!(pass) => {
376 pass_uniforms.push(field.ident.0, ty, None);
377 }
378 live_id!(user) => {
379 user_uniforms.push(field.ident.0, ty, None);
380 }
381 _ => ()
382 }
383 }
384 DrawShaderFieldKind::Texture {..} => {
385 textures.push(DrawShaderTextureInput {
386 ty:ty,
387 id: field.ident.0,
388 });
389 }
390 _ => ()
391 }
392 }
393
394 geometries.finalize();
395 instances.finalize();
396 var_instances.finalize();
397 user_uniforms.finalize();
398 live_uniforms.finalize();
399 draw_list_uniforms.finalize();
400 draw_call_uniforms.finalize();
401 pass_uniforms.finalize();
402
403 for (value_node_ptr, ty) in draw_shader_def.all_live_refs.borrow().iter() {
408 live_uniforms.push(LiveId(0), ty.clone(), Some(value_node_ptr.0));
409 }
410
411 CxDrawShaderMapping {
412 const_table,
413 uses_time: draw_shader_def.uses_time.get(),
414 flags: draw_shader_def.flags,
415 geometries,
416 instances,
417 live_uniforms_buf: {let mut r = Vec::new(); r.resize(live_uniforms.total_slots, 0.0); r},
418 var_instances,
419 live_instances,
420 user_uniforms,
421 live_uniforms,
422 draw_list_uniforms,
423 draw_call_uniforms,
424 pass_uniforms,
425 instance_enums,
426 textures,
427 rect_pos,
428 rect_size,
429 draw_clip,
430 }
431 }
432
433 pub fn update_live_and_user_uniforms(&mut self, cx: &mut Cx, apply: &mut Apply) {
434 let live_registry = cx.live_registry.clone();
436 let live_registry = live_registry.borrow();
437
438 for input in &self.live_uniforms.inputs {
439 let (nodes,index) = live_registry.ptr_to_nodes_index(input.live_ptr.unwrap());
440 DrawVars::apply_slots(
441 cx,
442 input.slots,
443 &mut self.live_uniforms_buf,
444 input.offset,
445 apply,
446 index,
447 nodes
448 );
449 }
450 }
451}