From 6efead432883dd889a88cdd3b7bfd81217b1cb1b Mon Sep 17 00:00:00 2001 From: Marius Date: Wed, 27 Jul 2016 00:56:00 +0300 Subject: [PATCH] updated to Swift 3 --- ch01/chapter01.xcodeproj/project.pbxproj | 17 +- .../UserInterfaceState.xcuserstate | Bin 18776 -> 22924 bytes .../xcschemes/chapter01.xcscheme | 2 +- ch01/chapter01/AppDelegate.swift | 13 - .../AppIcon.appiconset/Contents.json | 58 -- ch01/chapter01/Base.lproj/Main.storyboard | 18 +- ch01/chapter01/ViewController.swift | 15 +- ch02/chapter02.xcodeproj/project.pbxproj | 17 +- .../UserInterfaceState.xcuserstate | Bin 14020 -> 17440 bytes .../xcschemes/chapter02.xcscheme | 2 +- .../AppIcon.appiconset/Contents.json | 58 -- ch02/chapter02/MetalView.swift | 34 +- ch03/chapter03.xcodeproj/project.pbxproj | 16 +- .../UserInterfaceState.xcuserstate | Bin 17515 -> 19763 bytes .../xcschemes/chapter03.xcscheme | 2 +- .../AppIcon.appiconset/Contents.json | 58 -- ch03/chapter03/MetalView.swift | 52 +- ch03/chapter03/Shaders.metal | 3 +- ch04/chapter04.xcodeproj/project.pbxproj | 20 +- .../UserInterfaceState.xcuserstate | Bin 14141 -> 19895 bytes .../xcschemes/chapter04.xcscheme | 2 +- ch04/chapter04/AppDelegate.swift | 13 - .../AppIcon.appiconset/Contents.json | 58 -- ch04/chapter04/Base.lproj/Main.storyboard | 8 +- ch04/chapter04/MetalView.swift | 63 +- ch04/chapter04/Shaders.metal | 3 +- ch04/chapter04/ViewController.swift | 27 - ch05/chapter05.xcodeproj/project.pbxproj | 16 +- .../UserInterfaceState.xcuserstate | Bin 24557 -> 26227 bytes .../xcschemes/chapter05.xcscheme | 2 +- .../AppIcon.appiconset/Contents.json | 58 -- ch05/chapter05/MetalView.swift | 79 +- ch06/chapter06.xcodeproj/project.pbxproj | 152 ++-- .../UserInterfaceState.xcuserstate | Bin 16131 -> 17929 bytes .../xcschemes/chapter06.xcscheme | 10 +- .../xcschemes/xcschememanagement.plist | 2 +- ch06/chapter06/AppDelegate.swift | 11 +- .../AppIcon.appiconset/Contents.json | 58 -- ch06/chapter06/Base.lproj/Main.storyboard | 687 +----------------- ch06/chapter06/Info.plist | 31 +- ch06/chapter06/MetalView.swift | 39 +- ch07/chapter07.xcodeproj/project.pbxproj | 16 +- .../UserInterfaceState.xcuserstate | Bin 14862 -> 18537 bytes .../xcschemes/chapter07.xcscheme | 2 +- .../AppIcon.appiconset/Contents.json | 58 -- ch07/chapter07/MathUtils.swift | 12 +- ch07/chapter07/MetalView.swift | 65 +- ch08/chapter08.playground/Contents.swift | 13 +- .../Resources/Shaders.metal | 4 +- .../Sources/MathUtils.swift | 12 +- .../Sources/MetalView.swift | 83 ++- .../contents.xcplayground | 2 +- .../UserInterfaceState.xcuserstate | Bin 14980 -> 16465 bytes ch09/chapter09.playground/Contents.swift | 13 +- .../Sources/MathUtils.swift | 2 +- .../Sources/MetalView.swift | 116 +-- .../UserInterfaceState.xcuserstate | Bin 24161 -> 27041 bytes ch09/chapter09.playground/timeline.xctimeline | 6 - ch10/chapter10.playground/Contents.swift | 13 +- .../Sources/MetalView.swift | 61 +- .../contents.xcplayground | 0 .../UserInterfaceState.xcuserstate | Bin 16567 -> 23421 bytes ch10/chapter10.playground/timeline.xctimeline | 6 - ch11/chapter11.playground/Contents.swift | 13 +- .../Sources/MetalView.swift | 71 +- .../UserInterfaceState.xcuserstate | Bin 18466 -> 19188 bytes ch11/chapter11.playground/timeline.xctimeline | 6 - ch12/chapter12.playground/Contents.swift | 10 +- .../Sources/MetalView.swift | 34 +- .../UserInterfaceState.xcuserstate | Bin 19598 -> 22543 bytes ch13/chapter13.playground/Contents.swift | 6 +- .../Sources/MetalView.swift | 32 +- .../UserInterfaceState.xcuserstate | Bin 19608 -> 20504 bytes ch14/chapter14.playground/Contents.swift | 4 +- .../Sources/MetalView.swift | 32 +- .../UserInterfaceState.xcuserstate | Bin 21322 -> 22481 bytes ch15/chapter15.playground/Contents.swift | 13 +- .../Sources/MetalView.swift | 73 +- .../contents.xcplayground | 0 .../UserInterfaceState.xcuserstate | Bin 22934 -> 23897 bytes ch15/chapter15.playground/timeline.xctimeline | 0 81 files changed, 684 insertions(+), 1798 deletions(-) delete mode 100644 ch01/chapter01/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 ch02/chapter02/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 ch03/chapter03/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 ch04/chapter04/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 ch04/chapter04/ViewController.swift delete mode 100644 ch05/chapter05/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 ch06/chapter06/Assets.xcassets/AppIcon.appiconset/Contents.json mode change 100644 => 100755 ch06/chapter06/MetalView.swift delete mode 100644 ch07/chapter07/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 ch09/chapter09.playground/timeline.xctimeline mode change 100755 => 100644 ch10/chapter10.playground/Contents.swift mode change 100755 => 100644 ch10/chapter10.playground/contents.xcplayground delete mode 100755 ch10/chapter10.playground/timeline.xctimeline delete mode 100644 ch11/chapter11.playground/timeline.xctimeline mode change 100755 => 100644 ch15/chapter15.playground/Contents.swift mode change 100755 => 100644 ch15/chapter15.playground/contents.xcplayground mode change 100755 => 100644 ch15/chapter15.playground/timeline.xctimeline diff --git a/ch01/chapter01.xcodeproj/project.pbxproj b/ch01/chapter01.xcodeproj/project.pbxproj index 2d5df56..6cbc653 100644 --- a/ch01/chapter01.xcodeproj/project.pbxproj +++ b/ch01/chapter01.xcodeproj/project.pbxproj @@ -9,7 +9,6 @@ /* Begin PBXBuildFile section */ 29400C7D1C3AEE1300345568 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29400C7C1C3AEE1300345568 /* AppDelegate.swift */; }; 29400C7F1C3AEE1300345568 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29400C7E1C3AEE1300345568 /* ViewController.swift */; }; - 29400C811C3AEE1300345568 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 29400C801C3AEE1300345568 /* Assets.xcassets */; }; 29400C841C3AEE1300345568 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 29400C821C3AEE1300345568 /* Main.storyboard */; }; /* End PBXBuildFile section */ @@ -17,7 +16,6 @@ 29400C791C3AEE1300345568 /* chapter01.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = chapter01.app; sourceTree = BUILT_PRODUCTS_DIR; }; 29400C7C1C3AEE1300345568 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 29400C7E1C3AEE1300345568 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; - 29400C801C3AEE1300345568 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 29400C831C3AEE1300345568 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 29400C851C3AEE1300345568 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; /* End PBXFileReference section */ @@ -53,7 +51,6 @@ isa = PBXGroup; children = ( 29400C7E1C3AEE1300345568 /* ViewController.swift */, - 29400C801C3AEE1300345568 /* Assets.xcassets */, 29400C821C3AEE1300345568 /* Main.storyboard */, 29400C851C3AEE1300345568 /* Info.plist */, 29400C7C1C3AEE1300345568 /* AppDelegate.swift */, @@ -88,11 +85,12 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0800; ORGANIZATIONNAME = "Marius Horga"; TargetAttributes = { 29400C781C3AEE1300345568 = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0800; }; }; }; @@ -119,7 +117,6 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 29400C811C3AEE1300345568 /* Assets.xcassets in Resources */, 29400C841C3AEE1300345568 /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -186,7 +183,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.12; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; @@ -224,7 +221,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.12; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; }; @@ -233,24 +230,25 @@ 29400C891C3AEE1300345568 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = chapter01/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = org.mhorga.chapter01; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Debug; }; 29400C8A1C3AEE1300345568 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = chapter01/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = org.mhorga.chapter01; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 3.0; }; name = Release; }; @@ -273,6 +271,7 @@ 29400C8A1C3AEE1300345568 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; diff --git a/ch01/chapter01.xcodeproj/project.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate b/ch01/chapter01.xcodeproj/project.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate index 18e3b2b0c68b7b24567c3efdd9c9379238c67e1c..ba92cabe6645acbd44ae86a22125b3d9d32e8a48 100644 GIT binary patch literal 22924 zcmd6P2UwF=+weKh3Y!2D2z&295+H<~gaiqSq9|@LLQoV4CZOW#Io-q6y=*H(?Y7g} zz4zOxZLQs{Z--So?a-?K{p2A)EVaJh^?qM}xGqSZbDsN*dyjJ#cD1*;y4C8v2qOlu zh(kOQWUFOsW~MB+J6&y#&Y3BWg-h(s-L6?FHfQtVHh4TOrQ6XJitvS7cZM+2kPP{t zFfqqXJZdO3`%Gh-RRfXcn4{=AgM~9-5Du&;n#by=WC$ zjn<&GXdOBS5k%3s=sa`@x)g0f*P`pt_2>q4Bf1%FM?281=nix@dH_9$9z~C#7to97 zCG;|S4Sj+>MW3P1(HH0d`ZxL#eT9BPKcl1Q7xXLo4gHReVGi@yABW&j9EKxsG>*Xu zI1#7g44i}2Sc8jj39i7Ecs#DbRy+ky#dGmIJRdjVX5539;}v)%?!~L{YP<%o#h2hq z@nv{D-hemaO?WfD2H%MLa6i5k--d6;ci^4)9(*sp58sa;!jIy|@C*1A{2~4te}fO= zZ}AWKS9~1*!5{`RJmbswF+ofy6UM|d2}~lB#3VC$jGECfS|*>-F=b3SQ^A-S3scKX zWg3`i%v@$3GoM+=EMa<>)eL1WU@l=cFdLaGm}{9EnOm3v<~HVTW*74ivzvK}d762Z z`4{sV^E&e}^9l1Q^BMCw^96H&Immp={J{Lk9Al2NnB`f44PZmrNH&g*XN%bqwv;Vn z%h?LHk~OeK*2Gq^X4b;iuoKzIY(3k+HnOu=8@rHgX4_Z?yMkTG_Og^cmpzZYj9t%O z#a_)`!(PkY#@^1}!QRQ<#oo>CWba|0V4q~4VxMN8VP9hZ#lFVA$L?d_XZN!ou%ED> zvj^ED?04)>?9Uv-u^h+ooWRLAA1;Us(ztXko6~Swu7oS)%D8f_f~(@j za}C@yZaUY<&EV#73%MoSQm∨5xbG+zM_b*UPQt&gIVI&ga&18@P?!ChkgZ8+RLb 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 Mc8+%#rnd9{0i2SlLI3~& delta 10426 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 LdAO|p%DVr5uKSBK diff --git a/ch01/chapter01.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter01.xcscheme b/ch01/chapter01.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter01.xcscheme index b3bc40d..2adec09 100644 --- a/ch01/chapter01.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter01.xcscheme +++ b/ch01/chapter01.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter01.xcscheme @@ -1,6 +1,6 @@ - + + - + @@ -673,8 +673,11 @@ - - + + + + + @@ -682,6 +685,11 @@ + + + + + diff --git a/ch01/chapter01/ViewController.swift b/ch01/chapter01/ViewController.swift index 65fd44c..994db6f 100644 --- a/ch01/chapter01/ViewController.swift +++ b/ch01/chapter01/ViewController.swift @@ -6,7 +6,7 @@ // Copyright © 2016 Marius Horga. All rights reserved. // -import Cocoa // contains Metal +import Cocoa class ViewController: NSViewController { @@ -15,10 +15,15 @@ class ViewController: NSViewController { override func viewDidLoad() { super.viewDidLoad() - if let device = MTLCreateSystemDefaultDevice() { - label.stringValue = "Your GPU name is:\n\(device.name!)" - } else { - label.stringValue = "Your GPU does not support Metal!" + /* The MTLCopyAllDevices() function is only available in macOS. + For iOS/tvOS devices use MTLCreateSystemDefaultDevice() instead. */ + let devices = MTLCopyAllDevices() + guard let _ = devices.first else { + fatalError("Your GPU does not support Metal!") + } + label.stringValue = "Your system has the following GPU(s):\n" + for device in devices { + label.stringValue += "\(device.name!)\n" } } } diff --git a/ch02/chapter02.xcodeproj/project.pbxproj b/ch02/chapter02.xcodeproj/project.pbxproj index c91e5c5..c8b196f 100644 --- a/ch02/chapter02.xcodeproj/project.pbxproj +++ b/ch02/chapter02.xcodeproj/project.pbxproj @@ -8,7 +8,6 @@ /* Begin PBXBuildFile section */ 29E74AD11C4159D60023A39A /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29E74AD01C4159D60023A39A /* AppDelegate.swift */; }; - 29E74AD51C4159D60023A39A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 29E74AD41C4159D60023A39A /* Assets.xcassets */; }; 29E74AD81C4159D60023A39A /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 29E74AD61C4159D60023A39A /* Main.storyboard */; }; 29E74AE01C415A020023A39A /* MetalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29E74ADF1C415A020023A39A /* MetalView.swift */; }; /* End PBXBuildFile section */ @@ -16,7 +15,6 @@ /* Begin PBXFileReference section */ 29E74ACD1C4159D60023A39A /* chapter02.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = chapter02.app; sourceTree = BUILT_PRODUCTS_DIR; }; 29E74AD01C4159D60023A39A /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 29E74AD41C4159D60023A39A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 29E74AD71C4159D60023A39A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 29E74AD91C4159D60023A39A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 29E74ADF1C415A020023A39A /* MetalView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MetalView.swift; sourceTree = ""; }; @@ -54,7 +52,6 @@ children = ( 29E74ADF1C415A020023A39A /* MetalView.swift */, 29E74AD61C4159D60023A39A /* Main.storyboard */, - 29E74AD41C4159D60023A39A /* Assets.xcassets */, 29E74AD91C4159D60023A39A /* Info.plist */, 29E74AD01C4159D60023A39A /* AppDelegate.swift */, ); @@ -88,11 +85,12 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0800; ORGANIZATIONNAME = "Marius Horga"; TargetAttributes = { 29E74ACC1C4159D60023A39A = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0800; }; }; }; @@ -119,7 +117,6 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 29E74AD51C4159D60023A39A /* Assets.xcassets in Resources */, 29E74AD81C4159D60023A39A /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -186,7 +183,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.12; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; @@ -224,7 +221,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.12; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; }; @@ -233,24 +230,25 @@ 29E74ADD1C4159D60023A39A /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = chapter02/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = org.mhorga.chapter02; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Debug; }; 29E74ADE1C4159D60023A39A /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = chapter02/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = org.mhorga.chapter02; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 3.0; }; name = Release; }; @@ -273,6 +271,7 @@ 29E74ADE1C4159D60023A39A /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; diff --git a/ch02/chapter02.xcodeproj/project.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate b/ch02/chapter02.xcodeproj/project.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate index e571953582ee938d05f774f15767fd88f8cd55fb..6326d60b7dc156aad9ce7b2ec8296ae12fbb11c6 100644 GIT binary patch delta 10636 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 PxaRjc&0pC6nH&BO?8;Ii delta 7865 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 delta 9931 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 diff --git a/ch03/chapter03.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter03.xcscheme b/ch03/chapter03.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter03.xcscheme index 6ec6aa7..2c78ce6 100644 --- a/ch03/chapter03.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter03.xcscheme +++ b/ch03/chapter03.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter03.xcscheme @@ -1,6 +1,6 @@ $901|&W><| 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 delta 8263 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 - + + - + @@ -668,7 +668,7 @@ - + diff --git a/ch04/chapter04/MetalView.swift b/ch04/chapter04/MetalView.swift index 847b46e..744f295 100644 --- a/ch04/chapter04/MetalView.swift +++ b/ch04/chapter04/MetalView.swift @@ -10,59 +10,56 @@ import MetalKit class MetalView: MTKView { - var vertex_buffer: MTLBuffer! - var rps: MTLRenderPipelineState! = nil - - override func drawRect(dirtyRect: NSRect) { - super.drawRect(dirtyRect) - render() - } - - func render() { - device = MTLCreateSystemDefaultDevice() - createBuffer() - registerShaders() - sendToGPU() - } + var commandQueue: MTLCommandQueue? + var rps: MTLRenderPipelineState? + var vertexBuffer: MTLBuffer? struct Vertex { var position: vector_float4 var color: vector_float4 - }; + } + + required init(coder: NSCoder) { + super.init(coder: coder) + createBuffer() + registerShaders() + } func createBuffer() { - let vertex_data = [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])] - vertex_buffer = device!.newBufferWithBytes(vertex_data, length: sizeof(Vertex) * 3, options:[]) + 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:[]) } func registerShaders() { let library = device!.newDefaultLibrary()! - let vertex_func = library.newFunctionWithName("vertex_func") - let frag_func = library.newFunctionWithName("fragment_func") + let vertex_func = library.newFunction(withName: "vertex_func") + let frag_func = library.newFunction(withName: "fragment_func") let rpld = MTLRenderPipelineDescriptor() rpld.vertexFunction = vertex_func rpld.fragmentFunction = frag_func - rpld.colorAttachments[0].pixelFormat = .BGRA8Unorm + rpld.colorAttachments[0].pixelFormat = .bgra8Unorm do { - try rps = device!.newRenderPipelineStateWithDescriptor(rpld) + try rps = device!.newRenderPipelineState(with: rpld) } catch let error { self.print("\(error)") } } - func sendToGPU() { - if let rpd = currentRenderPassDescriptor, drawable = currentDrawable { + 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 command_buffer = device!.newCommandQueue().commandBuffer() - let command_encoder = command_buffer.renderCommandEncoderWithDescriptor(rpd) - command_encoder.setRenderPipelineState(rps) - command_encoder.setVertexBuffer(vertex_buffer, offset: 0, atIndex: 0) - command_encoder.drawPrimitives(.Triangle, vertexStart: 0, vertexCount: 3, instanceCount: 1) - command_encoder.endEncoding() - command_buffer.presentDrawable(drawable) - command_buffer.commit() + let commandBuffer = commandQueue!.commandBuffer() + let commandEncoder = commandBuffer.renderCommandEncoder(with: rpd) + commandEncoder.setRenderPipelineState(rps!) + commandEncoder.setVertexBuffer(vertexBuffer, offset: 0, at: 0) + commandEncoder.drawPrimitives(.triangle, vertexStart: 0, vertexCount: 3, instanceCount: 1) + commandEncoder.endEncoding() + commandBuffer.present(drawable) + commandBuffer.commit() } } } diff --git a/ch04/chapter04/Shaders.metal b/ch04/chapter04/Shaders.metal index 87188e5..958e762 100644 --- a/ch04/chapter04/Shaders.metal +++ b/ch04/chapter04/Shaders.metal @@ -14,7 +14,8 @@ struct Vertex { float4 color; }; -vertex Vertex vertex_func(constant Vertex *vertices [[buffer(0)]], uint vid [[vertex_id]]) { +vertex Vertex vertex_func(constant Vertex *vertices [[buffer(0)]], + uint vid [[vertex_id]]) { return vertices[vid]; } diff --git a/ch04/chapter04/ViewController.swift b/ch04/chapter04/ViewController.swift deleted file mode 100644 index d8740a2..0000000 --- a/ch04/chapter04/ViewController.swift +++ /dev/null @@ -1,27 +0,0 @@ -// -// ViewController.swift -// chapter04 -// -// Created by Marius on 1/26/16. -// Copyright © 2016 Marius Horga. All rights reserved. -// - -import Cocoa - -class ViewController: NSViewController { - - override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - } - - override var representedObject: AnyObject? { - didSet { - // Update the view, if already loaded. - } - } - - -} - diff --git a/ch05/chapter05.xcodeproj/project.pbxproj b/ch05/chapter05.xcodeproj/project.pbxproj index 4ffaaea..c2db75a 100644 --- a/ch05/chapter05.xcodeproj/project.pbxproj +++ b/ch05/chapter05.xcodeproj/project.pbxproj @@ -8,7 +8,6 @@ /* Begin PBXBuildFile section */ 298037231C62437900FBBC6A /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 298037221C62437900FBBC6A /* AppDelegate.swift */; }; - 298037271C62437900FBBC6A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 298037261C62437900FBBC6A /* Assets.xcassets */; }; 2980372A1C62437900FBBC6A /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 298037281C62437900FBBC6A /* Main.storyboard */; }; 298037321C6243CB00FBBC6A /* MetalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 298037311C6243CB00FBBC6A /* MetalView.swift */; }; 298037341C62440400FBBC6A /* Shaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = 298037331C62440400FBBC6A /* Shaders.metal */; }; @@ -17,7 +16,6 @@ /* Begin PBXFileReference section */ 2980371F1C62437900FBBC6A /* chapter05.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = chapter05.app; sourceTree = BUILT_PRODUCTS_DIR; }; 298037221C62437900FBBC6A /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 298037261C62437900FBBC6A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 298037291C62437900FBBC6A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 2980372B1C62437900FBBC6A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 298037311C6243CB00FBBC6A /* MetalView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MetalView.swift; sourceTree = ""; }; @@ -56,7 +54,6 @@ children = ( 298037311C6243CB00FBBC6A /* MetalView.swift */, 298037331C62440400FBBC6A /* Shaders.metal */, - 298037261C62437900FBBC6A /* Assets.xcassets */, 298037281C62437900FBBC6A /* Main.storyboard */, 2980372B1C62437900FBBC6A /* Info.plist */, 298037221C62437900FBBC6A /* AppDelegate.swift */, @@ -91,11 +88,12 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0800; ORGANIZATIONNAME = "Marius Horga"; TargetAttributes = { 2980371E1C62437900FBBC6A = { CreatedOnToolsVersion = 7.2.1; + LastSwiftMigration = 0800; }; }; }; @@ -122,7 +120,6 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 298037271C62437900FBBC6A /* Assets.xcassets in Resources */, 2980372A1C62437900FBBC6A /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -190,7 +187,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.12; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; @@ -228,7 +225,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.12; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; }; @@ -237,7 +234,6 @@ 2980372F1C62437900FBBC6A /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = chapter05/Info.plist; @@ -245,19 +241,21 @@ PRODUCT_BUNDLE_IDENTIFIER = org.mhorga.chapter05; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; }; name = Debug; }; 298037301C62437900FBBC6A /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = chapter05/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = org.mhorga.chapter05; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/ch05/chapter05.xcodeproj/project.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate b/ch05/chapter05.xcodeproj/project.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate index d5df0befe731d91dc6b101348ba43a3736e6cccb..963e81b21c9ef556f23b3d27f76a0dee92f3553d 100644 GIT binary patch delta 14695 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 delta 13299 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 Mear8cKTGTW4>C?aZ~y=R diff --git a/ch05/chapter05.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter05.xcscheme b/ch05/chapter05.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter05.xcscheme index 1ad0d75..2f4f9c3 100644 --- a/ch05/chapter05.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter05.xcscheme +++ b/ch05/chapter05.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter05.xcscheme @@ -1,6 +1,6 @@ Matrix { + func translationMatrix(_ matrix: Matrix, _ position: float3) -> Matrix { + var matrix = matrix matrix.m[12] = position.x matrix.m[13] = position.y matrix.m[14] = position.z return matrix } - - func scalingMatrix(var matrix: Matrix, _ scale: Float) -> Matrix { + func scalingMatrix(_ matrix: Matrix, _ scale: Float) -> Matrix { + var matrix = matrix matrix.m[0] = scale matrix.m[5] = scale matrix.m[10] = scale matrix.m[15] = 1.0 return matrix } - - func rotationMatrix(var matrix: Matrix, _ rot: float3) -> Matrix { + func rotationMatrix(_ matrix: Matrix, _ rot: float3) -> Matrix { + var matrix = matrix matrix.m[0] = cos(rot.y) * cos(rot.z) matrix.m[4] = cos(rot.z) * sin(rot.x) * sin(rot.y) - cos(rot.x) * sin(rot.z) matrix.m[8] = cos(rot.x) * cos(rot.z) * sin(rot.y) + sin(rot.x) * sin(rot.z) @@ -70,8 +64,8 @@ class MetalView: MTKView { matrix.m[15] = 1.0 return matrix } - - func modelMatrix(var matrix: Matrix) -> Matrix { + func modelMatrix(_ matrix: Matrix) -> Matrix { + var matrix = matrix matrix = rotationMatrix(matrix, float3(0.0, 0.0, 0.1)) matrix = scalingMatrix(matrix, 0.25) matrix = translationMatrix(matrix, float3(0.0, 0.5, 0.0)) @@ -80,44 +74,45 @@ class MetalView: MTKView { } func createBuffers() { - let vertex_data = [ - 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]) + device = MTLCreateSystemDefaultDevice()! + commandQueue = device!.newCommandQueue() + let vertex_data = [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]) ] - vertex_buffer = device!.newBufferWithBytes(vertex_data, length: sizeof(Vertex) * 3, options:[]) - uniform_buffer = device!.newBufferWithLength(sizeof(Float) * 16, options: []) - let bufferPointer = uniform_buffer.contents() - memcpy(bufferPointer, Matrix().modelMatrix(Matrix()).m, sizeof(Float) * 16) + vertexBuffer = device!.newBuffer(withBytes: vertex_data, length: sizeof(Vertex.self) * 3, options:[]) + uniformBuffer = device!.newBuffer(withLength: sizeof(Float.self) * 16, options: []) + let bufferPointer = uniformBuffer.contents() + memcpy(bufferPointer, Matrix().modelMatrix(Matrix()).m, sizeof(Float.self) * 16) } func registerShaders() { let library = device!.newDefaultLibrary()! - let vertex_func = library.newFunctionWithName("vertex_func") - let frag_func = library.newFunctionWithName("fragment_func") + let vertex_func = library.newFunction(withName: "vertex_func") + let frag_func = library.newFunction(withName: "fragment_func") let rpld = MTLRenderPipelineDescriptor() rpld.vertexFunction = vertex_func rpld.fragmentFunction = frag_func - rpld.colorAttachments[0].pixelFormat = .BGRA8Unorm + rpld.colorAttachments[0].pixelFormat = .bgra8Unorm do { - try rps = device!.newRenderPipelineStateWithDescriptor(rpld) + try rps = device!.newRenderPipelineState(with: rpld) } catch let error { self.print("\(error)") } } - func sendToGPU() { + override func draw(_ dirtyRect: NSRect) { if let rpd = currentRenderPassDescriptor, drawable = currentDrawable { rpd.colorAttachments[0].clearColor = MTLClearColorMake(0.5, 0.5, 0.5, 1.0) - let command_buffer = device!.newCommandQueue().commandBuffer() - let command_encoder = command_buffer.renderCommandEncoderWithDescriptor(rpd) - command_encoder.setRenderPipelineState(rps) - command_encoder.setVertexBuffer(vertex_buffer, offset: 0, atIndex: 0) - command_encoder.setVertexBuffer(uniform_buffer, offset: 0, atIndex: 1) - command_encoder.drawPrimitives(.Triangle, vertexStart: 0, vertexCount: 3, instanceCount: 1) - command_encoder.endEncoding() - command_buffer.presentDrawable(drawable) - command_buffer.commit() + let commandBuffer = device!.newCommandQueue().commandBuffer() + let commandEncoder = commandBuffer.renderCommandEncoder(with: rpd) + commandEncoder.setRenderPipelineState(rps!) + commandEncoder.setVertexBuffer(vertexBuffer, offset: 0, at: 0) + commandEncoder.setVertexBuffer(uniformBuffer, offset: 0, at: 1) + commandEncoder.drawPrimitives(.triangle, vertexStart: 0, vertexCount: 3, instanceCount: 1) + commandEncoder.endEncoding() + commandBuffer.present(drawable) + commandBuffer.commit() } } } diff --git a/ch06/chapter06.xcodeproj/project.pbxproj b/ch06/chapter06.xcodeproj/project.pbxproj index d5b5d90..04ca30b 100644 --- a/ch06/chapter06.xcodeproj/project.pbxproj +++ b/ch06/chapter06.xcodeproj/project.pbxproj @@ -7,23 +7,21 @@ objects = { /* Begin PBXBuildFile section */ - 292765421C6BDE3400094CA9 /* MetalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 292765411C6BDE3400094CA9 /* MetalView.swift */; }; - 29DB1AF61C6BDDD500BCC31B /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29DB1AF51C6BDDD500BCC31B /* AppDelegate.swift */; }; - 29DB1AFA1C6BDDD500BCC31B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 29DB1AF91C6BDDD500BCC31B /* Assets.xcassets */; }; - 29DB1AFD1C6BDDD500BCC31B /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 29DB1AFB1C6BDDD500BCC31B /* Main.storyboard */; }; + 298451301D47EF08008D81B9 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2984512F1D47EF08008D81B9 /* AppDelegate.swift */; }; + 298451351D47EF08008D81B9 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 298451331D47EF08008D81B9 /* Main.storyboard */; }; + 298451421D47F0BF008D81B9 /* MetalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 298451411D47F0BF008D81B9 /* MetalView.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - 292765411C6BDE3400094CA9 /* MetalView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MetalView.swift; sourceTree = ""; }; - 29DB1AF21C6BDDD500BCC31B /* chapter06.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = chapter06.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 29DB1AF51C6BDDD500BCC31B /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 29DB1AF91C6BDDD500BCC31B /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 29DB1AFC1C6BDDD500BCC31B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 29DB1AFE1C6BDDD500BCC31B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 2984512C1D47EF08008D81B9 /* chapter06.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = chapter06.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 2984512F1D47EF08008D81B9 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 298451341D47EF08008D81B9 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 2984513B1D47EF08008D81B9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 298451411D47F0BF008D81B9 /* MetalView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MetalView.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 29DB1AEF1C6BDDD500BCC31B /* Frameworks */ = { + 298451291D47EF08008D81B9 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( @@ -33,30 +31,29 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 29DB1AE91C6BDDD400BCC31B = { + 298451231D47EF07008D81B9 = { isa = PBXGroup; children = ( - 29DB1AF41C6BDDD500BCC31B /* chapter06 */, - 29DB1AF31C6BDDD500BCC31B /* Products */, + 2984512E1D47EF08008D81B9 /* chapter06 */, + 2984512D1D47EF08008D81B9 /* Products */, ); sourceTree = ""; }; - 29DB1AF31C6BDDD500BCC31B /* Products */ = { + 2984512D1D47EF08008D81B9 /* Products */ = { isa = PBXGroup; children = ( - 29DB1AF21C6BDDD500BCC31B /* chapter06.app */, + 2984512C1D47EF08008D81B9 /* chapter06.app */, ); name = Products; sourceTree = ""; }; - 29DB1AF41C6BDDD500BCC31B /* chapter06 */ = { + 2984512E1D47EF08008D81B9 /* chapter06 */ = { isa = PBXGroup; children = ( - 292765411C6BDE3400094CA9 /* MetalView.swift */, - 29DB1AF91C6BDDD500BCC31B /* Assets.xcassets */, - 29DB1AFB1C6BDDD500BCC31B /* Main.storyboard */, - 29DB1AFE1C6BDDD500BCC31B /* Info.plist */, - 29DB1AF51C6BDDD500BCC31B /* AppDelegate.swift */, + 298451411D47F0BF008D81B9 /* MetalView.swift */, + 298451331D47EF08008D81B9 /* Main.storyboard */, + 2984513B1D47EF08008D81B9 /* Info.plist */, + 2984512F1D47EF08008D81B9 /* AppDelegate.swift */, ); path = chapter06; sourceTree = ""; @@ -64,13 +61,13 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - 29DB1AF11C6BDDD500BCC31B /* chapter06 */ = { + 2984512B1D47EF08008D81B9 /* chapter06 */ = { isa = PBXNativeTarget; - buildConfigurationList = 29DB1B011C6BDDD500BCC31B /* Build configuration list for PBXNativeTarget "chapter06" */; + buildConfigurationList = 2984513E1D47EF08008D81B9 /* Build configuration list for PBXNativeTarget "chapter06" */; buildPhases = ( - 29DB1AEE1C6BDDD500BCC31B /* Sources */, - 29DB1AEF1C6BDDD500BCC31B /* Frameworks */, - 29DB1AF01C6BDDD500BCC31B /* Resources */, + 298451281D47EF08008D81B9 /* Sources */, + 298451291D47EF08008D81B9 /* Frameworks */, + 2984512A1D47EF08008D81B9 /* Resources */, ); buildRules = ( ); @@ -78,25 +75,28 @@ ); name = chapter06; productName = chapter06; - productReference = 29DB1AF21C6BDDD500BCC31B /* chapter06.app */; + productReference = 2984512C1D47EF08008D81B9 /* chapter06.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ - 29DB1AEA1C6BDDD400BCC31B /* Project object */ = { + 298451241D47EF07008D81B9 /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; - ORGANIZATIONNAME = "Marius Horga"; + LastSwiftUpdateCheck = 0800; + LastUpgradeCheck = 0800; + ORGANIZATIONNAME = Marius; TargetAttributes = { - 29DB1AF11C6BDDD500BCC31B = { - CreatedOnToolsVersion = 7.2.1; + 2984512B1D47EF08008D81B9 = { + CreatedOnToolsVersion = 8.0; + DevelopmentTeam = C2X9Q6VFVJ; + DevelopmentTeamName = "Marius Horga"; + ProvisioningStyle = Automatic; }; }; }; - buildConfigurationList = 29DB1AED1C6BDDD400BCC31B /* Build configuration list for PBXProject "chapter06" */; + buildConfigurationList = 298451271D47EF07008D81B9 /* Build configuration list for PBXProject "chapter06" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; @@ -104,45 +104,44 @@ en, Base, ); - mainGroup = 29DB1AE91C6BDDD400BCC31B; - productRefGroup = 29DB1AF31C6BDDD500BCC31B /* Products */; + mainGroup = 298451231D47EF07008D81B9; + productRefGroup = 2984512D1D47EF08008D81B9 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( - 29DB1AF11C6BDDD500BCC31B /* chapter06 */, + 2984512B1D47EF08008D81B9 /* chapter06 */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 29DB1AF01C6BDDD500BCC31B /* Resources */ = { + 2984512A1D47EF08008D81B9 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 29DB1AFA1C6BDDD500BCC31B /* Assets.xcassets in Resources */, - 29DB1AFD1C6BDDD500BCC31B /* Main.storyboard in Resources */, + 298451351D47EF08008D81B9 /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - 29DB1AEE1C6BDDD500BCC31B /* Sources */ = { + 298451281D47EF08008D81B9 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 292765421C6BDE3400094CA9 /* MetalView.swift in Sources */, - 29DB1AF61C6BDDD500BCC31B /* AppDelegate.swift in Sources */, + 298451421D47F0BF008D81B9 /* MetalView.swift in Sources */, + 298451301D47EF08008D81B9 /* AppDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ - 29DB1AFB1C6BDDD500BCC31B /* Main.storyboard */ = { + 298451331D47EF08008D81B9 /* Main.storyboard */ = { isa = PBXVariantGroup; children = ( - 29DB1AFC1C6BDDD500BCC31B /* Base */, + 298451341D47EF08008D81B9 /* Base */, ); name = Main.storyboard; sourceTree = ""; @@ -150,10 +149,11 @@ /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ - 29DB1AFF1C6BDDD500BCC31B /* Debug */ = { + 2984513C1D47EF08008D81B9 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; @@ -161,13 +161,14 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -186,18 +187,21 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; - 29DB1B001C6BDDD500BCC31B /* Release */ = { + 2984513D1D47EF08008D81B9 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; @@ -205,13 +209,14 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "-"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; @@ -224,58 +229,63 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = macosx; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; }; name = Release; }; - 29DB1B021C6BDDD500BCC31B /* Debug */ = { + 2984513F1D47EF08008D81B9 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - COMBINE_HIDPI_IMAGES = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; INFOPLIST_FILE = chapter06/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = org.mhorga.chapter06; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = org.metalkit.chapter06; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 3.0; }; name = Debug; }; - 29DB1B031C6BDDD500BCC31B /* Release */ = { + 298451401D47EF08008D81B9 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - COMBINE_HIDPI_IMAGES = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; INFOPLIST_FILE = chapter06/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = org.mhorga.chapter06; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = org.metalkit.chapter06; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 29DB1AED1C6BDDD400BCC31B /* Build configuration list for PBXProject "chapter06" */ = { + 298451271D47EF07008D81B9 /* Build configuration list for PBXProject "chapter06" */ = { isa = XCConfigurationList; buildConfigurations = ( - 29DB1AFF1C6BDDD500BCC31B /* Debug */, - 29DB1B001C6BDDD500BCC31B /* Release */, + 2984513C1D47EF08008D81B9 /* Debug */, + 2984513D1D47EF08008D81B9 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 29DB1B011C6BDDD500BCC31B /* Build configuration list for PBXNativeTarget "chapter06" */ = { + 2984513E1D47EF08008D81B9 /* Build configuration list for PBXNativeTarget "chapter06" */ = { isa = XCConfigurationList; buildConfigurations = ( - 29DB1B021C6BDDD500BCC31B /* Debug */, - 29DB1B031C6BDDD500BCC31B /* Release */, + 2984513F1D47EF08008D81B9 /* Debug */, + 298451401D47EF08008D81B9 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; - rootObject = 29DB1AEA1C6BDDD400BCC31B /* Project object */; + rootObject = 298451241D47EF07008D81B9 /* Project object */; } diff --git a/ch06/chapter06.xcodeproj/project.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate b/ch06/chapter06.xcodeproj/project.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate index b174838decb42b20cabeb9e84eddc8efbcdd903a..8f4dc11fe8b672fc60db4534ca171ed98e993112 100644 GIT binary patch literal 17929 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 a%&W_5&s&stzF7PaBL0;W2G&G*p8o+d8v-8y diff --git a/ch06/chapter06.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter06.xcscheme b/ch06/chapter06.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter06.xcscheme index d92b1b7..af7d21a 100644 --- a/ch06/chapter06.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter06.xcscheme +++ b/ch06/chapter06.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/chapter06.xcscheme @@ -1,6 +1,6 @@ @@ -32,7 +32,7 @@ @@ -55,7 +55,7 @@ runnableDebuggingMode = "0"> @@ -74,7 +74,7 @@ runnableDebuggingMode = "0"> diff --git a/ch06/chapter06.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/xcschememanagement.plist b/ch06/chapter06.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/xcschememanagement.plist index 8e90fc7..9b1a329 100644 --- a/ch06/chapter06.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/ch06/chapter06.xcodeproj/xcuserdata/marius.xcuserdatad/xcschemes/xcschememanagement.plist @@ -12,7 +12,7 @@ SuppressBuildableAutocreation - 29DB1AF11C6BDDD500BCC31B + 2984512B1D47EF08008D81B9 primary diff --git a/ch06/chapter06/AppDelegate.swift b/ch06/chapter06/AppDelegate.swift index 247cfb6..b492ba3 100644 --- a/ch06/chapter06/AppDelegate.swift +++ b/ch06/chapter06/AppDelegate.swift @@ -2,13 +2,14 @@ // AppDelegate.swift // chapter06 // -// Created by Marius on 2/10/16. -// Copyright © 2016 Marius Horga. All rights reserved. +// Created by Marius on 7/26/16. +// Copyright © 2016 Marius. All rights reserved. // -import Cocoa +import UIKit -@NSApplicationMain -class AppDelegate: NSObject, NSApplicationDelegate { +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + var window: UIWindow? } diff --git a/ch06/chapter06/Assets.xcassets/AppIcon.appiconset/Contents.json b/ch06/chapter06/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 2db2b1c..0000000 --- a/ch06/chapter06/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "images" : [ - { - "idiom" : "mac", - "size" : "16x16", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "16x16", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "32x32", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "32x32", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "128x128", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "128x128", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "256x256", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "256x256", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "512x512", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "512x512", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/ch06/chapter06/Base.lproj/Main.storyboard b/ch06/chapter06/Base.lproj/Main.storyboard index 46163bb..5327e07 100644 --- a/ch06/chapter06/Base.lproj/Main.storyboard +++ b/ch06/chapter06/Base.lproj/Main.storyboard @@ -1,682 +1,27 @@ - - + + - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - + + + + + + + + + - + - diff --git a/ch06/chapter06/Info.plist b/ch06/chapter06/Info.plist index 69d1345..e4ece02 100644 --- a/ch06/chapter06/Info.plist +++ b/ch06/chapter06/Info.plist @@ -6,8 +6,6 @@ en CFBundleExecutable $(EXECUTABLE_NAME) - CFBundleIconFile - CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion @@ -18,17 +16,28 @@ APPL CFBundleShortVersionString 1.0 - CFBundleSignature - ???? CFBundleVersion 1 - LSMinimumSystemVersion - $(MACOSX_DEPLOYMENT_TARGET) - NSHumanReadableCopyright - Copyright © 2016 Marius Horga. All rights reserved. - NSMainStoryboardFile + LSRequiresIPhoneOS + + UILaunchStoryboardName Main - NSPrincipalClass - NSApplication + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + diff --git a/ch06/chapter06/MetalView.swift b/ch06/chapter06/MetalView.swift old mode 100644 new mode 100755 index 33682be..58fccb5 --- a/ch06/chapter06/MetalView.swift +++ b/ch06/chapter06/MetalView.swift @@ -6,39 +6,36 @@ // Copyright © 2016 Marius Horga. All rights reserved. // -import Cocoa +import UIKit -class MetalView: NSView { +class MetalView: UIView { - override func drawRect(dirtyRect: NSRect) { - super.drawRect(dirtyRect) - render() + var commandQueue: MTLCommandQueue! + + var metalLayer: CAMetalLayer { + return self.layer as! CAMetalLayer } override class func layerClass() -> AnyClass { return CAMetalLayer.self } - var metalLayer: CAMetalLayer { - return layer as! CAMetalLayer + override func didMoveToWindow() { + super.didMoveToWindow() + let device = MTLCreateSystemDefaultDevice()! + commandQueue = device.newCommandQueue() + redraw() } - func render() { - let device = MTLCreateSystemDefaultDevice()! - metalLayer.device = device - metalLayer.pixelFormat = .BGRA8Unorm - let drawable = metalLayer.nextDrawable() - let texture = drawable!.texture - let rpd = MTLRenderPassDescriptor() - rpd.colorAttachments[0].texture = texture - rpd.colorAttachments[0].loadAction = .Clear - rpd.colorAttachments[0].storeAction = .Store - rpd.colorAttachments[0].clearColor = MTLClearColor(red: 1, green: 0, blue: 0, alpha: 1) - let commandQueue = device.newCommandQueue() + private func redraw() { + let drawable = metalLayer.nextDrawable()! + let descriptor = MTLRenderPassDescriptor() + descriptor.colorAttachments[0].clearColor = MTLClearColorMake(0, 1, 1, 1) + descriptor.colorAttachments[0].texture = drawable.texture let commandBuffer = commandQueue.commandBuffer() - let commandEncoder = commandBuffer.renderCommandEncoderWithDescriptor(rpd) + let commandEncoder = commandBuffer.renderCommandEncoder(with: descriptor) commandEncoder.endEncoding() - commandBuffer.presentDrawable(drawable!) + commandBuffer.present(drawable) commandBuffer.commit() } } diff --git a/ch07/chapter07.xcodeproj/project.pbxproj b/ch07/chapter07.xcodeproj/project.pbxproj index bc672e5..2bb7acb 100644 --- a/ch07/chapter07.xcodeproj/project.pbxproj +++ b/ch07/chapter07.xcodeproj/project.pbxproj @@ -9,7 +9,6 @@ /* Begin PBXBuildFile section */ 29B186261C84FF5800E9C0AA /* MathUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29B186251C84FF5800E9C0AA /* MathUtils.swift */; }; 29D8782A1C84D2B0007B5F17 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29D878291C84D2B0007B5F17 /* AppDelegate.swift */; }; - 29D8782E1C84D2B0007B5F17 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 29D8782D1C84D2B0007B5F17 /* Assets.xcassets */; }; 29D878311C84D2B0007B5F17 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 29D8782F1C84D2B0007B5F17 /* Main.storyboard */; }; 29D878391C84D309007B5F17 /* MetalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29D878381C84D309007B5F17 /* MetalView.swift */; }; 29D8783B1C84D335007B5F17 /* Shaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = 29D8783A1C84D335007B5F17 /* Shaders.metal */; }; @@ -19,7 +18,6 @@ 29B186251C84FF5800E9C0AA /* MathUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MathUtils.swift; sourceTree = ""; }; 29D878261C84D2B0007B5F17 /* chapter07.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = chapter07.app; sourceTree = BUILT_PRODUCTS_DIR; }; 29D878291C84D2B0007B5F17 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 29D8782D1C84D2B0007B5F17 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 29D878301C84D2B0007B5F17 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 29D878321C84D2B0007B5F17 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 29D878381C84D309007B5F17 /* MetalView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MetalView.swift; sourceTree = ""; }; @@ -59,7 +57,6 @@ 29D878381C84D309007B5F17 /* MetalView.swift */, 29B186251C84FF5800E9C0AA /* MathUtils.swift */, 29D8783A1C84D335007B5F17 /* Shaders.metal */, - 29D8782D1C84D2B0007B5F17 /* Assets.xcassets */, 29D8782F1C84D2B0007B5F17 /* Main.storyboard */, 29D878321C84D2B0007B5F17 /* Info.plist */, 29D878291C84D2B0007B5F17 /* AppDelegate.swift */, @@ -94,11 +91,12 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0800; ORGANIZATIONNAME = "Marius Horga"; TargetAttributes = { 29D878251C84D2B0007B5F17 = { CreatedOnToolsVersion = 7.2.1; + LastSwiftMigration = 0800; }; }; }; @@ -125,7 +123,6 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 29D8782E1C84D2B0007B5F17 /* Assets.xcassets in Resources */, 29D878311C84D2B0007B5F17 /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -194,7 +191,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.12; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; @@ -232,7 +229,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.12; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; }; @@ -241,24 +238,25 @@ 29D878361C84D2B0007B5F17 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = chapter07/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = org.mhorga.chapter07; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Debug; }; 29D878371C84D2B0007B5F17 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = chapter07/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = org.mhorga.chapter07; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/ch07/chapter07.xcodeproj/project.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate b/ch07/chapter07.xcodeproj/project.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate index 4118b493aa3470c7a114e07688642fe7cfe766f3..43480b97236a21fb94fc1511db74b7fd7ed640c0 100644 GIT binary patch delta 10852 zcmai32V9d^w7=uKBxDgFAp;T;k^nL?2vI=lp0$pOdtrpAC;|d*G5539x<^y1)@o%q ztJP{Xn5@xSMsd%roQcjm!)N{)O* zzV;<2#_BhO!b3m+gdiL!fD*)kc+dbOfJBf4l7V%;Tjk9H-9UHH1M~y^!5}aU30(OJXz#gy{90JF|S@0G3 z8e9Tbz;$o~ynp~gh#-a>BrpgHpb!Q_5fnoi41-D-0W~nn3!`BijE4=N4Z7efunBAm z+roCRJ$xN@g?(UO*bnxHC9o8Zf}`OWI2MkB&x}y z`f~%gVP0-Hm(Pvh3b;b9h#Se3ag#VNN4Z(tY;F$s9=C*hpIgnX;ns2=a@)A=+z##_ zcZfU8o#W1P7q~CEtK2p2I(LJ6$o<0o%Do_fK!S*n1QQX_lW1ZfMiN6z#7rzCmc)^G z(tsq8MB*SW(vUPE?xv&}X--;@*GNawiF77CiJJ@}IV6{O$Y3&rj3mXRgp`s=#7ijQ z$xJef%p>oRDzbvCB&*1mYgFOec>!Xr>M!- z4Ud#9me81zn-o_yILtqCEkOG__6}Uh{&26YwmG{qe`>o^7gG-XGIPz9Mj1?I&X-ZP4#6X-Q0s-a}V<5 zXUmhTb>v9{Rd`3wh{ED=ZHwJSLtA+UjT$nWA@F!mqojA!dusL9lP?G}?eB(8NkG1Iz@oXcBEnTQTQM4LA8Zheu@VdgT=6daTUP9r8-8bpf-s zFDV)2sgw6MSPWuU0v~t>ECBCAm%ZAaVFS7`_O8tq6s(as+-?>}OHkHPQY5AXy$WzQDyoW-CE z`+J>c(QdRm?ZKX#(VqU@tM+fL;^M;MHhKBXzj*~iS{L}ymph=nw^i#Nc_n%5OIL>F zY5XaW98}!rFtl?LIadsV5P?|S_F>9DK zrl6;w^q(eV%fr}Qos71{g`VgfX-??Ni~8 zQ*~5WOqA6ocJ>zJk9*DI9`4C)kzbfIoM|52t7~A2&9p2mDD~T1TsWdrSR;9nInrgyE70dOdYT?4b>KA9j$`&<^s zyuo>%;_mI)<{3+yGG)gFK)4F7_C*I9FkAzC`e4JbTFz~LPL}u>Va*WSP(3u!KlFFD z4Act>KdJCnk#le>Q+ONP4tGGlZ*F1Es1a=G?pv*mN)mEHt2*S z{6*H5Gt@UfCMr0f(Qf#eZ>~OqRKPu;#Q#(?z7Kxx^N5l-xStI#5G7^4fuHDRyq8dPGcxKB(^n!-@@AjHQJSm>zqiyN?Gp-DGeQs{1vVq98nB11>i_m(((WltG$il85B_ilzE6x6U9WGh|<*-Nkr0H{}Pv3pE>c18oAAS6M8ngcOv0eRF4Zuh+sqVle#-s*6p zwx}J;rwoA=s4XZ7DETV$HR?du(K40_|E}K-M;f!bp~F>Iz)@$^4a8QVF6edC6=l(n z=mxrxeq4pRqaLUy>P0uv?Q}2QN8@_E<{4b-Zx#b3$@fQyH34O#TtD|f1q*yeT^_gfK8c#o^ zyX(>`Dnqn>8bmyrOn1^<)KsUJsoBK6^)n}W3(a_m#XA$tqMy+{)YQ9c-jJcy#xSOh z)l70!gG%%^dWWfneDw2jkjeCC)g+Wviju;7PoO$>WNlt8@nZCzzul;7V$f3bfuDOB zJy?#G(?iwVt$K9JD$39EJ(h>qQI+4k6=)?rOppF;-Ws&-C0*B}kLVZl2*YguFs&AC zMq6K+-iEf*WAr$io*x$Ji&RB>KVuOGDt3CQ-CgK&bPU9ga2^jA@o*;(clqs5v|uNP z;YEdc1*Ij;S+_pg&03Odxwe&Ou-ms$m8sYHpGM`^9Ac`QnykF>o;HQW44oyuyQ-lv z-yznXRif|F74!rBnqH#cRHAF>I=VqG(_eX*$o6!JdPUri=qJAy@6m6|(S7!ekdaVi#K~K?N=mo>zHF}-i zV$yeNMu*`bEM(%bfZiy_!Sp5@ZmCU5z%m@pq~H)N$Dufk-llixUHW4cR$wKLz$$u= z{zUK7Ul{pf?Z|L!V3`0LaSS%mpXmeoke2y$k?}2X1Dx;@CU7#gvl@-9*hU}G#}(Lt zQ|KQ&jCjc`+^E{D-?HVIFV~GTI#onH^KoW1-S64*j2iPpeIG@JdT>+R8pN)^&2V$v z0=LAi=o9*sKBIrq=PPg<+!nXP?eVMhFZzOqA|8r)sPqRlx%$-N>{49lKWzn0h+T?3 zqw@+!mAo|A(tm36-HF`f%9g8MVrpM7xG=z2vny~G?(X+*Hy(m=+=GXZxs0758{$3; z{J1af$3w(JK^^>YHXg+AjR#^k4>1q93Y>#;c}RE|#4vs*sz=OlT<{NyLR`c{ArFJ8 zi5)ZNPV@EG8C;{;Ho#+eD4}KN@px9JS+&L!@I+jOC-p9=Zll>LlZPQZl<`o?L&d-N zTa&cA^^m34qi)sOGa0|>58xYk3J>Kx46VRZ@mo9$<6$_nEKF|`u)2%q;JLm+y+Kfk z=i&LRsut>-wD4h;OzPzayb!E*b;VAOm(uL{HVs@Z=$!%Zy-PR!BHiKU2tySV1eEDTJeUDiJSdXvZAMjPg z;p_MYzKL()+xQN?i+{xTc$maPD-Z2-4G&Xzn99S3JWS(Z1`jiN*o248c-Ue+zK?&# z5AZ|$3;q>9!oT6i_;>sVeuAI!uoa_!jfV`R42}bNn8U-tJRHWu5jlpFO%wM7{Cgz_=q@-qgRVNp&~qyAq?XPb3QvIcr+R z8loRehWbR|0V1~hTE3hgdPYar*F+tlYqWV&8ZY(#B$(z8#{yZGumzPcBOwIlMX@mJg|E)i*707c_ z>nrJfNz1pmX#p)+Djig#C6n4Z_gufomI0~u6i02Bz|G}Yg8C1G7jW+eM6t}lZY!$| zt`^n2Tz0J5+LV;kvU9cZTFO=UMg42MDmm5^aw~Z_goi`@qS(Es?}a(e%dO+sJ=K52 zY7@6Ppulh*=GQ5(Ys%TX4^y^OE0F3+t25&s8kmSJiJq zin9^B+Dfsr=+%1p3+}{!nsbsn#l)TA;Yc19`^A+obF6W3_KO@#WdGrVZ@KRn(-j_$ z;^AmN(-_8-WidOro7|88$#swWDWLf{9*(ck+}9yi zn#9&x5F4W)m=JbzMmTmPFDF4fVj$59gN?8xMUiC0CLf$N_Kv%gI^i4devUh-9#8Mbbz*58vV8f(p`@ zuzde64;NBX_c3|7r9*oR_4vDcQ?u#SjXf|mo4U99sV1X4YE6vF2KElyiU53EYgjz)UcF?RXkkH z!*x8|SXX>WFVfGyKyT8A^yT3)9)7^X<&~sA89=gmSkA)=9#*n=Y-~^!Pll5GeRjSMZQ+npKQ=VuCuJj3VRyjd(nnKvEl6 zTdhYI5Z2VJWCkxJi%4Jc9$}3QGy7v6Zeo`6a5E1-S;_2QMm`|R*(aN0Uf9CJtvuXb z{jkOF@0dD&``THRzHsX#FImI1T1!4;m-klx1xs~)d}tpznTOi~Dy}CV1+?*0koEqX zj?iv}x$bcWcd5bQ$grmyx^$EetACrru1v^g;4TMJ_O>Us`n*iG0rx7zksahyvXks0 zyYWqbU$L8S3_s)HULJnV!vn0tU?Kjy#^JI6UZwTM$l<`)p8u;f5}DSKgf0bgYu)Nkx{ zA>=T7T`1xtoQ%CJY{Y71Uv3zC-&eri^%Zla+-O#y-r}ZnGuhj|x!iot$1UI%a$j+` zSf^d#t6(4PXCAX1E+6ps{_ zi06oxig$@mi*Jj6mxv|N5~rlIBv&#)GDY&HL4W!ZPKE3&Jy z-(Tq}=~ z>*WS{y1a$Fy}Y}8tbB@ms(hM!hJ2QMj=WO7Ren(ZmHd(XvHTDDQ~96rze4Sy>7mU+ zTZFa>Z4=rqw0r2l(7~ZYLx+XthmHz;Cv_Rxc&heMBq9t-^{^it^M(C*M>)h>%$Gmoji*ch=X;**Ho5eFg;MSKx)G~#%~*Ad@Dd>iq7#J!075f37~zeK!H zK^0aJRfsA|rB@kLF{(sWHzXW0f6ZXcP|YaKSj~7%nZ~Q(H48Kqno3QTW~FAcW~*kqW~XMi zW{>8a=CbAo%{9#p%`MF%%@fTt&2uf%a@ruRP#dO=)W&PQ$y%G%p>3#5(`INhwVkv* zwME)-+KJjpTB@C`U8Y^Gt$xgl~_a zQFEi-k6ISB+#6L9^&slGE=VWTiF6X3OsCRmbdfrpE?Q^Qy`p zTcum0JE%LU`$l(NcT;y;cUN~$_nYo_-4oq2-E-Xwy+|LSx9fZA2kM9GOZ5}v%MlX(D61_5db@bZk_0b!nH%D)YzG09Xni>iW3k@F|J~Qky955U< z95oy_Tru1++&4TlJTg2sVx!O~Hp-0Q#t5Uv7-?)^%rp)(<{3vDCm1IgdE->$bmJ`J z9ItV%aglMoajS8MahLHk<0<3U#>>X=2Xm$m|tRkjd>LF*n~|IQ-~?dq%^5bMw8hTXG$<7n{1{&rs<~b zrXNiAO%F}KnjV{;n4XzAbFf)r4l#$Cy?V3B9BXc1wwfL0RC7afD|1it1oJfWZ1X&` z&%DUI#JtSB+`Pv8nfb8!sQHBXl=+JJn)#;rj`^M?!Q!+uv$VFfvvja@v1D0#SbAAT zSjJl>SSDH~S!P;RTGm+BSvFWcwtQmQX8F{z+p^cP-*U)u#B$tn%W~K9ljVWe@~h>s z<%#7_%ZpePOJaqw;#gU%JXRMQ9czp=$MuWLiyIy{BCaTIOWfyi2jULJ9f=pmtK+rt zQSs67Iq^mD#qp)_W8!zmAB{gAe=`0|0#1-8ge52vR0-J$`3VIHMF}MdTNCyt985Tz za5Pbvs7zEPY7(Oo`y>uY%uDnRPb^4Wo474;N8--J&k|oGNs^RF>ZHgdeUdRLAt^b@ zo|Ka0N@|qUHECSZTS*&|wkI7(I+1iK=~~jwq&rFXl73G5Bk5VvU&$aDCzE7Da@*wY z$z{n?ljkNcN?wutQS!&hpCoTf{xo@i@}cA-$;XmUCZA6J(HdqoSld}&xAyT`-PQu@ z80$Fe1Z$bqYn^7DX`N%8XZ2YZSeIE>TQ^zvSii6yv!1k`v7WbnYrSH&#^DDSJ_wD*V@h@isPE& zrsIy|spGlhMG8#eQUocY6lqFGN@z-CN^DBglpZO=Q)tSfl#f$(r(8|BlX5rZi8II< z?36gYA%7yk2+5{ z&pR(VFFC(;exDkanw;7uwR38p)c&ahQ*%-Wr{<*&PaT`;O`V+jX6m%mxv6ibE=XOJ z`d;e()Q2veE7q0lYUFC=>fq|+dfnB{)z>w^>vFqtU4vbPu92=Wt|_jWt~svxu6JBZ zT+3YLt}53`*9O-n*Dlu)*J;-|*O#uZT~}OJT{m2}U3Xm%T~8aLv>|E3(n`|!v}tK` z)80>8leR8xL)xaaEos}+cBXxib}a2=+L^TTX&2KjrCm;k>9Ofu(#NO2kv=p1o%Dt2 z%hM;UN?(`0H~sVUN9emVU{`lIy6=}*%COn;GqGDwCnLzJP)&}2kr=ra;C zk~3@>DH)?P-pF_}OI&qKO=dRnP)>W0|uA^$T z?rQ6*tL|C1RdLkO*7dXf-+-w6{{4{;$$jVEGwwOxd(L_H{%kliZ#GZJCbD^s-eu_p zf`A05fd=rv0i3`E+#m+T0uP7-jX>i$U3I=*AQ$uoeL!FE8R!T4g8^V57y%}NSztE! z3VaPFfW@E~tOTpTTCfg$3$}vq!A|f4*bfeaW8fq>4=#YK;2O9OO27l~5IlhhVo0C} zieV6xKq(A{TBw6zP!A2z2*aTXnqee#Ko3lWRei7qtO@JFdN3I_f=ys^*c!HhU12wv z0W)D1{0#Pk{ow#O5az*=a1^9)3j7>Sh11}4_$8bRzk&7Ggpvv5 zOEQ;yMdpEVWIp+tEG7A*fE1GDWF6V)KY{DwEi~P)BqNoZ>30-S5e=hlX=aA9u79>z z@83j9NKIg0?Jp2%d^D8Gse&r0igHvrS zlP;$l*mx6l)67qsq&7^?>fSu7ySHzKQpujudi5XHGHYmV&#b)ugSs+8!<<|;N*UzM z%20aPbBF$e`V1bBmF;DG4gC3HslT<@<)0<);{T7x=u@=t=4JJ5pX(hKH+WcXk38vV zAO*o71f+qkz`hEkgLa@j=m0u`PM|aR6m+2mYNX-RM9tJfBWNUzS_Qg+3}$pH`(%S0 z;00D1O=~cd-RzT1$I!8CoY}c=)`VkT1;fB_ z|8YgLh^iD&E3JMGj0B_D)MzjUjAhe9fB?pU@nC|#hO(u(Dos*CYEy!~6_7Iby{BJ*<0!zSBkPiwvTeJIS4IbPt>oaf1vZ2>M zUlk!L1cji;zd&X2b!?f|s(Wv5c3!!rWdTjp6A;`fyI0nLJnx`{r1HttrIYa$C(E?0 z2OB!HOiLLwC~HI^SPzO$gN@AYO<*(l4h;P?r+@a4&zSM;+BWZ$m;0G_a9-AD185~G zu1rCOvX*~fOsv0aWreg%);6%+eAD*0Ol5eVJu(?W#WGZM>3QSf4(}}KU+;Ch2SVC`alo|1)O&r zobWGJI|%rNsamYI`yZ==I4185uor;Sv}OS~OKZ_ge~>0V8C(RH1LRAzb^*9T>(I>f z7FoId%E5Xa+y-0`xB+g0TeL2%N0W=d9p=cpG=(`bi=ED)nyhs2C}8DdT0aoKfs^hFYp4qqzz~)ZAcr@#`F`~WCeH)-hlsrw+tZvKtP+)X0#pc!f?@* zc4OAX@N3*K1S$bn3}rAB%AtZbr!8np+Nv0;AO~zvLtE1}EF+}R^e?m{eLE+@8@s=G z(0Nqlq}YhW8dZ|UNIH(HlEfYo#*}&wT3|$%mT9TE*?GDB`(+IpQ3x%d=p%^3C>UJ^ zar!B3Uk2~eI6xh+hTUP$!18RE1HG^Z&859*AKJGV*gz`m%`#P6 zw$;x9`N`iZY;*)11m@4W1kPY2P#g>WLAMDyqn2EGA7k^Tt1z9*akXIEG<2Yx|^(cv_`Q`_90z48KS zI68Us1`zlwbJaXJzgx?+7DMu~y7%>#9{nOXFL3yks9f(NxHw?s*K~9ND;umx_yxT& z8WzGLV9(E|ndR%2!8c17;k9$LZ&E z`Uf*k!ZQ^_o`vV=R632Ow~kJx$_m;q!>j+b^g3HQgQiC(_sa*Y!~#%m!fkjL*bCtu z_#2%?XBWbI@IIYGzX+6URhqXiOV!?-_cb*`8R1_m(fMacLSXqwno=(6clZ~uFNaUy zQ}_%%hkw97sh@sH=hCm}JUV|ld;wp=S1bp-0XDjTE~WVlaK-FD(;p(O>Gw;c{N1IA z{)SSM{+&c5LP3BlKw`SE07>W~=Dp)meH|o2a^^M^O1~~Z3c8qPeq1_AlNnMYE!!4Y zhIm$7mJ}kM4VJJ^ravy&;zK56c`rDE7SQx^jnT;VUbLMSzDEplp%^v+mQhauils## zCgM?IU}6Dv6_n~I#~7-LlHTj6PM3YqQL8hmT>*}$9!g;{O3xOmPglId0cr?+MW_*K zj6R_&=^DE3Jr+9kM%-*n5R)L>P^3;8w*+U6J%vMB#=dF z$cOnm7%Uz00<}iRdcpEqgN7r@Y7H8JMxs$@G#Z1(A|KsKzo*;icDjS^q`OuCD;kH! zqX}ptnuI1ZdAkLeAi&B3Oc7v?0KH7Xc|&J^8)J{iIcP4h7ojhZAAL#p&>!gDBJ>rS zhvw6L^df!1R$eqNb1Xsm%*$vg{jmTQ(ETigA5t}1&PsR&{V7A)%)d7#(SI&H%C!ou zW9bsDMr+VFXe~WJ57I;Qa53zS)}n9GMwTiM)1T=vCOy(LltbIlj)3^>^hg2PNslt} zDpRZ*?L`LyQud)A(NAbUJx)*1U+BqVbPydvhtbdU6g^GP&!!|7)u#&a1fTz+w@K$4#pw$H+uJ7zONlw)xcrC!U`?c(fhQ7WiNle z)tX>p5W!~ph$fuDk*tqn-5id>(b$S@od%btAy)qB6Z$)SO#ckDaDi=EY~gwrj%Dz} zZX83O(r1O(gX8FP`Ul%Z+o22s4z)rHJlYS*iX=YX7on?C%#-=VN+a8C~Sx z9aCTX(fSc(^q>r7!%}h0-2BJWW6P$c40m`O9*-yBi2@7}piF?F z0+biy$#@E|;i&>t2vAAe3Q$EeSzqY)c_KXcOT2(F{=ZHVFT{%&(_#Ut1=de8CZ0vx z7w_=kBFxJAzi_O=s~N{P0@MkRy^jh|&o~YwSUq?n-ukZ`-{WnJV}}5Z0t^pum>9?U zSX(0Aiv#ER-?wuRA7WfT3(z9KhyYh4Kh zVL?wUAS~#WSWZ}!Xz4&WVg%euq9z)`6D`q^Frp{y|ing?VyAx%j$0X7!kCjx9zL|TxRq?G`h3XoBo2bw3l|5|mke@B(^KGKnN`8S@f zq#I!ew50$UXKUuRlF6dH#FBDT7&n$tv=RA7BH(8l11#* zKQ8cIAHeHBubzj536QnUEZLLAWJ#Gd-a@iC@Sd$o@1K)3A|fj*jZ6IB7o#RB};rTT&uXE|M;ju9I$&?vNgmo{?UaUYFjK-VXLf z1;+%Z1UCxq66_709XvPqhv19BmxF%|z7~8VxFq;d@bAG-gI|YOLtG(gAzebog-i}v z8?rrQSIC}_eIY-E90++F@+RbO8IWO_NERfM$@H=aS(MBwv&%fPcv+&XvaG5sOEy9_ zN48M5ShiGFAX_KfCEFw0EBjHlUv|(ZJ1jdQyCl0JyDGabyD7UZ`%QLFRw8>5ibKtz zl|oyF_6;2#Ix}=pXmRNB(3PR9L%#|AE_7??w$L4+yF&MbUXnw(LY^c~mN%0(m$#F5 zllPGikWZ9PmVYjvCZ8dnC7&-}Dld>1$(PAj$T!Qk$iJ6wmmicLmLHKHlV6hiuE?*- zuggp1FXXS}Z{%+kL5c)L9YsS$8%3I;ouY#xQ_(}wN0FzPs+gl#s93C6swhx=uh_3R zuJ}c9N^wSUPH|0fLvc%SM{!qiU-3*CtmKszWvsHQGD%rOSxZ?**+}_`vZ=DUvZb=M zvY&FAa-H&^@)zYvJTBh2p+M(K|`dM{MbwYJYbw+hgRib*K zdZ~J)dc#S$5H6HcavZ1OoLnMTjjPVpVX3zjJ?Ze{nCl*W4R5 zQLEHib(q?qwx}c3(Q2DIPF+i#tgf$4RX0&LQ@2pJQfI3tsaL7DsDD)NS07X#Rv%Fx z^Qlj$uc)u8ud8pWZ>xV(-&2=pphl^Q(lpWx(R`^X&=hNyYgTF2Xx3`>XpU-5XijR* zXwGRaXl`nL*ZiUROY>6mR`U-JdCU{u$UFHM-oq#GmG~-r3ZKe1;+ycz_!fL;zAK-> zcjt5X9{gZ_C_kJZ#gE~Ayl*-`i=V@P$$!Pq=a=!z`4#*seha^i-@)(Zf8h7=NBC3x z8U7r9fxpDxaX}f5%wAos( zwzsygwx4!@cD#1BcCL1wc7b+@HeXw)E!G~;-qsm)RdjWHx@28_U8=5)E>qWCm!s>U z>!s_h>#OUh8>92-1l|?k}y+Pd|1=44q@HGGQ+xu<%IPK z`z)+~*ub#CVQa(g>XmwvK0+U*x9J^vm%f_5y1u5qwtlL9o<3h+s4vzp*RRxntKX#m zPQO*ZP4C;GKd*maP#N5YBtuO@Z9_dnilKoa!_dnx#4y%C4dVm zv+$NMi_v1TxGk}kI7@5$sJ&5dql10XvS@j1Y-nHJhKC}L5eQAAd zeQW*4Cb980i!Ihx)s|$dVXI}UV{2q~1Z|7O2ue`H>04y(iAa5-WfagHQM zilc?2v!kmc(~<4y;ppWU>Y$DpjwOx)N3mmtW3^+gV}oOpV~gXU<7dZF$8pC=#~H_Y z$0f%V$5qEY$8)F58SSj@Y~l1e$2zAv*E_d3eOsLeoTr_aoWDA+J8wBloR6GOoX?$q zx}2^Ct}ZUGYk+I8Yp834YqZPf5?nJ~b6xXYi(E@w%Umm6Yh3GG8(bINLGH@#+U^GK z7VggOEO(B(r@Oa%pgYe!%stXQ+C9-d**(L(&|TmzcCT=+c7N;M?B43$?%wI%?>^*n zpK@Pw|K`5$e(3(){g?Zt`;GhW7!VT_ql^jjjPX#<=bm| Matrix { + func translationMatrix(_ matrix: Matrix, _ position: float3) -> Matrix { + var matrix = matrix matrix.m[12] = position.x matrix.m[13] = position.y matrix.m[14] = position.z return matrix } - func scalingMatrix(var matrix: Matrix, _ scale: Float) -> Matrix { + func scalingMatrix(_ matrix: Matrix, _ scale: Float) -> Matrix { + var matrix = matrix matrix.m[0] = scale matrix.m[5] = scale matrix.m[10] = scale @@ -39,7 +41,8 @@ struct Matrix { return matrix } - func rotationMatrix(var matrix: Matrix, _ rot: float3) -> Matrix { + func rotationMatrix(_ matrix: Matrix, _ rot: float3) -> Matrix { + var matrix = matrix matrix.m[0] = cos(rot.y) * cos(rot.z) matrix.m[4] = cos(rot.z) * sin(rot.x) * sin(rot.y) - cos(rot.x) * sin(rot.z) matrix.m[8] = cos(rot.x) * cos(rot.z) * sin(rot.y) + sin(rot.x) * sin(rot.z) @@ -53,7 +56,8 @@ struct Matrix { return matrix } - func modelMatrix(var matrix: Matrix) -> Matrix { + func modelMatrix(_ matrix: Matrix) -> Matrix { + var matrix = matrix matrix = rotationMatrix(matrix, float3(0.0, 0.0, 0.1)) matrix = scalingMatrix(matrix, 0.25) matrix = translationMatrix(matrix, float3(0.0, 0.5, 0.0)) diff --git a/ch07/chapter07/MetalView.swift b/ch07/chapter07/MetalView.swift index a042c98..975c572 100644 --- a/ch07/chapter07/MetalView.swift +++ b/ch07/chapter07/MetalView.swift @@ -10,57 +10,58 @@ import MetalKit class MetalView: MTKView { - var vertex_buffer: MTLBuffer! - var uniform_buffer: MTLBuffer! - var rps: MTLRenderPipelineState! = nil + var commandQueue: MTLCommandQueue? + var rps: MTLRenderPipelineState? + var vertexBuffer: MTLBuffer! + var uniformBuffer: MTLBuffer! required init(coder: NSCoder) { super.init(coder: coder) - device = MTLCreateSystemDefaultDevice() createBuffers() registerShaders() } - override func drawRect(dirtyRect: NSRect) { - super.drawRect(dirtyRect) - if let rpd = currentRenderPassDescriptor, drawable = currentDrawable { - rpd.colorAttachments[0].clearColor = MTLClearColorMake(0.5, 0.5, 0.5, 1.0) - let command_buffer = device!.newCommandQueue().commandBuffer() - let command_encoder = command_buffer.renderCommandEncoderWithDescriptor(rpd) - command_encoder.setRenderPipelineState(rps) - command_encoder.setVertexBuffer(vertex_buffer, offset: 0, atIndex: 0) - command_encoder.setVertexBuffer(uniform_buffer, offset: 0, atIndex: 1) - command_encoder.drawPrimitives(.Triangle, vertexStart: 0, vertexCount: 3, instanceCount: 1) - command_encoder.endEncoding() - command_buffer.presentDrawable(drawable) - command_buffer.commit() - } - } - func createBuffers() { - let vertex_data = [ - 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]) + device = MTLCreateSystemDefaultDevice()! + commandQueue = device!.newCommandQueue() + let vertex_data = [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]) ] - vertex_buffer = device!.newBufferWithBytes(vertex_data, length: sizeof(Vertex) * 3, options:[]) - uniform_buffer = device!.newBufferWithLength(sizeof(Float) * 16, options: []) - let bufferPointer = uniform_buffer.contents() - memcpy(bufferPointer, Matrix().modelMatrix(Matrix()).m, sizeof(Float) * 16) + vertexBuffer = device!.newBuffer(withBytes: vertex_data, length: sizeof(Vertex.self) * 3, options:[]) + uniformBuffer = device!.newBuffer(withLength: sizeof(Float.self) * 16, options: []) + let bufferPointer = uniformBuffer.contents() + memcpy(bufferPointer, Matrix().modelMatrix(Matrix()).m, sizeof(Float.self) * 16) } func registerShaders() { let library = device!.newDefaultLibrary()! - let vertex_func = library.newFunctionWithName("vertex_func") - let frag_func = library.newFunctionWithName("fragment_func") + let vertex_func = library.newFunction(withName: "vertex_func") + let frag_func = library.newFunction(withName: "fragment_func") let rpld = MTLRenderPipelineDescriptor() rpld.vertexFunction = vertex_func rpld.fragmentFunction = frag_func - rpld.colorAttachments[0].pixelFormat = .BGRA8Unorm + rpld.colorAttachments[0].pixelFormat = .bgra8Unorm do { - try rps = device!.newRenderPipelineStateWithDescriptor(rpld) + try rps = device!.newRenderPipelineState(with: rpld) } catch let error { self.print("\(error)") } } + + override func draw(_ dirtyRect: NSRect) { + super.draw(dirtyRect) + if let rpd = currentRenderPassDescriptor, drawable = currentDrawable { + rpd.colorAttachments[0].clearColor = MTLClearColorMake(0.5, 0.5, 0.5, 1.0) + let commandBuffer = device!.newCommandQueue().commandBuffer() + let commandEncoder = commandBuffer.renderCommandEncoder(with: rpd) + commandEncoder.setRenderPipelineState(rps!) + commandEncoder.setVertexBuffer(vertexBuffer, offset: 0, at: 0) + commandEncoder.setVertexBuffer(uniformBuffer, offset: 0, at: 1) + commandEncoder.drawPrimitives(.triangle, vertexStart: 0, vertexCount: 3, instanceCount: 1) + commandEncoder.endEncoding() + commandBuffer.present(drawable) + commandBuffer.commit() + } + } } diff --git a/ch08/chapter08.playground/Contents.swift b/ch08/chapter08.playground/Contents.swift index 96ca6ff..694d377 100644 --- a/ch08/chapter08.playground/Contents.swift +++ b/ch08/chapter08.playground/Contents.swift @@ -1,8 +1,9 @@ -import Cocoa -import XCPlayground +import MetalKit +import PlaygroundSupport -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 +let frame = NSRect(x: 0, y: 0, width: 400, height: 400) +let delegate = MetalView() +let view = MTKView(frame: frame, device: delegate.device) +view.delegate = delegate +PlaygroundPage.current.liveView = view diff --git a/ch08/chapter08.playground/Resources/Shaders.metal b/ch08/chapter08.playground/Resources/Shaders.metal index a9bad7e..2234835 100644 --- a/ch08/chapter08.playground/Resources/Shaders.metal +++ b/ch08/chapter08.playground/Resources/Shaders.metal @@ -11,7 +11,9 @@ struct Uniforms { float4x4 modelMatrix; }; -vertex Vertex vertex_func(constant Vertex *vertices [[buffer(0)]], constant Uniforms &uniforms [[buffer(1)]], uint vid [[vertex_id]]) { +vertex Vertex vertex_func(constant Vertex *vertices [[buffer(0)]], + constant Uniforms &uniforms [[buffer(1)]], + uint vid [[vertex_id]]) { float4x4 matrix = uniforms.modelMatrix; Vertex in = vertices[vid]; Vertex out; diff --git a/ch08/chapter08.playground/Sources/MathUtils.swift b/ch08/chapter08.playground/Sources/MathUtils.swift index cc13d82..3461891 100644 --- a/ch08/chapter08.playground/Sources/MathUtils.swift +++ b/ch08/chapter08.playground/Sources/MathUtils.swift @@ -21,14 +21,16 @@ struct Matrix { ] } - func translationMatrix(var matrix: Matrix, _ position: float3) -> Matrix { + func translationMatrix(_ matrix: Matrix, _ position: float3) -> Matrix { + var matrix = matrix matrix.m[12] = position.x matrix.m[13] = position.y matrix.m[14] = position.z return matrix } - func scalingMatrix(var matrix: Matrix, _ scale: Float) -> Matrix { + func scalingMatrix(_ matrix: Matrix, _ scale: Float) -> Matrix { + var matrix = matrix matrix.m[0] = scale matrix.m[5] = scale matrix.m[10] = scale @@ -36,7 +38,8 @@ struct Matrix { return matrix } - func rotationMatrix(var matrix: Matrix, _ rot: float3) -> Matrix { + func rotationMatrix(_ matrix: Matrix, _ rot: float3) -> Matrix { + var matrix = matrix matrix.m[0] = cos(rot.y) * cos(rot.z) matrix.m[4] = cos(rot.z) * sin(rot.x) * sin(rot.y) - cos(rot.x) * sin(rot.z) matrix.m[8] = cos(rot.x) * cos(rot.z) * sin(rot.y) + sin(rot.x) * sin(rot.z) @@ -50,7 +53,8 @@ struct Matrix { return matrix } - func modelMatrix(var matrix: Matrix) -> Matrix { + func modelMatrix(matrix: Matrix) -> Matrix { + var matrix = matrix matrix = rotationMatrix(matrix, float3(0.0, 0.0, 0.1)) matrix = scalingMatrix(matrix, 0.25) matrix = translationMatrix(matrix, float3(0.0, 0.5, 0.0)) diff --git a/ch08/chapter08.playground/Sources/MetalView.swift b/ch08/chapter08.playground/Sources/MetalView.swift index 9305067..61a864c 100644 --- a/ch08/chapter08.playground/Sources/MetalView.swift +++ b/ch08/chapter08.playground/Sources/MetalView.swift @@ -1,69 +1,68 @@ import MetalKit -public class MetalView: MTKView { +public class MetalView: NSObject, MTKViewDelegate { - var vertex_buffer: MTLBuffer! - var uniform_buffer: MTLBuffer! - var rps: MTLRenderPipelineState! = nil + public var device: MTLDevice! + var queue: MTLCommandQueue! + var vertexBuffer: MTLBuffer! + var uniformBuffer: MTLBuffer! + var rps: MTLRenderPipelineState! - required public init(coder: NSCoder) { - super.init(coder: coder) - } - - override public init(frame frameRect: CGRect, device: MTLDevice?) { - super.init(frame: frameRect, device: device) + override public init() { + super.init() createBuffers() registerShaders() } - override public func drawRect(dirtyRect: NSRect) { - super.drawRect(dirtyRect) - if let rpd = currentRenderPassDescriptor, drawable = currentDrawable { - rpd.colorAttachments[0].clearColor = MTLClearColorMake(0.5, 0.5, 0.5, 1.0) - let command_buffer = device!.newCommandQueue().commandBuffer() - let command_encoder = command_buffer.renderCommandEncoderWithDescriptor(rpd) - command_encoder.setRenderPipelineState(rps) - command_encoder.setVertexBuffer(vertex_buffer, offset: 0, atIndex: 0) - command_encoder.setVertexBuffer(uniform_buffer, offset: 0, atIndex: 1) - command_encoder.drawPrimitives(.Triangle, vertexStart: 0, vertexCount: 3, instanceCount: 1) - command_encoder.endEncoding() - command_buffer.presentDrawable(drawable) - command_buffer.commit() - } - } - func createBuffers() { - let vertex_data = [ - Vertex(pos: [-1.0, -1.0, 0.0, 1.0], col: [1, 0, 0, 1]), - Vertex(pos: [ 1.0, -1.0, 0.0, 1.0], col: [0, 1, 0, 1]), - Vertex(pos: [ 0.0, 1.0, 0.0, 1.0], col: [0, 0, 1, 1]) + device = MTLCreateSystemDefaultDevice() + queue = device.newCommandQueue() + let vertexData = [Vertex(pos: [-1.0, -1.0, 0.0, 1.0], col: [1, 0, 0, 1]), + Vertex(pos: [ 1.0, -1.0, 0.0, 1.0], col: [0, 1, 0, 1]), + Vertex(pos: [ 0.0, 1.0, 0.0, 1.0], col: [0, 0, 1, 1]) ] - vertex_buffer = device!.newBufferWithBytes(vertex_data, length: sizeof(Vertex) * 3, options:[]) - uniform_buffer = device!.newBufferWithLength(sizeof(Float) * 16, options: []) - let bufferPointer = uniform_buffer.contents() - memcpy(bufferPointer, Matrix().modelMatrix(Matrix()).m, sizeof(Float) * 16) + vertexBuffer = device!.newBuffer(withBytes: vertexData, length: sizeof(Vertex.self) * 3, options:[]) + uniformBuffer = device!.newBuffer(withLength: sizeof(Float.self) * 16, options: []) + let bufferPointer = uniformBuffer.contents() + memcpy(bufferPointer, Matrix().modelMatrix(matrix: Matrix()).m, sizeof(Float.self) * 16) } func registerShaders() { - let path = NSBundle.mainBundle().pathForResource("Shaders", ofType: "metal") + let path = Bundle.main.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) - //print(library.functionNames) - vert_func = library.newFunctionWithName("vertex_func")! - frag_func = library.newFunctionWithName("fragment_func")! + input = try String(contentsOfFile: path!, encoding: String.Encoding.utf8) + library = try device!.newLibrary(withSource: input!, options: nil) + vert_func = library.newFunction(withName: "vertex_func")! + frag_func = library.newFunction(withName: "fragment_func")! let rpld = MTLRenderPipelineDescriptor() rpld.vertexFunction = vert_func rpld.fragmentFunction = frag_func - rpld.colorAttachments[0].pixelFormat = .BGRA8Unorm - rps = try device!.newRenderPipelineStateWithDescriptor(rpld) + rpld.colorAttachments[0].pixelFormat = .bgra8Unorm + rps = try device!.newRenderPipelineState(with: rpld) } catch let e { Swift.print("\(e)") } } + + public func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {} + + public func draw(in view: MTKView) { + if let rpd = view.currentRenderPassDescriptor, let drawable = view.currentDrawable { + rpd.colorAttachments[0].clearColor = MTLClearColorMake(0.5, 0.5, 0.5, 1.0) + let commandBuffer = queue.commandBuffer() + let commandEncoder = commandBuffer.renderCommandEncoder(with: rpd) + commandEncoder.setRenderPipelineState(rps) + commandEncoder.setVertexBuffer(vertexBuffer, offset: 0, at: 0) + commandEncoder.setVertexBuffer(uniformBuffer, offset: 0, at: 1) + commandEncoder.drawPrimitives(.triangle, vertexStart: 0, vertexCount: 3, instanceCount: 1) + commandEncoder.endEncoding() + commandBuffer.present(drawable) + commandBuffer.commit() + } + } } diff --git a/ch08/chapter08.playground/contents.xcplayground b/ch08/chapter08.playground/contents.xcplayground index 06828af..9f9eecc 100644 --- a/ch08/chapter08.playground/contents.xcplayground +++ b/ch08/chapter08.playground/contents.xcplayground @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/ch08/chapter08.playground/playground.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate b/ch08/chapter08.playground/playground.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate index 4b12b70ee54fcc35f0dcf5400cbe4f928aeff114..9826afda956d995046a0b520d44fb800856e8857 100644 GIT binary patch literal 16465 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 E9~N)+RsaA1 literal 14980 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 rRg&5zwMVKmwI+3HsyDSRbzbU%)Fu966`~g!xF6 matrix_float4x4 { return matrix_float4x4(columns:(X, Y, Z, W)) } -func rotationMatrix(angle: Float, _ axis: vector_float3) -> matrix_float4x4 { +func rotationMatrix(angle: Float, axis: vector_float3) -> matrix_float4x4 { var X = vector_float4(0, 0, 0, 0) X.x = axis.x * axis.x + (1 - axis.x * axis.x) * cos(angle) X.y = axis.x * axis.y * (1 - cos(angle)) - axis.z * sin(angle) diff --git a/ch09/chapter09.playground/Sources/MetalView.swift b/ch09/chapter09.playground/Sources/MetalView.swift index 27e9042..769c51d 100755 --- a/ch09/chapter09.playground/Sources/MetalView.swift +++ b/ch09/chapter09.playground/Sources/MetalView.swift @@ -1,28 +1,26 @@ import MetalKit -public class MetalView: MTKView { +public class MetalView: NSObject, MTKViewDelegate { - var vertex_buffer: MTLBuffer! - var uniform_buffer: MTLBuffer! - var index_buffer: MTLBuffer! - var dss: MTLDepthStencilState! + public var device: MTLDevice! + var queue: MTLCommandQueue! + var vertexBuffer: MTLBuffer! + var uniformBuffer: MTLBuffer! + var indexBuffer: MTLBuffer! var rps: MTLRenderPipelineState! - var commandQueue: MTLCommandQueue! var rotation: Float = 0 - required public init(coder: NSCoder) { - super.init(coder: coder) - } - - override public init(frame frameRect: CGRect, device: MTLDevice?) { - super.init(frame: frameRect, device: device) + override public init() { + super.init() + device = MTLCreateSystemDefaultDevice() + queue = device.newCommandQueue() createBuffers() createPipeline() } func createBuffers() { - let vertex_data = [ + let vertexData = [ Vertex(pos: [-1.0, -1.0, 1.0, 1.0], col: [1, 1, 1, 1]), Vertex(pos: [ 1.0, -1.0, 1.0, 1.0], col: [1, 0, 0, 1]), Vertex(pos: [ 1.0, 1.0, 1.0, 1.0], col: [1, 1, 0, 1]), @@ -30,71 +28,75 @@ public class MetalView: MTKView { Vertex(pos: [-1.0, -1.0, -1.0, 1.0], col: [0, 0, 1, 1]), Vertex(pos: [ 1.0, -1.0, -1.0, 1.0], col: [1, 0, 1, 1]), Vertex(pos: [ 1.0, 1.0, -1.0, 1.0], col: [0, 0, 0, 1]), - Vertex(pos: [-1.0, 1.0, -1.0, 1.0], col: [0, 1, 1, 1]) - ] - let index_data: [UInt16] = [ - 0, 1, 2, 2, 3, 0, // front - 1, 5, 6, 6, 2, 1, // right - 3, 2, 6, 6, 7, 3, // top - 4, 5, 1, 1, 0, 4, // bottom - 4, 0, 3, 3, 7, 4, // left - 7, 6, 5, 5, 4, 7, // back - ] - vertex_buffer = device!.newBufferWithBytes(vertex_data, length: sizeof(Vertex) * vertex_data.count, options: []) - index_buffer = device!.newBufferWithBytes(index_data, length: sizeof(UInt16) * index_data.count , options: []) - uniform_buffer = device!.newBufferWithLength(sizeof(matrix_float4x4), options: []) + Vertex(pos: [-1.0, 1.0, -1.0, 1.0], col: [0, 1, 1, 1])] + + let indexData: [UInt16] = [0, 1, 2, 2, 3, 0, // front + 1, 5, 6, 6, 2, 1, // right + 3, 2, 6, 6, 7, 3, // top + 4, 5, 1, 1, 0, 4, // bottom + 4, 0, 3, 3, 7, 4, // left + 7, 6, 5, 5, 4, 7] // back + + vertexBuffer = device!.newBuffer(withBytes: vertexData, length: sizeof(Vertex.self) * vertexData.count, options: []) + indexBuffer = device!.newBuffer(withBytes: indexData, length: sizeof(UInt16.self) * indexData.count , options: []) + uniformBuffer = device!.newBuffer(withLength: sizeof(matrix_float4x4.self), options: []) } func createPipeline() { + let path = Bundle.main.pathForResource("Shaders", ofType: "metal") + let input: String? + let library: MTLLibrary + let vert_func: MTLFunction + let frag_func: MTLFunction do { - let path = NSBundle.mainBundle().pathForResource("Shaders", ofType: "metal") - let input = try String(contentsOfFile: path!, encoding: NSUTF8StringEncoding) - let library = try device!.newLibraryWithSource(input, options: nil) - let vert_func = library.newFunctionWithName("vertex_func")! - let frag_func = library.newFunctionWithName("fragment_func")! + input = try String(contentsOfFile: path!, encoding: String.Encoding.utf8) + library = try device!.newLibrary(withSource: input!, options: nil) + vert_func = library.newFunction(withName: "vertex_func")! + frag_func = library.newFunction(withName: "fragment_func")! let rpld = MTLRenderPipelineDescriptor() rpld.vertexFunction = vert_func rpld.fragmentFunction = frag_func - rpld.colorAttachments[0].pixelFormat = .BGRA8Unorm - rps = try device!.newRenderPipelineStateWithDescriptor(rpld) + rpld.colorAttachments[0].pixelFormat = .bgra8Unorm + rps = try device!.newRenderPipelineState(with: rpld) } catch let e { Swift.print("\(e)") } - commandQueue = device?.newCommandQueue() } func update() { - let scaled = scalingMatrix(0.5) + let scaled = scalingMatrix(scale: 0.5) rotation += 1 / 100 * Float(M_PI) / 4 - let rotatedY = rotationMatrix(rotation, float3(0, 1, 0)) - let rotatedX = rotationMatrix(Float(M_PI) / 4, float3(1, 0, 0)) + let rotatedY = rotationMatrix(angle: rotation, axis: float3(0, 1, 0)) + let rotatedX = rotationMatrix(angle: Float(M_PI) / 4, axis: float3(1, 0, 0)) let modelMatrix = matrix_multiply(matrix_multiply(rotatedX, rotatedY), scaled) let cameraPosition = vector_float3(0, 0, -3) - let viewMatrix = translationMatrix(cameraPosition) - let aspect = Float(drawableSize.width / drawableSize.height) - let projMatrix = projectionMatrix(0, far: 10, aspect: aspect, fovy: 1) + let viewMatrix = translationMatrix(position: cameraPosition) +// let aspect = Float(view.drawableSize.width / view.drawableSize.height) + let projMatrix = projectionMatrix(near: 0, far: 10, aspect: 1, fovy: 1) +// let projMatrix = projectionMatrix(0, far: 10, aspect: aspect, fovy: 1) let modelViewProjectionMatrix = matrix_multiply(projMatrix, matrix_multiply(viewMatrix, modelMatrix)) - let bufferPointer = uniform_buffer.contents() + let bufferPointer = uniformBuffer.contents() var uniforms = Uniforms(modelViewProjectionMatrix: modelViewProjectionMatrix) - memcpy(bufferPointer, &uniforms, sizeof(Uniforms)) + memcpy(bufferPointer, &uniforms, sizeof(Uniforms.self)) } - override public func drawRect(dirtyRect: NSRect) { - super.drawRect(dirtyRect) + public func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {} + + public func draw(in view: MTKView) { update() - if let rpd = currentRenderPassDescriptor, drawable = currentDrawable { - rpd.colorAttachments[0].clearColor = MTLClearColorMake(0.3, 0.5, 0.5, 1.0) - let command_buffer = commandQueue.commandBuffer() - let command_encoder = command_buffer.renderCommandEncoderWithDescriptor(rpd) - command_encoder.setRenderPipelineState(rps) - command_encoder.setFrontFacingWinding(.CounterClockwise) - command_encoder.setCullMode(.Back) - command_encoder.setVertexBuffer(vertex_buffer, offset: 0, atIndex: 0) - command_encoder.setVertexBuffer(uniform_buffer, offset: 0, atIndex: 1) - command_encoder.drawIndexedPrimitives(.Triangle, indexCount: index_buffer.length / sizeof(UInt16), indexType: MTLIndexType.UInt16, indexBuffer: index_buffer, indexBufferOffset: 0) - command_encoder.endEncoding() - command_buffer.presentDrawable(drawable) - command_buffer.commit() + if let rpd = view.currentRenderPassDescriptor, let drawable = view.currentDrawable { + rpd.colorAttachments[0].clearColor = MTLClearColorMake(0.5, 0.5, 0.5, 1.0) + let commandBuffer = queue.commandBuffer() + let commandEncoder = commandBuffer.renderCommandEncoder(with: rpd) + commandEncoder.setRenderPipelineState(rps) + commandEncoder.setFrontFacing(.counterClockwise) + commandEncoder.setCullMode(.back) + commandEncoder.setVertexBuffer(vertexBuffer, offset: 0, at: 0) + commandEncoder.setVertexBuffer(uniformBuffer, offset: 0, at: 1) + commandEncoder.drawIndexedPrimitives(.triangle, indexCount: indexBuffer.length / sizeof(UInt16.self), indexType: MTLIndexType.uInt16, indexBuffer: indexBuffer, indexBufferOffset: 0) + commandEncoder.endEncoding() + commandBuffer.present(drawable) + commandBuffer.commit() } } } diff --git a/ch09/chapter09.playground/playground.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate b/ch09/chapter09.playground/playground.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate index 6294b51a5384da980209f0281e9d4a149eb835ae..1d5e4b9ef41811637d59fbc2eccdf3b1021a850d 100755 GIT binary patch literal 27041 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 - - - - diff --git a/ch10/chapter10.playground/Contents.swift b/ch10/chapter10.playground/Contents.swift old mode 100755 new mode 100644 index 96ca6ff..694d377 --- a/ch10/chapter10.playground/Contents.swift +++ b/ch10/chapter10.playground/Contents.swift @@ -1,8 +1,9 @@ -import Cocoa -import XCPlayground +import MetalKit +import PlaygroundSupport -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 +let frame = NSRect(x: 0, y: 0, width: 400, height: 400) +let delegate = MetalView() +let view = MTKView(frame: frame, device: delegate.device) +view.delegate = delegate +PlaygroundPage.current.liveView = view diff --git a/ch10/chapter10.playground/Sources/MetalView.swift b/ch10/chapter10.playground/Sources/MetalView.swift index 6cbc65c..393222e 100755 --- a/ch10/chapter10.playground/Sources/MetalView.swift +++ b/ch10/chapter10.playground/Sources/MetalView.swift @@ -1,46 +1,45 @@ import MetalKit -public class MetalView: MTKView { +public class MetalView: NSObject, MTKViewDelegate { - var queue: MTLCommandQueue! = nil - var cps: MTLComputePipelineState! = nil + public var device: MTLDevice! + var queue: MTLCommandQueue! + var cps: MTLComputePipelineState! - required public init(coder: NSCoder) { - super.init(coder: coder) - } - - override public init(frame frameRect: CGRect, device: MTLDevice?) { - super.init(frame: frameRect, device: device) + override public init() { + super.init() registerShaders() } - override public func drawRect(dirtyRect: NSRect) { - super.drawRect(dirtyRect) - if let drawable = currentDrawable { - let command_buffer = queue.commandBuffer() - let command_encoder = command_buffer.computeCommandEncoder() - command_encoder.setComputePipelineState(cps) - command_encoder.setTexture(drawable.texture, atIndex: 0) - let threadGroupCount = MTLSizeMake(8, 8, 1) - let threadGroups = MTLSizeMake(drawable.texture.width / threadGroupCount.width, drawable.texture.height / threadGroupCount.height, 1) - command_encoder.dispatchThreadgroups(threadGroups, threadsPerThreadgroup: threadGroupCount) - command_encoder.endEncoding() - command_buffer.presentDrawable(drawable) - command_buffer.commit() - } - } - func registerShaders() { - queue = device!.newCommandQueue() - let path = NSBundle.mainBundle().pathForResource("Shaders", ofType: "metal") + device = MTLCreateSystemDefaultDevice()! + queue = device.newCommandQueue() + let path = Bundle.main.pathForResource("Shaders", ofType: "metal") do { - let input = try String(contentsOfFile: path!, encoding: NSUTF8StringEncoding) - let library = try device!.newLibraryWithSource(input, options: nil) - let kernel = library.newFunctionWithName("compute")! - cps = try device!.newComputePipelineStateWithFunction(kernel) + let input = try String(contentsOfFile: path!, encoding: String.Encoding.utf8) + let library = try device.newLibrary(withSource: input, options: nil) + let kernel = library.newFunction(withName: "compute")! + cps = try device.newComputePipelineState(with: kernel) } catch let e { Swift.print("\(e)") } } + + public func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {} + + public func draw(in view: MTKView) { + if let drawable = view.currentDrawable { + let commandBuffer = queue.commandBuffer() + let commandEncoder = commandBuffer.computeCommandEncoder() + commandEncoder.setComputePipelineState(cps) + commandEncoder.setTexture(drawable.texture, at: 0) + let threadGroupCount = MTLSizeMake(8, 8, 1) + let threadGroups = MTLSizeMake(drawable.texture.width / threadGroupCount.width, drawable.texture.height / threadGroupCount.height, 1) + commandEncoder.dispatchThreadgroups(threadGroups, threadsPerThreadgroup: threadGroupCount) + commandEncoder.endEncoding() + commandBuffer.present(drawable) + commandBuffer.commit() + } + } } diff --git a/ch10/chapter10.playground/contents.xcplayground b/ch10/chapter10.playground/contents.xcplayground old mode 100755 new mode 100644 diff --git a/ch10/chapter10.playground/playground.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate b/ch10/chapter10.playground/playground.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate index b0371a6e8797b8d4ce9f83f00151cbe0082ec193..4591e067402659c8f2fa1fb12861372764f1ff17 100755 GIT binary patch literal 23421 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 literal 16567 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 P3Vt$+f}f$^nbZFtQ2z&= diff --git a/ch10/chapter10.playground/timeline.xctimeline b/ch10/chapter10.playground/timeline.xctimeline deleted file mode 100755 index bf468af..0000000 --- a/ch10/chapter10.playground/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/ch11/chapter11.playground/Contents.swift b/ch11/chapter11.playground/Contents.swift index 00f436f..694d377 100644 --- a/ch11/chapter11.playground/Contents.swift +++ b/ch11/chapter11.playground/Contents.swift @@ -1,8 +1,9 @@ -import Cocoa -import XCPlayground +import MetalKit +import PlaygroundSupport -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 +let frame = NSRect(x: 0, y: 0, width: 400, height: 400) +let delegate = MetalView() +let view = MTKView(frame: frame, device: delegate.device) +view.delegate = delegate +PlaygroundPage.current.liveView = view diff --git a/ch11/chapter11.playground/Sources/MetalView.swift b/ch11/chapter11.playground/Sources/MetalView.swift index 425569a..db61db1 100755 --- a/ch11/chapter11.playground/Sources/MetalView.swift +++ b/ch11/chapter11.playground/Sources/MetalView.swift @@ -1,56 +1,45 @@ import MetalKit -public class MetalView: MTKView { +public class MetalView: NSObject, MTKViewDelegate { - var queue: MTLCommandQueue! = nil - var cps: MTLComputePipelineState! = nil + public var device: MTLDevice! + var queue: MTLCommandQueue! + var cps: MTLComputePipelineState! - var shader = - "#include \n" + - "using namespace metal;" + - "kernel void compute(texture2d output [[texture(0)]]," + - " uint2 gid [[thread_position_in_grid]])" + - "{" + - " output.write(float4(1, 1, 0, 1), gid);" + - "}" - - required public init(coder: NSCoder) { - super.init(coder: coder) - } - - override public init(frame frameRect: CGRect, device: MTLDevice?) { - super.init(frame: frameRect, device: device) + override public init() { + super.init() registerShaders() } - override public func drawRect(dirtyRect: NSRect) { - super.drawRect(dirtyRect) - if let drawable = currentDrawable { - let command_buffer = queue.commandBuffer() - let command_encoder = command_buffer.computeCommandEncoder() - command_encoder.setComputePipelineState(cps) - command_encoder.setTexture(drawable.texture, atIndex: 0) - let threadGroupCount = MTLSizeMake(8, 8, 1) - let threadGroups = MTLSizeMake(drawable.texture.width / threadGroupCount.width, drawable.texture.height / threadGroupCount.height, 1) - command_encoder.dispatchThreadgroups(threadGroups, threadsPerThreadgroup: threadGroupCount) - command_encoder.endEncoding() - command_buffer.presentDrawable(drawable) - command_buffer.commit() - } - } - func registerShaders() { - queue = device!.newCommandQueue() - let path = NSBundle.mainBundle().pathForResource("Shaders", ofType: "metal") + device = MTLCreateSystemDefaultDevice()! + queue = device.newCommandQueue() + let path = Bundle.main.pathForResource("Shaders", ofType: "metal") do { - let input = try String(contentsOfFile: path!, encoding: NSUTF8StringEncoding) - let library = try device!.newLibraryWithSource(input, options: nil) -// let library = try device!.newLibraryWithSource(shader, options: nil) - let kernel = library.newFunctionWithName("compute")! - cps = try device!.newComputePipelineStateWithFunction(kernel) + let input = try String(contentsOfFile: path!, encoding: String.Encoding.utf8) + let library = try device.newLibrary(withSource: input, options: nil) + let kernel = library.newFunction(withName: "compute")! + cps = try device.newComputePipelineState(with: kernel) } catch let e { Swift.print("\(e)") } } + + public func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {} + + public func draw(in view: MTKView) { + if let drawable = view.currentDrawable { + let commandBuffer = queue.commandBuffer() + let commandEncoder = commandBuffer.computeCommandEncoder() + commandEncoder.setComputePipelineState(cps) + commandEncoder.setTexture(drawable.texture, at: 0) + let threadGroupCount = MTLSizeMake(8, 8, 1) + let threadGroups = MTLSizeMake(drawable.texture.width / threadGroupCount.width, drawable.texture.height / threadGroupCount.height, 1) + commandEncoder.dispatchThreadgroups(threadGroups, threadsPerThreadgroup: threadGroupCount) + commandEncoder.endEncoding() + commandBuffer.present(drawable) + commandBuffer.commit() + } + } } diff --git a/ch11/chapter11.playground/playground.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate b/ch11/chapter11.playground/playground.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate index f4c9511657e57e18cf265a284e8735a79b65f256..81d391f703f4bec3a0f64a34640d4465e91c0139 100755 GIT binary patch literal 19188 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

