quick save #2

This commit is contained in:
Janis 2025-01-06 04:01:15 +01:00
parent 146ffa654f
commit 131887b633

View file

@ -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,
)