11// @ts -check
22
3+ // https://developer.apple.com/documentation/metal/using_a_render_pipeline_to_render_primitives?language=objc
4+
35import "objc" ;
46
7+ objc . import ( "Metal" ) ;
8+ objc . import ( "MetalKit" ) ;
9+
510export class ApplicationDelegate extends NSObject {
611 static ObjCProtocols = [ NSApplicationDelegate , NSWindowDelegate ] ;
712
@@ -30,19 +35,11 @@ export class ApplicationDelegate extends NSObject {
3035 window . title = "NativeScript for macOS" ;
3136 window . delegate = this ;
3237 window . styleMask = NSWindowStyleMask . Titled | NSWindowStyleMask . Closable |
33- NSWindowStyleMask . Miniaturizable | NSWindowStyleMask . Resizable |
34- NSWindowStyleMask . FullSizeContentView ;
38+ NSWindowStyleMask . Miniaturizable | NSWindowStyleMask . Resizable ;
3539
3640 window . titlebarAppearsTransparent = true ;
3741 window . titleVisibility = NSWindowTitleVisibility . Hidden ;
3842
39- window . backgroundColor = NSColor . colorWithSRGBRedGreenBlueAlpha (
40- 118 / 255 ,
41- 171 / 255 ,
42- 235 / 255 ,
43- 1 ,
44- ) ;
45-
4643 window . makeKeyAndOrderFront ( this ) ;
4744
4845 NSApp . activateIgnoringOtherApps ( false ) ;
@@ -56,17 +53,219 @@ export class ApplicationDelegate extends NSObject {
5653 }
5754}
5855
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+
59245export class ViewController extends NSViewController {
60246 static {
61247 NativeClass ( this ) ;
62248 }
63249
250+ /** @type {MTKView } */
251+ mtkView ;
252+
64253 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+ ) ;
66261 }
67262
68263 viewDidLoad ( ) {
69264 super . viewDidLoad ( ) ;
265+
266+ this . renderer = Renderer . new ( ) . initWithMtkView ( this . mtkView ) ;
267+
268+ this . mtkView . delegate = this . renderer ;
70269 }
71270}
72271
0 commit comments