quick save #2
This commit is contained in:
parent
146ffa654f
commit
131887b633
|
@ -86,11 +86,11 @@ impl core::ops::BitOr for Access {
|
|||
type Output = Self;
|
||||
|
||||
fn bitor(self, rhs: Self) -> Self::Output {
|
||||
assert_eq!(self.layout, rhs.layout);
|
||||
//assert_eq!(self.layout, rhs.layout);
|
||||
Self {
|
||||
stage: self.stage | rhs.stage,
|
||||
mask: self.mask | rhs.mask,
|
||||
layout: self.layout,
|
||||
layout: self.layout.max(rhs.layout),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -161,6 +161,13 @@ impl Access {
|
|||
mask: self.mask,
|
||||
}
|
||||
}
|
||||
pub fn empty() -> Self {
|
||||
Self {
|
||||
stage: vk::PipelineStageFlags2::NONE,
|
||||
mask: vk::AccessFlags2::empty(),
|
||||
layout: None,
|
||||
}
|
||||
}
|
||||
pub fn undefined() -> Self {
|
||||
Self {
|
||||
stage: vk::PipelineStageFlags2::NONE,
|
||||
|
@ -393,13 +400,30 @@ impl RenderGraph {
|
|||
}
|
||||
|
||||
impl PassNode {
|
||||
fn into_u32(&self) -> u32 {
|
||||
fn into_node_idx(&self) -> u32 {
|
||||
match self {
|
||||
PassNode::First => 0,
|
||||
PassNode::Last => 1,
|
||||
PassNode::Pass(i) => 2 + *i as u32,
|
||||
}
|
||||
}
|
||||
fn into_u32(&self, max_i: u32) -> u32 {
|
||||
match self {
|
||||
PassNode::First => 0,
|
||||
PassNode::Last => max_i + 1,
|
||||
PassNode::Pass(i) => 1 + *i as u32,
|
||||
}
|
||||
}
|
||||
fn range_full(from: Self, to: Self, max_i: u32) -> std::ops::RangeInclusive<u32> {
|
||||
from.into_u32(max_i)..=to.into_u32(max_i)
|
||||
}
|
||||
fn from_u32(v: u32, max_i: u32) -> Self {
|
||||
match v {
|
||||
0 => Self::First,
|
||||
n if n == 1 + max_i => Self::Last,
|
||||
n => Self::Pass(n as usize - 1),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
|
@ -436,6 +460,20 @@ impl RenderGraph {
|
|||
access: RefAccess::Write(Access::undefined()),
|
||||
});
|
||||
}
|
||||
for rid in self.resources.keys() {
|
||||
references.insert(GraphRef {
|
||||
pass: PassNode::First,
|
||||
resource: *rid,
|
||||
access: RefAccess::Write(
|
||||
self.accesses
|
||||
.get(rid)
|
||||
.cloned()
|
||||
.unwrap_or(Access::undefined()),
|
||||
),
|
||||
});
|
||||
|
||||
intervals.insert(*rid, (PassNode::First, PassNode::First));
|
||||
}
|
||||
|
||||
for (i, pass) in self.pass_descs.iter().enumerate() {
|
||||
let mut reads = BTreeMap::new();
|
||||
|
@ -476,6 +514,7 @@ impl RenderGraph {
|
|||
})
|
||||
.or_insert((PassNode::Pass(i), PassNode::Pass(i)));
|
||||
}
|
||||
|
||||
references.extend(writes.into_iter().map(|(resource, access)| GraphRef {
|
||||
pass: PassNode::Pass(i),
|
||||
resource,
|
||||
|
@ -500,6 +539,9 @@ impl RenderGraph {
|
|||
.or_insert((PassNode::Last, PassNode::Last));
|
||||
}
|
||||
|
||||
eprintln!("references: {references:#?}");
|
||||
eprintln!("intervals: {intervals:#?}");
|
||||
|
||||
(references, intervals)
|
||||
};
|
||||
|
||||
|
@ -570,35 +612,62 @@ impl RenderGraph {
|
|||
let mut to_make_available = AccessMask::undefined();
|
||||
// writes already made-visible
|
||||
let mut made_visible = AccessMask::undefined();
|
||||
let mut last_read = PreviousRef::Write(PassNode::First, Access::undefined());
|
||||
let mut last_write = PreviousRef::Write(PassNode::First, Access::undefined());
|
||||
let mut last_ref = PreviousRef::Write(PassNode::First, Access::undefined());
|
||||
let mut last_read = Option::<PreviousRef>::None;
|
||||
let mut last_write = Option::<PreviousRef>::None;
|
||||
let mut last_ref = Option::<PreviousRef>::None;
|
||||
|
||||
references
|
||||
.range(
|
||||
// pass, read, write
|
||||
let mut current_pass = (from, Access::empty(), Access::empty());
|
||||
let max_i = self.pass_descs.len() as u32;
|
||||
eprintln!("{rid:?}:");
|
||||
for pass in
|
||||
PassNode::range_full(from, to, max_i).map(|i| PassNode::from_u32(i, max_i))
|
||||
{
|
||||
eprintln!("{pass:?}:");
|
||||
let mut range = references.range(
|
||||
GraphRef {
|
||||
pass: from,
|
||||
pass,
|
||||
resource: rid,
|
||||
access: RefAccess::__Min,
|
||||
}..GraphRef {
|
||||
pass: to,
|
||||
pass,
|
||||
resource: rid,
|
||||
access: RefAccess::__Max,
|
||||
},
|
||||
)
|
||||
.for_each(|a| {
|
||||
);
|
||||
|
||||
while let Some(a) = range.next() {
|
||||
eprintln!("{a:?}");
|
||||
eprintln!("made_visible: {made_visible:?}");
|
||||
eprintln!("to_make_available: {to_make_available:?}");
|
||||
if a.pass != current_pass.0 {
|
||||
if current_pass.1 != Access::empty() {
|
||||
last_read = Some(PreviousRef::Read(current_pass.0, current_pass.1));
|
||||
last_ref = Some(PreviousRef::Read(current_pass.0, current_pass.1));
|
||||
}
|
||||
if current_pass.2 != Access::empty() {
|
||||
last_write =
|
||||
Some(PreviousRef::Write(current_pass.0, current_pass.2));
|
||||
last_ref = Some(PreviousRef::Write(current_pass.0, current_pass.2));
|
||||
}
|
||||
|
||||
current_pass = (a.pass, Access::empty(), Access::empty());
|
||||
}
|
||||
|
||||
// TODO: VkEvents can make this more
|
||||
// fine-grained but also probably have zero
|
||||
// real-world benefit :<
|
||||
|
||||
last_ref = match a.access {
|
||||
match a.access {
|
||||
RefAccess::None => {
|
||||
// make-available previous writes
|
||||
// no-op edge between previous reference and a.pass
|
||||
|
||||
edges.push(((last_ref.node(), a.pass), (rid, Barrier::Logical)));
|
||||
if let Some(last_ref) = last_ref.as_ref() {
|
||||
edges
|
||||
.push(((last_ref.node(), a.pass), (rid, Barrier::Logical)));
|
||||
}
|
||||
// because this is the last node, setting last_ref isn't required.
|
||||
PreviousRef::Read(a.pass, Access::undefined())
|
||||
}
|
||||
RefAccess::Read(access) => {
|
||||
// - if read: no writes pending, check for
|
||||
|
@ -610,34 +679,37 @@ impl RenderGraph {
|
|||
made_visible = made_visible | make_visible_mask;
|
||||
|
||||
match last_ref {
|
||||
PreviousRef::Read(pass_node, before) => {
|
||||
if !make_visible_mask.is_empty() {
|
||||
// make-visible reads.
|
||||
edges.push((
|
||||
(last_write.node(), a.pass),
|
||||
(
|
||||
rid,
|
||||
Barrier::MakeVisible {
|
||||
src: last_write.access().stage,
|
||||
dst: (
|
||||
make_visible_mask.stage,
|
||||
make_visible_mask.mask,
|
||||
),
|
||||
},
|
||||
),
|
||||
));
|
||||
} else {
|
||||
// still require a after b
|
||||
edges.push((
|
||||
(last_write.node(), a.pass),
|
||||
(
|
||||
rid,
|
||||
Barrier::Execution {
|
||||
src: last_write.access().stage,
|
||||
dst: access.stage,
|
||||
},
|
||||
),
|
||||
));
|
||||
None => {}
|
||||
Some(PreviousRef::Read(pass_node, before)) => {
|
||||
if let Some(last_write) = last_write.as_ref() {
|
||||
if !make_visible_mask.is_empty() {
|
||||
// make-visible reads.
|
||||
edges.push((
|
||||
(last_write.node(), a.pass),
|
||||
(
|
||||
rid,
|
||||
Barrier::MakeVisible {
|
||||
src: last_write.access().stage,
|
||||
dst: (
|
||||
make_visible_mask.stage,
|
||||
make_visible_mask.mask,
|
||||
),
|
||||
},
|
||||
),
|
||||
));
|
||||
} else {
|
||||
// still require a after b
|
||||
edges.push((
|
||||
(last_write.node(), a.pass),
|
||||
(
|
||||
rid,
|
||||
Barrier::Execution {
|
||||
src: last_write.access().stage,
|
||||
dst: access.stage,
|
||||
},
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
if before.layout != access.layout {
|
||||
|
@ -653,15 +725,15 @@ impl RenderGraph {
|
|||
));
|
||||
}
|
||||
}
|
||||
PreviousRef::Write(..) => {
|
||||
Some(PreviousRef::Write(write, before)) => {
|
||||
// make writes visible
|
||||
if make_visible_mask.is_empty() {
|
||||
if !make_visible_mask.is_empty() {
|
||||
edges.push((
|
||||
(last_write.node(), a.pass),
|
||||
(write, a.pass),
|
||||
(
|
||||
rid,
|
||||
Barrier::MakeVisible {
|
||||
src: last_write.access().stage,
|
||||
src: before.stage,
|
||||
dst: (
|
||||
make_visible_mask.stage,
|
||||
make_visible_mask.mask,
|
||||
|
@ -672,8 +744,14 @@ impl RenderGraph {
|
|||
}
|
||||
// make all writes available
|
||||
if !to_make_available.is_empty() {
|
||||
tracing::debug!(
|
||||
"making available {:?} for {:?} on {:?}",
|
||||
to_make_available,
|
||||
rid,
|
||||
a.pass
|
||||
);
|
||||
edges.push((
|
||||
(last_write.node(), a.pass),
|
||||
(write, a.pass),
|
||||
(
|
||||
rid,
|
||||
Barrier::MakeAvailable {
|
||||
|
@ -694,11 +772,11 @@ impl RenderGraph {
|
|||
{
|
||||
// still require a after b
|
||||
edges.push((
|
||||
(last_write.node(), a.pass),
|
||||
(write, a.pass),
|
||||
(
|
||||
rid,
|
||||
Barrier::Execution {
|
||||
src: last_write.access().stage,
|
||||
src: before.stage,
|
||||
dst: access.stage,
|
||||
},
|
||||
),
|
||||
|
@ -706,8 +784,7 @@ impl RenderGraph {
|
|||
}
|
||||
}
|
||||
}
|
||||
last_read = PreviousRef::Read(a.pass, access);
|
||||
last_write
|
||||
current_pass.1 = current_pass.1 | access;
|
||||
}
|
||||
RefAccess::Write(access) => {
|
||||
// - if read: execution barrier against write-after-read
|
||||
|
@ -715,7 +792,8 @@ impl RenderGraph {
|
|||
to_make_available = to_make_available | access.into_access_mask();
|
||||
|
||||
match last_ref {
|
||||
PreviousRef::Read(pass_node, before) => {
|
||||
None => {}
|
||||
Some(PreviousRef::Read(pass_node, before)) => {
|
||||
// execution barrier to ward against write-after-read
|
||||
edges.push((
|
||||
(pass_node, a.pass),
|
||||
|
@ -728,7 +806,7 @@ impl RenderGraph {
|
|||
),
|
||||
));
|
||||
}
|
||||
PreviousRef::Write(pass_node, before) => {
|
||||
Some(PreviousRef::Write(pass_node, before)) => {
|
||||
if before.layout != access.layout {
|
||||
// as far as I understand the spec,
|
||||
// this already makes-available
|
||||
|
@ -742,9 +820,10 @@ impl RenderGraph {
|
|||
},
|
||||
),
|
||||
));
|
||||
} else {
|
||||
// write_no_sync: pass tells us that
|
||||
// writes do not interleave.
|
||||
}
|
||||
// write_no_sync: pass tells us that
|
||||
// writes do not interleave.
|
||||
if let Some(last_read) = last_read.as_ref() {
|
||||
edges.push((
|
||||
(last_read.node(), a.pass),
|
||||
(rid, Barrier::Logical),
|
||||
|
@ -752,12 +831,13 @@ impl RenderGraph {
|
|||
}
|
||||
}
|
||||
}
|
||||
last_write = PreviousRef::Write(a.pass, access);
|
||||
last_write
|
||||
|
||||
current_pass.2 = current_pass.2 | access;
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let mut dag = petgraph::graph::DiGraph::new();
|
||||
|
@ -768,7 +848,11 @@ impl RenderGraph {
|
|||
dag.add_node(PassNode::Last);
|
||||
|
||||
for ((from, to), weight) in edges {
|
||||
dag.add_edge(from.into_u32().into(), to.into_u32().into(), weight);
|
||||
dag.add_edge(
|
||||
from.into_node_idx().into(),
|
||||
to.into_node_idx().into(),
|
||||
weight,
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(any(debug_assertions, test))]
|
||||
|
@ -781,7 +865,7 @@ impl RenderGraph {
|
|||
&[],
|
||||
&|_graph, edgeref| {
|
||||
format!(
|
||||
"label = \"{},{}\"",
|
||||
"label = \"{},{:#?}\"",
|
||||
edgeref.weight().0.as_u32(),
|
||||
edgeref.weight().1,
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue