diff --git a/bin/app/src/gfx/mod.rs b/bin/app/src/gfx/mod.rs index 551abe3ea..93638833d 100644 --- a/bin/app/src/gfx/mod.rs +++ b/bin/app/src/gfx/mod.rs @@ -330,6 +330,12 @@ impl RenderApi { pub fn replace_draw_calls(&self, batch_id: BatchGuardId, dcs: Vec<(DcId, DrawCall)>) { let method = GraphicsMethod::ReplaceGfxDrawCalls { batch_id, dcs }; self.send(method); + + // I'm not sure whether we need this. Anyway its not fully reliable either since + // we have no guarantee that when `Stage::update()` whether this method is ready + // in the receiver. + #[cfg(target_os = "android")] + miniquad::window::schedule_update(); } fn start_batch(&self, batch_id: BatchGuardId, tag: DebugTag) { @@ -340,6 +346,10 @@ impl RenderApi { let timest = unixtime(); let method = GraphicsMethod::EndBatch { batch_id, timest }; self.send(method); + + // Force an update + #[cfg(target_os = "android")] + miniquad::window::schedule_update(); } pub fn make_guard(&self, debug_str: Option<&'static str>) -> PropertyAtomicGuard { @@ -954,13 +964,11 @@ struct Stage { anims: Box>, epoch: EpochIndex, - method_queue: Arc>>, + method_recv: async_channel::Receiver<(EpochIndex, GraphicsMethod)>, event_pub: GraphicsEventPublisherPtr, pruner: PruneMethodHeap, screen_state: ScreenState, - #[cfg(target_os = "android")] - ex: ExecutorPtr, } impl Stage { @@ -979,24 +987,6 @@ impl Stage { let method_recv = god.method_recv.clone(); let event_pub = god.event_pub.clone(); - let ex = god.fg_ex.clone(); - let method_queue = Arc::new(SyncMutex::new(vec![])); - let method_queue2 = method_queue.clone(); - let sink_task = ex.spawn(async move { - // Pull from render_api - while let Ok((epoch, method)) = method_recv.recv().await { - let is_replace_dc = matches!(method, GraphicsMethod::ReplaceGfxDrawCalls { .. }); - // Append to stage data - method_queue2.lock().push((epoch, method)); - // If ReplaceGfxDrawCall then wake up miniquad - if is_replace_dc { - #[cfg(target_os = "android")] - 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 anims: HashMap = HashMap::new(); @@ -1025,13 +1015,11 @@ impl Stage { anims: Box::new(anims), epoch, - method_queue, + method_recv, event_pub, pruner: PruneMethodHeap::new(epoch), screen_state: ScreenState::On, - #[cfg(target_os = "android")] - ex: ex.clone(), }; self_.pruner.textures = &*self_.textures as *const _; self_.pruner.buffers = &*self_.buffers as *const _; @@ -1347,8 +1335,7 @@ impl Stage { #[instrument(skip_all, target = "gfx::process")] fn process_methods(&mut self) { // Process as many methods as we can - let methods = std::mem::take(&mut *self.method_queue.lock()); - for (epoch, method) in methods { + while let Ok((epoch, method)) = self.method_recv.try_recv() { if DEBUG_TRAX { self.trax_method(epoch, &method); } @@ -1479,9 +1466,9 @@ impl PruneMethodHeap { } #[instrument(skip_all, target = "gfx::pruner")] - fn drain(&mut self, methods: Vec<(EpochIndex, GraphicsMethod)>) { + fn drain(&mut self, method_recv: &async_channel::Receiver<(EpochIndex, GraphicsMethod)>) { // Process as many methods as we can - for (epoch, method) in methods { + while let Ok((epoch, method)) = method_recv.try_recv() { if epoch < self.epoch { // Discard old rubbish t!( @@ -1723,15 +1710,13 @@ impl EventHandler for Stage { self.close_pending_batches(); // Screen is off so collect all methods into the pruner - let methods = std::mem::take(&mut *self.method_queue.lock()); - self.pruner.drain(methods); + self.pruner.drain(&self.method_recv); } ScreenState::Off => { assert!(self.pending_batches.is_empty()); // Screen is off so collect all methods into the pruner - let methods = std::mem::take(&mut *self.method_queue.lock()); - self.pruner.drain(methods); + self.pruner.drain(&self.method_recv); } ScreenState::ReadyOn => { // We actually want to skip draining the prune queue the first time so