Skip to content

Commit

Permalink
keep track of failed context borrows
Browse files Browse the repository at this point in the history
  • Loading branch information
samuelselleck committed Oct 30, 2024
1 parent b619509 commit 949b80d
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 19 deletions.
2 changes: 1 addition & 1 deletion pax-runtime-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ pub trait RenderContext {
fn layers(&self) -> usize;
fn resize_layers_to(&mut self, layer_count: usize, dirty_canvases: Rc<RefCell<Vec<bool>>>);
fn clear(&mut self, layer: usize);
fn flush(&mut self, layer: usize);
fn flush(&mut self, layer: usize, dirty_canvases: Rc<RefCell<Vec<bool>>>);
fn resize(&mut self, width: usize, height: usize);
}

Expand Down
8 changes: 4 additions & 4 deletions pax-runtime/src/engine/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,6 @@ impl PaxEngine {
/// a. find lowest node (last child of last node)
/// b. start rendering, from lowest node on-up, throughout tree
pub fn tick(&mut self) -> Vec<NativeMessage> {
// self.runtime_context.set_all_canvases_dirty();
//
// 1. UPDATE NODES (properties, etc.). This part we should be able to
// completely remove once reactive properties dirty-dag is a thing.
Expand Down Expand Up @@ -299,7 +298,7 @@ impl PaxEngine {
.borrow()
.get(i)
.cloned()
.unwrap_or(true)
.unwrap_or(false)
{
rcs.clear(i);
}
Expand All @@ -310,10 +309,11 @@ impl PaxEngine {
.recurse_render_queue(&mut self.runtime_context, rcs);
self.runtime_context.recurse_flush_queued_renders(rcs);

self.runtime_context.clear_all_dirty_canvases();

for i in 0..rcs.layers() {
rcs.flush(i);
rcs.flush(i, Rc::clone(&self.runtime_context.dirty_canvases));
}
self.runtime_context.clear_all_dirty_canvases();

//dirtify the canvases that where created this frame
for i in new_range {
Expand Down
56 changes: 45 additions & 11 deletions pax-runtime/src/engine/pax_pixels_render_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pub struct PaxPixelsRenderer {
layer_factory:
Rc<dyn Fn(usize) -> Pin<Box<dyn Future<Output = Option<WgpuRenderer<'static>>>>>>,
image_map: HashMap<String, Image>,
failed_context_gets: RefCell<Vec<bool>>,
}

pub enum RenderLayerState {
Expand All @@ -24,6 +25,7 @@ impl PaxPixelsRenderer {
backends: Default::default(),
layer_factory: Rc::new(layer_factory),
image_map: Default::default(),
failed_context_gets: RefCell::new(vec![]),
}
}
}
Expand All @@ -34,10 +36,17 @@ impl PaxPixelsRenderer {
match backends.get_mut(layer) {
Some(layer_state) => match layer_state {
RenderLayerState::Pending => {
log::warn!(
"tried to retrieve layer {} context that wasn't ready",
layer
);
let mut failed_context_gets = self.failed_context_gets.borrow_mut();
if failed_context_gets.len() <= layer {
failed_context_gets.resize(layer + 1, false);
}
failed_context_gets[layer] = true;
// this happens to often to be useful right now - how to handle asyncness
// better here feels important
// log::warn!(
// "tried to retrieve layer {} context that wasn't ready",
// layer
// );
}
RenderLayerState::Ready(renderer) => f(renderer),
},
Expand Down Expand Up @@ -155,13 +164,20 @@ impl RenderContext for PaxPixelsRenderer {
let dirty_canvases = Rc::clone(&dirty_canvases);
wasm_bindgen_futures::spawn_local(async move {
let backend = (factory)(i).await;
if let (Some(change), Some(backend)) =
(backends.borrow_mut().get_mut(i), backend)
{
*change = RenderLayerState::Ready(backend);
if let Some(dirty_bit) = dirty_canvases.borrow_mut().get_mut(i) {
*dirty_bit = true;
match (backends.borrow_mut().get_mut(i), backend) {
(Some(change), Some(backend)) => {
*change = RenderLayerState::Ready(backend);
if let Some(dirty_bit) = dirty_canvases.borrow_mut().get_mut(i) {
*dirty_bit = true;
}
}
(Some(_), None) => log::warn!(
"failed to set poll state to ready: backend failed to initialize"
),
(None, Some(_)) => {
log::warn!("failed to set poll state to ready: layer doesn't exist anymore")
}
(None, None) => log::warn!("failed to set poll state to ready: layer doesn't exist AND backend failed to initialize")
}
});
}
Expand All @@ -175,8 +191,26 @@ impl RenderContext for PaxPixelsRenderer {
});
}

fn flush(&mut self, layer: usize) {
fn flush(&mut self, layer: usize, dirty_canvases: Rc<RefCell<Vec<bool>>>) {
// HACK: GPU rendering currently doesn't correctly handle
// re-dirtyfying canvases that where created but not ready before
// being drawn to - maybe encapsulate canvas dirtifiation inside
// rendercontext?
if let Some(dirty_bit) = dirty_canvases.borrow_mut().get_mut(layer) {
*dirty_bit = true;
}

self.with_layer_context(layer, |context| {
if let Some(failed) = self.failed_context_gets.borrow_mut().get_mut(layer) {
if *failed {
if let Some(dirty_bit) = dirty_canvases.borrow_mut().get_mut(layer) {
// if we failed to draw to this layer last frame because the context wasn't
// vailable yet, set this canvas to dirty for next frame
*dirty_bit = true;
}
*failed = false;
}
}
context.flush();
});
}
Expand Down
2 changes: 1 addition & 1 deletion pax-runtime/src/engine/piet_render_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ impl<R: piet::RenderContext> api::RenderContext for PietRenderer<R> {
}
}

fn flush(&mut self, _layer: usize) {
fn flush(&mut self, _layer: usize, _dirty_canvases: Rc<RefCell<Vec<bool>>>) {
// NOTE: used for GPU rendering to flush changes to the screen, not needed
// during CPU rendering
}
Expand Down
4 changes: 2 additions & 2 deletions pax-runtime/src/properties.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ impl RuntimeContext {

pub fn resize_canvas_layers_to(&self, id: usize) {
let mut dirty_canvases = borrow_mut!(self.dirty_canvases);
dirty_canvases.resize(id, false);
dirty_canvases.resize(id, true);
}

pub fn clear_all_dirty_canvases(&self) {
Expand All @@ -171,7 +171,7 @@ impl RuntimeContext {
}

pub fn is_canvas_dirty(&self, id: &usize) -> bool {
*borrow!(self.dirty_canvases).get(*id).unwrap_or(&false)
*borrow!(self.dirty_canvases).get(*id).unwrap_or(&true)
}

pub fn set_all_canvases_dirty(&self) {
Expand Down

0 comments on commit 949b80d

Please sign in to comment.