Skip to content

Commit c7f0240

Browse files
PicoLeafsilvanshade
authored andcommitted
Update the metal example to make the triangle spin
1 parent 779dd38 commit c7f0240

File tree

1 file changed

+76
-36
lines changed

1 file changed

+76
-36
lines changed

crates/icrate/examples/metal.rs

Lines changed: 76 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,14 @@ use icrate::{
99
NSBackingStoreBuffered, NSWindow, NSWindowStyleMaskClosable, NSWindowStyleMaskResizable,
1010
NSWindowStyleMaskTitled,
1111
},
12-
Foundation::{NSNotification, NSObject, NSObjectProtocol, NSPoint, NSRect, NSSize, NSString},
12+
Foundation::{
13+
NSDate, NSNotification, NSObject, NSObjectProtocol, NSPoint, NSRect, NSSize, NSString,
14+
},
1315
Metal::{
14-
MTLCommandBuffer, MTLCommandEncoder, MTLCommandQueue, MTLCreateSystemDefaultDevice,
15-
MTLDevice, MTLDrawable, MTLLibrary, MTLPrimitiveTypeTriangle, MTLRenderCommandEncoder,
16-
MTLRenderPipelineDescriptor, MTLRenderPipelineState,
16+
MTLArgumentEncoder, MTLCommandBuffer, MTLCommandEncoder, MTLCommandQueue,
17+
MTLCreateSystemDefaultDevice, MTLDevice, MTLDrawable, MTLFunction, MTLLibrary,
18+
MTLPrimitiveTypeTriangle, MTLRenderCommandEncoder, MTLRenderPipelineDescriptor,
19+
MTLRenderPipelineState,
1720
},
1821
MetalKit::{MTKView, MTKViewDelegate},
1922
};
@@ -33,8 +36,10 @@ declare_class!(
3336
device: IvarDrop<Id<ProtocolObject<dyn MTLDevice>>, "_device">,
3437
command_queue: IvarDrop<Id<ProtocolObject<dyn MTLCommandQueue>>, "_command_queue">,
3538
pipeline_state: IvarDrop<Id<ProtocolObject<dyn MTLRenderPipelineState>>, "_pipeline_state">,
39+
pipeline_descriptor: IvarDrop<Id<MTLRenderPipelineDescriptor>, "_pipeline_descriptor">,
3640
window: IvarDrop<Id<NSWindow>, "_window">,
3741
mtk_view: IvarDrop<Id<MTKView>, "_mtk_view">,
42+
start_date: IvarDrop<Id<NSDate>, "_start_date">,
3843
}
3944
mod ivars;
4045

@@ -45,6 +50,27 @@ declare_class!(
4550
const NAME: &'static str = "Delegate";
4651
}
4752

53+
// define the delegate methods for the `NSApplicationDelegate` protocol
54+
unsafe impl NSApplicationDelegate for Delegate {
55+
#[method(applicationDidFinishLaunching:)]
56+
#[allow(non_snake_case)]
57+
unsafe fn applicationDidFinishLaunching(&self, _notification: &NSNotification) {
58+
// configure the metal view delegate
59+
unsafe {
60+
let object = ProtocolObject::from_ref(self);
61+
self.mtk_view.setDelegate(Some(object));
62+
}
63+
64+
// configure the window
65+
unsafe {
66+
self.window.setContentView(Some(&self.mtk_view));
67+
self.window.center();
68+
self.window.setTitle(ns_string!("metal example"));
69+
self.window.makeKeyAndOrderFront(None);
70+
}
71+
}
72+
}
73+
4874
// define the Delegate methods (e.g., initializer)
4975
unsafe impl Delegate {
5076
#[method(initWithShaders:)]
@@ -66,7 +92,7 @@ declare_class!(
6692
// create the app window
6793
let window = {
6894
let this = NSWindow::alloc();
69-
let content_rect = NSRect::new(NSPoint::new(0., 0.), NSSize::new(1024., 768.));
95+
let content_rect = NSRect::new(NSPoint::new(0., 0.), NSSize::new(768., 768.));
7096
let style = NSWindowStyleMaskClosable
7197
| NSWindowStyleMaskResizable
7298
| NSWindowStyleMaskTitled;
@@ -119,34 +145,15 @@ declare_class!(
119145
Ivar::write(&mut this.device, device);
120146
Ivar::write(&mut this.command_queue, command_queue);
121147
Ivar::write(&mut this.pipeline_state, pipeline_state);
148+
Ivar::write(&mut this.pipeline_descriptor, pipeline_descriptor);
122149
Ivar::write(&mut this.window, window);
123150
Ivar::write(&mut this.mtk_view, mtk_view);
151+
Ivar::write(&mut this.start_date, unsafe { NSDate::now() });
124152
NonNull::from(this)
125153
})
126154
}
127155
}
128156

