Skip to content

Commit

Permalink
Fix reflection
Browse files Browse the repository at this point in the history
  • Loading branch information
mxpv authored and kvark committed Dec 19, 2021
1 parent 65474ba commit 2fb6930
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 42 deletions.
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

0 comments on commit 2fb6930

Please sign in to comment.