mirror of
https://github.com/italicsjenga/vello.git
synced 2025-01-10 12:41:30 +11:00
Start adding support for creating images
This is still WIP, focused on creating image resources and making them available GPU-side. Progress toward #38
This commit is contained in:
parent
1d0fd02c79
commit
47e24ec9d5
|
@ -196,6 +196,14 @@ impl Session {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CmdBuf {
|
impl CmdBuf {
|
||||||
|
/// Make sure the resource lives until the command buffer completes.
|
||||||
|
///
|
||||||
|
/// The submitted command buffer will hold this reference until the corresponding
|
||||||
|
/// fence is signaled.
|
||||||
|
///
|
||||||
|
/// There are two choices for upholding the lifetime invariant: this function, or
|
||||||
|
/// the caller can manually hold the reference. The latter is appropriate when it's
|
||||||
|
/// part of retained state.
|
||||||
pub fn add_resource<T: Clone + 'static>(&mut self, resource: &T) {
|
pub fn add_resource<T: Clone + 'static>(&mut self, resource: &T) {
|
||||||
self.resources.push(Box::new(resource.clone()));
|
self.resources.push(Box::new(resource.clone()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -431,6 +431,11 @@ impl crate::Device for VkDevice {
|
||||||
height,
|
height,
|
||||||
depth: 1,
|
depth: 1,
|
||||||
};
|
};
|
||||||
|
// TODO: maybe want to fine-tune these for different use cases, especially because we'll
|
||||||
|
// want to add sampling for images and so on.
|
||||||
|
let usage = vk::ImageUsageFlags::STORAGE
|
||||||
|
| vk::ImageUsageFlags::TRANSFER_SRC
|
||||||
|
| vk::ImageUsageFlags::TRANSFER_DST;
|
||||||
let image = device.create_image(
|
let image = device.create_image(
|
||||||
&vk::ImageCreateInfo::builder()
|
&vk::ImageCreateInfo::builder()
|
||||||
.image_type(vk::ImageType::TYPE_2D)
|
.image_type(vk::ImageType::TYPE_2D)
|
||||||
|
@ -441,7 +446,7 @@ impl crate::Device for VkDevice {
|
||||||
.samples(vk::SampleCountFlags::TYPE_1)
|
.samples(vk::SampleCountFlags::TYPE_1)
|
||||||
.tiling(vk::ImageTiling::OPTIMAL)
|
.tiling(vk::ImageTiling::OPTIMAL)
|
||||||
.initial_layout(vk::ImageLayout::UNDEFINED)
|
.initial_layout(vk::ImageLayout::UNDEFINED)
|
||||||
.usage(vk::ImageUsageFlags::STORAGE | vk::ImageUsageFlags::TRANSFER_SRC) // write in compute and blit src
|
.usage(usage)
|
||||||
.sharing_mode(vk::SharingMode::EXCLUSIVE),
|
.sharing_mode(vk::SharingMode::EXCLUSIVE),
|
||||||
None,
|
None,
|
||||||
)?;
|
)?;
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
mod pico_svg;
|
mod pico_svg;
|
||||||
mod render_ctx;
|
mod render_ctx;
|
||||||
|
|
||||||
|
use std::convert::TryInto;
|
||||||
|
|
||||||
pub use render_ctx::PietGpuRenderContext;
|
pub use render_ctx::PietGpuRenderContext;
|
||||||
|
|
||||||
use rand::{Rng, RngCore};
|
use rand::{Rng, RngCore};
|
||||||
|
|
||||||
use piet::kurbo::{BezPath, Circle, Line, Point, Vec2};
|
use piet::kurbo::{BezPath, Circle, Line, Point, Vec2};
|
||||||
use piet::{Color, RenderContext};
|
use piet::{Color, ImageFormat, RenderContext};
|
||||||
|
|
||||||
use piet_gpu_types::encoder::Encode;
|
use piet_gpu_types::encoder::Encode;
|
||||||
|
|
||||||
|
@ -213,14 +215,16 @@ impl Renderer {
|
||||||
// TODO: constants
|
// TODO: constants
|
||||||
const PATH_SIZE: usize = 12;
|
const PATH_SIZE: usize = 12;
|
||||||
let tile_alloc_start = ((n_paths + 31) & !31) * PATH_SIZE;
|
let tile_alloc_start = ((n_paths + 31) & !31) * PATH_SIZE;
|
||||||
tile_alloc_buf_host.write(
|
tile_alloc_buf_host.write(&[n_paths as u32, n_pathseg as u32, tile_alloc_start as u32])?;
|
||||||
&[n_paths as u32, n_pathseg as u32, tile_alloc_start as u32],
|
|
||||||
)?;
|
|
||||||
let tile_alloc_code = include_bytes!("../shader/tile_alloc.spv");
|
let tile_alloc_code = include_bytes!("../shader/tile_alloc.spv");
|
||||||
let tile_pipeline = session.create_simple_compute_pipeline(tile_alloc_code, 3, 0)?;
|
let tile_pipeline = session.create_simple_compute_pipeline(tile_alloc_code, 3, 0)?;
|
||||||
let tile_ds = session.create_descriptor_set(
|
let tile_ds = session.create_descriptor_set(
|
||||||
&tile_pipeline,
|
&tile_pipeline,
|
||||||
&[anno_buf.vk_buffer(), tile_alloc_buf_dev.vk_buffer(), tile_buf.vk_buffer()],
|
&[
|
||||||
|
anno_buf.vk_buffer(),
|
||||||
|
tile_alloc_buf_dev.vk_buffer(),
|
||||||
|
tile_buf.vk_buffer(),
|
||||||
|
],
|
||||||
&[],
|
&[],
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
@ -228,7 +232,11 @@ impl Renderer {
|
||||||
let path_pipeline = session.create_simple_compute_pipeline(path_alloc_code, 3, 0)?;
|
let path_pipeline = session.create_simple_compute_pipeline(path_alloc_code, 3, 0)?;
|
||||||
let path_ds = session.create_descriptor_set(
|
let path_ds = session.create_descriptor_set(
|
||||||
&path_pipeline,
|
&path_pipeline,
|
||||||
&[pathseg_buf.vk_buffer(), tile_alloc_buf_dev.vk_buffer(), tile_buf.vk_buffer()],
|
&[
|
||||||
|
pathseg_buf.vk_buffer(),
|
||||||
|
tile_alloc_buf_dev.vk_buffer(),
|
||||||
|
tile_buf.vk_buffer(),
|
||||||
|
],
|
||||||
&[],
|
&[],
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
@ -237,7 +245,11 @@ impl Renderer {
|
||||||
session.create_simple_compute_pipeline(backdrop_alloc_code, 3, 0)?;
|
session.create_simple_compute_pipeline(backdrop_alloc_code, 3, 0)?;
|
||||||
let backdrop_ds = session.create_descriptor_set(
|
let backdrop_ds = session.create_descriptor_set(
|
||||||
&backdrop_pipeline,
|
&backdrop_pipeline,
|
||||||
&[anno_buf.vk_buffer(), tile_alloc_buf_dev.vk_buffer(), tile_buf.vk_buffer()],
|
&[
|
||||||
|
anno_buf.vk_buffer(),
|
||||||
|
tile_alloc_buf_dev.vk_buffer(),
|
||||||
|
tile_buf.vk_buffer(),
|
||||||
|
],
|
||||||
&[],
|
&[],
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
@ -251,7 +263,11 @@ impl Renderer {
|
||||||
let bin_pipeline = session.create_simple_compute_pipeline(bin_code, 3, 0)?;
|
let bin_pipeline = session.create_simple_compute_pipeline(bin_code, 3, 0)?;
|
||||||
let bin_ds = session.create_descriptor_set(
|
let bin_ds = session.create_descriptor_set(
|
||||||
&bin_pipeline,
|
&bin_pipeline,
|
||||||
&[anno_buf.vk_buffer(), bin_alloc_buf_dev.vk_buffer(), bin_buf.vk_buffer()],
|
&[
|
||||||
|
anno_buf.vk_buffer(),
|
||||||
|
bin_alloc_buf_dev.vk_buffer(),
|
||||||
|
bin_buf.vk_buffer(),
|
||||||
|
],
|
||||||
&[],
|
&[],
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
@ -259,9 +275,7 @@ impl Renderer {
|
||||||
let coarse_alloc_buf_dev = session.create_buffer(8, dev)?;
|
let coarse_alloc_buf_dev = session.create_buffer(8, dev)?;
|
||||||
|
|
||||||
let coarse_alloc_start = WIDTH_IN_TILES * HEIGHT_IN_TILES * PTCL_INITIAL_ALLOC;
|
let coarse_alloc_start = WIDTH_IN_TILES * HEIGHT_IN_TILES * PTCL_INITIAL_ALLOC;
|
||||||
coarse_alloc_buf_host.write(
|
coarse_alloc_buf_host.write(&[n_paths as u32, coarse_alloc_start as u32])?;
|
||||||
&[n_paths as u32, coarse_alloc_start as u32],
|
|
||||||
)?;
|
|
||||||
let coarse_code = include_bytes!("../shader/coarse.spv");
|
let coarse_code = include_bytes!("../shader/coarse.spv");
|
||||||
let coarse_pipeline = session.create_simple_compute_pipeline(coarse_code, 5, 0)?;
|
let coarse_pipeline = session.create_simple_compute_pipeline(coarse_code, 5, 0)?;
|
||||||
let coarse_ds = session.create_descriptor_set(
|
let coarse_ds = session.create_descriptor_set(
|
||||||
|
@ -278,8 +292,11 @@ impl Renderer {
|
||||||
|
|
||||||
let k4_code = include_bytes!("../shader/kernel4.spv");
|
let k4_code = include_bytes!("../shader/kernel4.spv");
|
||||||
let k4_pipeline = session.create_simple_compute_pipeline(k4_code, 2, 1)?;
|
let k4_pipeline = session.create_simple_compute_pipeline(k4_code, 2, 1)?;
|
||||||
let k4_ds =
|
let k4_ds = session.create_descriptor_set(
|
||||||
session.create_descriptor_set(&k4_pipeline, &[ptcl_buf.vk_buffer(), tile_buf.vk_buffer()], &[image_dev.vk_image()])?;
|
&k4_pipeline,
|
||||||
|
&[ptcl_buf.vk_buffer(), tile_buf.vk_buffer()],
|
||||||
|
&[image_dev.vk_image()],
|
||||||
|
)?;
|
||||||
|
|
||||||
Ok(Renderer {
|
Ok(Renderer {
|
||||||
scene_buf,
|
scene_buf,
|
||||||
|
@ -398,4 +415,41 @@ impl Renderer {
|
||||||
ImageLayout::BlitSrc,
|
ImageLayout::BlitSrc,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn make_image(
|
||||||
|
session: &hub::Session,
|
||||||
|
width: usize,
|
||||||
|
height: usize,
|
||||||
|
buf: &[u8],
|
||||||
|
format: ImageFormat,
|
||||||
|
) -> Result<hub::Image, Error> {
|
||||||
|
unsafe {
|
||||||
|
if format != ImageFormat::RgbaPremul {
|
||||||
|
return Err("unsupported image format".into());
|
||||||
|
}
|
||||||
|
let host_mem_flags = MemFlags::host_coherent();
|
||||||
|
let dev_mem_flags = MemFlags::device_local();
|
||||||
|
let mut buffer = session.create_buffer(buf.len() as u64, host_mem_flags)?;
|
||||||
|
buffer.write(buf)?;
|
||||||
|
let image =
|
||||||
|
session.create_image2d(width.try_into()?, height.try_into()?, dev_mem_flags)?;
|
||||||
|
let mut cmd_buf = session.cmd_buf()?;
|
||||||
|
cmd_buf.begin();
|
||||||
|
cmd_buf.image_barrier(
|
||||||
|
image.vk_image(),
|
||||||
|
ImageLayout::Undefined,
|
||||||
|
ImageLayout::BlitDst,
|
||||||
|
);
|
||||||
|
cmd_buf.copy_buffer_to_image(buffer.vk_buffer(), image.vk_image());
|
||||||
|
// TODO: instead of General, we might want ShaderReadOnly
|
||||||
|
cmd_buf.image_barrier(image.vk_image(), ImageLayout::BlitDst, ImageLayout::General);
|
||||||
|
cmd_buf.finish();
|
||||||
|
// Make sure not to drop the buffer and image until the command buffer completes.
|
||||||
|
cmd_buf.add_resource(&buffer);
|
||||||
|
cmd_buf.add_resource(&image);
|
||||||
|
let _ = session.run_cmd_buf(cmd_buf, &[], &[]);
|
||||||
|
// We let the session reclaim the fence.
|
||||||
|
Ok(image)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue