Compare commits
No commits in common. "ef68b2a4c5bb6d95a2ca5bd35e1023a74c47c8f5" and "c846d52b0d6cff8df94c8b15433e927586b424c6" have entirely different histories.
ef68b2a4c5
...
c846d52b0d
|
@ -1867,7 +1867,6 @@ dependencies = [
|
|||
"instant",
|
||||
"itertools 0.11.0",
|
||||
"lyra-ecs",
|
||||
"lyra-game-derive",
|
||||
"lyra-math",
|
||||
"lyra-reflect",
|
||||
"lyra-resource",
|
||||
|
@ -1888,15 +1887,6 @@ dependencies = [
|
|||
"winit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lyra-game-derive"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.51",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lyra-math"
|
||||
version = "0.1.0"
|
||||
|
|
|
@ -4,7 +4,6 @@ version = "0.0.1"
|
|||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
lyra-game-derive = { path = "./lyra-game-derive" }
|
||||
lyra-resource = { path = "../lyra-resource" }
|
||||
lyra-ecs = { path = "../lyra-ecs", features = [ "math" ] }
|
||||
lyra-reflect = { path = "../lyra-reflect", features = [ "math" ] }
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
[package]
|
||||
name = "lyra-game-derive"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
proc-macro2 = "1.0.70"
|
||||
quote = "1.0.33"
|
||||
syn = "2.0.41"
|
|
@ -1,35 +0,0 @@
|
|||
use quote::quote;
|
||||
use syn::{parse_macro_input, DeriveInput};
|
||||
|
||||
#[proc_macro_derive(RenderGraphLabel)]
|
||||
pub fn derive_render_graph_label(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
let input = parse_macro_input!(input as DeriveInput);
|
||||
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
|
||||
|
||||
let type_ident = &input.ident;
|
||||
|
||||
proc_macro::TokenStream::from(quote! {
|
||||
impl #impl_generics crate::render::graph::RenderGraphLabel for #type_ident #ty_generics #where_clause {
|
||||
fn rc_clone(&self) -> std::rc::Rc<dyn crate::render::graph::RenderGraphLabel> {
|
||||
std::rc::Rc::new(self.clone())
|
||||
}
|
||||
|
||||
/* fn as_dyn(&self) -> &dyn crate::render::graph::RenderGraphLabel {
|
||||
&self
|
||||
}
|
||||
|
||||
fn as_partial_eq(&self) -> &dyn PartialEq<dyn crate::render::graph::RenderGraphLabel> {
|
||||
self
|
||||
} */
|
||||
|
||||
fn as_label_hash(&self) -> u64 {
|
||||
let tyid = ::std::any::TypeId::of::<Self>();
|
||||
|
||||
let mut s = ::std::hash::DefaultHasher::new();
|
||||
::std::hash::Hash::hash(&tyid, &mut s);
|
||||
::std::hash::Hash::hash(self, &mut s);
|
||||
::std::hash::Hasher::finish(&s)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
|
@ -1,6 +1,9 @@
|
|||
mod pass;
|
||||
use std::{
|
||||
cell::RefCell, collections::{HashMap, VecDeque}, fmt::Debug, hash::Hash, rc::Rc, sync::Arc
|
||||
cell::RefCell,
|
||||
collections::{HashMap, VecDeque},
|
||||
rc::Rc,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use itertools::Itertools;
|
||||
|
@ -19,62 +22,6 @@ use wgpu::ComputePass;
|
|||
|
||||
use super::resource::{ComputePipeline, Pipeline, RenderPipeline};
|
||||
|
||||
pub trait RenderGraphLabel: Debug + 'static {
|
||||
fn rc_clone(&self) -> Rc<dyn RenderGraphLabel>;
|
||||
//fn as_dyn(&self) -> &dyn RenderGraphLabel;
|
||||
//fn as_partial_eq(&self) -> &dyn PartialEq<dyn RenderGraphLabel>;
|
||||
fn as_label_hash(&self) -> u64;
|
||||
|
||||
fn label_eq_rc(&self, other: &Rc<dyn RenderGraphLabel>) -> bool {
|
||||
self.as_label_hash() == other.as_label_hash()
|
||||
}
|
||||
|
||||
fn label_eq(&self, other: &dyn RenderGraphLabel) -> bool {
|
||||
self.as_label_hash() == other.as_label_hash()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct RenderGraphLabelValue(Rc<dyn RenderGraphLabel>);
|
||||
|
||||
impl Debug for RenderGraphLabelValue {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<L: RenderGraphLabel> From<L> for RenderGraphLabelValue {
|
||||
fn from(value: L) -> Self {
|
||||
Self(Rc::new(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Rc<dyn RenderGraphLabel>> for RenderGraphLabelValue {
|
||||
fn from(value: Rc<dyn RenderGraphLabel>) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Rc<dyn RenderGraphLabel>> for RenderGraphLabelValue {
|
||||
fn from(value: &Rc<dyn RenderGraphLabel>) -> Self {
|
||||
Self(value.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for RenderGraphLabelValue {
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
state.write_u64(self.0.as_label_hash());
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for RenderGraphLabelValue {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.0.label_eq_rc(&other.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for RenderGraphLabelValue {}
|
||||
|
||||
struct PassEntry {
|
||||
inner: Arc<RefCell<dyn RenderGraphPass>>,
|
||||
desc: Arc<RenderGraphPassDesc>,
|
||||
|
@ -83,7 +30,7 @@ struct PassEntry {
|
|||
}
|
||||
|
||||
pub struct BindGroupEntry {
|
||||
pub label: RenderGraphLabelValue,
|
||||
pub name: String,
|
||||
/// BindGroup
|
||||
pub bg: Rc<wgpu::BindGroup>,
|
||||
/// BindGroupLayout
|
||||
|
@ -92,7 +39,7 @@ pub struct BindGroupEntry {
|
|||
|
||||
#[allow(dead_code)]
|
||||
struct ResourcedSlot {
|
||||
label: RenderGraphLabelValue,
|
||||
name: String,
|
||||
ty: SlotType,
|
||||
value: SlotValue,
|
||||
}
|
||||
|
@ -117,13 +64,11 @@ pub struct RenderGraph {
|
|||
device: Rc<wgpu::Device>,
|
||||
queue: Rc<wgpu::Queue>,
|
||||
slots: FxHashMap<u64, ResourcedSlot>,
|
||||
/// HashMap used to lookup the slot id using the label's hash
|
||||
slot_label_lookup: FxHashMap<RenderGraphLabelValue, u64>,
|
||||
slot_names: HashMap<String, u64>,
|
||||
passes: FxHashMap<u64, PassEntry>,
|
||||
// TODO: Use a SlotMap
|
||||
bind_groups: FxHashMap<u64, BindGroupEntry>,
|
||||
/// HashMap used to lookup the bind group id using the label's hash
|
||||
bind_group_names: FxHashMap<RenderGraphLabelValue, u64>,
|
||||
bind_group_names: HashMap<String, u64>,
|
||||
// TODO: make pipelines a `type` parameter in RenderPasses,
|
||||
// then the pipelines can be retrieved via TypeId to the pass.
|
||||
pipelines: FxHashMap<u64, PipelineResource>,
|
||||
|
@ -138,7 +83,7 @@ impl RenderGraph {
|
|||
device,
|
||||
queue,
|
||||
slots: Default::default(),
|
||||
slot_label_lookup: Default::default(),
|
||||
slot_names: Default::default(),
|
||||
passes: Default::default(),
|
||||
bind_groups: Default::default(),
|
||||
bind_group_names: Default::default(),
|
||||
|
@ -157,12 +102,8 @@ impl RenderGraph {
|
|||
self.current_id
|
||||
}
|
||||
|
||||
pub(crate) fn slot_id_rc(&self, label: &RenderGraphLabelValue) -> Option<u64> {
|
||||
self.slot_label_lookup.get(&label.clone().into()).cloned()
|
||||
}
|
||||
|
||||
pub fn slot_id(&self, label: &dyn RenderGraphLabel) -> Option<u64> {
|
||||
self.slot_label_lookup.get(&label.rc_clone().into()).cloned()
|
||||
pub fn slot_id(&self, name: &str) -> Option<u64> {
|
||||
self.slot_names.get(name).cloned()
|
||||
}
|
||||
|
||||
#[instrument(skip(self, pass), level = "debug")]
|
||||
|
@ -172,53 +113,48 @@ impl RenderGraph {
|
|||
// collect all the slots of the pass
|
||||
for slot in &mut desc.slots {
|
||||
if let Some((id, other)) = self
|
||||
.slot_label_lookup
|
||||
.get(&slot.label)
|
||||
.slot_names
|
||||
.get(&slot.name)
|
||||
.and_then(|id| self.slots.get_mut(id).map(|s| (id, s)))
|
||||
{
|
||||
debug_assert_eq!(
|
||||
slot.ty, other.ty,
|
||||
"slot {:?} in pass {:?} does not match existing slot of same name",
|
||||
slot.label, desc.label
|
||||
"slot {} in pass {} does not match existing slot of same name",
|
||||
slot.name, desc.name
|
||||
);
|
||||
|
||||
trace!(
|
||||
"Found existing slot for {:?}, changing id to {}",
|
||||
slot.label,
|
||||
"Found existing slot for {}, changing id to {}",
|
||||
slot.name,
|
||||
id
|
||||
);
|
||||
|
||||
// if there is a slot of the same name
|
||||
slot.id = *id;
|
||||
} else {
|
||||
debug_assert!(!self.slots.contains_key(&slot.id),
|
||||
"Reuse of id detected in render graph! Pass: {:?}, slot: {:?}",
|
||||
desc.label, slot.label,
|
||||
);
|
||||
|
||||
let res_slot = ResourcedSlot {
|
||||
label: slot.label.clone(),
|
||||
name: slot.name.clone(),
|
||||
ty: slot.ty,
|
||||
value: slot.value.clone().unwrap_or(SlotValue::None),
|
||||
};
|
||||
|
||||
self.slots.insert(slot.id, res_slot);
|
||||
self.slot_label_lookup.insert(slot.label.clone(), slot.id);
|
||||
self.slot_names.insert(slot.name.clone(), slot.id);
|
||||
}
|
||||
}
|
||||
|
||||
// get clones of the bind groups and layouts
|
||||
for (label, bg, bgl) in &desc.bind_groups {
|
||||
for (name, bg, bgl) in &desc.bind_groups {
|
||||
let bg_id = self.next_id();
|
||||
self.bind_groups.insert(
|
||||
bg_id,
|
||||
BindGroupEntry {
|
||||
label: label.clone(),
|
||||
name: name.clone(),
|
||||
bg: bg.clone(),
|
||||
layout: bgl.clone(),
|
||||
},
|
||||
);
|
||||
self.bind_group_names.insert(label.clone().into(), bg_id);
|
||||
self.bind_group_names.insert(name.clone(), bg_id);
|
||||
}
|
||||
|
||||
let index = self.execution_graph.add_node(desc.id);
|
||||
|
@ -283,15 +219,15 @@ impl RenderGraph {
|
|||
while let Some(bufwr) = context.buffer_writes.pop_front() {
|
||||
let slot = self
|
||||
.slots
|
||||
.get(&self.slot_id_rc(&bufwr.target_slot).unwrap())
|
||||
.get(&self.slot_id(&bufwr.target_slot).unwrap())
|
||||
.expect(&format!(
|
||||
"Failed to find slot '{:?}' for buffer write",
|
||||
"Failed to find slot '{}' for buffer write",
|
||||
bufwr.target_slot
|
||||
));
|
||||
let buf = slot
|
||||
.value
|
||||
.as_buffer()
|
||||
.expect(&format!("Slot '{:?}' is not a buffer", bufwr.target_slot));
|
||||
.expect(&format!("Slot '{}' is not a buffer", bufwr.target_slot));
|
||||
|
||||
self.queue.write_buffer(buf, bufwr.offset, &bufwr.bytes);
|
||||
}
|
||||
|
@ -307,7 +243,7 @@ impl RenderGraph {
|
|||
.collect();
|
||||
let path_names = sorted
|
||||
.iter()
|
||||
.map(|i| self.pass(*i).unwrap().label.clone())
|
||||
.map(|i| self.pass(*i).unwrap().name.clone())
|
||||
.collect_vec();
|
||||
trace!("Render graph execution order: {:?}", path_names);
|
||||
|
||||
|
@ -316,7 +252,7 @@ impl RenderGraph {
|
|||
let pass = self.passes.get(&pass_id).unwrap();
|
||||
let pass_inn = pass.inner.clone();
|
||||
let pass_desc = pass.desc.clone();
|
||||
let label = format!("{:?} Encoder", pass_desc.label);
|
||||
let label = format!("{} Encoder", pass_desc.name);
|
||||
|
||||
// encoders are not needed for presenter nodes.
|
||||
let encoder = if pass_desc.pass_type.should_have_pipeline() {
|
||||
|
@ -341,7 +277,7 @@ impl RenderGraph {
|
|||
self.queue.submit(encoders.drain(..));
|
||||
}
|
||||
|
||||
trace!("Executing {:?}", pass_desc.label);
|
||||
trace!("Executing {}", pass_desc.name);
|
||||
let mut inner = pass_inn.borrow_mut();
|
||||
inner.execute(self, &*pass_desc, &mut context);
|
||||
|
||||
|
@ -400,30 +336,24 @@ impl RenderGraph {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn bind_group_id(&self, label: &dyn RenderGraphLabel) -> Option<u64> {
|
||||
self.bind_group_names.get(&label.rc_clone().into()).copied()
|
||||
pub fn bind_group_id(&self, name: &str) -> Option<u64> {
|
||||
self.bind_group_names.get(name).copied()
|
||||
}
|
||||
|
||||
pub fn add_edge(&mut self, from: impl RenderGraphLabel, to: impl RenderGraphLabel)
|
||||
{
|
||||
let from = RenderGraphLabelValue::from(from);
|
||||
let to = RenderGraphLabelValue::from(to);
|
||||
|
||||
pub fn add_edge(&mut self, from: &str, to: &str) {
|
||||
let from_idx = self
|
||||
.passes
|
||||
.iter()
|
||||
.find(|p| p.1.desc.label == from)
|
||||
.find(|p| p.1.desc.name == from)
|
||||
.map(|p| p.1.graph_index)
|
||||
.expect("Failed to find from pass");
|
||||
let to_idx = self
|
||||
.passes
|
||||
.iter()
|
||||
.find(|p| p.1.desc.label == to)
|
||||
.find(|p| p.1.desc.name == to)
|
||||
.map(|p| p.1.graph_index)
|
||||
.expect("Failed to find to pass");
|
||||
|
||||
debug_assert_ne!(from_idx, to_idx, "cannot add edges between the same node");
|
||||
|
||||
self.execution_graph.add_edge(from_idx, to_idx, ());
|
||||
}
|
||||
|
||||
|
@ -454,13 +384,13 @@ impl RenderGraph {
|
|||
pub fn set_bind_groups<'a>(
|
||||
&'a self,
|
||||
pass: &mut ComputePass<'a>,
|
||||
bind_groups: &[(&dyn RenderGraphLabel, u32)],
|
||||
bind_groups: &[(&str, u32)],
|
||||
) {
|
||||
for (label, index) in bind_groups {
|
||||
for (name, index) in bind_groups {
|
||||
let bg = self
|
||||
.bind_group_id(*label)
|
||||
.bind_group_id(name)
|
||||
.map(|bgi| self.bind_group(bgi))
|
||||
.expect(&format!("Could not find bind group '{:?}'", label));
|
||||
.expect(&format!("Could not find bind group '{}'", name));
|
||||
|
||||
pass.set_bind_group(*index, bg, &[]);
|
||||
}
|
||||
|
@ -470,7 +400,7 @@ impl RenderGraph {
|
|||
/// A queued write to a GPU buffer targeting a graph slot.
|
||||
pub(crate) struct GraphBufferWrite {
|
||||
/// The name of the slot that has the resource that will be written
|
||||
target_slot: RenderGraphLabelValue,
|
||||
target_slot: String,
|
||||
offset: u64,
|
||||
bytes: Vec<u8>,
|
||||
}
|
||||
|
@ -525,9 +455,9 @@ impl<'a> RenderGraphContext<'a> {
|
|||
/// data will be submitted to the GPU queue right after the prepare stage for all passes
|
||||
/// is ran.
|
||||
#[instrument(skip(self, bytes), level="trace", fields(size = bytes.len()))]
|
||||
pub fn queue_buffer_write(&mut self, target_slot: impl RenderGraphLabel, offset: u64, bytes: &[u8]) {
|
||||
pub fn queue_buffer_write(&mut self, target_slot: &str, offset: u64, bytes: &[u8]) {
|
||||
self.buffer_writes.push_back(GraphBufferWrite {
|
||||
target_slot: target_slot.into(),
|
||||
target_slot: target_slot.to_string(),
|
||||
offset,
|
||||
bytes: bytes.to_vec(),
|
||||
})
|
||||
|
@ -537,7 +467,7 @@ impl<'a> RenderGraphContext<'a> {
|
|||
#[instrument(skip(self, bytes), level="trace", fields(size = std::mem::size_of::<T>()))]
|
||||
pub fn queue_buffer_write_with<T: bytemuck::NoUninit>(
|
||||
&mut self,
|
||||
target_slot: impl RenderGraphLabel,
|
||||
target_slot: &str,
|
||||
offset: u64,
|
||||
bytes: T,
|
||||
) {
|
||||
|
|
|
@ -4,7 +4,7 @@ use lyra_ecs::World;
|
|||
|
||||
use crate::render::resource::PipelineDescriptor;
|
||||
|
||||
use super::{RenderGraph, RenderGraphContext, RenderGraphLabel, RenderGraphLabelValue, RenderTarget};
|
||||
use super::{RenderGraph, RenderGraphContext, RenderTarget};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)]
|
||||
pub enum RenderPassType {
|
||||
|
@ -96,7 +96,7 @@ pub struct RenderPassSlot {
|
|||
pub ty: SlotType,
|
||||
pub attribute: SlotAttribute,
|
||||
pub id: u64,
|
||||
pub label: RenderGraphLabelValue,
|
||||
pub name: String,
|
||||
/// The descriptor of the slot value.
|
||||
/// This will be `None` if this slot is an input.
|
||||
pub value: Option<SlotValue>,
|
||||
|
@ -159,36 +159,36 @@ impl RenderGraphPipelineInfo {
|
|||
|
||||
pub struct RenderGraphPassDesc {
|
||||
pub id: u64,
|
||||
pub label: RenderGraphLabelValue,
|
||||
pub name: String,
|
||||
pub pass_type: RenderPassType,
|
||||
pub slots: Vec<RenderPassSlot>,
|
||||
slot_label_lookup: HashMap<RenderGraphLabelValue, u64>,
|
||||
slot_names: HashMap<String, u64>,
|
||||
pub pipeline_desc: Option<PipelineDescriptor>,
|
||||
pub bind_groups: Vec<(
|
||||
RenderGraphLabelValue,
|
||||
String,
|
||||
Rc<wgpu::BindGroup>,
|
||||
Option<Rc<wgpu::BindGroupLayout>>,
|
||||
)>,
|
||||
}
|
||||
|
||||
impl RenderGraphPassDesc {
|
||||
pub fn new<L: RenderGraphLabel>(
|
||||
pub fn new(
|
||||
id: u64,
|
||||
label: L,
|
||||
name: &str,
|
||||
pass_type: RenderPassType,
|
||||
pipeline_desc: Option<PipelineDescriptor>,
|
||||
bind_groups: Vec<(&dyn RenderGraphLabel, Rc<wgpu::BindGroup>, Option<Rc<wgpu::BindGroupLayout>>)>,
|
||||
bind_groups: Vec<(&str, Rc<wgpu::BindGroup>, Option<Rc<wgpu::BindGroupLayout>>)>,
|
||||
) -> Self {
|
||||
Self {
|
||||
id,
|
||||
label: label.into(),
|
||||
name: name.to_string(),
|
||||
pass_type,
|
||||
slots: vec![],
|
||||
slot_label_lookup: HashMap::default(),
|
||||
slot_names: HashMap::default(),
|
||||
pipeline_desc,
|
||||
bind_groups: bind_groups
|
||||
.into_iter()
|
||||
.map(|bg| (bg.0.rc_clone().into(), bg.1, bg.2))
|
||||
.map(|bg| (bg.0.to_string(), bg.1, bg.2))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
@ -199,15 +199,15 @@ impl RenderGraphPassDesc {
|
|||
"input slots should not have values"
|
||||
);
|
||||
|
||||
self.slot_label_lookup.insert(slot.label.clone().into(), slot.id);
|
||||
self.slot_names.insert(slot.name.clone(), slot.id);
|
||||
self.slots.push(slot);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn add_buffer_slot<L: RenderGraphLabel>(
|
||||
pub fn add_buffer_slot(
|
||||
&mut self,
|
||||
id: u64,
|
||||
label: L,
|
||||
name: &str,
|
||||
attribute: SlotAttribute,
|
||||
value: Option<SlotValue>,
|
||||
) {
|
||||
|
@ -218,7 +218,7 @@ impl RenderGraphPassDesc {
|
|||
|
||||
let slot = RenderPassSlot {
|
||||
id,
|
||||
label: label.into(),
|
||||
name: name.to_string(),
|
||||
ty: SlotType::Buffer,
|
||||
attribute,
|
||||
value,
|
||||
|
@ -227,10 +227,10 @@ impl RenderGraphPassDesc {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn add_texture_slot<L: RenderGraphLabel>(
|
||||
pub fn add_texture_slot(
|
||||
&mut self,
|
||||
id: u64,
|
||||
label: L,
|
||||
name: &str,
|
||||
attribute: SlotAttribute,
|
||||
value: Option<SlotValue>,
|
||||
) {
|
||||
|
@ -241,7 +241,7 @@ impl RenderGraphPassDesc {
|
|||
|
||||
let slot = RenderPassSlot {
|
||||
id,
|
||||
label: label.into(),
|
||||
name: name.to_string(),
|
||||
ty: SlotType::Texture,
|
||||
attribute,
|
||||
value,
|
||||
|
@ -250,10 +250,10 @@ impl RenderGraphPassDesc {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn add_texture_view_slot<L: RenderGraphLabel>(
|
||||
pub fn add_texture_view_slot(
|
||||
&mut self,
|
||||
id: u64,
|
||||
label: L,
|
||||
name: &str,
|
||||
attribute: SlotAttribute,
|
||||
value: Option<SlotValue>,
|
||||
) {
|
||||
|
@ -264,7 +264,7 @@ impl RenderGraphPassDesc {
|
|||
|
||||
let slot = RenderPassSlot {
|
||||
id,
|
||||
label: label.into(),
|
||||
name: name.to_string(),
|
||||
ty: SlotType::TextureView,
|
||||
attribute,
|
||||
value,
|
||||
|
@ -273,10 +273,10 @@ impl RenderGraphPassDesc {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn add_sampler_slot<L: RenderGraphLabel>(
|
||||
pub fn add_sampler_slot(
|
||||
&mut self,
|
||||
id: u64,
|
||||
label: L,
|
||||
name: &str,
|
||||
attribute: SlotAttribute,
|
||||
value: Option<SlotValue>,
|
||||
) {
|
||||
|
@ -287,7 +287,7 @@ impl RenderGraphPassDesc {
|
|||
|
||||
let slot = RenderPassSlot {
|
||||
id,
|
||||
label: label.into(),
|
||||
name: name.to_string(),
|
||||
ty: SlotType::Sampler,
|
||||
attribute,
|
||||
value,
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
use glam::UVec2;
|
||||
use lyra_game_derive::RenderGraphLabel;
|
||||
use tracing::warn;
|
||||
use winit::dpi::PhysicalSize;
|
||||
|
||||
|
@ -17,19 +16,6 @@ use crate::{
|
|||
scene::CameraComponent,
|
||||
};
|
||||
|
||||
#[derive(Debug, Hash, Clone, Default, PartialEq, RenderGraphLabel)]
|
||||
pub struct BasePassLabel;
|
||||
|
||||
#[derive(Debug, Hash, Clone, PartialEq, RenderGraphLabel)]
|
||||
pub enum BasePassSlots {
|
||||
DepthTexture,
|
||||
ScreenSize,
|
||||
Camera,
|
||||
MainRenderTarget,
|
||||
WindowTextureView,
|
||||
DepthTextureView,
|
||||
}
|
||||
|
||||
/// Supplies some basic things other passes needs.
|
||||
///
|
||||
/// screen size buffer, camera buffer,
|
||||
|
@ -103,13 +89,13 @@ impl RenderGraphPass for BasePass {
|
|||
|
||||
let mut desc = RenderGraphPassDesc::new(
|
||||
graph.next_id(),
|
||||
BasePassLabel,
|
||||
"base",
|
||||
RenderPassType::Node,
|
||||
None,
|
||||
vec![
|
||||
(&BasePassSlots::DepthTexture, depth_texture_bg, Some(depth_texture_bgl)),
|
||||
(&BasePassSlots::ScreenSize, screen_size_bg, Some(screen_size_bgl)),
|
||||
(&BasePassSlots::Camera, camera_bg, Some(camera_bgl)),
|
||||
("depth_texture", depth_texture_bg, Some(depth_texture_bgl)),
|
||||
("screen_size", screen_size_bg, Some(screen_size_bgl)),
|
||||
("camera", camera_bg, Some(camera_bgl)),
|
||||
],
|
||||
);
|
||||
|
||||
|
@ -118,7 +104,7 @@ impl RenderGraphPass for BasePass {
|
|||
ty: SlotType::RenderTarget,
|
||||
attribute: SlotAttribute::Output,
|
||||
id: self.main_rt_id,
|
||||
label: BasePassSlots::MainRenderTarget.into(),
|
||||
name: "main_render_target".into(),
|
||||
value: Some(SlotValue::RenderTarget(Rc::new(RefCell::new(
|
||||
render_target,
|
||||
)))),
|
||||
|
@ -126,25 +112,25 @@ impl RenderGraphPass for BasePass {
|
|||
self.window_tv_id = graph.next_id();
|
||||
desc.add_texture_view_slot(
|
||||
self.window_tv_id,
|
||||
BasePassSlots::WindowTextureView,
|
||||
"window_texture_view",
|
||||
SlotAttribute::Output,
|
||||
Some(SlotValue::Lazy),
|
||||
);
|
||||
desc.add_texture_view_slot(
|
||||
graph.next_id(),
|
||||
BasePassSlots::DepthTextureView,
|
||||
"depth_texture_view",
|
||||
SlotAttribute::Output,
|
||||
Some(SlotValue::TextureView(depth_texture_view)),
|
||||
);
|
||||
desc.add_buffer_slot(
|
||||
graph.next_id(),
|
||||
BasePassSlots::ScreenSize,
|
||||
"screen_size_buffer",
|
||||
SlotAttribute::Output,
|
||||
Some(SlotValue::Buffer(Rc::new(screen_size_buf))),
|
||||
);
|
||||
desc.add_buffer_slot(
|
||||
graph.next_id(),
|
||||
BasePassSlots::Camera,
|
||||
"camera_buffer",
|
||||
SlotAttribute::Output,
|
||||
Some(SlotValue::Buffer(Rc::new(camera_buf))),
|
||||
);
|
||||
|
@ -158,7 +144,7 @@ impl RenderGraphPass for BasePass {
|
|||
RenderCamera::new(PhysicalSize::new(self.screen_size.x, self.screen_size.y));
|
||||
let uniform = render_cam.calc_view_projection(&camera);
|
||||
|
||||
context.queue_buffer_write_with(BasePassSlots::Camera, 0, uniform)
|
||||
context.queue_buffer_write_with("camera_buffer", 0, uniform)
|
||||
} else {
|
||||
warn!("Missing camera!");
|
||||
}
|
||||
|
@ -184,7 +170,7 @@ impl RenderGraphPass for BasePass {
|
|||
|| rt.surface_config.height != self.screen_size.y
|
||||
{
|
||||
self.screen_size = UVec2::new(rt.surface_config.width, rt.surface_config.height);
|
||||
context.queue_buffer_write_with(BasePassSlots::ScreenSize, 0, self.screen_size)
|
||||
context.queue_buffer_write_with("screen_size_buffer", 0, self.screen_size)
|
||||
}
|
||||
|
||||
let surface_tex = rt.surface.get_current_texture().unwrap();
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
use lyra_game_derive::RenderGraphLabel;
|
||||
|
||||
use crate::render::{
|
||||
graph::{
|
||||
RenderGraphContext, RenderGraphPass, RenderGraphPassDesc, RenderPassType, SlotAttribute,
|
||||
|
@ -8,14 +6,6 @@ use crate::render::{
|
|||
light::LightUniformBuffers,
|
||||
};
|
||||
|
||||
#[derive(Debug, Hash, Clone, Default, PartialEq, RenderGraphLabel)]
|
||||
pub struct LightBasePassLabel;
|
||||
|
||||
#[derive(Debug, Hash, Clone, PartialEq, RenderGraphLabel)]
|
||||
pub enum LightBasePassSlots {
|
||||
Lights
|
||||
}
|
||||
|
||||
/// Supplies some basic things other passes needs.
|
||||
///
|
||||
/// screen size buffer, camera buffer,
|
||||
|
@ -41,11 +31,11 @@ impl RenderGraphPass for LightBasePass {
|
|||
|
||||
let mut desc = RenderGraphPassDesc::new(
|
||||
graph.next_id(),
|
||||
LightBasePassLabel,
|
||||
"light_base",
|
||||
RenderPassType::Node,
|
||||
None,
|
||||
vec![(
|
||||
&LightBasePassSlots::Lights,
|
||||
"light_buffers",
|
||||
light_buffers.bind_group.clone(),
|
||||
Some(light_buffers.bind_group_layout.clone()),
|
||||
)],
|
||||
|
@ -53,7 +43,7 @@ impl RenderGraphPass for LightBasePass {
|
|||
|
||||
desc.add_buffer_slot(
|
||||
graph.next_id(),
|
||||
LightBasePassSlots::Lights,
|
||||
"light_buffers",
|
||||
SlotAttribute::Output,
|
||||
Some(SlotValue::Buffer(light_buffers.buffer.clone())),
|
||||
);
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use std::{mem, rc::Rc};
|
||||
|
||||
use lyra_ecs::World;
|
||||
use lyra_game_derive::RenderGraphLabel;
|
||||
use wgpu::util::DeviceExt;
|
||||
|
||||
use crate::render::{
|
||||
|
@ -12,19 +11,6 @@ use crate::render::{
|
|||
resource::{ComputePipelineDescriptor, PipelineDescriptor, Shader},
|
||||
};
|
||||
|
||||
use super::{BasePassSlots, LightBasePassSlots};
|
||||
|
||||
#[derive(Debug, Hash, Clone, Default, PartialEq, RenderGraphLabel)]
|
||||
pub struct LightCullComputePassLabel;
|
||||
|
||||
#[derive(Debug, Hash, Clone, PartialEq, RenderGraphLabel)]
|
||||
pub enum LightCullComputePassSlots {
|
||||
LightGridTexture,
|
||||
LightGridTextureView,
|
||||
IndexCounterBuffer,
|
||||
LightIndicesGridGroup,
|
||||
}
|
||||
|
||||
pub struct LightCullComputePass {
|
||||
workgroup_size: glam::UVec2,
|
||||
}
|
||||
|
@ -49,7 +35,7 @@ impl RenderGraphPass for LightCullComputePass {
|
|||
|
||||
// get the size of the work group for the grid
|
||||
let main_rt = graph
|
||||
.slot_id(&BasePassSlots::MainRenderTarget)
|
||||
.slot_id("main_render_target")
|
||||
.and_then(|s| graph.slot_value(s))
|
||||
.and_then(|s| s.as_render_target())
|
||||
.expect("missing main render target");
|
||||
|
@ -171,14 +157,14 @@ impl RenderGraphPass for LightCullComputePass {
|
|||
drop(main_rt);
|
||||
let pass_id = graph.next_id();
|
||||
|
||||
let depth_tex_bgl = graph.bind_group_layout(graph.bind_group_id(&BasePassSlots::DepthTexture).unwrap());
|
||||
let camera_bgl = graph.bind_group_layout(graph.bind_group_id(&BasePassSlots::Camera).unwrap());
|
||||
let lights_bgl = graph.bind_group_layout(graph.bind_group_id(&LightBasePassSlots::Lights).unwrap());
|
||||
let screen_size_bgl = graph.bind_group_layout(graph.bind_group_id(&BasePassSlots::ScreenSize).unwrap());
|
||||
let depth_tex_bgl = graph.bind_group_layout(graph.bind_group_id("depth_texture").unwrap());
|
||||
let camera_bgl = graph.bind_group_layout(graph.bind_group_id("camera").unwrap());
|
||||
let lights_bgl = graph.bind_group_layout(graph.bind_group_id("light_buffers").unwrap());
|
||||
let screen_size_bgl = graph.bind_group_layout(graph.bind_group_id("screen_size").unwrap());
|
||||
|
||||
let mut desc = RenderGraphPassDesc::new(
|
||||
pass_id,
|
||||
LightCullComputePassLabel,
|
||||
"light_cull_compute",
|
||||
RenderPassType::Compute,
|
||||
Some(PipelineDescriptor::Compute(ComputePipelineDescriptor {
|
||||
label: Some("light_cull_pipeline".into()),
|
||||
|
@ -194,7 +180,7 @@ impl RenderGraphPass for LightCullComputePass {
|
|||
shader_entry_point: "cs_main".into(),
|
||||
})),
|
||||
vec![(
|
||||
&LightCullComputePassSlots::LightIndicesGridGroup,
|
||||
"light_indices_grid",
|
||||
light_indices_bg,
|
||||
Some(light_indices_bg_layout),
|
||||
)],
|
||||
|
@ -202,20 +188,20 @@ impl RenderGraphPass for LightCullComputePass {
|
|||
|
||||
desc.add_texture_view_slot(
|
||||
graph.next_id(),
|
||||
BasePassSlots::WindowTextureView,
|
||||
"window_texture_view",
|
||||
SlotAttribute::Input,
|
||||
None,
|
||||
);
|
||||
desc.add_buffer_slot(
|
||||
graph.next_id(),
|
||||
BasePassSlots::ScreenSize,
|
||||
"screen_size_buffer",
|
||||
SlotAttribute::Input,
|
||||
None,
|
||||
);
|
||||
desc.add_buffer_slot(graph.next_id(), BasePassSlots::Camera, SlotAttribute::Input, None);
|
||||
desc.add_buffer_slot(graph.next_id(), "camera_buffer", SlotAttribute::Input, None);
|
||||
desc.add_buffer_slot(
|
||||
graph.next_id(),
|
||||
LightCullComputePassSlots::IndexCounterBuffer,
|
||||
"index_counter_buffer",
|
||||
SlotAttribute::Output,
|
||||
Some(SlotValue::Buffer(Rc::new(light_index_counter_buffer))),
|
||||
);
|
||||
|
@ -253,11 +239,11 @@ impl RenderGraphPass for LightCullComputePass {
|
|||
graph.set_bind_groups(
|
||||
&mut pass,
|
||||
&[
|
||||
(&BasePassSlots::DepthTexture, 0),
|
||||
(&BasePassSlots::Camera, 1),
|
||||
(&LightBasePassSlots::Lights, 2),
|
||||
(&LightCullComputePassSlots::LightIndicesGridGroup, 3),
|
||||
(&BasePassSlots::ScreenSize, 4),
|
||||
("depth_texture", 0),
|
||||
("camera", 1),
|
||||
("light_buffers", 2),
|
||||
("light_indices_grid", 3),
|
||||
("screen_size", 4),
|
||||
],
|
||||
);
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ use std::{collections::{HashSet, VecDeque}, rc::Rc};
|
|||
use glam::Vec3;
|
||||
use itertools::izip;
|
||||
use lyra_ecs::{query::{filter::{Has, Not, Or}, Entities, Res, TickOf}, relation::{ChildOf, RelationOriginComponent}, Component, Entity};
|
||||
use lyra_game_derive::RenderGraphLabel;
|
||||
use lyra_math::Transform;
|
||||
use lyra_resource::{gltf::Mesh, ResHandle};
|
||||
use lyra_scene::{SceneGraph, WorldTransform};
|
||||
|
@ -22,26 +21,20 @@ use crate::{
|
|||
DeltaTime,
|
||||
};
|
||||
|
||||
use super::{BasePassSlots, LightBasePassSlots, LightCullComputePassSlots};
|
||||
|
||||
type MeshHandle = ResHandle<Mesh>;
|
||||
type SceneHandle = ResHandle<SceneGraph>;
|
||||
|
||||
#[derive(Debug, Hash, Clone, Default, PartialEq, RenderGraphLabel)]
|
||||
pub struct MeshesPassLabel;
|
||||
|
||||
#[derive(Debug, Hash, Clone, PartialEq, RenderGraphLabel)]
|
||||
pub enum MeshesPassSlots {
|
||||
Material
|
||||
}
|
||||
|
||||
struct MeshBufferStorage {
|
||||
buffer_vertex: BufferStorage,
|
||||
buffer_indices: Option<(wgpu::IndexFormat, BufferStorage)>,
|
||||
|
||||
// maybe this should just be a Uuid and the material can be retrieved though
|
||||
// MeshPass's `material_buffers` field?
|
||||
//#[allow(dead_code)]
|
||||
//render_texture: Option<RenderTexture>,
|
||||
material: Option<Rc<Material>>,
|
||||
|
||||
// The index of the transform for this entity.
|
||||
// The tuple is structured like this: (transform index, index of transform inside the buffer)
|
||||
//transform_index: TransformBufferIndices,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Component)]
|
||||
|
@ -187,8 +180,16 @@ impl MeshPass {
|
|||
}
|
||||
|
||||
/// Processes the mesh for the renderer, storing and creating buffers as needed. Returns true if a new mesh was processed.
|
||||
#[instrument(skip(self, device, queue, mesh, entity))]
|
||||
fn process_mesh(&mut self, device: &wgpu::Device, queue: &wgpu::Queue, entity: Entity, mesh: &Mesh, mesh_uuid: Uuid) -> bool {
|
||||
#[instrument(skip(self, device, queue, transform, mesh, entity))]
|
||||
fn process_mesh(&mut self, device: &wgpu::Device, queue: &wgpu::Queue, entity: Entity, transform: Transform, mesh: &Mesh, mesh_uuid: Uuid) -> bool {
|
||||
let _ = transform;
|
||||
/* if self.transform_buffers.should_expand() {
|
||||
self.transform_buffers.expand_buffers(&self.device);
|
||||
}
|
||||
|
||||
self.transform_buffers.update_or_insert(&self.queue, &self.render_limits,
|
||||
entity, || ( transform.calculate_mat4(), glam::Mat3::from_quat(transform.rotation) )); */
|
||||
|
||||
#[allow(clippy::map_entry)]
|
||||
if !self.mesh_buffers.contains_key(&mesh_uuid) {
|
||||
// create the mesh's buffers
|
||||
|
@ -232,7 +233,7 @@ impl RenderGraphPass for MeshPass {
|
|||
self.default_texture = Some(RenderTexture::from_bytes(&device, &graph.queue, texture_bind_group_layout.clone(), bytes, "default_texture").unwrap());
|
||||
|
||||
// get surface config format
|
||||
let main_rt = graph.slot_id(&BasePassSlots::MainRenderTarget)
|
||||
let main_rt = graph.slot_id("main_render_target")
|
||||
.and_then(|s| graph.slot_value(s))
|
||||
.and_then(|s| s.as_render_target())
|
||||
.expect("missing main render target");
|
||||
|
@ -242,10 +243,10 @@ impl RenderGraphPass for MeshPass {
|
|||
// get the id here to make borrow checker happy
|
||||
let pass_id = graph.next_id();
|
||||
|
||||
let camera_bgl = graph.bind_group_layout(graph.bind_group_id(&BasePassSlots::Camera).unwrap());
|
||||
let lights_bgl = graph.bind_group_layout(graph.bind_group_id(&LightBasePassSlots::Lights).unwrap());
|
||||
let camera_bgl = graph.bind_group_layout(graph.bind_group_id("camera").unwrap());
|
||||
let lights_bgl = graph.bind_group_layout(graph.bind_group_id("light_buffers").unwrap());
|
||||
let light_grid_bgl = graph
|
||||
.bind_group_layout(graph.bind_group_id(&LightCullComputePassSlots::LightIndicesGridGroup)
|
||||
.bind_group_layout(graph.bind_group_id("light_indices_grid")
|
||||
.expect("Missing light grid bind group"));
|
||||
|
||||
let shader = Rc::new(Shader {
|
||||
|
@ -255,7 +256,7 @@ impl RenderGraphPass for MeshPass {
|
|||
|
||||
let desc = RenderGraphPassDesc::new(
|
||||
pass_id,
|
||||
MeshesPassLabel,
|
||||
"meshes",
|
||||
RenderPassType::Render,
|
||||
Some(PipelineDescriptor::Render(RenderPipelineDescriptor {
|
||||
label: Some("meshes".into()),
|
||||
|
@ -297,7 +298,7 @@ impl RenderGraphPass for MeshPass {
|
|||
multiview: None,
|
||||
})),
|
||||
vec![
|
||||
(&MeshesPassSlots::Material, material_bg, Some(material_bgl)),
|
||||
("material", material_bg, Some(material_bgl)),
|
||||
],
|
||||
);
|
||||
|
||||
|
@ -342,9 +343,6 @@ impl RenderGraphPass for MeshPass {
|
|||
{
|
||||
alive_entities.insert(entity);
|
||||
|
||||
// Interpolate the transform for this entity using a component.
|
||||
// If the entity does not have the component then it will be queued to be added
|
||||
// to it after all the entities are prepared for rendering.
|
||||
let interp_transform = match interp_tran {
|
||||
Some(mut interp_transform) => {
|
||||
// found in https://youtu.be/YJB1QnEmlTs?t=472
|
||||
|
@ -364,28 +362,22 @@ impl RenderGraphPass for MeshPass {
|
|||
}
|
||||
};
|
||||
|
||||
{
|
||||
// expand the transform buffers if they need to be.
|
||||
// this is done in its own scope to avoid multiple mutable references to self at
|
||||
// once; aka, make the borrow checker happy
|
||||
let transforms = self.transforms.as_mut().unwrap();
|
||||
if transforms.needs_expand() {
|
||||
debug!("Expanding transform buffers");
|
||||
transforms.expand_buffers(device);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some((mesh_han, mesh_epoch)) = mesh_pair {
|
||||
if let Some(mesh) = mesh_han.data_ref() {
|
||||
// if process mesh did not just create a new mesh, and the epoch
|
||||
// shows that the scene has changed, verify that the mesh buffers
|
||||
// dont need to be resent to the gpu.
|
||||
if !self.process_mesh(device, queue, entity, &*mesh, mesh_han.uuid())
|
||||
if !self.process_mesh(device, queue, entity, interp_transform, &*mesh, mesh_han.uuid())
|
||||
&& mesh_epoch == last_epoch {
|
||||
self.check_mesh_buffers(device, queue, &mesh_han);
|
||||
}
|
||||
|
||||
|
||||
let transforms = self.transforms.as_mut().unwrap();
|
||||
if transforms.needs_expand() {
|
||||
debug!("Expanding transform buffers");
|
||||
transforms.expand_buffers(device);
|
||||
}
|
||||
|
||||
let group = TransformGroup::EntityRes(entity, mesh_han.uuid());
|
||||
let transform_id = transforms.update_or_push(device, queue, &render_limits,
|
||||
group, interp_transform.calculate_mat4(), glam::Mat3::from_quat(interp_transform.rotation));
|
||||
|
@ -412,12 +404,17 @@ impl RenderGraphPass for MeshPass {
|
|||
// if process mesh did not just create a new mesh, and the epoch
|
||||
// shows that the scene has changed, verify that the mesh buffers
|
||||
// dont need to be resent to the gpu.
|
||||
if !self.process_mesh(device, queue, entity, &*mesh, mesh_han.uuid())
|
||||
if !self.process_mesh(device, queue, entity, mesh_interpo, &*mesh, mesh_han.uuid())
|
||||
&& scene_epoch == last_epoch {
|
||||
self.check_mesh_buffers(device, queue, &mesh_han);
|
||||
}
|
||||
|
||||
let transforms = self.transforms.as_mut().unwrap();
|
||||
if transforms.needs_expand() {
|
||||
debug!("Expanding transform buffers");
|
||||
transforms.expand_buffers(device);
|
||||
}
|
||||
|
||||
let scene_mesh_group = TransformGroup::Res(scene_han.uuid(), mesh_han.uuid());
|
||||
let group = TransformGroup::OwnedGroup(entity, scene_mesh_group.into());
|
||||
let transform_id = transforms.update_or_push(device, queue, &render_limits,
|
||||
|
@ -451,29 +448,29 @@ impl RenderGraphPass for MeshPass {
|
|||
let encoder = context.encoder.as_mut().unwrap();
|
||||
|
||||
let view = graph
|
||||
.slot_value(graph.slot_id(&BasePassSlots::WindowTextureView).unwrap())
|
||||
.slot_value(graph.slot_id("window_texture_view").unwrap())
|
||||
.unwrap()
|
||||
.as_texture_view();
|
||||
|
||||
let depth_view = graph
|
||||
.slot_value(graph.slot_id(&BasePassSlots::DepthTextureView).unwrap())
|
||||
.slot_value(graph.slot_id("depth_texture_view").unwrap())
|
||||
.unwrap()
|
||||
.as_texture_view();
|
||||
|
||||
let camera_bg = graph
|
||||
.bind_group(graph.bind_group_id(&BasePassSlots::Camera)
|
||||
.bind_group(graph.bind_group_id("camera")
|
||||
.expect("Missing camera bind group"));
|
||||
|
||||
let lights_bg = graph
|
||||
.bind_group(graph.bind_group_id(&LightBasePassSlots::Lights)
|
||||
.bind_group(graph.bind_group_id("light_buffers")
|
||||
.expect("Missing lights bind group"));
|
||||
|
||||
let light_grid_bg = graph
|
||||
.bind_group(graph.bind_group_id(&LightCullComputePassSlots::LightIndicesGridGroup)
|
||||
.bind_group(graph.bind_group_id("light_indices_grid")
|
||||
.expect("Missing light grid bind group"));
|
||||
|
||||
let material_bg = graph
|
||||
.bind_group(graph.bind_group_id(&MeshesPassSlots::Material)
|
||||
.bind_group(graph.bind_group_id("material")
|
||||
.expect("Missing material bind group"));
|
||||
|
||||
let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
mod light_cull_compute;
|
||||
pub use light_cull_compute::*;
|
||||
|
||||
/*mod depth_prepass;
|
||||
pub use depth_prepass::*; */
|
||||
|
||||
/* mod simple_phong;
|
||||
pub use simple_phong::*; */
|
||||
|
||||
mod base;
|
||||
pub use base::*;
|
||||
|
||||
|
@ -11,4 +17,7 @@ mod light_base;
|
|||
pub use light_base::*;
|
||||
|
||||
mod present_pass;
|
||||
pub use present_pass::*;
|
||||
pub use present_pass::*;
|
||||
|
||||
mod triangle;
|
||||
pub use triangle::*;
|
|
@ -1,32 +1,16 @@
|
|||
use std::hash::Hash;
|
||||
|
||||
use lyra_game_derive::RenderGraphLabel;
|
||||
|
||||
use crate::render::graph::{RenderGraphContext, RenderGraphLabel, RenderGraphLabelValue, RenderGraphPass, RenderGraphPassDesc, RenderPassSlot, RenderPassType, SlotAttribute, SlotType};
|
||||
|
||||
#[derive(Debug, Clone, Hash, PartialEq, RenderGraphLabel)]
|
||||
pub struct PresentPassLabel(RenderGraphLabelValue);
|
||||
|
||||
impl PresentPassLabel {
|
||||
pub fn new(label: impl RenderGraphLabel) -> Self {
|
||||
Self(label.into())
|
||||
}
|
||||
}
|
||||
use crate::render::graph::{RenderGraphContext, RenderGraphPass, RenderGraphPassDesc, RenderPassSlot, RenderPassType, SlotAttribute, SlotType};
|
||||
|
||||
/// Supplies some basic things other passes needs.
|
||||
///
|
||||
/// screen size buffer, camera buffer,
|
||||
pub struct PresentPass {
|
||||
/// Label of this pass
|
||||
label: PresentPassLabel,
|
||||
//render_target_slot: Rc<dyn RenderGraphLabel>,
|
||||
render_target_slot: String,
|
||||
}
|
||||
|
||||
impl PresentPass {
|
||||
pub fn new(render_target_slot: impl RenderGraphLabel) -> Self {
|
||||
pub fn new(render_target_slot: &str) -> Self {
|
||||
Self {
|
||||
//render_target_slot: render_target_slot.rc_clone(),
|
||||
label: PresentPassLabel::new(render_target_slot),
|
||||
render_target_slot: render_target_slot.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +19,7 @@ impl RenderGraphPass for PresentPass {
|
|||
fn desc(&mut self, graph: &mut crate::render::graph::RenderGraph) -> crate::render::graph::RenderGraphPassDesc {
|
||||
let mut desc = RenderGraphPassDesc::new(
|
||||
graph.next_id(),
|
||||
self.label.clone(),
|
||||
&format!("present_{}", self.render_target_slot),
|
||||
RenderPassType::Presenter,
|
||||
None,
|
||||
vec![],
|
||||
|
@ -46,7 +30,7 @@ impl RenderGraphPass for PresentPass {
|
|||
ty: SlotType::RenderTarget,
|
||||
attribute: SlotAttribute::Input,
|
||||
id: graph.next_id(),
|
||||
label: self.label.0.clone(),
|
||||
name: self.render_target_slot.clone(),
|
||||
value: None,
|
||||
}
|
||||
);
|
||||
|
@ -59,8 +43,8 @@ impl RenderGraphPass for PresentPass {
|
|||
}
|
||||
|
||||
fn execute(&mut self, graph: &mut crate::render::graph::RenderGraph, _desc: &crate::render::graph::RenderGraphPassDesc, _context: &mut crate::render::graph::RenderGraphContext) {
|
||||
let id = graph.slot_id_rc(&self.label.0)
|
||||
.expect(&format!("render target slot '{:?}' for PresentPass is missing", self.label.0));
|
||||
let id = graph.slot_id(&self.render_target_slot)
|
||||
.expect(&format!("render target slot '{}' for PresentPass is missing", self.render_target_slot));
|
||||
let mut slot = graph.slot_value_mut(id).unwrap().as_render_target_mut().unwrap();
|
||||
let surf_tex = slot.current_texture.take().unwrap();
|
||||
surf_tex.present();
|
||||
|
|
|
@ -0,0 +1,153 @@
|
|||
use std::rc::Rc;
|
||||
|
||||
use crate::{
|
||||
render::{
|
||||
graph::{
|
||||
RenderGraphContext, RenderGraphPass, RenderGraphPassDesc, RenderPassType,
|
||||
SlotAttribute, SlotValue,
|
||||
},
|
||||
render_buffer::BufferWrapper,
|
||||
resource::{FragmentState, PipelineDescriptor, RenderPipelineDescriptor, Shader, VertexState},
|
||||
},
|
||||
DeltaTime,
|
||||
};
|
||||
|
||||
/// A demo pass that renders a triangle that changes colors every frame.
|
||||
#[derive(Default)]
|
||||
pub struct TrianglePass {
|
||||
acc: f32,
|
||||
}
|
||||
|
||||
impl TrianglePass {
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderGraphPass for TrianglePass {
|
||||
fn desc(
|
||||
&mut self,
|
||||
graph: &mut crate::render::graph::RenderGraph,
|
||||
) -> crate::render::graph::RenderGraphPassDesc {
|
||||
let shader = Rc::new(Shader {
|
||||
label: Some("triangle_shader".into()),
|
||||
source: include_str!("../../shaders/triangle.wgsl").to_string(),
|
||||
});
|
||||
|
||||
let device = graph.device();
|
||||
let (color_bgl, color_bg, color_buf, _) = BufferWrapper::builder()
|
||||
.label_prefix("color")
|
||||
.visibility(wgpu::ShaderStages::FRAGMENT)
|
||||
.buffer_usage(wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST)
|
||||
.contents(&[glam::Vec4::new(0.902, 0.639, 0.451, 1.0)])
|
||||
.finish_parts(device);
|
||||
let color_bgl = Rc::new(color_bgl);
|
||||
let color_bg = Rc::new(color_bg);
|
||||
|
||||
let main_rt = graph.slot_id("main_render_target")
|
||||
.and_then(|s| graph.slot_value(s))
|
||||
.and_then(|s| s.as_render_target())
|
||||
.expect("missing main render target");
|
||||
let surface_config_format = main_rt.surface_config.format;
|
||||
drop(main_rt);
|
||||
|
||||
let mut desc = RenderGraphPassDesc::new(
|
||||
graph.next_id(),
|
||||
"triangle",
|
||||
RenderPassType::Render,
|
||||
Some(PipelineDescriptor::Render(RenderPipelineDescriptor {
|
||||
label: Some("triangle_pipeline".into()),
|
||||
layouts: vec![color_bgl.clone()],
|
||||
push_constant_ranges: vec![],
|
||||
vertex: VertexState {
|
||||
module: shader.clone(),
|
||||
entry_point: "vs_main".into(),
|
||||
buffers: vec![],
|
||||
},
|
||||
fragment: Some(FragmentState {
|
||||
module: shader,
|
||||
entry_point: "fs_main".into(),
|
||||
targets: vec![Some(wgpu::ColorTargetState {
|
||||
format: surface_config_format,
|
||||
blend: Some(wgpu::BlendState::REPLACE),
|
||||
write_mask: wgpu::ColorWrites::ALL,
|
||||
})],
|
||||
}),
|
||||
depth_stencil: None,
|
||||
primitive: wgpu::PrimitiveState::default(),
|
||||
multisample: wgpu::MultisampleState::default(),
|
||||
multiview: None,
|
||||
})),
|
||||
vec![("color_bg", color_bg, Some(color_bgl))],
|
||||
);
|
||||
|
||||
desc.add_texture_view_slot(
|
||||
graph.next_id(),
|
||||
"window_texture_view",
|
||||
SlotAttribute::Input,
|
||||
None,
|
||||
);
|
||||
|
||||
desc.add_buffer_slot(
|
||||
graph.next_id(),
|
||||
"color_buffer",
|
||||
SlotAttribute::Output,
|
||||
Some(SlotValue::Buffer(Rc::new(color_buf))),
|
||||
);
|
||||
|
||||
desc
|
||||
}
|
||||
|
||||
fn prepare(&mut self, world: &mut lyra_ecs::World, context: &mut RenderGraphContext) {
|
||||
const SPEED: f32 = 1.5;
|
||||
|
||||
let dt = **world.get_resource::<DeltaTime>();
|
||||
self.acc += dt;
|
||||
let x = (self.acc * SPEED).sin();
|
||||
let y = ((self.acc + 2.15) * SPEED).sin();
|
||||
let z = ((self.acc + 5.35) * SPEED).sin();
|
||||
|
||||
let color = glam::Vec4::new(x, y, z, 1.0);
|
||||
context.queue_buffer_write_with("color_buffer", 0, color);
|
||||
}
|
||||
|
||||
fn execute(
|
||||
&mut self,
|
||||
graph: &mut crate::render::graph::RenderGraph,
|
||||
desc: &crate::render::graph::RenderGraphPassDesc,
|
||||
context: &mut crate::render::graph::RenderGraphContext,
|
||||
) {
|
||||
let view = graph
|
||||
.slot_value(graph.slot_id("window_texture_view").unwrap())
|
||||
.unwrap()
|
||||
.as_texture_view();
|
||||
let color_bg = graph.bind_group(graph.bind_group_id("color_bg").unwrap());
|
||||
|
||||
let encoder = context.encoder.as_mut().unwrap();
|
||||
let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
label: Some("triangle_pass"),
|
||||
color_attachments: &[
|
||||
// This is what @location(0) in the fragment shader targets
|
||||
Some(wgpu::RenderPassColorAttachment {
|
||||
view: &view,
|
||||
resolve_target: None,
|
||||
ops: wgpu::Operations {
|
||||
load: wgpu::LoadOp::Clear(wgpu::Color {
|
||||
r: 0.1,
|
||||
g: 0.2,
|
||||
b: 0.3,
|
||||
a: 1.0,
|
||||
}),
|
||||
store: true,
|
||||
},
|
||||
}),
|
||||
],
|
||||
depth_stencil_attachment: None,
|
||||
});
|
||||
|
||||
let pipeline = graph.pipeline(desc.id);
|
||||
pass.set_pipeline(&pipeline.as_render());
|
||||
pass.set_bind_group(0, color_bg, &[]);
|
||||
pass.draw(0..3, 0..1);
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@ use lyra_ecs::World;
|
|||
use tracing::{debug, instrument, warn};
|
||||
use winit::window::Window;
|
||||
|
||||
use crate::render::graph::{BasePass, BasePassLabel, BasePassSlots, LightBasePass, LightBasePassLabel, LightCullComputePass, LightCullComputePassLabel, MeshPass, MeshesPassLabel, PresentPass, PresentPassLabel};
|
||||
use crate::render::graph::{BasePass, LightBasePass, LightCullComputePass, MeshPass, PresentPass};
|
||||
|
||||
use super::graph::RenderGraph;
|
||||
use super::{resource::RenderPipeline, render_job::RenderJob};
|
||||
|
@ -137,16 +137,16 @@ impl BasicRenderer {
|
|||
g.add_pass(MeshPass::new());
|
||||
|
||||
debug!("Adding present pass");
|
||||
g.add_pass(PresentPass::new(BasePassSlots::MainRenderTarget));
|
||||
g.add_pass(PresentPass::new("main_render_target"));
|
||||
|
||||
g.add_edge(BasePassLabel, LightBasePassLabel);
|
||||
g.add_edge(LightBasePassLabel, LightCullComputePassLabel);
|
||||
g.add_edge(BasePassLabel, MeshesPassLabel);
|
||||
g.add_edge("base", "light_base");
|
||||
g.add_edge("light_base", "light_cull_compute");
|
||||
g.add_edge("base", "meshes");
|
||||
|
||||
// make sure that present runs last
|
||||
g.add_edge(BasePassLabel, PresentPassLabel::new(BasePassSlots::MainRenderTarget));
|
||||
g.add_edge(LightCullComputePassLabel, PresentPassLabel::new(BasePassSlots::MainRenderTarget));
|
||||
g.add_edge(MeshesPassLabel, PresentPassLabel::new(BasePassSlots::MainRenderTarget));
|
||||
g.add_edge("base", "present_main_render_target");
|
||||
g.add_edge("light_cull_compute", "present_main_render_target");
|
||||
g.add_edge("meshes", "present_main_render_target");
|
||||
|
||||
g.setup(&device);
|
||||
|
||||
|
@ -188,7 +188,7 @@ impl Renderer for BasicRenderer {
|
|||
self.size = new_size;
|
||||
|
||||
// update surface config and the surface
|
||||
let mut rt = self.graph.slot_value_mut(self.graph.slot_id(&BasePassSlots::MainRenderTarget).unwrap())
|
||||
let mut rt = self.graph.slot_value_mut(self.graph.slot_id("main_render_target").unwrap())
|
||||
.unwrap().as_render_target_mut().unwrap();
|
||||
rt.surface_config.width = new_size.width;
|
||||
rt.surface_config.height = new_size.height;
|
||||
|
|
Loading…
Reference in New Issue