From f04da3af9dddc96fa640811c741dff922f013412 Mon Sep 17 00:00:00 2001 From: Raph Levien Date: Tue, 25 May 2021 08:25:24 -0700 Subject: [PATCH 1/3] Add multiplexer abstraction Adds a new "mux" module which can have multiple backends. As of this commit, it's not wired up at all, but the functionality should be reasonably complete. Minor tweaks to the backend trait to accommodate this, mostly changing Fence and Semaphore to references so they don't need to be Copy. Part of the work toward #95 --- Cargo.lock | 5 +- piet-gpu-hal/Cargo.toml | 2 + piet-gpu-hal/examples/dx12_toy.rs | 6 +- piet-gpu-hal/src/dx12.rs | 20 +- piet-gpu-hal/src/hub.rs | 8 +- piet-gpu-hal/src/lib.rs | 19 +- piet-gpu-hal/src/macros.rs | 79 +++++ piet-gpu-hal/src/mux.rs | 461 ++++++++++++++++++++++++++++++ piet-gpu-hal/src/vulkan.rs | 39 ++- piet-gpu/bin/android.rs | 4 +- piet-gpu/bin/winit.rs | 4 +- 11 files changed, 611 insertions(+), 36 deletions(-) create mode 100644 piet-gpu-hal/src/macros.rs create mode 100644 piet-gpu-hal/src/mux.rs diff --git a/Cargo.lock b/Cargo.lock index a04cbf4..0619b43 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -851,6 +851,7 @@ dependencies = [ "ash-window", "bitflags", "raw-window-handle", + "smallvec", "winapi 0.3.9", "wio", ] @@ -1036,9 +1037,9 @@ checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" [[package]] name = "smallvec" -version = "1.4.2" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbee7696b84bbf3d89a1c2eccff0850e3047ed46bfcd2e92c29a2d074d57e252" +checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" [[package]] name = "smithay-client-toolkit" diff --git a/piet-gpu-hal/Cargo.toml b/piet-gpu-hal/Cargo.toml index abbe98a..763da23 100644 --- a/piet-gpu-hal/Cargo.toml +++ b/piet-gpu-hal/Cargo.toml @@ -11,7 +11,9 @@ ash = "0.31" ash-window = "0.5" raw-window-handle = "0.3" bitflags = "1.2.1" +smallvec = "1.6.1" +[target.'cfg(target_os="windows")'.dependencies] winapi = { version = "0.3.9", features = [ 'd3d12', 'd3d12sdklayers', 'd3dcommon', 'd3dcompiler', 'dxgi', 'dxgi1_2', 'dxgi1_3', 'dxgi1_4', 'dxgidebug', 'dxgiformat', 'dxgitype', diff --git a/piet-gpu-hal/examples/dx12_toy.rs b/piet-gpu-hal/examples/dx12_toy.rs index 892ec0c..63e3db4 100644 --- a/piet-gpu-hal/examples/dx12_toy.rs +++ b/piet-gpu-hal/examples/dx12_toy.rs @@ -50,8 +50,8 @@ void main(SPIRV_Cross_Input stage_input) "#; fn toy() -> Result<(), Error> { - let instance = dx12::Dx12Instance::new()?; - let device = instance.device()?; + let (instance, _surface) = dx12::Dx12Instance::new(None)?; + let device = instance.device(None)?; let buf = device.create_buffer( 1024, BufferUsage::MAP_READ @@ -87,7 +87,7 @@ fn toy() -> Result<(), Error> { cmd_buf.host_barrier(); cmd_buf.finish(); device.run_cmd_bufs(&[&cmd_buf], &[], &[], Some(&fence))?; - device.wait_and_reset(&[fence])?; + device.wait_and_reset(&[&fence])?; let mut readback: Vec = vec![0u32; 256]; device.read_buffer(&buf, readback.as_mut_ptr() as *mut u8, 0, 1024)?; println!("{:?}", readback); diff --git a/piet-gpu-hal/src/dx12.rs b/piet-gpu-hal/src/dx12.rs index bf0e44e..47801dc 100644 --- a/piet-gpu-hal/src/dx12.rs +++ b/piet-gpu-hal/src/dx12.rs @@ -9,6 +9,8 @@ use winapi::shared::dxgi1_3; use winapi::shared::minwindef::TRUE; use winapi::um::d3d12; +use smallvec::SmallVec; + use crate::{BufferUsage, Error, ImageLayout}; use self::wrappers::{ @@ -19,6 +21,9 @@ pub struct Dx12Instance { factory: Factory4, } +// TODO +pub struct Dx12Surface; + pub struct Dx12Device { device: Device, command_allocator: CommandAllocator, @@ -95,7 +100,7 @@ impl Dx12Instance { /// /// TODO: take a raw window handle. /// TODO: can probably be a trait. - pub fn new() -> Result { + pub fn new(window_handle: Option<&dyn raw_window_handle::HasRawWindowHandle>) -> Result<(Dx12Instance, Option), Error> { unsafe { #[cfg(debug_assertions)] if let Err(e) = wrappers::enable_debug_layer() { @@ -110,7 +115,7 @@ impl Dx12Instance { let factory_flags: u32 = 0; let factory = Factory4::create(factory_flags)?; - Ok(Dx12Instance { factory }) + Ok((Dx12Instance { factory }, None)) } } @@ -118,7 +123,7 @@ impl Dx12Instance { /// /// TODO: handle window. /// TODO: probably can also be trait'ified. - pub fn device(&self) -> Result { + pub fn device(&self, surface: Option<&Dx12Surface>) -> Result { unsafe { let device = Device::create_device(&self.factory)?; let list_type = d3d12::D3D12_COMMAND_LIST_TYPE_DIRECT; @@ -262,16 +267,15 @@ impl crate::Device for Dx12Device { unsafe fn run_cmd_bufs( &self, cmd_bufs: &[&Self::CmdBuf], - wait_semaphores: &[Self::Semaphore], - signal_semaphores: &[Self::Semaphore], + wait_semaphores: &[&Self::Semaphore], + signal_semaphores: &[&Self::Semaphore], fence: Option<&Self::Fence>, ) -> Result<(), Error> { // TODO: handle semaphores - // SmallVec? let lists = cmd_bufs .iter() .map(|c| c.0.as_raw_command_list()) - .collect::>(); + .collect::>(); self.command_queue.execute_command_lists(&lists); if let Some(fence) = fence { let val = fence.val.get() + 1; @@ -319,7 +323,7 @@ impl crate::Device for Dx12Device { Ok(Fence { fence, event, val }) } - unsafe fn wait_and_reset(&self, fences: &[Self::Fence]) -> Result<(), Error> { + unsafe fn wait_and_reset(&self, fences: &[&Self::Fence]) -> Result<(), Error> { for fence in fences { // TODO: probably handle errors here. let _status = fence.event.wait(winapi::um::winbase::INFINITE); diff --git a/piet-gpu-hal/src/hub.rs b/piet-gpu-hal/src/hub.rs index 3238376..5a67ffc 100644 --- a/piet-gpu-hal/src/hub.rs +++ b/piet-gpu-hal/src/hub.rs @@ -133,7 +133,7 @@ impl Session { if let Ok(true) = self.0.device.get_fence_status(pending[i].fence) { let item = pending.swap_remove(i); // 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]); let mut pool = self.0.cmd_buf_pool.lock().unwrap(); pool.push((item.cmd_buf, item.fence)); std::mem::drop(item.resources); @@ -151,8 +151,8 @@ impl Session { pub unsafe fn run_cmd_buf( &self, cmd_buf: CmdBuf, - wait_semaphores: &[Semaphore], - signal_semaphores: &[Semaphore], + wait_semaphores: &[&Semaphore], + signal_semaphores: &[&Semaphore], ) -> Result { // Again, SmallVec here? let mut cmd_bufs = Vec::with_capacity(2); @@ -322,7 +322,7 @@ impl SubmittedCmdBuf { let item = self.0.take().unwrap(); if let Some(session) = Weak::upgrade(&self.1) { unsafe { - session.device.wait_and_reset(&[item.fence])?; + session.device.wait_and_reset(&[&item.fence])?; } session .cmd_buf_pool diff --git a/piet-gpu-hal/src/lib.rs b/piet-gpu-hal/src/lib.rs index 2fc7a8d..811d51a 100644 --- a/piet-gpu-hal/src/lib.rs +++ b/piet-gpu-hal/src/lib.rs @@ -6,8 +6,17 @@ use bitflags::bitflags; pub mod hub; -#[cfg(target_os = "windows")] -pub mod dx12; +#[macro_use] +mod macros; + +// TODO make this not pub +pub mod mux; + +mux! { + #[cfg(vk)] + pub mod dx12; +} +#[cfg(not(target_os = "macos"))] pub mod vulkan; /// This isn't great but is expedient. @@ -178,8 +187,8 @@ pub trait Device: Sized { unsafe fn run_cmd_bufs( &self, cmd_buf: &[&Self::CmdBuf], - wait_semaphores: &[Self::Semaphore], - signal_semaphores: &[Self::Semaphore], + wait_semaphores: &[&Self::Semaphore], + signal_semaphores: &[&Self::Semaphore], fence: Option<&Self::Fence>, ) -> Result<(), Error>; @@ -217,7 +226,7 @@ pub trait Device: Sized { unsafe fn create_semaphore(&self) -> Result; unsafe fn create_fence(&self, signaled: bool) -> Result; - 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; unsafe fn create_sampler(&self, params: SamplerParams) -> Result; diff --git a/piet-gpu-hal/src/macros.rs b/piet-gpu-hal/src/macros.rs new file mode 100644 index 0000000..f1c1a01 --- /dev/null +++ b/piet-gpu-hal/src/macros.rs @@ -0,0 +1,79 @@ +// Copyright 2021 The piet-gpu authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Also licensed under MIT license, at your choice. + +//! Macros, mostly to automate backend selection tedium. + +#[macro_export] +macro_rules! mux { + ( #[cfg(vk)] $($tokens:tt)* ) => { + #[cfg(not(target_os="macos"))] $( $tokens )* + }; + + ( #[cfg(dx12)] $($tokens:tt)* ) => { + #[cfg(target_os="windows")] $( $tokens )* + }; +} + +#[macro_export] +macro_rules! mux_enum { + ( $(#[$outer:meta])* $v:vis enum $name:ident { + Vk($vk:ty), + Dx12($dx12:ty), + } ) => { + $(#[$outer])* $v enum $name { + #[cfg(not(target_os="macos"))] + Vk($vk), + #[cfg(target_os="windows")] + Dx12($dx12), + } + + impl $name { + $crate::mux! { + #[cfg(vk)] + #[allow(unused)] + fn vk(&self) -> &$vk { + match self { + $name::Vk(x) => x, + _ => panic!("downcast error") + } + } + } + + $crate::mux! { + #[cfg(dx12)] + #[allow(unused)] + fn dx12(&self) -> &$dx12 { + match self { + $name::Dx12(x) => x, + _ => panic!("downcast error") + } + } + } + } + }; +} + +macro_rules! mux_device_enum { + ( $(#[$outer:meta])* $assoc_type: ident) => { + $crate::mux_enum! { + $(#[$outer])* + pub enum $assoc_type { + Vk(<$crate::vulkan::VkDevice as $crate::Device>::$assoc_type), + Dx12(<$crate::dx12::Dx12Device as $crate::Device>::$assoc_type), + } + } + } +} diff --git a/piet-gpu-hal/src/mux.rs b/piet-gpu-hal/src/mux.rs new file mode 100644 index 0000000..45e8879 --- /dev/null +++ b/piet-gpu-hal/src/mux.rs @@ -0,0 +1,461 @@ +// Copyright 2021 The piet-gpu authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Also licensed under MIT license, at your choice. + +//! A multiplexer module that selects a back-end at runtime. + +use smallvec::SmallVec; + +use crate::dx12; +use crate::vulkan; +use crate::CmdBuf as CmdBufTrait; +use crate::DescriptorSetBuilder as DescriptorSetBuilderTrait; +use crate::Device as DeviceTrait; +use crate::PipelineBuilder as PipelineBuilderTrait; +use crate::{BufferUsage, Error, GpuInfo, ImageLayout}; + +mux_enum! { + /// An instance, selected from multiple backends. + pub enum Instance { + Vk(vulkan::VkInstance), + Dx12(dx12::Dx12Instance), + } +} + +mux_enum! { + /// A device, selected from multiple backends. + pub enum Device { + Vk(vulkan::VkDevice), + Dx12(dx12::Dx12Device), + } +} + +mux_enum! { + /// A surface, which can apply to one of multiple backends. + pub enum Surface { + Vk(vulkan::VkSurface), + Dx12(dx12::Dx12Surface), + } +} + +mux_device_enum! { Buffer } +mux_device_enum! { Image } +mux_device_enum! { Fence } +mux_device_enum! { Semaphore } +mux_device_enum! { PipelineBuilder } +mux_device_enum! { Pipeline } +mux_device_enum! { DescriptorSetBuilder } +mux_device_enum! { DescriptorSet } +mux_device_enum! { CmdBuf } +mux_device_enum! { QueryPool } + +/// The code for a shader, either as source or intermediate representation. +pub enum ShaderCode<'a> { + Spv(&'a [u8]), + Hlsl(&'a str), +} + +impl Instance { + pub fn new( + window_handle: Option<&dyn raw_window_handle::HasRawWindowHandle>, + ) -> Result<(Instance, Option), Error> { + mux! { + #[cfg(vk)] + { + let result = vulkan::VkInstance::new(window_handle); + if let Ok((instance, surface)) = result { + return Ok((Instance::Vk(instance), surface.map(Surface::Vk))); + } + } + } + mux! { + #[cfg(dx12)] + { + let result = dx12::Dx12Instance::new(window_handle); + if let Ok((instance, surface)) = result { + return Ok((Instance::Dx12(instance), surface.map(Surface::Dx12))); + } + } + } + // TODO plumb creation errors through. + Err("No suitable instances found".into()) + } + + pub unsafe fn device(&self, surface: Option<&Surface>) -> Result { + match self { + Instance::Vk(i) => i.device(surface.map(Surface::vk)).map(Device::Vk), + Instance::Dx12(i) => i.device(surface.map(Surface::dx12)).map(Device::Dx12), + } + } +} + +// This is basically re-exporting the backend device trait, and we could do that, +// but not doing so lets us diverge more easily (at the moment, the divergence is +// missing functionality). +impl Device { + pub fn query_gpu_info(&self) -> GpuInfo { + match self { + Device::Vk(d) => d.query_gpu_info(), + Device::Dx12(d) => d.query_gpu_info(), + } + } + + pub fn create_buffer(&self, size: u64, usage: BufferUsage) -> Result { + match self { + Device::Vk(d) => d.create_buffer(size, usage).map(Buffer::Vk), + Device::Dx12(d) => d.create_buffer(size, usage).map(Buffer::Dx12), + } + } + + pub unsafe fn destroy_buffer(&self, buffer: &Buffer) -> Result<(), Error> { + match self { + Device::Vk(d) => d.destroy_buffer(buffer.vk()), + Device::Dx12(d) => d.destroy_buffer(buffer.dx12()), + } + } + + pub unsafe fn create_fence(&self, signaled: bool) -> Result { + match self { + Device::Vk(d) => d.create_fence(signaled).map(Fence::Vk), + Device::Dx12(d) => d.create_fence(signaled).map(Fence::Dx12), + } + } + + pub unsafe fn wait_and_reset(&self, fences: &[&Fence]) -> Result<(), Error> { + match self { + Device::Vk(d) => { + let fences = fences + .iter() + .copied() + .map(Fence::vk) + .collect::>(); + d.wait_and_reset(&*fences) + } + Device::Dx12(d) => { + let fences = fences + .iter() + .copied() + .map(Fence::dx12) + .collect::>(); + d.wait_and_reset(&*fences) + } + // Probably need to change device trait to accept &Fence + _ => todo!(), + } + } + + pub unsafe fn pipeline_builder(&self) -> PipelineBuilder { + match self { + Device::Vk(d) => PipelineBuilder::Vk(d.pipeline_builder()), + Device::Dx12(d) => PipelineBuilder::Dx12(d.pipeline_builder()), + } + } + + pub unsafe fn descriptor_set_builder(&self) -> DescriptorSetBuilder { + match self { + Device::Vk(d) => DescriptorSetBuilder::Vk(d.descriptor_set_builder()), + Device::Dx12(d) => DescriptorSetBuilder::Dx12(d.descriptor_set_builder()), + } + } + + pub fn create_cmd_buf(&self) -> Result { + match self { + Device::Vk(d) => d.create_cmd_buf().map(CmdBuf::Vk), + Device::Dx12(d) => d.create_cmd_buf().map(CmdBuf::Dx12), + } + } + + pub fn create_query_pool(&self, n_queries: u32) -> Result { + match self { + Device::Vk(d) => d.create_query_pool(n_queries).map(QueryPool::Vk), + Device::Dx12(d) => d.create_query_pool(n_queries).map(QueryPool::Dx12), + } + } + + pub unsafe fn fetch_query_pool(&self, pool: &QueryPool) -> Result, Error> { + match self { + Device::Vk(d) => d.fetch_query_pool(pool.vk()), + Device::Dx12(d) => d.fetch_query_pool(pool.dx12()), + } + } + + pub unsafe fn run_cmd_bufs( + &self, + cmd_bufs: &[&CmdBuf], + wait_semaphores: &[&Semaphore], + signal_semaphores: &[&Semaphore], + fence: Option<&Fence>, + ) -> Result<(), Error> { + match self { + Device::Vk(d) => d.run_cmd_bufs( + &cmd_bufs + .iter() + .map(|c| c.vk()) + .collect::>(), + &wait_semaphores.iter().copied().map(Semaphore::vk).collect::>(), + &signal_semaphores.iter().copied().map(Semaphore::vk).collect::>(), + fence.map(Fence::vk), + ), + Device::Dx12(d) => d.run_cmd_bufs( + &cmd_bufs + .iter() + .map(|c| c.dx12()) + .collect::>(), + &wait_semaphores.iter().copied().map(Semaphore::dx12).collect::>(), + &signal_semaphores.iter().copied().map(Semaphore::dx12).collect::>(), + fence.map(Fence::dx12), + ), + } + } + + pub unsafe fn read_buffer( + &self, + buffer: &Buffer, + dst: *mut u8, + offset: u64, + size: u64, + ) -> Result<(), Error> { + match self { + Device::Vk(d) => d.read_buffer(buffer.vk(), dst, offset, size), + Device::Dx12(d) => d.read_buffer(buffer.dx12(), dst, offset, size), + } + } + + pub unsafe fn write_buffer( + &self, + buffer: &Buffer, + contents: *const u8, + offset: u64, + size: u64, + ) -> Result<(), Error> { + match self { + Device::Vk(d) => d.write_buffer(buffer.vk(), contents, offset, size), + Device::Dx12(d) => d.write_buffer(buffer.dx12(), contents, offset, size), + } + } +} + +impl PipelineBuilder { + pub fn add_buffers(&mut self, n_buffers: u32) { + match self { + PipelineBuilder::Vk(x) => x.add_buffers(n_buffers), + PipelineBuilder::Dx12(x) => x.add_buffers(n_buffers), + } + } + + pub fn add_images(&mut self, n_buffers: u32) { + match self { + PipelineBuilder::Vk(x) => x.add_images(n_buffers), + PipelineBuilder::Dx12(x) => x.add_images(n_buffers), + } + } + + pub fn add_textures(&mut self, n_buffers: u32) { + match self { + PipelineBuilder::Vk(x) => x.add_textures(n_buffers), + PipelineBuilder::Dx12(x) => x.add_textures(n_buffers), + } + } + + pub unsafe fn create_compute_pipeline<'a>( + self, + device: &Device, + code: ShaderCode<'a>, + ) -> Result { + match self { + PipelineBuilder::Vk(x) => { + let shader_code = match code { + ShaderCode::Spv(spv) => spv, + // Panic or return "incompatible shader" error here? + _ => panic!("Vulkan backend requires shader code in SPIR-V format"), + }; + x.create_compute_pipeline(device.vk(), shader_code) + .map(Pipeline::Vk) + } + PipelineBuilder::Dx12(x) => { + let shader_code = match code { + ShaderCode::Hlsl(hlsl) => hlsl, + // Panic or return "incompatible shader" error here? + _ => panic!("DX12 backend requires shader code in HLSL format"), + }; + x.create_compute_pipeline(device.dx12(), shader_code) + .map(Pipeline::Dx12) + } + } + } +} + +impl DescriptorSetBuilder { + pub fn add_buffers(&mut self, buffers: &[Buffer]) { + match self { + DescriptorSetBuilder::Vk(x) => { + x.add_buffers(&buffers.iter().map(Buffer::vk).collect::>()) + } + DescriptorSetBuilder::Dx12(x) => x.add_buffers( + &buffers + .iter() + .map(Buffer::dx12) + .collect::>(), + ), + } + } + + pub fn add_images(&mut self, images: &[Image]) { + match self { + DescriptorSetBuilder::Vk(x) => { + x.add_images(&images.iter().map(Image::vk).collect::>()) + } + DescriptorSetBuilder::Dx12(x) => { + x.add_images(&images.iter().map(Image::dx12).collect::>()) + } + } + } + + pub fn add_textures(&mut self, images: &[Image]) { + match self { + DescriptorSetBuilder::Vk(x) => { + x.add_textures(&images.iter().map(Image::vk).collect::>()) + } + DescriptorSetBuilder::Dx12(x) => { + x.add_textures(&images.iter().map(Image::dx12).collect::>()) + } + } + } + + pub unsafe fn build( + self, + device: &Device, + pipeline: &Pipeline, + ) -> Result { + match self { + DescriptorSetBuilder::Vk(x) => { + x.build(device.vk(), pipeline.vk()).map(DescriptorSet::Vk) + } + DescriptorSetBuilder::Dx12(x) => x + .build(device.dx12(), pipeline.dx12()) + .map(DescriptorSet::Dx12), + } + } +} + +impl CmdBuf { + pub unsafe fn begin(&mut self) { + match self { + CmdBuf::Vk(c) => c.begin(), + CmdBuf::Dx12(c) => c.begin(), + } + } + + pub unsafe fn finish(&mut self) { + match self { + CmdBuf::Vk(c) => c.finish(), + CmdBuf::Dx12(c) => c.finish(), + } + } + + pub unsafe fn dispatch( + &mut self, + pipeline: &Pipeline, + descriptor_set: &DescriptorSet, + size: (u32, u32, u32), + ) { + match self { + CmdBuf::Vk(c) => c.dispatch(pipeline.vk(), descriptor_set.vk(), size), + CmdBuf::Dx12(c) => c.dispatch(pipeline.dx12(), descriptor_set.dx12(), size), + } + } + + pub unsafe fn memory_barrier(&mut self) { + match self { + CmdBuf::Vk(c) => c.memory_barrier(), + CmdBuf::Dx12(c) => c.memory_barrier(), + } + } + + pub unsafe fn host_barrier(&mut self) { + match self { + CmdBuf::Vk(c) => c.host_barrier(), + CmdBuf::Dx12(c) => c.host_barrier(), + } + } + + pub unsafe fn image_barrier( + &mut self, + image: &Image, + src_layout: ImageLayout, + dst_layout: ImageLayout, + ) { + match self { + CmdBuf::Vk(c) => c.image_barrier(image.vk(), 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) { + match self { + CmdBuf::Vk(c) => c.clear_buffer(buffer.vk(), size), + CmdBuf::Dx12(c) => c.clear_buffer(buffer.dx12(), size), + } + } + + pub unsafe fn copy_buffer(&mut self, src: &Buffer, dst: &Buffer) { + match self { + CmdBuf::Vk(c) => c.copy_buffer(src.vk(), dst.vk()), + CmdBuf::Dx12(c) => c.copy_buffer(src.dx12(), dst.dx12()), + } + } + + pub unsafe fn copy_image_to_buffer(&mut self, src: &Image, dst: &Buffer) { + match self { + CmdBuf::Vk(c) => c.copy_image_to_buffer(src.vk(), dst.vk()), + 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) { + match self { + CmdBuf::Vk(c) => c.copy_buffer_to_image(src.vk(), dst.vk()), + CmdBuf::Dx12(c) => c.copy_buffer_to_image(src.dx12(), dst.dx12()), + } + } + + pub unsafe fn blit_image(&mut self, src: &Image, dst: &Image) { + match self { + CmdBuf::Vk(c) => c.blit_image(src.vk(), dst.vk()), + CmdBuf::Dx12(c) => c.blit_image(src.dx12(), dst.dx12()), + } + } + + pub unsafe fn reset_query_pool(&mut self, pool: &QueryPool) { + match self { + CmdBuf::Vk(c) => c.reset_query_pool(pool.vk()), + CmdBuf::Dx12(c) => c.reset_query_pool(pool.dx12()), + } + } + + pub unsafe fn write_timestamp(&mut self, pool: &QueryPool, query: u32) { + match self { + CmdBuf::Vk(c) => c.write_timestamp(pool.vk(), query), + CmdBuf::Dx12(c) => c.write_timestamp(pool.dx12(), query), + } + } + + pub unsafe fn finish_timestamps(&mut self, pool: &QueryPool) { + match self { + CmdBuf::Vk(c) => c.finish_timestamps(pool.vk()), + CmdBuf::Dx12(c) => c.finish_timestamps(pool.dx12()), + } + } +} diff --git a/piet-gpu-hal/src/vulkan.rs b/piet-gpu-hal/src/vulkan.rs index b93b0c0..a28132b 100644 --- a/piet-gpu-hal/src/vulkan.rs +++ b/piet-gpu-hal/src/vulkan.rs @@ -10,6 +10,8 @@ use ash::extensions::{ext::DebugUtils, khr}; use ash::version::{DeviceV1_0, EntryV1_0, InstanceV1_0, InstanceV1_1}; use ash::{vk, Device, Entry, Instance}; +use smallvec::SmallVec; + use crate::{ BufferUsage, Device as DeviceTrait, Error, GpuInfo, ImageLayout, SamplerParams, SubgroupSize, }; @@ -617,10 +619,15 @@ impl crate::Device for VkDevice { Ok(device.create_semaphore(&vk::SemaphoreCreateInfo::default(), None)?) } - unsafe fn wait_and_reset(&self, fences: &[Self::Fence]) -> Result<(), Error> { + unsafe fn wait_and_reset(&self, fences: &[&Self::Fence]) -> Result<(), Error> { let device = &self.device.device; - device.wait_for_fences(fences, true, !0)?; - device.reset_fences(fences)?; + let fences = fences + .iter() + .copied() + .copied() + .collect::>(); + device.wait_for_fences(&fences, true, !0)?; + device.reset_fences(&fences)?; Ok(()) } @@ -709,8 +716,8 @@ impl crate::Device for VkDevice { unsafe fn run_cmd_bufs( &self, cmd_bufs: &[&CmdBuf], - wait_semaphores: &[Self::Semaphore], - signal_semaphores: &[Self::Semaphore], + wait_semaphores: &[&Self::Semaphore], + signal_semaphores: &[&Self::Semaphore], fence: Option<&Self::Fence>, ) -> Result<(), Error> { let device = &self.device.device; @@ -722,16 +729,28 @@ impl crate::Device for VkDevice { let wait_stages = wait_semaphores .iter() .map(|_| vk::PipelineStageFlags::ALL_COMMANDS) - .collect::>(); - // Use SmallVec or similar here to reduce allocation? - let cmd_bufs = cmd_bufs.iter().map(|c| c.cmd_buf).collect::>(); + .collect::>(); + let cmd_bufs = cmd_bufs + .iter() + .map(|c| c.cmd_buf) + .collect::>(); + let wait_semaphores = wait_semaphores + .iter() + .copied() + .copied() + .collect::>(); + let signal_semaphores = signal_semaphores + .iter() + .copied() + .copied() + .collect::>(); device.queue_submit( self.queue, &[vk::SubmitInfo::builder() .command_buffers(&cmd_bufs) - .wait_semaphores(wait_semaphores) + .wait_semaphores(&wait_semaphores) .wait_dst_stage_mask(&wait_stages) - .signal_semaphores(signal_semaphores) + .signal_semaphores(&signal_semaphores) .build()], fence, )?; diff --git a/piet-gpu/bin/android.rs b/piet-gpu/bin/android.rs index 3bf3ca6..54745c9 100644 --- a/piet-gpu/bin/android.rs +++ b/piet-gpu/bin/android.rs @@ -159,8 +159,8 @@ impl GfxState { self.session .run_cmd_buf( cmd_buf, - &[acquisition_semaphore], - &[self.present_semaphores[frame_idx]], + &[&acquisition_semaphore], + &[&self.present_semaphores[frame_idx]], ) .unwrap(), ); diff --git a/piet-gpu/bin/winit.rs b/piet-gpu/bin/winit.rs index 5eb5be6..20e0aeb 100644 --- a/piet-gpu/bin/winit.rs +++ b/piet-gpu/bin/winit.rs @@ -110,8 +110,8 @@ fn main() -> Result<(), Error> { submitted = Some(session .run_cmd_buf( cmd_buf, - &[acquisition_semaphore], - &[present_semaphores[frame_idx]], + &[&acquisition_semaphore], + &[&present_semaphores[frame_idx]], ) .unwrap()); last_frame_idx = frame_idx; From d15994fe44d6e8f54196e260bc9876fe163e98ff Mon Sep 17 00:00:00 2001 From: Raph Levien Date: Tue, 25 May 2021 17:09:24 -0700 Subject: [PATCH 2/3] Fix cfg'ed backend imports --- piet-gpu-hal/src/lib.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/piet-gpu-hal/src/lib.rs b/piet-gpu-hal/src/lib.rs index 811d51a..58bcb9a 100644 --- a/piet-gpu-hal/src/lib.rs +++ b/piet-gpu-hal/src/lib.rs @@ -14,10 +14,12 @@ pub mod mux; mux! { #[cfg(vk)] + pub mod vulkan; +} +mux! { + #[cfg(dx12)] pub mod dx12; } -#[cfg(not(target_os = "macos"))] -pub mod vulkan; /// This isn't great but is expedient. pub type Error = Box; From 2ecfc7a41437df8703760c8383df382826048518 Mon Sep 17 00:00:00 2001 From: Raph Levien Date: Tue, 25 May 2021 18:06:51 -0700 Subject: [PATCH 3/3] 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. --- piet-gpu-hal/examples/collatz.rs | 8 +- piet-gpu-hal/src/dx12.rs | 7 +- piet-gpu-hal/src/hub.rs | 97 ++++++----- piet-gpu-hal/src/lib.rs | 6 +- piet-gpu-hal/src/macros.rs | 31 +++- piet-gpu-hal/src/mux.rs | 274 +++++++++++++++++++++++-------- piet-gpu-hal/src/vulkan.rs | 9 +- piet-gpu/bin/android.rs | 12 +- piet-gpu/bin/cli.rs | 8 +- piet-gpu/bin/winit.rs | 10 +- piet-gpu/src/lib.rs | 39 +++-- 11 files changed, 337 insertions(+), 164 deletions(-) diff --git a/piet-gpu-hal/examples/collatz.rs b/piet-gpu-hal/examples/collatz.rs index bde4084..5dcce21 100644 --- a/piet-gpu-hal/examples/collatz.rs +++ b/piet-gpu-hal/examples/collatz.rs @@ -1,16 +1,16 @@ use piet_gpu_hal::hub; -use piet_gpu_hal::vulkan::VkInstance; -use piet_gpu_hal::{BufferUsage, CmdBuf}; +use piet_gpu_hal::mux::{Instance, ShaderCode}; +use piet_gpu_hal::BufferUsage; fn main() { - let (instance, _) = VkInstance::new(None).unwrap(); + let (instance, _) = Instance::new(None).unwrap(); unsafe { let device = instance.device(None).unwrap(); let session = hub::Session::new(device); let usage = BufferUsage::MAP_READ | BufferUsage::STORAGE; let src = (0..256).map(|x| x + 1).collect::>(); 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 descriptor_set = session .create_simple_descriptor_set(&pipeline, &[&buffer]) diff --git a/piet-gpu-hal/src/dx12.rs b/piet-gpu-hal/src/dx12.rs index 47801dc..cc9e77b 100644 --- a/piet-gpu-hal/src/dx12.rs +++ b/piet-gpu-hal/src/dx12.rs @@ -24,6 +24,9 @@ pub struct Dx12Instance { // TODO pub struct Dx12Surface; +// TODO +pub struct Dx12Swapchain; + pub struct Dx12Device { device: Device, command_allocator: CommandAllocator, @@ -35,7 +38,7 @@ pub struct Dx12Device { #[derive(Clone)] pub struct Buffer { resource: Resource, - size: u64, + pub size: u64, } #[derive(Clone)] @@ -331,7 +334,7 @@ impl crate::Device for Dx12Device { Ok(()) } - unsafe fn get_fence_status(&self, fence: Self::Fence) -> Result { + unsafe fn get_fence_status(&self, fence: &Self::Fence) -> Result { let fence_val = fence.fence.get_value(); Ok(fence_val == fence.val.get()) } diff --git a/piet-gpu-hal/src/hub.rs b/piet-gpu-hal/src/hub.rs index 5a67ffc..80c03cf 100644 --- a/piet-gpu-hal/src/hub.rs +++ b/piet-gpu-hal/src/hub.rs @@ -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. -//! It is likely that it will also take care of compile time and runtime -//! negotiation of backends (Vulkan, DX12), but right now it's Vulkan-only. +//! This layer is on top of the lower-level layer that multiplexes different +//! back-ends. It handles details such as managing staging buffers for creating +//! 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::sync::{Arc, Mutex, Weak}; -use crate::vulkan; -use crate::CmdBuf as CmdBufTrait; -use crate::DescriptorSetBuilder as DescriptorSetBuilderTrait; -use crate::PipelineBuilder as PipelineBuilderTrait; -use crate::{BufferUsage, Device, Error, GpuInfo, SamplerParams}; +use smallvec::SmallVec; -pub type Semaphore = ::Semaphore; -pub type Pipeline = ::Pipeline; -pub type DescriptorSet = ::DescriptorSet; -pub type QueryPool = ::QueryPool; -pub type Sampler = ::Sampler; +use crate::mux; -type Fence = ::Fence; +use crate::{BufferUsage, Error, GpuInfo, SamplerParams}; -type VkImage = ::Image; -type VkBuffer = ::Buffer; +pub use crate::mux::{DescriptorSet, Fence, Pipeline, QueryPool, Sampler, Semaphore, ShaderCode}; #[derive(Clone)] pub struct Session(Arc); struct SessionInner { - device: vulkan::VkDevice, - cmd_buf_pool: Mutex>, + device: mux::Device, + cmd_buf_pool: Mutex>, /// Command buffers that are still pending (so resources can't be freed). pending: Mutex>, /// A command buffer that is used for copying from staging buffers. @@ -38,7 +31,7 @@ struct SessionInner { } pub struct CmdBuf { - cmd_buf: vulkan::CmdBuf, + cmd_buf: mux::CmdBuf, fence: Fence, resources: Vec, session: Weak, @@ -50,7 +43,7 @@ pub struct SubmittedCmdBuf(Option, Weak); struct SubmittedCmdBufInner { // It's inconsistent, cmd_buf is unpacked, staging_cmd_buf isn't. Probably // better to chose one or the other. - cmd_buf: vulkan::CmdBuf, + cmd_buf: mux::CmdBuf, fence: Fence, resources: Vec, staging_cmd_buf: Option, @@ -60,7 +53,7 @@ struct SubmittedCmdBufInner { pub struct Image(Arc); struct ImageInner { - image: VkImage, + image: mux::Image, session: Weak, } @@ -68,13 +61,13 @@ struct ImageInner { pub struct Buffer(Arc); struct BufferInner { - buffer: VkBuffer, + buffer: mux::Buffer, session: Weak, } -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. pub unsafe trait PlainData {} @@ -97,7 +90,7 @@ pub enum RetainResource { } impl Session { - pub fn new(device: vulkan::VkDevice) -> Session { + pub fn new(device: mux::Device) -> Session { let gpu_info = device.query_gpu_info(); Session(Arc::new(SessionInner { device, @@ -130,7 +123,7 @@ impl Session { unsafe { let mut i = 0; 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); // TODO: wait is superfluous, can just reset let _ = self.0.device.wait_and_reset(&[&item.fence]); @@ -222,7 +215,7 @@ impl Session { let create_buf = self.create_buffer(size, create_usage)?; self.0 .device - .write_buffer(&create_buf.vk_buffer(), contents, 0, size)?; + .write_buffer(&create_buf.mux_buffer(), contents, 0, size)?; if use_staging_buffer { let buf = self.create_buffer(size, usage | BufferUsage::COPY_DST)?; let mut staging_cmd_buf = self.0.staging_cmd_buf.lock().unwrap(); @@ -232,8 +225,8 @@ impl Session { *staging_cmd_buf = Some(cmd_buf); } let staging_cmd_buf = staging_cmd_buf.as_mut().unwrap(); - // This will ensure the staging buffer is deallocated. It would be nice to - staging_cmd_buf.copy_buffer(create_buf.vk_buffer(), buf.vk_buffer()); + // This will ensure the staging buffer is deallocated. + staging_cmd_buf.copy_buffer(create_buf.mux_buffer(), buf.mux_buffer()); staging_cmd_buf.add_resource(create_buf); Ok(buf) } else { @@ -256,9 +249,9 @@ impl Session { /// 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). - pub unsafe fn create_simple_compute_pipeline( + pub unsafe fn create_simple_compute_pipeline<'a>( &self, - code: &[u8], + code: ShaderCode<'a>, n_buffers: u32, ) -> Result { self.pipeline_builder() @@ -295,7 +288,8 @@ impl Session { } pub unsafe fn create_sampler(&self, params: SamplerParams) -> Result { - self.0.device.create_sampler(params) + todo!() + //self.0.device.create_sampler(params) } 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 -/// all methods. +// Probably migrate from deref here to wrapping all methods. impl std::ops::Deref for CmdBuf { - type Target = vulkan::CmdBuf; + type Target = mux::CmdBuf; fn deref(&self) -> &Self::Target { &self.cmd_buf } @@ -382,13 +375,13 @@ impl std::ops::DerefMut for CmdBuf { } impl Image { - pub fn vk_image(&self) -> &vulkan::Image { + pub fn mux_image(&self) -> &mux::Image { &self.0.image } } impl Buffer { - pub fn vk_buffer(&self) -> &vulkan::Buffer { + pub fn mux_buffer(&self) -> &mux::Buffer { &self.0.buffer } @@ -405,7 +398,7 @@ impl Buffer { Ok(()) } pub unsafe fn read(&self, result: &mut Vec) -> Result<(), Error> { - let size = self.vk_buffer().size; + let size = self.mux_buffer().size(); let len = size as usize / std::mem::size_of::(); if len > result.len() { result.reserve(len - result.len()); @@ -440,10 +433,10 @@ impl PipelineBuilder { self } - pub unsafe fn create_compute_pipeline( + pub unsafe fn create_compute_pipeline<'a>( self, session: &Session, - code: &[u8], + code: ShaderCode<'a>, ) -> Result { self.0.create_compute_pipeline(&session.0.device, code) } @@ -451,23 +444,29 @@ impl PipelineBuilder { impl DescriptorSetBuilder { pub fn add_buffers<'a>(mut self, buffers: impl IntoRefs<'a, Buffer>) -> Self { - let vk_buffers = buffers + let mux_buffers = buffers .into_refs() - .map(|b| b.vk_buffer()) - .collect::>(); - self.0.add_buffers(&vk_buffers); + .map(|b| b.mux_buffer()) + .collect::>(); + self.0.add_buffers(&mux_buffers); 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::>(); - self.0.add_images(&vk_images); + let mux_images = images + .into_refs() + .map(|i| i.mux_image()) + .collect::>(); + self.0.add_images(&mux_images); 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::>(); - self.0.add_textures(&vk_images); + let mux_images = images + .into_refs() + .map(|i| i.mux_image()) + .collect::>(); + self.0.add_textures(&mux_images); self } diff --git a/piet-gpu-hal/src/lib.rs b/piet-gpu-hal/src/lib.rs index 58bcb9a..9a16686 100644 --- a/piet-gpu-hal/src/lib.rs +++ b/piet-gpu-hal/src/lib.rs @@ -12,11 +12,11 @@ mod macros; // TODO make this not pub pub mod mux; -mux! { +mux_cfg! { #[cfg(vk)] pub mod vulkan; } -mux! { +mux_cfg! { #[cfg(dx12)] pub mod dx12; } @@ -229,7 +229,7 @@ pub trait Device: Sized { unsafe fn create_semaphore(&self) -> Result; unsafe fn create_fence(&self, signaled: bool) -> Result; unsafe fn wait_and_reset(&self, fences: &[&Self::Fence]) -> Result<(), Error>; - unsafe fn get_fence_status(&self, fence: Self::Fence) -> Result; + unsafe fn get_fence_status(&self, fence: &Self::Fence) -> Result; unsafe fn create_sampler(&self, params: SamplerParams) -> Result; } diff --git a/piet-gpu-hal/src/macros.rs b/piet-gpu-hal/src/macros.rs index f1c1a01..f1d7019 100644 --- a/piet-gpu-hal/src/macros.rs +++ b/piet-gpu-hal/src/macros.rs @@ -17,7 +17,7 @@ //! Macros, mostly to automate backend selection tedium. #[macro_export] -macro_rules! mux { +macro_rules! mux_cfg { ( #[cfg(vk)] $($tokens:tt)* ) => { #[cfg(not(target_os="macos"))] $( $tokens )* }; @@ -41,7 +41,7 @@ macro_rules! mux_enum { } impl $name { - $crate::mux! { + $crate::mux_cfg! { #[cfg(vk)] #[allow(unused)] fn vk(&self) -> &$vk { @@ -52,7 +52,7 @@ macro_rules! mux_enum { } } - $crate::mux! { + $crate::mux_cfg! { #[cfg(dx12)] #[allow(unused)] 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 } + } + }; +} diff --git a/piet-gpu-hal/src/mux.rs b/piet-gpu-hal/src/mux.rs index 45e8879..70525c4 100644 --- a/piet-gpu-hal/src/mux.rs +++ b/piet-gpu-hal/src/mux.rs @@ -18,8 +18,14 @@ use smallvec::SmallVec; -use crate::dx12; -use crate::vulkan; +mux_cfg! { + #[cfg(vk)] + use crate::vulkan; +} +mux_cfg! { + #[cfg(dx12)] + use crate::dx12; +} use crate::CmdBuf as CmdBufTrait; use crate::DescriptorSetBuilder as DescriptorSetBuilderTrait; 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! { Image } mux_device_enum! { Fence } @@ -60,6 +74,7 @@ mux_device_enum! { DescriptorSetBuilder } mux_device_enum! { DescriptorSet } mux_device_enum! { CmdBuf } mux_device_enum! { QueryPool } +mux_device_enum! { Sampler } /// The code for a shader, either as source or intermediate representation. pub enum ShaderCode<'a> { @@ -71,7 +86,7 @@ impl Instance { pub fn new( window_handle: Option<&dyn raw_window_handle::HasRawWindowHandle>, ) -> Result<(Instance, Option), Error> { - mux! { + mux_cfg! { #[cfg(vk)] { let result = vulkan::VkInstance::new(window_handle); @@ -80,7 +95,7 @@ impl Instance { } } } - mux! { + mux_cfg! { #[cfg(dx12)] { let result = dx12::Dx12Instance::new(window_handle); @@ -94,11 +109,26 @@ impl Instance { } pub unsafe fn device(&self, surface: Option<&Surface>) -> Result { - match self { + mux_match! { self; Instance::Vk(i) => i.device(surface.map(Surface::vk)).map(Device::Vk), 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 { + 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, @@ -106,35 +136,49 @@ impl Instance { // missing functionality). impl Device { pub fn query_gpu_info(&self) -> GpuInfo { - match self { + mux_match! { self; Device::Vk(d) => d.query_gpu_info(), Device::Dx12(d) => d.query_gpu_info(), } } pub fn create_buffer(&self, size: u64, usage: BufferUsage) -> Result { - match self { + mux_match! { self; Device::Vk(d) => d.create_buffer(size, usage).map(Buffer::Vk), Device::Dx12(d) => d.create_buffer(size, usage).map(Buffer::Dx12), } } pub unsafe fn destroy_buffer(&self, buffer: &Buffer) -> Result<(), Error> { - match self { + mux_match! { self; Device::Vk(d) => d.destroy_buffer(buffer.vk()), Device::Dx12(d) => d.destroy_buffer(buffer.dx12()), } } + pub unsafe fn create_image2d(&self, width: u32, height: u32) -> Result { + 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 { - match self { + mux_match! { self; Device::Vk(d) => d.create_fence(signaled).map(Fence::Vk), Device::Dx12(d) => d.create_fence(signaled).map(Fence::Dx12), } } pub unsafe fn wait_and_reset(&self, fences: &[&Fence]) -> Result<(), Error> { - match self { + mux_match! { self; Device::Vk(d) => { let fences = fences .iter() @@ -151,41 +195,53 @@ impl Device { .collect::>(); 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 { + 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 { + 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 { - match self { + mux_match! { self; Device::Vk(d) => PipelineBuilder::Vk(d.pipeline_builder()), Device::Dx12(d) => PipelineBuilder::Dx12(d.pipeline_builder()), } } pub unsafe fn descriptor_set_builder(&self) -> DescriptorSetBuilder { - match self { + mux_match! { self; Device::Vk(d) => DescriptorSetBuilder::Vk(d.descriptor_set_builder()), Device::Dx12(d) => DescriptorSetBuilder::Dx12(d.descriptor_set_builder()), } } pub fn create_cmd_buf(&self) -> Result { - match self { + mux_match! { self; Device::Vk(d) => d.create_cmd_buf().map(CmdBuf::Vk), Device::Dx12(d) => d.create_cmd_buf().map(CmdBuf::Dx12), } } pub fn create_query_pool(&self, n_queries: u32) -> Result { - match self { + mux_match! { self; Device::Vk(d) => d.create_query_pool(n_queries).map(QueryPool::Vk), Device::Dx12(d) => d.create_query_pool(n_queries).map(QueryPool::Dx12), } } pub unsafe fn fetch_query_pool(&self, pool: &QueryPool) -> Result, Error> { - match self { + mux_match! { self; Device::Vk(d) => d.fetch_query_pool(pool.vk()), Device::Dx12(d) => d.fetch_query_pool(pool.dx12()), } @@ -198,14 +254,22 @@ impl Device { signal_semaphores: &[&Semaphore], fence: Option<&Fence>, ) -> Result<(), Error> { - match self { + mux_match! { self; Device::Vk(d) => d.run_cmd_bufs( &cmd_bufs .iter() .map(|c| c.vk()) .collect::>(), - &wait_semaphores.iter().copied().map(Semaphore::vk).collect::>(), - &signal_semaphores.iter().copied().map(Semaphore::vk).collect::>(), + &wait_semaphores + .iter() + .copied() + .map(Semaphore::vk) + .collect::>(), + &signal_semaphores + .iter() + .copied() + .map(Semaphore::vk) + .collect::>(), fence.map(Fence::vk), ), Device::Dx12(d) => d.run_cmd_bufs( @@ -213,8 +277,16 @@ impl Device { .iter() .map(|c| c.dx12()) .collect::>(), - &wait_semaphores.iter().copied().map(Semaphore::dx12).collect::>(), - &signal_semaphores.iter().copied().map(Semaphore::dx12).collect::>(), + &wait_semaphores + .iter() + .copied() + .map(Semaphore::dx12) + .collect::>(), + &signal_semaphores + .iter() + .copied() + .map(Semaphore::dx12) + .collect::>(), fence.map(Fence::dx12), ), } @@ -227,7 +299,7 @@ impl Device { offset: u64, size: u64, ) -> Result<(), Error> { - match self { + mux_match! { self; Device::Vk(d) => d.read_buffer(buffer.vk(), dst, offset, size), Device::Dx12(d) => d.read_buffer(buffer.dx12(), dst, offset, size), } @@ -240,7 +312,7 @@ impl Device { offset: u64, size: u64, ) -> Result<(), Error> { - match self { + mux_match! { self; Device::Vk(d) => d.write_buffer(buffer.vk(), contents, offset, size), Device::Dx12(d) => d.write_buffer(buffer.dx12(), contents, offset, size), } @@ -249,21 +321,21 @@ impl Device { impl PipelineBuilder { pub fn add_buffers(&mut self, n_buffers: u32) { - match self { + mux_match! { self; PipelineBuilder::Vk(x) => x.add_buffers(n_buffers), PipelineBuilder::Dx12(x) => x.add_buffers(n_buffers), } } pub fn add_images(&mut self, n_buffers: u32) { - match self { + mux_match! { self; PipelineBuilder::Vk(x) => x.add_images(n_buffers), PipelineBuilder::Dx12(x) => x.add_images(n_buffers), } } pub fn add_textures(&mut self, n_buffers: u32) { - match self { + mux_match! { self; PipelineBuilder::Vk(x) => x.add_textures(n_buffers), PipelineBuilder::Dx12(x) => x.add_textures(n_buffers), } @@ -274,7 +346,7 @@ impl PipelineBuilder { device: &Device, code: ShaderCode<'a>, ) -> Result { - match self { + mux_match! { self; PipelineBuilder::Vk(x) => { let shader_code = match code { ShaderCode::Spv(spv) => spv, @@ -298,39 +370,60 @@ impl PipelineBuilder { } impl DescriptorSetBuilder { - pub fn add_buffers(&mut self, buffers: &[Buffer]) { - match self { - DescriptorSetBuilder::Vk(x) => { - x.add_buffers(&buffers.iter().map(Buffer::vk).collect::>()) - } + pub fn add_buffers(&mut self, buffers: &[&Buffer]) { + mux_match! { self; + DescriptorSetBuilder::Vk(x) => x.add_buffers( + &buffers + .iter() + .copied() + .map(Buffer::vk) + .collect::>(), + ), DescriptorSetBuilder::Dx12(x) => x.add_buffers( &buffers .iter() + .copied() .map(Buffer::dx12) .collect::>(), ), } } - pub fn add_images(&mut self, images: &[Image]) { - match self { - DescriptorSetBuilder::Vk(x) => { - x.add_images(&images.iter().map(Image::vk).collect::>()) - } - DescriptorSetBuilder::Dx12(x) => { - x.add_images(&images.iter().map(Image::dx12).collect::>()) - } + pub fn add_images(&mut self, images: &[&Image]) { + mux_match! { self; + DescriptorSetBuilder::Vk(x) => x.add_images( + &images + .iter() + .copied() + .map(Image::vk) + .collect::>(), + ), + DescriptorSetBuilder::Dx12(x) => x.add_images( + &images + .iter() + .copied() + .map(Image::dx12) + .collect::>(), + ), } } - pub fn add_textures(&mut self, images: &[Image]) { - match self { - DescriptorSetBuilder::Vk(x) => { - x.add_textures(&images.iter().map(Image::vk).collect::>()) - } - DescriptorSetBuilder::Dx12(x) => { - x.add_textures(&images.iter().map(Image::dx12).collect::>()) - } + pub fn add_textures(&mut self, images: &[&Image]) { + mux_match! { self; + DescriptorSetBuilder::Vk(x) => x.add_textures( + &images + .iter() + .copied() + .map(Image::vk) + .collect::>(), + ), + DescriptorSetBuilder::Dx12(x) => x.add_textures( + &images + .iter() + .copied() + .map(Image::dx12) + .collect::>(), + ), } } @@ -339,10 +432,9 @@ impl DescriptorSetBuilder { device: &Device, pipeline: &Pipeline, ) -> Result { - match self { - DescriptorSetBuilder::Vk(x) => { - x.build(device.vk(), pipeline.vk()).map(DescriptorSet::Vk) - } + mux_match! { self; + DescriptorSetBuilder::Vk(x) => + x.build(device.vk(), pipeline.vk()).map(DescriptorSet::Vk), DescriptorSetBuilder::Dx12(x) => x .build(device.dx12(), pipeline.dx12()) .map(DescriptorSet::Dx12), @@ -352,14 +444,14 @@ impl DescriptorSetBuilder { impl CmdBuf { pub unsafe fn begin(&mut self) { - match self { + mux_match! { self; CmdBuf::Vk(c) => c.begin(), CmdBuf::Dx12(c) => c.begin(), } } pub unsafe fn finish(&mut self) { - match self { + mux_match! { self; CmdBuf::Vk(c) => c.finish(), CmdBuf::Dx12(c) => c.finish(), } @@ -371,21 +463,21 @@ impl CmdBuf { descriptor_set: &DescriptorSet, size: (u32, u32, u32), ) { - match self { + mux_match! { self; CmdBuf::Vk(c) => c.dispatch(pipeline.vk(), descriptor_set.vk(), size), CmdBuf::Dx12(c) => c.dispatch(pipeline.dx12(), descriptor_set.dx12(), size), } } pub unsafe fn memory_barrier(&mut self) { - match self { + mux_match! { self; CmdBuf::Vk(c) => c.memory_barrier(), CmdBuf::Dx12(c) => c.memory_barrier(), } } pub unsafe fn host_barrier(&mut self) { - match self { + mux_match! { self; CmdBuf::Vk(c) => c.host_barrier(), CmdBuf::Dx12(c) => c.host_barrier(), } @@ -397,65 +489,113 @@ impl CmdBuf { src_layout: ImageLayout, dst_layout: ImageLayout, ) { - match self { + mux_match! { self; CmdBuf::Vk(c) => c.image_barrier(image.vk(), 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) { - match self { + mux_match! { self; CmdBuf::Vk(c) => c.clear_buffer(buffer.vk(), size), CmdBuf::Dx12(c) => c.clear_buffer(buffer.dx12(), size), } } 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::Dx12(c) => c.copy_buffer(src.dx12(), dst.dx12()), } } 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::Dx12(c) => c.copy_image_to_buffer(src.dx12(), dst.dx12()), } } 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::Dx12(c) => c.copy_buffer_to_image(src.dx12(), dst.dx12()), } } 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::Dx12(c) => c.blit_image(src.dx12(), dst.dx12()), } } 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::Dx12(c) => c.reset_query_pool(pool.dx12()), } } 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::Dx12(c) => c.write_timestamp(pool.dx12(), query), } } pub unsafe fn finish_timestamps(&mut self, pool: &QueryPool) { - match self { + mux_match! { self; CmdBuf::Vk(c) => c.finish_timestamps(pool.vk()), 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 { + mux_match! { self; + Swapchain::Vk(s) => s.present( + image_idx, + &semaphores + .iter() + .copied() + .map(Semaphore::vk) + .collect::>(), + ), + Swapchain::Dx12(_s) => todo!(), + } + } +} diff --git a/piet-gpu-hal/src/vulkan.rs b/piet-gpu-hal/src/vulkan.rs index a28132b..619c6bd 100644 --- a/piet-gpu-hal/src/vulkan.rs +++ b/piet-gpu-hal/src/vulkan.rs @@ -631,9 +631,9 @@ impl crate::Device for VkDevice { Ok(()) } - unsafe fn get_fence_status(&self, fence: Self::Fence) -> Result { + unsafe fn get_fence_status(&self, fence: &Self::Fence) -> Result { let device = &self.device.device; - Ok(device.get_fence_status(fence)?) + Ok(device.get_fence_status(*fence)?) } unsafe fn pipeline_builder(&self) -> PipelineBuilder { @@ -1306,14 +1306,15 @@ impl VkSwapchain { pub unsafe fn present( &self, image_idx: usize, - semaphores: &[vk::Semaphore], + semaphores: &[&vk::Semaphore], ) -> Result { + let semaphores = semaphores.iter().copied().copied().collect::>(); Ok(self.swapchain_fn.queue_present( self.present_queue, &vk::PresentInfoKHR::builder() .swapchains(&[self.swapchain]) .image_indices(&[image_idx as u32]) - .wait_semaphores(semaphores) + .wait_semaphores(&semaphores) .build(), )?) } diff --git a/piet-gpu/bin/android.rs b/piet-gpu/bin/android.rs index 54745c9..63ee91a 100644 --- a/piet-gpu/bin/android.rs +++ b/piet-gpu/bin/android.rs @@ -12,7 +12,7 @@ use ndk::native_window::NativeWindow; use ndk_glue::Event; 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::{render_scene, PietGpuRenderContext, Renderer}; @@ -30,7 +30,7 @@ struct MyHandle { struct GfxState { session: hub::Session, renderer: Renderer, - swapchain: VkSwapchain, + swapchain: Swapchain, current_frame: usize, last_frame_idx: usize, submitted: Option, @@ -52,7 +52,7 @@ fn my_main() -> Result<(), Error> { let window = ndk_glue::native_window(); if let Some(window) = &*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())?); } else { println!("native window is sadly none"); @@ -90,7 +90,7 @@ unsafe impl HasRawWindowHandle for MyHandle { } impl GfxState { - fn new(instance: &VkInstance, surface: Option<&VkSurface>) -> Result { + fn new(instance: &Instance, surface: Option<&Surface>) -> Result { unsafe { let device = instance.device(surface)?; let mut swapchain = @@ -151,7 +151,7 @@ impl GfxState { // Image -> Swapchain 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.finish(); @@ -167,7 +167,7 @@ impl GfxState { self.last_frame_idx = frame_idx; self.swapchain - .present(image_idx, &[self.present_semaphores[frame_idx]]) + .present(image_idx, &[&self.present_semaphores[frame_idx]]) .unwrap(); self.current_frame += 1; diff --git a/piet-gpu/bin/cli.rs b/piet-gpu/bin/cli.rs index 69e0fc4..a1d766d 100644 --- a/piet-gpu/bin/cli.rs +++ b/piet-gpu/bin/cli.rs @@ -5,8 +5,8 @@ use std::path::Path; use clap::{App, Arg}; use piet_gpu_hal::hub; -use piet_gpu_hal::vulkan::VkInstance; -use piet_gpu_hal::{BufferUsage, CmdBuf, Error}; +use piet_gpu_hal::mux::Instance; +use piet_gpu_hal::{BufferUsage, Error}; use piet_gpu::{render_scene, render_svg, PietGpuRenderContext, Renderer, HEIGHT, WIDTH}; @@ -225,7 +225,7 @@ fn main() -> Result<(), Error> { .takes_value(true), ) .get_matches(); - let (instance, _) = VkInstance::new(None)?; + let (instance, _) = Instance::new(None)?; unsafe { let device = instance.device(None)?; let session = hub::Session::new(device); @@ -258,7 +258,7 @@ fn main() -> Result<(), Error> { cmd_buf.begin(); 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.finish(); let start = std::time::Instant::now(); diff --git a/piet-gpu/bin/winit.rs b/piet-gpu/bin/winit.rs index 20e0aeb..af60a3a 100644 --- a/piet-gpu/bin/winit.rs +++ b/piet-gpu/bin/winit.rs @@ -1,6 +1,6 @@ use piet_gpu_hal::hub; -use piet_gpu_hal::vulkan::VkInstance; -use piet_gpu_hal::{CmdBuf, Error, ImageLayout}; +use piet_gpu_hal::mux::Instance; +use piet_gpu_hal::{Error, ImageLayout}; use piet_gpu::{render_scene, PietGpuRenderContext, Renderer, HEIGHT, WIDTH}; @@ -22,7 +22,7 @@ fn main() -> Result<(), Error> { .with_resizable(false) // currently not supported .build(&event_loop)?; - let (instance, surface) = VkInstance::new(Some(&window))?; + let (instance, surface) = Instance::new(Some(&window))?; unsafe { let device = instance.device(surface.as_ref())?; let mut swapchain = @@ -103,7 +103,7 @@ fn main() -> Result<(), Error> { ImageLayout::Undefined, 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.finish(); @@ -117,7 +117,7 @@ fn main() -> Result<(), Error> { last_frame_idx = frame_idx; swapchain - .present(image_idx, &[present_semaphores[frame_idx]]) + .present(image_idx, &[&present_semaphores[frame_idx]]) .unwrap(); current_frame += 1; diff --git a/piet-gpu/src/lib.rs b/piet-gpu/src/lib.rs index 3c87f68..2b8ed0f 100644 --- a/piet-gpu/src/lib.rs +++ b/piet-gpu/src/lib.rs @@ -13,7 +13,8 @@ use piet::{Color, ImageFormat, RenderContext}; use piet_gpu_types::encoder::Encode; 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; @@ -292,35 +293,35 @@ impl Renderer { let memory_buf_dev = session.create_buffer(128 * 1024 * 1024, dev)?; 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_ds = session.create_simple_descriptor_set( &el_pipeline, &[&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_ds = session .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_ds = session .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_ds = session .create_simple_descriptor_set(&backdrop_pipeline, &[&memory_buf_dev, &config_buf])?; // 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_ds = 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_ds = session .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 k4_code = if session.gpu_info().has_descriptor_indexing { - &include_bytes!("../shader/kernel4_idx.spv")[..] + ShaderCode::Spv(include_bytes!("../shader/kernel4_idx.spv")) } else { 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 // 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) { cmd_buf.copy_buffer( - self.memory_buf_host.vk_buffer(), - self.memory_buf_dev.vk_buffer(), + self.memory_buf_host.mux_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.image_barrier( - self.image_dev.vk_image(), + self.image_dev.mux_image(), ImageLayout::Undefined, ImageLayout::General, ); @@ -451,7 +452,7 @@ impl Renderer { cmd_buf.write_timestamp(&query_pool, 7); cmd_buf.memory_barrier(); cmd_buf.image_barrier( - self.image_dev.vk_image(), + self.image_dev.mux_image(), ImageLayout::General, ImageLayout::BlitSrc, ); @@ -475,12 +476,16 @@ impl Renderer { let mut cmd_buf = session.cmd_buf()?; cmd_buf.begin(); cmd_buf.image_barrier( - image.vk_image(), + image.mux_image(), ImageLayout::Undefined, ImageLayout::BlitDst, ); - cmd_buf.copy_buffer_to_image(buffer.vk_buffer(), image.vk_image()); - cmd_buf.image_barrier(image.vk_image(), ImageLayout::BlitDst, ImageLayout::General); + cmd_buf.copy_buffer_to_image(buffer.mux_buffer(), image.mux_image()); + cmd_buf.image_barrier( + image.mux_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);