Merge pull request #32 from Mixthos/optional-oomerrors

Optional OomErrors
This commit is contained in:
tomaka 2016-04-15 16:16:52 +02:00
commit 68cc6057c9
24 changed files with 506 additions and 174 deletions

View File

@ -78,8 +78,7 @@ fn main() {
};
let cb_pool = vulkano::command_buffer::CommandBufferPool::new(&device, &queue.family())
.expect("failed to create command buffer pool");
let cb_pool = vulkano::command_buffer::CommandBufferPool::new(&device, &queue.family());
let depth_buffer = vulkano::image::attachment::AttachmentImage::transient(&device, images[0].dimensions(), vulkano::format::D16Unorm).unwrap();
@ -162,9 +161,9 @@ fn main() {
let renderpass = renderpass::CustomRenderPass::new(&device, &renderpass::Formats {
color: (images[0].format(), 1),
depth: (vulkano::format::D16Unorm, 1)
}).unwrap();
});
let descriptor_pool = vulkano::descriptor::descriptor_set::DescriptorPool::new(&device).unwrap();
let descriptor_pool = vulkano::descriptor::descriptor_set::DescriptorPool::new(&device);
mod pipeline_layout {
pipeline_layout!{
@ -177,7 +176,7 @@ fn main() {
let pipeline_layout = pipeline_layout::CustomPipeline::new(&device).unwrap();
let set = pipeline_layout::set0::Set::new(&descriptor_pool, &pipeline_layout, &pipeline_layout::set0::Descriptors {
uniforms: &uniform_buffer
}).unwrap();
});
let pipeline = vulkano::pipeline::GraphicsPipeline::new(&device, vulkano::pipeline::GraphicsPipelineParams {
vertex_input: vulkano::pipeline::vertex::TwoBuffersDefinition::new(),
@ -214,7 +213,7 @@ fn main() {
let command_buffers = framebuffers.iter().map(|framebuffer| {
vulkano::command_buffer::PrimaryCommandBufferBuilder::new(&cb_pool).unwrap()
vulkano::command_buffer::PrimaryCommandBufferBuilder::new(&cb_pool)
.draw_inline(&renderpass, &framebuffer, renderpass::ClearValues {
color: [0.0, 0.0, 1.0, 1.0].into(),
depth: 1.0,
@ -222,7 +221,7 @@ fn main() {
.draw_indexed(&pipeline, (&vertex_buffer, &normals_buffer), &index_buffer,
&vulkano::command_buffer::DynamicState::none(), &set, &())
.draw_end()
.build().unwrap()
.build()
}).collect::<Vec<_>>();
let mut submissions: Vec<Arc<vulkano::command_buffer::Submission>> = Vec::new();

View File

@ -1694,7 +1694,9 @@ pub fn submit(me: &InnerCommandBuffer, me_arc: Arc<KeepAlive>,
assert_eq!(queue.device().internal_object(), me.pool.device().internal_object());
assert_eq!(queue.family().id(), me.pool.queue_family().id());
let fence = try!(Fence::new(queue.device()));
// TODO: check if this change is okay (maybe the Arc can be omitted?) - Mixthos
//let fence = try!(Fence::new(queue.device()));
let fence = Arc::new(try!(Fence::raw(queue.device())));
let mut keep_alive_semaphores = SmallVec::<[_; 8]>::new();
let mut post_semaphores_ids = SmallVec::<[_; 8]>::new();
@ -1706,7 +1708,9 @@ pub fn submit(me: &InnerCommandBuffer, me_arc: Arc<KeepAlive>,
// TODO: for now that's not true ^ as semaphores are only used once then destroyed ;
// waiting on https://github.com/KhronosGroup/Vulkan-Docs/issues/155
{
let signalled = try!(Semaphore::new(queue.device()));
// TODO: check if this change is okay (maybe the Arc can be omitted?) - Mixthos
//let signalled = try!(Semaphore::new(queue.device()));
let signalled = Arc::new(try!(Semaphore::raw(queue.device())));
let wait = unsafe { queue.dedicated_semaphore(signalled.clone()) };
if let Some(wait) = wait {
pre_semaphores_ids.push(wait.internal_object());
@ -1723,7 +1727,9 @@ pub fn submit(me: &InnerCommandBuffer, me_arc: Arc<KeepAlive>,
let semaphores_to_signal = {
let mut list = SmallVec::new();
for _ in 0 .. queue_transitions_hint {
let sem = try!(Semaphore::new(queue.device()));
// TODO: check if this change is okay (maybe the Arc can be omitted?) - Mixthos
//let sem = try!(Semaphore::new(queue.device()));
let sem = Arc::new(try!(Semaphore::raw(queue.device())));
post_semaphores_ids.push(sem.internal_object());
keep_alive_semaphores.push(sem.clone());
list.push(sem);
@ -1861,7 +1867,8 @@ pub fn submit(me: &InnerCommandBuffer, me_arc: Arc<KeepAlive>,
let mut infos = SmallVec::<[_; 3]>::new();
if !before_command_buffers.is_empty() {
let semaphore = Semaphore::new(queue.device()).unwrap();
// TODO: Use try!()? - Mixthos
let semaphore = Semaphore::new(queue.device());
let semaphore_id = semaphore.internal_object();
pre_semaphores_stages.push(vk::PIPELINE_STAGE_TOP_OF_PIPE_BIT); // TODO:
pre_semaphores_ids.push(semaphore.internal_object());
@ -1881,7 +1888,8 @@ pub fn submit(me: &InnerCommandBuffer, me_arc: Arc<KeepAlive>,
}
let after_semaphore = if !after_command_buffers.is_empty() {
let semaphore = Semaphore::new(queue.device()).unwrap();
// TODO: Use try!()? - Mixthos
let semaphore = Semaphore::new(queue.device());
let semaphore_id = semaphore.internal_object();
post_semaphores_ids.push(semaphore.internal_object());
keep_alive_semaphores.push(semaphore);

View File

@ -61,14 +61,27 @@ pub struct PrimaryCommandBufferBuilder {
}
impl PrimaryCommandBufferBuilder {
/// Builds a new primary command buffer and start recording commands in it.
/// See the docs of new().
#[inline]
pub fn new(pool: &Arc<CommandBufferPool>)
pub fn raw(pool: &Arc<CommandBufferPool>)
-> Result<PrimaryCommandBufferBuilder, OomError>
{
let inner = try!(InnerCommandBufferBuilder::new::<UnsafeRenderPass>(pool, false, None, None));
Ok(PrimaryCommandBufferBuilder { inner: inner })
}
/// Builds a new primary command buffer and start recording commands in it.
///
/// # Panic
///
/// - Panicks if the device or host ran out of memory.
///
#[inline]
pub fn new(pool: &Arc<CommandBufferPool>)
-> PrimaryCommandBufferBuilder
{
PrimaryCommandBufferBuilder::raw(pool).unwrap()
}
/// Writes data to a buffer.
///
@ -266,11 +279,22 @@ impl PrimaryCommandBufferBuilder {
}
}
/// Finish recording commands and build the command buffer.
/// See the docs of build().
#[inline]
pub fn build(self) -> Result<Arc<PrimaryCommandBuffer>, OomError> {
pub fn build_raw(self) -> Result<PrimaryCommandBuffer, OomError> {
let inner = try!(self.inner.build());
Ok(Arc::new(PrimaryCommandBuffer { inner: inner }))
Ok(PrimaryCommandBuffer { inner: inner })
}
/// Finish recording commands and build the command buffer.
///
/// # Panic
///
/// - Panicks if the device or host ran out of memory.
///
#[inline]
pub fn build(self) -> Arc<PrimaryCommandBuffer> {
Arc::new(self.build_raw().unwrap())
}
}
@ -511,11 +535,9 @@ pub struct SecondaryGraphicsCommandBufferBuilder<R> {
impl<R> SecondaryGraphicsCommandBufferBuilder<R>
where R: RenderPass + RenderPassDesc + 'static
{
/// Builds a new secondary command buffer and start recording commands in it.
///
/// The `framebuffer` parameter is optional and can be used as an optimisation.
/// See the docs of new().
#[inline]
pub fn new(pool: &Arc<CommandBufferPool>, subpass: Subpass<R>,
pub fn raw(pool: &Arc<CommandBufferPool>, subpass: Subpass<R>,
framebuffer: Option<&Arc<Framebuffer<R>>>)
-> Result<SecondaryGraphicsCommandBufferBuilder<R>, OomError>
where R: 'static + Send + Sync
@ -529,6 +551,23 @@ impl<R> SecondaryGraphicsCommandBufferBuilder<R>
})
}
/// Builds a new secondary command buffer and start recording commands in it.
///
/// The `framebuffer` parameter is optional and can be used as an optimisation.
///
/// # Panic
///
/// - Panicks if the device or host ran out of memory.
///
#[inline]
pub fn new(pool: &Arc<CommandBufferPool>, subpass: Subpass<R>,
framebuffer: Option<&Arc<Framebuffer<R>>>)
-> SecondaryGraphicsCommandBufferBuilder<R>
where R: 'static + Send + Sync
{
SecondaryGraphicsCommandBufferBuilder::raw(pool, subpass, framebuffer).unwrap()
}
/// Calls `vkCmdDraw`.
// FIXME: push constants
pub fn draw<V, L, Pv, Pl, Rp, Pc>(self, pipeline: &Arc<GraphicsPipeline<Pv, Pl, Rp>>,
@ -594,16 +633,27 @@ impl<R> SecondaryGraphicsCommandBufferBuilder<R>
}
}
/// Finish recording commands and build the command buffer.
/// See the docs of build().
#[inline]
pub fn build(self) -> Result<Arc<SecondaryGraphicsCommandBuffer<R>>, OomError> {
pub fn build_raw(self) -> Result<SecondaryGraphicsCommandBuffer<R>, OomError> {
let inner = try!(self.inner.build());
Ok(Arc::new(SecondaryGraphicsCommandBuffer {
Ok(SecondaryGraphicsCommandBuffer {
inner: inner,
render_pass: self.render_pass,
render_pass_subpass: self.render_pass_subpass,
}))
})
}
/// Finish recording commands and build the command buffer.
///
/// # Panic
///
/// - Panicks if the device or host ran out of memory.
///
#[inline]
pub fn build(self) -> Arc<SecondaryGraphicsCommandBuffer<R>> {
Arc::new(self.build_raw().unwrap())
}
}
@ -626,15 +676,28 @@ pub struct SecondaryComputeCommandBufferBuilder {
}
impl SecondaryComputeCommandBufferBuilder {
/// Builds a new secondary command buffer and start recording commands in it.
/// See the docs of new().
#[inline]
pub fn new(pool: &Arc<CommandBufferPool>)
pub fn raw(pool: &Arc<CommandBufferPool>)
-> Result<SecondaryComputeCommandBufferBuilder, OomError>
{
let inner = try!(InnerCommandBufferBuilder::new::<UnsafeRenderPass>(pool, true, None, None));
Ok(SecondaryComputeCommandBufferBuilder { inner: inner })
}
/// Builds a new secondary command buffer and start recording commands in it.
///
/// # Panic
///
/// - Panicks if the device or host ran out of memory.
///
#[inline]
pub fn new(pool: &Arc<CommandBufferPool>)
-> SecondaryComputeCommandBufferBuilder
{
SecondaryComputeCommandBufferBuilder::raw(pool).unwrap()
}
/// Writes data to a buffer.
///
/// The data is stored inside the command buffer and written to the given buffer slice.
@ -684,11 +747,22 @@ impl SecondaryComputeCommandBufferBuilder {
}
}
/// Finish recording commands and build the command buffer.
/// See the docs of build().
#[inline]
pub fn build(self) -> Result<Arc<SecondaryComputeCommandBuffer>, OomError> {
pub fn build_raw(self) -> Result<SecondaryComputeCommandBuffer, OomError> {
let inner = try!(self.inner.build());
Ok(Arc::new(SecondaryComputeCommandBuffer { inner: inner }))
Ok(SecondaryComputeCommandBuffer { inner: inner })
}
/// Finish recording commands and build the command buffer.
///
/// # Panic
///
/// - Panicks if the device or host ran out of memory.
///
#[inline]
pub fn build(self) -> Arc<SecondaryComputeCommandBuffer> {
Arc::new(self.build_raw().unwrap())
}
}

View File

@ -31,18 +31,10 @@ pub struct CommandBufferPool {
}
impl CommandBufferPool {
/// Creates a new pool.
///
/// The command buffers created with this pool can only be executed on queues of the given
/// family.
///
/// # Panic
///
/// Panicks if the queue family doesn't belong to the same physical device as `device`.
///
/// See the docs of new().
#[inline]
pub fn new(device: &Arc<Device>, queue_family: &QueueFamily)
-> Result<Arc<CommandBufferPool>, OomError>
pub fn raw(device: &Arc<Device>, queue_family: &QueueFamily)
-> Result<CommandBufferPool, OomError>
{
assert_eq!(device.physical_device().internal_object(),
queue_family.physical_device().internal_object());
@ -63,11 +55,28 @@ impl CommandBufferPool {
output
};
Ok(Arc::new(CommandBufferPool {
Ok(CommandBufferPool {
pool: Mutex::new(pool),
device: device.clone(),
queue_family_index: queue_family.id(),
}))
})
}
/// Creates a new pool.
///
/// The command buffers created with this pool can only be executed on queues of the given
/// family.
///
/// # Panic
///
/// - Panicks if the queue family doesn't belong to the same physical device as `device`.
/// - Panicks if the device or host ran out of memory.
///
#[inline]
pub fn new(device: &Arc<Device>, queue_family: &QueueFamily)
-> Arc<CommandBufferPool>
{
Arc::new(CommandBufferPool::raw(device, queue_family).unwrap())
}
/// Returns the device this command pool was created with.

View File

@ -32,9 +32,9 @@ pub struct DescriptorPool {
}
impl DescriptorPool {
/// Initializes a new pool.
/// See the docs of new().
// FIXME: capacity of the pool
pub fn new(device: &Arc<Device>) -> Result<Arc<DescriptorPool>, OomError> {
pub fn raw(device: &Arc<Device>) -> Result<DescriptorPool, OomError> {
let vk = device.pointers();
// FIXME: arbitrary
@ -77,10 +77,22 @@ impl DescriptorPool {
output
};
Ok(Arc::new(DescriptorPool {
Ok(DescriptorPool {
pool: Mutex::new(pool),
device: device.clone(),
}))
})
}
/// Initializes a new pool.
///
/// # Panic
///
/// - Panicks if the device or host ran out of memory.
///
// FIXME: capacity of the pool
#[inline]
pub fn new(device: &Arc<Device>) -> Arc<DescriptorPool> {
Arc::new(DescriptorPool::raw(device).unwrap())
}
/// Returns the device this pool was created from.
@ -117,13 +129,13 @@ mod tests {
#[test]
fn create() {
let (device, _) = gfx_dev_and_queue!();
let _ = DescriptorPool::new(&device).unwrap();
let _ = DescriptorPool::new(&device);
}
#[test]
fn device() {
let (device, _) = gfx_dev_and_queue!();
let pool = DescriptorPool::new(&device).unwrap();
let pool = DescriptorPool::new(&device);
assert_eq!(&**pool.device() as *const _, &*device as *const _);
}
}

View File

@ -46,16 +46,11 @@ pub struct UnsafeDescriptorSet {
}
impl UnsafeDescriptorSet {
/// Builds a new descriptor set.
///
/// # Panic
///
/// - Panicks if the pool and the layout were not created from the same `Device`.
///
/// See the docs of uninitialized().
// FIXME: this has to check whether there's still enough room in the pool
pub unsafe fn uninitialized(pool: &Arc<DescriptorPool>,
layout: &Arc<UnsafeDescriptorSetLayout>)
-> Result<UnsafeDescriptorSet, OomError>
pub unsafe fn uninitialized_raw(pool: &Arc<DescriptorPool>,
layout: &Arc<UnsafeDescriptorSetLayout>)
-> Result<UnsafeDescriptorSet, OomError>
{
assert_eq!(&**pool.device() as *const Device, &**layout.device() as *const Device);
@ -89,6 +84,22 @@ impl UnsafeDescriptorSet {
resources_buffers: Vec::new(),
})
}
/// Builds a new descriptor set.
///
/// # Panic
///
/// - Panicks if the pool and the layout were not created from the same `Device`.
/// - Panicks if the device or host ran out of memory.
///
// FIXME: this has to check whether there's still enough room in the pool
#[inline]
pub unsafe fn uninitialized(pool: &Arc<DescriptorPool>,
layout: &Arc<UnsafeDescriptorSetLayout>)
-> UnsafeDescriptorSet
{
UnsafeDescriptorSet::uninitialized_raw(pool, layout).unwrap()
}
/// Modifies a descriptor set without checking that the writes are correct.
///

View File

@ -31,9 +31,9 @@ pub struct UnsafeDescriptorSetLayout {
}
impl UnsafeDescriptorSetLayout {
/// Builds a new `UnsafeDescriptorSetLayout` with the given descriptors.
pub fn new<I>(device: &Arc<Device>, descriptors: I)
-> Result<Arc<UnsafeDescriptorSetLayout>, OomError>
/// See the docs of new().
pub fn raw<I>(device: &Arc<Device>, descriptors: I)
-> Result<UnsafeDescriptorSetLayout, OomError>
where I: IntoIterator<Item = DescriptorDesc>
{
let vk = device.pointers();
@ -63,10 +63,23 @@ impl UnsafeDescriptorSetLayout {
output
};
Ok(Arc::new(UnsafeDescriptorSetLayout {
Ok(UnsafeDescriptorSetLayout {
layout: layout,
device: device.clone(),
}))
})
}
/// Builds a new `UnsafeDescriptorSetLayout` with the given descriptors.
///
/// # Panic
///
/// - Panicks if the device or host ran out of memory.
///
#[inline]
pub fn new<I>(device: &Arc<Device>, descriptors: I) -> Arc<UnsafeDescriptorSetLayout>
where I: IntoIterator<Item = DescriptorDesc>
{
Arc::new(UnsafeDescriptorSetLayout::raw(device, descriptors).unwrap())
}
/// Returns the device used to create this layout.

View File

@ -49,7 +49,7 @@ macro_rules! pipeline_layout {
{
let layouts = vec![
$(
try!($name::build_set_layout(device))
Arc::new(try!($name::build_set_layout_raw(device)))
),*
];
@ -160,19 +160,29 @@ macro_rules! pipeline_layout {
impl Set {
#[inline]
#[allow(non_camel_case_types)]
pub fn new<$($field: ValidParameter<$ty>),*>
pub fn raw<$($field: ValidParameter<$ty>),*>
(pool: &Arc<DescriptorPool>, layout: &Arc<CustomPipeline>,
descriptors: &Descriptors<$($field),*>)
-> Result<Arc<Set>, OomError>
-> Result<Set, OomError>
{
#![allow(unsafe_code)]
unsafe {
let layout = layout.inner_pipeline_layout().descriptor_set_layout($num).unwrap();
let mut set = try!(UnsafeDescriptorSet::uninitialized(pool, layout));
let mut set = try!(UnsafeDescriptorSet::uninitialized_raw(pool, layout));
set.write(descriptors.writes());
Ok(Arc::new(Set { inner: set }))
Ok(Set { inner: set })
}
}
#[inline]
#[allow(non_camel_case_types)]
pub fn new<$($field: ValidParameter<$ty>),*>
(pool: &Arc<DescriptorPool>, layout: &Arc<CustomPipeline>,
descriptors: &Descriptors<$($field),*>)
-> Arc<Set>
{
Arc::new(Set::raw(pool, layout, descriptors).unwrap())
}
}
#[allow(unsafe_code)]
@ -195,8 +205,8 @@ macro_rules! pipeline_layout {
}
#[allow(unused_assignments)]
pub fn build_set_layout(device: &Arc<Device>)
-> Result<Arc<UnsafeDescriptorSetLayout>, OomError>
pub fn build_set_layout_raw(device: &Arc<Device>)
-> Result<UnsafeDescriptorSetLayout, OomError>
{
let mut descriptors = Vec::new();
let mut binding = 0;
@ -213,7 +223,14 @@ macro_rules! pipeline_layout {
binding += 1;
)*
UnsafeDescriptorSetLayout::new(device, descriptors.into_iter())
UnsafeDescriptorSetLayout::raw(device, descriptors.into_iter())
}
#[inline]
pub fn build_set_layout(device: &Arc<Device>)
-> Arc<UnsafeDescriptorSetLayout>
{
Arc::new(build_set_layout_raw(device).unwrap())
}
}

View File

@ -225,6 +225,7 @@ impl From<Error> for UnsafePipelineLayoutCreationError {
#[cfg(test)]
mod tests {
use std::iter;
use std::sync::Arc;
use descriptor::descriptor::ShaderStages;
use descriptor::descriptor_set::UnsafeDescriptorSetLayout;
use descriptor::pipeline_layout::sys::UnsafePipelineLayout;
@ -242,8 +243,8 @@ mod tests {
let (device1, _) = gfx_dev_and_queue!();
let (device2, _) = gfx_dev_and_queue!();
let set = match UnsafeDescriptorSetLayout::new(&device1, iter::empty()) {
Ok(s) => s,
let set = match UnsafeDescriptorSetLayout::raw(&device1, iter::empty()) {
Ok(s) => Arc::new(s),
Err(_) => return
};

View File

@ -213,19 +213,31 @@ impl Device {
Ok((device, output_queues))
}
/// Waits until all work on this device has finished. You should never need to call
/// this function, but it can be useful for debugging or benchmarking purposes.
///
/// This is the Vulkan equivalent of `glFinish`.
/// See the docs of wait().
// FIXME: must synchronize all queuees
#[inline]
pub fn wait(&self) -> Result<(), OomError> {
pub fn wait_raw(&self) -> Result<(), OomError> {
unsafe {
try!(check_errors(self.vk.DeviceWaitIdle(self.device)));
Ok(())
}
}
/// Waits until all work on this device has finished. You should never need to call
/// this function, but it can be useful for debugging or benchmarking purposes.
///
/// This is the Vulkan equivalent of `glFinish`.
///
/// # Panic
///
/// - Panicks if the device or host ran out of memory.
///
// FIXME: must synchronize all queuees
#[inline]
pub fn wait(&self) {
self.wait_raw().unwrap();
}
/// Returns the instance used to create this device.
#[inline]
pub fn instance(&self) -> &Arc<Instance> {
@ -369,11 +381,9 @@ impl Queue {
self.id
}
/// Waits until all work on this queue has finished.
///
/// Just like `Device::wait()`, you shouldn't have to call this function.
/// See the docs of wait().
#[inline]
pub fn wait(&self) -> Result<(), OomError> {
pub fn wait_raw(&self) -> Result<(), OomError> {
unsafe {
let vk = self.device.pointers();
let queue = self.queue.lock().unwrap();
@ -381,6 +391,19 @@ impl Queue {
Ok(())
}
}
/// Waits until all work on this queue has finished.
///
/// Just like `Device::wait()`, you shouldn't have to call this function.
///
/// # Panic
///
/// - Panicks if the device or host ran out of memory.
///
#[inline]
pub fn wait(&self) {
self.wait_raw().unwrap();
}
// TODO: the design of this functions depends on https://github.com/KhronosGroup/Vulkan-Docs/issues/155
/*// TODO: document

View File

@ -38,8 +38,8 @@ pub struct EmptySinglePassRenderPass {
}
impl EmptySinglePassRenderPass {
/// Builds the render pass.
pub fn new(device: &Arc<Device>) -> Result<Arc<EmptySinglePassRenderPass>, OomError> {
/// See the docs of new().
pub fn raw(device: &Arc<Device>) -> Result<EmptySinglePassRenderPass, OomError> {
let rp = try!(unsafe {
let pass = LayoutPassDescription {
color_attachments: vec![],
@ -49,12 +49,23 @@ impl EmptySinglePassRenderPass {
preserve_attachments: vec![],
};
UnsafeRenderPass::new(device, iter::empty(), Some(pass).into_iter(), iter::empty())
UnsafeRenderPass::raw(device, iter::empty(), Some(pass).into_iter(), iter::empty())
});
Ok(Arc::new(EmptySinglePassRenderPass {
Ok(EmptySinglePassRenderPass {
render_pass: rp
}))
})
}
/// Builds the render pass.
///
/// # Panic
///
/// - Panicks if the device or host ran out of memory.
///
#[inline]
pub fn new(device: &Arc<Device>) -> Arc<EmptySinglePassRenderPass> {
Arc::new(EmptySinglePassRenderPass::raw(device).unwrap())
}
}
@ -148,6 +159,6 @@ mod tests {
#[ignore] // TODO: crashes on AMD+Windows
fn create() {
let (device, _) = gfx_dev_and_queue!();
let _ = EmptySinglePassRenderPass::new(&device).unwrap();
let _ = EmptySinglePassRenderPass::new(&device);
}
}

View File

@ -290,7 +290,7 @@ mod tests {
let render_pass = example::CustomRenderPass::new(&device, &example::Formats {
color: (R8G8B8A8Unorm, 1)
}).unwrap();
});
let image = AttachmentImage::new(&device, [1024, 768], R8G8B8A8Unorm).unwrap();
let _ = Framebuffer::new(&render_pass, (1024, 768, 1), example::AList {
@ -304,7 +304,7 @@ mod tests {
let render_pass = example::CustomRenderPass::new(&device, &example::Formats {
color: (R8G8B8A8Unorm, 1)
}).unwrap();
});
let image = AttachmentImage::new(&device, [1024, 768], R8G8B8A8Unorm).unwrap();
let alist = example::AList { color: &image };
@ -320,7 +320,7 @@ mod tests {
let render_pass = example::CustomRenderPass::new(&device, &example::Formats {
color: (R8G8B8A8Unorm, 1)
}).unwrap();
});
let image = AttachmentImage::new(&device, [512, 512], R8G8B8A8Unorm).unwrap();
let alist = example::AList { color: &image };

View File

@ -84,19 +84,26 @@ macro_rules! ordered_passes_renderpass {
}
impl CustomRenderPass {
pub fn new(device: &Arc<Device>, formats: &Formats)
-> Result<Arc<CustomRenderPass>, OomError>
pub fn raw(device: &Arc<Device>, formats: &Formats)
-> Result<CustomRenderPass, OomError>
{
#![allow(unsafe_code)]
let rp = try!(unsafe {
UnsafeRenderPass::new(device, attachments(formats), passes(), dependencies())
UnsafeRenderPass::raw(device, attachments(formats), passes(), dependencies())
});
Ok(Arc::new(CustomRenderPass {
Ok(CustomRenderPass {
render_pass: rp,
formats: formats.clone(),
}))
})
}
#[inline]
pub fn new(device: &Arc<Device>, formats: &Formats)
-> Arc<CustomRenderPass>
{
Arc::new(CustomRenderPass::raw(device, formats).unwrap())
}
}

View File

@ -34,25 +34,8 @@ pub struct UnsafeRenderPass {
}
impl UnsafeRenderPass {
/// Builds a new renderpass.
///
/// This function calls the methods of the `Layout` implementation and builds the
/// corresponding Vulkan object.
///
/// # Safety
///
/// This function doesn't check whether all the restrictions in the attachments, passes and
/// passes dependencies were enforced.
///
/// See the documentation of the structs of this module for more info about these restrictions.
///
/// # Panic
///
/// Can panick if it detects some violations in the restrictions. Only unexpensive checks are
/// performed. `debug_assert!` is used, so some restrictions are only checked in debug
/// mode.
///
pub unsafe fn new<Ia, Ip, Id>(device: &Arc<Device>, attachments: Ia, passes: Ip,
/// See the docs of new().
pub unsafe fn raw<Ia, Ip, Id>(device: &Arc<Device>, attachments: Ia, passes: Ip,
pass_dependencies: Id)
-> Result<UnsafeRenderPass, OomError>
where Ia: ExactSizeIterator<Item = LayoutAttachmentDescription> + Clone, // with specialization we can handle the "Clone" restriction internally
@ -243,6 +226,36 @@ impl UnsafeRenderPass {
renderpass: renderpass,
})
}
/// Builds a new renderpass.
///
/// This function calls the methods of the `Layout` implementation and builds the
/// corresponding Vulkan object.
///
/// # Safety
///
/// This function doesn't check whether all the restrictions in the attachments, passes and
/// passes dependencies were enforced.
///
/// See the documentation of the structs of this module for more info about these restrictions.
///
/// # Panic
///
/// - Can panick if it detects some violations in the restrictions. Only unexpensive checks are
/// performed. `debug_assert!` is used, so some restrictions are only checked in debug
/// mode.
///
/// - Panicks if the device or host ran out of memory.
///
pub unsafe fn new<Ia, Ip, Id>(device: &Arc<Device>, attachments: Ia, passes: Ip,
pass_dependencies: Id)
-> UnsafeRenderPass
where Ia: ExactSizeIterator<Item = LayoutAttachmentDescription> + Clone, // with specialization we can handle the "Clone" restriction internally
Ip: ExactSizeIterator<Item = LayoutPassDescription> + Clone, // with specialization we can handle the "Clone" restriction internally
Id: ExactSizeIterator<Item = LayoutPassDependencyDescription>
{
UnsafeRenderPass::raw(device, attachments, passes, pass_dependencies).unwrap()
}
/// Returns the device that was used to create this render pass.
#[inline]

View File

@ -169,7 +169,7 @@ impl<F> AttachmentImage<F> {
unsafe { try!(image.bind_memory(mem.memory(), mem.offset())); }
let view = unsafe {
try!(UnsafeImageView::new(&image, 0 .. 1, 0 .. 1))
try!(UnsafeImageView::raw(&image, 0 .. 1, 0 .. 1))
};
Ok(Arc::new(AttachmentImage {

View File

@ -84,7 +84,7 @@ impl<F> ImmutableImage<F> {
unsafe { try!(image.bind_memory(mem.memory(), mem.offset())); }
let view = unsafe {
try!(UnsafeImageView::new(&image, 0 .. image.mipmap_levels(),
try!(UnsafeImageView::raw(&image, 0 .. image.mipmap_levels(),
0 .. image.dimensions().array_layers()))
};

View File

@ -49,7 +49,7 @@ impl SwapchainImage {
pub unsafe fn from_raw(image: UnsafeImage, format: Format, swapchain: &Arc<Swapchain>, id: u32)
-> Result<Arc<SwapchainImage>, OomError>
{
let view = try!(UnsafeImageView::new(&image, 0 .. 1, 0 .. 1));
let view = try!(UnsafeImageView::raw(&image, 0 .. 1, 0 .. 1));
Ok(Arc::new(SwapchainImage {
image: image,
@ -124,7 +124,8 @@ unsafe impl Image for SwapchainImage {
let dependency = mem::replace(&mut guarded.latest_submission, Some(Arc::downgrade(submission)));
let dependency = dependency.and_then(|d| d.upgrade());
let signal = Semaphore::new(submission.queue().device()).unwrap();
// TODO: use try!()? - Mixthos
let signal = Semaphore::new(submission.queue().device());
let wait = self.swapchain.image_semaphore(self.id, signal.clone()).expect("Try to render to a swapchain image that was not acquired first");
if guarded.present_layout {

View File

@ -459,7 +459,7 @@ impl UnsafeImage {
}
pub unsafe fn bind_memory(&self, memory: &DeviceMemory, offset: usize)
-> Result<(), OomError>
-> Result<(), OomError>
{
let vk = self.device.pointers();
@ -619,11 +619,8 @@ pub struct UnsafeImageView {
}
impl UnsafeImageView {
/// Creates a new view from an image.
///
/// Note that you must create the view with identity swizzling if you want to use this view
/// as a framebuffer attachment.
pub unsafe fn new(image: &UnsafeImage, mipmap_levels: Range<u32>, array_layers: Range<u32>)
/// See the docs of new().
pub unsafe fn raw(image: &UnsafeImage, mipmap_levels: Range<u32>, array_layers: Range<u32>)
-> Result<UnsafeImageView, OomError>
{
let vk = image.device.pointers();
@ -674,6 +671,21 @@ impl UnsafeImageView {
format: image.format,
})
}
/// Creates a new view from an image.
///
/// Note that you must create the view with identity swizzling if you want to use this view
/// as a framebuffer attachment.
///
/// # Panic
///
/// - Panicks if the device or host ran out of memory.
#[inline]
pub unsafe fn new(image: &UnsafeImage, mipmap_levels: Range<u32>, array_layers: Range<u32>)
-> UnsafeImageView
{
UnsafeImageView::raw(image, mipmap_levels, array_layers).unwrap()
}
#[inline]
pub fn format(&self) -> Format {

View File

@ -32,9 +32,9 @@ pub struct OcclusionQueriesPool {
}
impl OcclusionQueriesPool {
/// Builds a new query pool.
pub fn new(device: &Arc<Device>, num_slots: u32)
-> Result<Arc<OcclusionQueriesPool>, OomError>
/// See the docs of new().
pub fn raw(device: &Arc<Device>, num_slots: u32)
-> Result<OcclusionQueriesPool, OomError>
{
let vk = device.pointers();
@ -54,11 +54,24 @@ impl OcclusionQueriesPool {
output
};
Ok(Arc::new(OcclusionQueriesPool {
Ok(OcclusionQueriesPool {
pool: pool,
num_slots: num_slots,
device: device.clone(),
}))
})
}
/// Builds a new query pool.
///
/// # Panic
///
/// - Panicks if the device or host ran out of memory.
///
#[inline]
pub fn new(device: &Arc<Device>, num_slots: u32)
-> Arc<OcclusionQueriesPool>
{
Arc::new(OcclusionQueriesPool::raw(device, num_slots).unwrap())
}
/// Returns the number of slots of that query pool.
@ -90,6 +103,6 @@ mod tests {
#[test]
fn occlusion_create() {
let (device, _) = gfx_dev_and_queue!();
let _ = OcclusionQueriesPool::new(&device, 256).unwrap();
let _ = OcclusionQueriesPool::new(&device, 256);
}
}

View File

@ -39,8 +39,8 @@ pub struct DisplayPlane {
}
impl DisplayPlane {
/// Enumerates all the display planes that are available on a given physical device.
pub fn enumerate(device: &PhysicalDevice) -> Result<IntoIter<DisplayPlane>, OomError> {
/// See the docs of enumerate().
pub fn enumerate_raw(device: &PhysicalDevice) -> Result<IntoIter<DisplayPlane>, OomError> {
let vk = device.instance().pointers();
assert!(device.instance().loaded_extensions().khr_display); // TODO: return error instead
@ -89,6 +89,18 @@ impl DisplayPlane {
}
}).collect::<Vec<_>>().into_iter())
}
/// Enumerates all the display planes that are available on a given physical device.
///
/// # Panic
///
/// - Panicks if the device or host ran out of memory.
///
// TODO: move iterator creation here from raw constructor?
#[inline]
pub fn enumerate(device: &PhysicalDevice) -> IntoIter<DisplayPlane> {
DisplayPlane::enumerate_raw(device).unwrap()
}
/// Returns the physical device that was used to create this display.
#[inline]
@ -117,8 +129,8 @@ pub struct Display {
}
impl Display {
/// Enumerates all the displays that are available on a given physical device.
pub fn enumerate(device: &PhysicalDevice) -> Result<IntoIter<Display>, OomError> {
/// See the docs of enumerate().
pub fn enumerate_raw(device: &PhysicalDevice) -> Result<IntoIter<Display>, OomError> {
let vk = device.instance().pointers();
assert!(device.instance().loaded_extensions().khr_display); // TODO: return error instead
@ -147,6 +159,18 @@ impl Display {
}
}).collect::<Vec<_>>().into_iter())
}
/// Enumerates all the displays that are available on a given physical device.
///
/// # Panic
///
/// - Panicks if the device or host ran out of memory.
///
// TODO: move iterator creation here from raw constructor?
#[inline]
pub fn enumerate(device: &PhysicalDevice) -> IntoIter<Display> {
Display::enumerate_raw(device).unwrap()
}
/// Returns the name of the display.
#[inline]
@ -170,8 +194,8 @@ impl Display {
[r.width, r.height]
}
/// Returns a list of all modes available on this display.
pub fn display_modes(&self) -> Result<IntoIter<DisplayMode>, OomError> {
/// See the docs of display_modes().
pub fn display_modes_raw(&self) -> Result<IntoIter<DisplayMode>, OomError> {
let vk = self.instance.pointers();
let num = unsafe {
@ -200,6 +224,18 @@ impl Display {
}
}).collect::<Vec<_>>().into_iter())
}
/// Returns a list of all modes available on this display.
///
/// # Panic
///
/// - Panicks if the device or host ran out of memory.
///
// TODO: move iterator creation here from display_modes_raw?
#[inline]
pub fn display_modes(&self) -> IntoIter<DisplayMode> {
self.display_modes_raw().unwrap()
}
}
unsafe impl VulkanObject for Display {

View File

@ -212,7 +212,9 @@ impl Swapchain {
}
for _ in 0 .. images.len() + 1 {
swapchain.semaphores_pool.push(try!(Semaphore::new(device)));
// TODO: check if this change is okay (maybe the Arc can be omitted?) - Mixthos
//swapchain.semaphores_pool.push(try!(Semaphore::new(device)));
swapchain.semaphores_pool.push(Arc::new(try!(Semaphore::raw(device))));
}
Ok((swapchain, images))

View File

@ -35,9 +35,9 @@ pub struct Event {
}
impl Event {
/// Builds a new event.
/// See the docs of new().
#[inline]
pub fn new(device: &Arc<Device>) -> Result<Arc<Event>, OomError> {
pub fn raw(device: &Arc<Device>) -> Result<Event, OomError> {
let vk = device.pointers();
let event = unsafe {
@ -54,10 +54,21 @@ impl Event {
output
};
Ok(Arc::new(Event {
Ok(Event {
device: device.clone(),
event: Mutex::new(event),
}))
})
}
/// Builds a new event.
///
/// # Panic
///
/// - Panicks if the device or host ran out of memory.
///
#[inline]
pub fn new(device: &Arc<Device>) -> Arc<Event> {
Arc::new(Event::raw(device).unwrap())
}
/// Returns true if the event is signaled.
@ -76,11 +87,9 @@ impl Event {
}
}
/// Changes the `Event` to the signaled state.
///
/// If a command buffer is waiting on this event, it is then unblocked.
/// See the docs of set().
#[inline]
pub fn set(&self) -> Result<(), OomError> {
pub fn set_raw(&self) -> Result<(), OomError> {
unsafe {
let vk = self.device.pointers();
let event = self.event.lock().unwrap();
@ -89,9 +98,22 @@ impl Event {
}
}
/// Changes the `Event` to the unsignaled state.
/// Changes the `Event` to the signaled state.
///
/// If a command buffer is waiting on this event, it is then unblocked.
///
/// # Panic
///
/// - Panicks if the device or host ran out of memory.
///
#[inline]
pub fn reset(&self) -> Result<(), OomError> {
pub fn set(&self) {
self.set_raw().unwrap();
}
/// See the docs of reset().
#[inline]
pub fn reset_raw(&self) -> Result<(), OomError> {
unsafe {
let vk = self.device.pointers();
let event = self.event.lock().unwrap();
@ -99,6 +121,17 @@ impl Event {
Ok(())
}
}
/// Changes the `Event` to the unsignaled state.
///
/// # Panic
///
/// - Panicks if the device or host ran out of memory.
///
#[inline]
pub fn reset(&self) {
self.reset_raw().unwrap();
}
}
unsafe impl SynchronizedVulkanObject for Event {
@ -128,17 +161,17 @@ mod tests {
#[test]
fn event_create() {
let (device, _) = gfx_dev_and_queue!();
let event = Event::new(&device).unwrap();
let event = Event::new(&device);
assert!(!event.signaled().unwrap());
}
#[test]
fn event_set() {
let (device, _) = gfx_dev_and_queue!();
let event = Event::new(&device).unwrap();
let event = Event::new(&device);
assert!(!event.signaled().unwrap());
event.set().unwrap();
event.set();
assert!(event.signaled().unwrap());
}
@ -146,11 +179,11 @@ mod tests {
fn event_reset() {
let (device, _) = gfx_dev_and_queue!();
let event = Event::new(&device).unwrap();
event.set().unwrap();
let event = Event::new(&device);
event.set();
assert!(event.signaled().unwrap());
event.reset().unwrap();
event.reset();
assert!(!event.signaled().unwrap());
}
}

View File

@ -46,23 +46,49 @@ pub struct Fence<D = Arc<Device>> where D: Deref<Target = Device> {
}
impl<D> Fence<D> where D: Deref<Target = Device> {
/// Builds a new fence.
/// See the docs of new().
#[inline]
pub fn new(device: &D) -> Result<Arc<Fence<D>>, OomError>
pub fn raw(device: &D) -> Result<Fence<D>, OomError>
where D: Clone
{
Fence::new_impl(device, false)
}
/// Builds a new fence already in the "signaled" state.
/// Builds a new fence.
///
/// # Panic
///
/// - Panicks if the device or host ran out of memory.
///
#[inline]
pub fn signaled(device: &D) -> Result<Arc<Fence<D>>, OomError>
pub fn new(device: &D) -> Arc<Fence<D>>
where D: Clone
{
Arc::new(Fence::raw(device).unwrap())
}
/// See the docs of signaled().
#[inline]
pub fn signaled_raw(device: &D) -> Result<Fence<D>, OomError>
where D: Clone
{
Fence::new_impl(device, true)
}
fn new_impl(device_ptr: &D, signaled: bool) -> Result<Arc<Fence<D>>, OomError>
/// Builds a new fence already in the "signaled" state.
///
/// # Panic
///
/// - Panicks if the device or host ran out of memory.
///
#[inline]
pub fn signaled(device: &D) -> Arc<Fence<D>>
where D: Clone
{
Arc::new(Fence::signaled_raw(device).unwrap())
}
fn new_impl(device_ptr: &D, signaled: bool) -> Result<Fence<D>, OomError>
where D: Clone
{
let device: &Device = &*device_ptr;
@ -81,12 +107,12 @@ impl<D> Fence<D> where D: Deref<Target = Device> {
output
};
Ok(Arc::new(Fence {
Ok(Fence {
fence: fence,
device: device_ptr.clone(),
device_raw: device.internal_object(),
signaled: AtomicBool::new(signaled),
}))
})
}
/// Returns true if the fence is signaled.
@ -315,7 +341,7 @@ mod tests {
fn fence_create() {
let (device, _) = gfx_dev_and_queue!();
let fence = Fence::new(&device).unwrap();
let fence = Fence::new(&device);
assert!(!fence.ready().unwrap());
}
@ -323,7 +349,7 @@ mod tests {
fn fence_create_signaled() {
let (device, _) = gfx_dev_and_queue!();
let fence = Fence::signaled(&device).unwrap();
let fence = Fence::signaled(&device);
assert!(fence.ready().unwrap());
}
@ -331,7 +357,7 @@ mod tests {
fn fence_signaled_wait() {
let (device, _) = gfx_dev_and_queue!();
let fence = Fence::signaled(&device).unwrap();
let fence = Fence::signaled(&device);
fence.wait(Duration::new(0, 10)).unwrap();
}
@ -340,7 +366,7 @@ mod tests {
fn fence_reset() {
let (device, _) = gfx_dev_and_queue!();
let fence = Fence::signaled(&device).unwrap();
let fence = Fence::signaled(&device);
fence.reset();
assert!(!fence.ready().unwrap());
}
@ -351,8 +377,8 @@ mod tests {
let (device1, _) = gfx_dev_and_queue!();
let (device2, _) = gfx_dev_and_queue!();
let fence1 = Fence::signaled(&device1).unwrap();
let fence2 = Fence::signaled(&device2).unwrap();
let fence1 = Fence::signaled(&device1);
let fence2 = Fence::signaled(&device2);
let _ = Fence::multi_wait([&*fence1, &*fence2].iter().cloned(), Duration::new(0, 10));
}
@ -363,8 +389,8 @@ mod tests {
let (device1, _) = gfx_dev_and_queue!();
let (device2, _) = gfx_dev_and_queue!();
let fence1 = Fence::signaled(&device1).unwrap();
let fence2 = Fence::signaled(&device2).unwrap();
let fence1 = Fence::signaled(&device1);
let fence2 = Fence::signaled(&device2);
let _ = Fence::multi_reset([&*fence1, &*fence2].iter().cloned());
}

View File

@ -29,9 +29,9 @@ pub struct Semaphore {
}
impl Semaphore {
/// Builds a new semaphore.
/// See the docs of new().
#[inline]
pub fn new(device: &Arc<Device>) -> Result<Arc<Semaphore>, OomError> {
pub fn raw(device: &Arc<Device>) -> Result<Semaphore, OomError> {
let vk = device.pointers();
let semaphore = unsafe {
@ -48,10 +48,21 @@ impl Semaphore {
output
};
Ok(Arc::new(Semaphore {
Ok(Semaphore {
device: device.clone(),
semaphore: semaphore,
}))
})
}
/// Builds a new semaphore.
///
/// # Panic
///
/// - Panicks if the device or host ran out of memory.
///
#[inline]
pub fn new(device: &Arc<Device>) -> Arc<Semaphore> {
Arc::new(Semaphore::raw(device).unwrap())
}
}
@ -81,6 +92,6 @@ mod tests {
#[test]
fn semaphore_create() {
let (device, _) = gfx_dev_and_queue!();
let _ = Semaphore::new(&device).unwrap();
let _ = Semaphore::new(&device);
}
}