Explorar o código

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 hai 1 ano
pai
achega
ffd44686b9
Modificáronse 3 ficheiros con 46 adicións e 20 borrados
  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::*;
 
-static ENTRIES: &[&'static str] = &[
-    "app.ftl"
-];
+static ENTRIES: &[&'static str] = &["app.ftl"];
 
 pub fn read_locale_ftl(locale: &str) -> String {
     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);
         miniquad::fs::load_file(&path, move |res| match res {
             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 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,
     TouchPhase, UniformDesc, UniformType, VertexAttribute, VertexFormat,
 };
+use parking_lot::Mutex as SyncMutex;
 use std::{
     collections::HashMap,
     fs::File,
@@ -790,6 +791,7 @@ impl GraphicsEventPublisher {
 
 struct Stage {
     ctx: Box<dyn RenderingBackend>,
+    #[cfg(target_os = "android")]
     libegl: egl::LibEgl,
     pipeline: Pipeline,
     white_texture: miniquad::TextureId,
@@ -799,7 +801,7 @@ struct Stage {
     buffers: HashMap<GfxBufferId, miniquad::BufferId>,
 
     epoch: EpochIndex,
-    method_recv: async_channel::Receiver<(EpochIndex, GraphicsMethod)>,
+    method_queue: Arc<SyncMutex<Vec<(EpochIndex, GraphicsMethod)>>>,
     event_pub: GraphicsEventPublisherPtr,
 
     pruner: PruneMethodHeap,
@@ -822,6 +824,22 @@ impl Stage {
         let method_recv = god.method_recv.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 mut shader_meta: ShaderMeta = shader::meta();
@@ -861,10 +879,12 @@ impl Stage {
             params,
         );
 
+        #[cfg(target_os = "android")]
         let libegl = egl::LibEgl::try_load().expect("Cant load LibEGL");
 
         Stage {
             ctx,
+            #[cfg(target_os = "android")]
             libegl,
             pipeline,
             white_texture,
@@ -877,7 +897,7 @@ impl Stage {
             buffers: HashMap::new(),
 
             epoch,
-            method_recv,
+            method_queue,
             event_pub,
 
             pruner: PruneMethodHeap::new(epoch),
@@ -901,7 +921,7 @@ impl Stage {
             GraphicsMethod::DeleteBuffer((gbuff_id, _, _)) => self.method_delete_buffer(*gbuff_id),
             GraphicsMethod::ReplaceDrawCalls { timest, 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 {
@@ -1029,7 +1049,7 @@ impl Stage {
         }
         Ok(())
     }
-    fn method_recvlace_draw_calls(
+    fn method_replace_draw_calls(
         &mut self,
         timest: Timestamp,
         dcs: Vec<(DcId, GfxDrawCall)>,
@@ -1097,8 +1117,13 @@ impl Stage {
     }
 
     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
-        while let Ok((epoch, method)) = method_recv.try_recv() {
+        for (epoch, method) in methods {
             if epoch < self.epoch {
                 // Discard old rubbish
                 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 } => {
-                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 {
             match self.dcs.get_mut(&key) {
                 Some(old_val) => {
@@ -1206,9 +1231,11 @@ impl PruneMethodHeap {
 
 impl EventHandler for Stage {
     fn update(&mut self) {
+        let methods = std::mem::take(&mut *self.method_queue.lock());
+
         if self.egl_ctx_is_disabled() {
             // 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;
             return
         }
@@ -1234,7 +1261,7 @@ impl EventHandler for Stage {
         }
 
         // 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 {
                 self.trax_method(epoch, &method);
             }
@@ -1359,7 +1386,8 @@ pub fn run_gui() {
         window_resizable: true,
         platform: miniquad::conf::Platform {
             linux_backend: miniquad::conf::LinuxBackend::WaylandWithX11Fallback,
-            //blocking_event_loop: true,
+            #[cfg(target_os = "android")]
+            blocking_event_loop: true,
             android_panic_hook: false,
             ..Default::default()
         },

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

@@ -102,8 +102,8 @@ struct God {
     _bg_runtime: AsyncRuntime,
     _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.
     cv_app_is_setup: Arc<CondVar>,
@@ -200,7 +200,7 @@ impl God {
             _bg_ex: bg_ex,
 
             fg_runtime,
-            _fg_ex: fg_ex,
+            fg_ex,
             cv_app_is_setup,
             app,