Browse Source

use a staging buffer for vertex buffers

master
Alison Watson 1 year ago
parent
commit
c9a064649b
6 changed files with 209 additions and 97 deletions
  1. +29
    -21
      source/main.rs
  2. +1
    -1
      source/render.rs
  3. +35
    -10
      source/render/buffer.rs
  4. +129
    -54
      source/render/cmd.rs
  5. +6
    -3
      source/render/queue.rs
  6. +9
    -8
      source/render/swapchain.rs

+ 29
- 21
source/main.rs View File

@@ -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,
)?;
}


+ 1
- 1
source/render.rs View File

@@ -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,


+ 35
- 10
source/render/buffer.rs View File

@@ -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 }))


+ 129
- 54
source/render/cmd.rs View File

@@ -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 {


+ 6
- 3
source/render/queue.rs View File

@@ -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 })
}
}



+ 9
- 8
source/render/swapchain.rs View File

@@ -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