use std::error;
use std::fmt;
use std::sync::Arc;
use buffer::BufferAccess;
use buffer::BufferInner;
use command_buffer::CommandAddError;
use command_buffer::cb::AddCommand;
use command_buffer::cb::UnsafeCommandBufferBuilder;
use command_buffer::pool::CommandPool;
use device::Device;
use device::DeviceOwned;
use VulkanObject;
use VulkanPointers;
use vk;
pub struct CmdFillBuffer<B> {
buffer: B,
buffer_handle: vk::Buffer,
offset: vk::DeviceSize,
size: vk::DeviceSize,
data: u32,
}
unsafe impl<B> DeviceOwned for CmdFillBuffer<B>
where B: DeviceOwned
{
#[inline]
fn device(&self) -> &Arc<Device> {
self.buffer.device()
}
}
impl<B> CmdFillBuffer<B>
where B: BufferAccess
{
pub fn new(buffer: B, data: u32) -> Result<CmdFillBuffer<B>, CmdFillBufferError> {
let size = buffer.size();
let (buffer_handle, offset) = {
let BufferInner { buffer: buffer_inner, offset } = buffer.inner();
if !buffer_inner.usage_transfer_dest() {
return Err(CmdFillBufferError::BufferMissingUsage);
}
if offset % 4 != 0 {
return Err(CmdFillBufferError::WrongAlignment);
}
(buffer_inner.internal_object(), offset)
};
Ok(CmdFillBuffer {
buffer: buffer,
buffer_handle: buffer_handle,
offset: offset as vk::DeviceSize,
size: size as vk::DeviceSize,
data: data,
})
}
}
impl<B> CmdFillBuffer<B> {
#[inline]
pub fn buffer(&self) -> &B {
&self.buffer
}
}
unsafe impl<'a, P, B> AddCommand<&'a CmdFillBuffer<B>> for UnsafeCommandBufferBuilder<P>
where P: CommandPool
{
type Out = UnsafeCommandBufferBuilder<P>;
#[inline]
fn add(self, command: &'a CmdFillBuffer<B>) -> Result<Self::Out, CommandAddError> {
unsafe {
let vk = self.device().pointers();
let cmd = self.internal_object();
vk.CmdFillBuffer(cmd, command.buffer_handle, command.offset,
command.size, command.data);
}
Ok(self)
}
}
#[derive(Debug, Copy, Clone)]
pub enum CmdFillBufferError {
BufferMissingUsage,
WrongAlignment,
}
impl error::Error for CmdFillBufferError {
#[inline]
fn description(&self) -> &str {
match *self {
CmdFillBufferError::BufferMissingUsage => {
"the transfer destination usage must be enabled on the buffer"
},
CmdFillBufferError::WrongAlignment => {
"the offset or size are not aligned to 4 bytes"
},
}
}
}
impl fmt::Display for CmdFillBufferError {
#[inline]
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(fmt, "{}", error::Error::description(self))
}
}