diff --git a/ch04/chapter04.xcodeproj/project.pbxproj b/ch04/chapter04.xcodeproj/project.pbxproj index ae8dba4..428e017 100644 --- a/ch04/chapter04.xcodeproj/project.pbxproj +++ b/ch04/chapter04.xcodeproj/project.pbxproj @@ -33,6 +33,16 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 293936291D96FDD500008B3A /* Supporting files */ = { + isa = PBXGroup; + children = ( + 29C87D461C56E93B005F4615 /* Main.storyboard */, + 29C87D491C56E93B005F4615 /* Info.plist */, + 29C87D401C56E93A005F4615 /* AppDelegate.swift */, + ); + name = "Supporting files"; + sourceTree = ""; + }; 29C87D341C56E93A005F4615 = { isa = PBXGroup; children = ( @@ -54,9 +64,7 @@ children = ( 29C87D511C56E9DE005F4615 /* MetalView.swift */, 29C87D4F1C56E9C2005F4615 /* Shaders.metal */, - 29C87D461C56E93B005F4615 /* Main.storyboard */, - 29C87D491C56E93B005F4615 /* Info.plist */, - 29C87D401C56E93A005F4615 /* AppDelegate.swift */, + 293936291D96FDD500008B3A /* Supporting files */, ); path = chapter04; sourceTree = ""; diff --git a/ch04/chapter04.xcodeproj/project.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate b/ch04/chapter04.xcodeproj/project.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate index 059fd6f..43b3357 100644 Binary files a/ch04/chapter04.xcodeproj/project.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate and b/ch04/chapter04.xcodeproj/project.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/ch04/chapter04.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter04.xcscheme b/ch04/chapter04.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter04.xcscheme index 84e0aed..56204a9 100644 --- a/ch04/chapter04.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter04.xcscheme +++ b/ch04/chapter04.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter04.xcscheme @@ -50,6 +50,8 @@ ignoresPersistentStateOnLaunch = "NO" debugDocumentVersioning = "YES" debugServiceExtension = "internal" + enableGPUFrameCaptureMode = "3" + enableGPUValidationMode = "1" allowLocationSimulation = "YES"> diff --git a/ch04/chapter04/MetalView.swift b/ch04/chapter04/MetalView.swift index 744f295..13712ee 100644 --- a/ch04/chapter04/MetalView.swift +++ b/ch04/chapter04/MetalView.swift @@ -27,36 +27,32 @@ class MetalView: MTKView { func createBuffer() { device = MTLCreateSystemDefaultDevice()! - commandQueue = device!.newCommandQueue() - let vertexData = [Vertex(position: [-1.0, -1.0, 0.0, 1.0], color: [1, 0, 0, 1]), - Vertex(position: [ 1.0, -1.0, 0.0, 1.0], color: [0, 1, 0, 1]), - Vertex(position: [ 0.0, 1.0, 0.0, 1.0], color: [0, 0, 1, 1])] - vertexBuffer = device!.newBuffer(withBytes: vertexData, length: sizeof(Vertex.self) * 3, options:[]) + commandQueue = device!.makeCommandQueue() + let vertexData = [Vertex(position: [-0.5, -0.5, 0.0, 1.0], color: [1, 0, 0, 1]), + Vertex(position: [ 0.5, -0.5, 0.0, 1.0], color: [0, 1, 0, 1]), + Vertex(position: [ 0.0, 0.5, 0.0, 1.0], color: [0, 0, 1, 1])] + vertexBuffer = device!.makeBuffer(bytes: vertexData, length: MemoryLayout.size * 3, options:[]) } func registerShaders() { let library = device!.newDefaultLibrary()! - let vertex_func = library.newFunction(withName: "vertex_func") - let frag_func = library.newFunction(withName: "fragment_func") + let vertex_func = library.makeFunction(name: "vertex_func") + let frag_func = library.makeFunction(name: "fragment_func") let rpld = MTLRenderPipelineDescriptor() rpld.vertexFunction = vertex_func rpld.fragmentFunction = frag_func rpld.colorAttachments[0].pixelFormat = .bgra8Unorm - do { - try rps = device!.newRenderPipelineState(with: rpld) - } catch let error { - self.print("\(error)") - } + rps = try! device!.makeRenderPipelineState(descriptor: rpld) } override func draw(_ dirtyRect: NSRect) { if let drawable = currentDrawable, let rpd = currentRenderPassDescriptor { rpd.colorAttachments[0].clearColor = MTLClearColorMake(0.5, 0.5, 0.5, 1.0) - let commandBuffer = commandQueue!.commandBuffer() - let commandEncoder = commandBuffer.renderCommandEncoder(with: rpd) + let commandBuffer = commandQueue!.makeCommandBuffer() + let commandEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: rpd) commandEncoder.setRenderPipelineState(rps!) commandEncoder.setVertexBuffer(vertexBuffer, offset: 0, at: 0) - commandEncoder.drawPrimitives(.triangle, vertexStart: 0, vertexCount: 3, instanceCount: 1) + commandEncoder.drawPrimitives(type: .triangle, vertexStart: 0, vertexCount: 3, instanceCount: 1) commandEncoder.endEncoding() commandBuffer.present(drawable) commandBuffer.commit() diff --git a/ch17/chapter17.playground/Contents.swift b/ch17/chapter17.playground/Contents.swift new file mode 100644 index 0000000..01fb50a --- /dev/null +++ b/ch17/chapter17.playground/Contents.swift @@ -0,0 +1,8 @@ + +import MetalKit +import PlaygroundSupport + +let view = MTKView(frame: NSRect(x: 0, y: 0, width: 300, height: 300)) +let renderer = Render(mtkView: view) +view.delegate = renderer +PlaygroundPage.current.liveView = view diff --git a/ch17/chapter17.playground/Resources/Shaders.metal b/ch17/chapter17.playground/Resources/Shaders.metal new file mode 100644 index 0000000..93a57ab --- /dev/null +++ b/ch17/chapter17.playground/Resources/Shaders.metal @@ -0,0 +1,24 @@ + +#include + +using namespace metal; + +struct Vertex { + float4 position [[position]]; + float4 color; +}; + +vertex Vertex vertex_transform(device Vertex *vertices [[buffer(0)]], + uint vertexId [[vertex_id]]) +{ + Vertex out; + out.position = vertices[vertexId].position; + out.color = vertices[vertexId].color; + return out; +} + +fragment half4 fragment_lighting(Vertex fragmentIn [[stage_in]]) +{ +// return half4(fragmentIn.color); + return half4(0.0, 1.0, 0.0, 1.0); +} diff --git a/ch17/chapter17.playground/Sources/Render.swift b/ch17/chapter17.playground/Sources/Render.swift new file mode 100644 index 0000000..afea1d9 --- /dev/null +++ b/ch17/chapter17.playground/Sources/Render.swift @@ -0,0 +1,73 @@ + +import MetalKit + +public class Render : NSObject, MTKViewDelegate { + + weak var view: MTKView! + let commandQueue: MTLCommandQueue + let renderPipelineState: MTLRenderPipelineState + let device: MTLDevice + var vertexBuffer: MTLBuffer + var indexBuffer: MTLBuffer + + struct Vertex { + var position: float4 + var color: float4 + } + + public init?(mtkView: MTKView) { + view = mtkView + view.clearColor = MTLClearColorMake(0.5, 0.5, 0.5, 1) + view.colorPixelFormat = .bgra8Unorm + device = MTLCreateSystemDefaultDevice()! + commandQueue = device.makeCommandQueue() + renderPipelineState = try! Render.buildRenderPipelineWithDevice(device: device, view: mtkView) + + var vertices = [Vertex]() + vertices.append(Vertex(position: float4(-0.5, -0.5, 0, 1), color: float4(1, 0, 0, 1))) + vertices.append(Vertex(position: float4( 0.5, -0.5, 0, 1), color: float4(0, 1, 0, 1))) + vertices.append(Vertex(position: float4( 0.0, 0.5, 0, 1), color: float4(0, 0, 1, 1))) + + var indices = [UInt16]() + indices.append(0) + indices.append(1) + indices.append(2) + + vertexBuffer = device.makeBuffer(bytes: vertices, length: MemoryLayout.stride * vertices.count, options: []) + indexBuffer = device.makeBuffer(bytes: indices, length: MemoryLayout.stride * indices.count, options: []) + + super.init() + view.delegate = self + view.device = device + } + + class func buildRenderPipelineWithDevice(device: MTLDevice, view: MTKView) throws -> MTLRenderPipelineState { + let path = Bundle.main.path(forResource: "Shaders", ofType: "metal")! + let input = try! String(contentsOfFile: path, encoding: String.Encoding.utf8) + let library = try! device.makeLibrary(source: input, options: nil) + let vertexFunction = library.makeFunction(name: "vertex_transform") + let fragmentFunction = library.makeFunction(name: "fragment_lighting") + let pipelineDescriptor = MTLRenderPipelineDescriptor() + pipelineDescriptor.sampleCount = view.sampleCount + pipelineDescriptor.vertexFunction = vertexFunction + pipelineDescriptor.fragmentFunction = fragmentFunction + pipelineDescriptor.colorAttachments[0].pixelFormat = .bgra8Unorm + return try device.makeRenderPipelineState(descriptor: pipelineDescriptor) + } + + public func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {} + + public func draw(in view: MTKView) { + let commandBuffer = commandQueue.makeCommandBuffer() + let renderPassDescriptor = view.currentRenderPassDescriptor! + let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: renderPassDescriptor) + renderEncoder.setVertexBuffer(vertexBuffer, offset:0, at:0) + renderEncoder.setRenderPipelineState(renderPipelineState) + renderEncoder.setTriangleFillMode(.lines) + renderEncoder.drawIndexedPrimitives(type: .triangle, indexCount: 3, indexType: .uint16, indexBuffer: indexBuffer,indexBufferOffset: 0) + renderEncoder.endEncoding() + commandBuffer.present(view.currentDrawable!) + commandBuffer.commit() + } +} + diff --git a/ch17/chapter17.playground/contents.xcplayground b/ch17/chapter17.playground/contents.xcplayground new file mode 100644 index 0000000..06828af --- /dev/null +++ b/ch17/chapter17.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/ch17/chapter17.playground/playground.xcworkspace/contents.xcworkspacedata b/ch17/chapter17.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/ch17/chapter17.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ch17/chapter17.playground/playground.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate b/ch17/chapter17.playground/playground.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..6cfead6 Binary files /dev/null and b/ch17/chapter17.playground/playground.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/ch17/chapter17.playground/timeline.xctimeline b/ch17/chapter17.playground/timeline.xctimeline new file mode 100644 index 0000000..4e2f1f2 --- /dev/null +++ b/ch17/chapter17.playground/timeline.xctimeline @@ -0,0 +1,11 @@ + + + + + + +