git.iko.soy/metal-metaballs
on master help sign in
Updated the imageBuffer to avoid reallocation.
4b04dcdvinivendra
PixelImage.xcodeproj/project.xcworkspace/xcuserdata/vini.xcuserdatad/UserInterfaceState.xcuserstate

Binary file not shown.

PixelImage.xcodeproj/xcuserdata/vini.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist+3−3
@@ -10,11 +10,11 @@
10 ignoreCount = "0"
10 ignoreCount = "0"
11 continueAfterRunningActions = "No"
11 continueAfterRunningActions = "No"
12 filePath = "PixelImage/MetalMetaballRenderer.swift"
12 filePath = "PixelImage/MetalMetaballRenderer.swift"
13− timestampString = "476822048.152874"
13+ timestampString = "476822764.315769"
14 startingColumnNumber = "9223372036854775807"
14 startingColumnNumber = "9223372036854775807"
15 endingColumnNumber = "9223372036854775807"
15 endingColumnNumber = "9223372036854775807"
16− startingLineNumber = "77"
16+ startingLineNumber = "84"
17− endingLineNumber = "77"
17+ endingLineNumber = "84"
18 landmarkName = "updateTargetView()"
18 landmarkName = "updateTargetView()"
19 landmarkType = "5">
19 landmarkType = "5">
20 </BreakpointContent>
20 </BreakpointContent>
PixelImage/MetalMetaballRenderer.swift+32−15
@@ -21,9 +21,11 @@ class MetalMetaballRenderer: MetaballRenderer {
21 typealias TargetView = UIImageView
21 typealias TargetView = UIImageView
22
22
23 let targetView = TargetView()
23 let targetView = TargetView()
24+ var previousFrame = CGRect.zero
24
25
25 let context = MTLContext()
26 let context = MTLContext()
26− var internalTexture: MTLTexture!
27+ var renderingTexture: MTLTexture!
28+ var imageBuffer: UnsafeMutablePointer<Void>!
27
29
28 let dataSource: MetaballDataSource
30 let dataSource: MetaballDataSource
29
31
@@ -34,14 +36,19 @@ class MetalMetaballRenderer: MetaballRenderer {
34 func updateTargetView() {
36 func updateTargetView() {
35 let metaballs = dataSource.metaballs
37 let metaballs = dataSource.metaballs
36
38
39+ if previousFrame != targetView.frame {
40+ previousFrame = targetView.frame
41+ updateFrame()
42+ }
43+
37 let width = Int(targetView.width)
44 let width = Int(targetView.width)
38 let height = Int(targetView.height)
45 let height = Int(targetView.height)
39
46
40− if internalTexture == nil {
47+ if renderingTexture == nil {
41 let textureDescriptor =
48 let textureDescriptor =
42 MTLTextureDescriptor.texture2DDescriptorWithPixelFormat(.BGRA8Unorm, width: width, height: height, mipmapped: false)
49 MTLTextureDescriptor.texture2DDescriptorWithPixelFormat(.BGRA8Unorm, width: width, height: height, mipmapped: false)
43
50
44− internalTexture = context.device.newTextureWithDescriptor(textureDescriptor)
51+ renderingTexture = context.device.newTextureWithDescriptor(textureDescriptor)
45 }
52 }
46
53
47 let kernelFunction: MTLFunction?
54 let kernelFunction: MTLFunction?
@@ -64,7 +71,7 @@ class MetalMetaballRenderer: MetaballRenderer {
64
71
65 let commandEncoder = commandBuffer.computeCommandEncoder()
72 let commandEncoder = commandBuffer.computeCommandEncoder()
66 commandEncoder.setComputePipelineState(pipeline)
73 commandEncoder.setComputePipelineState(pipeline)
67− commandEncoder.setTexture(internalTexture, atIndex: 0)
74+ commandEncoder.setTexture(renderingTexture, atIndex: 0)
68 commandEncoder.setTexture(metaballInfoTexture, atIndex: 1)
75 commandEncoder.setTexture(metaballInfoTexture, atIndex: 1)
69 commandEncoder.dispatchThreadgroups(threadGroups,
76 commandEncoder.dispatchThreadgroups(threadGroups,
70 threadsPerThreadgroup: threadGroupCounts)
77 threadsPerThreadgroup: threadGroupCounts)
@@ -77,28 +84,27 @@ class MetalMetaballRenderer: MetaballRenderer {
77 print("Error!")
84 print("Error!")
78 }
85 }
79
86
80− targetView.image = image(texture: internalTexture)
87+ targetView.image = image(texture: renderingTexture)
81 }
88 }
82
89
83 func image(texture texture: MTLTexture) -> UIImage {
90 func image(texture texture: MTLTexture) -> UIImage {
84 let imageSize = CGSizeMake(CGFloat(texture.width),
91 let imageSize = CGSizeMake(CGFloat(texture.width),
85 CGFloat(texture.height))
92 CGFloat(texture.height))
86−
87 let width = Int(imageSize.width)
93 let width = Int(imageSize.width)
88 let height = Int(imageSize.height)
94 let height = Int(imageSize.height)
89−
90 let imageByteCount = width * height * 4
95 let imageByteCount = width * height * 4
96+
97+ if imageBuffer == nil {
91− let imageBytes = malloc(imageByteCount)
98+ imageBuffer = malloc(imageByteCount)
99+ }
100+
92 let bytesPerRow = width * 4
101 let bytesPerRow = width * 4
93 let region = MTLRegionMake2D(0, 0, width, height)
102 let region = MTLRegionMake2D(0, 0, width, height)
94− texture.getBytes(imageBytes, bytesPerRow: bytesPerRow,
103+ texture.getBytes(imageBuffer, bytesPerRow: bytesPerRow,
95 fromRegion: region, mipmapLevel: 0)
104 fromRegion: region, mipmapLevel: 0)
96
105
97− let provider = CGDataProviderCreateWithData(nil, imageBytes,
106+ let provider = CGDataProviderCreateWithData(nil, imageBuffer,
98− imageByteCount) {
107+ imageByteCount, nil)
99− (_, data, _) -> Void in
100− free(UnsafeMutablePointer<Void>(data))
101− }
102
108
103 let bitsPerComponent = 8
109 let bitsPerComponent = 8
104 let bitsperPixel = 32
110 let bitsperPixel = 32
@@ -138,6 +144,17 @@ class MetalMetaballRenderer: MetaballRenderer {
138
144
139 return texture
145 return texture
140 }
146 }
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+
142}
159}
143
160