git.iko.soy/metal-metaballs
on master help sign in
Refactored resources into the MTLComputeContext class; removed frame updates for simplicity while development is still going on.
commit308619059f0969c752e9c29432507135885c5af1 authorvinivendra <vinivendra@gmail.com> dateWed 10 Feb 2016, 20:52 (11 years ago) parentaee469b
2 files changed+40−28
PixelImage/Metal.swift+30 PixelImage/MetalMetaballRenderer.swift+10−28
PixelImage/Metal.swift+30
@@ -1,4 +1,5 @@
11import Metal
2+import UIKit
23
34class MTLContext {
45 let device: MTLDevice
@@ -11,3 +12,32 @@ class MTLContext {
1112 self.commandQueue = device.newCommandQueue()
1213 }
1314}
15+
16+class MTLComputeContext {
17+ var texture: MTLTexture
18+ var imageBuffer: UnsafeMutablePointer<Void>
19+
20+ init(size: CGSize, texture: MTLTexture) {
21+ let width = Int(size.width)
22+ let height = Int(size.height)
23+ let imageByteCount = width * height * 4
24+ imageBuffer = malloc(imageByteCount)
25+
26+ self.texture = texture
27+ }
28+
29+ func updateToSize(size: CGSize, texture: MTLTexture) {
30+ free(imageBuffer)
31+
32+ let width = Int(size.width)
33+ let height = Int(size.height)
34+ let imageByteCount = width * height * 4
35+ imageBuffer = malloc(imageByteCount)
36+
37+ self.texture = texture
38+ }
39+
40+ deinit {
41+ free(imageBuffer)
42+ }
43+}
PixelImage/MetalMetaballRenderer.swift+10−28
@@ -22,11 +22,9 @@ class MetalMetaballRenderer: MetaballRenderer {
2222 }
2323
2424 let targetView = TargetView()
25− var previousSize = CGSize.zero
2625
2726 let context = MTLContext()
28− var renderingTexture: MTLTexture!
29− var imageBuffer: UnsafeMutablePointer<Void>!
27+ var computeContext: MTLComputeContext!
3028
3129 let dataSource: MetaballDataSource
3230
@@ -59,12 +57,6 @@ class MetalMetaballRenderer: MetaballRenderer {
5957
6058 state = .Ending
6159
62− // Re-alloc buffers if the size has changed
63− if previousSize != targetView.size {
64− previousSize = targetView.size
65− updateFrame()
66− }
67−
6860 dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_USER_INTERACTIVE.rawValue), 0)) { () -> Void in
6961
7062 // Render graphics to metal texture
@@ -90,11 +82,12 @@ class MetalMetaballRenderer: MetaballRenderer {
9082 let width = Int(targetView.width)
9183 let height = Int(targetView.height)
9284
93− if renderingTexture == nil {
85+ if computeContext == nil {
9486 let textureDescriptor =
9587 MTLTextureDescriptor.texture2DDescriptorWithPixelFormat(.BGRA8Unorm, width: width, height: height, mipmapped: false)
9688
97− renderingTexture = context.device.newTextureWithDescriptor(textureDescriptor)
89+ let texture = context.device.newTextureWithDescriptor(textureDescriptor)
90+ computeContext = MTLComputeContext(size: targetView.size, texture: texture)
9891 }
9992
10093 let kernelFunction: MTLFunction?
@@ -114,7 +107,7 @@ class MetalMetaballRenderer: MetaballRenderer {
114107
115108 let commandEncoder = commandBuffer.computeCommandEncoder()
116109 commandEncoder.setComputePipelineState(pipeline)
117− commandEncoder.setTexture(renderingTexture, atIndex: 0)
110+ commandEncoder.setTexture(computeContext.texture, atIndex: 0)
118111 let metaballInfoBuffer = metaballBuffer()
119112 commandEncoder.setBuffer(metaballInfoBuffer, offset: 0, atIndex: 0)
120113 commandEncoder.dispatchThreadgroups(threadGroups,
@@ -130,7 +123,7 @@ class MetalMetaballRenderer: MetaballRenderer {
130123 }
131124
132125 func createImageFromTexture() -> UIImage {
133− let texture = renderingTexture
126+ let texture = computeContext.texture
134127
135128 // Get image info
136129 let imageSize = CGSizeMake(CGFloat(texture.width),
@@ -142,16 +135,16 @@ class MetalMetaballRenderer: MetaballRenderer {
142135 let region = MTLRegionMake2D(0, 0, width, height)
143136
144137 // Allocate the buffer if needed
145− if imageBuffer == nil {
146− imageBuffer = malloc(imageByteCount)
138+ if computeContext.imageBuffer == nil {
139+ computeContext.imageBuffer = malloc(imageByteCount)
147140 }
148141
149142 // Transfer texture info into image buffer
150− texture.getBytes(imageBuffer, bytesPerRow: bytesPerRow,
143+ texture.getBytes(computeContext.imageBuffer, bytesPerRow: bytesPerRow,
151144 fromRegion: region, mipmapLevel: 0)
152145
153146 // Get info for UIImage
154− let provider = CGDataProviderCreateWithData(nil, imageBuffer,
147+ let provider = CGDataProviderCreateWithData(nil, computeContext.imageBuffer,
155148 imageByteCount, nil)
156149 let bitsPerComponent = 8
157150 let bitsperPixel = 32
@@ -195,15 +188,4 @@ class MetalMetaballRenderer: MetaballRenderer {
195188
196189 return buffer
197190 }
198−
199− func updateFrame() {
200− if imageBuffer != nil {
201− free(imageBuffer)
202− }
203− imageBuffer = nil
204− }
205−
206− deinit {
207− free(imageBuffer)
208− }
209191}