From 2fb6930a15256fbecb4043bdc283751c40c6a54d Mon Sep 17 00:00:00 2001 From: Maksym Pavlenko Date: Sat, 18 Dec 2021 17:47:40 -0800 Subject: [PATCH] Fix reflection --- examples/reflection/main.rs | 22 ++++++------ src/argument.rs | 22 ++++++++++-- src/device.rs | 69 ++++++++++++++++++++++--------------- src/pipeline/render.rs | 44 +++++++++++++++++++++-- 4 files changed, 115 insertions(+), 42 deletions(-) diff --git a/examples/reflection/main.rs b/examples/reflection/main.rs index 9750f04d..efe9fc29 100644 --- a/examples/reflection/main.rs +++ b/examples/reflection/main.rs @@ -60,16 +60,16 @@ fn main() { println!("{:?}", desc); - #[cfg(features = "private")] - let _reflection = unsafe { - RenderPipelineReflection::new( - desc.serialize_vertex_data(), - desc.serialize_fragment_data(), - vertex_desc.serialize_descriptor(), - &device, - 0x8, - 0x0, - ) - }; + let reflect_options = MTLPipelineOption::ArgumentInfo | MTLPipelineOption::BufferTypeInfo; + let (_, reflection) = device + .new_render_pipeline_state_with_reflection(&desc, reflect_options) + .unwrap(); + + println!("Vertex arguments: "); + let vertex_arguments = reflection.vertex_arguments(); + for index in 0..vertex_arguments.count() { + let argument = vertex_arguments.object_at(index).unwrap(); + println!("{:?}", argument); + } }); } diff --git a/src/argument.rs b/src/argument.rs index 74cc0742..1bf55659 100644 --- a/src/argument.rs +++ b/src/argument.rs @@ -5,7 +5,7 @@ // http://opensource.org/licenses/MIT>, at your option. This file may not be // copied, modified, or distributed except according to those terms. -use super::{Array, MTLTextureType, NSUInteger}; +use super::{MTLTextureType, NSUInteger}; use objc::runtime::{NO, YES}; #[repr(u64)] @@ -161,6 +161,24 @@ impl StructMemberRef { } } +pub enum MTLStructMemberArray {} + +foreign_obj_type! { + type CType = MTLStructMemberArray; + pub struct StructMemberArray; + pub struct StructMemberArrayRef; +} + +impl StructMemberArrayRef { + pub fn object_at(&self, index: NSUInteger) -> Option<&StructMemberRef> { + unsafe { msg_send![self, objectAtIndexedSubscript: index] } + } + + pub fn count(&self) -> NSUInteger { + unsafe { msg_send![self, count] } + } +} + pub enum MTLStructType {} foreign_obj_type! { @@ -170,7 +188,7 @@ foreign_obj_type! { } impl StructTypeRef { - pub fn members(&self) -> &Array { + pub fn members(&self) -> &StructMemberArrayRef { unsafe { msg_send![self, members] } } diff --git a/src/device.rs b/src/device.rs index 4b5c19bd..41c08ff4 100644 --- a/src/device.rs +++ b/src/device.rs @@ -1391,10 +1391,17 @@ pub enum MTLSparseTextureRegionAlignmentMode { } bitflags! { - struct MTLPipelineOption: NSUInteger { + /// Options that determine how Metal prepares the pipeline. + pub struct MTLPipelineOption: NSUInteger { + /// Do not provide any reflection information. const None = 0; + /// An option that requests argument information for buffers, textures, and threadgroup memory. const ArgumentInfo = 1 << 0; + /// An option that requests detailed buffer type information for buffer arguments. const BufferTypeInfo = 1 << 1; + /// An option that specifies that Metal should create the pipeline state object only if the + /// compiled shader is present inside the binary archive. + /// /// Only available on (macos(11.0), ios(14.0)) const FailOnBinaryArchiveMiss = 1 << 2; } @@ -1809,44 +1816,27 @@ impl DeviceRef { } } + /// Synchronously creates a render pipeline state object and associated reflection information. pub fn new_render_pipeline_state_with_reflection( &self, descriptor: &RenderPipelineDescriptorRef, - reflection: &RenderPipelineReflectionRef, - ) -> Result { + reflection_options: MTLPipelineOption, + ) -> Result<(RenderPipelineState, RenderPipelineReflection), String> { unsafe { - let reflection_options = - MTLPipelineOption::ArgumentInfo | MTLPipelineOption::BufferTypeInfo; - + let mut reflection: *mut Object = ptr::null_mut(); let pipeline_state: *mut MTLRenderPipelineState = try_objc! { err => msg_send![self, newRenderPipelineStateWithDescriptor:descriptor options:reflection_options - reflection:reflection + reflection:&mut reflection error:&mut err] }; - Ok(RenderPipelineState::from_ptr(pipeline_state)) - } - } + let state = RenderPipelineState::from_ptr(pipeline_state); - /// Useful for debugging binary archives. - pub fn new_render_pipeline_state_with_fail_on_binary_archive_miss( - &self, - descriptor: &RenderPipelineDescriptorRef, - ) -> Result { - unsafe { - let pipeline_options = MTLPipelineOption::FailOnBinaryArchiveMiss; - - let reflection: *mut MTLRenderPipelineReflection = std::ptr::null_mut(); - - let pipeline_state: *mut MTLRenderPipelineState = try_objc! { err => - msg_send![self, newRenderPipelineStateWithDescriptor:descriptor - options:pipeline_options - reflection:reflection - error:&mut err] - }; + let () = msg_send![reflection, retain]; + let reflection = RenderPipelineReflection::from_ptr(reflection as _); - Ok(RenderPipelineState::from_ptr(pipeline_state)) + Ok((state, reflection)) } } @@ -1892,6 +1882,31 @@ impl DeviceRef { } } + /// Synchronously creates a compute pipeline state object and associated reflection information, + /// using a compute pipeline descriptor. + pub fn new_compute_pipeline_state_with_reflection( + &self, + descriptor: &ComputePipelineDescriptorRef, + reflection_options: MTLPipelineOption, + ) -> Result<(ComputePipelineState, ComputePipelineReflection), String> { + unsafe { + let mut reflection: *mut Object = ptr::null_mut(); + let pipeline_state: *mut MTLComputePipelineState = try_objc! { err => + msg_send![self, newComputePipelineStateWithDescriptor:descriptor + options:reflection_options + reflection:&mut reflection + error:&mut err] + }; + + let state = ComputePipelineState::from_ptr(pipeline_state); + + let () = msg_send![reflection, retain]; + let reflection = ComputePipelineReflection::from_ptr(reflection as _); + + Ok((state, reflection)) + } + } + pub fn new_buffer(&self, length: u64, options: MTLResourceOptions) -> Buffer { unsafe { msg_send![self, newBufferWithLength:length diff --git a/src/pipeline/render.rs b/src/pipeline/render.rs index 31f90fd3..a4b3a629 100644 --- a/src/pipeline/render.rs +++ b/src/pipeline/render.rs @@ -193,13 +193,53 @@ impl RenderPipelineReflection { } impl RenderPipelineReflectionRef { - pub fn fragment_arguments(&self) -> &Array { + /// An array of objects that describe the arguments of a fragment function. + pub fn fragment_arguments(&self) -> &ArgumentArrayRef { unsafe { msg_send![self, fragmentArguments] } } - pub fn vertex_arguments(&self) -> &Array { + /// An array of objects that describe the arguments of a vertex function. + pub fn vertex_arguments(&self) -> &ArgumentArrayRef { unsafe { msg_send![self, vertexArguments] } } + + /// An array of objects that describe the arguments of a tile shading function. + pub fn tile_arguments(&self) -> &ArgumentArrayRef { + unsafe { msg_send![self, tileArguments] } + } +} + +pub enum MTLArgumentArray {} + +foreign_obj_type! { + type CType = MTLArgumentArray; + pub struct ArgumentArray; + pub struct ArgumentArrayRef; +} + +impl ArgumentArrayRef { + pub fn object_at(&self, index: NSUInteger) -> Option<&ArgumentRef> { + unsafe { msg_send![self, objectAtIndexedSubscript: index] } + } + + pub fn count(&self) -> NSUInteger { + unsafe { msg_send![self, count] } + } +} + +pub enum MTLComputePipelineReflection {} + +foreign_obj_type! { + type CType = MTLComputePipelineReflection; + pub struct ComputePipelineReflection; + pub struct ComputePipelineReflectionRef; +} + +impl ComputePipelineReflectionRef { + /// An array of objects that describe the arguments of a compute function. + pub fn arguments(&self) -> &ArgumentArrayRef { + unsafe { msg_send![self, arguments] } + } } pub enum MTLRenderPipelineDescriptor {}