Browse Source

use a staging buffer for vertex buffers

master
Alison Watson 3 years ago
parent
commit
c9a064649b
  1. 50
      source/main.rs
  2. 2
      source/render.rs
  3. 45
      source/render/buffer.rs
  4. 183
      source/render/cmd.rs
  5. 9
      source/render/queue.rs
  6. 17
      source/render/swapchain.rs

50
source/main.rs

@ -34,22 +34,24 @@ impl Pipelines {
impl SwapchainData<'_> {
pub fn create(
device: Rc<Device>,
phys_device: &PhysicalDevice,
surface: Rc<Surface>,
shader_vert: Rc<ShaderModule>,
shader_frag: Rc<ShaderModule>,
layout: Rc<PipelineLayout>,
vertex_buffer: Rc<Buffer>,
qf_info: &QueueFamilyInfo,
conf: &render::Conf,
device: Rc<Device>,
phys_device: &PhysicalDevice,
surface: Rc<Surface>,
shader_vert: Rc<ShaderModule>,
shader_frag: Rc<ShaderModule>,
layout: Rc<PipelineLayout>,
vertex_buffer: Rc<Buffer>,
queue_graphics: &Queue,
queue_surface: &Queue,
conf: &render::Conf,
) -> Result<Self, vk::Result> {
let swapchain = Swapchain::create(
device.clone(),
&phys_device,
surface,
conf,
qf_info,
queue_graphics,
queue_surface,
)?;
let images = Swapchain::get_images(swapchain.clone())?;
@ -85,7 +87,7 @@ impl SwapchainData<'_> {
let cmd_pool = CommandPool::create_graphics(
device,
qf_info.gfx_index,
queue_graphics.index,
&framebuffers,
render_pass,
swapchain.extent,
@ -117,7 +119,7 @@ fn draw_frame<'a>(
render_fini_s: &Semaphore,
frame_f: &'a Fence,
image_f: &mut [Option<&'a Fence>],
cmd_buffers: &[CommandBuffer],
cmd_buffers: &[vk::CommandBuffer],
queue_graphics: &Queue,
queue_surface: &Queue,
) -> Result<(), vk::Result> {
@ -153,7 +155,7 @@ fn draw_frame<'a>(
let signal_semaphores = [**render_fini_s];
let submit_cmd_buffers = [*cmd_buffers[image_index]];
let submit_cmd_buffers = &cmd_buffers[image_index..=image_index];
let submit_info = [
vk::SubmitInfo {
@ -241,8 +243,15 @@ fn fallback_main(
let device = Device::create(instance, &phys_device, &qf_info)?;
let vertex_buffer =
Buffer::create_vertex(device.clone(), &phys_device, VERTICES)?;
let queue_graphics = Queue::get(device.clone(), qf_info.gfx_index);
let queue_surface = Queue::get(device.clone(), qf_info.srf_index);
let vertex_buffer = Buffer::create_vertex(
device.clone(),
&phys_device,
VERTICES,
&queue_graphics,
)?;
let image_avail_s = Semaphore::create_all(device.clone(), concur_frames)?;
let render_fini_s = Semaphore::create_all(device.clone(), concur_frames)?;
@ -257,9 +266,6 @@ fn fallback_main(
let shader_vert = ShaderModule::create(device.clone(), &spir_vert)?;
let shader_frag = ShaderModule::create(device.clone(), &spir_frag)?;
let queue_graphics = Queue::get(device.clone(), qf_info.gfx_index);
let queue_surface = Queue::get(device.clone(), qf_info.srf_index);
let mut sc_data = SwapchainData::create(
device.clone(),
&phys_device,
@ -268,7 +274,8 @@ fn fallback_main(
shader_frag.clone(),
layout.clone(),
vertex_buffer.clone(),
&qf_info,
&queue_graphics,
&queue_surface,
&conf.render,
)?;
@ -288,7 +295,7 @@ fn fallback_main(
&render_fini_s[cur_c_frame],
&frame_f[cur_c_frame],
&mut sc_data.image_f,
sc_data.cmd_pool.buffers(),
sc_data.cmd_pool.buf_handles(),
&queue_graphics,
&queue_surface,
);
@ -305,7 +312,8 @@ fn fallback_main(
shader_frag.clone(),
layout.clone(),
vertex_buffer.clone(),
&qf_info,
&queue_graphics,
&queue_surface,
&conf.render,
)?;
}

2
source/render.rs

@ -32,7 +32,7 @@ pub use self::{
pipeline::{Pipeline, PipelineCreateInfo},
pipelinelayout::PipelineLayout,
properties::{ensure_properties, ErrNoProperty},
queue::{ErrQueueFamilyCollect, Queue, QueueFamilyInfo},
queue::{ErrQueueFamilyCollect, Queue, QueueFamilyInfo, QueueIndex},
renderpass::RenderPass,
semaphore::Semaphore,
shader::ShaderModule,

45
source/render/buffer.rs

@ -1,4 +1,4 @@
use crate::render::{Device, PhysicalDevice, Vertex};
use crate::render::{CommandPool, Device, PhysicalDevice, Queue, Vertex};
use ash::{
version::{DeviceV1_0, InstanceV1_0},
vk,
@ -83,28 +83,27 @@ impl Buffer {
device: Rc<Device>,
phys_device: &PhysicalDevice,
vertices: &[Vertex],
xfer_queue: &Queue,
) -> Result<Rc<Self>, ErrBufferCreate> {
let size = std::mem::size_of::<Vertex>() * vertices.len();
let size = size as vk::DeviceSize;
let (handle, memory) = unsafe {
let (st_handle, st_memory) = create_buffer(
let (src_handle, src_memory) = create_buffer(
&device,
phys_device,
size,
//vk::BufferUsageFlags::TRANSFER_SRC,
vk::BufferUsageFlags::VERTEX_BUFFER,
vk::BufferUsageFlags::TRANSFER_SRC,
vk::MemoryPropertyFlags::HOST_VISIBLE |
vk::MemoryPropertyFlags::HOST_COHERENT,
)?;
let mem_flg = vk::MemoryMapFlags::empty();
let mem_map = device.map_memory(st_memory, 0, size, mem_flg)?;
let mem_map = device.map_memory(src_memory, 0, size, mem_flg)?;
(mem_map as *mut Vertex).copy_from(vertices.as_ptr(), vertices.len());
device.unmap_memory(st_memory);
device.unmap_memory(src_memory);
/*
let (st_handle, st_memory) = create_buffer(
let (dst_handle, dst_memory) = create_buffer(
&device,
phys_device,
size,
@ -112,9 +111,35 @@ impl Buffer {
vk::BufferUsageFlags::VERTEX_BUFFER,
vk::MemoryPropertyFlags::DEVICE_LOCAL,
)?;
*/
(st_handle, st_memory)
let pool = CommandPool::create_transfer(
device.clone(),
xfer_queue.index,
|cmd| cmd.transfer(src_handle, dst_handle, size),
)?;
let submit_buffers = pool.buf_handles();
let submit_info = [
vk::SubmitInfo {
command_buffer_count: submit_buffers.len() as u32,
p_command_buffers: submit_buffers.as_ptr(),
..Default::default()
}
];
device.queue_submit(
**xfer_queue,
&submit_info,
vk::Fence::null(),
)?;
device.queue_wait_idle(**xfer_queue)?;
device.free_memory(src_memory, None);
device.destroy_buffer(src_handle, None);
(dst_handle, dst_memory)
};
Ok(Rc::new(Self { handle, device, memory }))

183
source/render/cmd.rs

@ -2,6 +2,7 @@ use crate::render::{Buffer, Device, Framebuffer, Pipeline, RenderPass};
use ash::{version::DeviceV1_0, vk};
use std::rc::Rc;
#[allow(dead_code)]
pub struct CommandPool {
handle: vk::CommandPool,
@ -11,16 +12,15 @@ pub struct CommandPool {
pub device: Rc<Device>,
}
#[allow(dead_code)]
pub struct CommandBuffer {
handle: vk::CommandBuffer,
pub device: Rc<Device>,
pub render_pass: Rc<RenderPass>,
pub framebuffer: Rc<Framebuffer>,
pub extent: vk::Extent2D,
pub pipeline: Option<Rc<Pipeline>>,
pub vertex_buffer: Option<Rc<Buffer>>,
device: Rc<Device>,
render_pass: Option<Rc<RenderPass>>,
framebuffer: Option<Rc<Framebuffer>>,
pipeline: Option<Rc<Pipeline>>,
vertex_buffer: Option<Rc<Buffer>>,
}
impl CommandPool {
@ -32,19 +32,17 @@ impl CommandPool {
extent: vk::Extent2D,
f: impl Fn(&mut CommandBuffer) + Copy,
) -> Result<Rc<Self>, vk::Result> {
let flags = vk::CommandPoolCreateFlags::empty();
let handle = Self::create_inner(&device, index, flags)?;
let alloc_info = vk::CommandBufferAllocateInfo {
command_pool: handle,
level: vk::CommandBufferLevel::PRIMARY,
command_buffer_count: framebuffers.len() as u32,
..Default::default()
let (handle, buffers) = unsafe {
Self::create_inner(
&device,
index,
vk::CommandPoolCreateFlags::empty(),
framebuffers.len(),
)?
};
let buffers = unsafe {
device
.allocate_command_buffers(&alloc_info)?
let buffers =
buffers
.iter()
.zip(framebuffers.iter())
.map(|(&handle, framebuffer)| {
@ -57,47 +55,77 @@ impl CommandPool {
f,
)?)
})
.collect::<Result<Vec<_>, vk::Result>>()?
};
.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,
}))
Ok(Rc::new(Self { handle, buf_handles, buffers, device }))
}
/*
pub fn create_transient(
pub fn create_transfer(
device: Rc<Device>,
index: u32,
f: impl Fn(&mut CommandBuffer) + Copy,
) -> Result<Rc<Self>, vk::Result> {
let flags = vk::CommandPoolCreateFlags::TRANSIENT;
let handle = Self::create_inner(device, index, flags);
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 }))
}
*/
fn create_inner(
device: &Device,
index: u32,
flags: vk::CommandPoolCreateFlags,
) -> Result<vk::CommandPool, vk::Result> {
#[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 = unsafe { device.create_command_pool(&create_info, None)? };
let handle = device.create_command_pool(&create_info, None)?;
Ok(handle)
}
let alloc_info = vk::CommandBufferAllocateInfo {
command_pool: handle,
level: vk::CommandBufferLevel::PRIMARY,
command_buffer_count: buf_num as u32,
..Default::default()
};
pub fn buffers(&self) -> &[CommandBuffer] {
&self.buffers
let buffers = device.allocate_command_buffers(&alloc_info)?;
Ok((handle, buffers))
}
}
@ -132,6 +160,24 @@ impl CommandBuffer {
}
}
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>,
@ -140,16 +186,6 @@ impl CommandBuffer {
extent: vk::Extent2D,
f: impl Fn(&mut Self),
) -> Result<Self, vk::Result> {
let mut this = Self {
handle,
device,
render_pass,
framebuffer,
extent,
pipeline: None,
vertex_buffer: None,
};
let cmd_begin_info = vk::CommandBufferBeginInfo::default();
let clear_values = [
@ -159,17 +195,26 @@ impl CommandBuffer {
];
let ren_begin_info = vk::RenderPassBeginInfo {
render_pass: **this.render_pass,
framebuffer: **this.framebuffer,
render_pass: **render_pass,
framebuffer: **framebuffer,
render_area: vk::Rect2D {
extent,
offset: vk::Offset2D::default(),
extent: this.extent,
},
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,
};
unsafe {
this.device.begin_command_buffer(this.handle, &cmd_begin_info)?;
@ -188,6 +233,36 @@ impl CommandBuffer {
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,
};
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 {

9
source/render/queue.rs

@ -5,15 +5,18 @@ use ash::{
};
use std::rc::Rc;
pub type QueueIndex = u32;
pub struct QueueFamilyInfo {
pub gfx_index: u32,
pub srf_index: u32,
pub gfx_index: QueueIndex,
pub srf_index: QueueIndex,
}
pub struct Queue {
handle: vk::Queue,
pub device: Rc<Device>,
pub index: QueueIndex,
}
#[derive(Debug)]
@ -65,7 +68,7 @@ impl QueueFamilyInfo {
impl Queue {
pub fn get(device: Rc<Device>, index: u32) -> Rc<Self> {
let handle = unsafe { device.get_device_queue(index, 0) };
Rc::new(Self { handle, device })
Rc::new(Self { handle, device, index })
}
}

17
source/render/swapchain.rs

@ -1,5 +1,5 @@
use crate::render::{
Conf, Device, OwnedImage, PhysicalDevice, QueueFamilyInfo, Surface,
Conf, Device, OwnedImage, PhysicalDevice, Queue, Surface,
};
use ash::vk;
use std::rc::Rc;
@ -16,11 +16,12 @@ pub struct Swapchain {
impl Swapchain {
pub fn create(
device: Rc<Device>,
phys_device: &PhysicalDevice,
surface: Rc<Surface>,
conf: &Conf,
qf_info: &QueueFamilyInfo,
device: Rc<Device>,
phys_device: &PhysicalDevice,
surface: Rc<Surface>,
conf: &Conf,
queue_graphics: &Queue,
queue_surface: &Queue,
) -> Result<Rc<Self>, vk::Result> {
let capabilities = unsafe {
device.instance.surface_ext.get_physical_device_surface_capabilities(
@ -82,7 +83,7 @@ impl Swapchain {
min_image_count
};
let queue_family_indices = [qf_info.gfx_index, qf_info.srf_index];
let queue_family_indices = [queue_graphics.index, queue_surface.index];
let create_info = vk::SwapchainCreateInfoKHR {
min_image_count,
@ -93,7 +94,7 @@ impl Swapchain {
image_color_space: format.color_space,
image_array_layers: 1,
image_usage: vk::ImageUsageFlags::COLOR_ATTACHMENT,
image_sharing_mode: if qf_info.gfx_index != qf_info.srf_index {
image_sharing_mode: if queue_graphics.index != queue_surface.index {
vk::SharingMode::CONCURRENT
} else {
vk::SharingMode::EXCLUSIVE

Loading…
Cancel
Save