By now, you might have all noticed I am in love with Swift. I am also an avid user of Xcode playgrounds. This week we will take our Metal code and put it into a playground. Huzzah, for Metal prototyping in the playgrounds!

Let’s start by creating a new Xcode playground for OS X. Once created, click the Show the Assistant editor button and also press Command + 1 to show the Project navigator as well. Your playground should look like this:

alt text

First thing we do is create Shaders.metal under the Resources folder in the Project navigator with the same source code from the previous episode of this series. Next, we create MathUtils.swift and MetalView.swift under the Sources folder. The only change we make in MathUtils.swift is we create a handy initializer for the Vertex struct:

struct Vertex {
var position: vector_float4
var color: vector_float4
init(pos: vector_float4, col: vector_float4) {
position = pos
color = col

In MetalView.swift we need to make more changes though. First, we need to make the class public as we will call it from outside the Sources folder. Consequently, the initializer and the drawRect(:) method need to become public as well. Also, we will create a second initializer so we can create a MetalView with a given frame:

public class MetalView: MTKView {
required public init(coder: NSCoder) {
super.init(coder: coder)

override public init(frame frameRect: CGRect, device: MTLDevice?) {
super.init(frame: frameRect, device: device)

Next, we need to make a rather curious change because as you notice, creating a Library:

let library = device.newDefaultLibrary()!

fails with this error message: failed assertion `filepath must not be nil.'

Since the playground does not have a default filepath that we could use, we will need to create our own:

func registerShaders() {
let path = NSBundle.mainBundle().pathForResource("Shaders", ofType: "metal")
let input: String?
let library: MTLLibrary
let vert_func: MTLFunction
let frag_func: MTLFunction
do {
input = try String(contentsOfFile: path!, encoding: NSUTF8StringEncoding)
library = try device!.newLibraryWithSource(input!, options: nil)
vert_func = library.newFunctionWithName("vertex_func")!
frag_func = library.newFunctionWithName("fragment_func")!
let rpld = MTLRenderPipelineDescriptor()
rpld.vertexFunction = vert_func
rpld.fragmentFunction = frag_func
rpld.colorAttachments[0].pixelFormat = .BGRA8Unorm
rps = try device!.newRenderPipelineStateWithDescriptor(rpld)
} catch let e {

Notice that we tell the playground to find a path where a resource named Shaders of type metal exists. Next, we convert that file into a large String and then we create the library from this source.

Finally, we go to the playground’s main page and create a new MetalView with a given frame. Then we tell the playground to present us the live view:

import Cocoa
import XCPlayground

let device = MTLCreateSystemDefaultDevice()!
let frame = NSRect(x: 0, y: 0, width: 300, height: 300)
let view = MetalView(frame: frame, device: device)
XCPlaygroundPage.currentPage.liveView = view

If you are showing the Timeline in the Assistant editor you should have a similar view:

alt text

The source code is posted on Github as usual.

Until next time!