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
115pub struct CxDrawShader {
116 pub class_prop: LiveId,
117 pub type_name: LiveId,
118 pub os_shader_id: Option<usize>,
119 pub mapping: CxDrawShaderMapping
120}
121
122#[derive(Debug, PartialEq)]
123pub struct DrawShaderFingerprint {
124 pub fingerprint: Vec<LiveNode>,
125 pub draw_shader_id: usize
126}
127
128impl DrawShaderFingerprint {
129 pub fn from_ptr(cx: &Cx, draw_shader_ptr: DrawShaderPtr) -> Vec<LiveNode> {
130 let live_registry_cp = cx.live_registry.clone();
131 let live_registry = live_registry_cp.borrow();
132 let doc = live_registry.ptr_to_doc(draw_shader_ptr.0);
133 let mut node_iter = doc.nodes.first_child(draw_shader_ptr.node_index());
134 let mut fingerprint = Vec::new();
135 while let Some(node_index) = node_iter {
136 let node = &doc.nodes[node_index];
137 match node.value {
138 LiveValue::DSL {token_start, token_count, ..} => {
139 fingerprint.push(LiveNode {
140 id: node.id,
141 origin: node.origin,
142 value: LiveValue::DSL {token_start, token_count, expand_index: None}
143 });
144 }
145 _ => ()
146 }
147 node_iter = doc.nodes.next_child(node_index);
148 }
149 fingerprint
150 }
151}
152
153#[derive(Clone, Debug)]
154pub struct DrawShaderInputs {
155 pub inputs: Vec<DrawShaderInput>,
156 pub packing_method: DrawShaderInputPacking,
157 pub total_slots: usize,
158}
159
160#[derive(Clone, Copy, Debug)]
161pub enum DrawShaderInputPacking {
162 Attribute,
163 UniformsGLSL,
164 #[allow(dead_code)]
165 UniformsHLSL,
166 #[allow(dead_code)]
167 UniformsMetal
168}
169
170
171#[derive(Clone, Debug)]
172pub struct DrawShaderInput {
173 pub id: LiveId,
174 pub ty: ShaderTy,
175 pub offset: usize,
176 pub slots: usize,
177 pub live_ptr: Option<LivePtr>
178}
179
180
181#[cfg(any(target_os = "android", target_os = "linux", target_arch = "wasm32"))]
182pub const DRAW_SHADER_INPUT_PACKING: DrawShaderInputPacking = DrawShaderInputPacking::UniformsGLSL;
183#[cfg(any(target_os = "macos", target_os = "ios"))]
184pub const DRAW_SHADER_INPUT_PACKING: DrawShaderInputPacking = DrawShaderInputPacking::UniformsMetal;
185#[cfg(any(target_os = "windows"))]
186pub const DRAW_SHADER_INPUT_PACKING: DrawShaderInputPacking = DrawShaderInputPacking::UniformsHLSL;
187
188impl DrawShaderInputs {
189 pub fn new(packing_method: DrawShaderInputPacking) -> Self {
190 Self {
191 inputs: Vec::new(),
192 packing_method,
193 total_slots: 0
194 }
195 }
196
197 pub fn push(&mut self, id: LiveId, ty: ShaderTy, live_ptr: Option<LivePtr>) {
198 let slots = ty.slots();
199 match self.packing_method {
200 DrawShaderInputPacking::Attribute => {
201 self.inputs.push(DrawShaderInput {
202 id,
203 offset: self.total_slots,
204 slots,
205 ty,
206 live_ptr
207 });
208 self.total_slots += slots;
209 }
210 DrawShaderInputPacking::UniformsGLSL => {
211 self.inputs.push(DrawShaderInput {
212 id,
213 offset: self.total_slots,
214 slots,
215 ty,
216 live_ptr
217 });
218 self.total_slots += slots;
219 }
220 DrawShaderInputPacking::UniformsHLSL => {
221 if (self.total_slots & 3) + slots > 4 { self.total_slots += 4 - (self.total_slots & 3); }
224 self.inputs.push(DrawShaderInput {
225 id,
226 offset: self.total_slots,
227 slots,
228 ty,
229 live_ptr
230 });
231 self.total_slots += slots;
232 }
233 DrawShaderInputPacking::UniformsMetal => {
234 let aligned_slots = if slots == 3 {4} else {slots};
235 if (self.total_slots & 3) + aligned_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 += aligned_slots;
246 }
247 }
248 }
249
250 pub fn finalize(&mut self) {
251 match self.packing_method {
252 DrawShaderInputPacking::Attribute => (),
253 DrawShaderInputPacking::UniformsGLSL =>(),
254 DrawShaderInputPacking::UniformsHLSL |
255 DrawShaderInputPacking::UniformsMetal => {
256 if self.total_slots & 3 > 0 {
257 self.total_slots += 4 - (self.total_slots & 3);
258 }
259 }
260 }
261 }
262}
263
264#[derive(Clone)]
265pub struct DrawShaderTextureInput {
266 pub id: LiveId,
267 pub ty: ShaderTy
268}
269
270#[derive(Clone)]
271pub struct CxDrawShaderMapping {
272 pub flags: DrawShaderFlags,
273 pub const_table: DrawShaderConstTable,
274
275 pub geometries: DrawShaderInputs,
276 pub instances: DrawShaderInputs,
277 pub var_instances: DrawShaderInputs,
278 pub live_instances: DrawShaderInputs,
279 pub live_uniforms: DrawShaderInputs,
280 pub user_uniforms: DrawShaderInputs,
281 pub draw_uniforms: DrawShaderInputs,
282 pub view_uniforms: DrawShaderInputs,
283 pub pass_uniforms: DrawShaderInputs,
284 pub textures: Vec<DrawShaderTextureInput>,
285 pub instance_enums: Vec<usize>,
286 pub rect_pos: Option<usize>,
287 pub rect_size: Option<usize>,
288 pub draw_clip: Option<usize>,
289 pub live_uniforms_buf: Vec<f32>,
290}
291
292impl CxDrawShaderMapping {
293
294 pub fn from_draw_shader_def(draw_shader_def: &DrawShaderDef, const_table: DrawShaderConstTable, uniform_packing: DrawShaderInputPacking) -> CxDrawShaderMapping { let mut geometries = DrawShaderInputs::new(DrawShaderInputPacking::Attribute);
297 let mut instances = DrawShaderInputs::new(DrawShaderInputPacking::Attribute);
298 let mut var_instances = DrawShaderInputs::new(DrawShaderInputPacking::Attribute);
299 let mut live_instances = DrawShaderInputs::new(DrawShaderInputPacking::Attribute);
300 let mut user_uniforms = DrawShaderInputs::new(uniform_packing);
301 let mut live_uniforms = DrawShaderInputs::new(uniform_packing);
302 let mut draw_uniforms = DrawShaderInputs::new(uniform_packing);
303 let mut view_uniforms = DrawShaderInputs::new(uniform_packing);
304 let mut pass_uniforms = DrawShaderInputs::new(uniform_packing);
305 let mut textures = Vec::new();
306 let mut instance_enums = Vec::new();
307 let mut rect_pos = None;
308 let mut rect_size = None;
309 let mut draw_clip = None;
310
311 for field in &draw_shader_def.fields {
312 let ty = field.ty_expr.ty.borrow().as_ref().unwrap().clone();
313 match &field.kind {
314 DrawShaderFieldKind::Geometry {..} => {
315 geometries.push(field.ident.0, ty, None);
316 }
317 DrawShaderFieldKind::Instance {var_def_ptr, live_field_kind, ..} => {
318 if field.ident.0 == live_id!(rect_pos) {
319 rect_pos = Some(instances.total_slots);
320 }
321 if field.ident.0 == live_id!(rect_size) {
322 rect_size = Some(instances.total_slots);
323 }
324 if field.ident.0 == live_id!(draw_clip) {
325 draw_clip = Some(instances.total_slots);
326 }
327 if var_def_ptr.is_some() {
328 var_instances.push(field.ident.0, ty.clone(), None,);
329 }
330 if let ShaderTy::Enum{..} = ty{
331 instance_enums.push(instances.total_slots);
332 }
333 instances.push(field.ident.0, ty, None);
334 if let LiveFieldKind::Live = live_field_kind {
335 live_instances.inputs.push(instances.inputs.last().unwrap().clone());
336 }
337 }
338 DrawShaderFieldKind::Uniform {block_ident, ..} => {
339 match block_ident.0 {
340 live_id!(draw) => {
341 draw_uniforms.push(field.ident.0, ty, None);
342 }
343 live_id!(view) => {
344 view_uniforms.push(field.ident.0, ty, None);
345 }
346 live_id!(pass) => {
347 pass_uniforms.push(field.ident.0, ty, None);
348 }
349 live_id!(user) => {
350 user_uniforms.push(field.ident.0, ty, None);
351 }
352 _ => ()
353 }
354 }
355 DrawShaderFieldKind::Texture {..} => {
356 textures.push(DrawShaderTextureInput {
357 ty:ty,
358 id: field.ident.0,
359 });
360 }
361 _ => ()
362 }
363 }
364
365 geometries.finalize();
366 instances.finalize();
367 var_instances.finalize();
368 user_uniforms.finalize();
369 live_uniforms.finalize();
370 draw_uniforms.finalize();
371 view_uniforms.finalize();
372 pass_uniforms.finalize();
373
374 for (value_node_ptr, ty) in draw_shader_def.all_live_refs.borrow().iter() {
379 live_uniforms.push(LiveId(0), ty.clone(), Some(value_node_ptr.0));
380 }
381
382 CxDrawShaderMapping {
383 const_table,
384 flags: draw_shader_def.flags,
385 geometries,
386 instances,
387 live_uniforms_buf: {let mut r = Vec::new(); r.resize(live_uniforms.total_slots, 0.0); r},
388 var_instances,
389 live_instances,
390 user_uniforms,
391 live_uniforms,
392 draw_uniforms,
393 view_uniforms,
394 pass_uniforms,
395 instance_enums,
396 textures,
397 rect_pos,
398 rect_size,
399 draw_clip,
400 }
401 }
402
403 pub fn update_live_and_user_uniforms(&mut self, cx: &mut Cx, from: ApplyFrom) {
404 let live_registry = cx.live_registry.clone();
406 let live_registry = live_registry.borrow();
407
408 for input in &self.live_uniforms.inputs {
409 let (nodes,index) = live_registry.ptr_to_nodes_index(input.live_ptr.unwrap());
410 DrawVars::apply_slots(
411 cx,
412 input.slots,
413 &mut self.live_uniforms_buf,
414 input.offset,
415 from,
416 index,
417 nodes
418 );
419 }
420 }
421}