You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

332 lines
6.9 KiB

use crate::render::{
Buffer, DescriptorPool, Device, Framebuffer, Pipeline, PipelineLayout,
RenderPass,
};
use ash::{version::DeviceV1_0, vk};
use std::rc::Rc;
#[allow(dead_code)]
pub struct CommandPool {
handle: vk::CommandPool,
buf_handles: Vec<vk::CommandBuffer>,
buffers: Vec<CommandBuffer>,
pub device: Rc<Device>,
}
#[allow(dead_code)]
pub struct CommandBuffer {
handle: vk::CommandBuffer,
device: Rc<Device>,
render_pass: Option<Rc<RenderPass>>,
framebuffer: Option<Rc<Framebuffer>>,
pipeline: Option<Rc<Pipeline>>,
vertex_buffer: Option<Rc<Buffer>>,
index_buffer: Option<Rc<Buffer>>,
descriptor_pool: Option<Rc<DescriptorPool>>,
}
impl CommandPool {
pub fn create_graphics(
device: Rc<Device>,
index: u32,
framebuffers: &[Rc<Framebuffer>],
render_pass: Rc<RenderPass>,
extent: vk::Extent2D,
f: impl Fn(&mut CommandBuffer, usize) + Copy,
) -> Result<Rc<Self>, vk::Result> {
let (handle, buffers) = unsafe {
Self::create_inner(
&device,
index,
vk::CommandPoolCreateFlags::empty(),
framebuffers.len(),
)?
};
let buffers =
buffers
.iter()
.zip(framebuffers.iter())
.enumerate()
.map(|(framebuffer_num, (&handle, framebuffer))| {
Ok(CommandBuffer::create_graphics(
handle,
device.clone(),
render_pass.clone(),
framebuffer.clone(),
extent,
|cmd| f(cmd, framebuffer_num),
)?)
})
.collect::<Result<Vec<_>, vk::Result>>()?;
let buf_handles = buffers.iter().map(|cmd_buf| **cmd_buf).collect();
Ok(Rc::new(Self { handle, buf_handles, buffers, device }))
}
pub fn create_transfer(
device: Rc<Device>,
index: u32,
f: impl Fn(&mut CommandBuffer) + Copy,
) -> Result<Rc<Self>, vk::Result> {
let (handle, buffers) = unsafe {
Self::create_inner(
&device,
index,
vk::CommandPoolCreateFlags::TRANSIENT,
1,
)?
};
let buffers =
buffers
.iter()
.map(|&handle| {
Ok(CommandBuffer::create_transfer(
handle,
device.clone(),
f,
)?)
})
.collect::<Result<Vec<_>, vk::Result>>()?;
let buf_handles = buffers.iter().map(|cmd_buf| **cmd_buf).collect();
Ok(Rc::new(Self { handle, buf_handles, buffers, device }))
}
#[allow(dead_code)]
pub fn buffers(&self) -> &[CommandBuffer] {
&self.buffers
}
pub fn buf_handles(&self) -> &[vk::CommandBuffer] {
&self.buf_handles
}
unsafe fn create_inner(
device: &Device,
index: u32,
flags: vk::CommandPoolCreateFlags,
buf_num: usize,
) -> Result<(vk::CommandPool, Vec<vk::CommandBuffer>), vk::Result> {
let create_info = vk::CommandPoolCreateInfo {
flags,
queue_family_index: index,
..Default::default()
};
let handle = device.create_command_pool(&create_info, None)?;
let alloc_info = vk::CommandBufferAllocateInfo {
command_pool: handle,
level: vk::CommandBufferLevel::PRIMARY,
command_buffer_count: buf_num as u32,
..Default::default()
};
let buffers = device.allocate_command_buffers(&alloc_info)?;
Ok((handle, buffers))
}
}
impl CommandBuffer {
pub fn bind_pipeline(&mut self, pipeline: Rc<Pipeline>) {
unsafe {
self.device.cmd_bind_pipeline(
self.handle,
vk::PipelineBindPoint::GRAPHICS,
**pipeline,
);
self.pipeline = Some(pipeline);
}
}
pub fn bind_vertex_buffer(&mut self, buffer: Rc<Buffer>) {
unsafe {
self.device.cmd_bind_vertex_buffers(
self.handle,
0,
&[ **buffer ],
&[ 0 ],
);
self.vertex_buffer = Some(buffer);
}
}
pub fn bind_index_buffer(&mut self, buffer: Rc<Buffer>) {
let ty = vk::IndexType::UINT16;
unsafe {
self.device.cmd_bind_index_buffer(self.handle, **buffer, 0, ty);
self.index_buffer = Some(buffer);
}
}
pub fn bind_descriptor_pool(
&mut self,
descriptor_pool: Rc<DescriptorPool>,
pipeline_layout: Rc<PipelineLayout>,
which: usize,
) {
unsafe {
self.device.cmd_bind_descriptor_sets(
self.handle,
vk::PipelineBindPoint::GRAPHICS,
**pipeline_layout,
0,
&[*descriptor_pool.sets[which]],
&[],
);
self.descriptor_pool = Some(descriptor_pool);
}
}
pub fn draw(&self, num: usize) {
unsafe {
self.device.cmd_draw_indexed(self.handle, num as u32, 1, 0, 0, 0);
}
}
pub fn transfer(
&mut self,
src: vk::Buffer,
dst: vk::Buffer,
size: vk::DeviceSize
) {
let copy = [
vk::BufferCopy {
size,
..Default::default()
}
];
unsafe {
self.device.cmd_copy_buffer(self.handle, src, dst, &copy);
}
}
fn create_graphics(
handle: vk::CommandBuffer,
device: Rc<Device>,
render_pass: Rc<RenderPass>,
framebuffer: Rc<Framebuffer>,
extent: vk::Extent2D,
f: impl Fn(&mut Self),
) -> Result<Self, vk::Result> {
let cmd_begin_info = vk::CommandBufferBeginInfo::default();
let clear_values = [
vk::ClearValue {
color: vk::ClearColorValue { float32: [0.086, 0.098, 0.149, 1.0] }
}
];
let ren_begin_info = vk::RenderPassBeginInfo {
render_pass: **render_pass,
framebuffer: **framebuffer,
render_area: vk::Rect2D {
extent,
offset: vk::Offset2D::default(),
},
clear_value_count: clear_values.len() as u32,
p_clear_values: clear_values.as_ptr(),
..Default::default()
};
let mut this = Self {
handle,
device,
render_pass: Some(render_pass),
framebuffer: Some(framebuffer),
pipeline: None,
vertex_buffer: None,
index_buffer: None,
descriptor_pool: None,
};
unsafe {
this.device.begin_command_buffer(this.handle, &cmd_begin_info)?;
this.device.cmd_begin_render_pass(
this.handle,
&ren_begin_info,
vk::SubpassContents::INLINE,
);
f(&mut this);
this.device.cmd_end_render_pass(this.handle);
this.device.end_command_buffer(this.handle)?;
}
Ok(this)
}
fn create_transfer(
handle: vk::CommandBuffer,
device: Rc<Device>,
f: impl Fn(&mut Self),
) -> Result<Self, vk::Result> {
let cmd_begin_info = vk::CommandBufferBeginInfo {
flags: vk::CommandBufferUsageFlags::ONE_TIME_SUBMIT,
..Default::default()
};
let mut this = Self {
handle,
device,
render_pass: None,
framebuffer: None,
pipeline: None,
vertex_buffer: None,
index_buffer: None,
descriptor_pool: None,
};
unsafe {
this.device.begin_command_buffer(this.handle, &cmd_begin_info)?;
f(&mut this);
this.device.end_command_buffer(this.handle)?;
}
Ok(this)
}
}
impl Drop for CommandPool {
fn drop(&mut self) {
unsafe {
self.device.free_command_buffers(self.handle, &self.buf_handles);
self.device.destroy_command_pool(self.handle, None);
}
}
}
impl std::ops::Deref for CommandPool {
type Target = vk::CommandPool;
fn deref(&self) -> &Self::Target {
&self.handle
}
}
impl std::ops::Deref for CommandBuffer {
type Target = vk::CommandBuffer;
fn deref(&self) -> &Self::Target {
&self.handle
}
}
// EOF