From 9272cc65cc70d6aba9dcba1d7eaf567365eb299b Mon Sep 17 00:00:00 2001 From: Xiaopeng Li Date: Thu, 13 Oct 2022 14:13:31 +0800 Subject: [PATCH] Fix memory leak on macOS (#3056) --- wgpu-hal/src/metal/command.rs | 12 +- wgpu-hal/src/metal/device.rs | 741 +++++++++++++++++----------------- 2 files changed, 386 insertions(+), 367 deletions(-) diff --git a/wgpu-hal/src/metal/command.rs b/wgpu-hal/src/metal/command.rs index 3bc07d21e7..3b94c71ed0 100644 --- a/wgpu-hal/src/metal/command.rs +++ b/wgpu-hal/src/metal/command.rs @@ -905,11 +905,13 @@ impl crate::CommandEncoder for super::CommandEncoder { self.begin_pass(); let raw = self.raw_cmd_buf.as_ref().unwrap(); - let encoder = raw.new_compute_command_encoder(); - if let Some(label) = desc.label { - encoder.set_label(label); - } - self.state.compute = Some(encoder.to_owned()); + objc::rc::autoreleasepool(|| { + let encoder = raw.new_compute_command_encoder(); + if let Some(label) = desc.label { + encoder.set_label(label); + } + self.state.compute = Some(encoder.to_owned()); + }); } unsafe fn end_compute_pass(&mut self) { self.state.compute.take().unwrap().end_encoding(); diff --git a/wgpu-hal/src/metal/device.rs b/wgpu-hal/src/metal/device.rs index 04810ec458..9ff02a4413 100644 --- a/wgpu-hal/src/metal/device.rs +++ b/wgpu-hal/src/metal/device.rs @@ -235,13 +235,15 @@ impl crate::Device for super::Device { //TODO: HazardTrackingModeUntracked - let raw = self.shared.device.lock().new_buffer(desc.size, options); - if let Some(label) = desc.label { - raw.set_label(label); - } - Ok(super::Buffer { - raw, - size: desc.size, + objc::rc::autoreleasepool(|| { + let raw = self.shared.device.lock().new_buffer(desc.size, options); + if let Some(label) = desc.label { + raw.set_label(label); + } + Ok(super::Buffer { + raw, + size: desc.size, + }) }) } unsafe fn destroy_buffer(&self, _buffer: super::Buffer) {} @@ -271,61 +273,63 @@ impl crate::Device for super::Device { ) -> DeviceResult { let mtl_format = self.shared.private_caps.map_format(desc.format); - let descriptor = mtl::TextureDescriptor::new(); - let mut array_layers = desc.size.depth_or_array_layers; - let mut copy_size = crate::CopyExtent { - width: desc.size.width, - height: desc.size.height, - depth: 1, - }; - let mtl_type = match desc.dimension { - wgt::TextureDimension::D1 => { - if desc.size.depth_or_array_layers > 1 { - descriptor.set_array_length(desc.size.depth_or_array_layers as u64); - mtl::MTLTextureType::D1Array - } else { - mtl::MTLTextureType::D1 + objc::rc::autoreleasepool(|| { + let descriptor = mtl::TextureDescriptor::new(); + let mut array_layers = desc.size.depth_or_array_layers; + let mut copy_size = crate::CopyExtent { + width: desc.size.width, + height: desc.size.height, + depth: 1, + }; + let mtl_type = match desc.dimension { + wgt::TextureDimension::D1 => { + if desc.size.depth_or_array_layers > 1 { + descriptor.set_array_length(desc.size.depth_or_array_layers as u64); + mtl::MTLTextureType::D1Array + } else { + mtl::MTLTextureType::D1 + } } - } - wgt::TextureDimension::D2 => { - if desc.sample_count > 1 { - descriptor.set_sample_count(desc.sample_count as u64); - mtl::MTLTextureType::D2Multisample - } else if desc.size.depth_or_array_layers > 1 { - descriptor.set_array_length(desc.size.depth_or_array_layers as u64); - mtl::MTLTextureType::D2Array - } else { - mtl::MTLTextureType::D2 + wgt::TextureDimension::D2 => { + if desc.sample_count > 1 { + descriptor.set_sample_count(desc.sample_count as u64); + mtl::MTLTextureType::D2Multisample + } else if desc.size.depth_or_array_layers > 1 { + descriptor.set_array_length(desc.size.depth_or_array_layers as u64); + mtl::MTLTextureType::D2Array + } else { + mtl::MTLTextureType::D2 + } } + wgt::TextureDimension::D3 => { + descriptor.set_depth(desc.size.depth_or_array_layers as u64); + array_layers = 1; + copy_size.depth = desc.size.depth_or_array_layers; + mtl::MTLTextureType::D3 + } + }; + + descriptor.set_texture_type(mtl_type); + descriptor.set_width(desc.size.width as u64); + descriptor.set_height(desc.size.height as u64); + descriptor.set_mipmap_level_count(desc.mip_level_count as u64); + descriptor.set_pixel_format(mtl_format); + descriptor.set_usage(conv::map_texture_usage(desc.usage)); + descriptor.set_storage_mode(mtl::MTLStorageMode::Private); + + let raw = self.shared.device.lock().new_texture(&descriptor); + if let Some(label) = desc.label { + raw.set_label(label); } - wgt::TextureDimension::D3 => { - descriptor.set_depth(desc.size.depth_or_array_layers as u64); - array_layers = 1; - copy_size.depth = desc.size.depth_or_array_layers; - mtl::MTLTextureType::D3 - } - }; - descriptor.set_texture_type(mtl_type); - descriptor.set_width(desc.size.width as u64); - descriptor.set_height(desc.size.height as u64); - descriptor.set_mipmap_level_count(desc.mip_level_count as u64); - descriptor.set_pixel_format(mtl_format); - descriptor.set_usage(conv::map_texture_usage(desc.usage)); - descriptor.set_storage_mode(mtl::MTLStorageMode::Private); - - let raw = self.shared.device.lock().new_texture(&descriptor); - if let Some(label) = desc.label { - raw.set_label(label); - } - - Ok(super::Texture { - raw, - raw_format: mtl_format, - raw_type: mtl_type, - mip_levels: desc.mip_level_count, - array_layers, - copy_size, + Ok(super::Texture { + raw, + raw_format: mtl_format, + raw_type: mtl_type, + mip_levels: desc.mip_level_count, + array_layers, + copy_size, + }) }) } @@ -363,24 +367,24 @@ impl crate::Device for super::Device { None => texture.array_layers - desc.range.base_array_layer, }; - let raw = texture.raw.new_texture_view_from_slice( - raw_format, - raw_type, - mtl::NSRange { - location: desc.range.base_mip_level as _, - length: mip_level_count as _, - }, - mtl::NSRange { - location: desc.range.base_array_layer as _, - length: array_layer_count as _, - }, - ); - if let Some(label) = desc.label { - objc::rc::autoreleasepool(|| { + objc::rc::autoreleasepool(|| { + let raw = texture.raw.new_texture_view_from_slice( + raw_format, + raw_type, + mtl::NSRange { + location: desc.range.base_mip_level as _, + length: mip_level_count as _, + }, + mtl::NSRange { + location: desc.range.base_array_layer as _, + length: array_layer_count as _, + }, + ); + if let Some(label) = desc.label { raw.set_label(label); - }); - } - raw + } + raw + }) }; let aspects = crate::FormatAspects::from(desc.format); @@ -393,64 +397,66 @@ impl crate::Device for super::Device { desc: &crate::SamplerDescriptor, ) -> DeviceResult { let caps = &self.shared.private_caps; - let descriptor = mtl::SamplerDescriptor::new(); + objc::rc::autoreleasepool(|| { + let descriptor = mtl::SamplerDescriptor::new(); - descriptor.set_min_filter(conv::map_filter_mode(desc.min_filter)); - descriptor.set_mag_filter(conv::map_filter_mode(desc.mag_filter)); - descriptor.set_mip_filter(match desc.mipmap_filter { - wgt::FilterMode::Nearest if desc.lod_clamp.is_none() => { - mtl::MTLSamplerMipFilter::NotMipmapped + descriptor.set_min_filter(conv::map_filter_mode(desc.min_filter)); + descriptor.set_mag_filter(conv::map_filter_mode(desc.mag_filter)); + descriptor.set_mip_filter(match desc.mipmap_filter { + wgt::FilterMode::Nearest if desc.lod_clamp.is_none() => { + mtl::MTLSamplerMipFilter::NotMipmapped + } + wgt::FilterMode::Nearest => mtl::MTLSamplerMipFilter::Nearest, + wgt::FilterMode::Linear => mtl::MTLSamplerMipFilter::Linear, + }); + + let [s, t, r] = desc.address_modes; + descriptor.set_address_mode_s(conv::map_address_mode(s)); + descriptor.set_address_mode_t(conv::map_address_mode(t)); + descriptor.set_address_mode_r(conv::map_address_mode(r)); + + if let Some(aniso) = desc.anisotropy_clamp { + descriptor.set_max_anisotropy(aniso.get() as _); } - wgt::FilterMode::Nearest => mtl::MTLSamplerMipFilter::Nearest, - wgt::FilterMode::Linear => mtl::MTLSamplerMipFilter::Linear, - }); - let [s, t, r] = desc.address_modes; - descriptor.set_address_mode_s(conv::map_address_mode(s)); - descriptor.set_address_mode_t(conv::map_address_mode(t)); - descriptor.set_address_mode_r(conv::map_address_mode(r)); - - if let Some(aniso) = desc.anisotropy_clamp { - descriptor.set_max_anisotropy(aniso.get() as _); - } - - if let Some(ref range) = desc.lod_clamp { - descriptor.set_lod_min_clamp(range.start); - descriptor.set_lod_max_clamp(range.end); - } - - if caps.sampler_lod_average { - descriptor.set_lod_average(true); // optimization - } - - if let Some(fun) = desc.compare { - descriptor.set_compare_function(conv::map_compare_function(fun)); - } - - if let Some(border_color) = desc.border_color { - if let wgt::SamplerBorderColor::Zero = border_color { - if s == wgt::AddressMode::ClampToBorder { - descriptor.set_address_mode_s(mtl::MTLSamplerAddressMode::ClampToZero); - } - - if t == wgt::AddressMode::ClampToBorder { - descriptor.set_address_mode_t(mtl::MTLSamplerAddressMode::ClampToZero); - } - - if r == wgt::AddressMode::ClampToBorder { - descriptor.set_address_mode_r(mtl::MTLSamplerAddressMode::ClampToZero); - } - } else { - descriptor.set_border_color(conv::map_border_color(border_color)); + if let Some(ref range) = desc.lod_clamp { + descriptor.set_lod_min_clamp(range.start); + descriptor.set_lod_max_clamp(range.end); } - } - if let Some(label) = desc.label { - descriptor.set_label(label); - } - let raw = self.shared.device.lock().new_sampler(&descriptor); + if caps.sampler_lod_average { + descriptor.set_lod_average(true); // optimization + } - Ok(super::Sampler { raw }) + if let Some(fun) = desc.compare { + descriptor.set_compare_function(conv::map_compare_function(fun)); + } + + if let Some(border_color) = desc.border_color { + if let wgt::SamplerBorderColor::Zero = border_color { + if s == wgt::AddressMode::ClampToBorder { + descriptor.set_address_mode_s(mtl::MTLSamplerAddressMode::ClampToZero); + } + + if t == wgt::AddressMode::ClampToBorder { + descriptor.set_address_mode_t(mtl::MTLSamplerAddressMode::ClampToZero); + } + + if r == wgt::AddressMode::ClampToBorder { + descriptor.set_address_mode_r(mtl::MTLSamplerAddressMode::ClampToZero); + } + } else { + descriptor.set_border_color(conv::map_border_color(border_color)); + } + } + + if let Some(label) = desc.label { + descriptor.set_label(label); + } + let raw = self.shared.device.lock().new_sampler(&descriptor); + + Ok(super::Sampler { raw }) + }) } unsafe fn destroy_sampler(&self, _sampler: super::Sampler) {} @@ -784,201 +790,205 @@ impl crate::Device for super::Device { &self, desc: &crate::RenderPipelineDescriptor, ) -> Result { - let descriptor = mtl::RenderPipelineDescriptor::new(); + objc::rc::autoreleasepool(|| { + let descriptor = mtl::RenderPipelineDescriptor::new(); - let raw_triangle_fill_mode = match desc.primitive.polygon_mode { - wgt::PolygonMode::Fill => mtl::MTLTriangleFillMode::Fill, - wgt::PolygonMode::Line => mtl::MTLTriangleFillMode::Lines, - wgt::PolygonMode::Point => panic!( - "{:?} is not enabled for this backend", - wgt::Features::POLYGON_MODE_POINT - ), - }; - - let (primitive_class, raw_primitive_type) = - conv::map_primitive_topology(desc.primitive.topology); - - let vs = self.load_shader( - &desc.vertex_stage, - desc.layout, - primitive_class, - naga::ShaderStage::Vertex, - )?; - - descriptor.set_vertex_function(Some(&vs.function)); - if self.shared.private_caps.supports_mutability { - Self::set_buffers_mutability( - descriptor.vertex_buffers().unwrap(), - vs.immutable_buffer_mask, - ); - } - - // Fragment shader - let (fs_lib, fs_sized_bindings) = match desc.fragment_stage { - Some(ref stage) => { - let fs = self.load_shader( - stage, - desc.layout, - primitive_class, - naga::ShaderStage::Fragment, - )?; - descriptor.set_fragment_function(Some(&fs.function)); - if self.shared.private_caps.supports_mutability { - Self::set_buffers_mutability( - descriptor.fragment_buffers().unwrap(), - fs.immutable_buffer_mask, - ); - } - (Some(fs.library), fs.sized_bindings) - } - None => { - // TODO: This is a workaround for what appears to be a Metal validation bug - // A pixel format is required even though no attachments are provided - if desc.color_targets.is_empty() && desc.depth_stencil.is_none() { - descriptor.set_depth_attachment_pixel_format(mtl::MTLPixelFormat::Depth32Float); - } - (None, Vec::new()) - } - }; - - for (i, ct) in desc.color_targets.iter().enumerate() { - let at_descriptor = descriptor.color_attachments().object_at(i as u64).unwrap(); - let ct = if let Some(color_target) = ct.as_ref() { - color_target - } else { - at_descriptor.set_pixel_format(mtl::MTLPixelFormat::Invalid); - continue; + let raw_triangle_fill_mode = match desc.primitive.polygon_mode { + wgt::PolygonMode::Fill => mtl::MTLTriangleFillMode::Fill, + wgt::PolygonMode::Line => mtl::MTLTriangleFillMode::Lines, + wgt::PolygonMode::Point => panic!( + "{:?} is not enabled for this backend", + wgt::Features::POLYGON_MODE_POINT + ), }; - let raw_format = self.shared.private_caps.map_format(ct.format); - at_descriptor.set_pixel_format(raw_format); - at_descriptor.set_write_mask(conv::map_color_write(ct.write_mask)); + let (primitive_class, raw_primitive_type) = + conv::map_primitive_topology(desc.primitive.topology); - if let Some(ref blend) = ct.blend { - at_descriptor.set_blending_enabled(true); - let (color_op, color_src, color_dst) = conv::map_blend_component(&blend.color); - let (alpha_op, alpha_src, alpha_dst) = conv::map_blend_component(&blend.alpha); + let vs = self.load_shader( + &desc.vertex_stage, + desc.layout, + primitive_class, + naga::ShaderStage::Vertex, + )?; - at_descriptor.set_rgb_blend_operation(color_op); - at_descriptor.set_source_rgb_blend_factor(color_src); - at_descriptor.set_destination_rgb_blend_factor(color_dst); - - at_descriptor.set_alpha_blend_operation(alpha_op); - at_descriptor.set_source_alpha_blend_factor(alpha_src); - at_descriptor.set_destination_alpha_blend_factor(alpha_dst); + descriptor.set_vertex_function(Some(&vs.function)); + if self.shared.private_caps.supports_mutability { + Self::set_buffers_mutability( + descriptor.vertex_buffers().unwrap(), + vs.immutable_buffer_mask, + ); } - } - let depth_stencil = match desc.depth_stencil { - Some(ref ds) => { - let raw_format = self.shared.private_caps.map_format(ds.format); - let aspects = crate::FormatAspects::from(ds.format); - if aspects.contains(crate::FormatAspects::DEPTH) { - descriptor.set_depth_attachment_pixel_format(raw_format); + // Fragment shader + let (fs_lib, fs_sized_bindings) = match desc.fragment_stage { + Some(ref stage) => { + let fs = self.load_shader( + stage, + desc.layout, + primitive_class, + naga::ShaderStage::Fragment, + )?; + descriptor.set_fragment_function(Some(&fs.function)); + if self.shared.private_caps.supports_mutability { + Self::set_buffers_mutability( + descriptor.fragment_buffers().unwrap(), + fs.immutable_buffer_mask, + ); + } + (Some(fs.library), fs.sized_bindings) } - if aspects.contains(crate::FormatAspects::STENCIL) { - descriptor.set_stencil_attachment_pixel_format(raw_format); + None => { + // TODO: This is a workaround for what appears to be a Metal validation bug + // A pixel format is required even though no attachments are provided + if desc.color_targets.is_empty() && desc.depth_stencil.is_none() { + descriptor + .set_depth_attachment_pixel_format(mtl::MTLPixelFormat::Depth32Float); + } + (None, Vec::new()) } + }; - let ds_descriptor = create_depth_stencil_desc(ds); - let raw = self - .shared - .device - .lock() - .new_depth_stencil_state(&ds_descriptor); - Some((raw, ds.bias)) - } - None => None, - }; - - if desc.layout.total_counters.vs.buffers + (desc.vertex_buffers.len() as u32) - > self.shared.private_caps.max_vertex_buffers - { - let msg = format!( - "pipeline needs too many buffers in the vertex stage: {} vertex and {} layout", - desc.vertex_buffers.len(), - desc.layout.total_counters.vs.buffers - ); - return Err(crate::PipelineError::Linkage( - wgt::ShaderStages::VERTEX, - msg, - )); - } - - if !desc.vertex_buffers.is_empty() { - let vertex_descriptor = mtl::VertexDescriptor::new(); - for (i, vb) in desc.vertex_buffers.iter().enumerate() { - let buffer_index = - self.shared.private_caps.max_vertex_buffers as u64 - 1 - i as u64; - let buffer_desc = vertex_descriptor.layouts().object_at(buffer_index).unwrap(); - - buffer_desc.set_stride(vb.array_stride); - buffer_desc.set_step_function(conv::map_step_mode(vb.step_mode)); - - for at in vb.attributes { - let attribute_desc = vertex_descriptor - .attributes() - .object_at(at.shader_location as u64) - .unwrap(); - attribute_desc.set_format(conv::map_vertex_format(at.format)); - attribute_desc.set_buffer_index(buffer_index); - attribute_desc.set_offset(at.offset); - } - } - descriptor.set_vertex_descriptor(Some(vertex_descriptor)); - } - - if desc.multisample.count != 1 { - //TODO: handle sample mask - descriptor.set_sample_count(desc.multisample.count as u64); - descriptor.set_alpha_to_coverage_enabled(desc.multisample.alpha_to_coverage_enabled); - //descriptor.set_alpha_to_one_enabled(desc.multisample.alpha_to_one_enabled); - } - - if let Some(name) = desc.label { - descriptor.set_label(name); - } - - let raw = self - .shared - .device - .lock() - .new_render_pipeline_state(&descriptor) - .map_err(|e| { - crate::PipelineError::Linkage( - wgt::ShaderStages::VERTEX | wgt::ShaderStages::FRAGMENT, - format!("new_render_pipeline_state: {:?}", e), - ) - })?; - - Ok(super::RenderPipeline { - raw, - vs_lib: vs.library, - fs_lib, - vs_info: super::PipelineStageInfo { - push_constants: desc.layout.push_constants_infos.vs, - sizes_slot: desc.layout.naga_options.per_stage_map.vs.sizes_buffer, - sized_bindings: vs.sized_bindings, - }, - fs_info: super::PipelineStageInfo { - push_constants: desc.layout.push_constants_infos.fs, - sizes_slot: desc.layout.naga_options.per_stage_map.fs.sizes_buffer, - sized_bindings: fs_sized_bindings, - }, - raw_primitive_type, - raw_triangle_fill_mode, - raw_front_winding: conv::map_winding(desc.primitive.front_face), - raw_cull_mode: conv::map_cull_mode(desc.primitive.cull_mode), - raw_depth_clip_mode: if self.features.contains(wgt::Features::DEPTH_CLIP_CONTROL) { - Some(if desc.primitive.unclipped_depth { - mtl::MTLDepthClipMode::Clamp + for (i, ct) in desc.color_targets.iter().enumerate() { + let at_descriptor = descriptor.color_attachments().object_at(i as u64).unwrap(); + let ct = if let Some(color_target) = ct.as_ref() { + color_target } else { - mtl::MTLDepthClipMode::Clip - }) - } else { - None - }, - depth_stencil, + at_descriptor.set_pixel_format(mtl::MTLPixelFormat::Invalid); + continue; + }; + + let raw_format = self.shared.private_caps.map_format(ct.format); + at_descriptor.set_pixel_format(raw_format); + at_descriptor.set_write_mask(conv::map_color_write(ct.write_mask)); + + if let Some(ref blend) = ct.blend { + at_descriptor.set_blending_enabled(true); + let (color_op, color_src, color_dst) = conv::map_blend_component(&blend.color); + let (alpha_op, alpha_src, alpha_dst) = conv::map_blend_component(&blend.alpha); + + at_descriptor.set_rgb_blend_operation(color_op); + at_descriptor.set_source_rgb_blend_factor(color_src); + at_descriptor.set_destination_rgb_blend_factor(color_dst); + + at_descriptor.set_alpha_blend_operation(alpha_op); + at_descriptor.set_source_alpha_blend_factor(alpha_src); + at_descriptor.set_destination_alpha_blend_factor(alpha_dst); + } + } + + let depth_stencil = match desc.depth_stencil { + Some(ref ds) => { + let raw_format = self.shared.private_caps.map_format(ds.format); + let aspects = crate::FormatAspects::from(ds.format); + if aspects.contains(crate::FormatAspects::DEPTH) { + descriptor.set_depth_attachment_pixel_format(raw_format); + } + if aspects.contains(crate::FormatAspects::STENCIL) { + descriptor.set_stencil_attachment_pixel_format(raw_format); + } + + let ds_descriptor = create_depth_stencil_desc(ds); + let raw = self + .shared + .device + .lock() + .new_depth_stencil_state(&ds_descriptor); + Some((raw, ds.bias)) + } + None => None, + }; + + if desc.layout.total_counters.vs.buffers + (desc.vertex_buffers.len() as u32) + > self.shared.private_caps.max_vertex_buffers + { + let msg = format!( + "pipeline needs too many buffers in the vertex stage: {} vertex and {} layout", + desc.vertex_buffers.len(), + desc.layout.total_counters.vs.buffers + ); + return Err(crate::PipelineError::Linkage( + wgt::ShaderStages::VERTEX, + msg, + )); + } + + if !desc.vertex_buffers.is_empty() { + let vertex_descriptor = mtl::VertexDescriptor::new(); + for (i, vb) in desc.vertex_buffers.iter().enumerate() { + let buffer_index = + self.shared.private_caps.max_vertex_buffers as u64 - 1 - i as u64; + let buffer_desc = vertex_descriptor.layouts().object_at(buffer_index).unwrap(); + + buffer_desc.set_stride(vb.array_stride); + buffer_desc.set_step_function(conv::map_step_mode(vb.step_mode)); + + for at in vb.attributes { + let attribute_desc = vertex_descriptor + .attributes() + .object_at(at.shader_location as u64) + .unwrap(); + attribute_desc.set_format(conv::map_vertex_format(at.format)); + attribute_desc.set_buffer_index(buffer_index); + attribute_desc.set_offset(at.offset); + } + } + descriptor.set_vertex_descriptor(Some(vertex_descriptor)); + } + + if desc.multisample.count != 1 { + //TODO: handle sample mask + descriptor.set_sample_count(desc.multisample.count as u64); + descriptor + .set_alpha_to_coverage_enabled(desc.multisample.alpha_to_coverage_enabled); + //descriptor.set_alpha_to_one_enabled(desc.multisample.alpha_to_one_enabled); + } + + if let Some(name) = desc.label { + descriptor.set_label(name); + } + + let raw = self + .shared + .device + .lock() + .new_render_pipeline_state(&descriptor) + .map_err(|e| { + crate::PipelineError::Linkage( + wgt::ShaderStages::VERTEX | wgt::ShaderStages::FRAGMENT, + format!("new_render_pipeline_state: {:?}", e), + ) + })?; + + Ok(super::RenderPipeline { + raw, + vs_lib: vs.library, + fs_lib, + vs_info: super::PipelineStageInfo { + push_constants: desc.layout.push_constants_infos.vs, + sizes_slot: desc.layout.naga_options.per_stage_map.vs.sizes_buffer, + sized_bindings: vs.sized_bindings, + }, + fs_info: super::PipelineStageInfo { + push_constants: desc.layout.push_constants_infos.fs, + sizes_slot: desc.layout.naga_options.per_stage_map.fs.sizes_buffer, + sized_bindings: fs_sized_bindings, + }, + raw_primitive_type, + raw_triangle_fill_mode, + raw_front_winding: conv::map_winding(desc.primitive.front_face), + raw_cull_mode: conv::map_cull_mode(desc.primitive.cull_mode), + raw_depth_clip_mode: if self.features.contains(wgt::Features::DEPTH_CLIP_CONTROL) { + Some(if desc.primitive.unclipped_depth { + mtl::MTLDepthClipMode::Clamp + } else { + mtl::MTLDepthClipMode::Clip + }) + } else { + None + }, + depth_stencil, + }) }) } unsafe fn destroy_render_pipeline(&self, _pipeline: super::RenderPipeline) {} @@ -987,46 +997,51 @@ impl crate::Device for super::Device { &self, desc: &crate::ComputePipelineDescriptor, ) -> Result { - let descriptor = mtl::ComputePipelineDescriptor::new(); + objc::rc::autoreleasepool(|| { + let descriptor = mtl::ComputePipelineDescriptor::new(); - let cs = self.load_shader( - &desc.stage, - desc.layout, - mtl::MTLPrimitiveTopologyClass::Unspecified, - naga::ShaderStage::Compute, - )?; - descriptor.set_compute_function(Some(&cs.function)); + let cs = self.load_shader( + &desc.stage, + desc.layout, + mtl::MTLPrimitiveTopologyClass::Unspecified, + naga::ShaderStage::Compute, + )?; + descriptor.set_compute_function(Some(&cs.function)); - if self.shared.private_caps.supports_mutability { - Self::set_buffers_mutability(descriptor.buffers().unwrap(), cs.immutable_buffer_mask); - } + if self.shared.private_caps.supports_mutability { + Self::set_buffers_mutability( + descriptor.buffers().unwrap(), + cs.immutable_buffer_mask, + ); + } - if let Some(name) = desc.label { - descriptor.set_label(name); - } + if let Some(name) = desc.label { + descriptor.set_label(name); + } - let raw = self - .shared - .device - .lock() - .new_compute_pipeline_state(&descriptor) - .map_err(|e| { - crate::PipelineError::Linkage( - wgt::ShaderStages::COMPUTE, - format!("new_compute_pipeline_state: {:?}", e), - ) - })?; + let raw = self + .shared + .device + .lock() + .new_compute_pipeline_state(&descriptor) + .map_err(|e| { + crate::PipelineError::Linkage( + wgt::ShaderStages::COMPUTE, + format!("new_compute_pipeline_state: {:?}", e), + ) + })?; - Ok(super::ComputePipeline { - raw, - cs_info: super::PipelineStageInfo { - push_constants: desc.layout.push_constants_infos.cs, - sizes_slot: desc.layout.naga_options.per_stage_map.cs.sizes_buffer, - sized_bindings: cs.sized_bindings, - }, - cs_lib: cs.library, - work_group_size: cs.wg_size, - work_group_memory_sizes: cs.wg_memory_sizes, + Ok(super::ComputePipeline { + raw, + cs_info: super::PipelineStageInfo { + push_constants: desc.layout.push_constants_infos.cs, + sizes_slot: desc.layout.naga_options.per_stage_map.cs.sizes_buffer, + sized_bindings: cs.sized_bindings, + }, + cs_lib: cs.library, + work_group_size: cs.wg_size, + work_group_memory_sizes: cs.wg_memory_sizes, + }) }) } unsafe fn destroy_compute_pipeline(&self, _pipeline: super::ComputePipeline) {} @@ -1035,24 +1050,26 @@ impl crate::Device for super::Device { &self, desc: &wgt::QuerySetDescriptor, ) -> DeviceResult { - match desc.ty { - wgt::QueryType::Occlusion => { - let size = desc.count as u64 * crate::QUERY_SIZE; - let options = mtl::MTLResourceOptions::empty(); - //TODO: HazardTrackingModeUntracked - let raw_buffer = self.shared.device.lock().new_buffer(size, options); - if let Some(label) = desc.label { - raw_buffer.set_label(label); + objc::rc::autoreleasepool(|| { + match desc.ty { + wgt::QueryType::Occlusion => { + let size = desc.count as u64 * crate::QUERY_SIZE; + let options = mtl::MTLResourceOptions::empty(); + //TODO: HazardTrackingModeUntracked + let raw_buffer = self.shared.device.lock().new_buffer(size, options); + if let Some(label) = desc.label { + raw_buffer.set_label(label); + } + Ok(super::QuerySet { + raw_buffer, + ty: desc.ty, + }) + } + wgt::QueryType::Timestamp | wgt::QueryType::PipelineStatistics(_) => { + Err(crate::DeviceError::OutOfMemory) } - Ok(super::QuerySet { - raw_buffer, - ty: desc.ty, - }) } - wgt::QueryType::Timestamp | wgt::QueryType::PipelineStatistics(_) => { - Err(crate::DeviceError::OutOfMemory) - } - } + }) } unsafe fn destroy_query_set(&self, _set: super::QuerySet) {}