use std::error;
use std::fmt;
use std::sync::Arc;
use OomError;
use buffer::BufferAccess;
use command_buffer::CommandBuffer;
use command_buffer::CommandBufferExecError;
use command_buffer::CommandBufferExecFuture;
use command_buffer::submit::SubmitAnyBuilder;
use command_buffer::submit::SubmitBindSparseError;
use command_buffer::submit::SubmitCommandBufferError;
use command_buffer::submit::SubmitPresentError;
use device::DeviceOwned;
use device::Queue;
use image::ImageAccess;
use image::ImageLayout;
use swapchain;
use swapchain::PresentFuture;
use swapchain::PresentRegion;
use swapchain::Swapchain;
use sync::AccessFlagBits;
use sync::FenceWaitError;
use sync::PipelineStages;
pub use self::fence_signal::{FenceSignalFuture, FenceSignalFutureBehavior};
pub use self::join::JoinFuture;
pub use self::now::{NowFuture, now};
pub use self::semaphore_signal::SemaphoreSignalFuture;
mod now;
mod fence_signal;
mod join;
mod semaphore_signal;
pub unsafe trait GpuFuture: DeviceOwned {
fn cleanup_finished(&mut self);
unsafe fn build_submission(&self) -> Result<SubmitAnyBuilder, FlushError>;
fn flush(&self) -> Result<(), FlushError>;
unsafe fn signal_finished(&self);
fn queue(&self) -> Option<Arc<Queue>>;
fn queue_change_allowed(&self) -> bool;
fn check_buffer_access(&self, buffer: &dyn BufferAccess, exclusive: bool, queue: &Queue)
-> Result<Option<(PipelineStages, AccessFlagBits)>, AccessCheckError>;
fn check_image_access(&self, image: &dyn ImageAccess, layout: ImageLayout, exclusive: bool,
queue: &Queue)
-> Result<Option<(PipelineStages, AccessFlagBits)>, AccessCheckError>;
fn join<F>(self, other: F) -> JoinFuture<Self, F>
where Self: Sized,
F: GpuFuture
{
join::join(self, other)
}
#[inline]
fn then_execute<Cb>(self, queue: Arc<Queue>, command_buffer: Cb)
-> Result<CommandBufferExecFuture<Self, Cb>, CommandBufferExecError>
where Self: Sized,
Cb: CommandBuffer + 'static
{
command_buffer.execute_after(self, queue)
}
#[inline]
fn then_execute_same_queue<Cb>(
self, command_buffer: Cb)
-> Result<CommandBufferExecFuture<Self, Cb>, CommandBufferExecError>
where Self: Sized,
Cb: CommandBuffer + 'static
{
let queue = self.queue().unwrap().clone();
command_buffer.execute_after(self, queue)
}
#[inline]
fn then_signal_semaphore(self) -> SemaphoreSignalFuture<Self>
where Self: Sized
{
semaphore_signal::then_signal_semaphore(self)
}
#[inline]
fn then_signal_semaphore_and_flush(self) -> Result<SemaphoreSignalFuture<Self>, FlushError>
where Self: Sized
{
let f = self.then_signal_semaphore();
f.flush()?;
Ok(f)
}
#[inline]
fn then_signal_fence(self) -> FenceSignalFuture<Self>
where Self: Sized
{
fence_signal::then_signal_fence(self, FenceSignalFutureBehavior::Continue)
}
#[inline]
fn then_signal_fence_and_flush(self) -> Result<FenceSignalFuture<Self>, FlushError>
where Self: Sized
{
let f = self.then_signal_fence();
f.flush()?;
Ok(f)
}
#[inline]
fn then_swapchain_present<W>(self, queue: Arc<Queue>, swapchain: Arc<Swapchain<W>>,
image_index: usize)
-> PresentFuture<Self,W>
where Self: Sized
{
swapchain::present(swapchain, self, queue, image_index)
}
#[inline]
fn then_swapchain_present_incremental<W>(self, queue: Arc<Queue>, swapchain: Arc<Swapchain<W>>,
image_index: usize, present_region: PresentRegion)
-> PresentFuture<Self,W>
where Self: Sized
{
swapchain::present_incremental(swapchain, self, queue, image_index, present_region)
}
}
unsafe impl<F: ?Sized> GpuFuture for Box<F>
where F: GpuFuture
{
#[inline]
fn cleanup_finished(&mut self) {
(**self).cleanup_finished()
}
#[inline]
unsafe fn build_submission(&self) -> Result<SubmitAnyBuilder, FlushError> {
(**self).build_submission()
}
#[inline]
fn flush(&self) -> Result<(), FlushError> {
(**self).flush()
}
#[inline]
unsafe fn signal_finished(&self) {
(**self).signal_finished()
}
#[inline]
fn queue_change_allowed(&self) -> bool {
(**self).queue_change_allowed()
}
#[inline]
fn queue(&self) -> Option<Arc<Queue>> {
(**self).queue()
}
#[inline]
fn check_buffer_access(
&self, buffer: &dyn BufferAccess, exclusive: bool, queue: &Queue)
-> Result<Option<(PipelineStages, AccessFlagBits)>, AccessCheckError> {
(**self).check_buffer_access(buffer, exclusive, queue)
}
#[inline]
fn check_image_access(&self, image: &dyn ImageAccess, layout: ImageLayout, exclusive: bool,
queue: &Queue)
-> Result<Option<(PipelineStages, AccessFlagBits)>, AccessCheckError> {
(**self).check_image_access(image, layout, exclusive, queue)
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum AccessError {
ExclusiveDenied,
AlreadyInUse,
UnexpectedImageLayout {
allowed: ImageLayout,
requested: ImageLayout,
},
ImageNotInitialized {
requested: ImageLayout,
},
BufferNotInitialized,
SwapchainImageAcquireOnly,
}
impl error::Error for AccessError {
#[inline]
fn description(&self) -> &str {
match *self {
AccessError::ExclusiveDenied => {
"only shared access is allowed for this resource"
},
AccessError::AlreadyInUse => {
"the resource is already in use, and there is no tracking of concurrent usages"
},
AccessError::UnexpectedImageLayout { .. } => {
unimplemented!() },
AccessError::ImageNotInitialized { .. } => {
"trying to use an image without transitioning it from the undefined or \
preinitialized layouts first"
},
AccessError::BufferNotInitialized => {
"trying to use a buffer that still contains garbage data"
},
AccessError::SwapchainImageAcquireOnly => {
"trying to use a swapchain image without depending on a corresponding acquire \
image future"
},
}
}
}
impl fmt::Display for AccessError {
#[inline]
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(fmt, "{}", error::Error::description(self))
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum AccessCheckError {
Denied(AccessError),
Unknown,
}
impl error::Error for AccessCheckError {
#[inline]
fn description(&self) -> &str {
match *self {
AccessCheckError::Denied(_) => {
"access to the resource has been denied"
},
AccessCheckError::Unknown => {
"the resource is unknown"
},
}
}
}
impl fmt::Display for AccessCheckError {
#[inline]
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(fmt, "{}", error::Error::description(self))
}
}
impl From<AccessError> for AccessCheckError {
#[inline]
fn from(err: AccessError) -> AccessCheckError {
AccessCheckError::Denied(err)
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum FlushError {
AccessError(AccessError),
OomError(OomError),
DeviceLost,
SurfaceLost,
OutOfDate,
Timeout,
}
impl error::Error for FlushError {
#[inline]
fn description(&self) -> &str {
match *self {
FlushError::AccessError(_) => "access to a resource has been denied",
FlushError::OomError(_) => "not enough memory",
FlushError::DeviceLost => "the connection to the device has been lost",
FlushError::SurfaceLost => "the surface of this swapchain is no longer valid",
FlushError::OutOfDate => "the swapchain needs to be recreated",
FlushError::Timeout => "the flush operation needed to block, but the timeout has \
elapsed",
}
}
#[inline]
fn cause(&self) -> Option<&dyn error::Error> {
match *self {
FlushError::AccessError(ref err) => Some(err),
FlushError::OomError(ref err) => Some(err),
_ => None,
}
}
}
impl fmt::Display for FlushError {
#[inline]
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(fmt, "{}", error::Error::description(self))
}
}
impl From<AccessError> for FlushError {
#[inline]
fn from(err: AccessError) -> FlushError {
FlushError::AccessError(err)
}
}
impl From<SubmitPresentError> for FlushError {
#[inline]
fn from(err: SubmitPresentError) -> FlushError {
match err {
SubmitPresentError::OomError(err) => FlushError::OomError(err),
SubmitPresentError::DeviceLost => FlushError::DeviceLost,
SubmitPresentError::SurfaceLost => FlushError::SurfaceLost,
SubmitPresentError::OutOfDate => FlushError::OutOfDate,
}
}
}
impl From<SubmitCommandBufferError> for FlushError {
#[inline]
fn from(err: SubmitCommandBufferError) -> FlushError {
match err {
SubmitCommandBufferError::OomError(err) => FlushError::OomError(err),
SubmitCommandBufferError::DeviceLost => FlushError::DeviceLost,
}
}
}
impl From<SubmitBindSparseError> for FlushError {
#[inline]
fn from(err: SubmitBindSparseError) -> FlushError {
match err {
SubmitBindSparseError::OomError(err) => FlushError::OomError(err),
SubmitBindSparseError::DeviceLost => FlushError::DeviceLost,
}
}
}
impl From<FenceWaitError> for FlushError {
#[inline]
fn from(err: FenceWaitError) -> FlushError {
match err {
FenceWaitError::OomError(err) => FlushError::OomError(err),
FenceWaitError::Timeout => FlushError::Timeout,
FenceWaitError::DeviceLostError => FlushError::DeviceLost,
}
}
}