Skip to content

Commit

Permalink
Support per-output scene updates in renderer
Browse files Browse the repository at this point in the history
  • Loading branch information
wkozyra95 committed Feb 2, 2024
1 parent 024a76a commit 88d467d
Show file tree
Hide file tree
Showing 22 changed files with 383 additions and 496 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ jobs:
- name: 📖 Check formatting
run: cargo fmt --all --check

- name: 🛠 Cargo build
run: |
cargo build
cargo build --no-default-features
- name: 📎 Run clippy
run: cargo clippy --workspace --all-targets --all-features -- -D warnings

Expand Down
4 changes: 3 additions & 1 deletion compositor_pipeline/src/pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,8 @@ impl Pipeline {

self.inputs.insert(input_id.clone(), pipeline_input.into());

self.queue.add_input(input_id);
self.queue.add_input(input_id.clone());
self.renderer.register_input(input_id);
Ok(port)
}

Expand All @@ -160,6 +161,7 @@ impl Pipeline {

self.inputs.remove(input_id);
self.queue.remove_input(input_id);
self.renderer.unregister_input(input_id);
Ok(())
}

Expand Down
73 changes: 37 additions & 36 deletions compositor_render/src/scene/scene_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ pub(super) struct BuildStateTreeCtx<'a> {
}

pub(crate) struct SceneState {
outputs: Vec<OutputSceneState>,
output_scenes: HashMap<OutputId, OutputScene>,
output_states: HashMap<OutputId, OutputSceneState>,
last_pts: Duration,
// Input resolutions from the last render
input_resolutions: HashMap<InputId, Resolution>,
}

