use std::collections::hash_map::Entry;
use std::hash::{Hash, Hasher};
use std::sync::Arc;
use fnv::FnvHashMap;
use buffer::BufferAccess;
use command_buffer::cb::AddCommand;
use command_buffer::cb::CommandBufferBuild;
use command_buffer::cb::UnsafeCommandBuffer;
use command_buffer::CommandAddError;
use command_buffer::CommandBuffer;
use command_buffer::CommandBufferBuilder;
use command_buffer::CommandBufferExecError;
use command_buffer::commands_raw;
use framebuffer::FramebufferAbstract;
use image::ImageLayout;
use image::ImageAccess;
use instance::QueueFamily;
use device::Device;
use device::DeviceOwned;
use device::Queue;
use sync::AccessCheckError;
use sync::AccessError;
use sync::AccessFlagBits;
use sync::PipelineStages;
use sync::GpuFuture;
pub struct SubmitSyncBuilderLayer<I> {
inner: I,
resources: FnvHashMap<Key, ResourceEntry>,
behavior: SubmitSyncBuilderLayerBehavior,
}
#[derive(Debug, Copy, Clone)]
pub enum SubmitSyncBuilderLayerBehavior {
Explicit,
UseLayoutHint,
}
enum Key {
Buffer(Box<BufferAccess + Send + Sync>),
Image(Box<ImageAccess + Send + Sync>),
FramebufferAttachment(Box<FramebufferAbstract + Send + Sync>, u32),
}
impl Key {
#[inline]
fn conflicts_buffer_all(&self, buf: &BufferAccess) -> bool {
match self {
&Key::Buffer(ref a) => a.conflicts_buffer_all(buf),
&Key::Image(ref a) => a.conflicts_buffer_all(buf),
&Key::FramebufferAttachment(ref b, idx) => {
let img = b.attachments()[idx as usize].parent();
img.conflicts_buffer_all(buf)
},
}
}
#[inline]
fn conflicts_image_all(&self, img: &ImageAccess) -> bool {
match self {
&Key::Buffer(ref a) => a.conflicts_image_all(img),
&Key::Image(ref a) => a.conflicts_image_all(img),
&Key::FramebufferAttachment(ref b, idx) => {
let b = b.attachments()[idx as usize].parent();
b.conflicts_image_all(img)
},
}
}
}
impl PartialEq for Key {
#[inline]
fn eq(&self, other: &Key) -> bool {
match other {
&Key::Buffer(ref b) => self.conflicts_buffer_all(b),
&Key::Image(ref b) => self.conflicts_image_all(b),
&Key::FramebufferAttachment(ref b, idx) => {
self.conflicts_image_all(b.attachments()[idx as usize].parent())
},
}
}
}
impl Eq for Key {
}
impl Hash for Key {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
match self {
&Key::Buffer(ref buf) => buf.conflict_key_all().hash(state),
&Key::Image(ref img) => img.conflict_key_all().hash(state),
&Key::FramebufferAttachment(ref fb, idx) => {
let img = fb.attachments()[idx as usize].parent();
img.conflict_key_all().hash(state)
},
}
}
}
struct ResourceEntry {
final_stages: PipelineStages,
final_access: AccessFlagBits,
exclusive: bool,
initial_layout: ImageLayout,
final_layout: ImageLayout,
}
impl<I> SubmitSyncBuilderLayer<I> {
#[inline]
pub fn new(inner: I, behavior: SubmitSyncBuilderLayerBehavior) -> SubmitSyncBuilderLayer<I> {
SubmitSyncBuilderLayer {
inner: inner,
resources: FnvHashMap::default(),
behavior: behavior,
}
}
fn add_buffer<B>(&mut self, buffer: &B, exclusive: bool, stages: PipelineStages,
access: AccessFlagBits)
where B: BufferAccess + Send + Sync + Clone + 'static
{
let key = Key::Buffer(Box::new(buffer.clone()));
match self.resources.entry(key) {
Entry::Vacant(entry) => {
entry.insert(ResourceEntry {
final_stages: stages,
final_access: access,
exclusive: exclusive,
initial_layout: ImageLayout::Undefined,
final_layout: ImageLayout::Undefined,
});
},
Entry::Occupied(mut entry) => {
let entry = entry.get_mut();
entry.final_stages = entry.final_stages | stages;
entry.final_access = entry.final_access | access;
entry.exclusive = entry.exclusive || exclusive;
entry.final_layout = ImageLayout::Undefined;
},
}
}
fn add_image<T>(&mut self, image: &T, exclusive: bool, stages: PipelineStages,
access: AccessFlagBits)
where T: ImageAccess + Send + Sync + Clone + 'static
{
let key = Key::Image(Box::new(image.clone()));
let initial_layout = match self.behavior {
SubmitSyncBuilderLayerBehavior::Explicit => unimplemented!(), SubmitSyncBuilderLayerBehavior::UseLayoutHint => image.initial_layout_requirement(),
};
let final_layout = match self.behavior {
SubmitSyncBuilderLayerBehavior::Explicit => unimplemented!(), SubmitSyncBuilderLayerBehavior::UseLayoutHint => image.final_layout_requirement(),
};
match self.resources.entry(key) {
Entry::Vacant(entry) => {
entry.insert(ResourceEntry {
final_stages: stages,
final_access: access,
exclusive: exclusive,
initial_layout: initial_layout,
final_layout: final_layout,
});
},
Entry::Occupied(mut entry) => {
let entry = entry.get_mut();
entry.exclusive = entry.exclusive || exclusive;
entry.final_stages = entry.final_stages | stages;
entry.final_access = entry.final_access | access;
entry.final_layout = final_layout;
},
}
}
fn add_framebuffer<F>(&mut self, framebuffer: &F)
where F: FramebufferAbstract + Send + Sync + Clone + 'static
{
for index in 0 .. FramebufferAbstract::attachments(framebuffer).len() {
let key = Key::FramebufferAttachment(Box::new(framebuffer.clone()), index as u32);
let desc = framebuffer.attachment_desc(index).expect("Wrong implementation of FramebufferAbstract trait");
let image = FramebufferAbstract::attachments(framebuffer)[index];
let initial_layout = match self.behavior {
SubmitSyncBuilderLayerBehavior::Explicit => desc.initial_layout,
SubmitSyncBuilderLayerBehavior::UseLayoutHint => {
match desc.initial_layout {
ImageLayout::Undefined | ImageLayout::Preinitialized => desc.initial_layout,
_ => image.parent().initial_layout_requirement(),
}
},
};
let final_layout = match self.behavior {
SubmitSyncBuilderLayerBehavior::Explicit => desc.final_layout,
SubmitSyncBuilderLayerBehavior::UseLayoutHint => {
match desc.final_layout {
ImageLayout::Undefined | ImageLayout::Preinitialized => desc.final_layout,
_ => image.parent().final_layout_requirement(),
}
},
};
match self.resources.entry(key) {
Entry::Vacant(entry) => {
entry.insert(ResourceEntry {
final_stages: PipelineStages { all_commands: true, ..PipelineStages::none() }, final_access: AccessFlagBits::all(), exclusive: true, initial_layout: initial_layout,
final_layout: final_layout,
});
},
Entry::Occupied(mut entry) => {
let entry = entry.get_mut();
entry.exclusive = true; entry.final_layout = final_layout;
},
}
}
}
}
unsafe impl<I, O, E> CommandBufferBuild for SubmitSyncBuilderLayer<I>
where I: CommandBufferBuild<Out = O, Err = E>
{
type Out = SubmitSyncLayer<O>;
type Err = E;
#[inline]
fn build(self) -> Result<Self::Out, E> {
Ok(SubmitSyncLayer {
inner: try!(self.inner.build()),
resources: self.resources,
})
}
}
unsafe impl<I> DeviceOwned for SubmitSyncBuilderLayer<I>
where I: DeviceOwned
{
#[inline]
fn device(&self) -> &Arc<Device> {
self.inner.device()
}
}
unsafe impl<I> CommandBufferBuilder for SubmitSyncBuilderLayer<I>
where I: CommandBufferBuilder
{
#[inline]
fn queue_family(&self) -> QueueFamily {
self.inner.queue_family()
}
}
macro_rules! pass_through {
(($($param:ident),*), $cmd:ty) => {
unsafe impl<'a, I, O $(, $param)*> AddCommand<$cmd> for SubmitSyncBuilderLayer<I>
where I: AddCommand<$cmd, Out = O>
{
type Out = SubmitSyncBuilderLayer<O>;
#[inline]
fn add(self, command: $cmd) -> Result<Self::Out, CommandAddError> {
Ok(SubmitSyncBuilderLayer {
inner: AddCommand::add(self.inner, command)?,
resources: self.resources,
behavior: self.behavior,
})
}
}
}
}
pass_through!((S, Pl), commands_raw::CmdBindDescriptorSets<S, Pl>);
pass_through!((V), commands_raw::CmdBindVertexBuffers<V>);
pass_through!((C), commands_raw::CmdExecuteCommands<C>);
unsafe impl<I, O, Rp, F> AddCommand<commands_raw::CmdBeginRenderPass<Rp, F>> for SubmitSyncBuilderLayer<I>
where I: AddCommand<commands_raw::CmdBeginRenderPass<Rp, F>, Out = O>,
F: FramebufferAbstract + Send + Sync + Clone + 'static
{
type Out = SubmitSyncBuilderLayer<O>;
#[inline]
fn add(mut self, command: commands_raw::CmdBeginRenderPass<Rp, F>) -> Result<Self::Out, CommandAddError> {
self.add_framebuffer(command.framebuffer());
Ok(SubmitSyncBuilderLayer {
inner: AddCommand::add(self.inner, command)?,
resources: self.resources,
behavior: self.behavior,
})
}
}
unsafe impl<I, O, B> AddCommand<commands_raw::CmdBindIndexBuffer<B>> for SubmitSyncBuilderLayer<I>
where I: AddCommand<commands_raw::CmdBindIndexBuffer<B>, Out = O>,
B: BufferAccess + Send + Sync + Clone + 'static
{
type Out = SubmitSyncBuilderLayer<O>;
#[inline]
fn add(mut self, command: commands_raw::CmdBindIndexBuffer<B>) -> Result<Self::Out, CommandAddError> {
self.add_buffer(command.buffer(), false,
PipelineStages { vertex_input: true, .. PipelineStages::none() },
AccessFlagBits { index_read: true, .. AccessFlagBits::none() });
Ok(SubmitSyncBuilderLayer {
inner: AddCommand::add(self.inner, command)?,
resources: self.resources,
behavior: self.behavior,
})
}
}
unsafe impl<I, O, P> AddCommand<commands_raw::CmdBindPipeline<P>> for SubmitSyncBuilderLayer<I>
where I: AddCommand<commands_raw::CmdBindPipeline<P>, Out = O>
{
type Out = SubmitSyncBuilderLayer<O>;
#[inline]
fn add(self, command: commands_raw::CmdBindPipeline<P>) -> Result<Self::Out, CommandAddError> {
Ok(SubmitSyncBuilderLayer {
inner: AddCommand::add(self.inner, command)?,
resources: self.resources,
behavior: self.behavior,
})
}
}
unsafe impl<I, O, S, D> AddCommand<commands_raw::CmdBlitImage<S, D>> for SubmitSyncBuilderLayer<I>
where I: AddCommand<commands_raw::CmdBlitImage<S, D>, Out = O>,
S: ImageAccess + Send + Sync + Clone + 'static,
D: ImageAccess + Send + Sync + Clone + 'static
{
type Out = SubmitSyncBuilderLayer<O>;
#[inline]
fn add(mut self, command: commands_raw::CmdBlitImage<S, D>) -> Result<Self::Out, CommandAddError> {
self.add_image(command.source(), false,
PipelineStages { transfer: true, .. PipelineStages::none() },
AccessFlagBits { transfer_read: true, .. AccessFlagBits::none() });
self.add_image(command.destination(), true,
PipelineStages { transfer: true, .. PipelineStages::none() },
AccessFlagBits { transfer_write: true, .. AccessFlagBits::none() });
Ok(SubmitSyncBuilderLayer {
inner: AddCommand::add(self.inner, command)?,
resources: self.resources,
behavior: self.behavior,
})
}
}
unsafe impl<I, O> AddCommand<commands_raw::CmdClearAttachments> for SubmitSyncBuilderLayer<I>
where I: AddCommand<commands_raw::CmdClearAttachments, Out = O>
{
type Out = SubmitSyncBuilderLayer<O>;
#[inline]
fn add(self, command: commands_raw::CmdClearAttachments) -> Result<Self::Out, CommandAddError> {
Ok(SubmitSyncBuilderLayer {
inner: AddCommand::add(self.inner, command)?,
resources: self.resources,
behavior: self.behavior,
})
}
}
unsafe impl<I, O, S, D> AddCommand<commands_raw::CmdCopyBuffer<S, D>> for SubmitSyncBuilderLayer<I>
where I: AddCommand<commands_raw::CmdCopyBuffer<S, D>, Out = O>,
S: BufferAccess + Send + Sync + Clone + 'static,
D: BufferAccess + Send + Sync + Clone + 'static
{
type Out = SubmitSyncBuilderLayer<O>;
#[inline]
fn add(mut self, command: commands_raw::CmdCopyBuffer<S, D>) -> Result<Self::Out, CommandAddError> {
self.add_buffer(command.source(), false,
PipelineStages { transfer: true, .. PipelineStages::none() },
AccessFlagBits { transfer_read: true, .. AccessFlagBits::none() });
self.add_buffer(command.destination(), true,
PipelineStages { transfer: true, .. PipelineStages::none() },
AccessFlagBits { transfer_write: true, .. AccessFlagBits::none() });
Ok(SubmitSyncBuilderLayer {
inner: AddCommand::add(self.inner, command)?,
resources: self.resources,
behavior: self.behavior,
})
}
}
unsafe impl<I, O, S, D> AddCommand<commands_raw::CmdCopyBufferToImage<S, D>> for SubmitSyncBuilderLayer<I>
where I: AddCommand<commands_raw::CmdCopyBufferToImage<S, D>, Out = O>,
S: BufferAccess + Send + Sync + Clone + 'static,
D: ImageAccess + Send + Sync + Clone + 'static
{
type Out = SubmitSyncBuilderLayer<O>;
#[inline]
fn add(mut self, command: commands_raw::CmdCopyBufferToImage<S, D>) -> Result<Self::Out, CommandAddError> {
self.add_buffer(command.source(), false,
PipelineStages { transfer: true, .. PipelineStages::none() },
AccessFlagBits { transfer_read: true, .. AccessFlagBits::none() });
self.add_image(command.destination(), true,
PipelineStages { transfer: true, .. PipelineStages::none() },
AccessFlagBits { transfer_write: true, .. AccessFlagBits::none() });
Ok(SubmitSyncBuilderLayer {
inner: AddCommand::add(self.inner, command)?,
resources: self.resources,
behavior: self.behavior,
})
}
}
unsafe impl<I, O, S, D> AddCommand<commands_raw::CmdCopyImage<S, D>> for SubmitSyncBuilderLayer<I>
where I: AddCommand<commands_raw::CmdCopyImage<S, D>, Out = O>,
S: ImageAccess + Send + Sync + Clone + 'static,
D: ImageAccess + Send + Sync + Clone + 'static
{
type Out = SubmitSyncBuilderLayer<O>;
#[inline]
fn add(mut self, command: commands_raw::CmdCopyImage<S, D>) -> Result<Self::Out, CommandAddError> {
self.add_image(command.source(), false,
PipelineStages { transfer: true, .. PipelineStages::none() },
AccessFlagBits { transfer_read: true, .. AccessFlagBits::none() });
self.add_image(command.destination(), true,
PipelineStages { transfer: true, .. PipelineStages::none() },
AccessFlagBits { transfer_write: true, .. AccessFlagBits::none() });
Ok(SubmitSyncBuilderLayer {
inner: AddCommand::add(self.inner, command)?,
resources: self.resources,
behavior: self.behavior,
})
}
}
unsafe impl<I, O> AddCommand<commands_raw::CmdDispatchRaw> for SubmitSyncBuilderLayer<I>
where I: AddCommand<commands_raw::CmdDispatchRaw, Out = O>
{
type Out = SubmitSyncBuilderLayer<O>;
#[inline]
fn add(self, command: commands_raw::CmdDispatchRaw) -> Result<Self::Out, CommandAddError> {
Ok(SubmitSyncBuilderLayer {
inner: AddCommand::add(self.inner, command)?,
resources: self.resources,
behavior: self.behavior,
})
}
}
unsafe impl<I, O> AddCommand<commands_raw::CmdDrawRaw> for SubmitSyncBuilderLayer<I>
where I: AddCommand<commands_raw::CmdDrawRaw, Out = O>
{
type Out = SubmitSyncBuilderLayer<O>;
#[inline]
fn add(self, command: commands_raw::CmdDrawRaw) -> Result<Self::Out, CommandAddError> {
Ok(SubmitSyncBuilderLayer {
inner: AddCommand::add(self.inner, command)?,
resources: self.resources,
behavior: self.behavior,
})
}
}
unsafe impl<I, O> AddCommand<commands_raw::CmdDrawIndexedRaw> for SubmitSyncBuilderLayer<I>
where I: AddCommand<commands_raw::CmdDrawIndexedRaw, Out = O>
{
type Out = SubmitSyncBuilderLayer<O>;
#[inline]
fn add(self, command: commands_raw::CmdDrawIndexedRaw) -> Result<Self::Out, CommandAddError> {
Ok(SubmitSyncBuilderLayer {
inner: AddCommand::add(self.inner, command)?,
resources: self.resources,
behavior: self.behavior,
})
}
}
unsafe impl<I, O, B> AddCommand<commands_raw::CmdDrawIndirectRaw<B>> for SubmitSyncBuilderLayer<I>
where I: AddCommand<commands_raw::CmdDrawIndirectRaw<B>, Out = O>,
B: BufferAccess + Send + Sync + Clone + 'static
{
type Out = SubmitSyncBuilderLayer<O>;
#[inline]
fn add(mut self, command: commands_raw::CmdDrawIndirectRaw<B>) -> Result<Self::Out, CommandAddError> {
self.add_buffer(command.buffer(), false,
PipelineStages { draw_indirect: true, .. PipelineStages::none() },
AccessFlagBits { indirect_command_read: true, .. AccessFlagBits::none() });
Ok(SubmitSyncBuilderLayer {
inner: AddCommand::add(self.inner, command)?,
resources: self.resources,
behavior: self.behavior,
})
}
}
unsafe impl<I, O> AddCommand<commands_raw::CmdEndRenderPass> for SubmitSyncBuilderLayer<I>
where I: AddCommand<commands_raw::CmdEndRenderPass, Out = O>
{
type Out = SubmitSyncBuilderLayer<O>;
#[inline]
fn add(self, command: commands_raw::CmdEndRenderPass) -> Result<Self::Out, CommandAddError> {
Ok(SubmitSyncBuilderLayer {
inner: AddCommand::add(self.inner, command)?,
resources: self.resources,
behavior: self.behavior,
})
}
}
unsafe impl<I, O, B> AddCommand<commands_raw::CmdFillBuffer<B>> for SubmitSyncBuilderLayer<I>
where I: AddCommand<commands_raw::CmdFillBuffer<B>, Out = O>,
B: BufferAccess + Send + Sync + Clone + 'static
{
type Out = SubmitSyncBuilderLayer<O>;
#[inline]
fn add(mut self, command: commands_raw::CmdFillBuffer<B>) -> Result<Self::Out, CommandAddError> {
self.add_buffer(command.buffer(), true,
PipelineStages { transfer: true, .. PipelineStages::none() },
AccessFlagBits { transfer_write: true, .. AccessFlagBits::none() });
Ok(SubmitSyncBuilderLayer {
inner: AddCommand::add(self.inner, command)?,
resources: self.resources,
behavior: self.behavior,
})
}
}
unsafe impl<I, O> AddCommand<commands_raw::CmdNextSubpass> for SubmitSyncBuilderLayer<I>
where I: AddCommand<commands_raw::CmdNextSubpass, Out = O>
{
type Out = SubmitSyncBuilderLayer<O>;
#[inline]
fn add(self, command: commands_raw::CmdNextSubpass) -> Result<Self::Out, CommandAddError> {
Ok(SubmitSyncBuilderLayer {
inner: AddCommand::add(self.inner, command)?,
resources: self.resources,
behavior: self.behavior,
})
}
}
unsafe impl<I, O, Pc, Pl> AddCommand<commands_raw::CmdPushConstants<Pc, Pl>> for SubmitSyncBuilderLayer<I>
where I: AddCommand<commands_raw::CmdPushConstants<Pc, Pl>, Out = O>
{
type Out = SubmitSyncBuilderLayer<O>;
#[inline]
fn add(self, command: commands_raw::CmdPushConstants<Pc, Pl>) -> Result<Self::Out, CommandAddError> {
Ok(SubmitSyncBuilderLayer {
inner: AddCommand::add(self.inner, command)?,
resources: self.resources,
behavior: self.behavior,
})
}
}
unsafe impl<I, O, S, D> AddCommand<commands_raw::CmdResolveImage<S, D>> for SubmitSyncBuilderLayer<I>
where I: AddCommand<commands_raw::CmdResolveImage<S, D>, Out = O>,
S: ImageAccess + Send + Sync + Clone + 'static,
D: ImageAccess + Send + Sync + Clone + 'static
{
type Out = SubmitSyncBuilderLayer<O>;
#[inline]
fn add(mut self, command: commands_raw::CmdResolveImage<S, D>) -> Result<Self::Out, CommandAddError> {
self.add_image(command.source(), false,
PipelineStages { transfer: true, .. PipelineStages::none() },
AccessFlagBits { transfer_write: true, .. AccessFlagBits::none() });
self.add_image(command.destination(), true,
PipelineStages { transfer: true, .. PipelineStages::none() },
AccessFlagBits { transfer_write: true, .. AccessFlagBits::none() });
Ok(SubmitSyncBuilderLayer {
inner: AddCommand::add(self.inner, command)?,
resources: self.resources,
behavior: self.behavior,
})
}
}
unsafe impl<I, O> AddCommand<commands_raw::CmdSetEvent> for SubmitSyncBuilderLayer<I>
where I: AddCommand<commands_raw::CmdSetEvent, Out = O>
{
type Out = SubmitSyncBuilderLayer<O>;
#[inline]
fn add(self, command: commands_raw::CmdSetEvent) -> Result<Self::Out, CommandAddError> {
Ok(SubmitSyncBuilderLayer {
inner: AddCommand::add(self.inner, command)?,
resources: self.resources,
behavior: self.behavior,
})
}
}
unsafe impl<I, O> AddCommand<commands_raw::CmdSetState> for SubmitSyncBuilderLayer<I>
where I: AddCommand<commands_raw::CmdSetState, Out = O>
{
type Out = SubmitSyncBuilderLayer<O>;
#[inline]
fn add(self, command: commands_raw::CmdSetState) -> Result<Self::Out, CommandAddError> {
Ok(SubmitSyncBuilderLayer {
inner: AddCommand::add(self.inner, command)?,
resources: self.resources,
behavior: self.behavior,
})
}
}
unsafe impl<I, O, B, D> AddCommand<commands_raw::CmdUpdateBuffer<B, D>> for SubmitSyncBuilderLayer<I>
where I: AddCommand<commands_raw::CmdUpdateBuffer<B, D>, Out = O>,
B: BufferAccess + Send + Sync + Clone + 'static
{
type Out = SubmitSyncBuilderLayer<O>;
#[inline]
fn add(mut self, command: commands_raw::CmdUpdateBuffer<B, D>) -> Result<Self::Out, CommandAddError> {
self.add_buffer(command.buffer(), true,
PipelineStages { transfer: true, .. PipelineStages::none() },
AccessFlagBits { transfer_write: true, .. AccessFlagBits::none() });
Ok(SubmitSyncBuilderLayer {
inner: AddCommand::add(self.inner, command)?,
resources: self.resources,
behavior: self.behavior,
})
}
}
pub struct SubmitSyncLayer<I> {
inner: I,
resources: FnvHashMap<Key, ResourceEntry>,
}
unsafe impl<I> CommandBuffer for SubmitSyncLayer<I> where I: CommandBuffer {
type Pool = I::Pool;
#[inline]
fn inner(&self) -> &UnsafeCommandBuffer<I::Pool> {
self.inner.inner()
}
fn prepare_submit(&self, future: &GpuFuture, queue: &Queue) -> Result<(), CommandBufferExecError> {
for (key, entry) in self.resources.iter() {
match key {
&Key::Buffer(ref buf) => {
let prev_err = match future.check_buffer_access(&buf, entry.exclusive, queue) {
Ok(_) => {
unsafe { buf.increase_gpu_lock(); }
continue;
},
Err(err) => err
};
match (buf.try_gpu_lock(entry.exclusive, queue), prev_err) {
(Ok(_), _) => (),
(Err(err), AccessCheckError::Unknown) => return Err(err.into()),
(_, AccessCheckError::Denied(err)) => return Err(err.into()),
}
},
&Key::Image(ref img) => {
let prev_err = match future.check_image_access(img, entry.initial_layout,
entry.exclusive, queue)
{
Ok(_) => {
unsafe { img.increase_gpu_lock(); }
continue;
},
Err(err) => err
};
match (img.try_gpu_lock(entry.exclusive, queue), prev_err) {
(Ok(_), _) => (),
(Err(err), AccessCheckError::Unknown) => return Err(err.into()),
(_, AccessCheckError::Denied(err)) => return Err(err.into()),
}
},
&Key::FramebufferAttachment(ref fb, idx) => {
let img = fb.attachments()[idx as usize].parent();
let prev_err = match future.check_image_access(img, entry.initial_layout,
entry.exclusive, queue)
{
Ok(_) => {
unsafe { img.increase_gpu_lock(); }
continue;
},
Err(err) => err
};
match (img.try_gpu_lock(entry.exclusive, queue), prev_err) {
(Ok(_), _) => (),
(Err(err), AccessCheckError::Unknown) => return Err(err.into()),
(_, AccessCheckError::Denied(err)) => return Err(err.into()),
}
},
}
}
Ok(())
}
#[inline]
fn check_buffer_access(&self, buffer: &BufferAccess, exclusive: bool, queue: &Queue)
-> Result<Option<(PipelineStages, AccessFlagBits)>, AccessCheckError>
{
for (key, value) in self.resources.iter() {
if !key.conflicts_buffer_all(buffer) {
continue;
}
if !value.exclusive && exclusive {
return Err(AccessCheckError::Denied(AccessError::ExclusiveDenied));
}
return Ok(Some((value.final_stages, value.final_access)));
}
Err(AccessCheckError::Unknown)
}
#[inline]
fn check_image_access(&self, image: &ImageAccess, layout: ImageLayout, exclusive: bool, queue: &Queue)
-> Result<Option<(PipelineStages, AccessFlagBits)>, AccessCheckError>
{
for (key, value) in self.resources.iter() {
if !key.conflicts_image_all(image) {
continue;
}
if layout != ImageLayout::Undefined && value.final_layout != layout {
return Err(AccessCheckError::Denied(AccessError::UnexpectedImageLayout {
allowed: value.final_layout,
requested: layout,
}));
}
if !value.exclusive && exclusive {
return Err(AccessCheckError::Denied(AccessError::ExclusiveDenied));
}
return Ok(Some((value.final_stages, value.final_access)));
}
Err(AccessCheckError::Unknown)
}
}
unsafe impl<I> DeviceOwned for SubmitSyncLayer<I> where I: DeviceOwned {
#[inline]
fn device(&self) -> &Arc<Device> {
self.inner.device()
}
}