use crate::{
Constants, Graph, GraphExec, Kernel, Node, Result, Stream, View,
dependency_frontier::{Frontier, Use},
execution::Access,
};
#[derive(Clone, Copy, Debug)]
pub struct AccessView<'a> {
pub view: View<'a>,
pub access: Access,
}
pub struct AccessGraph<'a> {
graph: Graph<'a>,
frontier: Frontier,
nodes: Vec<Node>,
}
impl Stream {
pub fn access_graph(&self) -> Result<AccessGraph<'_>> {
Ok(AccessGraph {
graph: self.graph()?,
frontier: Frontier::default(),
nodes: Vec::new(),
})
}
}
impl<'a> View<'a> {
#[must_use]
pub fn access(self, access: Access) -> AccessView<'a> {
AccessView { view: self, access }
}
#[must_use]
pub fn read(self) -> AccessView<'a> {
self.access(Access::Read)
}
#[must_use]
pub fn write(self) -> AccessView<'a> {
self.access(Access::Write)
}
#[must_use]
pub fn read_write(self) -> AccessView<'a> {
self.access(Access::ReadWrite)
}
}
impl<'a> AccessGraph<'a> {
fn dependencies(&mut self, uses: impl IntoIterator<Item = AccessView<'a>>) -> Vec<Node> {
let index = self.nodes.len();
self.frontier
.dependencies(
index,
uses.into_iter().map(|binding| Use {
allocation: binding.view.owner() as *const crate::Buffer as usize,
range: binding.view.offset()
..binding.view.offset().saturating_add(binding.view.len()),
access: binding.access,
}),
)
.into_iter()
.map(|dependency| self.nodes[dependency])
.collect()
}
fn record(&mut self, node: Node) -> Node {
self.nodes.push(node);
node
}
pub fn fill(&mut self, destination: View<'a>, pattern: u8) -> Result<Node> {
let after = self.dependencies([destination.write()]);
let node = self.graph.fill(&after, destination, pattern)?;
Ok(self.record(node))
}
pub fn copy(&mut self, destination: View<'a>, source: View<'a>) -> Result<Node> {
let after = self.dependencies([source.read(), destination.write()]);
let node = self.graph.copy(&after, destination, source)?;
Ok(self.record(node))
}
pub unsafe fn dispatch(
&mut self,
kernel: &'a Kernel,
grid: [u32; 3],
block: [u32; 3],
constants: &Constants,
bindings: &[AccessView<'a>],
) -> Result<Node> {
let after = self.dependencies(bindings.iter().copied());
let views = bindings
.iter()
.map(|binding| binding.view)
.collect::<Vec<_>>();
let node = unsafe {
self.graph
.dispatch(&after, kernel, grid, block, constants, &views)?
};
Ok(self.record(node))
}
pub fn finish(self) -> Result<GraphExec> {
self.graph.finish()
}
#[must_use]
pub fn len(&self) -> usize {
self.nodes.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.nodes.is_empty()
}
}