8000 metal: make a shader from a precompiled Metal library by benface · Pull Request #681 · not-fl3/miniquad · GitHub
[go: up one dir, main page]

Skip to content
Open
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
10 changes: 9 additions & 1 deletion src/graphics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1042,6 +1042,13 @@ impl<'a> UniformsSource<'a> {
pub enum ShaderSource<'a> {
Glsl { vertex: &'a str, fragment: &'a str },
Msl { program: &'a str },
/// A Metal library compiled ahead of time, as `xcrun metal` writes
/// one, holding `vertexShader` and `fragmentShader`. Loading one skips
/// compiling MSL at runtime, which can take tens of milliseconds per
/// shader on a device that hasn't cached it yet. If Metal can't load
/// it, `new_shader` returns a `ShaderError::LinkError`, so the app
/// can compile the MSL instead.
MetalLibrary { data: &'a [u8] },
}

#[derive(Debug, Clone, Copy, PartialEq, Hash, Eq)]
Expand Down Expand Up @@ -1099,7 +1106,8 @@ impl ContextInfo {

pub trait RenderingBackend {
fn info(&self) -> ContextInfo;
/// For metal context's ShaderSource should contain MSL source string, for GL - glsl.
/// For metal context's ShaderSource should contain MSL source string or a compiled
/// Metal library, for GL - glsl.
///
/// If in doubt, _most_ OpenGL contexts support "#version 100" glsl shaders.
/// So far miniquad never encountered where it can create a rendering context,
Expand Down
39 changes: 29 additions & 10 deletions src/graphics/metal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -755,18 +755,37 @@ impl RenderingBackend for MetalContext {
_meta: ShaderMeta,
) -> Result<ShaderId, ShaderError> {
unsafe {
let program = match shader {
ShaderSource::Msl { program } => program,
let mut error: ObjcId = nil;
let library: ObjcId = match shader {
ShaderSource::Msl { program } => {
let shader = apple_util::str_to_nsstring(program);
msg_send![
self.device,
newLibraryWithSource: shader
options:nil
error: &mut error
]
}
ShaderSource::MetalLibrary { data } => {
let data = dispatch_data_create(
data.as_ptr() as *const c_void,
data.len(),
nil,
DISPATCH_DATA_DESTRUCTOR_DEFAULT,
);
let library: ObjcId =
msg_send![self.device, newLibraryWithData: data error: &mut error];
dispatch_release(data);
if library.is_null() {
let description: ObjcId = msg_send![error, localizedDescription];
return Err(ShaderError::LinkError(apple_util::nsstring_to_string(
description,
)));
}
library
}
_ => panic!("OpenGl source on Metal context"),
};
let shader = apple_util::str_to_nsstring(program);
let mut error: ObjcId = nil;
let library: ObjcId = msg_send![
self.device,
newLibraryWithSource: shader
options:nil
error: &mut error
];
if library.is_null() {
let description: ObjcId = msg_send![error, localizedDescription];
let string = apple_util::nsstring_to_string(description);
Expand Down
10 changes: 10 additions & 0 deletions src/native/apple/frameworks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,18 @@ impl Drop for RcObjcId {
extern "C" {
pub static _NSConcreteStackBlock: [*const c_void; 32];
pub static _NSConcreteBogusBlock: [*const c_void; 32];
pub fn dispatch_data_create(
buffer: *const c_void,
size: usize,
queue: ObjcId,
destructor: ObjcId,
) -> ObjcId;
pub fn dispatch_release(object: ObjcId);
}

/// Has `dispatch_data_create` copy the buffer it's given.
pub const DISPATCH_DATA_DESTRUCTOR_DEFAULT: ObjcId = nil;

#[link(name = "Foundation", kind = "framework")]
extern "C" {
pub static NSRunLoopCommonModes: ObjcId;
Expand Down
Loading
0