#[derive(Debug, Clone)]
struct OutputSceneState {
output_id: OutputId,
root: StatefulComponent,
resolution: Resolution,
}
Expand All @@ -49,7 +49,8 @@ pub(crate) struct OutputNode {
impl SceneState {
pub fn new() -> Self {
Self {
outputs: vec![],
output_scenes: HashMap::new(),
output_states: HashMap::new(),
last_pts: Duration::ZERO,
input_resolutions: HashMap::new(),
}
Expand All @@ -65,15 +66,21 @@ impl SceneState {
// TODO: pass input stream sizes and populate it in the ComponentState tree
}

pub(crate) fn unregister_output(&mut self, output_id: &OutputId) {
self.output_scenes.remove(output_id);
self.output_states.remove(output_id);
}

pub(crate) fn update_scene(
&mut self,
outputs: Vec<OutputScene>,
output_scene: OutputScene,
renderers: &Renderers,
text_renderer_ctx: &TextRendererCtx,
) -> Result<Vec<OutputNode>, SceneError> {
validate_scene_update(&outputs)?;
) -> Result<OutputNode, SceneError> {
let output_id = output_scene.output_id.clone();
validate_scene_update(&self.output_scenes, &output_scene)?;

for output in self.outputs.iter_mut() {
for (_, output) in self.output_states.iter_mut() {
recalculate_layout(
&mut output.root,
Some(output.resolution.into()),
Expand All @@ -84,44 +91,38 @@ impl SceneState {

let ctx = BuildStateTreeCtx {
prev_state: self
.outputs
.iter()
.flat_map(|o| {
.output_states
.get(&output_id)
.map(|o| {
let mut components = HashMap::new();
gather_components_with_id(&o.root, &mut components);
components
})
.collect(),
.unwrap_or_else(|| HashMap::new()),
last_render_pts: self.last_pts,
input_resolutions: &self.input_resolutions,
text_renderer_ctx,
renderers,
};
let output_states = outputs
.into_iter()
.map(|o| {
Ok(OutputSceneState {
output_id: o.output_id,
root: o.root.stateful_component(&ctx)?,
resolution: o.resolution,
})
})
.collect::<Result<Vec<_>, _>>()?;
let nodes = output_states
.iter()
.map(|output| {
Ok(OutputNode {
output_id: output.output_id.clone(),
node: output
.root
.intermediate_node()
.build_tree(Some(output.resolution), self.last_pts)?,
resolution: output.resolution,
})
})
.collect::<Result<_, _>>()?;
self.outputs = output_states;
Ok(nodes)

let output_state_tree = OutputSceneState {
root: output_scene.root.clone().stateful_component(&ctx)?,
resolution: output_scene.resolution,
};

let output_node_tree = OutputNode {
output_id: output_id.clone(),
node: output_state_tree
.root
.intermediate_node()
.build_tree(Some(output_scene.resolution), self.last_pts)?,
resolution: output_scene.resolution,
};

self.output_scenes.insert(output_id.clone(), output_scene);
self.output_states.insert(output_id, output_state_tree);

Ok(output_node_tree)
}
}

Expand Down
25 changes: 18 additions & 7 deletions compositor_render/src/scene/validation.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::collections::HashSet;
use std::collections::{HashMap, HashSet};

use crate::RendererId;
use crate::{OutputId, RendererId};

use super::{Component, ComponentId, OutputScene, SceneError};

Expand Down Expand Up @@ -32,13 +32,24 @@ impl Component {
}
}

pub(super) fn validate_scene_update(outputs: &[OutputScene]) -> Result<(), SceneError> {
validate_component_ids_uniqueness(outputs)?;
validate_web_renderer_ids_uniqueness(outputs)?;
pub(super) fn validate_scene_update(
old_outputs: &HashMap<OutputId, OutputScene>,
updated_output: &OutputScene,
) -> Result<(), SceneError> {
let updated_outputs: Vec<&OutputScene> = old_outputs
.iter()
.map(|(id, output)| match id {
id if id == &updated_output.output_id => updated_output,
_ => output,
})
.collect();

validate_component_ids_uniqueness(&updated_outputs)?;
validate_web_renderer_ids_uniqueness(&updated_outputs)?;
Ok(())
}

fn validate_component_ids_uniqueness(outputs: &[OutputScene]) -> Result<(), SceneError> {
fn validate_component_ids_uniqueness(outputs: &[&OutputScene]) -> Result<(), SceneError> {
let mut ids: HashSet<&ComponentId> = HashSet::new();

fn visit<'a>(
Expand All @@ -65,7 +76,7 @@ fn validate_component_ids_uniqueness(outputs: &[OutputScene]) -> Result<(), Scen
.try_for_each(|output| visit(&output.root, &mut ids))
}

fn validate_web_renderer_ids_uniqueness(outputs: &[OutputScene]) -> Result<(), SceneError> {
fn validate_web_renderer_ids_uniqueness(outputs: &[&OutputScene]) -> Result<(), SceneError> {
let mut web_renderer_ids: HashSet<&RendererId> = HashSet::new();

fn visit<'a>(
Expand Down
65 changes: 42 additions & 23 deletions compositor_render/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ pub mod render_graph;
mod render_loop;
pub mod renderers;

pub(crate) use render_loop::NodeRenderPass;

pub struct RendererOptions {
pub web_renderer: web_renderer::WebRendererInitOptions,
pub framerate: Framerate,
Expand Down Expand Up @@ -89,6 +87,27 @@ impl Renderer {
Ok((Self(Arc::new(Mutex::new(renderer))), event_loop))
}

pub fn register_input(&self, input_id: InputId) {
self.0.lock().unwrap().render_graph.register_input(input_id);
}

pub fn unregister_input(&self, input_id: &InputId) {
self.0
.lock()
.unwrap()
.render_graph
.unregister_input(input_id);
}

pub fn unregister_output(&self, output_id: &OutputId) {
self.0
.lock()
.unwrap()
.render_graph
.unregister_output(output_id);
self.0.lock().unwrap().scene.unregister_output(output_id)
}

pub fn register_renderer(&self, spec: RendererSpec) -> Result<(), RegisterRendererError> {
let ctx = self.0.lock().unwrap().register_ctx();
match spec {
Expand Down Expand Up @@ -173,7 +192,7 @@ impl InnerRenderer {

pub fn render(
&mut self,
mut inputs: FrameSet<InputId>,
inputs: FrameSet<InputId>,
) -> Result<FrameSet<OutputId>, RenderSceneError> {
let ctx = &mut RenderCtx {
wgpu_ctx: &self.wgpu_ctx,
Expand All @@ -192,34 +211,34 @@ impl InnerRenderer {
self.scene
.register_render_event(inputs.pts, input_resolutions);

populate_inputs(ctx, &mut self.render_graph, &mut inputs).unwrap();
run_transforms(ctx, &mut self.render_graph, inputs.pts).unwrap();
let frames = read_outputs(ctx, &mut self.render_graph, inputs.pts).unwrap();
let pts = inputs.pts.clone();
populate_inputs(ctx, &mut self.render_graph, inputs);
run_transforms(ctx, &mut self.render_graph, pts);
let frames = read_outputs(ctx, &mut self.render_graph, pts);

scope.pop(&ctx.wgpu_ctx.device)?;

Ok(FrameSet {
frames,
pts: inputs.pts,
})
Ok(FrameSet { frames, pts })
}

pub fn update_scene(
&mut self,
scenes: Vec<scene::OutputScene>,
outputs: Vec<scene::OutputScene>,
) -> Result<(), UpdateSceneError> {
let output_nodes =
self.scene
.update_scene(scenes, &self.renderers, &self.text_renderer_ctx)?;
self.render_graph.update(
&RenderCtx {
wgpu_ctx: &self.wgpu_ctx,
text_renderer_ctx: &self.text_renderer_ctx,
renderers: &self.renderers,
stream_fallback_timeout: self.stream_fallback_timeout,
},
output_nodes,
)?;
for output_scene in outputs {
let output_node =
self.scene
.update_scene(output_scene, &self.renderers, &self.text_renderer_ctx)?;
self.render_graph.update(
&RenderCtx {
wgpu_ctx: &self.wgpu_ctx,
text_renderer_ctx: &self.text_renderer_ctx,
renderers: &self.renderers,
stream_fallback_timeout: self.stream_fallback_timeout,
},
output_node,
)?;
}
Ok(())
}
}
Loading

0 comments on commit 88d467d

Please sign in to comment.