129-
// define the delegate methods for the `NSApplicationDelegate` protocol
130-
unsafe impl NSApplicationDelegate for Delegate {
131-
#[method(applicationDidFinishLaunching:)]
132-
#[allow(non_snake_case)]
133-
unsafe fn applicationDidFinishLaunching(&self, _notification: &NSNotification) {
134-
// configure the metal view delegate
135-
unsafe {
136-
let object = ProtocolObject::from_ref(self);
137-
self.mtk_view.setDelegate(Some(object));
138-
}
139-
140-
// configure the window
141-
unsafe {
142-
self.window.setContentView(Some(&self.mtk_view));
143-
self.window.center();
144-
self.window.setTitle(ns_string!("metal example"));
145-
self.window.makeKeyAndOrderFront(None);
146-
}
147-
}
148-
}
149-
150157
// define the delegate methods for the `MTKViewDelegate` protocol
151158
unsafe impl MTKViewDelegate for Delegate {
152159
#[method(drawInMTKView:)]
@@ -165,10 +172,11 @@ declare_class!(
165172

166173
#[rustfmt::skip]
167174
let vertex_data: &mut [f32] = &mut [
168-
-0.5, -0.5, 0. , 1. , 0. , 0. ,
169-
0.5, -0.5, 0. , 0. , 1. , 0. ,
170-
0. , 0.5, 0. , 0. , 0. , 1. ,
175+
-f32::sqrt(3.0) / 4.0, -0.25, 0. , 1. , 0. , 0. ,
176+
f32::sqrt(3.0) / 4.0, -0.25, 0. , 0. , 1. , 0. ,
177+
0. , 0.5, 0. , 0. , 0. , 1. ,
171178
];
179+
172180
let vertex_bytes = unsafe {
173181
NonNull::new_unchecked(vertex_data.as_mut_ptr().cast::<core::ffi::c_void>())
174182
};
@@ -180,21 +188,45 @@ declare_class!(
180188
)
181189
};
182190

191+
let argument_encoder = unsafe {
192+
self.pipeline_descriptor
193+
.vertexFunction()
194+
.unwrap()
195+
.newArgumentEncoderWithBufferIndex(1)
196+
};
197+
198+
let argument_buffer = self
199+
.device
200+
.newBufferWithLength_options(argument_encoder.encodedLength(), 0)
201+
.unwrap();
202+
203+
unsafe {
204+
argument_encoder.setArgumentBuffer_offset(Some(&*argument_buffer), 0);
205+
};
206+
207+
let time = unsafe {
208+
(argument_encoder.constantDataAtIndex(0).as_ptr() as *mut f32)
209+
.as_mut()
210+
.unwrap()
211+
};
212+
213+
*time = unsafe { self.start_date.timeIntervalSinceNow() as f32 };
214+
215+
unsafe { encoder.setVertexBuffer_offset_atIndex(Some(&*argument_buffer), 0, 1) };
216+
183217
encoder.setRenderPipelineState(&self.pipeline_state);
184218
unsafe {
185219
encoder.drawPrimitives_vertexStart_vertexCount(MTLPrimitiveTypeTriangle, 0, 3)
186220
};
187221
encoder.endEncoding();
188-
189222
command_buffer.presentDrawable(&current_drawable);
190-
191223
command_buffer.commit();
192224
}
193225

194226
#[method(mtkView:drawableSizeWillChange:)]
195227
#[allow(non_snake_case)]
196228
unsafe fn mtkView_drawableSizeWillChange(&self, _view: &MTKView, _size: NSSize) {
197-
println!("mtkView_drawableSizeWillChange");
229+
// println!("mtkView_drawableSizeWillChange");
198230
}
199231
}
200232
);
@@ -216,19 +248,27 @@ fn main() {
216248
r#"
217249
#include <metal_stdlib>
218250
using namespace metal;
251+
struct FragmentShaderArguments {
252+
float time [[id(0)]];
253+
};
219254
struct VertexIn {
220255
packed_float3 position;
221256
packed_float3 color;
222257
};
258+
223259
struct VertexOut {
224260
float4 position [[position]];
225261
float4 color;
226262
};
227-
vertex VertexOut vertex_main(device const VertexIn *vertices [[buffer(0)]],
228-
uint vertexId [[vertex_id]]) {
263+
vertex VertexOut vertex_main(
264+
device const VertexIn *vertices [[buffer(0)]],
265+
device const FragmentShaderArguments & arg [[buffer(1)]],
266+
uint vertexId [[vertex_id]]
267+
) {
229268
VertexOut out;
230-
out.position = float4(vertices[vertexId].position, 1);
231-
out.color = float4(vertices[vertexId].color, 1);
269+
VertexIn vert = vertices[vertexId];
270+
out.position = float4(float2x2(cos(arg.time), -sin(arg.time), sin(arg.time), cos(arg.time))*vert.position.xy, vert.position.z, 1);
271+
out.color = float4(vert.color, 1);
232272
return out;
233273
}
234274
fragment float4 fragment_main(VertexOut in [[stage_in]]) {

0 commit comments

Comments
 (0)