Last active
December 12, 2022 13:07
-
-
Save sortofsleepy/2f6b6fd9c818fd7697b942ff8bfa31cb to your computer and use it in GitHub Desktop.
Basic setup of getting a Metal context up and running.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// ViewController.h | |
// metal.test | |
// | |
// Created by josephchow on 12/10/19. | |
// Copyright © 2019 josephchow. All rights reserved. | |
// | |
#import <UIKit/UIKit.h> | |
#import <Metal/Metal.h> | |
#import <MetalKit/MetalKit.h> | |
#import <vector> | |
#import <memory> | |
/** | |
Quick abstracted sample of how to draw a triangle with Metal. Follows Ray Wenderlich tutorial. | |
https://www.raywenderlich.com/7475-metal-tutorial-getting-started | |
*/ | |
typedef std::shared_ptr<class Vbo> VboRef; | |
class Vbo { | |
public: | |
Vbo(id<MTLDevice> device){ | |
this->device = device; | |
} | |
//! Add data | |
template<typename T> | |
void bufferData(std::vector<T> &data){ | |
buffer = [device newBufferWithBytes:data.data() length:sizeof(T) * data.size() options:MTLResourceCPUCacheModeDefaultCache]; | |
} | |
//! Returns the buffer. | |
id<MTLBuffer> getBuffer() { return buffer; } | |
protected: | |
id <MTLDevice> device; | |
id <MTLBuffer> buffer; | |
}; | |
@interface ViewController : UIViewController{ | |
// device referencing the GPU | |
id <MTLDevice> device; | |
id <MTLBuffer> buffer; | |
// used to render something to screen | |
id <MTLRenderPipelineState> pipeline; | |
// timer synced to display refresh rate. | |
CADisplayLink * timer; | |
// object used to render something to screen. | |
CAMetalLayer * layer; | |
id <MTLCommandQueue> commandQueue; | |
Vbo * vbo; | |
}; | |
- (void) draw; | |
@end | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// ViewController.m | |
// metal.test | |
// | |
// Created by josephchow on 12/10/19. | |
// Copyright © 2019 josephchow. All rights reserved. | |
// | |
#import "ViewController.h" | |
@interface ViewController () | |
@end | |
@implementation ViewController | |
- (void)viewDidLoad { | |
[super viewDidLoad]; | |
// Do any additional setup after loading the view. | |
// ======= LOAD DEVICE ======== // | |
device = MTLCreateSystemDefaultDevice(); | |
if(device == nil){ | |
NSLog(@"Deivce nil"); | |
} | |
// ========= BUILD LAYER ======== // | |
layer = [[CAMetalLayer alloc] init]; | |
layer.device = device; | |
layer.pixelFormat = MTLPixelFormatBGRA8Unorm; | |
layer.framebufferOnly = true; | |
layer.frame = self.view.layer.frame; | |
[self.view.layer addSublayer:layer]; | |
// ====== LOAD DATA =========== // | |
std::vector<float> data = { | |
0.0, 1.0, 0.0, | |
-1.0, -1.0, 0.0, | |
1.0, -1.0, 0.0 | |
}; | |
vbo = new Vbo(device); | |
vbo->bufferData(data); | |
// ========= LOAD SHADER ======== // | |
// looks for all .metal source files set in compiled sources. | |
id <MTLLibrary> defaultLibrary = [device newDefaultLibrary]; | |
id <MTLFunction> vertex_func = [defaultLibrary newFunctionWithName:@"basic_vertex"]; | |
id <MTLFunction> fragment_func = [defaultLibrary newFunctionWithName:@"basic_fragment"]; | |
// ======== BUILD PIPELINE DESCRIPTOR AND PIPELINE STATE ========= // | |
MTLRenderPipelineDescriptor * descrip = [[MTLRenderPipelineDescriptor alloc] init]; | |
descrip.label = @"MyCapturedImagePipeline"; | |
descrip.vertexFunction = vertex_func; | |
descrip.fragmentFunction =fragment_func; | |
descrip.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm; | |
NSError * err = nil; | |
pipeline = [device newRenderPipelineStateWithDescriptor:descrip error:&err]; | |
if (err != nil) { | |
NSLog(@"Error creating render pipeline state: %@",[err localizedFailureReason]); | |
} | |
// ======== BUILD COMMAND QUEUE =========== // | |
commandQueue = [device newCommandQueue]; | |
// ======= SETUP DISPLAY LINKE ========= // | |
timer = [CADisplayLink displayLinkWithTarget:self selector:@selector(draw)]; | |
[timer addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; | |
} | |
-(void) draw { | |
//===== BUILD RENDER PASS DESCRIPTOR ======= // | |
auto drawable = layer.nextDrawable; | |
if(drawable != nil){ | |
MTLClearColor color = MTLClearColor(); | |
color.red = 0.0f; | |
color.green = 104.0 / 255.0; | |
color.blue = 55.0 / 255.0; | |
color.alpha = 1.0; | |
MTLRenderPassDescriptor * renderPassDescriptor = [[MTLRenderPassDescriptor alloc] init]; | |
renderPassDescriptor.colorAttachments[0].texture = drawable.texture; | |
renderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear; | |
renderPassDescriptor.colorAttachments[0].clearColor = color; | |
id<MTLCommandBuffer> commandBuffer = [commandQueue commandBuffer]; | |
id<MTLRenderCommandEncoder> renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor]; | |
[renderEncoder setRenderPipelineState:pipeline]; | |
//[renderEncoder setVertexBuffer:buffer offset:0 atIndex:0]; | |
[renderEncoder setVertexBuffer:vbo->getBuffer() offset:0 atIndex:0]; | |
[renderEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:3 instanceCount:1]; | |
[renderEncoder endEncoding]; | |
[commandBuffer presentDrawable:drawable]; | |
[commandBuffer commit]; | |
} | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment