Skip to content

Instantly share code, notes, and snippets.

Last active May 20, 2021 08:10
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
What would you like to do?
Minimal OSX Metal Application, single file
#include <Cocoa/Cocoa.h>
#import <Metal/Metal.h>
#import <MetalKit/MetalKit.h>
#import <simd/simd.h>
// BUG: on OSX 10.15.6, the App menu is not clickable at the first activation, but becomes so after switching to another app
@interface AppApplicationDelegate : NSObject < NSApplicationDelegate >
@interface AppWindowDelegate : NSObject < NSWindowDelegate >
@interface AppMetalView : MTKView
int main()
[NSAutoreleasePool new];
[NSApplication sharedApplication];
AppApplicationDelegate* appdelegate = [[AppApplicationDelegate alloc] init];
[NSApp setDelegate:appdelegate];
// Window
NSWindow* window = [[NSWindow alloc] autorelease];
[window initWithContentRect:NSMakeRect(0, 0, 800, 600)
styleMask:NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask
[window setTitle:@"appName"];
[window setLevel:NSNormalWindowLevel];
[window center];
[window makeKeyAndOrderFront:nil];
AppWindowDelegate* windelegate = [[AppWindowDelegate alloc] init];
[window setDelegate:windelegate];
// Custom MTKView
AppMetalView* view = [[AppMetalView alloc] initWithFrame:window.frame];
window.contentView = view;
// Run
[NSApp run];
return 0;
@implementation AppWindowDelegate
-(BOOL)windowShouldClose : (id)window
[NSApp terminate:nil];
return true;
@implementation AppApplicationDelegate
-(void)applicationWillFinishLaunching:(NSNotification *)aNotification
// Menu
id quitMenuItemTitle = [@"Quit " stringByAppendingString:@"appName"];
id quitMenuItem = [[NSMenuItem alloc] autorelease];
id appMenu = [[NSMenu new] autorelease];
[appMenu addItem:quitMenuItem];
id appMenuItem = [[NSMenuItem new] autorelease];
[appMenuItem setSubmenu:appMenu];
id mainMenu = [[NSMenu new] autorelease];
[mainMenu addItem:appMenuItem];
[NSApp setMainMenu:mainMenu];
// Required since OSX 10.6 to get menubar and bring to front
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
-(void)applicationDidFinishLaunching:(NSNotification *)notification
// Required since OSX 10.15 to get menubar working at launch
[NSApp activateIgnoringOtherApps:YES];
@implementation AppMetalView
id <MTLCommandQueue> _commandQueue;
long _frame;
- (id)initWithFrame:(CGRect)inFrame
// Select a GPU to run on
// Note that on Intel laptops, the Metal "system default device" is always the discrete GPU
// even if `pmset -a gpuswitch 0` has been used to force the integrated GPU.
id<MTLDevice> device = MTLCreateSystemDefaultDevice();
self = [super initWithFrame:inFrame device:device];
if (self)
[self setup];
return self;
- (void)setup
self.colorPixelFormat = MTLPixelFormatBGRA8Unorm;
self.depthStencilPixelFormat = MTLPixelFormatDepth32Float_Stencil8;
_commandQueue = [self.device newCommandQueue];
- (void)drawRect:(CGRect)rect
// Animate clear color
float rad = _frame * 0.01f;
float sin = std::sin(rad), cos = std::cos(rad);
self.clearColor = MTLClearColorMake(0.5f*sin+0.5f, 0.5f, 0.25f*cos+0.25f, 1.0f);
// Clear the drawable
id <MTLCommandBuffer> commandBuffer = [_commandQueue commandBuffer];
MTLRenderPassDescriptor *currentRenderPassDescriptor = self.currentRenderPassDescriptor;
id <MTLRenderCommandEncoder> encoder =
[commandBuffer renderCommandEncoderWithDescriptor:currentRenderPassDescriptor];
[encoder setViewport:(MTLViewport){0, 0, self.drawableSize.width, self.drawableSize.height, 0, 1}];
[encoder endEncoding];
// Present the drawing
[commandBuffer presentDrawable:self.currentDrawable];
[commandBuffer commit];
// Draw children
[super drawRect:rect];
Copy link

jim-ec commented Mar 19, 2021

Had to compile it with:

clang++ -o minimal-metal-app -framework Cocoa -framework Metal -framework MetalKit

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment