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/ThreadsExperiment/GrayScottRenderer.swift b/ThreadsExperiment/GrayScottRenderer.swift index 68cb558..879c561 100644 --- a/ThreadsExperiment/GrayScottRenderer.swift +++ b/ThreadsExperiment/GrayScottRenderer.swift @@ -9,31 +9,53 @@ import Foundation import UIKit +struct PixelData { + var a:UInt8 = 255 + var r:UInt8 + var g:UInt8 + var b:UInt8 +} + +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))) + let cgim = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, width * UInt(sizeof(PixelData)), rgbColorSpace, bitmapInfo, providerRef, nil, true, kCGRenderingIntentDefault) + return UIImage(CGImage: cgim) +} +private var statsCount = 0 func renderGrayScott(grayScottData:[GrayScottStruct])->UIImage { - let startTime : CFAbsoluteTime = CFAbsoluteTimeGetCurrent(); - - UIGraphicsBeginImageContextWithOptions(CGSize(width: Constants.LENGTH, height: Constants.LENGTH), true, 1); - let context = UIGraphicsGetCurrentContext(); + 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 { 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 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 = UIGraphicsGetImageFromCurrentImageContext(); - - UIGraphicsEndImageContext(); - - println(" R RENDER:" + NSString(format: "%.4f", CFAbsoluteTimeGetCurrent() - startTime)); - + let outputImage = imageFromARGB32Bitmap(pixelArray, UInt(Constants.LENGTH), UInt(Constants.LENGTH)) + 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 3580730..5fe2f49 100644 --- a/ThreadsExperiment/ViewController.swift +++ b/ThreadsExperiment/ViewController.swift @@ -103,18 +103,28 @@ class ViewController: UIViewController } } - + private var lastFrameCountTime = NSDate() + private var frameCount = 0 private func dispatchSolverOperation() { 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 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()) { - self.grayScottData = newGSData - self.imageView.image = newImage - self.dispatchSolverOperation() + if let s = weakSelf { + 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 + } } } }