Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reflection fixes #224

Merged
merged 1 commit into from
Dec 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions examples/reflection/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
});
}
22 changes: 20 additions & 2 deletions src/argument.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -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! {
Expand All @@ -170,7 +188,7 @@ foreign_obj_type! {
}

impl StructTypeRef {
pub fn members(&self) -> &Array<StructMember> {
pub fn members(&self) -> &StructMemberArrayRef {
unsafe { msg_send![self, members] }
}

Expand Down
69 changes: 42 additions & 27 deletions src/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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<RenderPipelineState, String> {
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<RenderPipelineState, String> {
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))
}
}

Expand Down Expand Up @@ -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
Expand Down
44 changes: 42 additions & 2 deletions src/pipeline/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,13 +193,53 @@ impl RenderPipelineReflection {
}

impl RenderPipelineReflectionRef {
pub fn fragment_arguments(&self) -> &Array<Argument> {
/// 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<Argument> {
/// 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 {}
Expand Down