@@ -9,11 +9,14 @@ use icrate::{
9
9
NSBackingStoreBuffered , NSWindow , NSWindowStyleMaskClosable , NSWindowStyleMaskResizable ,
10
10
NSWindowStyleMaskTitled ,
11
11
} ,
12
- Foundation :: { NSNotification , NSObject , NSObjectProtocol , NSPoint , NSRect , NSSize , NSString } ,
12
+ Foundation :: {
13
+ NSDate , NSNotification , NSObject , NSObjectProtocol , NSPoint , NSRect , NSSize , NSString ,
14
+ } ,
13
15
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 ,
17
20
} ,
18
21
MetalKit :: { MTKView , MTKViewDelegate } ,
19
22
} ;
@@ -33,8 +36,10 @@ declare_class!(
33
36
device: IvarDrop <Id <ProtocolObject <dyn MTLDevice >>, "_device" >,
34
37
command_queue: IvarDrop <Id <ProtocolObject <dyn MTLCommandQueue >>, "_command_queue" >,
35
38
pipeline_state: IvarDrop <Id <ProtocolObject <dyn MTLRenderPipelineState >>, "_pipeline_state" >,
39
+ pipeline_descriptor: IvarDrop <Id <MTLRenderPipelineDescriptor >, "_pipeline_descriptor" >,
36
40
window: IvarDrop <Id <NSWindow >, "_window" >,
37
41
mtk_view: IvarDrop <Id <MTKView >, "_mtk_view" >,
42
+ start_date: IvarDrop <Id <NSDate >, "_start_date" >,
38
43
}
39
44
mod ivars;
40
45
@@ -45,6 +50,27 @@ declare_class!(
45
50
const NAME : & ' static str = "Delegate" ;
46
51
}
47
52
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
+
48
74
// define the Delegate methods (e.g., initializer)
49
75
unsafe impl Delegate {
50
76
#[ method( initWithShaders: ) ]
@@ -66,7 +92,7 @@ declare_class!(
66
92
// create the app window
67
93
let window = {
68
94
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. ) ) ;
70
96
let style = NSWindowStyleMaskClosable
71
97
| NSWindowStyleMaskResizable
72
98
| NSWindowStyleMaskTitled ;
@@ -119,34 +145,15 @@ declare_class!(
119
145
Ivar :: write( & mut this. device, device) ;
120
146
Ivar :: write( & mut this. command_queue, command_queue) ;
121
147
Ivar :: write( & mut this. pipeline_state, pipeline_state) ;
148
+ Ivar :: write( & mut this. pipeline_descriptor, pipeline_descriptor) ;
122
149
Ivar :: write( & mut this. window, window) ;
123
150
Ivar :: write( & mut this. mtk_view, mtk_view) ;
151
+ Ivar :: write( & mut this. start_date, unsafe { NSDate :: now( ) } ) ;
124
152
NonNull :: from( this)
125
153
} )
126
154
}
127
155
}
128
156
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
-
150
157
// define the delegate methods for the `MTKViewDelegate` protocol
151
158
unsafe impl MTKViewDelegate for Delegate {
152
159
#[ method( drawInMTKView: ) ]
@@ -165,10 +172,11 @@ declare_class!(
165
172
166
173
#[ rustfmt:: skip]
167
174
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. ,
171
178
] ;
179
+
172
180
let vertex_bytes = unsafe {
173
181
NonNull :: new_unchecked( vertex_data. as_mut_ptr( ) . cast:: <core:: ffi:: c_void>( ) )
174
182
} ;
@@ -180,21 +188,45 @@ declare_class!(
180
188
)
181
189
} ;
182
190
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
+
183
217
encoder. setRenderPipelineState( & self . pipeline_state) ;
184
218
unsafe {
185
219
encoder. drawPrimitives_vertexStart_vertexCount( MTLPrimitiveTypeTriangle , 0 , 3 )
186
220
} ;
187
221
encoder. endEncoding( ) ;
188
-
189
222
command_buffer. presentDrawable( & current_drawable) ;
190
-
191
223
command_buffer. commit( ) ;
192
224
}
193
225
194
226
#[ method( mtkView: drawableSizeWillChange: ) ]
195
227
#[ allow( non_snake_case) ]
196
228
unsafe fn mtkView_drawableSizeWillChange( & self , _view: & MTKView , _size: NSSize ) {
197
- println!( "mtkView_drawableSizeWillChange" ) ;
229
+ // println!("mtkView_drawableSizeWillChange");
198
230
}
199
231
}
200
232
) ;
@@ -216,19 +248,27 @@ fn main() {
216
248
r#"
217
249
#include <metal_stdlib>
218
250
using namespace metal;
251
+ struct FragmentShaderArguments {
252
+ float time [[id(0)]];
253
+ };
219
254
struct VertexIn {
220
255
packed_float3 position;
221
256
packed_float3 color;
222
257
};
258
+
223
259
struct VertexOut {
224
260
float4 position [[position]];
225
261
float4 color;
226
262
};
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
+ ) {
229
268
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);
232
272
return out;
233
273
}
234
274
fragment float4 fragment_main(VertexOut in [[stage_in]]) {
0 commit comments