// // MarchingSquares.swift // Metaballs // // Created by Eryn Wells on 10/11/18. // Copyright © 2018 Eryn Wells. All rights reserved. // import Foundation import Metal class MarchingSquares { private var field: Field private var sampleGridSize = Size(16) private var semaphore: DispatchSemaphore /// Samples of the field's current state. private(set) var samplesBuffer: MTLBuffer? /// Indexes of geometry to render. private(set) var indexes: MTLTexture? private(set) var gridGeometry: MTLBuffer? private var xSamples: Int { return Int(field.size.x / sampleGridSize.x) } private var ySamples: Int { return Int(field.size.y / sampleGridSize.y) } private var lastSamplesCount = 0 var samplesCount: Int { return xSamples * ySamples } init(field: Field) { self.field = field semaphore = DispatchSemaphore(value: 1) } func setupMetal(withDevice device: MTLDevice) { // let samplesDesc = MTLTextureDescriptor() // samplesDesc.textureType = .type2D // samplesDesc.width = xSamples // samplesDesc.height = ySamples // samplesDesc.pixelFormat = .r32Float // samples = device.makeTexture(descriptor: samplesDesc) // // let indexesDesc = MTLTextureDescriptor() // indexesDesc.textureType = .type2D // indexesDesc.width = xSamples - 1 // indexesDesc.height = ySamples - 1 // indexesDesc.pixelFormat = .a8Unorm // indexes = device.makeTexture(descriptor: indexesDesc) } func fieldDidResize() { guard let device = gridGeometry?.device else { return } populateGrid(withDevice: device) populateSamples(withDevice: device) lastSamplesCount = samplesCount } func populateGrid(withDevice device: MTLDevice) { guard lastSamplesCount != samplesCount else { return } print("Populating grid with (\(xSamples), \(ySamples)) samples") let gridSizeX = Float(sampleGridSize.x) let gridSizeY = Float(sampleGridSize.y) var grid = [Rect]() grid.reserveCapacity(samplesCount) for y in 0...stride * samplesCount, options: .storageModeShared) { memcpy(buffer.contents(), grid, MemoryLayout.stride * grid.count) gridGeometry = buffer } else { fatalError("Couldn't create buffer for grid rects") } } func populateSamples(withDevice device: MTLDevice) { print("Populating samples buffer with \(samplesCount) values") var samples = [Float]() samples.reserveCapacity(samplesCount) for ys in 0...stride * samplesCount if let buffer = device.makeBuffer(length: MemoryLayout.stride * samples.count, options: .storageModeShared) { memcpy(buffer.contents(), samples, samplesLength) samplesBuffer = buffer } else { fatalError("Couldn't create buffer for samples") } } }