From 5e221d2e91b772f1d23aa3148302eae86f4e48de Mon Sep 17 00:00:00 2001 From: Raph Levien Date: Sat, 25 Dec 2021 16:55:13 -0800 Subject: [PATCH] Add capability to function as a guest in Metal WIP --- piet-gpu-hal/src/lib.rs | 2 +- piet-gpu-hal/src/metal.rs | 76 +++++++++++++++++++++------------------ piet-gpu-hal/src/mux.rs | 5 +++ 3 files changed, 47 insertions(+), 36 deletions(-) diff --git a/piet-gpu-hal/src/lib.rs b/piet-gpu-hal/src/lib.rs index a0a4da3..be0c1d6 100644 --- a/piet-gpu-hal/src/lib.rs +++ b/piet-gpu-hal/src/lib.rs @@ -16,7 +16,7 @@ mod macros; mod mux; pub use crate::mux::{ - DescriptorSet, Fence, Instance, Pipeline, QueryPool, Sampler, Semaphore, ShaderCode, Surface, + DescriptorSet, Device, Fence, Instance, Pipeline, QueryPool, Sampler, Semaphore, ShaderCode, Surface, Swapchain, }; pub use bufwrite::BufWrite; diff --git a/piet-gpu-hal/src/metal.rs b/piet-gpu-hal/src/metal.rs index 45e0406..dd622fc 100644 --- a/piet-gpu-hal/src/metal.rs +++ b/piet-gpu-hal/src/metal.rs @@ -153,41 +153,7 @@ impl MtlInstance { pub fn device(&self, _surface: Option<&MtlSurface>) -> Result { if let Some(device) = metal::Device::system_default() { let cmd_queue = device.new_command_queue(); - let is_mac = device.supports_feature_set(MTLFeatureSet::macOS_GPUFamily1_v1); - let is_ios = device.supports_feature_set(MTLFeatureSet::iOS_GPUFamily1_v1); - let version = NSOperatingSystemVersion::get(); - - let use_staging_buffers = - if (is_mac && version.at_least(10, 15)) || (is_ios && version.at_least(13, 0)) { - !device.has_unified_memory() - } else { - !device.is_low_power() - }; - // TODO: these are conservative; we need to derive these from - // supports_feature_set queries. - let gpu_info = GpuInfo { - has_descriptor_indexing: false, - has_subgroups: false, - subgroup_size: None, - // The workgroup limits are taken from the minimum of a desktop installation; - // we don't support iOS right now, but in case of testing on those devices it might - // need to change these (or just queried properly). - workgroup_limits: WorkgroupLimits { - max_size: [1024, 1024, 64], - max_invocations: 1024, - }, - has_memory_model: false, - use_staging_buffers, - }; - let helpers = Arc::new(Helpers { - clear_pipeline: clear::make_clear_pipeline(&device), - }); - Ok(MtlDevice { - device, - cmd_queue: Arc::new(Mutex::new(cmd_queue)), - gpu_info, - helpers, - }) + Ok(MtlDevice::new_from_raw_mtl(device, cmd_queue)) } else { Err("can't create system default Metal device".into()) } @@ -212,6 +178,46 @@ impl MtlInstance { } } +impl MtlDevice { + pub fn new_from_raw_mtl(device: metal::Device, cmd_queue: metal::CommandQueue) -> MtlDevice { + let is_mac = device.supports_feature_set(MTLFeatureSet::macOS_GPUFamily1_v1); + let is_ios = device.supports_feature_set(MTLFeatureSet::iOS_GPUFamily1_v1); + let version = NSOperatingSystemVersion::get(); + + let use_staging_buffers = + if (is_mac && version.at_least(10, 15)) || (is_ios && version.at_least(13, 0)) { + !device.has_unified_memory() + } else { + !device.is_low_power() + }; + // TODO: these are conservative; we need to derive these from + // supports_feature_set queries. + let gpu_info = GpuInfo { + has_descriptor_indexing: false, + has_subgroups: false, + subgroup_size: None, + // The workgroup limits are taken from the minimum of a desktop installation; + // we don't support iOS right now, but in case of testing on those devices it might + // need to change these (or just queried properly). + workgroup_limits: WorkgroupLimits { + max_size: [1024, 1024, 64], + max_invocations: 1024, + }, + has_memory_model: false, + use_staging_buffers, + }; + let helpers = Arc::new(Helpers { + clear_pipeline: clear::make_clear_pipeline(&device), + }); + MtlDevice { + device, + cmd_queue: Arc::new(Mutex::new(cmd_queue)), + gpu_info, + helpers, + } + } +} + impl crate::backend::Device for MtlDevice { type Buffer = Buffer; diff --git a/piet-gpu-hal/src/mux.rs b/piet-gpu-hal/src/mux.rs index 24fef5c..654a77b 100644 --- a/piet-gpu-hal/src/mux.rs +++ b/piet-gpu-hal/src/mux.rs @@ -208,6 +208,11 @@ impl Instance { // but not doing so lets us diverge more easily (at the moment, the divergence is // missing functionality). impl Device { + #[cfg(target_os = "macos")] + pub fn new_from_raw_mtl(device: &::metal::DeviceRef, queue: &::metal::CommandQueueRef) -> Device { + Device::Mtl(metal::MtlDevice::new_from_raw_mtl(device.to_owned(), queue.to_owned())) + } + pub fn query_gpu_info(&self) -> GpuInfo { mux_match! { self; Device::Vk(d) => d.query_gpu_info(),