Sign in Join
Wiki copytemporary

Metal Framework: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: Metal Framework

OldNewLine
1+*(macOS only)*
2+
3+## Overview
4+
5+Graphics processors are designed to quickly render graphics and perform data-parallel calculations. The Apple Metal framework allows you to communicate directly with the graphics processor available on a device. Applications that render complex scenes or that perform advanced scientific calculations can use this power to achieve maximum performance. Such applications include:
6+
7+- Games that render sophisticated 3D environments;
8+- Video processing applications, like Final Cut Pro;
9+- Data-crunching applications, such as those used to perform scientific research.
10+
11+Metal works hand-in-hand with other Apple frameworks that supplement its capability. MetalKit simplifies the task of getting your Metal content onscreen. Metal Performance Shaders implement custom rendering functions or to take advantage of a large library of existing functions.
12+
13+Many high level Apple frameworks are built on top of Metal to take advantage of its performance, including Core Image, SpriteKit, and SceneKit. Using one of these high-level frameworks shields you from the details of graphics processor programming, but writing custom Metal code enables you to achieve the highest level of performance.
14+
15+## Metal and Lazarus
16+
17+Metal support in Lazarus uses Ryan Joseph's [lazmetalcontrol](https://github.com/genericptr/Metal-Framework/tree/master/lazarus/package).
18+
19+### Requirements
20+
21+- You will need to have the latest version of Lazarus installed on a macOS computer (or better yet, have the latest Lazarus SVN version).
22+- You will need to download the Lazarus Metal Package (lazmetalcontrol) by Ryan Joseph.
23+- From Lazarus, choose the Package menu -\> Open Package File and select lazmetalcontrol.lpk - install this into Lazarus.
24+- To use Metal you will need macOS 10.11 (El Capitan) or later and a Mac computer that supports Metal - typically Macs from 2012 and later.
25+
26+### Errata
27+
28+The Lazarus 2.0.6 release for macOS contained a regression for OpenGL support. See Bugtracker [Issue \#35797](https://bugs.freepascal.org/view.php?id=35797) GLCocoaNSContext.pas now requires "cocoa_extra" in the *Uses* section.
29+
30+### Lazarus Example Code
31+
32+[ChrisR](https://forum.lazarus.freepascal.org/index.php?action=profile;u=57624) has created a few Lazarus projects that can be compiled for Apple's Metal Framework. The projects can be downloaded from [GitHub](https://github.com/neurolabusc/Metal-Demos) and will compile on Lazarus provided you have met the requirements outlined above.
33+
34+Unfortunately the documentation is sparse, but both the [main page](https://github.com/neurolabusc/Metal-Demos) and the [line project](https://github.com/neurolabusc/Metal-Demos/tree/master/lines) include some useful information.
35+
36+Most of the projects can also be compiled to support [[OpenGL|OpenGL 3.3 Core]] - providing support for Windows, Linux and older Macs. By keeping a thin layer for either OpenGL or Metal, one can retain most of the Lazarus *write once, compile everywhere* magic.
37+
38+These example projects all use Lazarus. However, [Ryan's repository](https://github.com/genericptr/Metal-Framework) also includes some examples of how to use Metal directly from Free Pascal without Lazarus.
39+
40+See this [Forum post](https://forum.lazarus.freepascal.org/index.php/topic,42306.msg366256.html#msg366256) with demo project for offscreen rendering in Metal.
41+
42+### Metal debugging in Xcode
43+
44+If your Lazarus application uses Metal graphics, Igor Kokarev explains below how you can save a GPU trace to a file and then open it in Xcode to check the performance of Metal, view much useful information about your 3D commands and even see a visualization of your 3D scene. Note that this requires macOS 10.15 Catalina or newer and FPC 3.2.0.
45+
46+**Step 1** Download Ryan Joseph's [lazmetalcontrol](https://github.com/genericptr/Metal-Framework/tree/master/lazarus/package).
47+
48+**Step 2** Replace the file `MTLCaptureManager.inc` with this one:
49+
50+``` pascal
51+{ Parsed from Metal.framework /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/Metal.framework/Headers/MTLCaptureManager.h }
52+
53+{$ifdef TYPES}
54+type
55+ MTLCaptureDescriptorPtr = ^MTLCaptureDescriptor;
56+ MTLCaptureManagerPtr = ^MTLCaptureManager;
57+{$endif}
58+
59+{$ifdef EXTERNAL_SYMBOLS}
60+//var
61+// MTLCaptureErrorDomain: NSErrorDomain; cvar; external;
62+{$endif}
63+
64+{$ifdef TYPES}
65+type
66+ MTLCaptureError = NSInteger;
67+ MTLCaptureErrorPtr = ^MTLCaptureError;
68+
69+const
70+ MTLCaptureErrorNotSupported = 1;
71+ MTLCaptureErrorAlreadyCapturing = 2;
72+ MTLCaptureErrorInvalidDescriptor = 3;
73+
74+type
75+ MTLCaptureDestination = NSInteger;
76+ MTLCaptureDestinationPtr = ^MTLCaptureDestination;
77+
78+const
79+ MTLCaptureDestinationDeveloperTools = 1;
80+ MTLCaptureDestinationGPUTraceDocument = 2;
81+{$endif}
82+
83+{$ifdef CLASSES}
84+
85+type
86+ MTLCaptureDescriptor = objcclass external (NSObject, NSCopyingProtocol)
87+ private
88+ _captureObject: id;
89+ _destination: MTLCaptureDestination;
90+ _outputURL: NSURL;
91+ public
92+ procedure setCaptureObject(newValue: id); message 'setCaptureObject:';
93+ function captureObject: id; message 'captureObject';
94+ procedure setDestination(newValue: MTLCaptureDestination); message 'setDestination:';
95+ function destination: MTLCaptureDestination; message 'destination';
96+ procedure setOutputURL(newValue: NSURL); message 'setOutputURL:';
97+ function outputURL: NSURL; message 'outputURL';
98+
99+ { Adopted protocols }
100+ function copyWithZone (zone: NSZonePtr): id; message 'copyWithZone:';
101+ end;
102+
103+type
104+ MTLCaptureManager = objcclass external (NSObject)
105+ private
106+ _isCapturing: objcbool;
107+ _defaultCaptureScope: MTLCaptureScopeProtocol;
108+ public
109+ class function sharedCaptureManager: MTLCaptureManager; message 'sharedCaptureManager';
110+ function init: id; message 'init'; { unavailable in macos, ios }
111+ function newCaptureScopeWithDevice (device: id): id; message 'newCaptureScopeWithDevice:';
112+ function newCaptureScopeWithCommandQueue (commandQueue: id): id; message 'newCaptureScopeWithCommandQueue:';
113+ function supportsDestination (destination: MTLCaptureDestination): objcbool; message 'supportsDestination:'; { available in macos(10.15), ios(13.0) }
114+ function startCaptureWithDescriptor_error (descriptor: MTLCaptureDescriptor; error: NSErrorPtr): objcbool; message 'startCaptureWithDescriptor:error:'; { available in macos(10.15), ios(13.0) }
115+ procedure startCaptureWithDevice (device: id); message 'startCaptureWithDevice:'; deprecated 'Use startCaptureWithDescriptor:error: instead in macos(10.13, 10.15), ios(11.0, 13.0)';
116+ procedure startCaptureWithCommandQueue (commandQueue: id); message 'startCaptureWithCommandQueue:'; deprecated 'Use startCaptureWithDescriptor:error: instead in macos(10.13, 10.15), ios(11.0, 13.0)';
117+ procedure startCaptureWithScope (captureScope: id); message 'startCaptureWithScope:'; deprecated 'Use startCaptureWithDescriptor:error: instead in macos(10.13, 10.15), ios(11.0, 13.0)';
118+ procedure stopCapture; message 'stopCapture';
119+ procedure setDefaultCaptureScope(newValue: id); message 'setDefaultCaptureScope:';
120+ function defaultCaptureScope: id; message 'defaultCaptureScope';
121+ function isCapturing: objcbool; message 'isCapturing';
122+ end;
123+{$endif}
124+```
125+
126+This updated header includes a new Cocoa interface - MTLCaptureDescriptor.
127+
128+**Step 3** Insert a new text line in the existing file `DefinedClassesMetal.pas`:
129+
130+``` pascal
131+MTLCaptureDescriptor = objcclass external;
132+```
133+
134+Ryan will probably include both changes (Steps 2 and 3) in a future update to his Metal framework.
135+
136+**Step 4** Add this key and value to the `Info.plist` file in your application bundle:
137+
138+``` XML
139+<key>MetalCaptureEnabled</key>
140+ <true/>
141+```
142+
143+Note: remove this key when you do a release build for your application because this key has a small negative effect on Metal performance.
144+
145+**Step 5** Add the following code for your Metal application:
146+
147+``` pascal
148+captureManager: MTLCaptureManager;
149+captureDescriptor: MTLCaptureDescriptor;
150+```
151+
152+``` pascal
153+procedure TMetalContext.StartMetalDebug;
154+var
155+ nserr: NSError;
156+ //str: string;
157+begin
158+ // GPU trace for debugging of Metal
159+ captureManager := MTLCaptureManager.sharedCaptureManager;
160+ if captureManager.supportsDestination(MTLCaptureDestinationGPUTraceDocument) then
161+ begin
162+ captureDescriptor := MTLCaptureDescriptor.alloc.init.autorelease;
163+ captureDescriptor.SetCaptureObject(device);
164+ captureDescriptor.SetDestination(MTLCaptureDestinationGPUTraceDocument);
165+ captureDescriptor.setOutputURL(NSURL.URLWithString(StrToNSStr('file:///Users/mac/Development/myapp.gputrace')));
166+
167+ if not captureManager.startCaptureWithDescriptor_error(captureDescriptor, @nserr) then
168+ begin
169+ // Metal captiring failed.
170+ exit;
171+ end;
172+
173+ //str := NSStrToStr(nserr.localizedDescription);
174+ end;
175+end;
176+
177+procedure TMetalContext.StopMetalDebug;
178+begin
179+ captureManager.stopCapture;
180+end;
181+```
182+
183+A saved file with GPU trace should use the `.gputrace` file extension.
184+
185+When you call `stopCapture()` the application will save the *.gputrace file. Double click on this file in the Finder and it will be opened in Xcode for you to explore the Metal performance and 3D data.
186+
187+As it is only possible to capture one frame at a time, just call the *start* and *stop* commands before and after you render each frame.
188+
189+More information is available in the Apple documentation:
190+
191+- [Capturing GPU Command Data Programmatically](https://developer.apple.com/documentation/metal/frame_capture_debugging_tools/capturing_gpu_command_data_programmatically).
192+
193+## External links
194+
195+- [Apple: Sample Code](https://developer.apple.com/metal/sample-code/)
196+- [Apple: Metal Framework Documentation](https://developer.apple.com/documentation/metal)
197+- [Apple: Metal Programming Guide](https://developer.apple.com/library/archive/documentation/Miscellaneous/Conceptual/MetalProgrammingGuide/)
198+- [Apple: Metal Best Practices Guide](https://developer.apple.com/library/archive/documentation/3DDrawing/Conceptual/MTLBestPracticesGuide/)
199+- [Apple: Metal Videos](https://developer.apple.com/videos/graphics-and-games/metal)
200+- [Apple: Metal Forum](https://developer.apple.com/forums/tags/metal)
201+
202+- **[Apple: Porting Your Metal Code to Apple Silicon](https://developer.apple.com/documentation/metal/porting_your_metal_code_to_apple_silicon)**
203+
204+---
205+*From the Free Pascal wiki, page "Metal Framework", as it stood on 2022-02-13 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
206+Category: Code
207+Category: Components
208+Category: Debugging
209+Category: Graphics
210+Category: OpenGL
211+Category: Video
212+Category: macOS

Back to history