فهرست منبع

app: use a Mutex<Vec> + thread to merge render_api incoming requests queue with the main render loop update(). Once update() is called, we take the stack from the Vec and process it.

darkfi 11 ماه پیش
والد
کامیت
ffd44686b9
3فایلهای تغییر یافته به همراه46 افزوده شده و 20 حذف شده
  1. 2 4
      bin/app/src/app/locale.rs
  2. 41 13
      bin/app/src/gfx/mod.rs
  3. 3 3
      bin/app/src/main.rs

+ 2 - 4
bin/app/src/app/locale.rs

@@ -32,9 +32,7 @@ mod ui_consts {
 
 
 pub use ui_consts::*;
 pub use ui_consts::*;
 
 
-static ENTRIES: &[&'static str] = &[
-    "app.ftl"
-];
+static ENTRIES: &[&'static str] = &["app.ftl"];
 
 
 pub fn read_locale_ftl(locale: &str) -> String {
 pub fn read_locale_ftl(locale: &str) -> String {
     let dir = LOCALE_PATH.replace("{locale}", locale);
     let dir = LOCALE_PATH.replace("{locale}", locale);
@@ -45,7 +43,7 @@ pub fn read_locale_ftl(locale: &str) -> String {
         let (sender, recvr) = sync_channel(1);
         let (sender, recvr) = sync_channel(1);
         miniquad::fs::load_file(&path, move |res| match res {
         miniquad::fs::load_file(&path, move |res| match res {
             Ok(res) => sender.send(res).unwrap(),
             Ok(res) => sender.send(res).unwrap(),
-            Err(e) => panic!("FTL not found! {e}")
+            Err(e) => panic!("FTL not found! {e}"),
         });
         });
         let res = recvr.recv().unwrap();
         let res = recvr.recv().unwrap();
         let contents = std::str::from_utf8(&res).unwrap();
         let contents = std::str::from_utf8(&res).unwrap();

+ 41 - 13
bin/app/src/gfx/mod.rs

@@ -27,6 +27,7 @@ use miniquad::{
     MouseButton, PassAction, Pipeline, PipelineParams, RenderingBackend, ShaderMeta, ShaderSource,
     MouseButton, PassAction, Pipeline, PipelineParams, RenderingBackend, ShaderMeta, ShaderSource,
     TouchPhase, UniformDesc, UniformType, VertexAttribute, VertexFormat,
     TouchPhase, UniformDesc, UniformType, VertexAttribute, VertexFormat,
 };
 };
+use parking_lot::Mutex as SyncMutex;
 use std::{
 use std::{
     collections::HashMap,
     collections::HashMap,
     fs::File,
     fs::File,
@@ -790,6 +791,7 @@ impl GraphicsEventPublisher {
 
 
 struct Stage {
 struct Stage {
     ctx: Box<dyn RenderingBackend>,
     ctx: Box<dyn RenderingBackend>,
+    #[cfg(target_os = "android")]
     libegl: egl::LibEgl,
     libegl: egl::LibEgl,
     pipeline: Pipeline,
     pipeline: Pipeline,
     white_texture: miniquad::TextureId,
     white_texture: miniquad::TextureId,
@@ -799,7 +801,7 @@ struct Stage {
     buffers: HashMap<GfxBufferId, miniquad::BufferId>,
     buffers: HashMap<GfxBufferId, miniquad::BufferId>,
 
 
     epoch: EpochIndex,
     epoch: EpochIndex,
-    method_recv: async_channel::Receiver<(EpochIndex, GraphicsMethod)>,
+    method_queue: Arc<SyncMutex<Vec<(EpochIndex, GraphicsMethod)>>>,
     event_pub: GraphicsEventPublisherPtr,
     event_pub: GraphicsEventPublisherPtr,
 
 
     pruner: PruneMethodHeap,
     pruner: PruneMethodHeap,
@@ -822,6 +824,22 @@ impl Stage {
         let method_recv = god.method_recv.clone();
         let method_recv = god.method_recv.clone();
         let event_pub = god.event_pub.clone();
         let event_pub = god.event_pub.clone();
 
 
+        let method_queue = Arc::new(SyncMutex::new(vec![]));
+        let method_queue2 = method_queue.clone();
+        let sink_task = god.fg_ex.spawn(async move {
+            // Pull from render_api
+            while let Ok((epoch, method)) = method_recv.recv().await {
+                let is_replace_dc = matches!(method, GraphicsMethod::ReplaceDrawCalls { .. });
+                // Append to stage data
+                method_queue2.lock().push((epoch, method));
+                // If ReplaceDrawCall then wake up miniquad
+                if is_replace_dc {
+                    miniquad::window::schedule_update();
+                }
+            }
+        });
+        god.fg_runtime.push_task(sink_task);
+
         let white_texture = ctx.new_texture_from_rgba8(1, 1, &[255, 255, 255, 255]);
         let white_texture = ctx.new_texture_from_rgba8(1, 1, &[255, 255, 255, 255]);
 
 
         let mut shader_meta: ShaderMeta = shader::meta();
         let mut shader_meta: ShaderMeta = shader::meta();
@@ -861,10 +879,12 @@ impl Stage {
             params,
             params,
         );
         );
 
 
+        #[cfg(target_os = "android")]
         let libegl = egl::LibEgl::try_load().expect("Cant load LibEGL");
         let libegl = egl::LibEgl::try_load().expect("Cant load LibEGL");
 
 
         Stage {
         Stage {
             ctx,
             ctx,
+            #[cfg(target_os = "android")]
             libegl,
             libegl,
             pipeline,
             pipeline,
             white_texture,
             white_texture,
@@ -877,7 +897,7 @@ impl Stage {
             buffers: HashMap::new(),
             buffers: HashMap::new(),
 
 
             epoch,
             epoch,
-            method_recv,
+            method_queue,
             event_pub,
             event_pub,
 
 
             pruner: PruneMethodHeap::new(epoch),
             pruner: PruneMethodHeap::new(epoch),
@@ -901,7 +921,7 @@ impl Stage {
             GraphicsMethod::DeleteBuffer((gbuff_id, _, _)) => self.method_delete_buffer(*gbuff_id),
             GraphicsMethod::DeleteBuffer((gbuff_id, _, _)) => self.method_delete_buffer(*gbuff_id),
             GraphicsMethod::ReplaceDrawCalls { timest, dcs } => {
             GraphicsMethod::ReplaceDrawCalls { timest, dcs } => {
                 let dcs = std::mem::take(dcs);
                 let dcs = std::mem::take(dcs);
-                self.method_recvlace_draw_calls(*timest, dcs)
+                self.method_replace_draw_calls(*timest, dcs)
             }
             }
         };
         };
         if let Err(err) = res {
         if let Err(err) = res {
@@ -1029,7 +1049,7 @@ impl Stage {
         }
         }
         Ok(())
         Ok(())
     }
     }
-    fn method_recvlace_draw_calls(
+    fn method_replace_draw_calls(
         &mut self,
         &mut self,
         timest: Timestamp,
         timest: Timestamp,
         dcs: Vec<(DcId, GfxDrawCall)>,
         dcs: Vec<(DcId, GfxDrawCall)>,
@@ -1097,8 +1117,13 @@ impl Stage {
     }
     }
 
 
     fn egl_ctx_is_disabled(&self) -> bool {
     fn egl_ctx_is_disabled(&self) -> bool {
-        let egl_ctx = unsafe { (self.libegl.eglGetCurrentContext)() };
-        egl_ctx.is_null()
+        #[cfg(target_os = "android")]
+        {
+            let egl_ctx = unsafe { (self.libegl.eglGetCurrentContext)() };
+            egl_ctx.is_null()
+        }
+        #[cfg(not(target_os = "android"))]
+        false
     }
     }
 }
 }
 
 
@@ -1129,9 +1154,9 @@ impl PruneMethodHeap {
         }
         }
     }
     }
 
 
-    fn drain(&mut self, method_recv: &async_channel::Receiver<(EpochIndex, GraphicsMethod)>) {
+    fn drain(&mut self, methods: Vec<(EpochIndex, GraphicsMethod)>) {
         // Process as many methods as we can
         // Process as many methods as we can
-        while let Ok((epoch, method)) = method_recv.try_recv() {
+        for (epoch, method) in methods {
             if epoch < self.epoch {
             if epoch < self.epoch {
                 // Discard old rubbish
                 // Discard old rubbish
                 trace!(target: "gfx::pruner", "Discard method with old epoch: {epoch} curr: {} [method={method:?}]", self.epoch);
                 trace!(target: "gfx::pruner", "Discard method with old epoch: {epoch} curr: {} [method={method:?}]", self.epoch);
@@ -1164,12 +1189,12 @@ impl PruneMethodHeap {
                 }
                 }
             }
             }
             GraphicsMethod::ReplaceDrawCalls { timest, dcs } => {
             GraphicsMethod::ReplaceDrawCalls { timest, dcs } => {
-                self.method_recvlace_draw_calls(timest, dcs)
+                self.method_replace_draw_calls(timest, dcs)
             }
             }
         }
         }
     }
     }
 
 
-    fn method_recvlace_draw_calls(&mut self, timest: Timestamp, dcs: Vec<(DcId, GfxDrawCall)>) {
+    fn method_replace_draw_calls(&mut self, timest: Timestamp, dcs: Vec<(DcId, GfxDrawCall)>) {
         for (key, val) in dcs {
         for (key, val) in dcs {
             match self.dcs.get_mut(&key) {
             match self.dcs.get_mut(&key) {
                 Some(old_val) => {
                 Some(old_val) => {
@@ -1206,9 +1231,11 @@ impl PruneMethodHeap {
 
 
 impl EventHandler for Stage {
 impl EventHandler for Stage {
     fn update(&mut self) {
     fn update(&mut self) {
+        let methods = std::mem::take(&mut *self.method_queue.lock());
+
         if self.egl_ctx_is_disabled() {
         if self.egl_ctx_is_disabled() {
             // Screen is off so collect all methods into the pruner
             // Screen is off so collect all methods into the pruner
-            self.pruner.drain(&self.method_recv);
+            self.pruner.drain(methods);
             self.screen_was_off = true;
             self.screen_was_off = true;
             return
             return
         }
         }
@@ -1234,7 +1261,7 @@ impl EventHandler for Stage {
         }
         }
 
 
         // Process as many methods as we can
         // Process as many methods as we can
-        while let Ok((epoch, method)) = self.method_recv.try_recv() {
+        for (epoch, method) in methods {
             if DEBUG_TRAX {
             if DEBUG_TRAX {
                 self.trax_method(epoch, &method);
                 self.trax_method(epoch, &method);
             }
             }
@@ -1359,7 +1386,8 @@ pub fn run_gui() {
         window_resizable: true,
         window_resizable: true,
         platform: miniquad::conf::Platform {
         platform: miniquad::conf::Platform {
             linux_backend: miniquad::conf::LinuxBackend::WaylandWithX11Fallback,
             linux_backend: miniquad::conf::LinuxBackend::WaylandWithX11Fallback,
-            //blocking_event_loop: true,
+            #[cfg(target_os = "android")]
+            blocking_event_loop: true,
             android_panic_hook: false,
             android_panic_hook: false,
             ..Default::default()
             ..Default::default()
         },
         },

+ 3 - 3
bin/app/src/main.rs

@@ -102,8 +102,8 @@ struct God {
     _bg_runtime: AsyncRuntime,
     _bg_runtime: AsyncRuntime,
     _bg_ex: ExecutorPtr,
     _bg_ex: ExecutorPtr,
 
 
-    fg_runtime: AsyncRuntime,
-    _fg_ex: ExecutorPtr,
+    pub fg_runtime: AsyncRuntime,
+    pub fg_ex: ExecutorPtr,
 
 
     /// App must fully finish setup() before start() is allowed to begin.
     /// App must fully finish setup() before start() is allowed to begin.
     cv_app_is_setup: Arc<CondVar>,
     cv_app_is_setup: Arc<CondVar>,
@@ -200,7 +200,7 @@ impl God {
             _bg_ex: bg_ex,
             _bg_ex: bg_ex,
 
 
             fg_runtime,
             fg_runtime,
-            _fg_ex: fg_ex,
+            fg_ex,
             cv_app_is_setup,
             cv_app_is_setup,
             app,
             app,