mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-22 14:56:42 +00:00
Merge pull request #593 from tomaka/clear-color-image
Add AutoCommandBufferBuilder::clear_color_image
This commit is contained in:
commit
84caa04414
@ -33,6 +33,7 @@ use command_buffer::sys::Flags;
|
||||
use command_buffer::sys::Kind;
|
||||
use command_buffer::sys::UnsafeCommandBuffer;
|
||||
use command_buffer::sys::UnsafeCommandBufferBuilderBufferImageCopy;
|
||||
use command_buffer::sys::UnsafeCommandBufferBuilderColorImageClear;
|
||||
use command_buffer::sys::UnsafeCommandBufferBuilderImageAspect;
|
||||
use command_buffer::validity::*;
|
||||
use descriptor::descriptor_set::DescriptorSetsCollection;
|
||||
@ -40,6 +41,7 @@ use descriptor::pipeline_layout::PipelineLayoutAbstract;
|
||||
use device::Device;
|
||||
use device::DeviceOwned;
|
||||
use device::Queue;
|
||||
use format::ClearValue;
|
||||
use framebuffer::FramebufferAbstract;
|
||||
use framebuffer::RenderPassDescClearValues;
|
||||
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.
|
||||
///
|
||||
/// 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
|
||||
});
|
||||
|
||||
err_gen!(ClearColorImageError {
|
||||
AutoCommandBufferBuilderContextError,
|
||||
CheckClearColorImageError,
|
||||
SyncCommandBufferBuilderError
|
||||
});
|
||||
|
||||
err_gen!(CopyBufferError {
|
||||
AutoCommandBufferBuilderContextError,
|
||||
CheckCopyBufferError,
|
||||
|
@ -31,6 +31,7 @@ use command_buffer::sys::UnsafeCommandBuffer;
|
||||
use command_buffer::sys::UnsafeCommandBufferBuilder;
|
||||
use command_buffer::sys::UnsafeCommandBufferBuilderBindVertexBuffer;
|
||||
use command_buffer::sys::UnsafeCommandBufferBuilderBufferImageCopy;
|
||||
use command_buffer::sys::UnsafeCommandBufferBuilderColorImageClear;
|
||||
use command_buffer::sys::UnsafeCommandBufferBuilderPipelineBarrier;
|
||||
use descriptor::descriptor::ShaderStages;
|
||||
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.
|
||||
///
|
||||
/// Does nothing if the list of regions is empty, as it would be a no-op and isn't a valid
|
||||
|
@ -30,6 +30,7 @@ use descriptor::pipeline_layout::PipelineLayoutAbstract;
|
||||
use device::Device;
|
||||
use device::DeviceOwned;
|
||||
use format::ClearValue;
|
||||
use format::FormatTy;
|
||||
use framebuffer::EmptySinglePassRenderPassDesc;
|
||||
use framebuffer::Framebuffer;
|
||||
use framebuffer::FramebufferAbstract;
|
||||
@ -507,6 +508,73 @@ impl<P> UnsafeCommandBufferBuilder<P> {
|
||||
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.
|
||||
///
|
||||
/// 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?
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct UnsafeCommandBufferBuilderBufferImageCopy {
|
||||
|
74
vulkano/src/command_buffer/validity/clear_color_image.rs
Normal file
74
vulkano/src/command_buffer/validity/clear_color_image.rs
Normal 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))
|
||||
}
|
||||
}
|
@ -9,6 +9,7 @@
|
||||
|
||||
//! 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::descriptor_sets::{check_descriptor_sets_validity, CheckDescriptorSetsValidityError};
|
||||
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::vertex_buffers::{check_vertex_buffers, CheckVertexBuffer, CheckVertexBufferError};
|
||||
|
||||
mod clear_color_image;
|
||||
mod copy_buffer;
|
||||
mod descriptor_sets;
|
||||
mod dispatch;
|
||||
|
Loading…
Reference in New Issue
Block a user