Add clear_depth_stencil_image as well

This commit is contained in:
Pierre Krieger 2016-07-20 20:03:03 +02:00
parent efdd315b4f
commit 6f02a246c2

View File

@ -299,6 +299,102 @@ impl<P> UnsafeCommandBufferBuilder<P> where P: CommandPool {
ranges.len() as u32, ranges.as_ptr());
}
/// Clears an image with a depth, stencil or depth-stencil format, from outside of a
/// render pass.
///
/// If the `ClearValue` is a depth value, then only the depth component will be cleared. Same
/// for stencil. If it contains a depth-stencil value, then they will both be cleared.
///
/// If `general_layout` is true, then the `General` image layout is used. Otherwise the
/// `TransferDstOptimal` layout is used.
///
/// # Panic
///
/// - Panics if the image was not created with the same device as this command buffer.
/// - Panics if the mipmap levels range or the array layers range is invalid, ie. if the end
/// is inferior to the start.
///
/// # Safety
///
/// - The image must be kept alive and must be properly synchronized while this command
/// buffer runs.
/// - The ranges must be in range of the image.
/// - The image must have a depth, stencil or depth-stencil format.
/// - The clear value must match the format of the image.
/// - The queue family must support graphics operations.
/// - The image must have been created with the "transfer_dest" usage.
/// - Must be called outside of a render pass.
///
pub unsafe fn clear_depth_stencil_image<I>(&mut self, image: &UnsafeImage, general_layout: bool,
color: ClearValue, ranges: I)
where I: Iterator<Item = ImageSubresourcesRange>
{
assert_eq!(image.device().internal_object(), self.device.internal_object());
let (clear_value, aspect_mask) = match color {
ClearValue::None => panic!(),
ClearValue::Float(_) => panic!(),
ClearValue::Int(_) => panic!(),
ClearValue::Uint(_) => panic!(),
ClearValue::Depth(val) => {
debug_assert!(image.format().ty() == FormatTy::Depth ||
image.format().ty() == FormatTy::DepthStencil);
let clear = vk::ClearDepthStencilValue { depth: val, stencil: 0 };
let aspect = vk::IMAGE_ASPECT_DEPTH_BIT;
(clear, aspect)
},
ClearValue::Stencil(val) => {
debug_assert!(image.format().ty() == FormatTy::Stencil ||
image.format().ty() == FormatTy::DepthStencil);
let clear = vk::ClearDepthStencilValue { depth: 0.0, stencil: val };
let aspect = vk::IMAGE_ASPECT_STENCIL_BIT;
(clear, aspect)
},
ClearValue::DepthStencil((depth, stencil)) => {
debug_assert_eq!(image.format().ty(), FormatTy::DepthStencil);
let clear = vk::ClearDepthStencilValue { depth: depth, stencil: stencil };
let aspect = vk::IMAGE_ASPECT_DEPTH_BIT | vk::IMAGE_ASPECT_STENCIL_BIT;
(clear, aspect)
},
};
let ranges: SmallVec<[_; 4]> = ranges.filter_map(|range| {
assert!(range.mipmap_levels.start <= range.mipmap_levels.end);
assert!(range.array_layers.start <= range.array_layers.end);
debug_assert!(range.mipmap_levels.end <= image.mipmap_levels());
debug_assert!(range.array_layers.end <= image.dimensions().array_layers());
if range.mipmap_levels.start == range.mipmap_levels.end {
return None;
}
if range.array_layers.start == range.array_layers.end {
return None;
}
Some(vk::ImageSubresourceRange {
aspectMask: aspect_mask,
baseMipLevel: range.mipmap_levels.start,
levelCount: range.mipmap_levels.end - range.mipmap_levels.start,
baseArrayLayer: range.array_layers.start,
layerCount: range.array_layers.end - range.array_layers.start,
})
}).collect();
// Do nothing if no range to clear.
if ranges.is_empty() {
return;
}
let layout = if general_layout { vk::IMAGE_LAYOUT_GENERAL }
else { vk::IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL };
let vk = self.device.pointers();
let cmd = self.cmd.take().unwrap();
vk.CmdClearDepthStencilImage(cmd, image.internal_object(), layout, &clear_value,
ranges.len() as u32, ranges.as_ptr());
}
/// Fills a buffer by repeating a 32 bits data.
///
/// This is similar to the `memset` function in C/C++.