use crate::{
node::State,
resource::{AccessFlags, Resource},
schedule::{QueueId, SubmissionId},
};
#[derive(Clone, Copy, Debug)]
pub struct LinkQueueState<R: Resource> {
pub first: usize,
pub last: usize,
pub access: R::Access,
pub stages: rendy_core::hal::pso::PipelineStage,
}
impl<R> LinkQueueState<R>
where
R: Resource,
{
fn new(node: &LinkNode<R>) -> Self {
LinkQueueState {
first: node.sid.index(),
last: node.sid.index(),
access: node.state.access,
stages: node.state.stages,
}
}
fn push(&mut self, node: &LinkNode<R>) {
assert!(self.last < node.sid.index());
self.access |= node.state.access;
self.stages |= node.state.stages;
self.last = node.sid.index();
}
}
#[derive(Clone, Debug)]
pub struct Link<R: Resource> {
access: R::Access,
usage: R::Usage,
layout: R::Layout,
stages: rendy_core::hal::pso::PipelineStage,
queue_count: usize,
queues: Vec<Option<LinkQueueState<R>>>,
family: rendy_core::hal::queue::QueueFamilyId,
}
#[derive(Debug)]
pub struct LinkNode<R: Resource> {
pub sid: SubmissionId,
pub state: State<R>,
}
impl<R> Link<R>
where
R: Resource,
{
pub fn new(node: LinkNode<R>) -> Self {
let mut link = Link {
access: node.state.access,
usage: node.state.usage,
layout: node.state.layout,
stages: node.state.stages,
queue_count: 1,
queues: Vec::new(),
family: node.sid.family(),
};
link.ensure_queue(node.sid.queue().index());
link.queues[node.sid.queue().index()] = Some(LinkQueueState::new(&node));
link
}
fn ensure_queue(&mut self, index: usize) {
if index >= self.queues.len() {
let reserve = index - self.queues.len() + 1;
self.queues.reserve(reserve);
while index >= self.queues.len() {
self.queues.push(None);
}
}
}
pub fn family(&self) -> rendy_core::hal::queue::QueueFamilyId {
self.family
}
pub fn submission_state(&self, sid: SubmissionId) -> State<R> {
assert_eq!(sid.family(), self.family);
let lqs = self.queues[sid.queue().index()].as_ref().unwrap();
State {
access: lqs.access,
layout: self.layout,
stages: lqs.stages,
usage: self.usage,
}
}
pub fn state(&self) -> State<R> {
State {
access: self.access,
layout: self.layout,
stages: self.stages,
usage: self.usage,
}
}
pub fn access(&self) -> R::Access {
self.access
}
pub fn layout(&self) -> R::Layout {
self.layout
}
pub fn usage(&self) -> R::Usage {
self.usage
}
pub fn single_queue(&self) -> bool {
self.queue_count == 1
}
pub fn compatible(&self, node: &LinkNode<R>) -> bool {
self.family == node.sid.family() && !(self.access | node.state.access).exclusive()
}
pub fn add_node(&mut self, node: LinkNode<R>) {
assert_eq!(self.family, node.sid.family());
self.ensure_queue(node.sid.queue().index());
self.access |= node.state.access;
self.usage |= node.state.usage;
self.stages |= node.state.stages;
match &mut self.queues[node.sid.queue().index()] {
&mut Some(ref mut queue) => {
queue.push(&node);
}
slot @ &mut None => {
self.queue_count += 1;
*slot = Some(LinkQueueState::new(&node));
}
}
}
pub fn queues(&self) -> impl Iterator<Item = (QueueId, &LinkQueueState<R>)> {
let family = self.family;
self.queues
.iter()
.enumerate()
.filter_map(move |(index, queue)| {
queue
.as_ref()
.map(move |queue| (QueueId::new(family, index), queue))
})
}
pub fn queue(&self, qid: QueueId) -> &LinkQueueState<R> {
assert_eq!(qid.family(), self.family);
self.queues[qid.index()].as_ref().unwrap()
}
}