Files
yawn/core/render_graph/store.rs
T
Ampandheaust 31d3ae21ff core: manual buffer sync with sync-rows, reuse unchanged buffers and pipelines across activations
Also lets the screenshot suite point at another reference directory and settle longer.

Amp-Thread-ID: https://ampcode.com/threads/T-01a0b2dd-db32-712d-99ce-12ce4a86d979
Co-authored-by: Heaust Azure <heaust.azure@gmail.com>
2026-09-18 05:53:44 +00:00

128 lines
3.7 KiB
Rust

use std::collections::HashMap;
use crate::gpu::Wgpu;
use crate::gpu_resource::GpuResources;
use crate::graph::RenderGraph;
use crate::render_data::RenderData;
pub struct Loadout {
pub graph: RenderGraph,
pub resources: GpuResources,
}
#[derive(Default)]
pub struct Store {
graphs: HashMap<String, RenderGraph>,
texture_sources: HashMap<String, HashMap<u32, web_sys::ImageBitmap>>,
active: Option<Loadout>,
}
impl Store {
pub fn save(&mut self, graph: RenderGraph) -> String {
let id = graph.id.clone();
self.graphs.insert(id.clone(), graph);
id
}
pub fn switch(&mut self, id: &str, gpu: &Wgpu, data: &RenderData) -> Result<(), String> {
let graph = self.graphs.get(id).ok_or("GRAPH_UNKNOWN")?.clone();
let mut resources = GpuResources::activate(&graph, gpu, data, self.active.as_ref())?;
for (name, levels) in &self.texture_sources {
for (mip_level, image) in levels {
if resources.needs_upload(name, *mip_level) {
resources.upload_texture(name, *mip_level, image, gpu)?;
}
}
}
self.active = Some(Loadout { graph, resources });
Ok(())
}
pub fn upload_texture(
&mut self,
name: String,
mip_level: u32,
image: web_sys::ImageBitmap,
gpu: &Wgpu,
) -> Result<(), String> {
if let Some(active) = &mut self.active {
if active.resources.texture_slots.contains_key(&name) {
active
.resources
.upload_texture(&name, mip_level, &image, gpu)?;
}
}
let levels = self.texture_sources.entry(name).or_default();
if let Some(previous) = levels.insert(mip_level, image) {
previous.close();
}
Ok(())
}
pub fn delete_texture(&mut self, name: &str) {
if let Some(levels) = self.texture_sources.remove(name) {
for image in levels.into_values() {
image.close();
}
}
}
pub fn sync_rows(
&self,
name: &str,
first: u32,
count: u32,
gpu: &Wgpu,
data: &RenderData,
) -> Result<(), String> {
match &self.active {
Some(active) => active.resources.sync_rows(name, first, count, gpu, data),
None => Ok(()),
}
}
pub fn active_mut(&mut self) -> Option<&mut Loadout> {
self.active.as_mut()
}
pub fn uses_rows(&self, name: &str) -> bool {
self.active.as_ref().is_some_and(|active| {
active
.graph
.resources
.buffers
.iter()
.any(|buffer| buffer.array == name)
})
}
pub fn refresh_rows(
&mut self,
name: &str,
gpu: &Wgpu,
data: &RenderData,
) -> Result<(), String> {
if !self.uses_rows(name) {
return Ok(());
}
self.refresh(gpu, data)
}
pub fn refresh(&mut self, gpu: &Wgpu, data: &RenderData) -> Result<(), String> {
let Some(active) = self.active.as_ref() else {
return Ok(());
};
let graph = active.graph.clone();
let mut resources = GpuResources::activate(&graph, gpu, data, self.active.as_ref())?;
for (name, levels) in &self.texture_sources {
for (mip_level, image) in levels {
if resources.needs_upload(name, *mip_level) {
resources.upload_texture(name, *mip_level, image, gpu)?;
}
}
}
self.active = Some(Loadout { graph, resources });
Ok(())
}
}