1
1
// @ts -check
2
2
3
+ // https://developer.apple.com/documentation/metal/using_a_render_pipeline_to_render_primitives?language=objc
4
+
3
5
import "objc" ;
4
6
7
+ objc . import ( "Metal" ) ;
8
+ objc . import ( "MetalKit" ) ;
9
+
5
10
export class ApplicationDelegate extends NSObject {
6
11
static ObjCProtocols = [ NSApplicationDelegate , NSWindowDelegate ] ;
7
12
@@ -30,19 +35,11 @@ export class ApplicationDelegate extends NSObject {
30
35
window . title = "NativeScript for macOS" ;
31
36
window . delegate = this ;
32
37
window . styleMask = NSWindowStyleMask . Titled | NSWindowStyleMask . Closable |
33
- NSWindowStyleMask . Miniaturizable | NSWindowStyleMask . Resizable |
34
- NSWindowStyleMask . FullSizeContentView ;
38
+ NSWindowStyleMask . Miniaturizable | NSWindowStyleMask . Resizable ;
35
39
36
40
window . titlebarAppearsTransparent = true ;
37
41
window . titleVisibility = NSWindowTitleVisibility . Hidden ;
38
42
39
- window . backgroundColor = NSColor . colorWithSRGBRedGreenBlueAlpha (
40
- 118 / 255 ,
41
- 171 / 255 ,
42
- 235 / 255 ,
43
- 1 ,
44
- ) ;
45
-
46
43
window . makeKeyAndOrderFront ( this ) ;
47
44
48
45
NSApp . activateIgnoringOtherApps ( false ) ;
@@ -56,17 +53,219 @@ export class ApplicationDelegate extends NSObject {
56
53
}
57
54
}
58
55
56
+ // deno-fmt-ignore
57
+ const vertices = new Float32Array ( [
58
+ 250 , - 250 , 0 , 0 , 1 , 0 , 0 , 1 ,
59
+ - 250 , - 250 , 0 , 0 , 0 , 1 , 0 , 1 ,
60
+ 0 , 250 , 0 , 0 , 0 , 0 , 1 , 1 ,
61
+ ] ) ;
62
+
63
+ /**
64
+ * @implements {MTKViewDelegate}
65
+ */
66
+ export class Renderer extends NSObject {
67
+ static ObjCProtocols = [ MTKViewDelegate ] ;
68
+
69
+ static {
70
+ NativeClass ( this ) ;
71
+ }
72
+
73
+ /** @type {MTLDevice } */
74
+ device ;
75
+ /** @type {MTLRenderPipelineState } */
76
+ pipelineState ;
77
+ /** @type {MTLCommandQueue } */
78
+ commandQueue ;
79
+ /** @type {Uint32Array } */
80
+ viewportSize ;
81
+
82
+ /**
83
+ * @param {MTKView } mtkView
84
+ */
85
+ initWithMtkView ( mtkView ) {
86
+ this . device = mtkView . device ;
87
+
88
+ const error = new interop . Reference ( ) ;
89
+ const library = this . device . newLibraryWithSourceOptionsError (
90
+ `
91
+ #ifndef AAPLShaderTypes_h
92
+ #define AAPLShaderTypes_h
93
+
94
+ #include <simd/simd.h>
95
+
96
+ typedef enum AAPLVertexInputIndex
97
+ {
98
+ AAPLVertexInputIndexVertices = 0,
99
+ AAPLVertexInputIndexViewportSize = 1,
100
+ } AAPLVertexInputIndex;
101
+
102
+ typedef struct
103
+ {
104
+ vector_float2 position;
105
+ vector_float4 color;
106
+ } AAPLVertex;
107
+
108
+ #endif /* AAPLShaderTypes_h */
109
+
110
+ #include <metal_stdlib>
111
+
112
+ using namespace metal;
113
+
114
+ struct RasterizerData
115
+ {
116
+ float4 position [[position]];
117
+ float4 color;
118
+ };
119
+
120
+ vertex RasterizerData
121
+ vertexShader(uint vertexID [[vertex_id]],
122
+ constant AAPLVertex *vertices [[buffer(AAPLVertexInputIndexVertices)]],
123
+ constant vector_uint2 *viewportSizePointer [[buffer(AAPLVertexInputIndexViewportSize)]])
124
+ {
125
+ RasterizerData out;
126
+
127
+ float2 pixelSpacePosition = vertices[vertexID].position.xy;
128
+
129
+ vector_float2 viewportSize = vector_float2(*viewportSizePointer);
130
+
131
+ out.position = vector_float4(0.0, 0.0, 0.0, 1.0);
132
+ out.position.xy = pixelSpacePosition / (viewportSize / 2.0);
133
+
134
+ out.color = vertices[vertexID].color;
135
+
136
+ return out;
137
+ }
138
+
139
+ fragment float4 fragmentShader(RasterizerData in [[stage_in]])
140
+ {
141
+ return in.color;
142
+ }
143
+
144
+ ` ,
145
+ null ,
146
+ error ,
147
+ ) ;
148
+
149
+ if ( ! library ) {
150
+ console . log ( error . value ) ;
151
+ throw new Error ( "Failed to create library" ) ;
152
+ }
153
+
154
+ const vertexFunction = library . newFunctionWithName ( "vertexShader" ) ;
155
+ const fragmentFunction = library . newFunctionWithName ( "fragmentShader" ) ;
156
+
157
+ const descriptor = MTLRenderPipelineDescriptor . new ( ) ;
158
+ descriptor . vertexFunction = vertexFunction ;
159
+ descriptor . fragmentFunction = fragmentFunction ;
160
+ descriptor . colorAttachments . objectAtIndexedSubscript ( 0 ) . pixelFormat =
161
+ mtkView . colorPixelFormat ;
162
+
163
+ this . pipelineState = this . device . newRenderPipelineStateWithDescriptorError (
164
+ descriptor ,
165
+ error ,
166
+ ) ;
167
+
168
+ if ( ! this . pipelineState ) {
169
+ console . log ( error . value ) ;
170
+ throw new Error ( "Failed to create pipeline state" ) ;
171
+ }
172
+
173
+ this . commandQueue = this . device . newCommandQueue ( ) ;
174
+
175
+ this . viewportSize = new Uint32Array ( [
176
+ mtkView . drawableSize . width ,
177
+ mtkView . drawableSize . height ,
178
+ ] ) ;
179
+
180
+ return this ;
181
+ }
182
+
183
+ /**
184
+ * @param {MTKView } _view
185
+ * @param {CGSize } size
186
+ */
187
+ mtkViewDrawableSizeWillChange ( _view , size ) {
188
+ this . viewportSize [ 0 ] = size . width ;
189
+ this . viewportSize [ 1 ] = size . height ;
190
+ }
191
+
192
+ /**
193
+ * @param {MTKView } view
194
+ */
195
+ drawInMTKView ( view ) {
196
+ const commandBuffer = this . commandQueue . commandBuffer ( ) ;
197
+ commandBuffer . label = "MyCommand" ;
198
+
199
+ const renderPassDescriptor = view . currentRenderPassDescriptor ;
200
+
201
+ if ( renderPassDescriptor !== null ) {
202
+ const renderEncoder = commandBuffer . renderCommandEncoderWithDescriptor (
203
+ renderPassDescriptor ,
204
+ ) ;
205
+ renderEncoder . label = "MyRenderEncoder" ;
206
+
207
+ renderEncoder . setViewport ( {
208
+ originX : 0 ,
209
+ originY : 0 ,
210
+ width : this . viewportSize [ 0 ] ,
211
+ height : this . viewportSize [ 1 ] ,
212
+ znear : 0 ,
213
+ zfar : 1. ,
214
+ } ) ;
215
+
216
+ renderEncoder . setRenderPipelineState ( this . pipelineState ) ;
217
+
218
+ renderEncoder . setVertexBytesLengthAtIndex (
219
+ vertices ,
220
+ vertices . byteLength ,
221
+ 0 ,
222
+ ) ;
223
+
224
+ renderEncoder . setVertexBytesLengthAtIndex (
225
+ this . viewportSize ,
226
+ this . viewportSize . byteLength ,
227
+ 1 ,
228
+ ) ;
229
+
230
+ renderEncoder . drawPrimitivesVertexStartVertexCount (
231
+ MTLPrimitiveType . Triangle ,
232
+ 0 ,
233
+ 3 ,
234
+ ) ;
235
+
236
+ renderEncoder . endEncoding ( ) ;
237
+
238
+ commandBuffer . presentDrawable ( view . currentDrawable ) ;
239
+ }
240
+
241
+ commandBuffer . commit ( ) ;
242
+ }
243
+ }
244
+
59
245
export class ViewController extends NSViewController {
60
246
static {
61
247
NativeClass ( this ) ;
62
248
}
63
249
250
+ /** @type {MTKView } */
251
+ mtkView ;
252
+
64
253
loadView ( ) {
65
- this . view = NSView . new ( ) ;
254
+ this . mtkView = this . view = MTKView . alloc ( ) . initWithFrameDevice (
255
+ {
256
+ origin : { x : 0 , y : 0 } ,
257
+ size : { width : 480 , height : 480 } ,
258
+ } ,
259
+ MTLCreateSystemDefaultDevice ( ) ,
260
+ ) ;
66
261
}
67
262
68
263
viewDidLoad ( ) {
69
264
super . viewDidLoad ( ) ;
265
+
266
+ this . renderer = Renderer . new ( ) . initWithMtkView ( this . mtkView ) ;
267
+
268
+ this . mtkView . delegate = this . renderer ;
70
269
}
71
270
}
72
271
0 commit comments