mirror of
https://github.com/italicsjenga/vello.git
synced 2025-01-10 12:41:30 +11:00
Migrate to BufferUsage
Adopt the BufferUsage concept from WebGPU, and replace MemFlags, which is inadequate.
This commit is contained in:
parent
34d8fa358b
commit
e9a8b4643b
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -849,6 +849,7 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"ash",
|
||||
"ash-window",
|
||||
"bitflags",
|
||||
"raw-window-handle",
|
||||
]
|
||||
|
||||
|
|
|
@ -10,3 +10,4 @@ edition = "2018"
|
|||
ash = "0.31"
|
||||
ash-window = "0.5"
|
||||
raw-window-handle = "0.3"
|
||||
bitflags = "1.2.1"
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
use piet_gpu_hal::hub;
|
||||
use piet_gpu_hal::vulkan::VkInstance;
|
||||
use piet_gpu_hal::{CmdBuf, MemFlags};
|
||||
use piet_gpu_hal::{BufferUsage, CmdBuf};
|
||||
|
||||
fn main() {
|
||||
let (instance, _) = VkInstance::new(None).unwrap();
|
||||
unsafe {
|
||||
let device = instance.device(None).unwrap();
|
||||
let session = hub::Session::new(device);
|
||||
let mem_flags = MemFlags::host_coherent();
|
||||
let usage = BufferUsage::MAP_READ | BufferUsage::MAP_WRITE | BufferUsage::STORAGE;
|
||||
let src = (0..256).map(|x| x + 1).collect::<Vec<u32>>();
|
||||
let mut buffer = session
|
||||
.create_buffer(std::mem::size_of_val(&src[..]) as u64, mem_flags)
|
||||
.create_buffer(std::mem::size_of_val(&src[..]) as u64, usage)
|
||||
.unwrap();
|
||||
buffer.write(&src).unwrap();
|
||||
let code = include_bytes!("./shader/collatz.spv");
|
||||
|
|
|
@ -10,9 +10,8 @@ use std::sync::{Arc, Mutex, Weak};
|
|||
use crate::vulkan;
|
||||
use crate::DescriptorSetBuilder as DescriptorSetBuilderTrait;
|
||||
use crate::PipelineBuilder as PipelineBuilderTrait;
|
||||
use crate::{Device, Error, GpuInfo, SamplerParams};
|
||||
use crate::{BufferUsage, Device, Error, GpuInfo, SamplerParams};
|
||||
|
||||
pub type MemFlags = <vulkan::VkDevice as Device>::MemFlags;
|
||||
pub type Semaphore = <vulkan::VkDevice as Device>::Semaphore;
|
||||
pub type Pipeline = <vulkan::VkDevice as Device>::Pipeline;
|
||||
pub type DescriptorSet = <vulkan::VkDevice as Device>::DescriptorSet;
|
||||
|
@ -143,8 +142,8 @@ impl Session {
|
|||
))
|
||||
}
|
||||
|
||||
pub fn create_buffer(&self, size: u64, mem_flags: MemFlags) -> Result<Buffer, Error> {
|
||||
let buffer = self.0.device.create_buffer(size, mem_flags)?;
|
||||
pub fn create_buffer(&self, size: u64, usage: BufferUsage) -> Result<Buffer, Error> {
|
||||
let buffer = self.0.device.create_buffer(size, usage)?;
|
||||
Ok(Buffer(Arc::new(BufferInner {
|
||||
buffer,
|
||||
session: Arc::downgrade(&self.0),
|
||||
|
@ -155,9 +154,8 @@ impl Session {
|
|||
&self,
|
||||
width: u32,
|
||||
height: u32,
|
||||
mem_flags: MemFlags,
|
||||
) -> Result<Image, Error> {
|
||||
let image = self.0.device.create_image2d(width, height, mem_flags)?;
|
||||
let image = self.0.device.create_image2d(width, height)?;
|
||||
Ok(Image(Arc::new(ImageInner {
|
||||
image,
|
||||
session: Arc::downgrade(&self.0),
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
///
|
||||
/// This abstraction is inspired by gfx-hal, but is specialized to the needs of piet-gpu.
|
||||
/// In time, it may go away and be replaced by either gfx-hal or wgpu.
|
||||
|
||||
use bitflags::bitflags;
|
||||
|
||||
pub mod hub;
|
||||
|
||||
pub mod vulkan;
|
||||
|
@ -29,6 +32,25 @@ pub enum SamplerParams {
|
|||
Linear,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// The intended usage for this buffer.
|
||||
pub struct BufferUsage: u32 {
|
||||
/// The buffer can be mapped for reading CPU-side.
|
||||
const MAP_READ = 0x1;
|
||||
/// The buffer can be mapped for writing CPU-side.
|
||||
const MAP_WRITE = 0x2;
|
||||
/// The buffer can be copied from.
|
||||
const COPY_SRC = 0x4;
|
||||
/// The buffer can be copied to.
|
||||
const COPY_DST = 0x8;
|
||||
/// The buffer can be bound to a compute shader.
|
||||
const STORAGE = 0x80;
|
||||
/// The buffer can be used to store the results of queries.
|
||||
const QUERY_RESOLVE = 0x200;
|
||||
// May add other types.
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
/// Information about the GPU.
|
||||
pub struct GpuInfo {
|
||||
|
@ -55,7 +77,6 @@ pub struct SubgroupSize {
|
|||
pub trait Device: Sized {
|
||||
type Buffer: 'static;
|
||||
type Image;
|
||||
type MemFlags: MemFlags;
|
||||
type Pipeline;
|
||||
type DescriptorSet;
|
||||
type QueryPool;
|
||||
|
@ -72,7 +93,7 @@ pub trait Device: Sized {
|
|||
/// the info.
|
||||
fn query_gpu_info(&self) -> GpuInfo;
|
||||
|
||||
fn create_buffer(&self, size: u64, mem_flags: Self::MemFlags) -> Result<Self::Buffer, Error>;
|
||||
fn create_buffer(&self, size: u64, usage: BufferUsage) -> Result<Self::Buffer, Error>;
|
||||
|
||||
/// Destroy a buffer.
|
||||
///
|
||||
|
@ -86,7 +107,6 @@ pub trait Device: Sized {
|
|||
&self,
|
||||
width: u32,
|
||||
height: u32,
|
||||
mem_flags: Self::MemFlags,
|
||||
) -> Result<Self::Image, Error>;
|
||||
|
||||
/// Destroy an image.
|
||||
|
|
|
@ -9,7 +9,7 @@ use ash::extensions::{ext::DebugUtils, khr};
|
|||
use ash::version::{DeviceV1_0, EntryV1_0, InstanceV1_0, InstanceV1_1};
|
||||
use ash::{vk, Device, Entry, Instance};
|
||||
|
||||
use crate::{Device as DeviceTrait, Error, GpuInfo, ImageLayout, SamplerParams, SubgroupSize};
|
||||
use crate::{BufferUsage, Device as DeviceTrait, Error, GpuInfo, ImageLayout, SamplerParams, SubgroupSize};
|
||||
|
||||
pub struct VkInstance {
|
||||
/// Retain the dynamic lib.
|
||||
|
@ -447,7 +447,6 @@ impl crate::Device for VkDevice {
|
|||
type DescriptorSet = DescriptorSet;
|
||||
type Pipeline = Pipeline;
|
||||
type QueryPool = QueryPool;
|
||||
type MemFlags = MemFlags;
|
||||
type Fence = vk::Fence;
|
||||
type Semaphore = vk::Semaphore;
|
||||
type PipelineBuilder = PipelineBuilder;
|
||||
|
@ -458,9 +457,19 @@ impl crate::Device for VkDevice {
|
|||
self.gpu_info.clone()
|
||||
}
|
||||
|
||||
fn create_buffer(&self, size: u64, mem_flags: MemFlags) -> Result<Buffer, Error> {
|
||||
fn create_buffer(&self, size: u64, usage: BufferUsage) -> Result<Buffer, Error> {
|
||||
unsafe {
|
||||
let device = &self.device.device;
|
||||
let mut vk_usage = vk::BufferUsageFlags::empty();
|
||||
if usage.contains(BufferUsage::STORAGE) {
|
||||
vk_usage |= vk::BufferUsageFlags::STORAGE_BUFFER;
|
||||
}
|
||||
if usage.contains(BufferUsage::COPY_SRC) {
|
||||
vk_usage |= vk::BufferUsageFlags::TRANSFER_SRC;
|
||||
}
|
||||
if usage.contains(BufferUsage::COPY_DST) {
|
||||
vk_usage |= vk::BufferUsageFlags::TRANSFER_DST;
|
||||
}
|
||||
let buffer = device.create_buffer(
|
||||
&vk::BufferCreateInfo::builder()
|
||||
.size(size)
|
||||
|
@ -473,9 +482,10 @@ impl crate::Device for VkDevice {
|
|||
None,
|
||||
)?;
|
||||
let mem_requirements = device.get_buffer_memory_requirements(buffer);
|
||||
let mem_flags = memory_property_flags_for_usage(usage);
|
||||
let mem_type = find_memory_type(
|
||||
mem_requirements.memory_type_bits,
|
||||
mem_flags.0,
|
||||
mem_flags,
|
||||
&self.device_mem_props,
|
||||
)
|
||||
.unwrap(); // TODO: proper error
|
||||
|
@ -505,7 +515,6 @@ impl crate::Device for VkDevice {
|
|||
&self,
|
||||
width: u32,
|
||||
height: u32,
|
||||
mem_flags: Self::MemFlags,
|
||||
) -> Result<Self::Image, Error> {
|
||||
let device = &self.device.device;
|
||||
let extent = vk::Extent3D {
|
||||
|
@ -533,9 +542,10 @@ impl crate::Device for VkDevice {
|
|||
None,
|
||||
)?;
|
||||
let mem_requirements = device.get_image_memory_requirements(image);
|
||||
let mem_flags = vk::MemoryPropertyFlags::DEVICE_LOCAL;
|
||||
let mem_type = find_memory_type(
|
||||
mem_requirements.memory_type_bits,
|
||||
mem_flags.0,
|
||||
mem_flags,
|
||||
&self.device_mem_props,
|
||||
)
|
||||
.unwrap(); // TODO: proper error
|
||||
|
@ -1002,16 +1012,6 @@ impl crate::CmdBuf<VkDevice> for CmdBuf {
|
|||
}
|
||||
}
|
||||
|
||||
impl crate::MemFlags for MemFlags {
|
||||
fn device_local() -> Self {
|
||||
MemFlags(vk::MemoryPropertyFlags::DEVICE_LOCAL)
|
||||
}
|
||||
|
||||
fn host_coherent() -> Self {
|
||||
MemFlags(vk::MemoryPropertyFlags::HOST_VISIBLE | vk::MemoryPropertyFlags::HOST_COHERENT)
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::PipelineBuilder<VkDevice> for PipelineBuilder {
|
||||
fn add_buffers(&mut self, n_buffers: u32) {
|
||||
let start = self.bindings.len() as u32;
|
||||
|
@ -1368,6 +1368,16 @@ unsafe fn choose_compute_device(
|
|||
None
|
||||
}
|
||||
|
||||
fn memory_property_flags_for_usage(usage: BufferUsage) -> vk::MemoryPropertyFlags {
|
||||
if usage.intersects(BufferUsage::MAP_READ | BufferUsage::MAP_WRITE) {
|
||||
vk::MemoryPropertyFlags::HOST_VISIBLE | vk::MemoryPropertyFlags::HOST_COHERENT
|
||||
} else {
|
||||
vk::MemoryPropertyFlags::DEVICE_LOCAL
|
||||
}
|
||||
}
|
||||
|
||||
// This could get more sophisticated about asking for CACHED when appropriate, but is
|
||||
// probably going to get replaced by a gpu-alloc solution anyway.
|
||||
fn find_memory_type(
|
||||
memory_type_bits: u32,
|
||||
property_flags: vk::MemoryPropertyFlags,
|
||||
|
|
|
@ -6,7 +6,7 @@ use clap::{App, Arg};
|
|||
|
||||
use piet_gpu_hal::hub;
|
||||
use piet_gpu_hal::vulkan::VkInstance;
|
||||
use piet_gpu_hal::{CmdBuf, Error, MemFlags};
|
||||
use piet_gpu_hal::{BufferUsage, CmdBuf, Error};
|
||||
|
||||
use piet_gpu::{render_scene, render_svg, PietGpuRenderContext, Renderer, HEIGHT, WIDTH};
|
||||
|
||||
|
@ -253,8 +253,9 @@ fn main() -> Result<(), Error> {
|
|||
//dump_scene(&scene);
|
||||
|
||||
let renderer = Renderer::new(&session, scene, n_paths, n_pathseg, n_trans)?;
|
||||
let image_usage = BufferUsage::MAP_READ | BufferUsage::COPY_DST;
|
||||
let image_buf =
|
||||
session.create_buffer((WIDTH * HEIGHT * 4) as u64, MemFlags::host_coherent())?;
|
||||
session.create_buffer((WIDTH * HEIGHT * 4) as u64, image_usage)?;
|
||||
|
||||
cmd_buf.begin();
|
||||
renderer.record(&mut cmd_buf, &query_pool);
|
||||
|
|
|
@ -13,7 +13,7 @@ use piet::{Color, ImageFormat, RenderContext};
|
|||
use piet_gpu_types::encoder::Encode;
|
||||
|
||||
use piet_gpu_hal::hub;
|
||||
use piet_gpu_hal::{CmdBuf, Error, ImageLayout, MemFlags};
|
||||
use piet_gpu_hal::{BufferUsage, CmdBuf, Error, ImageLayout};
|
||||
|
||||
use pico_svg::PicoSvg;
|
||||
|
||||
|
@ -237,8 +237,8 @@ impl Renderer {
|
|||
n_pathseg: usize,
|
||||
n_trans: usize,
|
||||
) -> Result<Self, Error> {
|
||||
let host = MemFlags::host_coherent();
|
||||
let dev = MemFlags::device_local();
|
||||
let dev = BufferUsage::STORAGE | BufferUsage::COPY_DST;
|
||||
let host_upload = BufferUsage::MAP_WRITE | BufferUsage::COPY_SRC;
|
||||
|
||||
let n_elements = scene.len() / piet_gpu_types::scene::Element::fixed_size();
|
||||
println!(
|
||||
|
@ -247,7 +247,7 @@ impl Renderer {
|
|||
);
|
||||
|
||||
let mut scene_buf_host = session
|
||||
.create_buffer(std::mem::size_of_val(&scene[..]) as u64, host)
|
||||
.create_buffer(std::mem::size_of_val(&scene[..]) as u64, host_upload)
|
||||
.unwrap();
|
||||
let scene_buf_dev = session
|
||||
.create_buffer(std::mem::size_of_val(&scene[..]) as u64, dev)
|
||||
|
@ -255,10 +255,10 @@ impl Renderer {
|
|||
scene_buf_host.write(&scene)?;
|
||||
|
||||
let state_buf = session.create_buffer(1 * 1024 * 1024, dev)?;
|
||||
let image_dev = session.create_image2d(WIDTH as u32, HEIGHT as u32, dev)?;
|
||||
let image_dev = session.create_image2d(WIDTH as u32, HEIGHT as u32)?;
|
||||
|
||||
const CONFIG_SIZE: u64 = 10 * 4; // Size of Config in setup.h.
|
||||
let mut config_buf_host = session.create_buffer(CONFIG_SIZE, host)?;
|
||||
let mut config_buf_host = session.create_buffer(CONFIG_SIZE, host_upload)?;
|
||||
let config_buf_dev = session.create_buffer(CONFIG_SIZE, dev)?;
|
||||
|
||||
// TODO: constants
|
||||
|
@ -293,7 +293,7 @@ impl Renderer {
|
|||
trans_base as u32,
|
||||
])?;
|
||||
|
||||
let mut memory_buf_host = session.create_buffer(2 * 4, host)?;
|
||||
let mut memory_buf_host = session.create_buffer(2 * 4, host_upload)?;
|
||||
let memory_buf_dev = session.create_buffer(128 * 1024 * 1024, dev)?;
|
||||
memory_buf_host.write(&[alloc as u32, 0 /* Overflow flag */])?;
|
||||
|
||||
|
@ -485,12 +485,11 @@ impl Renderer {
|
|||
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)?;
|
||||
let host_upload = BufferUsage::MAP_WRITE | BufferUsage::COPY_SRC;
|
||||
let mut buffer = session.create_buffer(buf.len() as u64, host_upload)?;
|
||||
buffer.write(buf)?;
|
||||
let image =
|
||||
session.create_image2d(width.try_into()?, height.try_into()?, dev_mem_flags)?;
|
||||
session.create_image2d(width.try_into()?, height.try_into()?)?;
|
||||
let mut cmd_buf = session.cmd_buf()?;
|
||||
cmd_buf.begin();
|
||||
cmd_buf.image_barrier(
|
||||
|
|
Loading…
Reference in a new issue