mirror of
https://github.com/italicsjenga/vello.git
synced 2025-01-10 20:51:29 +11:00
Wire hub to mux
Make the hub abstraction connect to the mux, rather than directly to the Vulkan back-end. As of this commit, both command line and winit examples work (on Vulkan). In theory it should be possible to get them working on Dx12 as well by translating the shader code, but there's a lot that can go wrong. This commit also contains a bunch of changes to mux to make conditional compilation of match arms work, and new methods to support swapchain.
This commit is contained in:
parent
d15994fe44
commit
2ecfc7a414
|
@ -1,16 +1,16 @@
|
||||||
use piet_gpu_hal::hub;
|
use piet_gpu_hal::hub;
|
||||||
use piet_gpu_hal::vulkan::VkInstance;
|
use piet_gpu_hal::mux::{Instance, ShaderCode};
|
||||||
use piet_gpu_hal::{BufferUsage, CmdBuf};
|
use piet_gpu_hal::BufferUsage;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let (instance, _) = VkInstance::new(None).unwrap();
|
let (instance, _) = Instance::new(None).unwrap();
|
||||||
unsafe {
|
unsafe {
|
||||||
let device = instance.device(None).unwrap();
|
let device = instance.device(None).unwrap();
|
||||||
let session = hub::Session::new(device);
|
let session = hub::Session::new(device);
|
||||||
let usage = BufferUsage::MAP_READ | BufferUsage::STORAGE;
|
let usage = BufferUsage::MAP_READ | BufferUsage::STORAGE;
|
||||||
let src = (0..256).map(|x| x + 1).collect::<Vec<u32>>();
|
let src = (0..256).map(|x| x + 1).collect::<Vec<u32>>();
|
||||||
let buffer = session.create_buffer_init(&src, usage).unwrap();
|
let buffer = session.create_buffer_init(&src, usage).unwrap();
|
||||||
let code = include_bytes!("./shader/collatz.spv");
|
let code = ShaderCode::Spv(include_bytes!("./shader/collatz.spv"));
|
||||||
let pipeline = session.create_simple_compute_pipeline(code, 1).unwrap();
|
let pipeline = session.create_simple_compute_pipeline(code, 1).unwrap();
|
||||||
let descriptor_set = session
|
let descriptor_set = session
|
||||||
.create_simple_descriptor_set(&pipeline, &[&buffer])
|
.create_simple_descriptor_set(&pipeline, &[&buffer])
|
||||||
|
|
|
@ -24,6 +24,9 @@ pub struct Dx12Instance {
|
||||||
// TODO
|
// TODO
|
||||||
pub struct Dx12Surface;
|
pub struct Dx12Surface;
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
pub struct Dx12Swapchain;
|
||||||
|
|
||||||
pub struct Dx12Device {
|
pub struct Dx12Device {
|
||||||
device: Device,
|
device: Device,
|
||||||
command_allocator: CommandAllocator,
|
command_allocator: CommandAllocator,
|
||||||
|
@ -35,7 +38,7 @@ pub struct Dx12Device {
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Buffer {
|
pub struct Buffer {
|
||||||
resource: Resource,
|
resource: Resource,
|
||||||
size: u64,
|
pub size: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -331,7 +334,7 @@ impl crate::Device for Dx12Device {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn get_fence_status(&self, fence: Self::Fence) -> Result<bool, Error> {
|
unsafe fn get_fence_status(&self, fence: &Self::Fence) -> Result<bool, Error> {
|
||||||
let fence_val = fence.fence.get_value();
|
let fence_val = fence.fence.get_value();
|
||||||
Ok(fence_val == fence.val.get())
|
Ok(fence_val == fence.val.get())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,35 +1,28 @@
|
||||||
//! A convenience layer on top of raw hal.
|
//! A somewhat higher level GPU abstraction.
|
||||||
//!
|
//!
|
||||||
//! This layer takes care of some lifetime and synchronization bookkeeping.
|
//! This layer is on top of the lower-level layer that multiplexes different
|
||||||
//! It is likely that it will also take care of compile time and runtime
|
//! back-ends. It handles details such as managing staging buffers for creating
|
||||||
//! negotiation of backends (Vulkan, DX12), but right now it's Vulkan-only.
|
//! buffers with initial content, deferring dropping of resources until command
|
||||||
|
//! submission is complete, and a bit more. These conveniences might expand
|
||||||
|
//! even more in time.
|
||||||
|
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::sync::{Arc, Mutex, Weak};
|
use std::sync::{Arc, Mutex, Weak};
|
||||||
|
|
||||||
use crate::vulkan;
|
use smallvec::SmallVec;
|
||||||
use crate::CmdBuf as CmdBufTrait;
|
|
||||||
use crate::DescriptorSetBuilder as DescriptorSetBuilderTrait;
|
|
||||||
use crate::PipelineBuilder as PipelineBuilderTrait;
|
|
||||||
use crate::{BufferUsage, Device, Error, GpuInfo, SamplerParams};
|
|
||||||
|
|
||||||
pub type Semaphore = <vulkan::VkDevice as Device>::Semaphore;
|
use crate::mux;
|
||||||
pub type Pipeline = <vulkan::VkDevice as Device>::Pipeline;
|
|
||||||
pub type DescriptorSet = <vulkan::VkDevice as Device>::DescriptorSet;
|
|
||||||
pub type QueryPool = <vulkan::VkDevice as Device>::QueryPool;
|
|
||||||
pub type Sampler = <vulkan::VkDevice as Device>::Sampler;
|
|
||||||
|
|
||||||
type Fence = <vulkan::VkDevice as Device>::Fence;
|
use crate::{BufferUsage, Error, GpuInfo, SamplerParams};
|
||||||
|
|
||||||
type VkImage = <vulkan::VkDevice as Device>::Image;
|
pub use crate::mux::{DescriptorSet, Fence, Pipeline, QueryPool, Sampler, Semaphore, ShaderCode};
|
||||||
type VkBuffer = <vulkan::VkDevice as Device>::Buffer;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Session(Arc<SessionInner>);
|
pub struct Session(Arc<SessionInner>);
|
||||||
|
|
||||||
struct SessionInner {
|
struct SessionInner {
|
||||||
device: vulkan::VkDevice,
|
device: mux::Device,
|
||||||
cmd_buf_pool: Mutex<Vec<(vulkan::CmdBuf, Fence)>>,
|
cmd_buf_pool: Mutex<Vec<(mux::CmdBuf, Fence)>>,
|
||||||
/// Command buffers that are still pending (so resources can't be freed).
|
/// Command buffers that are still pending (so resources can't be freed).
|
||||||
pending: Mutex<Vec<SubmittedCmdBufInner>>,
|
pending: Mutex<Vec<SubmittedCmdBufInner>>,
|
||||||
/// A command buffer that is used for copying from staging buffers.
|
/// A command buffer that is used for copying from staging buffers.
|
||||||
|
@ -38,7 +31,7 @@ struct SessionInner {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CmdBuf {
|
pub struct CmdBuf {
|
||||||
cmd_buf: vulkan::CmdBuf,
|
cmd_buf: mux::CmdBuf,
|
||||||
fence: Fence,
|
fence: Fence,
|
||||||
resources: Vec<RetainResource>,
|
resources: Vec<RetainResource>,
|
||||||
session: Weak<SessionInner>,
|
session: Weak<SessionInner>,
|
||||||
|
@ -50,7 +43,7 @@ pub struct SubmittedCmdBuf(Option<SubmittedCmdBufInner>, Weak<SessionInner>);
|
||||||
struct SubmittedCmdBufInner {
|
struct SubmittedCmdBufInner {
|
||||||
// It's inconsistent, cmd_buf is unpacked, staging_cmd_buf isn't. Probably
|
// It's inconsistent, cmd_buf is unpacked, staging_cmd_buf isn't. Probably
|
||||||
// better to chose one or the other.
|
// better to chose one or the other.
|
||||||
cmd_buf: vulkan::CmdBuf,
|
cmd_buf: mux::CmdBuf,
|
||||||
fence: Fence,
|
fence: Fence,
|
||||||
resources: Vec<RetainResource>,
|
resources: Vec<RetainResource>,
|
||||||
staging_cmd_buf: Option<CmdBuf>,
|
staging_cmd_buf: Option<CmdBuf>,
|
||||||
|
@ -60,7 +53,7 @@ struct SubmittedCmdBufInner {
|
||||||
pub struct Image(Arc<ImageInner>);
|
pub struct Image(Arc<ImageInner>);
|
||||||
|
|
||||||
struct ImageInner {
|
struct ImageInner {
|
||||||
image: VkImage,
|
image: mux::Image,
|
||||||
session: Weak<SessionInner>,
|
session: Weak<SessionInner>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,13 +61,13 @@ struct ImageInner {
|
||||||
pub struct Buffer(Arc<BufferInner>);
|
pub struct Buffer(Arc<BufferInner>);
|
||||||
|
|
||||||
struct BufferInner {
|
struct BufferInner {
|
||||||
buffer: VkBuffer,
|
buffer: mux::Buffer,
|
||||||
session: Weak<SessionInner>,
|
session: Weak<SessionInner>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PipelineBuilder(vulkan::PipelineBuilder);
|
pub struct PipelineBuilder(mux::PipelineBuilder);
|
||||||
|
|
||||||
pub struct DescriptorSetBuilder(vulkan::DescriptorSetBuilder);
|
pub struct DescriptorSetBuilder(mux::DescriptorSetBuilder);
|
||||||
|
|
||||||
/// Data types that can be stored in a GPU buffer.
|
/// Data types that can be stored in a GPU buffer.
|
||||||
pub unsafe trait PlainData {}
|
pub unsafe trait PlainData {}
|
||||||
|
@ -97,7 +90,7 @@ pub enum RetainResource {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Session {
|
impl Session {
|
||||||
pub fn new(device: vulkan::VkDevice) -> Session {
|
pub fn new(device: mux::Device) -> Session {
|
||||||
let gpu_info = device.query_gpu_info();
|
let gpu_info = device.query_gpu_info();
|
||||||
Session(Arc::new(SessionInner {
|
Session(Arc::new(SessionInner {
|
||||||
device,
|
device,
|
||||||
|
@ -130,7 +123,7 @@ impl Session {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while i < pending.len() {
|
while i < pending.len() {
|
||||||
if let Ok(true) = self.0.device.get_fence_status(pending[i].fence) {
|
if let Ok(true) = self.0.device.get_fence_status(&pending[i].fence) {
|
||||||
let item = pending.swap_remove(i);
|
let item = pending.swap_remove(i);
|
||||||
// TODO: wait is superfluous, can just reset
|
// TODO: wait is superfluous, can just reset
|
||||||
let _ = self.0.device.wait_and_reset(&[&item.fence]);
|
let _ = self.0.device.wait_and_reset(&[&item.fence]);
|
||||||
|
@ -222,7 +215,7 @@ impl Session {
|
||||||
let create_buf = self.create_buffer(size, create_usage)?;
|
let create_buf = self.create_buffer(size, create_usage)?;
|
||||||
self.0
|
self.0
|
||||||
.device
|
.device
|
||||||
.write_buffer(&create_buf.vk_buffer(), contents, 0, size)?;
|
.write_buffer(&create_buf.mux_buffer(), contents, 0, size)?;
|
||||||
if use_staging_buffer {
|
if use_staging_buffer {
|
||||||
let buf = self.create_buffer(size, usage | BufferUsage::COPY_DST)?;
|
let buf = self.create_buffer(size, usage | BufferUsage::COPY_DST)?;
|
||||||
let mut staging_cmd_buf = self.0.staging_cmd_buf.lock().unwrap();
|
let mut staging_cmd_buf = self.0.staging_cmd_buf.lock().unwrap();
|
||||||
|
@ -232,8 +225,8 @@ impl Session {
|
||||||
*staging_cmd_buf = Some(cmd_buf);
|
*staging_cmd_buf = Some(cmd_buf);
|
||||||
}
|
}
|
||||||
let staging_cmd_buf = staging_cmd_buf.as_mut().unwrap();
|
let staging_cmd_buf = staging_cmd_buf.as_mut().unwrap();
|
||||||
// This will ensure the staging buffer is deallocated. It would be nice to
|
// This will ensure the staging buffer is deallocated.
|
||||||
staging_cmd_buf.copy_buffer(create_buf.vk_buffer(), buf.vk_buffer());
|
staging_cmd_buf.copy_buffer(create_buf.mux_buffer(), buf.mux_buffer());
|
||||||
staging_cmd_buf.add_resource(create_buf);
|
staging_cmd_buf.add_resource(create_buf);
|
||||||
Ok(buf)
|
Ok(buf)
|
||||||
} else {
|
} else {
|
||||||
|
@ -256,9 +249,9 @@ impl Session {
|
||||||
/// This creates a pipeline that operates on some buffers and images.
|
/// This creates a pipeline that operates on some buffers and images.
|
||||||
///
|
///
|
||||||
/// The descriptor set layout is just some number of storage buffers and storage images (this might change).
|
/// The descriptor set layout is just some number of storage buffers and storage images (this might change).
|
||||||
pub unsafe fn create_simple_compute_pipeline(
|
pub unsafe fn create_simple_compute_pipeline<'a>(
|
||||||
&self,
|
&self,
|
||||||
code: &[u8],
|
code: ShaderCode<'a>,
|
||||||
n_buffers: u32,
|
n_buffers: u32,
|
||||||
) -> Result<Pipeline, Error> {
|
) -> Result<Pipeline, Error> {
|
||||||
self.pipeline_builder()
|
self.pipeline_builder()
|
||||||
|
@ -295,7 +288,8 @@ impl Session {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn create_sampler(&self, params: SamplerParams) -> Result<Sampler, Error> {
|
pub unsafe fn create_sampler(&self, params: SamplerParams) -> Result<Sampler, Error> {
|
||||||
self.0.device.create_sampler(params)
|
todo!()
|
||||||
|
//self.0.device.create_sampler(params)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gpu_info(&self) -> &GpuInfo {
|
pub fn gpu_info(&self) -> &GpuInfo {
|
||||||
|
@ -366,10 +360,9 @@ impl Drop for ImageInner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// For now, we deref, but for runtime backend switching we'll need to wrap
|
// Probably migrate from deref here to wrapping all methods.
|
||||||
/// all methods.
|
|
||||||
impl std::ops::Deref for CmdBuf {
|
impl std::ops::Deref for CmdBuf {
|
||||||
type Target = vulkan::CmdBuf;
|
type Target = mux::CmdBuf;
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.cmd_buf
|
&self.cmd_buf
|
||||||
}
|
}
|
||||||
|
@ -382,13 +375,13 @@ impl std::ops::DerefMut for CmdBuf {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Image {
|
impl Image {
|
||||||
pub fn vk_image(&self) -> &vulkan::Image {
|
pub fn mux_image(&self) -> &mux::Image {
|
||||||
&self.0.image
|
&self.0.image
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Buffer {
|
impl Buffer {
|
||||||
pub fn vk_buffer(&self) -> &vulkan::Buffer {
|
pub fn mux_buffer(&self) -> &mux::Buffer {
|
||||||
&self.0.buffer
|
&self.0.buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -405,7 +398,7 @@ impl Buffer {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
pub unsafe fn read<T: PlainData>(&self, result: &mut Vec<T>) -> Result<(), Error> {
|
pub unsafe fn read<T: PlainData>(&self, result: &mut Vec<T>) -> Result<(), Error> {
|
||||||
let size = self.vk_buffer().size;
|
let size = self.mux_buffer().size();
|
||||||
let len = size as usize / std::mem::size_of::<T>();
|
let len = size as usize / std::mem::size_of::<T>();
|
||||||
if len > result.len() {
|
if len > result.len() {
|
||||||
result.reserve(len - result.len());
|
result.reserve(len - result.len());
|
||||||
|
@ -440,10 +433,10 @@ impl PipelineBuilder {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn create_compute_pipeline(
|
pub unsafe fn create_compute_pipeline<'a>(
|
||||||
self,
|
self,
|
||||||
session: &Session,
|
session: &Session,
|
||||||
code: &[u8],
|
code: ShaderCode<'a>,
|
||||||
) -> Result<Pipeline, Error> {
|
) -> Result<Pipeline, Error> {
|
||||||
self.0.create_compute_pipeline(&session.0.device, code)
|
self.0.create_compute_pipeline(&session.0.device, code)
|
||||||
}
|
}
|
||||||
|
@ -451,23 +444,29 @@ impl PipelineBuilder {
|
||||||
|
|
||||||
impl DescriptorSetBuilder {
|
impl DescriptorSetBuilder {
|
||||||
pub fn add_buffers<'a>(mut self, buffers: impl IntoRefs<'a, Buffer>) -> Self {
|
pub fn add_buffers<'a>(mut self, buffers: impl IntoRefs<'a, Buffer>) -> Self {
|
||||||
let vk_buffers = buffers
|
let mux_buffers = buffers
|
||||||
.into_refs()
|
.into_refs()
|
||||||
.map(|b| b.vk_buffer())
|
.map(|b| b.mux_buffer())
|
||||||
.collect::<Vec<_>>();
|
.collect::<SmallVec<[_; 8]>>();
|
||||||
self.0.add_buffers(&vk_buffers);
|
self.0.add_buffers(&mux_buffers);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_images<'a>(mut self, images: impl IntoRefs<'a, Image>) -> Self {
|
pub fn add_images<'a>(mut self, images: impl IntoRefs<'a, Image>) -> Self {
|
||||||
let vk_images = images.into_refs().map(|i| i.vk_image()).collect::<Vec<_>>();
|
let mux_images = images
|
||||||
self.0.add_images(&vk_images);
|
.into_refs()
|
||||||
|
.map(|i| i.mux_image())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
self.0.add_images(&mux_images);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_textures<'a>(mut self, images: impl IntoRefs<'a, Image>) -> Self {
|
pub fn add_textures<'a>(mut self, images: impl IntoRefs<'a, Image>) -> Self {
|
||||||
let vk_images = images.into_refs().map(|i| i.vk_image()).collect::<Vec<_>>();
|
let mux_images = images
|
||||||
self.0.add_textures(&vk_images);
|
.into_refs()
|
||||||
|
.map(|i| i.mux_image())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
self.0.add_textures(&mux_images);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,11 +12,11 @@ mod macros;
|
||||||
// TODO make this not pub
|
// TODO make this not pub
|
||||||
pub mod mux;
|
pub mod mux;
|
||||||
|
|
||||||
mux! {
|
mux_cfg! {
|
||||||
#[cfg(vk)]
|
#[cfg(vk)]
|
||||||
pub mod vulkan;
|
pub mod vulkan;
|
||||||
}
|
}
|
||||||
mux! {
|
mux_cfg! {
|
||||||
#[cfg(dx12)]
|
#[cfg(dx12)]
|
||||||
pub mod dx12;
|
pub mod dx12;
|
||||||
}
|
}
|
||||||
|
@ -229,7 +229,7 @@ pub trait Device: Sized {
|
||||||
unsafe fn create_semaphore(&self) -> Result<Self::Semaphore, Error>;
|
unsafe fn create_semaphore(&self) -> Result<Self::Semaphore, Error>;
|
||||||
unsafe fn create_fence(&self, signaled: bool) -> Result<Self::Fence, Error>;
|
unsafe fn create_fence(&self, signaled: bool) -> Result<Self::Fence, Error>;
|
||||||
unsafe fn wait_and_reset(&self, fences: &[&Self::Fence]) -> Result<(), Error>;
|
unsafe fn wait_and_reset(&self, fences: &[&Self::Fence]) -> Result<(), Error>;
|
||||||
unsafe fn get_fence_status(&self, fence: Self::Fence) -> Result<bool, Error>;
|
unsafe fn get_fence_status(&self, fence: &Self::Fence) -> Result<bool, Error>;
|
||||||
|
|
||||||
unsafe fn create_sampler(&self, params: SamplerParams) -> Result<Self::Sampler, Error>;
|
unsafe fn create_sampler(&self, params: SamplerParams) -> Result<Self::Sampler, Error>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
//! Macros, mostly to automate backend selection tedium.
|
//! Macros, mostly to automate backend selection tedium.
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! mux {
|
macro_rules! mux_cfg {
|
||||||
( #[cfg(vk)] $($tokens:tt)* ) => {
|
( #[cfg(vk)] $($tokens:tt)* ) => {
|
||||||
#[cfg(not(target_os="macos"))] $( $tokens )*
|
#[cfg(not(target_os="macos"))] $( $tokens )*
|
||||||
};
|
};
|
||||||
|
@ -41,7 +41,7 @@ macro_rules! mux_enum {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl $name {
|
impl $name {
|
||||||
$crate::mux! {
|
$crate::mux_cfg! {
|
||||||
#[cfg(vk)]
|
#[cfg(vk)]
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
fn vk(&self) -> &$vk {
|
fn vk(&self) -> &$vk {
|
||||||
|
@ -52,7 +52,7 @@ macro_rules! mux_enum {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$crate::mux! {
|
$crate::mux_cfg! {
|
||||||
#[cfg(dx12)]
|
#[cfg(dx12)]
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
fn dx12(&self) -> &$dx12 {
|
fn dx12(&self) -> &$dx12 {
|
||||||
|
@ -77,3 +77,28 @@ macro_rules! mux_device_enum {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! mux_match {
|
||||||
|
( $e:expr ;
|
||||||
|
$vkname:ident::Vk($vkvar:ident) => $vkblock: block
|
||||||
|
$dx12name:ident::Dx12($dx12var:ident) => $dx12block: block
|
||||||
|
) => {
|
||||||
|
match $e {
|
||||||
|
#[cfg(not(target_os="macos"))]
|
||||||
|
$vkname::Vk($vkvar) => $vkblock
|
||||||
|
#[cfg(target_os="windows")]
|
||||||
|
$dx12name::Dx12($dx12var) => $dx12block
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
( $e:expr ;
|
||||||
|
$vkname:ident::Vk($vkvar:ident) => $vkblock: expr,
|
||||||
|
$dx12name:ident::Dx12($dx12var:ident) => $dx12block: expr,
|
||||||
|
) => {
|
||||||
|
$crate::mux_match! { $e;
|
||||||
|
$vkname::Vk($vkvar) => { $vkblock }
|
||||||
|
$dx12name::Dx12($dx12var) => { $dx12block }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -18,8 +18,14 @@
|
||||||
|
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
use crate::dx12;
|
mux_cfg! {
|
||||||
|
#[cfg(vk)]
|
||||||
use crate::vulkan;
|
use crate::vulkan;
|
||||||
|
}
|
||||||
|
mux_cfg! {
|
||||||
|
#[cfg(dx12)]
|
||||||
|
use crate::dx12;
|
||||||
|
}
|
||||||
use crate::CmdBuf as CmdBufTrait;
|
use crate::CmdBuf as CmdBufTrait;
|
||||||
use crate::DescriptorSetBuilder as DescriptorSetBuilderTrait;
|
use crate::DescriptorSetBuilder as DescriptorSetBuilderTrait;
|
||||||
use crate::Device as DeviceTrait;
|
use crate::Device as DeviceTrait;
|
||||||
|
@ -50,6 +56,14 @@ mux_enum! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mux_enum! {
|
||||||
|
/// A surface, which can apply to one of multiple backends.
|
||||||
|
pub enum Swapchain {
|
||||||
|
Vk(vulkan::VkSwapchain),
|
||||||
|
Dx12(dx12::Dx12Swapchain),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mux_device_enum! { Buffer }
|
mux_device_enum! { Buffer }
|
||||||
mux_device_enum! { Image }
|
mux_device_enum! { Image }
|
||||||
mux_device_enum! { Fence }
|
mux_device_enum! { Fence }
|
||||||
|
@ -60,6 +74,7 @@ mux_device_enum! { DescriptorSetBuilder }
|
||||||
mux_device_enum! { DescriptorSet }
|
mux_device_enum! { DescriptorSet }
|
||||||
mux_device_enum! { CmdBuf }
|
mux_device_enum! { CmdBuf }
|
||||||
mux_device_enum! { QueryPool }
|
mux_device_enum! { QueryPool }
|
||||||
|
mux_device_enum! { Sampler }
|
||||||
|
|
||||||
/// The code for a shader, either as source or intermediate representation.
|
/// The code for a shader, either as source or intermediate representation.
|
||||||
pub enum ShaderCode<'a> {
|
pub enum ShaderCode<'a> {
|
||||||
|
@ -71,7 +86,7 @@ impl Instance {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
window_handle: Option<&dyn raw_window_handle::HasRawWindowHandle>,
|
window_handle: Option<&dyn raw_window_handle::HasRawWindowHandle>,
|
||||||
) -> Result<(Instance, Option<Surface>), Error> {
|
) -> Result<(Instance, Option<Surface>), Error> {
|
||||||
mux! {
|
mux_cfg! {
|
||||||
#[cfg(vk)]
|
#[cfg(vk)]
|
||||||
{
|
{
|
||||||
let result = vulkan::VkInstance::new(window_handle);
|
let result = vulkan::VkInstance::new(window_handle);
|
||||||
|
@ -80,7 +95,7 @@ impl Instance {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mux! {
|
mux_cfg! {
|
||||||
#[cfg(dx12)]
|
#[cfg(dx12)]
|
||||||
{
|
{
|
||||||
let result = dx12::Dx12Instance::new(window_handle);
|
let result = dx12::Dx12Instance::new(window_handle);
|
||||||
|
@ -94,11 +109,26 @@ impl Instance {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn device(&self, surface: Option<&Surface>) -> Result<Device, Error> {
|
pub unsafe fn device(&self, surface: Option<&Surface>) -> Result<Device, Error> {
|
||||||
match self {
|
mux_match! { self;
|
||||||
Instance::Vk(i) => i.device(surface.map(Surface::vk)).map(Device::Vk),
|
Instance::Vk(i) => i.device(surface.map(Surface::vk)).map(Device::Vk),
|
||||||
Instance::Dx12(i) => i.device(surface.map(Surface::dx12)).map(Device::Dx12),
|
Instance::Dx12(i) => i.device(surface.map(Surface::dx12)).map(Device::Dx12),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub unsafe fn swapchain(
|
||||||
|
&self,
|
||||||
|
width: usize,
|
||||||
|
height: usize,
|
||||||
|
device: &Device,
|
||||||
|
surface: &Surface,
|
||||||
|
) -> Result<Swapchain, Error> {
|
||||||
|
mux_match! { self;
|
||||||
|
Instance::Vk(i) => i
|
||||||
|
.swapchain(width, height, device.vk(), surface.vk())
|
||||||
|
.map(Swapchain::Vk),
|
||||||
|
Instance::Dx12(_i) => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is basically re-exporting the backend device trait, and we could do that,
|
// This is basically re-exporting the backend device trait, and we could do that,
|
||||||
|
@ -106,35 +136,49 @@ impl Instance {
|
||||||
// missing functionality).
|
// missing functionality).
|
||||||
impl Device {
|
impl Device {
|
||||||
pub fn query_gpu_info(&self) -> GpuInfo {
|
pub fn query_gpu_info(&self) -> GpuInfo {
|
||||||
match self {
|
mux_match! { self;
|
||||||
Device::Vk(d) => d.query_gpu_info(),
|
Device::Vk(d) => d.query_gpu_info(),
|
||||||
Device::Dx12(d) => d.query_gpu_info(),
|
Device::Dx12(d) => d.query_gpu_info(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_buffer(&self, size: u64, usage: BufferUsage) -> Result<Buffer, Error> {
|
pub fn create_buffer(&self, size: u64, usage: BufferUsage) -> Result<Buffer, Error> {
|
||||||
match self {
|
mux_match! { self;
|
||||||
Device::Vk(d) => d.create_buffer(size, usage).map(Buffer::Vk),
|
Device::Vk(d) => d.create_buffer(size, usage).map(Buffer::Vk),
|
||||||
Device::Dx12(d) => d.create_buffer(size, usage).map(Buffer::Dx12),
|
Device::Dx12(d) => d.create_buffer(size, usage).map(Buffer::Dx12),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn destroy_buffer(&self, buffer: &Buffer) -> Result<(), Error> {
|
pub unsafe fn destroy_buffer(&self, buffer: &Buffer) -> Result<(), Error> {
|
||||||
match self {
|
mux_match! { self;
|
||||||
Device::Vk(d) => d.destroy_buffer(buffer.vk()),
|
Device::Vk(d) => d.destroy_buffer(buffer.vk()),
|
||||||
Device::Dx12(d) => d.destroy_buffer(buffer.dx12()),
|
Device::Dx12(d) => d.destroy_buffer(buffer.dx12()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub unsafe fn create_image2d(&self, width: u32, height: u32) -> Result<Image, Error> {
|
||||||
|
mux_match! { self;
|
||||||
|
Device::Vk(d) => d.create_image2d(width, height).map(Image::Vk),
|
||||||
|
Device::Dx12(d) => d.create_image2d(width, height).map(Image::Dx12),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn destroy_image(&self, image: &Image) -> Result<(), Error> {
|
||||||
|
mux_match! { self;
|
||||||
|
Device::Vk(d) => d.destroy_image(image.vk()),
|
||||||
|
Device::Dx12(d) => d.destroy_image(image.dx12()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub unsafe fn create_fence(&self, signaled: bool) -> Result<Fence, Error> {
|
pub unsafe fn create_fence(&self, signaled: bool) -> Result<Fence, Error> {
|
||||||
match self {
|
mux_match! { self;
|
||||||
Device::Vk(d) => d.create_fence(signaled).map(Fence::Vk),
|
Device::Vk(d) => d.create_fence(signaled).map(Fence::Vk),
|
||||||
Device::Dx12(d) => d.create_fence(signaled).map(Fence::Dx12),
|
Device::Dx12(d) => d.create_fence(signaled).map(Fence::Dx12),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn wait_and_reset(&self, fences: &[&Fence]) -> Result<(), Error> {
|
pub unsafe fn wait_and_reset(&self, fences: &[&Fence]) -> Result<(), Error> {
|
||||||
match self {
|
mux_match! { self;
|
||||||
Device::Vk(d) => {
|
Device::Vk(d) => {
|
||||||
let fences = fences
|
let fences = fences
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -151,41 +195,53 @@ impl Device {
|
||||||
.collect::<SmallVec<[_; 4]>>();
|
.collect::<SmallVec<[_; 4]>>();
|
||||||
d.wait_and_reset(&*fences)
|
d.wait_and_reset(&*fences)
|
||||||
}
|
}
|
||||||
// Probably need to change device trait to accept &Fence
|
}
|
||||||
_ => todo!(),
|
}
|
||||||
|
|
||||||
|
pub unsafe fn get_fence_status(&self, fence: &Fence) -> Result<bool, Error> {
|
||||||
|
mux_match! { self;
|
||||||
|
Device::Vk(d) => d.get_fence_status(fence.vk()),
|
||||||
|
Device::Dx12(d) => d.get_fence_status(fence.dx12()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn create_semaphore(&self) -> Result<Semaphore, Error> {
|
||||||
|
mux_match! { self;
|
||||||
|
Device::Vk(d) => d.create_semaphore().map(Semaphore::Vk),
|
||||||
|
Device::Dx12(d) => d.create_semaphore().map(Semaphore::Dx12),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn pipeline_builder(&self) -> PipelineBuilder {
|
pub unsafe fn pipeline_builder(&self) -> PipelineBuilder {
|
||||||
match self {
|
mux_match! { self;
|
||||||
Device::Vk(d) => PipelineBuilder::Vk(d.pipeline_builder()),
|
Device::Vk(d) => PipelineBuilder::Vk(d.pipeline_builder()),
|
||||||
Device::Dx12(d) => PipelineBuilder::Dx12(d.pipeline_builder()),
|
Device::Dx12(d) => PipelineBuilder::Dx12(d.pipeline_builder()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn descriptor_set_builder(&self) -> DescriptorSetBuilder {
|
pub unsafe fn descriptor_set_builder(&self) -> DescriptorSetBuilder {
|
||||||
match self {
|
mux_match! { self;
|
||||||
Device::Vk(d) => DescriptorSetBuilder::Vk(d.descriptor_set_builder()),
|
Device::Vk(d) => DescriptorSetBuilder::Vk(d.descriptor_set_builder()),
|
||||||
Device::Dx12(d) => DescriptorSetBuilder::Dx12(d.descriptor_set_builder()),
|
Device::Dx12(d) => DescriptorSetBuilder::Dx12(d.descriptor_set_builder()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_cmd_buf(&self) -> Result<CmdBuf, Error> {
|
pub fn create_cmd_buf(&self) -> Result<CmdBuf, Error> {
|
||||||
match self {
|
mux_match! { self;
|
||||||
Device::Vk(d) => d.create_cmd_buf().map(CmdBuf::Vk),
|
Device::Vk(d) => d.create_cmd_buf().map(CmdBuf::Vk),
|
||||||
Device::Dx12(d) => d.create_cmd_buf().map(CmdBuf::Dx12),
|
Device::Dx12(d) => d.create_cmd_buf().map(CmdBuf::Dx12),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_query_pool(&self, n_queries: u32) -> Result<QueryPool, Error> {
|
pub fn create_query_pool(&self, n_queries: u32) -> Result<QueryPool, Error> {
|
||||||
match self {
|
mux_match! { self;
|
||||||
Device::Vk(d) => d.create_query_pool(n_queries).map(QueryPool::Vk),
|
Device::Vk(d) => d.create_query_pool(n_queries).map(QueryPool::Vk),
|
||||||
Device::Dx12(d) => d.create_query_pool(n_queries).map(QueryPool::Dx12),
|
Device::Dx12(d) => d.create_query_pool(n_queries).map(QueryPool::Dx12),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn fetch_query_pool(&self, pool: &QueryPool) -> Result<Vec<f64>, Error> {
|
pub unsafe fn fetch_query_pool(&self, pool: &QueryPool) -> Result<Vec<f64>, Error> {
|
||||||
match self {
|
mux_match! { self;
|
||||||
Device::Vk(d) => d.fetch_query_pool(pool.vk()),
|
Device::Vk(d) => d.fetch_query_pool(pool.vk()),
|
||||||
Device::Dx12(d) => d.fetch_query_pool(pool.dx12()),
|
Device::Dx12(d) => d.fetch_query_pool(pool.dx12()),
|
||||||
}
|
}
|
||||||
|
@ -198,14 +254,22 @@ impl Device {
|
||||||
signal_semaphores: &[&Semaphore],
|
signal_semaphores: &[&Semaphore],
|
||||||
fence: Option<&Fence>,
|
fence: Option<&Fence>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
match self {
|
mux_match! { self;
|
||||||
Device::Vk(d) => d.run_cmd_bufs(
|
Device::Vk(d) => d.run_cmd_bufs(
|
||||||
&cmd_bufs
|
&cmd_bufs
|
||||||
.iter()
|
.iter()
|
||||||
.map(|c| c.vk())
|
.map(|c| c.vk())
|
||||||
.collect::<SmallVec<[_; 4]>>(),
|
.collect::<SmallVec<[_; 4]>>(),
|
||||||
&wait_semaphores.iter().copied().map(Semaphore::vk).collect::<SmallVec<[_; 4]>>(),
|
&wait_semaphores
|
||||||
&signal_semaphores.iter().copied().map(Semaphore::vk).collect::<SmallVec<[_; 4]>>(),
|
.iter()
|
||||||
|
.copied()
|
||||||
|
.map(Semaphore::vk)
|
||||||
|
.collect::<SmallVec<[_; 4]>>(),
|
||||||
|
&signal_semaphores
|
||||||
|
.iter()
|
||||||
|
.copied()
|
||||||
|
.map(Semaphore::vk)
|
||||||
|
.collect::<SmallVec<[_; 4]>>(),
|
||||||
fence.map(Fence::vk),
|
fence.map(Fence::vk),
|
||||||
),
|
),
|
||||||
Device::Dx12(d) => d.run_cmd_bufs(
|
Device::Dx12(d) => d.run_cmd_bufs(
|
||||||
|
@ -213,8 +277,16 @@ impl Device {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|c| c.dx12())
|
.map(|c| c.dx12())
|
||||||
.collect::<SmallVec<[_; 4]>>(),
|
.collect::<SmallVec<[_; 4]>>(),
|
||||||
&wait_semaphores.iter().copied().map(Semaphore::dx12).collect::<SmallVec<[_; 4]>>(),
|
&wait_semaphores
|
||||||
&signal_semaphores.iter().copied().map(Semaphore::dx12).collect::<SmallVec<[_; 4]>>(),
|
.iter()
|
||||||
|
.copied()
|
||||||
|
.map(Semaphore::dx12)
|
||||||
|
.collect::<SmallVec<[_; 4]>>(),
|
||||||
|
&signal_semaphores
|
||||||
|
.iter()
|
||||||
|
.copied()
|
||||||
|
.map(Semaphore::dx12)
|
||||||
|
.collect::<SmallVec<[_; 4]>>(),
|
||||||
fence.map(Fence::dx12),
|
fence.map(Fence::dx12),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
@ -227,7 +299,7 @@ impl Device {
|
||||||
offset: u64,
|
offset: u64,
|
||||||
size: u64,
|
size: u64,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
match self {
|
mux_match! { self;
|
||||||
Device::Vk(d) => d.read_buffer(buffer.vk(), dst, offset, size),
|
Device::Vk(d) => d.read_buffer(buffer.vk(), dst, offset, size),
|
||||||
Device::Dx12(d) => d.read_buffer(buffer.dx12(), dst, offset, size),
|
Device::Dx12(d) => d.read_buffer(buffer.dx12(), dst, offset, size),
|
||||||
}
|
}
|
||||||
|
@ -240,7 +312,7 @@ impl Device {
|
||||||
offset: u64,
|
offset: u64,
|
||||||
size: u64,
|
size: u64,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
match self {
|
mux_match! { self;
|
||||||
Device::Vk(d) => d.write_buffer(buffer.vk(), contents, offset, size),
|
Device::Vk(d) => d.write_buffer(buffer.vk(), contents, offset, size),
|
||||||
Device::Dx12(d) => d.write_buffer(buffer.dx12(), contents, offset, size),
|
Device::Dx12(d) => d.write_buffer(buffer.dx12(), contents, offset, size),
|
||||||
}
|
}
|
||||||
|
@ -249,21 +321,21 @@ impl Device {
|
||||||
|
|
||||||
impl PipelineBuilder {
|
impl PipelineBuilder {
|
||||||
pub fn add_buffers(&mut self, n_buffers: u32) {
|
pub fn add_buffers(&mut self, n_buffers: u32) {
|
||||||
match self {
|
mux_match! { self;
|
||||||
PipelineBuilder::Vk(x) => x.add_buffers(n_buffers),
|
PipelineBuilder::Vk(x) => x.add_buffers(n_buffers),
|
||||||
PipelineBuilder::Dx12(x) => x.add_buffers(n_buffers),
|
PipelineBuilder::Dx12(x) => x.add_buffers(n_buffers),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_images(&mut self, n_buffers: u32) {
|
pub fn add_images(&mut self, n_buffers: u32) {
|
||||||
match self {
|
mux_match! { self;
|
||||||
PipelineBuilder::Vk(x) => x.add_images(n_buffers),
|
PipelineBuilder::Vk(x) => x.add_images(n_buffers),
|
||||||
PipelineBuilder::Dx12(x) => x.add_images(n_buffers),
|
PipelineBuilder::Dx12(x) => x.add_images(n_buffers),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_textures(&mut self, n_buffers: u32) {
|
pub fn add_textures(&mut self, n_buffers: u32) {
|
||||||
match self {
|
mux_match! { self;
|
||||||
PipelineBuilder::Vk(x) => x.add_textures(n_buffers),
|
PipelineBuilder::Vk(x) => x.add_textures(n_buffers),
|
||||||
PipelineBuilder::Dx12(x) => x.add_textures(n_buffers),
|
PipelineBuilder::Dx12(x) => x.add_textures(n_buffers),
|
||||||
}
|
}
|
||||||
|
@ -274,7 +346,7 @@ impl PipelineBuilder {
|
||||||
device: &Device,
|
device: &Device,
|
||||||
code: ShaderCode<'a>,
|
code: ShaderCode<'a>,
|
||||||
) -> Result<Pipeline, Error> {
|
) -> Result<Pipeline, Error> {
|
||||||
match self {
|
mux_match! { self;
|
||||||
PipelineBuilder::Vk(x) => {
|
PipelineBuilder::Vk(x) => {
|
||||||
let shader_code = match code {
|
let shader_code = match code {
|
||||||
ShaderCode::Spv(spv) => spv,
|
ShaderCode::Spv(spv) => spv,
|
||||||
|
@ -298,39 +370,60 @@ impl PipelineBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DescriptorSetBuilder {
|
impl DescriptorSetBuilder {
|
||||||
pub fn add_buffers(&mut self, buffers: &[Buffer]) {
|
pub fn add_buffers(&mut self, buffers: &[&Buffer]) {
|
||||||
match self {
|
mux_match! { self;
|
||||||
DescriptorSetBuilder::Vk(x) => {
|
DescriptorSetBuilder::Vk(x) => x.add_buffers(
|
||||||
x.add_buffers(&buffers.iter().map(Buffer::vk).collect::<SmallVec<[_; 8]>>())
|
&buffers
|
||||||
}
|
.iter()
|
||||||
|
.copied()
|
||||||
|
.map(Buffer::vk)
|
||||||
|
.collect::<SmallVec<[_; 8]>>(),
|
||||||
|
),
|
||||||
DescriptorSetBuilder::Dx12(x) => x.add_buffers(
|
DescriptorSetBuilder::Dx12(x) => x.add_buffers(
|
||||||
&buffers
|
&buffers
|
||||||
.iter()
|
.iter()
|
||||||
|
.copied()
|
||||||
.map(Buffer::dx12)
|
.map(Buffer::dx12)
|
||||||
.collect::<SmallVec<[_; 8]>>(),
|
.collect::<SmallVec<[_; 8]>>(),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_images(&mut self, images: &[Image]) {
|
pub fn add_images(&mut self, images: &[&Image]) {
|
||||||
match self {
|
mux_match! { self;
|
||||||
DescriptorSetBuilder::Vk(x) => {
|
DescriptorSetBuilder::Vk(x) => x.add_images(
|
||||||
x.add_images(&images.iter().map(Image::vk).collect::<SmallVec<[_; 8]>>())
|
&images
|
||||||
}
|
.iter()
|
||||||
DescriptorSetBuilder::Dx12(x) => {
|
.copied()
|
||||||
x.add_images(&images.iter().map(Image::dx12).collect::<SmallVec<[_; 8]>>())
|
.map(Image::vk)
|
||||||
}
|
.collect::<SmallVec<[_; 8]>>(),
|
||||||
|
),
|
||||||
|
DescriptorSetBuilder::Dx12(x) => x.add_images(
|
||||||
|
&images
|
||||||
|
.iter()
|
||||||
|
.copied()
|
||||||
|
.map(Image::dx12)
|
||||||
|
.collect::<SmallVec<[_; 8]>>(),
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_textures(&mut self, images: &[Image]) {
|
pub fn add_textures(&mut self, images: &[&Image]) {
|
||||||
match self {
|
mux_match! { self;
|
||||||
DescriptorSetBuilder::Vk(x) => {
|
DescriptorSetBuilder::Vk(x) => x.add_textures(
|
||||||
x.add_textures(&images.iter().map(Image::vk).collect::<SmallVec<[_; 8]>>())
|
&images
|
||||||
}
|
.iter()
|
||||||
DescriptorSetBuilder::Dx12(x) => {
|
.copied()
|
||||||
x.add_textures(&images.iter().map(Image::dx12).collect::<SmallVec<[_; 8]>>())
|
.map(Image::vk)
|
||||||
}
|
.collect::<SmallVec<[_; 8]>>(),
|
||||||
|
),
|
||||||
|
DescriptorSetBuilder::Dx12(x) => x.add_textures(
|
||||||
|
&images
|
||||||
|
.iter()
|
||||||
|
.copied()
|
||||||
|
.map(Image::dx12)
|
||||||
|
.collect::<SmallVec<[_; 8]>>(),
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -339,10 +432,9 @@ impl DescriptorSetBuilder {
|
||||||
device: &Device,
|
device: &Device,
|
||||||
pipeline: &Pipeline,
|
pipeline: &Pipeline,
|
||||||
) -> Result<DescriptorSet, Error> {
|
) -> Result<DescriptorSet, Error> {
|
||||||
match self {
|
mux_match! { self;
|
||||||
DescriptorSetBuilder::Vk(x) => {
|
DescriptorSetBuilder::Vk(x) =>
|
||||||
x.build(device.vk(), pipeline.vk()).map(DescriptorSet::Vk)
|
x.build(device.vk(), pipeline.vk()).map(DescriptorSet::Vk),
|
||||||
}
|
|
||||||
DescriptorSetBuilder::Dx12(x) => x
|
DescriptorSetBuilder::Dx12(x) => x
|
||||||
.build(device.dx12(), pipeline.dx12())
|
.build(device.dx12(), pipeline.dx12())
|
||||||
.map(DescriptorSet::Dx12),
|
.map(DescriptorSet::Dx12),
|
||||||
|
@ -352,14 +444,14 @@ impl DescriptorSetBuilder {
|
||||||
|
|
||||||
impl CmdBuf {
|
impl CmdBuf {
|
||||||
pub unsafe fn begin(&mut self) {
|
pub unsafe fn begin(&mut self) {
|
||||||
match self {
|
mux_match! { self;
|
||||||
CmdBuf::Vk(c) => c.begin(),
|
CmdBuf::Vk(c) => c.begin(),
|
||||||
CmdBuf::Dx12(c) => c.begin(),
|
CmdBuf::Dx12(c) => c.begin(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn finish(&mut self) {
|
pub unsafe fn finish(&mut self) {
|
||||||
match self {
|
mux_match! { self;
|
||||||
CmdBuf::Vk(c) => c.finish(),
|
CmdBuf::Vk(c) => c.finish(),
|
||||||
CmdBuf::Dx12(c) => c.finish(),
|
CmdBuf::Dx12(c) => c.finish(),
|
||||||
}
|
}
|
||||||
|
@ -371,21 +463,21 @@ impl CmdBuf {
|
||||||
descriptor_set: &DescriptorSet,
|
descriptor_set: &DescriptorSet,
|
||||||
size: (u32, u32, u32),
|
size: (u32, u32, u32),
|
||||||
) {
|
) {
|
||||||
match self {
|
mux_match! { self;
|
||||||
CmdBuf::Vk(c) => c.dispatch(pipeline.vk(), descriptor_set.vk(), size),
|
CmdBuf::Vk(c) => c.dispatch(pipeline.vk(), descriptor_set.vk(), size),
|
||||||
CmdBuf::Dx12(c) => c.dispatch(pipeline.dx12(), descriptor_set.dx12(), size),
|
CmdBuf::Dx12(c) => c.dispatch(pipeline.dx12(), descriptor_set.dx12(), size),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn memory_barrier(&mut self) {
|
pub unsafe fn memory_barrier(&mut self) {
|
||||||
match self {
|
mux_match! { self;
|
||||||
CmdBuf::Vk(c) => c.memory_barrier(),
|
CmdBuf::Vk(c) => c.memory_barrier(),
|
||||||
CmdBuf::Dx12(c) => c.memory_barrier(),
|
CmdBuf::Dx12(c) => c.memory_barrier(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn host_barrier(&mut self) {
|
pub unsafe fn host_barrier(&mut self) {
|
||||||
match self {
|
mux_match! { self;
|
||||||
CmdBuf::Vk(c) => c.host_barrier(),
|
CmdBuf::Vk(c) => c.host_barrier(),
|
||||||
CmdBuf::Dx12(c) => c.host_barrier(),
|
CmdBuf::Dx12(c) => c.host_barrier(),
|
||||||
}
|
}
|
||||||
|
@ -397,65 +489,113 @@ impl CmdBuf {
|
||||||
src_layout: ImageLayout,
|
src_layout: ImageLayout,
|
||||||
dst_layout: ImageLayout,
|
dst_layout: ImageLayout,
|
||||||
) {
|
) {
|
||||||
match self {
|
mux_match! { self;
|
||||||
CmdBuf::Vk(c) => c.image_barrier(image.vk(), src_layout, dst_layout),
|
CmdBuf::Vk(c) => c.image_barrier(image.vk(), src_layout, dst_layout),
|
||||||
CmdBuf::Dx12(c) => c.image_barrier(image.dx12(), src_layout, dst_layout),
|
CmdBuf::Dx12(c) => c.image_barrier(image.dx12(), src_layout, dst_layout),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn clear_buffer(&mut self, buffer: &Buffer, size: Option<u64>) {
|
pub unsafe fn clear_buffer(&mut self, buffer: &Buffer, size: Option<u64>) {
|
||||||
match self {
|
mux_match! { self;
|
||||||
CmdBuf::Vk(c) => c.clear_buffer(buffer.vk(), size),
|
CmdBuf::Vk(c) => c.clear_buffer(buffer.vk(), size),
|
||||||
CmdBuf::Dx12(c) => c.clear_buffer(buffer.dx12(), size),
|
CmdBuf::Dx12(c) => c.clear_buffer(buffer.dx12(), size),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn copy_buffer(&mut self, src: &Buffer, dst: &Buffer) {
|
pub unsafe fn copy_buffer(&mut self, src: &Buffer, dst: &Buffer) {
|
||||||
match self {
|
mux_match! { self;
|
||||||
CmdBuf::Vk(c) => c.copy_buffer(src.vk(), dst.vk()),
|
CmdBuf::Vk(c) => c.copy_buffer(src.vk(), dst.vk()),
|
||||||
CmdBuf::Dx12(c) => c.copy_buffer(src.dx12(), dst.dx12()),
|
CmdBuf::Dx12(c) => c.copy_buffer(src.dx12(), dst.dx12()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn copy_image_to_buffer(&mut self, src: &Image, dst: &Buffer) {
|
pub unsafe fn copy_image_to_buffer(&mut self, src: &Image, dst: &Buffer) {
|
||||||
match self {
|
mux_match! { self;
|
||||||
CmdBuf::Vk(c) => c.copy_image_to_buffer(src.vk(), dst.vk()),
|
CmdBuf::Vk(c) => c.copy_image_to_buffer(src.vk(), dst.vk()),
|
||||||
CmdBuf::Dx12(c) => c.copy_image_to_buffer(src.dx12(), dst.dx12()),
|
CmdBuf::Dx12(c) => c.copy_image_to_buffer(src.dx12(), dst.dx12()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn copy_buffer_to_image(&mut self, src: &Buffer, dst: &Image) {
|
pub unsafe fn copy_buffer_to_image(&mut self, src: &Buffer, dst: &Image) {
|
||||||
match self {
|
mux_match! { self;
|
||||||
CmdBuf::Vk(c) => c.copy_buffer_to_image(src.vk(), dst.vk()),
|
CmdBuf::Vk(c) => c.copy_buffer_to_image(src.vk(), dst.vk()),
|
||||||
CmdBuf::Dx12(c) => c.copy_buffer_to_image(src.dx12(), dst.dx12()),
|
CmdBuf::Dx12(c) => c.copy_buffer_to_image(src.dx12(), dst.dx12()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn blit_image(&mut self, src: &Image, dst: &Image) {
|
pub unsafe fn blit_image(&mut self, src: &Image, dst: &Image) {
|
||||||
match self {
|
mux_match! { self;
|
||||||
CmdBuf::Vk(c) => c.blit_image(src.vk(), dst.vk()),
|
CmdBuf::Vk(c) => c.blit_image(src.vk(), dst.vk()),
|
||||||
CmdBuf::Dx12(c) => c.blit_image(src.dx12(), dst.dx12()),
|
CmdBuf::Dx12(c) => c.blit_image(src.dx12(), dst.dx12()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn reset_query_pool(&mut self, pool: &QueryPool) {
|
pub unsafe fn reset_query_pool(&mut self, pool: &QueryPool) {
|
||||||
match self {
|
mux_match! { self;
|
||||||
CmdBuf::Vk(c) => c.reset_query_pool(pool.vk()),
|
CmdBuf::Vk(c) => c.reset_query_pool(pool.vk()),
|
||||||
CmdBuf::Dx12(c) => c.reset_query_pool(pool.dx12()),
|
CmdBuf::Dx12(c) => c.reset_query_pool(pool.dx12()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn write_timestamp(&mut self, pool: &QueryPool, query: u32) {
|
pub unsafe fn write_timestamp(&mut self, pool: &QueryPool, query: u32) {
|
||||||
match self {
|
mux_match! { self;
|
||||||
CmdBuf::Vk(c) => c.write_timestamp(pool.vk(), query),
|
CmdBuf::Vk(c) => c.write_timestamp(pool.vk(), query),
|
||||||
CmdBuf::Dx12(c) => c.write_timestamp(pool.dx12(), query),
|
CmdBuf::Dx12(c) => c.write_timestamp(pool.dx12(), query),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn finish_timestamps(&mut self, pool: &QueryPool) {
|
pub unsafe fn finish_timestamps(&mut self, pool: &QueryPool) {
|
||||||
match self {
|
mux_match! { self;
|
||||||
CmdBuf::Vk(c) => c.finish_timestamps(pool.vk()),
|
CmdBuf::Vk(c) => c.finish_timestamps(pool.vk()),
|
||||||
CmdBuf::Dx12(c) => c.finish_timestamps(pool.dx12()),
|
CmdBuf::Dx12(c) => c.finish_timestamps(pool.dx12()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Buffer {
|
||||||
|
pub fn size(&self) -> u64 {
|
||||||
|
mux_match! { self;
|
||||||
|
Buffer::Vk(b) => b.size,
|
||||||
|
Buffer::Dx12(b) => b.size,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Swapchain {
|
||||||
|
pub unsafe fn next(&mut self) -> Result<(usize, Semaphore), Error> {
|
||||||
|
mux_match! { self;
|
||||||
|
Swapchain::Vk(s) => {
|
||||||
|
let (idx, sem) = s.next()?;
|
||||||
|
Ok((idx, Semaphore::Vk(sem)))
|
||||||
|
}
|
||||||
|
Swapchain::Dx12(_s) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn image(&self, idx: usize) -> Image {
|
||||||
|
mux_match! { self;
|
||||||
|
Swapchain::Vk(s) => Image::Vk(s.image(idx)),
|
||||||
|
Swapchain::Dx12(_s) => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn present(
|
||||||
|
&self,
|
||||||
|
image_idx: usize,
|
||||||
|
semaphores: &[&Semaphore],
|
||||||
|
) -> Result<bool, Error> {
|
||||||
|
mux_match! { self;
|
||||||
|
Swapchain::Vk(s) => s.present(
|
||||||
|
image_idx,
|
||||||
|
&semaphores
|
||||||
|
.iter()
|
||||||
|
.copied()
|
||||||
|
.map(Semaphore::vk)
|
||||||
|
.collect::<SmallVec<[_; 4]>>(),
|
||||||
|
),
|
||||||
|
Swapchain::Dx12(_s) => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -631,9 +631,9 @@ impl crate::Device for VkDevice {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn get_fence_status(&self, fence: Self::Fence) -> Result<bool, Error> {
|
unsafe fn get_fence_status(&self, fence: &Self::Fence) -> Result<bool, Error> {
|
||||||
let device = &self.device.device;
|
let device = &self.device.device;
|
||||||
Ok(device.get_fence_status(fence)?)
|
Ok(device.get_fence_status(*fence)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn pipeline_builder(&self) -> PipelineBuilder {
|
unsafe fn pipeline_builder(&self) -> PipelineBuilder {
|
||||||
|
@ -1306,14 +1306,15 @@ impl VkSwapchain {
|
||||||
pub unsafe fn present(
|
pub unsafe fn present(
|
||||||
&self,
|
&self,
|
||||||
image_idx: usize,
|
image_idx: usize,
|
||||||
semaphores: &[vk::Semaphore],
|
semaphores: &[&vk::Semaphore],
|
||||||
) -> Result<bool, Error> {
|
) -> Result<bool, Error> {
|
||||||
|
let semaphores = semaphores.iter().copied().copied().collect::<SmallVec<[_; 4]>>();
|
||||||
Ok(self.swapchain_fn.queue_present(
|
Ok(self.swapchain_fn.queue_present(
|
||||||
self.present_queue,
|
self.present_queue,
|
||||||
&vk::PresentInfoKHR::builder()
|
&vk::PresentInfoKHR::builder()
|
||||||
.swapchains(&[self.swapchain])
|
.swapchains(&[self.swapchain])
|
||||||
.image_indices(&[image_idx as u32])
|
.image_indices(&[image_idx as u32])
|
||||||
.wait_semaphores(semaphores)
|
.wait_semaphores(&semaphores)
|
||||||
.build(),
|
.build(),
|
||||||
)?)
|
)?)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ use ndk::native_window::NativeWindow;
|
||||||
use ndk_glue::Event;
|
use ndk_glue::Event;
|
||||||
|
|
||||||
use piet_gpu_hal::hub;
|
use piet_gpu_hal::hub;
|
||||||
use piet_gpu_hal::vulkan::{QueryPool, VkInstance, VkSurface, VkSwapchain};
|
use piet_gpu_hal::mux::{QueryPool, Instance, Surface, Swapchain};
|
||||||
use piet_gpu_hal::{CmdBuf, Error, ImageLayout};
|
use piet_gpu_hal::{CmdBuf, Error, ImageLayout};
|
||||||
|
|
||||||
use piet_gpu::{render_scene, PietGpuRenderContext, Renderer};
|
use piet_gpu::{render_scene, PietGpuRenderContext, Renderer};
|
||||||
|
@ -30,7 +30,7 @@ struct MyHandle {
|
||||||
struct GfxState {
|
struct GfxState {
|
||||||
session: hub::Session,
|
session: hub::Session,
|
||||||
renderer: Renderer,
|
renderer: Renderer,
|
||||||
swapchain: VkSwapchain,
|
swapchain: Swapchain,
|
||||||
current_frame: usize,
|
current_frame: usize,
|
||||||
last_frame_idx: usize,
|
last_frame_idx: usize,
|
||||||
submitted: Option<hub::SubmittedCmdBuf>,
|
submitted: Option<hub::SubmittedCmdBuf>,
|
||||||
|
@ -52,7 +52,7 @@ fn my_main() -> Result<(), Error> {
|
||||||
let window = ndk_glue::native_window();
|
let window = ndk_glue::native_window();
|
||||||
if let Some(window) = &*window {
|
if let Some(window) = &*window {
|
||||||
let handle = get_handle(window);
|
let handle = get_handle(window);
|
||||||
let (instance, surface) = VkInstance::new(Some(&handle))?;
|
let (instance, surface) = Instance::new(Some(&handle))?;
|
||||||
gfx_state = Some(GfxState::new(&instance, surface.as_ref())?);
|
gfx_state = Some(GfxState::new(&instance, surface.as_ref())?);
|
||||||
} else {
|
} else {
|
||||||
println!("native window is sadly none");
|
println!("native window is sadly none");
|
||||||
|
@ -90,7 +90,7 @@ unsafe impl HasRawWindowHandle for MyHandle {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GfxState {
|
impl GfxState {
|
||||||
fn new(instance: &VkInstance, surface: Option<&VkSurface>) -> Result<GfxState, Error> {
|
fn new(instance: &Instance, surface: Option<&Surface>) -> Result<GfxState, Error> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let device = instance.device(surface)?;
|
let device = instance.device(surface)?;
|
||||||
let mut swapchain =
|
let mut swapchain =
|
||||||
|
@ -151,7 +151,7 @@ impl GfxState {
|
||||||
|
|
||||||
// Image -> Swapchain
|
// Image -> Swapchain
|
||||||
cmd_buf.image_barrier(&swap_image, ImageLayout::Undefined, ImageLayout::BlitDst);
|
cmd_buf.image_barrier(&swap_image, ImageLayout::Undefined, ImageLayout::BlitDst);
|
||||||
cmd_buf.blit_image(self.renderer.image_dev.vk_image(), &swap_image);
|
cmd_buf.blit_image(self.renderer.image_dev.mux_image(), &swap_image);
|
||||||
cmd_buf.image_barrier(&swap_image, ImageLayout::BlitDst, ImageLayout::Present);
|
cmd_buf.image_barrier(&swap_image, ImageLayout::BlitDst, ImageLayout::Present);
|
||||||
cmd_buf.finish();
|
cmd_buf.finish();
|
||||||
|
|
||||||
|
@ -167,7 +167,7 @@ impl GfxState {
|
||||||
self.last_frame_idx = frame_idx;
|
self.last_frame_idx = frame_idx;
|
||||||
|
|
||||||
self.swapchain
|
self.swapchain
|
||||||
.present(image_idx, &[self.present_semaphores[frame_idx]])
|
.present(image_idx, &[&self.present_semaphores[frame_idx]])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
self.current_frame += 1;
|
self.current_frame += 1;
|
||||||
|
|
|
@ -5,8 +5,8 @@ use std::path::Path;
|
||||||
use clap::{App, Arg};
|
use clap::{App, Arg};
|
||||||
|
|
||||||
use piet_gpu_hal::hub;
|
use piet_gpu_hal::hub;
|
||||||
use piet_gpu_hal::vulkan::VkInstance;
|
use piet_gpu_hal::mux::Instance;
|
||||||
use piet_gpu_hal::{BufferUsage, CmdBuf, Error};
|
use piet_gpu_hal::{BufferUsage, Error};
|
||||||
|
|
||||||
use piet_gpu::{render_scene, render_svg, PietGpuRenderContext, Renderer, HEIGHT, WIDTH};
|
use piet_gpu::{render_scene, render_svg, PietGpuRenderContext, Renderer, HEIGHT, WIDTH};
|
||||||
|
|
||||||
|
@ -225,7 +225,7 @@ fn main() -> Result<(), Error> {
|
||||||
.takes_value(true),
|
.takes_value(true),
|
||||||
)
|
)
|
||||||
.get_matches();
|
.get_matches();
|
||||||
let (instance, _) = VkInstance::new(None)?;
|
let (instance, _) = Instance::new(None)?;
|
||||||
unsafe {
|
unsafe {
|
||||||
let device = instance.device(None)?;
|
let device = instance.device(None)?;
|
||||||
let session = hub::Session::new(device);
|
let session = hub::Session::new(device);
|
||||||
|
@ -258,7 +258,7 @@ fn main() -> Result<(), Error> {
|
||||||
|
|
||||||
cmd_buf.begin();
|
cmd_buf.begin();
|
||||||
renderer.record(&mut cmd_buf, &query_pool);
|
renderer.record(&mut cmd_buf, &query_pool);
|
||||||
cmd_buf.copy_image_to_buffer(renderer.image_dev.vk_image(), image_buf.vk_buffer());
|
cmd_buf.copy_image_to_buffer(renderer.image_dev.mux_image(), image_buf.mux_buffer());
|
||||||
cmd_buf.host_barrier();
|
cmd_buf.host_barrier();
|
||||||
cmd_buf.finish();
|
cmd_buf.finish();
|
||||||
let start = std::time::Instant::now();
|
let start = std::time::Instant::now();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use piet_gpu_hal::hub;
|
use piet_gpu_hal::hub;
|
||||||
use piet_gpu_hal::vulkan::VkInstance;
|
use piet_gpu_hal::mux::Instance;
|
||||||
use piet_gpu_hal::{CmdBuf, Error, ImageLayout};
|
use piet_gpu_hal::{Error, ImageLayout};
|
||||||
|
|
||||||
use piet_gpu::{render_scene, PietGpuRenderContext, Renderer, HEIGHT, WIDTH};
|
use piet_gpu::{render_scene, PietGpuRenderContext, Renderer, HEIGHT, WIDTH};
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ fn main() -> Result<(), Error> {
|
||||||
.with_resizable(false) // currently not supported
|
.with_resizable(false) // currently not supported
|
||||||
.build(&event_loop)?;
|
.build(&event_loop)?;
|
||||||
|
|
||||||
let (instance, surface) = VkInstance::new(Some(&window))?;
|
let (instance, surface) = Instance::new(Some(&window))?;
|
||||||
unsafe {
|
unsafe {
|
||||||
let device = instance.device(surface.as_ref())?;
|
let device = instance.device(surface.as_ref())?;
|
||||||
let mut swapchain =
|
let mut swapchain =
|
||||||
|
@ -103,7 +103,7 @@ fn main() -> Result<(), Error> {
|
||||||
ImageLayout::Undefined,
|
ImageLayout::Undefined,
|
||||||
ImageLayout::BlitDst,
|
ImageLayout::BlitDst,
|
||||||
);
|
);
|
||||||
cmd_buf.blit_image(renderer.image_dev.vk_image(), &swap_image);
|
cmd_buf.blit_image(renderer.image_dev.mux_image(), &swap_image);
|
||||||
cmd_buf.image_barrier(&swap_image, ImageLayout::BlitDst, ImageLayout::Present);
|
cmd_buf.image_barrier(&swap_image, ImageLayout::BlitDst, ImageLayout::Present);
|
||||||
cmd_buf.finish();
|
cmd_buf.finish();
|
||||||
|
|
||||||
|
@ -117,7 +117,7 @@ fn main() -> Result<(), Error> {
|
||||||
last_frame_idx = frame_idx;
|
last_frame_idx = frame_idx;
|
||||||
|
|
||||||
swapchain
|
swapchain
|
||||||
.present(image_idx, &[present_semaphores[frame_idx]])
|
.present(image_idx, &[&present_semaphores[frame_idx]])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
current_frame += 1;
|
current_frame += 1;
|
||||||
|
|
|
@ -13,7 +13,8 @@ use piet::{Color, ImageFormat, RenderContext};
|
||||||
use piet_gpu_types::encoder::Encode;
|
use piet_gpu_types::encoder::Encode;
|
||||||
|
|
||||||
use piet_gpu_hal::hub;
|
use piet_gpu_hal::hub;
|
||||||
use piet_gpu_hal::{BufferUsage, CmdBuf, Error, ImageLayout};
|
use piet_gpu_hal::hub::ShaderCode;
|
||||||
|
use piet_gpu_hal::{BufferUsage, Error, ImageLayout};
|
||||||
|
|
||||||
use pico_svg::PicoSvg;
|
use pico_svg::PicoSvg;
|
||||||
|
|
||||||
|
@ -292,35 +293,35 @@ impl Renderer {
|
||||||
let memory_buf_dev = session.create_buffer(128 * 1024 * 1024, dev)?;
|
let memory_buf_dev = session.create_buffer(128 * 1024 * 1024, dev)?;
|
||||||
memory_buf_host.write(&[alloc as u32, 0 /* Overflow flag */])?;
|
memory_buf_host.write(&[alloc as u32, 0 /* Overflow flag */])?;
|
||||||
|
|
||||||
let el_code = include_bytes!("../shader/elements.spv");
|
let el_code = ShaderCode::Spv(include_bytes!("../shader/elements.spv"));
|
||||||
let el_pipeline = session.create_simple_compute_pipeline(el_code, 4)?;
|
let el_pipeline = session.create_simple_compute_pipeline(el_code, 4)?;
|
||||||
let el_ds = session.create_simple_descriptor_set(
|
let el_ds = session.create_simple_descriptor_set(
|
||||||
&el_pipeline,
|
&el_pipeline,
|
||||||
&[&memory_buf_dev, &config_buf, &scene_buf, &state_buf],
|
&[&memory_buf_dev, &config_buf, &scene_buf, &state_buf],
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let tile_alloc_code = include_bytes!("../shader/tile_alloc.spv");
|
let tile_alloc_code = ShaderCode::Spv(include_bytes!("../shader/tile_alloc.spv"));
|
||||||
let tile_pipeline = session.create_simple_compute_pipeline(tile_alloc_code, 2)?;
|
let tile_pipeline = session.create_simple_compute_pipeline(tile_alloc_code, 2)?;
|
||||||
let tile_ds = session
|
let tile_ds = session
|
||||||
.create_simple_descriptor_set(&tile_pipeline, &[&memory_buf_dev, &config_buf])?;
|
.create_simple_descriptor_set(&tile_pipeline, &[&memory_buf_dev, &config_buf])?;
|
||||||
|
|
||||||
let path_alloc_code = include_bytes!("../shader/path_coarse.spv");
|
let path_alloc_code = ShaderCode::Spv(include_bytes!("../shader/path_coarse.spv"));
|
||||||
let path_pipeline = session.create_simple_compute_pipeline(path_alloc_code, 2)?;
|
let path_pipeline = session.create_simple_compute_pipeline(path_alloc_code, 2)?;
|
||||||
let path_ds = session
|
let path_ds = session
|
||||||
.create_simple_descriptor_set(&path_pipeline, &[&memory_buf_dev, &config_buf])?;
|
.create_simple_descriptor_set(&path_pipeline, &[&memory_buf_dev, &config_buf])?;
|
||||||
|
|
||||||
let backdrop_alloc_code = include_bytes!("../shader/backdrop.spv");
|
let backdrop_alloc_code = ShaderCode::Spv(include_bytes!("../shader/backdrop.spv"));
|
||||||
let backdrop_pipeline = session.create_simple_compute_pipeline(backdrop_alloc_code, 2)?;
|
let backdrop_pipeline = session.create_simple_compute_pipeline(backdrop_alloc_code, 2)?;
|
||||||
let backdrop_ds = session
|
let backdrop_ds = session
|
||||||
.create_simple_descriptor_set(&backdrop_pipeline, &[&memory_buf_dev, &config_buf])?;
|
.create_simple_descriptor_set(&backdrop_pipeline, &[&memory_buf_dev, &config_buf])?;
|
||||||
|
|
||||||
// TODO: constants
|
// TODO: constants
|
||||||
let bin_code = include_bytes!("../shader/binning.spv");
|
let bin_code = ShaderCode::Spv(include_bytes!("../shader/binning.spv"));
|
||||||
let bin_pipeline = session.create_simple_compute_pipeline(bin_code, 2)?;
|
let bin_pipeline = session.create_simple_compute_pipeline(bin_code, 2)?;
|
||||||
let bin_ds =
|
let bin_ds =
|
||||||
session.create_simple_descriptor_set(&bin_pipeline, &[&memory_buf_dev, &config_buf])?;
|
session.create_simple_descriptor_set(&bin_pipeline, &[&memory_buf_dev, &config_buf])?;
|
||||||
|
|
||||||
let coarse_code = include_bytes!("../shader/coarse.spv");
|
let coarse_code = ShaderCode::Spv(include_bytes!("../shader/coarse.spv"));
|
||||||
let coarse_pipeline = session.create_simple_compute_pipeline(coarse_code, 2)?;
|
let coarse_pipeline = session.create_simple_compute_pipeline(coarse_code, 2)?;
|
||||||
let coarse_ds = session
|
let coarse_ds = session
|
||||||
.create_simple_descriptor_set(&coarse_pipeline, &[&memory_buf_dev, &config_buf])?;
|
.create_simple_descriptor_set(&coarse_pipeline, &[&memory_buf_dev, &config_buf])?;
|
||||||
|
@ -328,10 +329,10 @@ impl Renderer {
|
||||||
let bg_image = Self::make_test_bg_image(&session);
|
let bg_image = Self::make_test_bg_image(&session);
|
||||||
|
|
||||||
let k4_code = if session.gpu_info().has_descriptor_indexing {
|
let k4_code = if session.gpu_info().has_descriptor_indexing {
|
||||||
&include_bytes!("../shader/kernel4_idx.spv")[..]
|
ShaderCode::Spv(include_bytes!("../shader/kernel4_idx.spv"))
|
||||||
} else {
|
} else {
|
||||||
println!("doing non-indexed k4");
|
println!("doing non-indexed k4");
|
||||||
&include_bytes!("../shader/kernel4.spv")[..]
|
ShaderCode::Spv(include_bytes!("../shader/kernel4.spv"))
|
||||||
};
|
};
|
||||||
// This is an arbitrary limit on the number of textures that can be referenced by
|
// This is an arbitrary limit on the number of textures that can be referenced by
|
||||||
// the fine rasterizer. To set it for real, we probably want to pay attention both
|
// the fine rasterizer. To set it for real, we probably want to pay attention both
|
||||||
|
@ -386,13 +387,13 @@ impl Renderer {
|
||||||
|
|
||||||
pub unsafe fn record(&self, cmd_buf: &mut hub::CmdBuf, query_pool: &hub::QueryPool) {
|
pub unsafe fn record(&self, cmd_buf: &mut hub::CmdBuf, query_pool: &hub::QueryPool) {
|
||||||
cmd_buf.copy_buffer(
|
cmd_buf.copy_buffer(
|
||||||
self.memory_buf_host.vk_buffer(),
|
self.memory_buf_host.mux_buffer(),
|
||||||
self.memory_buf_dev.vk_buffer(),
|
self.memory_buf_dev.mux_buffer(),
|
||||||
);
|
);
|
||||||
cmd_buf.clear_buffer(self.state_buf.vk_buffer(), None);
|
cmd_buf.clear_buffer(self.state_buf.mux_buffer(), None);
|
||||||
cmd_buf.memory_barrier();
|
cmd_buf.memory_barrier();
|
||||||
cmd_buf.image_barrier(
|
cmd_buf.image_barrier(
|
||||||
self.image_dev.vk_image(),
|
self.image_dev.mux_image(),
|
||||||
ImageLayout::Undefined,
|
ImageLayout::Undefined,
|
||||||
ImageLayout::General,
|
ImageLayout::General,
|
||||||
);
|
);
|
||||||
|
@ -451,7 +452,7 @@ impl Renderer {
|
||||||
cmd_buf.write_timestamp(&query_pool, 7);
|
cmd_buf.write_timestamp(&query_pool, 7);
|
||||||
cmd_buf.memory_barrier();
|
cmd_buf.memory_barrier();
|
||||||
cmd_buf.image_barrier(
|
cmd_buf.image_barrier(
|
||||||
self.image_dev.vk_image(),
|
self.image_dev.mux_image(),
|
||||||
ImageLayout::General,
|
ImageLayout::General,
|
||||||
ImageLayout::BlitSrc,
|
ImageLayout::BlitSrc,
|
||||||
);
|
);
|
||||||
|
@ -475,12 +476,16 @@ impl Renderer {
|
||||||
let mut cmd_buf = session.cmd_buf()?;
|
let mut cmd_buf = session.cmd_buf()?;
|
||||||
cmd_buf.begin();
|
cmd_buf.begin();
|
||||||
cmd_buf.image_barrier(
|
cmd_buf.image_barrier(
|
||||||
image.vk_image(),
|
image.mux_image(),
|
||||||
ImageLayout::Undefined,
|
ImageLayout::Undefined,
|
||||||
ImageLayout::BlitDst,
|
ImageLayout::BlitDst,
|
||||||
);
|
);
|
||||||
cmd_buf.copy_buffer_to_image(buffer.vk_buffer(), image.vk_image());
|
cmd_buf.copy_buffer_to_image(buffer.mux_buffer(), image.mux_image());
|
||||||
cmd_buf.image_barrier(image.vk_image(), ImageLayout::BlitDst, ImageLayout::General);
|
cmd_buf.image_barrier(
|
||||||
|
image.mux_image(),
|
||||||
|
ImageLayout::BlitDst,
|
||||||
|
ImageLayout::General,
|
||||||
|
);
|
||||||
cmd_buf.finish();
|
cmd_buf.finish();
|
||||||
// Make sure not to drop the buffer and image until the command buffer completes.
|
// Make sure not to drop the buffer and image until the command buffer completes.
|
||||||
cmd_buf.add_resource(&buffer);
|
cmd_buf.add_resource(&buffer);
|
||||||
|
|
Loading…
Reference in a new issue