Merge pull request #593 from tomaka/clear-color-image

Add AutoCommandBufferBuilder::clear_color_image
This commit is contained in:
tomaka 2017-07-05 18:26:40 +02:00 committed by GitHub
commit 84caa04414
5 changed files with 283 additions and 0 deletions

View File

@ -33,6 +33,7 @@ use command_buffer::sys::Flags;
use command_buffer::sys::Kind; use command_buffer::sys::Kind;
use command_buffer::sys::UnsafeCommandBuffer; use command_buffer::sys::UnsafeCommandBuffer;
use command_buffer::sys::UnsafeCommandBufferBuilderBufferImageCopy; use command_buffer::sys::UnsafeCommandBufferBuilderBufferImageCopy;
use command_buffer::sys::UnsafeCommandBufferBuilderColorImageClear;
use command_buffer::sys::UnsafeCommandBufferBuilderImageAspect; use command_buffer::sys::UnsafeCommandBufferBuilderImageAspect;
use command_buffer::validity::*; use command_buffer::validity::*;
use descriptor::descriptor_set::DescriptorSetsCollection; use descriptor::descriptor_set::DescriptorSetsCollection;
@ -40,6 +41,7 @@ use descriptor::pipeline_layout::PipelineLayoutAbstract;
use device::Device; use device::Device;
use device::DeviceOwned; use device::DeviceOwned;
use device::Queue; use device::Queue;
use format::ClearValue;
use framebuffer::FramebufferAbstract; use framebuffer::FramebufferAbstract;
use framebuffer::RenderPassDescClearValues; use framebuffer::RenderPassDescClearValues;
use framebuffer::SubpassContents; use framebuffer::SubpassContents;
@ -169,6 +171,58 @@ impl<P> AutoCommandBufferBuilder<P> {
} }
} }
/// Adds a command that clears all the layers and mipmap levels of a color image with a
/// specific value.
///
/// # Panic
///
/// Panics if `color` is not a color value.
///
pub fn clear_color_image<I>(self, image: I, color: ClearValue)
-> Result<Self, ClearColorImageError>
where I: ImageAccess + Send + Sync + 'static,
{
let layers = image.dimensions().array_layers();
let levels = image.mipmap_levels();
self.clear_color_image_dimensions(image, 0, layers, 0, levels, color)
}
/// Adds a command that clears a color image with a specific value.
///
/// # Panic
///
/// - Panics if `color` is not a color value.
///
pub fn clear_color_image_dimensions<I>(mut self, image: I, first_layer: u32, num_layers: u32,
first_mipmap: u32, num_mipmaps: u32, color: ClearValue)
-> Result<Self, ClearColorImageError>
where I: ImageAccess + Send + Sync + 'static,
{
unsafe {
self.ensure_outside_render_pass()?;
check_clear_color_image(self.device(), &image, first_layer, num_layers,
first_mipmap, num_mipmaps)?;
match color {
ClearValue::Float(_) | ClearValue::Int(_) | ClearValue::Uint(_) => {},
_ => panic!("The clear color is not a color value"),
};
let region = UnsafeCommandBufferBuilderColorImageClear {
base_mip_level: first_mipmap,
level_count: num_mipmaps,
base_array_layer: first_layer,
layer_count: num_layers,
};
// TODO: let choose layout
self.inner.clear_color_image(image, ImageLayout::TransferDstOptimal, color,
iter::once(region))?;
Ok(self)
}
}
/// Adds a command that copies from a buffer to another. /// Adds a command that copies from a buffer to another.
/// ///
/// This command will copy from the source to the destination. If their size is not equal, then /// This command will copy from the source to the destination. If their size is not equal, then
@ -664,6 +718,12 @@ err_gen!(BeginRenderPassError {
SyncCommandBufferBuilderError SyncCommandBufferBuilderError
}); });
err_gen!(ClearColorImageError {
AutoCommandBufferBuilderContextError,
CheckClearColorImageError,
SyncCommandBufferBuilderError
});
err_gen!(CopyBufferError { err_gen!(CopyBufferError {
AutoCommandBufferBuilderContextError, AutoCommandBufferBuilderContextError,
CheckCopyBufferError, CheckCopyBufferError,

View File

@ -31,6 +31,7 @@ use command_buffer::sys::UnsafeCommandBuffer;
use command_buffer::sys::UnsafeCommandBufferBuilder; use command_buffer::sys::UnsafeCommandBufferBuilder;
use command_buffer::sys::UnsafeCommandBufferBuilderBindVertexBuffer; use command_buffer::sys::UnsafeCommandBufferBuilderBindVertexBuffer;
use command_buffer::sys::UnsafeCommandBufferBuilderBufferImageCopy; use command_buffer::sys::UnsafeCommandBufferBuilderBufferImageCopy;
use command_buffer::sys::UnsafeCommandBufferBuilderColorImageClear;
use command_buffer::sys::UnsafeCommandBufferBuilderPipelineBarrier; use command_buffer::sys::UnsafeCommandBufferBuilderPipelineBarrier;
use descriptor::descriptor::ShaderStages; use descriptor::descriptor::ShaderStages;
use descriptor::descriptor_set::DescriptorSet; use descriptor::descriptor_set::DescriptorSet;
@ -801,6 +802,75 @@ impl<P> SyncCommandBufferBuilder<P> {
} }
} }
/// Calls `vkCmdClearColorImage` on the builder.
///
/// Does nothing if the list of regions is empty, as it would be a no-op and isn't a valid
/// usage of the command anyway.
pub unsafe fn clear_color_image<I, R>(&mut self, image: I, layout: ImageLayout,
color: ClearValue, regions: R)
-> Result<(), SyncCommandBufferBuilderError>
where I: ImageAccess + Send + Sync + 'static,
R: Iterator<Item = UnsafeCommandBufferBuilderColorImageClear> + Send + Sync + 'static
{
struct Cmd<I, R> {
image: Option<I>,
layout: ImageLayout,
color: ClearValue,
regions: Option<R>,
}
impl<P, I, R> Command<P> for Cmd<I, R>
where I: ImageAccess + Send + Sync + 'static,
R: Iterator<Item = UnsafeCommandBufferBuilderColorImageClear> + Send + Sync + 'static
{
unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder<P>) {
out.clear_color_image(self.image.as_ref().unwrap(), self.layout, self.color,
self.regions.take().unwrap());
}
fn into_final_command(mut self: Box<Self>) -> Box<FinalCommand + Send + Sync> {
struct Fin<I>(I);
impl<I> FinalCommand for Fin<I>
where I: ImageAccess + Send + Sync + 'static,
{
fn image(&self, num: usize) -> &ImageAccess {
assert_eq!(num, 0);
&self.0
}
}
// Note: borrow checker somehow doesn't accept `self.image` without using an Option.
Box::new(Fin(self.image.take().unwrap()))
}
fn image(&self, num: usize) -> &ImageAccess {
assert_eq!(num, 0);
self.image.as_ref().unwrap()
}
}
self.commands.lock().unwrap().commands.push(Box::new(Cmd {
image: Some(image),
layout,
color,
regions: Some(regions),
}));
self.prev_cmd_resource(KeyTy::Image,
0,
true,
PipelineStages {
transfer: true,
..PipelineStages::none()
},
AccessFlagBits {
transfer_write: true,
..AccessFlagBits::none()
},
layout,
layout)?;
Ok(())
}
/// Calls `vkCmdCopyBuffer` on the builder. /// Calls `vkCmdCopyBuffer` on the builder.
/// ///
/// Does nothing if the list of regions is empty, as it would be a no-op and isn't a valid /// Does nothing if the list of regions is empty, as it would be a no-op and isn't a valid

