@@ -21,9 +21,11 @@ class MetalMetaballRenderer: MetaballRenderer {
2121 typealias TargetView = UIImageView
2222
2323 let targetView = TargetView()
24+ var previousFrame = CGRect.zero
2425
2526 let context = MTLContext()
26− var internalTexture: MTLTexture!
27+ var renderingTexture: MTLTexture!
28+ var imageBuffer: UnsafeMutablePointer<Void>!
2729
2830 let dataSource: MetaballDataSource
2931
@@ -34,14 +36,19 @@ class MetalMetaballRenderer: MetaballRenderer {
3436 func updateTargetView() {
3537 let metaballs = dataSource.metaballs
3638
39+ if previousFrame != targetView.frame {
40+ previousFrame = targetView.frame
41+ updateFrame()
42+ }
43+
3744 let width = Int(targetView.width)
3845 let height = Int(targetView.height)
3946
40− if internalTexture == nil {
47+ if renderingTexture == nil {
4148 let textureDescriptor =
4249 MTLTextureDescriptor.texture2DDescriptorWithPixelFormat(.BGRA8Unorm, width: width, height: height, mipmapped: false)
4350
44− internalTexture = context.device.newTextureWithDescriptor(textureDescriptor)
51+ renderingTexture = context.device.newTextureWithDescriptor(textureDescriptor)
4552 }
4653
4754 let kernelFunction: MTLFunction?
@@ -64,7 +71,7 @@ class MetalMetaballRenderer: MetaballRenderer {
6471
6572 let commandEncoder = commandBuffer.computeCommandEncoder()
6673 commandEncoder.setComputePipelineState(pipeline)
67− commandEncoder.setTexture(internalTexture, atIndex: 0)
74+ commandEncoder.setTexture(renderingTexture, atIndex: 0)
6875 commandEncoder.setTexture(metaballInfoTexture, atIndex: 1)
6976 commandEncoder.dispatchThreadgroups(threadGroups,
7077 threadsPerThreadgroup: threadGroupCounts)
@@ -77,28 +84,27 @@ class MetalMetaballRenderer: MetaballRenderer {
7784 print("Error!")
7885 }
7986
80− targetView.image = image(texture: internalTexture)
87+ targetView.image = image(texture: renderingTexture)
8188 }
8289
8390 func image(texture texture: MTLTexture) -> UIImage {
8491 let imageSize = CGSizeMake(CGFloat(texture.width),
8592 CGFloat(texture.height))
86−
8793 let width = Int(imageSize.width)
8894 let height = Int(imageSize.height)
89−
9095 let imageByteCount = width * height * 4
91− let imageBytes = malloc(imageByteCount)
96+
97+ if imageBuffer == nil {
98+ imageBuffer = malloc(imageByteCount)
99+ }
100+
92101 let bytesPerRow = width * 4
93102 let region = MTLRegionMake2D(0, 0, width, height)
94− texture.getBytes(imageBytes, bytesPerRow: bytesPerRow,
103+ texture.getBytes(imageBuffer, bytesPerRow: bytesPerRow,
95104 fromRegion: region, mipmapLevel: 0)
96105
97− let provider = CGDataProviderCreateWithData(nil, imageBytes,
98− imageByteCount) {
99− (_, data, _) -> Void in
100− free(UnsafeMutablePointer<Void>(data))
101− }
106+ let provider = CGDataProviderCreateWithData(nil, imageBuffer,
107+ imageByteCount, nil)
102108
103109 let bitsPerComponent = 8
104110 let bitsperPixel = 32
@@ -138,6 +144,17 @@ class MetalMetaballRenderer: MetaballRenderer {
138144
139145 return texture
140146 }
141−
147+
148+ func updateFrame() {
149+ if imageBuffer != nil {
150+ free(imageBuffer)
151+ }
152+ imageBuffer = nil
153+ }
154+
155+ deinit {
156+ free(imageBuffer)
157+ }
158+
142159}
143160