From 1e78735c9ad9da049aadda8d4efdbf6d62185f02 Mon Sep 17 00:00:00 2001 From: Rob Bishop Date: Mon, 11 May 2020 08:17:52 -0700 Subject: [PATCH] Solidify a bit for StackOverflow help --- Foil.xcodeproj/project.pbxproj | 10 +-- Foil/FoilViewController.swift | 146 +++++-------------------------- Foil/LikeObjcSync.swift | 15 ---- Foil/OFoilRenderer.m | 9 -- Renderer/FoilMathUtilities.swift | 12 +-- Renderer/FoilRenderer.swift | 138 ++++++++++++++++------------- Simulation/FoilSimulation.swift | 64 ++++++-------- 7 files changed, 135 insertions(+), 259 deletions(-) delete mode 100644 Foil/LikeObjcSync.swift delete mode 100644 Foil/OFoilRenderer.m diff --git a/Foil.xcodeproj/project.pbxproj b/Foil.xcodeproj/project.pbxproj index 70c0cc0..24ffca3 100644 --- a/Foil.xcodeproj/project.pbxproj +++ b/Foil.xcodeproj/project.pbxproj @@ -8,8 +8,6 @@ /* Begin PBXBuildFile section */ D42B958B24648E2900F4B5B0 /* FoilShaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = D42B958A24648E2900F4B5B0 /* FoilShaders.metal */; }; - D462CC9D2466652400D79B48 /* LikeObjcSync.swift in Sources */ = {isa = PBXBuildFile; fileRef = D462CC9C2466652400D79B48 /* LikeObjcSync.swift */; }; - D475693E2469259D000F87AE /* OFoilRenderer.m in Sources */ = {isa = PBXBuildFile; fileRef = D475693D2469259D000F87AE /* OFoilRenderer.m */; }; D4AC68B8245CF43F00917569 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AC68B7245CF43F00917569 /* AppDelegate.swift */; }; D4AC68BA245CF43F00917569 /* FoilViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AC68B9245CF43F00917569 /* FoilViewController.swift */; }; D4AC68BC245CF44000917569 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D4AC68BB245CF44000917569 /* Assets.xcassets */; }; @@ -23,9 +21,7 @@ /* Begin PBXFileReference section */ D42B958A24648E2900F4B5B0 /* FoilShaders.metal */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.metal; path = FoilShaders.metal; sourceTree = ""; }; - D462CC9C2466652400D79B48 /* LikeObjcSync.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LikeObjcSync.swift; sourceTree = ""; }; D475693C2469259D000F87AE /* Foil-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Foil-Bridging-Header.h"; sourceTree = ""; }; - D475693D2469259D000F87AE /* OFoilRenderer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OFoilRenderer.m; sourceTree = ""; }; D475693F24692638000F87AE /* FoilShaderTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FoilShaderTypes.h; sourceTree = ""; }; D47569402469267E000F87AE /* FoilKernelTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FoilKernelTypes.h; sourceTree = ""; }; D4AC68B4245CF43F00917569 /* Foil.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Foil.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -79,12 +75,10 @@ D4AC68BB245CF44000917569 /* Assets.xcassets */, D4AC68B7245CF43F00917569 /* AppDelegate.swift */, D4AC68C1245CF44000917569 /* Foil.entitlements */, + D475693C2469259D000F87AE /* Foil-Bridging-Header.h */, D4AC68B9245CF43F00917569 /* FoilViewController.swift */, D4AC68C0245CF44000917569 /* Info.plist */, - D462CC9C2466652400D79B48 /* LikeObjcSync.swift */, D4AC68BD245CF44000917569 /* Main.storyboard */, - D475693D2469259D000F87AE /* OFoilRenderer.m */, - D475693C2469259D000F87AE /* Foil-Bridging-Header.h */, ); path = Foil; sourceTree = ""; @@ -191,12 +185,10 @@ files = ( D4BE16FE2463F0E10085FD3C /* FoilKernels.metal in Sources */, D4AC68C9245CF57A00917569 /* FoilRenderer.swift in Sources */, - D462CC9D2466652400D79B48 /* LikeObjcSync.swift in Sources */, D4AC68BA245CF43F00917569 /* FoilViewController.swift in Sources */, D42B958B24648E2900F4B5B0 /* FoilShaders.metal in Sources */, D4F680AC245FACB3000B8EF2 /* FoilSimulation.swift in Sources */, D4F680BE24639638000B8EF2 /* FoilMathUtilities.swift in Sources */, - D475693E2469259D000F87AE /* OFoilRenderer.m in Sources */, D4AC68B8245CF43F00917569 /* AppDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Foil/FoilViewController.swift b/Foil/FoilViewController.swift index 1b84a42..1838a55 100644 --- a/Foil/FoilViewController.swift +++ b/Foil/FoilViewController.swift @@ -9,11 +9,7 @@ import Cocoa import MetalKit -class FoilViewController: NSViewController, MTKViewDelegate { - func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) { - assert(false) - } - +class FoilViewController: NSViewController { let IntelGPUInMetalDevicesArray = 0 let RadeonGPUInMetalDevicesArray = 1 @@ -36,8 +32,6 @@ class FoilViewController: NSViewController, MTKViewDelegate { static let FoilNumSimulationConfigs = FoilSimulationConfigTable.count -// var _view: MTKView { guard let v = self.view as? MTKView else { fatalError() }; return v } - var _view: MTKView { (self.view as? MTKView)! } var renderer: FoilRenderer! var simulation: FoilSimulation! @@ -88,7 +82,7 @@ class FoilViewController: NSViewController, MTKViewDelegate { super.viewDidLoad() selectDevices() - _view.delegate = self +// _view.delegate = self } override func viewDidAppear() { beginSimulation() } @@ -96,10 +90,10 @@ class FoilViewController: NSViewController, MTKViewDelegate { override func viewDidDisappear() { viewControllerispatchQueue.sync { // Stop simulation if on another thread - self.simulation.halt = true; + self.simulation.halt = true // Indicate that simulation should not continue and results will not be needed - self.terminateAllSimulations = true; + self.terminateAllSimulations = true } } @@ -108,140 +102,43 @@ class FoilViewController: NSViewController, MTKViewDelegate { precondition(!availableDevices.isEmpty, "Metal is not supported on this Mac") - computeDevice = availableDevices[IntelGPUInMetalDevicesArray] + computeDevice = availableDevices[RadeonGPUInMetalDevicesArray] NSLog("Selected compute device: \(computeDevice.name)") // Select renderer device - let rendererDevice = availableDevices[IntelGPUInMetalDevicesArray] - - if rendererDevice !== _view.device { - _view.device = rendererDevice; + let rendererDevice = availableDevices[RadeonGPUInMetalDevicesArray] - NSLog("New render device: '\(rendererDevice.name)', drawableSize \(_view.drawableSize)") + renderer = FoilRenderer(self, rendererDevice) - renderer = FoilRenderer(_view) - renderer.drawableSizeWillChange(size: _view.drawableSize) - } + NSLog("New render device: \"\(rendererDevice.name)\"") } func beginSimulation() { - simulationTime = 0; + simulationTime = 0 _simulationName.stringValue = "Simulation \(configNum)" config = FoilViewController.FoilSimulationConfigTable[configNum] simulation = FoilSimulation(computeDevice: computeDevice, config: config) - renderer.setRenderScale(renderScale: config.renderScale, drawableSize: _view.drawableSize) + renderer.setRenderScale(renderScale: config.renderScale) - NSLog("Starting Simulation Config: \(configNum)"); + commandQueue = renderer.device.makeCommandQueue() - if computeDevice === renderer.device { - // If the device used for rendering and compute are the same, create a command queue shared - // by both components - commandQueue = renderer.device.makeCommandQueue() - } else { - // If the device used for rendering is different than that used for compute, run the - // the simulation asynchronously on the compute device - runSimulationOnAlternateDevice() - } + NSLog("Starting Simulation Config: \(configNum)") } - // Asynchronously begins or continues a simulation on a different than the device used for rendering - func runSimulationOnAlternateDevice() { - assert(computeDevice !== renderer.device) - - commandQueue = nil; - - let updateHandler: (NSData, CFAbsoluteTime) -> () = { - // Update the renderer's position data so that it can show forward progress - self.updateWithNewPositionData(updateData: $0, forSimulationTime: $1) - } - - let dataProvider: (NSData, NSData, CFAbsoluteTime) -> () = { - self.handleFullyProvidedSetOfPositionData(positionData: $0, velocityData: $1, forSimulationTime: $2) - } - - simulation.runAsyncWithUpdateHandler(updateHandler: updateHandler, dataProvider: dataProvider) - } - - /// Receive and update of new positions for the simulation time given. - func updateWithNewPositionData(updateData: NSData, forSimulationTime simulationTime: CFAbsoluteTime) { - // Lock with updateData so thus thread does not update data during an update on another thread - dataUpdateDispatchQueue.sync { - // Update the renderer's position data so that it can show forward progress - self.renderer.providePositionData(data: updateData) - } - - viewControllerispatchQueue.sync { - // Lock around _simulation time since it will be accessed on another thread - self.simulationTime = simulationTime; - } - } - - // Handle the passing of full data set from asynchronous simulation executed on device different - // the the device used for rendering - func handleFullyProvidedSetOfPositionData( - positionData: NSData, velocityData: NSData, - forSimulationTime simulationTime: CFAbsoluteTime - ) { - viewControllerispatchQueue.sync { - if self.terminateAllSimulations { - NSLog("Terminating all simulations") - return - } - - self.simulationTime = simulationTime; - - if simulationTime >= config.simDuration { - NSLog("Simulation Config \(configNum) Complete") - - // If the simulation is complete, provide all the final positions to render - renderer.providePositionData(data: positionData) - } else { - NSLog("Simulation Config \(configNum) Cannot complete with current simulation object") - - // If the simulation is not complete, this indicates that compute device cannot complete - // the simulation, so data has been transferred from that device so the app can continue - // the simulation on another device - - // Reselect a new device to continue the simulation - selectDevices() - - // Create a new simulation object with the data provided - self.simulation = FoilSimulation( - computeDevice: computeDevice, config: config, - positionData: positionData, velocityData: velocityData, - simulationTime: simulationTime - ) - - if computeDevice === renderer.device { - // If the device used for rendering and compute are the same, create a command queue shared - // by both components - commandQueue = renderer.device.makeCommandQueue() - } else { - // If the device used for rendering is different than that used for compute, run the - // the simulation asynchronously on the compute device - runSimulationOnAlternateDevice() - } - } - } - } - - /// Called whenever view changes orientation or layout is changed - func drawableSizeWillChange(size: CGSize) { renderer.drawableSizeWillChange(size: size) } - static let FoilSecondsToPresentSimulationResults = CFTimeInterval(4.0) /// Called whenever the view needs to render func draw(in view: MTKView) { // Number of bodies to render this frame - var numBodies = config.renderBodies; + var numBodies = config.renderBodies // Handle simulations completion if(simulationTime >= config.simDuration) { // If the simulation is over, render all the bodies in the simulation to show final results - numBodies = config.numBodies; + numBodies = config.numBodies if(continuationTime == 0) { continuationTime = CACurrentMediaTime() + FoilViewController.FoilSecondsToPresentSimulationResults @@ -256,8 +153,8 @@ class FoilViewController: NSViewController, MTKViewDelegate { } let animationCompletion: () -> () = { - self._simulationName.alphaValue = 1.0; - self._simulationPercentage.alphaValue = 1.0; + self._simulationName.alphaValue = 1.0 + self._simulationPercentage.alphaValue = 1.0 } let blinkyBlock: (Timer) -> () = { timer in @@ -270,9 +167,9 @@ class FoilViewController: NSViewController, MTKViewDelegate { } else if(CACurrentMediaTime() >= continuationTime) { // If the continuation time has been reached, select a new simulation and begin execution - configNum = (configNum + 1) % FoilViewController.FoilNumSimulationConfigs; + configNum = (configNum + 1) % FoilViewController.FoilNumSimulationConfigs - continuationTime = 0; + continuationTime = 0 blinker.invalidate() blinker = nil @@ -297,8 +194,9 @@ class FoilViewController: NSViewController, MTKViewDelegate { // Render the updated positions (or all positions in the case that the simulation is complete) renderer.drawWithCommandBuffer( - commandBuffer: commandBuffer, positionsBuffer: positionBuffer, - numBodies: numBodies, view: _view + commandBuffer: commandBuffer, + positionsBuffer: positionBuffer, + numBodies: numBodies ) commandBuffer.commit() @@ -307,7 +205,7 @@ class FoilViewController: NSViewController, MTKViewDelegate { simulationTime += Double(config.simInterval) } else { - renderer.drawProvidedPositionDataWithNumBodies(numParticles: numBodies, inView: _view) + renderer.drawProvidedPositionDataWithNumBodies(numParticles: numBodies) } var percentComplete = 0 diff --git a/Foil/LikeObjcSync.swift b/Foil/LikeObjcSync.swift deleted file mode 100644 index 59bfe17..0000000 --- a/Foil/LikeObjcSync.swift +++ /dev/null @@ -1,15 +0,0 @@ -import Foundation - -class ikeObjcSync { - public class func synced(_ lock: Any, closure: () -> ()) { - objc_sync_enter(lock) - defer { objc_sync_exit(lock) } - closure() - } - - public class func syncedReturn(_ lock: Any, closure: () -> (Any?)) -> Any? { - objc_sync_enter(lock) - defer { objc_sync_exit(lock) } - return closure() - } -} diff --git a/Foil/OFoilRenderer.m b/Foil/OFoilRenderer.m deleted file mode 100644 index b7abd20..0000000 --- a/Foil/OFoilRenderer.m +++ /dev/null @@ -1,9 +0,0 @@ -// -// OFoilRenderer.m -// Foil -// -// Created by Rob Bishop on 5/10/20. -// Copyright © 2020 Boring Software. All rights reserved. -// - -#import diff --git a/Renderer/FoilMathUtilities.swift b/Renderer/FoilMathUtilities.swift index 7b8b259..b807aef 100644 --- a/Renderer/FoilMathUtilities.swift +++ b/Renderer/FoilMathUtilities.swift @@ -5,18 +5,18 @@ enum FoilMath { var rand = vector_float3() repeat { - rand = generateRandomVector(min, max); + rand = generateRandomVector(min, max) } while(simd_length(rand) > maxlength) return simd_normalize(rand) } static func generateRandomVector(_ min: Float, _ max: Float) -> vector_float3 { - let range = max - min; + let range = max - min - let x = Float.random(in: 0..<1) * range + min; - let y = Float.random(in: 0..<1) * range + min; - let z = Float.random(in: 0..<1) * range + min; + let x = Float.random(in: 0..<1) * range + min + let y = Float.random(in: 0..<1) * range + min + let z = Float.random(in: 0..<1) * range + min return vector_float3(x, y, z) } @@ -28,7 +28,7 @@ enum FoilMath { 2 / (right - left), 0, 0, (left + right) / (left - right), 0, 2 / (top - bottom), 0, (top + bottom) / (bottom - top), 0, 0, 1 / (farZ - nearZ), nearZ / (nearZ - farZ), - 0, 0, 0, 1 ); + 0, 0, 0, 1 ) } static func matriMakeRows( diff --git a/Renderer/FoilRenderer.swift b/Renderer/FoilRenderer.swift index 1de3703..fe096e4 100644 --- a/Renderer/FoilRenderer.swift +++ b/Renderer/FoilRenderer.swift @@ -1,16 +1,24 @@ import Foundation import MetalKit -class FoilRenderer: NSObject { +class FoilRenderer: NSObject, MTKViewDelegate { + func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) { + print("mtkview") + } + + func draw(in view: MTKView) { + viewController.draw(in: view) + } + // The point size (in pixels) of rendered bodies - static let bodyPointSize: Float = 15; + static let bodyPointSize: Float = 15 // Size of gaussian map to create rounded smooth points static let GaussianMapSize = 64 var gaussianMap: MTLTexture! - var device: MTLDevice! + var device: MTLDevice { view.device! } var commandQueue: MTLCommandQueue! var colorsBuffer: MTLBuffer? @@ -21,6 +29,9 @@ class FoilRenderer: NSObject { var positionsBuffer: MTLBuffer! var renderPipeline: MTLRenderPipelineState! + let view: MTKView + let viewController: FoilViewController + // Current buffer to fill with dynamic uniform data and set for the current frame var currentBufferIndex = 0 @@ -36,25 +47,32 @@ class FoilRenderer: NSObject { /// Initialize with the MetalKit view with the Metal device used to render. This MetalKit view /// object will also be used to set the pixelFormat and other properties of the drawable - init(_ mtkView: MTKView) { - self.device = mtkView.device! + init(_ viewController: FoilViewController, _ rendererDevice: MTLDevice) { + self.view = (viewController.view as? MTKView)! + self.view.device = rendererDevice + self.viewController = viewController super.init() - self.loadMetal(mtkView: mtkView) + self.view.delegate = self - self.gaussianMap = FoilRenderer.generateGaussianMap(self.device) + self.loadMetal() + self.generateGaussianMap() + + updateProjectionMatrix() } /// Update the projection matrix with a new drawable size - func drawableSizeWillChange(size: CGSize) { updateProjectionMatrix(with: size) } + func drawableSizeWillChange(size: CGSize) { + print("dswc(CGSize)") + updateProjectionMatrix() + } /// Draw particles at the supplied positions using the given command buffer to the given view func drawWithCommandBuffer( commandBuffer: MTLCommandBuffer, positionsBuffer: MTLBuffer, - numBodies: Int, - view: MTKView + numBodies: Int ) { commandBuffer.pushDebugGroup("Draw Simulation Data") @@ -68,7 +86,7 @@ class FoilRenderer: NSObject { let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: renderPassDescriptor) else { fatalError() } - renderEncoder.label = "Render Commands"; + renderEncoder.label = "Render Commands" renderEncoder.setRenderPipelineState(renderPipeline) // In objective-c, this was "if(positionsBuffer)" -- not sure what to make of it @@ -106,7 +124,7 @@ class FoilRenderer: NSObject { } /// Generates a texture to make rounded points for particles - static func generateGaussianMap(_ device: MTLDevice) -> MTLTexture { + func generateGaussianMap() { let textureDescriptor = MTLTextureDescriptor() textureDescriptor.textureType = .type2D @@ -117,11 +135,11 @@ class FoilRenderer: NSObject { textureDescriptor.cpuCacheMode = .defaultCache textureDescriptor.usage = .shaderRead - let gaussianMap = device.makeTexture(descriptor: textureDescriptor) + self.gaussianMap = device.makeTexture(descriptor: textureDescriptor) // Calculate the size of a RGBA8Unorm texture's data and allocate system memory buffer // used to fill the texture's memory - let dataSize = textureDescriptor.width * textureDescriptor.height * MemoryLayout.size + let dataSize = textureDescriptor.width * textureDescriptor.height * MemoryLayout.stride let nDelta: vector_float2 = [2.0 / Float(textureDescriptor.width), 2.0 / Float(textureDescriptor.height)] @@ -134,7 +152,7 @@ class FoilRenderer: NSObject { let sNormY = -1.0 + Float(y) * nDelta.y for x in 0...size + bytesPerRow: textureDescriptor.width * MemoryLayout.stride ) - gaussianMap!.label = "Gaussian Map" - - return gaussianMap! + gaussianMap.label = "Gaussian Map" } - func loadMetal(mtkView: MTKView) { + func loadMetal() { // Load all the shader files with a .metal file extension in the project guard let defaultLibrary = device.makeDefaultLibrary() else { fatalError() } @@ -172,25 +188,26 @@ class FoilRenderer: NSObject { // Load the fragment function from the library let fragmentFunction = defaultLibrary.makeFunction(name: "fragmentShader") - mtkView.depthStencilPixelFormat = MTLPixelFormat.depth32Float_stencil8 - mtkView.colorPixelFormat = MTLPixelFormat.bgra8Unorm; - mtkView.sampleCount = 1; + view.depthStencilPixelFormat = MTLPixelFormat.depth32Float_stencil8 + view.colorPixelFormat = MTLPixelFormat.bgra8Unorm + view.sampleCount = 1 let pipelineDescriptor = MTLRenderPipelineDescriptor() - pipelineDescriptor.label = "RenderPipeline"; - pipelineDescriptor.sampleCount = mtkView.sampleCount; - pipelineDescriptor.vertexFunction = vertexFunction; - pipelineDescriptor.fragmentFunction = fragmentFunction; - pipelineDescriptor.colorAttachments[0].pixelFormat = mtkView.colorPixelFormat; - pipelineDescriptor.depthAttachmentPixelFormat = mtkView.depthStencilPixelFormat; - pipelineDescriptor.stencilAttachmentPixelFormat = mtkView.depthStencilPixelFormat; - pipelineDescriptor.colorAttachments[0].isBlendingEnabled = true; - pipelineDescriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperation.add; - pipelineDescriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperation.add; - pipelineDescriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactor.sourceAlpha; - pipelineDescriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactor.sourceAlpha; - pipelineDescriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactor.one; - pipelineDescriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactor.one; + pipelineDescriptor.label = "RenderPipeline" + pipelineDescriptor.sampleCount = view.sampleCount + pipelineDescriptor.vertexFunction = vertexFunction + pipelineDescriptor.fragmentFunction = fragmentFunction + pipelineDescriptor.depthAttachmentPixelFormat = view.depthStencilPixelFormat + pipelineDescriptor.stencilAttachmentPixelFormat = view.depthStencilPixelFormat + + pipelineDescriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperation.add + pipelineDescriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactor.one + pipelineDescriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactor.one + pipelineDescriptor.colorAttachments[0].isBlendingEnabled = true + pipelineDescriptor.colorAttachments[0].pixelFormat = view.colorPixelFormat + pipelineDescriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperation.add + pipelineDescriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactor.sourceAlpha + pipelineDescriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactor.sourceAlpha guard let rp = try? device.makeRenderPipelineState(descriptor: pipelineDescriptor) else { fatalError("Failed to create render pipeline state") } @@ -198,8 +215,8 @@ class FoilRenderer: NSObject { self.renderPipeline = rp let depthStateDesc = MTLDepthStencilDescriptor() - depthStateDesc.depthCompareFunction = MTLCompareFunction.less; - depthStateDesc.isDepthWriteEnabled = true; + depthStateDesc.depthCompareFunction = MTLCompareFunction.less + depthStateDesc.isDepthWriteEnabled = true depthState = device.makeDepthStencilState(descriptor: depthStateDesc) // Indicate shared storage so that both the CPU can access the buffers @@ -236,10 +253,10 @@ class FoilRenderer: NSObject { options: .storageModeManaged, deallocator: nil ) else { fatalError() } - positionsBuffer.label = "Provided Positions"; + positionsBuffer.label = "Provided Positions" positionsBuffer.didModifyRange(0...stride // Create buffers to hold our simulation data and generate initial data set @@ -193,7 +191,7 @@ class FoilSimulation { guard let sp = device.makeBuffer(length: length, options: .storageModeManaged) else { fatalError() } - sp.label = "Simulation Params"; + sp.label = "Simulation Params" simulationParams = sp let c_ = UnsafeMutableRawPointer(mutating: sp.contents()) @@ -271,21 +269,21 @@ class FoilSimulation { p.w = 1 var axis = vector_float3(0.0, 0.0, 1.0) - let scalar = simd_dot(nrpos, axis); + let scalar = simd_dot(nrpos, axis) if((1 - scalar) < 1e-6) { axis.x = nrpos.y axis.y = nrpos.x - axis = simd_normalize(axis); + axis = simd_normalize(axis) } - let velocity = simd_cross(position, axis); + let velocity = simd_cross(position, axis) var v = velocities[i] - v.x = velocity.x * vscale; - v.y = velocity.y * vscale; - v.z = velocity.z * vscale; + v.x = velocity.x * vscale + v.y = velocity.y * vscale + v.z = velocity.z * vscale } let fullPRange = 0..