View File

@ -30,6 +30,7 @@ use descriptor::pipeline_layout::PipelineLayoutAbstract;
use device::Device; use device::Device;
use device::DeviceOwned; use device::DeviceOwned;
use format::ClearValue; use format::ClearValue;
use format::FormatTy;
use framebuffer::EmptySinglePassRenderPassDesc; use framebuffer::EmptySinglePassRenderPassDesc;
use framebuffer::Framebuffer; use framebuffer::Framebuffer;
use framebuffer::FramebufferAbstract; use framebuffer::FramebufferAbstract;
@ -507,6 +508,73 @@ impl<P> UnsafeCommandBufferBuilder<P> {
rects.len() as u32, rects.as_ptr()); rects.len() as u32, rects.as_ptr());
}*/ }*/
/// Calls `vkCmdClearColorImage` on the builder.
///
/// Does nothing if the list of regions is empty, as it would be a no-op and isn't a valid
/// usage of the command anyway.
// TODO: ClearValue could be more precise
pub unsafe fn clear_color_image<I, R>(&mut self, image: &I, layout: ImageLayout,
color: ClearValue, regions: R)
where I: ?Sized + ImageAccess,
R: Iterator<Item = UnsafeCommandBufferBuilderColorImageClear>
{
debug_assert!(image.format().ty() == FormatTy::Float ||
image.format().ty() == FormatTy::Uint ||
image.format().ty() == FormatTy::Sint);
let image = image.inner();
debug_assert!(image.image.usage_transfer_destination());
debug_assert!(layout == ImageLayout::General ||
layout == ImageLayout::TransferDstOptimal);
let color = match color {
ClearValue::Float(val) => {
vk::ClearColorValue::float32(val)
},
ClearValue::Int(val) => {
vk::ClearColorValue::int32(val)
},
ClearValue::Uint(val) => {
vk::ClearColorValue::uint32(val)
},
_ => {
vk::ClearColorValue::float32([0.0; 4])
},
};
let regions: SmallVec<[_; 8]> = regions
.filter_map(|region| {
debug_assert!(region.layer_count + region.base_array_layer <= image.num_layers as u32);
debug_assert!(region.level_count + region.base_mip_level <= image.num_mipmap_levels as u32);
if region.layer_count == 0 || region.level_count == 0 {
return None;
}
Some(vk::ImageSubresourceRange {
aspectMask: vk::IMAGE_ASPECT_COLOR_BIT,
baseMipLevel: region.base_mip_level + image.first_mipmap_level as u32,
levelCount: region.level_count,
baseArrayLayer: region.base_array_layer + image.first_layer as u32,
layerCount: region.layer_count,
})
})
.collect();
if regions.is_empty() {
return;
}
let vk = self.device().pointers();
let cmd = self.internal_object();
vk.CmdClearColorImage(cmd,
image.image.internal_object(),
layout as u32,
&color,
regions.len() as u32,
regions.as_ptr());
}
/// Calls `vkCmdCopyBuffer` on the builder. /// Calls `vkCmdCopyBuffer` on the builder.
/// ///
/// Does nothing if the list of regions is empty, as it would be a no-op and isn't a valid /// Does nothing if the list of regions is empty, as it would be a no-op and isn't a valid
@ -1098,6 +1166,15 @@ impl UnsafeCommandBufferBuilderImageAspect {
} }
} }
// TODO: move somewhere else?
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct UnsafeCommandBufferBuilderColorImageClear {
pub base_mip_level: u32,
pub level_count: u32,
pub base_array_layer: u32,
pub layer_count: u32,
}
// TODO: move somewhere else? // TODO: move somewhere else?
#[derive(Debug, Copy, Clone, PartialEq, Eq)] #[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct UnsafeCommandBufferBuilderBufferImageCopy { pub struct UnsafeCommandBufferBuilderBufferImageCopy {