NJk40smHjk6@kWR?l-=;quDjmY=(A@fQtJ&u)b$ z#FsgU0<01WH^{%K5)bnk8IK_5|5OkD4k8Z~zPeSyS9|jBHI9Fwe_tXhPZ#UqW9D%X z!~Pc};(2l)ZHll+j}MSeu?W}ws+yJZZFVPG2u#xpRHfeHquFfh#((3K2S zF;K%m9Rm#v%w(XM1-^&eOYS50lLyFy4M$-prTtY;w3BA#O4vkdOgDm*>Jmz+LE+XP+z zG`_pNS8Hs=6aLp6e0eM3KSG!Aof9@ybaLU^6aHlme(XPj--@K<8V5hlCg}L5{BdOz zo(94)=${7I3g} z5BzT`VKd&3G$1ORgRN~PUvL)Ma<41nua%sVaPajuLHmEEide}XRxVI-4lur4_&2TR zk4V?l)p&|Bo`Y;^ElWJJ*VeEknS*cnNAR0P>RrM#mBCaRg%7kF@lBtP@GYO+_>RwG z_`pq0TV)}0yn7*epeVy?VYw;;2qUa!R+3AF*A3>DOCbeZgp7&k-< zg&W%5romhbQOtX9)q#N>8Q6(|og1m%R38pf7Y26aApPmFTC1)M{nN9vZO4b5h}gApV78DYtTr zr|=!bMrr~zk(xvy2Iezx00RpcSlCECNlnJ2Ol9Ce1{SfT4Ej$=nSMU=_zi`N6t?v? z0N>KWXQ9nPd7gUtk(A7)=5W$|oPoAx=}y1YE&E{A0GFzpn&G@jH9Qi|LW(`w!zN>A z;E)zL-<&=7%tj6|4~tnr;U4`XSo=1$4zqRx14|g_U|BoVWzExXQdx5wit4pG_D-~3 zt(s7X??kIHoh|0Pg~HA8M;PJ`>H`e+Lk13KU?~fBgbVEPa@CZ1&u}(vGUzy<_?Au! z(7n_l4D^pa;xKgt13bpSG6t5j04q2rLEP?oeEGn7HFh*=qe{<0G-|Y-5I?29V9`8H zeMX(3K4)MR14l6s+l8}{`jR?}p?<}{8V1&~P)Gl#iZxRoR{s9NPH?dbJuu)p|p{OFh6) z|KRLtKtoQ?#xrn2v!0#0@*+AJ<E~u8CMlDeEu{eaXiqNFQFIK;<%fAAI+kw3@#JX+KGV#T z>EFBuuXJjL*yPseWLnAcB!y0;)97>tPGjJ644lru8I5!Xt-?IfFmNUVpJ#dU!hgz> zukL?;C9XSG6E%CaLxV5c6xHKEjx8%w(<0=ybT&(nmCm9cqjAaj5(8&3@MQ+hZlv4O zIhY_Ejps1%6_%h^|5Jj_4he6w+`@@OWnx`}D>-R)Hgs>gKkoF?edxY)KRTDJVBlN^ zzQMqG44jX9<%{TidH`KO7t%QHG%#=p1D7*!H3K(zRlc;1%feo_3Dkd@n7S)p&n(X) zTck@kIB&KVj%Nbx38$2U^HwY2cvZ@ta4I-B3v2@ApVIY*iq)vr^^-}+Z z*a8;Ob@W(lN(X4{T^bp<2pbd5<`%n@=27>&ajN;%gMc2-^mWNqqhYTi;lCa(lAcUI zhi`Y`tkr!>eGk})b658*_4cUk60D{(@V?LETk1#H+c6AW%5J?3=bl~ITQaVMcGmkB zbGTjb?QSjDwZZTqy3Ys>v%I97>lOu z{KIBTY5ah}Vm5ZsE2uN{s+RbLyHhxXt;JDnF};?48{fK5fZOSf41Alxx7FCkxn?kM zJ-cnIF5LeKw`aCZ;;X-Np{Ccdi5vdw$?f;(4>3a?deM#Eg>l-AdA)~$8(D@{V9!` zS2)kWJM3rRK?WZ2w#}xl6uu(x54uu+tnYr`XrP)oS&$!KSX%_Ey68 zE~+0@;k9((>87sKj@H8W^j)o}Q0b=5)Xsn2aCm5SO8-dT!N zy9~r_(vMNM{$toDLh^?@*o$=d($;0yVQ^f#r@Od5G^rR5@+fZ@JetR2;9dsqV{c+S z<(dre`d7V{`SXH)w=9_5`haU|JeynQ-Xx4C`rT|X54V`HcR0*$@^p-AdR)6H+z0nE z887yC%i6G;9Bta<$sMj`uE#jKJH|RnxQkDY>Z3dbFS)<#Fd0Go=y)W4*fSOAff+nT zULvoNck!dYfm9e3i68fkrrJ>P_+eiKuA7HaPF!Y9p`OBz@J^$q&@%S%jNaw4d4~>ig<&0HlCeV&O^MJyzRWBKEOxl)5gc*)6XZ@ z=Lw%NK4X3AeJ1!!@?m@?`%LwD+UHrH=X_@PH2N&|S?aUgXQj_-pS3>gd^Y&Jlg@$dTqKf*7>Pv{r!C-RH*i}H*1ll#T`DgDfT{ryV)rur@PTjRIa z@1);Fze|4K`d#(A=6A#I2fthXgg@oa^Y``l^AGS3@)!7r`WyWF`j`37^55#e*Z;Wx z=l&P{ulxV#|C9fN0Dgdfz>5KM16BsC57-v)QNX@{vjH~)VPIIGDo_)s3p4~~2ATuQ z0&4^70>=f84}3Q8<-oatZv@T@oFBM6aAn}ez!QO|1MdXEpr9a0P<&8gkRm80$QCp_ zXkyUhpx1&Lf(`~93%VDa7_1Gp1a}VZ8r(g&XK;S-pkRCOh~V(W+BP&Rv}YLAUq^IB0MHMAv`JkRQQ?jb{Gr`2nz}mgoTEMg++wLhQ);?ge8R~ zhoy$4hjj@n4x1MCYS@mjyY(TneZ>e&xM~4zZ?Er1V17)A}k^zLL4E9 zh>J*wNQy{~NR3F3FhsPA=pIoVQ57*ZqCR3m#H0u&Vp_!Xh?x;DM7$L7a>Tlb!x1+{ z{-Q8ZxJV?57bS_3MQI|XNG0kZ>MP0<<%?_>MBb7B2_c~*Jc(QqD~XdNNRlKfiC$uqm?RcSo+MvVAQ>nb zBymWFOGZe_BvU0%OP-ZHCz&C6UeYL8ELkd9E?FsAE!ia5CfP38A=xQ8EIB4QAvq;E zEjc5(EV(MVCiz}+Q*v8!FNznXiqc2fqJ~G!jG7g-Icj&*-l+XihoX)|9g8{>buQ|B z)P<;TqHaaqiMkv0n-oe(DJ}Jp`btBjGHIMNL7F5@lPaYusYYs%c9Hg!_LlaQ=1U8t z1EqtcRnl3~ccdRmk4TS6Pe@NnKb3wa{apI3^s4ll^oH~Y=`HDx(x0P)qOH+`qEYno z(F>wiN537tKKh;LccZsNABa93{dx44(O*S>9epwSM)YqoQbx;sWPF)G7AgyqMaaam zNLj2bRhB8U$gHw|@zp*?!qU*2iy_gS@XiUtS;|D7VS&@?yC|UMFYdtL0neyXAZ2`{jq^N98BvXXWSR7v-1b zSLD~^H)8x^q%o$LJ~34>V`FBl1Y71I#2C}wHQikMX~TVl4wY>)XM z7RCm}3SvWJ!(+>0$HvyjPQXus?`(6p&Cxc;+nkI`k2A-$jmwJ5j++!WJ#J>)3vsjJ z-;X~Ke<=P){PBd41X)5%LYsty#J-7-Cq9ulB+-%dV$$5CH~xduP9IyDIQnY6(x#ciV=!(MU}#-7_Atq7_XS5cv7)U zu~M-{u}-m3@vdU4V!Pr4#V*CiihYWMiX)2Sij#`diq92i6<;Z?E529URQ#Bno!l$A zPjbKH{>clHS0}GcUYEQv1*Qb02vR~*!czvPj7TXvMFU(%I=gsDf?5yQe#u& zQWH`YsTHa9sS{Esr9PRuFZERF>C`i+U#6v`8PiN@mb9$2r_yGn%}#qIZEo86v>RzZ zq}@vUDZPDq@ASUux#{`ouct3fU!J})eNFn0NzslJQo??u-)|zo}@IKozY@R3)p@R2eFb%A(3r zWvg;j9aWuGeN=_2p{hz%wW?NCr>a*?Q9Z4irkbvLUiG4CrRuoqD>Yvos*X~}tJP|= z+Ny4+&QW(#_g42)_g4>44^$6Qk5SK4uT-B*lhSKUE7T3qIdsEyBXt$JF}iWO3A#zTCv{VFGjy-%8gy%P@9MVbw&}L(cIfu%4(JZ+ zj_Qu z2Ez`+0mEs-dBa7+Wy4j&b;HkwyM}v)2S&n38Rf=K#ysPA<5c5JXp_JsG)0&qO;VHGlw!jFYl=x@(wU4VlPS+M*fi8sX&P^O&NRdHyy->L zEYob$E2h^>OHIp7t4wQ5>r5L=@0i{-Z83dlI$%0&x?s9wx?;L!`rdTQbl(ikl$mGt zHT#(Z%t>aI*<|iy&Nb(o3(bSfHuDg(!(45yHP@NPna7(ani=zC^Aht;^M3OQ^B3kT z<{!;Jn}0F?YQATFVDYmAT7oU1mN1LR5@~5;Nww%K*_Ixb-j;rr{+0quk!7f*)KX@t zv{YMaEn_TGEKgaUu{>uvWw~Ja#&X$mwXLyjhqj&Cc4^za?JI2?+b(XqwC#$vKU*m) z&+2RSx8_=(usW>6ts|{fR;P8ewaz-xI@LPU`iiyDy3D%Ly2iS}y2-l5y3P8L^^o<9 z^_=x<>o?Y`*6Y?EthcPcW%09uvO==LvLdsjS@NvdtduNmR=cc@SzWTaXZ6X-&C1Uz b$g*cSv+A-Yy6O%<5ZpU2g?o4Z%|ibJ!C^}% literal 18466 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 w?X>N-9kLy@eP%mpJ7YU*`^I*`cC}|j�bae?0&Qg8NJV!2J#U?iv6809+NU3IG5A diff --git a/ch11/chapter11.playground/timeline.xctimeline b/ch11/chapter11.playground/timeline.xctimeline deleted file mode 100644 index bf468af..0000000 --- a/ch11/chapter11.playground/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - diff --git a/ch12/chapter12.playground/Contents.swift b/ch12/chapter12.playground/Contents.swift index 9faf781..939e603 100644 --- a/ch12/chapter12.playground/Contents.swift +++ b/ch12/chapter12.playground/Contents.swift @@ -1,8 +1,8 @@ -import Cocoa -import XCPlayground +import MetalKit +import PlaygroundSupport let device = MTLCreateSystemDefaultDevice()! -let frame = NSRect(x:0, y:0, width:300, height:300) -let metalView = MetalView(frame: frame, device: device) -XCPlaygroundPage.currentPage.liveView = metalView +let frame = NSRect(x: 0, y: 0, width: 400, height: 400) +let view = MetalView(frame: frame, device: device) +PlaygroundPage.current.liveView = view diff --git a/ch12/chapter12.playground/Sources/MetalView.swift b/ch12/chapter12.playground/Sources/MetalView.swift index 37c8100..9cc48fd 100755 --- a/ch12/chapter12.playground/Sources/MetalView.swift +++ b/ch12/chapter12.playground/Sources/MetalView.swift @@ -10,8 +10,8 @@ public class MetalView: MTKView, NSWindowDelegate { var mouseBuffer: MTLBuffer! var pos: NSPoint! - override public func mouseDown(event: NSEvent) { - pos = convertPointToLayer(convertPoint(event.locationInWindow, fromView: nil)) + override public func mouseDown(_ event: NSEvent) { + pos = convertToLayer(convert(event.locationInWindow, from: nil)) let scale = layer!.contentsScale pos.x *= scale pos.y *= scale @@ -26,21 +26,21 @@ public class MetalView: MTKView, NSWindowDelegate { registerShaders() } - override public func drawRect(dirtyRect: NSRect) { - super.drawRect(dirtyRect) + override public func draw(_ dirtyRect: NSRect) { + super.draw(dirtyRect) if let drawable = currentDrawable { let commandBuffer = queue.commandBuffer() let commandEncoder = commandBuffer.computeCommandEncoder() commandEncoder.setComputePipelineState(cps) - commandEncoder.setTexture(drawable.texture, atIndex: 0) - commandEncoder.setBuffer(mouseBuffer, offset: 0, atIndex: 2) - commandEncoder.setBuffer(timerBuffer, offset: 0, atIndex: 1) + commandEncoder.setTexture(drawable.texture, at: 0) + commandEncoder.setBuffer(mouseBuffer, offset: 0, at: 2) + commandEncoder.setBuffer(timerBuffer, offset: 0, at: 1) update() let threadGroupCount = MTLSizeMake(8, 8, 1) let threadGroups = MTLSizeMake(drawable.texture.width / threadGroupCount.width, drawable.texture.height / threadGroupCount.height, 1) commandEncoder.dispatchThreadgroups(threadGroups, threadsPerThreadgroup: threadGroupCount) commandEncoder.endEncoding() - commandBuffer.presentDrawable(drawable) + commandBuffer.present(drawable) commandBuffer.commit() } @@ -49,23 +49,23 @@ public class MetalView: MTKView, NSWindowDelegate { func update() { timer += 0.01 var bufferPointer = timerBuffer.contents() - memcpy(bufferPointer, &timer, sizeof(Float)) + memcpy(bufferPointer, &timer, sizeof(Float.self)) bufferPointer = mouseBuffer.contents() - memcpy(bufferPointer, &pos, sizeof(NSPoint)) + memcpy(bufferPointer, &pos, sizeof(NSPoint.self)) } func registerShaders() { queue = device!.newCommandQueue() - let path = NSBundle.mainBundle().pathForResource("Shaders", ofType: "metal") + let path = Bundle.main.pathForResource("Shaders", ofType: "metal") do { - let input = try String(contentsOfFile: path!, encoding: NSUTF8StringEncoding) - let library = try device!.newLibraryWithSource(input, options: nil) - let kernel = library.newFunctionWithName("compute")! - cps = try device!.newComputePipelineStateWithFunction(kernel) + let input = try String(contentsOfFile: path!, encoding: String.Encoding.utf8) + let library = try device!.newLibrary(withSource: input, options: nil) + let kernel = library.newFunction(withName: "compute")! + cps = try device!.newComputePipelineState(with: kernel) } catch let e { Swift.print("\(e)") } - timerBuffer = device!.newBufferWithLength(sizeof(Float), options: []) - mouseBuffer = device!.newBufferWithLength(sizeof(NSPoint), options: []) + timerBuffer = device!.newBuffer(withLength: sizeof(Float.self), options: []) + mouseBuffer = device!.newBuffer(withLength: sizeof(NSPoint.self), options: []) } } diff --git a/ch12/chapter12.playground/playground.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate b/ch12/chapter12.playground/playground.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate index 746466e82019d519fd70aecdb7dddfa1aea64aae..844b8dfe10bbd70136d17174387ebdecb7d81c11 100755 GIT binary patch literal 22543 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 diff --git a/ch13/chapter13.playground/Contents.swift b/ch13/chapter13.playground/Contents.swift index 366d424..feabd6e 100644 --- a/ch13/chapter13.playground/Contents.swift +++ b/ch13/chapter13.playground/Contents.swift @@ -1,8 +1,8 @@ -import Cocoa -import XCPlayground +import MetalKit +import PlaygroundSupport let device = MTLCreateSystemDefaultDevice()! let frame = NSRect(x:0, y:0, width:400, height:400) let view = MetalView(frame: frame, device: device) -XCPlaygroundPage.currentPage.liveView = view +PlaygroundPage.current.liveView = view diff --git a/ch13/chapter13.playground/Sources/MetalView.swift b/ch13/chapter13.playground/Sources/MetalView.swift index 7120f0b..2a6bdcb 100755 --- a/ch13/chapter13.playground/Sources/MetalView.swift +++ b/ch13/chapter13.playground/Sources/MetalView.swift @@ -10,8 +10,8 @@ public class MetalView: MTKView, NSWindowDelegate { var mouseBuffer: MTLBuffer! var pos: NSPoint! - override public func mouseDown(event: NSEvent) { - pos = convertPointToLayer(convertPoint(event.locationInWindow, fromView: nil)) + override public func mouseDown(_ event: NSEvent) { + pos = convertToLayer(convert(event.locationInWindow, from: nil)) let scale = layer!.contentsScale pos.x *= scale pos.y *= scale @@ -26,20 +26,20 @@ public class MetalView: MTKView, NSWindowDelegate { registerShaders() } - override public func drawRect(dirtyRect: NSRect) { + override public func draw(_ dirtyRect: NSRect) { if let drawable = currentDrawable { let commandBuffer = queue.commandBuffer() let commandEncoder = commandBuffer.computeCommandEncoder() commandEncoder.setComputePipelineState(cps) - commandEncoder.setTexture(drawable.texture, atIndex: 0) - commandEncoder.setBuffer(mouseBuffer, offset: 0, atIndex: 2) - commandEncoder.setBuffer(timerBuffer, offset: 0, atIndex: 1) + commandEncoder.setTexture(drawable.texture, at: 0) + commandEncoder.setBuffer(mouseBuffer, offset: 0, at: 2) + commandEncoder.setBuffer(timerBuffer, offset: 0, at: 1) update() let threadGroupCount = MTLSizeMake(8, 8, 1) let threadGroups = MTLSizeMake(drawable.texture.width / threadGroupCount.width, drawable.texture.height / threadGroupCount.height, 1) commandEncoder.dispatchThreadgroups(threadGroups, threadsPerThreadgroup: threadGroupCount) commandEncoder.endEncoding() - commandBuffer.presentDrawable(drawable) + commandBuffer.present(drawable) commandBuffer.commit() } @@ -48,23 +48,23 @@ public class MetalView: MTKView, NSWindowDelegate { func update() { timer += 0.01 var bufferPointer = timerBuffer.contents() - memcpy(bufferPointer, &timer, sizeof(Float)) + memcpy(bufferPointer, &timer, sizeof(Float.self)) bufferPointer = mouseBuffer.contents() - memcpy(bufferPointer, &pos, sizeof(NSPoint)) + memcpy(bufferPointer, &pos, sizeof(NSPoint.self)) } func registerShaders() { queue = device!.newCommandQueue() - let path = NSBundle.mainBundle().pathForResource("Shaders", ofType: "metal") + let path = Bundle.main.pathForResource("Shaders", ofType: "metal") do { - let input = try String(contentsOfFile: path!, encoding: NSUTF8StringEncoding) - let library = try device!.newLibraryWithSource(input, options: nil) - let kernel = library.newFunctionWithName("compute")! - cps = try device!.newComputePipelineStateWithFunction(kernel) + let input = try String(contentsOfFile: path!, encoding: String.Encoding.utf8) + let library = try device!.newLibrary(withSource: input, options: nil) + let kernel = library.newFunction(withName: "compute")! + cps = try device!.newComputePipelineState(with: kernel) } catch let e { Swift.print("\(e)") } - timerBuffer = device!.newBufferWithLength(sizeof(Float), options: []) - mouseBuffer = device!.newBufferWithLength(sizeof(NSPoint), options: []) + timerBuffer = device!.newBuffer(withLength: sizeof(Float.self), options: []) + mouseBuffer = device!.newBuffer(withLength: sizeof(NSPoint.self), options: []) } } diff --git a/ch13/chapter13.playground/playground.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate b/ch13/chapter13.playground/playground.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate index ac9ca7b310403cea8b2ab3ba0332c49ce6191ba9..4c407cd41a5826e0cbbe29c8acbad230d77c6d54 100755 GIT binary patch literal 20504 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 diff --git a/ch14/chapter14.playground/Contents.swift b/ch14/chapter14.playground/Contents.swift index 366d424..abfc392 100644 --- a/ch14/chapter14.playground/Contents.swift +++ b/ch14/chapter14.playground/Contents.swift @@ -1,8 +1,8 @@ import Cocoa -import XCPlayground +import PlaygroundSupport let device = MTLCreateSystemDefaultDevice()! let frame = NSRect(x:0, y:0, width:400, height:400) let view = MetalView(frame: frame, device: device) -XCPlaygroundPage.currentPage.liveView = view +PlaygroundPage.current.liveView = view diff --git a/ch14/chapter14.playground/Sources/MetalView.swift b/ch14/chapter14.playground/Sources/MetalView.swift index 7120f0b..2a6bdcb 100755 --- a/ch14/chapter14.playground/Sources/MetalView.swift +++ b/ch14/chapter14.playground/Sources/MetalView.swift @@ -10,8 +10,8 @@ public class MetalView: MTKView, NSWindowDelegate { var mouseBuffer: MTLBuffer! var pos: NSPoint! - override public func mouseDown(event: NSEvent) { - pos = convertPointToLayer(convertPoint(event.locationInWindow, fromView: nil)) + override public func mouseDown(_ event: NSEvent) { + pos = convertToLayer(convert(event.locationInWindow, from: nil)) let scale = layer!.contentsScale pos.x *= scale pos.y *= scale @@ -26,20 +26,20 @@ public class MetalView: MTKView, NSWindowDelegate { registerShaders() } - override public func drawRect(dirtyRect: NSRect) { + override public func draw(_ dirtyRect: NSRect) { if let drawable = currentDrawable { let commandBuffer = queue.commandBuffer() let commandEncoder = commandBuffer.computeCommandEncoder() commandEncoder.setComputePipelineState(cps) - commandEncoder.setTexture(drawable.texture, atIndex: 0) - commandEncoder.setBuffer(mouseBuffer, offset: 0, atIndex: 2) - commandEncoder.setBuffer(timerBuffer, offset: 0, atIndex: 1) + commandEncoder.setTexture(drawable.texture, at: 0) + commandEncoder.setBuffer(mouseBuffer, offset: 0, at: 2) + commandEncoder.setBuffer(timerBuffer, offset: 0, at: 1) update() let threadGroupCount = MTLSizeMake(8, 8, 1) let threadGroups = MTLSizeMake(drawable.texture.width / threadGroupCount.width, drawable.texture.height / threadGroupCount.height, 1) commandEncoder.dispatchThreadgroups(threadGroups, threadsPerThreadgroup: threadGroupCount) commandEncoder.endEncoding() - commandBuffer.presentDrawable(drawable) + commandBuffer.present(drawable) commandBuffer.commit() } @@ -48,23 +48,23 @@ public class MetalView: MTKView, NSWindowDelegate { func update() { timer += 0.01 var bufferPointer = timerBuffer.contents() - memcpy(bufferPointer, &timer, sizeof(Float)) + memcpy(bufferPointer, &timer, sizeof(Float.self)) bufferPointer = mouseBuffer.contents() - memcpy(bufferPointer, &pos, sizeof(NSPoint)) + memcpy(bufferPointer, &pos, sizeof(NSPoint.self)) } func registerShaders() { queue = device!.newCommandQueue() - let path = NSBundle.mainBundle().pathForResource("Shaders", ofType: "metal") + let path = Bundle.main.pathForResource("Shaders", ofType: "metal") do { - let input = try String(contentsOfFile: path!, encoding: NSUTF8StringEncoding) - let library = try device!.newLibraryWithSource(input, options: nil) - let kernel = library.newFunctionWithName("compute")! - cps = try device!.newComputePipelineStateWithFunction(kernel) + let input = try String(contentsOfFile: path!, encoding: String.Encoding.utf8) + let library = try device!.newLibrary(withSource: input, options: nil) + let kernel = library.newFunction(withName: "compute")! + cps = try device!.newComputePipelineState(with: kernel) } catch let e { Swift.print("\(e)") } - timerBuffer = device!.newBufferWithLength(sizeof(Float), options: []) - mouseBuffer = device!.newBufferWithLength(sizeof(NSPoint), options: []) + timerBuffer = device!.newBuffer(withLength: sizeof(Float.self), options: []) + mouseBuffer = device!.newBuffer(withLength: sizeof(NSPoint.self), options: []) } } diff --git a/ch14/chapter14.playground/playground.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate b/ch14/chapter14.playground/playground.xcworkspace/xcuserdata/marius.xcuserdatad/UserInterfaceState.xcuserstate index a9856822261d25930c0699cf4f4fafff5ecc34ab..bbb890a256454901db20e18468c9392999305a99 100755 GIT binary patch literal 22481 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 Z;;7=d;uJ?J3kZUL7Z~_==l|l={|DypZRr32 literal 21322 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 diff --git a/ch15/chapter15.playground/timeline.xctimeline b/ch15/chapter15.playground/timeline.xctimeline old mode 100755 new mode 100644