From bfd8328845b283344036fe70e20323901fb9be39 Mon Sep 17 00:00:00 2001 From: Joseph Lord Date: Wed, 20 Aug 2014 00:04:42 +0100 Subject: [PATCH 1/8] Capture self weakly in case the view controller is used in another context. --- ThreadsExperiment/ViewController.swift | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ThreadsExperiment/ViewController.swift b/ThreadsExperiment/ViewController.swift index 3580730..32e936f 100644 --- a/ThreadsExperiment/ViewController.swift +++ b/ThreadsExperiment/ViewController.swift @@ -108,13 +108,16 @@ class ViewController: UIViewController { let dataCopy = grayScottData let params = GrayScottParmeters(f: f, k: k, dU: dU, dV: dV) + weak var weakSelf = self dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)) { let newGSData = grayScottSolver(dataCopy, params) let newImage = renderGrayScott(newGSData) dispatch_async(dispatch_get_main_queue()) { - self.grayScottData = newGSData - self.imageView.image = newImage - self.dispatchSolverOperation() + if let s = weakSelf { + s.grayScottData = newGSData + s.imageView.image = newImage + s.dispatchSolverOperation() + } } } } From 27f469f67dfb532b2663968baf9dba77871992ec Mon Sep 17 00:00:00 2001 From: Joseph Lord Date: Thu, 21 Aug 2014 01:23:15 +0100 Subject: [PATCH 2/8] Not linking but it may not be these changes. --- ThreadsExperiment/GrayScottRenderer.swift | 84 ++++++++++++++++++- .../contents.xcplayground | 7 ++ .../section-1.swift | 47 +++++++++++ .../timeline.xctimeline | 6 ++ 4 files changed, 142 insertions(+), 2 deletions(-) create mode 100644 ThreadsExperimentTests/ImageCreationPlayground.playground/contents.xcplayground create mode 100644 ThreadsExperimentTests/ImageCreationPlayground.playground/section-1.swift create mode 100644 ThreadsExperimentTests/ImageCreationPlayground.playground/timeline.xctimeline diff --git a/ThreadsExperiment/GrayScottRenderer.swift b/ThreadsExperiment/GrayScottRenderer.swift index 68cb558..4aa6554 100644 --- a/ThreadsExperiment/GrayScottRenderer.swift +++ b/ThreadsExperiment/GrayScottRenderer.swift @@ -8,13 +8,93 @@ import Foundation import UIKit +/* +class RenderedGSImage : CIImage { + let grayScottData:[GrayScottStruct] + init(grayScottData:[GrayScottStruct]) { + self.grayScottData = grayScottData + } + required init(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + override func extent() -> CGRect { + return CGRect(x: 0, y: 0, width: Constants.LENGTH, height: Constants.LENGTH) + } + +} +*/ +/* +CGImageRef CreateImageFromARGB32Bitmap( +unsigned int height, +unsigned int width, +void *baseAddr, +unsigned int rowBytes) +{ +const size_t bitsPerComponent = 8; +const size_t bitsPerPixel = 32; +CGImageRef retVal = NULL; + +// Create a data provider. We pass in NULL for the info +// and the release procedure pointer. +CGDataProviderRef dataProvider = +CGDataProviderCreateWithData( +NULL, baseAddr, rowBytes * height, NULL); + +// Get our hands on the generic RGB color space. +CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateWithName( +kCGColorSpaceGenericRGB); +// Create an image +retVal = CGImageCreate( +width, height, bitsPerComponent, bitsPerPixel, +rowBytes, rgbColorSpace, kCGImageAlphaPremultipliedFirst, +dataProvider, NULL, true, kCGRenderingIntentDefault); + +// The data provider and color space now belong to the +// image so we can release them. +CGDataProviderRelease(dataProvider); +CGColorSpaceRelease(rgbColorSpace); + +return retVal; +} +*/ +struct PixelData { + var r:UInt8 + var g:UInt8 + var b:UInt8 + var a:UInt8 = 255 +} +func imageFromARGB32Bitmap(pixels:[PixelData], width:UInt, height:UInt)->UIImage { + let bitsPerComponent:UInt = 8 + let bitsPerPixel:UInt = 32 + var data = pixels // Copy to mutable [] + let providerRef = CGDataProviderCreateWithCFData(NSData(bytes: &data, length: data.count * sizeof(PixelData))) //NSData(bytes: &pixelArray, length: pixelArray.count * sizeof(PixelData)) + let rgbColorSpace = CGColorSpaceCreateDeviceRGB() + let bitmapInfo:CGBitmapInfo = CGBitmapInfo(CGImageAlphaInfo.PremultipliedFirst.toRaw()) + let cgim = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, width * UInt(sizeof(PixelData)), rgbColorSpace, bitmapInfo, providerRef, nil, true, kCGRenderingIntentDefault) + return UIImage(CGImage: cgim) +} func renderGrayScott(grayScottData:[GrayScottStruct])->UIImage { let startTime : CFAbsoluteTime = CFAbsoluteTimeGetCurrent(); + var pixelArray = [PixelData](count: Constants.LENGTH_SQUARED, repeatedValue: PixelData(r: 0, g: 0, b: 0, a: 255)) + for i in 0 ..< Constants.LENGTH + { + for j in 0 ..< Constants.LENGTH + { + let grayScottCell : GrayScottStruct = grayScottData[i * Constants.LENGTH + j] + let index = i * Constants.LENGTH + j + let u_I = UInt8(grayScottCell.u * 255) + pixelArray[index].r = u_I + pixelArray[index].g = u_I + pixelArray[index].b = UInt8(grayScottCell.v * 255) + } + } + let outputImage = imageFromARGB32Bitmap(pixelArray, UInt(Constants.LENGTH), UInt(Constants.LENGTH)) +/* UIGraphicsBeginImageContextWithOptions(CGSize(width: Constants.LENGTH, height: Constants.LENGTH), true, 1); let context = UIGraphicsGetCurrentContext(); @@ -32,8 +112,8 @@ func renderGrayScott(grayScottData:[GrayScottStruct])->UIImage let outputImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); - +*/ println(" R RENDER:" + NSString(format: "%.4f", CFAbsoluteTimeGetCurrent() - startTime)); - + return outputImage } diff --git a/ThreadsExperimentTests/ImageCreationPlayground.playground/contents.xcplayground b/ThreadsExperimentTests/ImageCreationPlayground.playground/contents.xcplayground new file mode 100644 index 0000000..8e39341 --- /dev/null +++ b/ThreadsExperimentTests/ImageCreationPlayground.playground/contents.xcplayground @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/ThreadsExperimentTests/ImageCreationPlayground.playground/section-1.swift b/ThreadsExperimentTests/ImageCreationPlayground.playground/section-1.swift new file mode 100644 index 0000000..44f3014 --- /dev/null +++ b/ThreadsExperimentTests/ImageCreationPlayground.playground/section-1.swift @@ -0,0 +1,47 @@ +// Playground - noun: a place where people can play + +import UIKit + +var str = "Hello, playground" + +/* +struct PixelData { + var r:UInt8 + var g:UInt8 + var b:UInt8 + var a:UInt8 +} + +var pixelArray = [PixelData](count: 160, repeatedValue: PixelData(r: 128, g: 128, b: 255, a: 254)) +var data = NSData(bytes: &pixelArray, length: pixelArray.count * sizeof(PixelData)) +//data.length +//let b:UnsafePointer = data.bytes. +//let bytes = UnsafeArray(start:data.bytes, length:data.length) +//let bytes = UnsafeBufferPointer(start:data.bytes, length:data.length) +//println(bytes) +*/ + +struct PixelData { + var r:UInt8 + var g:UInt8 + var b:UInt8 + var a:UInt8 = 255 +} + +UInt8(0.01 * 255) + +func imageFromARGB32Bitmap(pixels:[PixelData], width:UInt, height:UInt)->UIImage { + let bitsPerComponent:UInt = 8 + let bitsPerPixel:UInt = 32 + var data = pixels // Copy to mutable [] + let providerRef = CGDataProviderCreateWithCFData(NSData(bytes: &data, length: data.count * sizeof(PixelData))) //NSData(bytes: &pixelArray, length: pixelArray.count * sizeof(PixelData)) + let rgbColorSpace = CGColorSpaceCreateDeviceRGB() + let bitmapInfo:CGBitmapInfo = CGBitmapInfo(CGImageAlphaInfo.PremultipliedFirst.toRaw()) + let cgim = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, width * UInt(sizeof(PixelData)), rgbColorSpace, bitmapInfo, providerRef, nil, true, kCGRenderingIntentDefault) + return UIImage(CGImage: cgim) +} + +var pixelArray = [PixelData](count: 160, repeatedValue: PixelData(r: 128, g: 128, b: 255, a: 255)) +let image1 = imageFromARGB32Bitmap(pixelArray, 40, 40) + +//sizeof(pixelArray) \ No newline at end of file diff --git a/ThreadsExperimentTests/ImageCreationPlayground.playground/timeline.xctimeline b/ThreadsExperimentTests/ImageCreationPlayground.playground/timeline.xctimeline new file mode 100644 index 0000000..bf468af --- /dev/null +++ b/ThreadsExperimentTests/ImageCreationPlayground.playground/timeline.xctimeline @@ -0,0 +1,6 @@ + + + + + From 473bdd88bb56c33a8fb21abdf26f3995cfe93363 Mon Sep 17 00:00:00 2001 From: Joseph Lord Date: Thu, 21 Aug 2014 01:50:46 +0100 Subject: [PATCH 3/8] Fix pixel order (and colours). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Render down to 0.0013s on Retina iPad Mini (release build). I can’t build on Beta 6 currently but may be a local issue. --- ThreadsExperiment/GrayScottRenderer.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ThreadsExperiment/GrayScottRenderer.swift b/ThreadsExperiment/GrayScottRenderer.swift index 4aa6554..d5eab37 100644 --- a/ThreadsExperiment/GrayScottRenderer.swift +++ b/ThreadsExperiment/GrayScottRenderer.swift @@ -60,10 +60,10 @@ return retVal; } */ struct PixelData { + var a:UInt8 = 255 var r:UInt8 var g:UInt8 var b:UInt8 - var a:UInt8 = 255 } func imageFromARGB32Bitmap(pixels:[PixelData], width:UInt, height:UInt)->UIImage { let bitsPerComponent:UInt = 8 @@ -79,7 +79,7 @@ func imageFromARGB32Bitmap(pixels:[PixelData], width:UInt, height:UInt)->UIImage func renderGrayScott(grayScottData:[GrayScottStruct])->UIImage { let startTime : CFAbsoluteTime = CFAbsoluteTimeGetCurrent(); - var pixelArray = [PixelData](count: Constants.LENGTH_SQUARED, repeatedValue: PixelData(r: 0, g: 0, b: 0, a: 255)) + var pixelArray = [PixelData](count: Constants.LENGTH_SQUARED, repeatedValue: PixelData(a: 255, r:0, g: 0, b: 0)) for i in 0 ..< Constants.LENGTH { From f5d83316ac7aa1af1eae4873f4b91b0b794884b5 Mon Sep 17 00:00:00 2001 From: Joseph Lord Date: Thu, 21 Aug 2014 01:53:24 +0100 Subject: [PATCH 4/8] Tidy up comments in renderer. --- ThreadsExperiment/GrayScottRenderer.swift | 70 +---------------------- 1 file changed, 1 insertion(+), 69 deletions(-) diff --git a/ThreadsExperiment/GrayScottRenderer.swift b/ThreadsExperiment/GrayScottRenderer.swift index d5eab37..dca3bb2 100644 --- a/ThreadsExperiment/GrayScottRenderer.swift +++ b/ThreadsExperiment/GrayScottRenderer.swift @@ -8,57 +8,7 @@ import Foundation import UIKit -/* -class RenderedGSImage : CIImage { - let grayScottData:[GrayScottStruct] - init(grayScottData:[GrayScottStruct]) { - self.grayScottData = grayScottData - } - - required init(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - override func extent() -> CGRect { - return CGRect(x: 0, y: 0, width: Constants.LENGTH, height: Constants.LENGTH) - } - -} -*/ -/* -CGImageRef CreateImageFromARGB32Bitmap( -unsigned int height, -unsigned int width, -void *baseAddr, -unsigned int rowBytes) -{ -const size_t bitsPerComponent = 8; -const size_t bitsPerPixel = 32; - -CGImageRef retVal = NULL; - -// Create a data provider. We pass in NULL for the info -// and the release procedure pointer. -CGDataProviderRef dataProvider = -CGDataProviderCreateWithData( -NULL, baseAddr, rowBytes * height, NULL); - -// Get our hands on the generic RGB color space. -CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateWithName( -kCGColorSpaceGenericRGB); -// Create an image -retVal = CGImageCreate( -width, height, bitsPerComponent, bitsPerPixel, -rowBytes, rgbColorSpace, kCGImageAlphaPremultipliedFirst, -dataProvider, NULL, true, kCGRenderingIntentDefault); - -// The data provider and color space now belong to the -// image so we can release them. -CGDataProviderRelease(dataProvider); -CGColorSpaceRelease(rgbColorSpace); -return retVal; -} -*/ struct PixelData { var a:UInt8 = 255 var r:UInt8 @@ -94,25 +44,7 @@ func renderGrayScott(grayScottData:[GrayScottStruct])->UIImage } } let outputImage = imageFromARGB32Bitmap(pixelArray, UInt(Constants.LENGTH), UInt(Constants.LENGTH)) -/* - UIGraphicsBeginImageContextWithOptions(CGSize(width: Constants.LENGTH, height: Constants.LENGTH), true, 1); - let context = UIGraphicsGetCurrentContext(); - - for i in 0 ..< Constants.LENGTH - { - for j in 0 ..< Constants.LENGTH - { - let grayScottCell : GrayScottStruct = grayScottData[i * Constants.LENGTH + j] as GrayScottStruct; - - CGContextSetRGBFillColor (context, CGFloat(grayScottCell.u), CGFloat(grayScottCell.u), CGFloat(grayScottCell.v), 1); - CGContextFillRect (context, CGRectMake (CGFloat(i), CGFloat(j), 1, 1)); - } - } - - let outputImage = UIGraphicsGetImageFromCurrentImageContext(); - - UIGraphicsEndImageContext(); -*/ + println(" R RENDER:" + NSString(format: "%.4f", CFAbsoluteTimeGetCurrent() - startTime)); return outputImage From 905fcceb66f0c8d8f5ac81fa450851ca920bfa45 Mon Sep 17 00:00:00 2001 From: Joseph Lord Date: Thu, 21 Aug 2014 02:09:13 +0100 Subject: [PATCH 5/8] Remove unused protocol and a playground that didn't work too well. --- ThreadsExperiment.xcodeproj/project.pbxproj | 4 -- ThreadsExperiment/GrayScottProtocol.swift | 15 ------ .../contents.xcplayground | 7 --- .../section-1.swift | 47 ------------------- .../timeline.xctimeline | 6 --- 5 files changed, 79 deletions(-) delete mode 100644 ThreadsExperiment/GrayScottProtocol.swift delete mode 100644 ThreadsExperimentTests/ImageCreationPlayground.playground/contents.xcplayground delete mode 100644 ThreadsExperimentTests/ImageCreationPlayground.playground/section-1.swift delete mode 100644 ThreadsExperimentTests/ImageCreationPlayground.playground/timeline.xctimeline diff --git a/ThreadsExperiment.xcodeproj/project.pbxproj b/ThreadsExperiment.xcodeproj/project.pbxproj index 38d304f..09e22cd 100644 --- a/ThreadsExperiment.xcodeproj/project.pbxproj +++ b/ThreadsExperiment.xcodeproj/project.pbxproj @@ -9,7 +9,6 @@ /* Begin PBXBuildFile section */ 3E7AECD81997E5FE00EFC5EC /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E7AECD71997E5FE00EFC5EC /* Constants.swift */; }; 3EF4B99D1991EA37004FC621 /* GrayScottStruct.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EF4B99C1991EA37004FC621 /* GrayScottStruct.swift */; }; - 3EF4B99F1991ECAF004FC621 /* GrayScottProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EF4B99E1991ECAF004FC621 /* GrayScottProtocol.swift */; }; BE0E5C68198CA26700395741 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE0E5C67198CA26700395741 /* AppDelegate.swift */; }; BE0E5C6B198CA26700395741 /* ThreadsExperiment.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = BE0E5C69198CA26700395741 /* ThreadsExperiment.xcdatamodeld */; }; BE0E5C6D198CA26700395741 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE0E5C6C198CA26700395741 /* ViewController.swift */; }; @@ -35,7 +34,6 @@ /* Begin PBXFileReference section */ 3E7AECD71997E5FE00EFC5EC /* Constants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = ""; }; 3EF4B99C1991EA37004FC621 /* GrayScottStruct.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GrayScottStruct.swift; sourceTree = ""; }; - 3EF4B99E1991ECAF004FC621 /* GrayScottProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GrayScottProtocol.swift; sourceTree = ""; }; BE0E5C62198CA26700395741 /* ThreadsExperiment.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ThreadsExperiment.app; sourceTree = BUILT_PRODUCTS_DIR; }; BE0E5C66198CA26700395741 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; BE0E5C67198CA26700395741 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; @@ -82,7 +80,6 @@ isa = PBXGroup; children = ( 3EF4B99C1991EA37004FC621 /* GrayScottStruct.swift */, - 3EF4B99E1991ECAF004FC621 /* GrayScottProtocol.swift */, ); name = structs; sourceTree = ""; @@ -266,7 +263,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 3EF4B99F1991ECAF004FC621 /* GrayScottProtocol.swift in Sources */, BE0E5C6D198CA26700395741 /* ViewController.swift in Sources */, BE623418198DFE2100C0A592 /* GrayScottRenderer.swift in Sources */, BE67FA84198E55420009D31E /* IntExtension.swift in Sources */, diff --git a/ThreadsExperiment/GrayScottProtocol.swift b/ThreadsExperiment/GrayScottProtocol.swift deleted file mode 100644 index 0cea640..0000000 --- a/ThreadsExperiment/GrayScottProtocol.swift +++ /dev/null @@ -1,15 +0,0 @@ -// -// GrayScottProtocol.swift -// ThreadsExperiment -// -// Created by Simon Gladman on 06/08/2014. -// Copyright (c) 2014 Simon Gladman. All rights reserved. -// - -import Foundation - -@objc protocol GrayScottProtocol -{ - var u : Double {get set}; - var v : Double {get set}; -} \ No newline at end of file diff --git a/ThreadsExperimentTests/ImageCreationPlayground.playground/contents.xcplayground b/ThreadsExperimentTests/ImageCreationPlayground.playground/contents.xcplayground deleted file mode 100644 index 8e39341..0000000 --- a/ThreadsExperimentTests/ImageCreationPlayground.playground/contents.xcplayground +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/ThreadsExperimentTests/ImageCreationPlayground.playground/section-1.swift b/ThreadsExperimentTests/ImageCreationPlayground.playground/section-1.swift deleted file mode 100644 index 44f3014..0000000 --- a/ThreadsExperimentTests/ImageCreationPlayground.playground/section-1.swift +++ /dev/null @@ -1,47 +0,0 @@ -// Playground - noun: a place where people can play - -import UIKit - -var str = "Hello, playground" - -/* -struct PixelData { - var r:UInt8 - var g:UInt8 - var b:UInt8 - var a:UInt8 -} - -var pixelArray = [PixelData](count: 160, repeatedValue: PixelData(r: 128, g: 128, b: 255, a: 254)) -var data = NSData(bytes: &pixelArray, length: pixelArray.count * sizeof(PixelData)) -//data.length -//let b:UnsafePointer = data.bytes. -//let bytes = UnsafeArray(start:data.bytes, length:data.length) -//let bytes = UnsafeBufferPointer(start:data.bytes, length:data.length) -//println(bytes) -*/ - -struct PixelData { - var r:UInt8 - var g:UInt8 - var b:UInt8 - var a:UInt8 = 255 -} - -UInt8(0.01 * 255) - -func imageFromARGB32Bitmap(pixels:[PixelData], width:UInt, height:UInt)->UIImage { - let bitsPerComponent:UInt = 8 - let bitsPerPixel:UInt = 32 - var data = pixels // Copy to mutable [] - let providerRef = CGDataProviderCreateWithCFData(NSData(bytes: &data, length: data.count * sizeof(PixelData))) //NSData(bytes: &pixelArray, length: pixelArray.count * sizeof(PixelData)) - let rgbColorSpace = CGColorSpaceCreateDeviceRGB() - let bitmapInfo:CGBitmapInfo = CGBitmapInfo(CGImageAlphaInfo.PremultipliedFirst.toRaw()) - let cgim = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, width * UInt(sizeof(PixelData)), rgbColorSpace, bitmapInfo, providerRef, nil, true, kCGRenderingIntentDefault) - return UIImage(CGImage: cgim) -} - -var pixelArray = [PixelData](count: 160, repeatedValue: PixelData(r: 128, g: 128, b: 255, a: 255)) -let image1 = imageFromARGB32Bitmap(pixelArray, 40, 40) - -//sizeof(pixelArray) \ No newline at end of file diff --git a/ThreadsExperimentTests/ImageCreationPlayground.playground/timeline.xctimeline b/ThreadsExperimentTests/ImageCreationPlayground.playground/timeline.xctimeline deleted file mode 100644 index bf468af..0000000 --- a/ThreadsExperimentTests/ImageCreationPlayground.playground/timeline.xctimeline +++ /dev/null @@ -1,6 +0,0 @@ - - - - - From 82969994fabe123a7ebef9d6e600a10f5a4981b1 Mon Sep 17 00:00:00 2001 From: Joseph Lord Date: Thu, 21 Aug 2014 02:21:01 +0100 Subject: [PATCH 6/8] Pull out the constants needing calculation as private globals. --- ThreadsExperiment/GrayScottRenderer.swift | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/ThreadsExperiment/GrayScottRenderer.swift b/ThreadsExperiment/GrayScottRenderer.swift index dca3bb2..2dcaea2 100644 --- a/ThreadsExperiment/GrayScottRenderer.swift +++ b/ThreadsExperiment/GrayScottRenderer.swift @@ -15,13 +15,17 @@ struct PixelData { var g:UInt8 var b:UInt8 } -func imageFromARGB32Bitmap(pixels:[PixelData], width:UInt, height:UInt)->UIImage { + +private let rgbColorSpace = CGColorSpaceCreateDeviceRGB() +private let bitmapInfo:CGBitmapInfo = CGBitmapInfo(CGImageAlphaInfo.PremultipliedFirst.toRaw()) + +private func imageFromARGB32Bitmap(pixels:[PixelData], width:UInt, height:UInt)->UIImage { let bitsPerComponent:UInt = 8 let bitsPerPixel:UInt = 32 + var data = pixels // Copy to mutable [] - let providerRef = CGDataProviderCreateWithCFData(NSData(bytes: &data, length: data.count * sizeof(PixelData))) //NSData(bytes: &pixelArray, length: pixelArray.count * sizeof(PixelData)) - let rgbColorSpace = CGColorSpaceCreateDeviceRGB() - let bitmapInfo:CGBitmapInfo = CGBitmapInfo(CGImageAlphaInfo.PremultipliedFirst.toRaw()) + let providerRef = CGDataProviderCreateWithCFData(NSData(bytes: &data, length: data.count * sizeof(PixelData))) + let cgim = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, width * UInt(sizeof(PixelData)), rgbColorSpace, bitmapInfo, providerRef, nil, true, kCGRenderingIntentDefault) return UIImage(CGImage: cgim) } From aa8385e78ed977f64bc8af1056896ae1e5dfff26 Mon Sep 17 00:00:00 2001 From: Joseph Lord Date: Thu, 21 Aug 2014 03:56:49 +0100 Subject: [PATCH 7/8] Timing improvements Sample solver and renderer timing. Count frames per second. --- ThreadsExperiment/GrayScottRenderer.swift | 14 ++++++++++---- ThreadsExperiment/GrayScottSolver.swift | 15 ++++++++++----- ThreadsExperiment/ViewController.swift | 9 ++++++++- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/ThreadsExperiment/GrayScottRenderer.swift b/ThreadsExperiment/GrayScottRenderer.swift index 2dcaea2..879c561 100644 --- a/ThreadsExperiment/GrayScottRenderer.swift +++ b/ThreadsExperiment/GrayScottRenderer.swift @@ -30,9 +30,14 @@ private func imageFromARGB32Bitmap(pixels:[PixelData], width:UInt, height:UInt)- return UIImage(CGImage: cgim) } +private var statsCount = 0 func renderGrayScott(grayScottData:[GrayScottStruct])->UIImage { - let startTime : CFAbsoluteTime = CFAbsoluteTimeGetCurrent(); + let stats = statsCount % 1024 == 0 + var startTime : CFAbsoluteTime? + if stats { + startTime = CFAbsoluteTimeGetCurrent(); + } var pixelArray = [PixelData](count: Constants.LENGTH_SQUARED, repeatedValue: PixelData(a: 255, r:0, g: 0, b: 0)) for i in 0 ..< Constants.LENGTH @@ -48,8 +53,9 @@ func renderGrayScott(grayScottData:[GrayScottStruct])->UIImage } } let outputImage = imageFromARGB32Bitmap(pixelArray, UInt(Constants.LENGTH), UInt(Constants.LENGTH)) - - println(" R RENDER:" + NSString(format: "%.4f", CFAbsoluteTimeGetCurrent() - startTime)); - + if stats { + println(" R RENDER:" + NSString(format: "%.4f", CFAbsoluteTimeGetCurrent() - startTime!)); + } + ++statsCount return outputImage } diff --git a/ThreadsExperiment/GrayScottSolver.swift b/ThreadsExperiment/GrayScottSolver.swift index 2f98f9f..7101885 100644 --- a/ThreadsExperiment/GrayScottSolver.swift +++ b/ThreadsExperiment/GrayScottSolver.swift @@ -21,9 +21,13 @@ struct GrayScottParmeters { var dV : Double } - +private var solverstatsCount = 0 func grayScottSolver(grayScottConstData: [GrayScottStruct], parameters:GrayScottParmeters)->[GrayScottStruct] { - let startTime : CFAbsoluteTime = CFAbsoluteTimeGetCurrent(); + let stats = solverstatsCount % 1024 == 0 + var startTime : CFAbsoluteTime? + if stats { + startTime = CFAbsoluteTimeGetCurrent(); + } var index : Int = 0; var outputArray = grayScottConstData // Copy to get array big enough @@ -52,8 +56,9 @@ func grayScottSolver(grayScottConstData: [GrayScottStruct], parameters:GrayScott } } - - println("S SOLVER:" + NSString(format: "%.4f", CFAbsoluteTimeGetCurrent() - startTime)); - + if stats { + println("S SOLVER:" + NSString(format: "%.4f", CFAbsoluteTimeGetCurrent() - startTime!)); + } + ++solverstatsCount return outputArray } diff --git a/ThreadsExperiment/ViewController.swift b/ThreadsExperiment/ViewController.swift index 32e936f..c71ccbb 100644 --- a/ThreadsExperiment/ViewController.swift +++ b/ThreadsExperiment/ViewController.swift @@ -103,7 +103,8 @@ class ViewController: UIViewController } } - + private var lastFrameCountTime = NSDate() + private var frameCount = 0 private func dispatchSolverOperation() { let dataCopy = grayScottData @@ -117,6 +118,12 @@ class ViewController: UIViewController s.grayScottData = newGSData s.imageView.image = newImage s.dispatchSolverOperation() + if s.lastFrameCountTime.timeIntervalSinceNow < -1.0 { + println("Frame count = \(s.frameCount)") + s.frameCount = 0 + s.lastFrameCountTime = NSDate() + } + ++s.frameCount } } } From 85a455393ed5defb7ec9a1f4c1250f90d272615b Mon Sep 17 00:00:00 2001 From: Joseph Lord Date: Thu, 21 Aug 2014 04:00:46 +0100 Subject: [PATCH 8/8] 62 fps by doing 13 solves/render. On retina iPad Mini as example. Just to show how fast this is now. --- ThreadsExperiment/ViewController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ThreadsExperiment/ViewController.swift b/ThreadsExperiment/ViewController.swift index c71ccbb..5fe2f49 100644 --- a/ThreadsExperiment/ViewController.swift +++ b/ThreadsExperiment/ViewController.swift @@ -111,7 +111,7 @@ class ViewController: UIViewController let params = GrayScottParmeters(f: f, k: k, dU: dU, dV: dV) weak var weakSelf = self dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)) { - let newGSData = grayScottSolver(dataCopy, params) + let newGSData = grayScottSolver(grayScottSolver(grayScottSolver(grayScottSolver(grayScottSolver(grayScottSolver(grayScottSolver(grayScottSolver(grayScottSolver(grayScottSolver(grayScottSolver(grayScottSolver(grayScottSolver(dataCopy, params), params), params), params), params), params), params), params), params), params), params), params), params) let newImage = renderGrayScott(newGSData) dispatch_async(dispatch_get_main_queue()) { if let s = weakSelf {