View File

@ -0,0 +1,74 @@
// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.
use std::error;
use std::fmt;
use VulkanObject;
use device::Device;
use image::ImageAccess;
/// Checks whether a clear color image command is valid.
///
/// # Panic
///
/// - Panics if the destination was not created with `device`.
///
pub fn check_clear_color_image<I>(device: &Device, image: &I, first_layer: u32, num_layers: u32,
first_mipmap: u32, num_mipmaps: u32)
-> Result<(), CheckClearColorImageError>
where I: ?Sized + ImageAccess,
{
assert_eq!(image.inner().image.device().internal_object(),
device.internal_object());
if !image.inner().image.usage_transfer_destination() {
return Err(CheckClearColorImageError::MissingTransferUsage);
}
if first_layer + num_layers > image.dimensions().array_layers() {
return Err(CheckClearColorImageError::OutOfRange);
}
if first_mipmap + num_mipmaps > image.mipmap_levels() {
return Err(CheckClearColorImageError::OutOfRange);
}
Ok(())
}
/// Error that can happen from `check_clear_color_image`.
#[derive(Debug, Copy, Clone)]
pub enum CheckClearColorImageError {
/// The image is missing the transfer destination usage.
MissingTransferUsage,
/// The array layers and mipmap levels are out of range.
OutOfRange,
}
impl error::Error for CheckClearColorImageError {
#[inline]
fn description(&self) -> &str {
match *self {
CheckClearColorImageError::MissingTransferUsage => {
"the image is missing the transfer destination usage"
},
CheckClearColorImageError::OutOfRange => {
"the array layers and mipmap levels are out of range"
},
}
}
}
impl fmt::Display for CheckClearColorImageError {
#[inline]
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(fmt, "{}", error::Error::description(self))
}
}

View File

@ -9,6 +9,7 @@
//! Functions that check the validity of commands. //! Functions that check the validity of commands.
pub use self::clear_color_image::{check_clear_color_image, CheckClearColorImageError};
pub use self::copy_buffer::{CheckCopyBufferError, check_copy_buffer, CheckCopyBuffer}; pub use self::copy_buffer::{CheckCopyBufferError, check_copy_buffer, CheckCopyBuffer};
pub use self::descriptor_sets::{check_descriptor_sets_validity, CheckDescriptorSetsValidityError}; pub use self::descriptor_sets::{check_descriptor_sets_validity, CheckDescriptorSetsValidityError};
pub use self::dispatch::{check_dispatch, CheckDispatchError}; pub use self::dispatch::{check_dispatch, CheckDispatchError};
@ -19,6 +20,7 @@ pub use self::push_constants::{check_push_constants_validity, CheckPushConstants
pub use self::update_buffer::{CheckUpdateBufferError, check_update_buffer}; pub use self::update_buffer::{CheckUpdateBufferError, check_update_buffer};
pub use self::vertex_buffers::{check_vertex_buffers, CheckVertexBuffer, CheckVertexBufferError}; pub use self::vertex_buffers::{check_vertex_buffers, CheckVertexBuffer, CheckVertexBufferError};
mod clear_color_image;
mod copy_buffer; mod copy_buffer;
mod descriptor_sets; mod descriptor_sets;
mod dispatch; mod dispatch;