git.iko.soy/metal-metaballs
on master help sign in
Refactored metaball info from being a texture to a buffer.
commit40cc1737d249b221a4816e5d04bda21777393ab2 authorvinivendra <vinivendra@gmail.com> dateWed 10 Feb 2016, 14:45 (11 years ago) parent038568f
2 files changed+13−25
PixelImage/MetalMetaballRenderer.swift+7−18 PixelImage/shaders.metal+6−7
PixelImage/MetalMetaballRenderer.swift+7−18
@@ -1,5 +1,3 @@
1−// TODO: Make shader ignore metaballs that are outside a certain area of tolerance (eg ±100 from borders)
2−
31// TODO: Metaballs from texture to buffer
42// TODO: Use async dispatch to free up main queue
53// TODO: Refactor update into 2 calls: metalRendering() and textureToImage()
@@ -62,7 +60,7 @@ class MetalMetaballRenderer: MetaballRenderer {
6260 height / threadGroupCounts.height, 1)
6361
6462 // Create up-to-date metaball buffer
65− let metaballInfoTexture = metaballTexture(metaballs)
63+ let metaballInfoBuffer = metaballBuffer(metaballs)
6664
6765 // Send commands to metal and render
6866 let commandBuffer = context.commandQueue.commandBuffer()
@@ -70,7 +68,7 @@ class MetalMetaballRenderer: MetaballRenderer {
7068 let commandEncoder = commandBuffer.computeCommandEncoder()
7169 commandEncoder.setComputePipelineState(pipeline)
7270 commandEncoder.setTexture(renderingTexture, atIndex: 0)
73− commandEncoder.setTexture(metaballInfoTexture, atIndex: 1)
71+ commandEncoder.setBuffer(metaballInfoBuffer, offset: 0, atIndex: 0)
7472 commandEncoder.dispatchThreadgroups(threadGroups,
7573 threadsPerThreadgroup: threadGroupCounts)
7674 commandEncoder.endEncoding()
@@ -127,7 +125,7 @@ class MetalMetaballRenderer: MetaballRenderer {
127125 return image
128126 }
129127
130− func metaballTexture(metaballs: [Metaball]) -> MTLTexture {
128+ func metaballBuffer(metaballs: [Metaball]) -> MTLBuffer {
131129 // Create Float array for buffer
132130 // Exclude metaballs far from the view's bounds
133131 let border: CGFloat = 100
@@ -144,19 +142,10 @@ class MetalMetaballRenderer: MetaballRenderer {
144142 // Add array size to start of array so metal knows how far to go
145143 floats[0] = Float(floats.count) / 2
146144
147− // Create texture
148− let size = floats.count
149− let textureDescriptor =
150− MTLTextureDescriptor.texture2DDescriptorWithPixelFormat(
151− .R32Float, width: size, height: 1, mipmapped: false)
152− let texture = context.device.newTextureWithDescriptor(textureDescriptor)
153−
154− // Copy array info into texture
155− let region = MTLRegionMake2D(0, 0, size, 1)
156− texture.replaceRegion(region, mipmapLevel: 0, withBytes: floats,
157− bytesPerRow: sizeof(Float) * size)
158−
159− return texture
145+ // Create buffer
146+ let buffer = context.device.newBufferWithBytes(floats, length: floats.count * sizeof(Float), options: .StorageModeShared)
147+
148+ return buffer
160149 }
161150
162151 func updateFrame() {
PixelImage/shaders.metal+6−7
@@ -5,22 +5,21 @@ using namespace metal;
55
66kernel void
77 drawMetaballs(texture2d<float, access::write> outTexture[[texture(0)]],
8− texture2d<float, access::read>
9− metaballTexture[[texture(1)]],
8+ constant float *metaballBuffer [[buffer(0)]],
109 uint2 gid[[thread_position_in_grid]]) {
1110
12− char numberOfMetaballs = metaballTexture.read(0)[0];
11+ char numberOfMetaballs = metaballBuffer[0];
1312 char metaballArraySize = numberOfMetaballs * 2 + 1;
1413
1514 float sum = 0;
1615
1716 for (char i = 1; i < metaballArraySize; i += 2) {
1817 for (char j = i + 2; j < metaballArraySize; j += 2) {
19− float2 metaball1 = float2(metaballTexture.read(i)[0],
20− metaballTexture.read(i + 1)[0]);
18+ float2 metaball1 = float2(metaballBuffer[i],
19+ metaballBuffer[i + 1]);
2120
22− float2 metaball2 = float2(metaballTexture.read(j)[0],
23− metaballTexture.read(j + 1)[0]);
21+ float2 metaball2 = float2(metaballBuffer[j],
22+ metaballBuffer[j + 1]);
2423
2524 float2 metaball1Vector
2625 = float2(metaball1.x - gid.x, metaball1.y - gid.y);