Staging buffers

Add hal methods to clear and copy buffers, so work happens in device
local buffers.
This commit is contained in:
Raph Levien 2020-04-18 07:46:59 -07:00
parent 957f710b91
commit 5adb703936
4 changed files with 61 additions and 11 deletions

View file

@ -71,6 +71,10 @@ pub trait CmdBuf<D: Device> {
unsafe fn memory_barrier(&mut self); unsafe fn memory_barrier(&mut self);
unsafe fn clear_buffer(&self, buffer: &D::Buffer);
unsafe fn copy_buffer(&self, src: &D::Buffer, dst: &D::Buffer);
unsafe fn write_timestamp(&mut self, pool: &D::QueryPool, query: u32); unsafe fn write_timestamp(&mut self, pool: &D::QueryPool, query: u32);
} }

View file

@ -142,7 +142,11 @@ impl crate::Device for VkDevice {
let buffer = device.create_buffer( let buffer = device.create_buffer(
&vk::BufferCreateInfo::builder() &vk::BufferCreateInfo::builder()
.size(size) .size(size)
.usage(vk::BufferUsageFlags::STORAGE_BUFFER) .usage(
vk::BufferUsageFlags::STORAGE_BUFFER
| vk::BufferUsageFlags::TRANSFER_SRC
| vk::BufferUsageFlags::TRANSFER_DST,
)
.sharing_mode(vk::SharingMode::EXCLUSIVE), .sharing_mode(vk::SharingMode::EXCLUSIVE),
None, None,
)?; )?;
@ -443,6 +447,31 @@ impl crate::CmdBuf<VkDevice> for CmdBuf {
); );
} }
unsafe fn clear_buffer(&self, buffer: &Buffer) {
let device = &self.device.device;
device.cmd_fill_buffer(
self.cmd_buf,
buffer.buffer,
0,
vk::WHOLE_SIZE,
0
);
}
unsafe fn copy_buffer(&self, src: &Buffer, dst: &Buffer) {
let device = &self.device.device;
let size = src.size.min(dst.size);
device.cmd_copy_buffer(
self.cmd_buf,
src.buffer,
dst.buffer,
&[vk::BufferCopy::builder()
.size(size)
.build()
]
);
}
unsafe fn write_timestamp(&mut self, pool: &QueryPool, query: u32) { unsafe fn write_timestamp(&mut self, pool: &QueryPool, query: u32) {
let device = &self.device.device; let device = &self.device.device;
device.cmd_write_timestamp( device.cmd_write_timestamp(

View file

@ -1,5 +1,8 @@
fn main() { fn main() {
let mod_name = std::env::args().skip(1).next().expect("provide a module name"); let mod_name = std::env::args()
.skip(1)
.next()
.expect("provide a module name");
match mod_name.as_str() { match mod_name.as_str() {
"scene" => print!("{}", piet_gpu_types::scene::gen_gpu_scene()), "scene" => print!("{}", piet_gpu_types::scene::gen_gpu_scene()),
"ptcl" => print!("{}", piet_gpu_types::ptcl::gen_gpu_ptcl()), "ptcl" => print!("{}", piet_gpu_types::ptcl::gen_gpu_ptcl()),

View file

@ -1,6 +1,6 @@
use std::path::Path;
use std::fs::File; use std::fs::File;
use std::io::BufWriter; use std::io::BufWriter;
use std::path::Path;
use rand::{Rng, RngCore}; use rand::{Rng, RngCore};
@ -29,7 +29,10 @@ fn make_scene() -> Vec<u8> {
let circle = PietCircle { let circle = PietCircle {
rgba_color: rng.next_u32(), rgba_color: rng.next_u32(),
center: Point { center: Point {
xy: [rng.gen_range(0.0, WIDTH as f32), rng.gen_range(0.0, HEIGHT as f32)], xy: [
rng.gen_range(0.0, WIDTH as f32),
rng.gen_range(0.0, HEIGHT as f32),
],
}, },
radius: rng.gen_range(0.0, 50.0), radius: rng.gen_range(0.0, 50.0),
}; };
@ -58,7 +61,7 @@ fn make_scene() -> Vec<u8> {
fn dump_scene(buf: &[u8]) { fn dump_scene(buf: &[u8]) {
for i in 0..(buf.len() / 4) { for i in 0..(buf.len() / 4) {
let mut buf_u32 = [0u8; 4]; let mut buf_u32 = [0u8; 4];
buf_u32.copy_from_slice(&buf[i * 4 .. i * 4 + 4]); buf_u32.copy_from_slice(&buf[i * 4..i * 4 + 4]);
println!("{:4x}: {:8x}", i * 4, u32::from_le_bytes(buf_u32)); println!("{:4x}: {:8x}", i * 4, u32::from_le_bytes(buf_u32));
} }
} }
@ -67,24 +70,33 @@ fn main() {
let instance = VkInstance::new().unwrap(); let instance = VkInstance::new().unwrap();
unsafe { unsafe {
let device = instance.device().unwrap(); let device = instance.device().unwrap();
let mem_flags = MemFlags::host_coherent(); let host = MemFlags::host_coherent();
let dev = MemFlags::device_local();
let scene = make_scene(); let scene = make_scene();
//dump_scene(&scene); //dump_scene(&scene);
let scene_buf = device let scene_buf = device
.create_buffer(std::mem::size_of_val(&scene[..]) as u64, mem_flags) .create_buffer(std::mem::size_of_val(&scene[..]) as u64, host)
.unwrap();
let scene_dev = device
.create_buffer(std::mem::size_of_val(&scene[..]) as u64, dev)
.unwrap(); .unwrap();
device.write_buffer(&scene_buf, &scene).unwrap(); device.write_buffer(&scene_buf, &scene).unwrap();
let image_buf = device let image_buf = device
.create_buffer((WIDTH * HEIGHT * 4) as u64, mem_flags) .create_buffer((WIDTH * HEIGHT * 4) as u64, host)
.unwrap();
let image_dev = device
.create_buffer((WIDTH * HEIGHT * 4) as u64, dev)
.unwrap(); .unwrap();
let code = include_bytes!("../shader/image.spv"); let code = include_bytes!("../shader/image.spv");
let pipeline = device.create_simple_compute_pipeline(code, 2).unwrap(); let pipeline = device.create_simple_compute_pipeline(code, 2).unwrap();
let descriptor_set = device let descriptor_set = device
.create_descriptor_set(&pipeline, &[&scene_buf, &image_buf]) .create_descriptor_set(&pipeline, &[&scene_dev, &image_dev])
.unwrap(); .unwrap();
let query_pool = device.create_query_pool(2).unwrap(); let query_pool = device.create_query_pool(2).unwrap();
let mut cmd_buf = device.create_cmd_buf().unwrap(); let mut cmd_buf = device.create_cmd_buf().unwrap();
cmd_buf.begin(); cmd_buf.begin();
cmd_buf.copy_buffer(&scene_buf, &scene_dev);
cmd_buf.memory_barrier();
cmd_buf.write_timestamp(&query_pool, 0); cmd_buf.write_timestamp(&query_pool, 0);
cmd_buf.dispatch( cmd_buf.dispatch(
&pipeline, &pipeline,
@ -92,6 +104,8 @@ fn main() {
((WIDTH / TILE_W) as u32, (HEIGHT / TILE_H) as u32, 1), ((WIDTH / TILE_W) as u32, (HEIGHT / TILE_H) as u32, 1),
); );
cmd_buf.write_timestamp(&query_pool, 1); cmd_buf.write_timestamp(&query_pool, 1);
cmd_buf.memory_barrier();
cmd_buf.copy_buffer(&image_dev, &image_buf);
cmd_buf.finish(); cmd_buf.finish();
device.run_cmd_buf(&cmd_buf).unwrap(); device.run_cmd_buf(&cmd_buf).unwrap();
let timestamps = device.reap_query_pool(query_pool).unwrap(); let timestamps = device.reap_query_pool(query_pool).unwrap();
@ -105,12 +119,12 @@ fn main() {
let path = Path::new("image.png"); let path = Path::new("image.png");
let file = File::create(path).unwrap(); let file = File::create(path).unwrap();
let ref mut w = BufWriter::new(file); let ref mut w = BufWriter::new(file);
let mut encoder = png::Encoder::new(w, WIDTH as u32, HEIGHT as u32); let mut encoder = png::Encoder::new(w, WIDTH as u32, HEIGHT as u32);
encoder.set_color(png::ColorType::RGBA); encoder.set_color(png::ColorType::RGBA);
encoder.set_depth(png::BitDepth::Eight); encoder.set_depth(png::BitDepth::Eight);
let mut writer = encoder.write_header().unwrap(); let mut writer = encoder.write_header().unwrap();
writer.write_image_data(&img_data).unwrap(); writer.write_image_data(&img_data).unwrap();
} }
} }