From 6966d52baebd91c03bbcc0495fab349a3420c0eb Mon Sep 17 00:00:00 2001 From: Joshua Groves Date: Sun, 24 Jun 2018 02:57:43 -0600 Subject: [PATCH] Use pointers for samplers --- src/backend/metal/src/command.rs | 55 +++++++++++++++++-------------- src/backend/metal/src/device.rs | 16 +++++---- src/backend/metal/src/internal.rs | 32 +++++++++++++----- src/backend/metal/src/lib.rs | 17 ++++++++++ src/backend/metal/src/native.rs | 38 ++++++++++++++++++--- src/backend/metal/src/soft.rs | 20 +++++------ 6 files changed, 122 insertions(+), 56 deletions(-) diff --git a/src/backend/metal/src/command.rs b/src/backend/metal/src/command.rs index 92dec31c9c3..ae8b4711807 100644 --- a/src/backend/metal/src/command.rs +++ b/src/backend/metal/src/command.rs @@ -1,4 +1,7 @@ -use {AutoreleasePool, Backend, PrivateDisabilities, Shared, validate_line_width, BufferPtr, TexturePtr}; +use { + AutoreleasePool, Backend, PrivateDisabilities, Shared, validate_line_width, + BufferPtr, TexturePtr, SamplerPtr, +}; use {conversions as conv, native, soft, window}; use internal::{BlitVertex, Channel, ClearKey, ClearVertex, ServicePipes}; @@ -208,7 +211,7 @@ impl State { .zip(render_resources) .flat_map(move |(&stage, resources)| { let com_buffers = resources.buffers.iter().enumerate().filter_map(move |(i, resource)| { - resource.as_ref().map(|&(buffer, offset)| { + resource.map(|(buffer, offset)| { soft::RenderCommand::BindBuffer { stage, index: i as _, @@ -227,11 +230,11 @@ impl State { }) }); let com_samplers = resources.samplers.iter().enumerate().filter_map(move |(i, resource)| { - resource.as_ref().map(|sampler| { + resource.map(|sampler| { soft::RenderCommand::BindSampler { stage, index: i as _, - sampler: Some(&**sampler), + sampler: Some(sampler), } }) }); @@ -265,7 +268,7 @@ impl State { .iter() .enumerate() .filter_map(|(i, resource)| { - resource.as_ref().map(|&(buffer, offset)| { + resource.map(|(buffer, offset)| { soft::ComputeCommand::BindBuffer { index: i as _, buffer: Some(buffer), @@ -288,10 +291,10 @@ impl State { .iter() .enumerate() .filter_map(|(i, ref resource)| { - resource.as_ref().map(|sampler| { + resource.map(|sampler| { soft::ComputeCommand::BindSampler { index: i as _, - sampler: Some(&**sampler), + sampler: Some(sampler), } }) }); @@ -346,7 +349,7 @@ impl State { .enumerate() .filter_map(move |(index, maybe_buffer)| { if mask & (1u64 << index) != 0 { - maybe_buffer.as_ref().map(|&(buffer, offset)| { + maybe_buffer.map(|(buffer, offset)| { soft::RenderCommand::BindBuffer { stage: pso::Stage::Vertex, index, @@ -535,7 +538,7 @@ impl State { struct StageResources { buffers: Vec>, textures: Vec>, - samplers: Vec>, + samplers: Vec>, push_constants_buffer_id: Option, } @@ -568,16 +571,16 @@ impl StageResources { self.textures.push(None) } for (out, tex) in self.textures[start..].iter_mut().zip(textures.iter()) { - *out = tex.as_ref().map(|&(ref t, _)| t.to_owned()); + *out = tex.map(|(t, _)| t); } } - fn add_samplers(&mut self, start: usize, samplers: &[Option]) { + fn add_samplers(&mut self, start: usize, samplers: &[Option]) { while self.samplers.len() < start + samplers.len() { self.samplers.push(None) } for (out, sampler) in self.samplers[start..].iter_mut().zip(samplers.iter()) { - *out = sampler.clone(); + *out = *sampler; } } } @@ -948,11 +951,12 @@ fn exec_render<'a>(encoder: &metal::RenderCommandEncoderRef, command: soft::Rend } } Cmd::BindSampler { stage, index, sampler } => { + let native = sampler.as_ref().map(|s| s.as_native()); match stage { pso::Stage::Vertex => - encoder.set_vertex_sampler_state(index as _, sampler), + encoder.set_vertex_sampler_state(index as _, native), pso::Stage::Fragment => - encoder.set_fragment_sampler_state(index as _, sampler), + encoder.set_fragment_sampler_state(index as _, native), _ => unimplemented!() } } @@ -1127,7 +1131,8 @@ fn exec_compute<'a>(encoder: &metal::ComputeCommandEncoderRef, command: soft::Co encoder.set_texture(index as _, native); } Cmd::BindSampler { index, sampler } => { - encoder.set_sampler_state(index as _, sampler); + let native = sampler.as_ref().map(|s| s.as_native()); + encoder.set_sampler_state(index as _, native); } Cmd::BindPipeline(pipeline) => { encoder.set_compute_pipeline_state(pipeline); @@ -2490,7 +2495,7 @@ impl com::RawCommandBuffer for CommandBuffer { soft::RenderCommand::BindSampler { stage, index: start + i, - sampler: sampler.as_ref().map(Borrow::borrow), + sampler: *sampler, } })); } @@ -2503,7 +2508,7 @@ impl com::RawCommandBuffer for CommandBuffer { soft::RenderCommand::BindTexture { stage, index: start + i, - texture: texture.as_ref().map(|&(root, _)| root), + texture: texture.map(|(root, _)| root), } })); } @@ -2512,18 +2517,18 @@ impl com::RawCommandBuffer for CommandBuffer { for &mut (stage, ref loc, ref mut resources) in &mut bind_stages { let start_tx = layout.res_overrides[loc].texture_id as usize; let start_sm = layout.res_overrides[loc].sampler_id as usize; - for (i, (ref texture, ref sampler)) in combos.iter().enumerate() { + for (i, (texture, sampler)) in combos.iter().enumerate() { resources.add_textures(start_tx + i, &[texture.clone()]); resources.add_samplers(start_sm + i, &[sampler.clone()]); commands.push(soft::RenderCommand::BindTexture { stage, index: start_tx + i, - texture: texture.as_ref().map(|&(root, _)| root), + texture: texture.map(|(root, _)| root), }); commands.push(soft::RenderCommand::BindSampler { stage, index: start_sm + i, - sampler: sampler.as_ref().map(Borrow::borrow), + sampler: *sampler, }); } } @@ -2676,7 +2681,7 @@ impl com::RawCommandBuffer for CommandBuffer { commands.extend(samplers.iter().enumerate().map(|(i, sampler)| { soft::ComputeCommand::BindSampler { index: start + i, - sampler: sampler.as_ref().map(Borrow::borrow), + sampler: *sampler, } })); } @@ -2686,23 +2691,23 @@ impl com::RawCommandBuffer for CommandBuffer { commands.extend(images.iter().enumerate().map(|(i, texture)| { soft::ComputeCommand::BindTexture { index: start + i, - texture: texture.as_ref().map(|&(root, _)| root), + texture: texture.map(|(root, _)| root), } })); } Combined(ref combos) => { - for (i, (ref texture, ref sampler)) in combos.iter().enumerate() { + for (i, (texture, sampler)) in combos.iter().enumerate() { let id_tx = res.texture_id as usize + i; let id_sm = res.sampler_id as usize + i; resources.add_textures(id_tx, &[texture.clone()]); resources.add_samplers(id_sm, &[sampler.clone()]); commands.push(soft::ComputeCommand::BindTexture { index: id_tx, - texture: texture.as_ref().map(|&(root, _)| root), + texture: texture.map(|(root, _)| root), }); commands.push(soft::ComputeCommand::BindSampler { index: id_sm, - sampler: sampler.as_ref().map(Borrow::borrow), + sampler: *sampler, }); } } diff --git a/src/backend/metal/src/device.rs b/src/backend/metal/src/device.rs index dbe1faa41ad..47745118406 100644 --- a/src/backend/metal/src/device.rs +++ b/src/backend/metal/src/device.rs @@ -1,6 +1,6 @@ use { AutoreleasePool, Backend, PrivateCapabilities, QueueFamily, - Shared, Surface, Swapchain, validate_line_width, BufferPtr, TexturePtr, + Shared, Surface, Swapchain, validate_line_width, BufferPtr, SamplerPtr, TexturePtr, }; use {conversions as conv, command, native as n}; use native; @@ -1232,12 +1232,16 @@ impl hal::Device for Device { }); } - n::Sampler( - self.shared.device + let raw = self.shared.device .lock() .unwrap() - .new_sampler(&descriptor) - ) + .new_sampler(&descriptor); + let raw_ptr = raw.as_ptr(); + unsafe { + msg_send![raw_ptr as *mut Object, retain]; + } + + n::Sampler(SamplerPtr(raw_ptr)) } fn destroy_sampler(&self, _sampler: n::Sampler) { @@ -1491,7 +1495,7 @@ impl hal::Device for Device { for descriptor in write.descriptors { match *descriptor.borrow() { pso::Descriptor::Sampler(sampler) => { - encoder.set_sampler_states(&[&sampler.0], write.binding as _); + encoder.set_sampler_states(&[&sampler.0.as_native()], write.binding as _); } pso::Descriptor::Image(image, _layout) => { encoder.set_textures(&[image.raw.as_native()], write.binding as _); diff --git a/src/backend/metal/src/internal.rs b/src/backend/metal/src/internal.rs index 8783695df6e..3a2b0b81ba6 100644 --- a/src/backend/metal/src/internal.rs +++ b/src/backend/metal/src/internal.rs @@ -1,3 +1,5 @@ +use SamplerPtr; + use metal; use hal::backend::FastHashMap; use hal::command::ClearColorRaw; @@ -8,6 +10,9 @@ use std::mem; use std::path::Path; use std::sync::Mutex; +use objc::runtime::Object; +use foreign_types::ForeignType; + #[derive(Clone, Debug)] pub struct ClearVertex { pub pos: [f32; 4], @@ -71,8 +76,8 @@ impl Channel { pub struct SamplerStates { - nearest: metal::SamplerState, - linear: metal::SamplerState, + nearest: SamplerPtr, + linear: SamplerPtr, } impl SamplerStates { @@ -81,21 +86,30 @@ impl SamplerStates { desc.set_min_filter(metal::MTLSamplerMinMagFilter::Nearest); desc.set_mag_filter(metal::MTLSamplerMinMagFilter::Nearest); desc.set_mip_filter(metal::MTLSamplerMipFilter::Nearest); - let nearest = device.new_sampler(&desc); + let nearest_raw = device.new_sampler(&desc); + let nearest_raw_ptr = nearest_raw.as_ptr(); + unsafe { + msg_send![nearest_raw_ptr as *mut Object, retain]; + } + desc.set_min_filter(metal::MTLSamplerMinMagFilter::Linear); desc.set_mag_filter(metal::MTLSamplerMinMagFilter::Linear); - let linear = device.new_sampler(&desc); + let linear_raw = device.new_sampler(&desc); + let linear_raw_ptr = linear_raw.as_ptr(); + unsafe { + msg_send![linear_raw_ptr as *mut Object, retain]; + } SamplerStates { - nearest, - linear, + nearest: SamplerPtr(nearest_raw_ptr), + linear: SamplerPtr(linear_raw_ptr), } } - pub fn get(&self, filter: Filter) -> &metal::SamplerStateRef { + pub fn get(&self, filter: Filter) -> SamplerPtr { match filter { - Filter::Nearest => &self.nearest, - Filter::Linear => &self.linear, + Filter::Nearest => self.nearest, + Filter::Linear => self.linear, } } } diff --git a/src/backend/metal/src/lib.rs b/src/backend/metal/src/lib.rs index 9d6e68b1a0c..265d4556c30 100644 --- a/src/backend/metal/src/lib.rs +++ b/src/backend/metal/src/lib.rs @@ -287,3 +287,20 @@ impl TexturePtr { self.0 } } + +#[derive(Clone, Copy, Debug)] +pub struct SamplerPtr(*mut metal::MTLSamplerState); + +impl SamplerPtr { + #[inline] + pub fn as_native(&self) -> &metal::SamplerStateRef { + unsafe { + metal::SamplerStateRef::from_ptr(self.0) + } + } + + #[inline] + pub fn as_ptr(&self) -> *mut metal::MTLSamplerState { + self.0 + } +} diff --git a/src/backend/metal/src/native.rs b/src/backend/metal/src/native.rs index 6e5981910e9..b5574df57f7 100644 --- a/src/backend/metal/src/native.rs +++ b/src/backend/metal/src/native.rs @@ -1,4 +1,4 @@ -use {Backend, BufferPtr, TexturePtr}; +use {Backend, BufferPtr, SamplerPtr, TexturePtr}; use internal::Channel; use window::SwapchainImage; @@ -184,6 +184,13 @@ impl Image { } } +impl Drop for Image { + fn drop(&mut self) { + // Own the texture and let it drop/release + let _ = *self.raw.as_native(); + } +} + unsafe impl Send for Image {} unsafe impl Sync for Image {} @@ -195,6 +202,13 @@ pub struct BufferView { unsafe impl Send for BufferView {} unsafe impl Sync for BufferView {} +impl Drop for BufferView { + fn drop(&mut self) { + // Own the texture and let it drop/release + let _ = *self.raw.as_native(); + } +} + #[derive(Debug)] pub struct ImageView { pub(crate) raw: TexturePtr, @@ -204,8 +218,22 @@ pub struct ImageView { unsafe impl Send for ImageView {} unsafe impl Sync for ImageView {} +impl Drop for ImageView { + fn drop(&mut self) { + // Own the texture and let it drop/release + let _ = *self.raw.as_native(); + } +} + #[derive(Debug)] -pub struct Sampler(pub(crate) metal::SamplerState); +pub struct Sampler(pub(crate) SamplerPtr); + +impl Drop for Sampler { + fn drop(&mut self) { + // Own the sampler and let it drop/release + let _ = *self.0.as_native(); + } +} unsafe impl Send for Sampler {} unsafe impl Sync for Sampler {} @@ -390,7 +418,7 @@ impl hal::DescriptorPool for DescriptorPool { #[derive(Debug)] pub enum DescriptorSetLayout { - Emulated(Vec, Vec), + Emulated(Vec, Vec), ArgumentBuffer(metal::ArgumentEncoder, pso::ShaderStageFlags), } unsafe impl Send for DescriptorSetLayout {} @@ -425,9 +453,9 @@ pub struct BufferBinding { #[derive(Clone, Debug)] pub enum DescriptorSetBinding { - Sampler(Vec>), + Sampler(Vec>), Image(Vec>), - Combined(Vec<(Option<(TexturePtr, image::Layout)>, Option)>), + Combined(Vec<(Option<(TexturePtr, image::Layout)>, Option)>), Buffer(Vec), //InputAttachment(Vec<(TexturePtr, image::Layout)>), } diff --git a/src/backend/metal/src/soft.rs b/src/backend/metal/src/soft.rs index 5f14a51c383..f86ad62ecf5 100644 --- a/src/backend/metal/src/soft.rs +++ b/src/backend/metal/src/soft.rs @@ -1,4 +1,4 @@ -use {BufferPtr, TexturePtr}; +use {BufferPtr, SamplerPtr, TexturePtr}; use command::IndexBuffer; use native::RasterizerState; @@ -24,7 +24,7 @@ impl Resources for Own { type Data = Vec; type Buffer = BufferPtr; type Texture = TexturePtr; - type Sampler = metal::SamplerState; + type Sampler = SamplerPtr; type DepthStencil = metal::DepthStencilState; type RenderPipeline = metal::RenderPipelineState; type ComputePipeline = metal::ComputePipelineState; @@ -34,7 +34,7 @@ impl<'a> Resources for &'a Own { type Data = &'a [u32]; type Buffer = BufferPtr; type Texture = TexturePtr; - type Sampler = &'a metal::SamplerStateRef; + type Sampler = SamplerPtr; type DepthStencil = &'a metal::DepthStencilStateRef; type RenderPipeline = &'a metal::RenderPipelineStateRef; type ComputePipeline = &'a metal::ComputePipelineStateRef; @@ -101,7 +101,6 @@ pub enum RenderCommand { impl RenderCommand { pub fn as_ref<'a>(&'a self) -> RenderCommand<&'a Own> { - use std::borrow::Borrow; use self::RenderCommand::*; match *self { SetViewport(vp) => SetViewport(vp), @@ -126,10 +125,10 @@ impl RenderCommand { index, texture, }, - BindSampler { stage, index, ref sampler } => BindSampler { + BindSampler { stage, index, sampler } => BindSampler { stage, index, - sampler: sampler.as_ref().map(Borrow::borrow), + sampler, }, BindPipeline(ref pso, ref state) => BindPipeline(&**pso, state.clone()), Draw { primitive_type, ref vertices, ref instances } => Draw { @@ -188,7 +187,7 @@ impl<'a> RenderCommand<&'a Own> { BindSampler { stage, index, sampler } => BindSampler { stage, index, - sampler: sampler.map(ToOwned::to_owned), + sampler, }, BindPipeline(pso, state) => BindPipeline(pso.to_owned(), state), Draw { primitive_type, vertices, instances } => Draw { @@ -339,7 +338,6 @@ pub enum ComputeCommand { impl ComputeCommand { pub fn as_ref<'a>(&'a self) -> ComputeCommand<&'a Own> { - use std::borrow::Borrow; use self::ComputeCommand::*; match *self { BindBuffer { index, buffer, offset } => BindBuffer { @@ -355,9 +353,9 @@ impl ComputeCommand { index, texture, }, - BindSampler { index, ref sampler } => BindSampler { + BindSampler { index, sampler } => BindSampler { index, - sampler: sampler.as_ref().map(Borrow::borrow), + sampler, }, BindPipeline(ref pso) => BindPipeline(&**pso), Dispatch { wg_size, wg_count } => Dispatch { @@ -392,7 +390,7 @@ impl<'a> ComputeCommand<&'a Own> { }, BindSampler { index, sampler } => BindSampler { index, - sampler: sampler.map(ToOwned::to_owned), + sampler, }, BindPipeline(pso) => BindPipeline(pso.to_owned()), Dispatch { wg_size, wg_count } => Dispatch {