Skip to content

Commit

Permalink
Simulations run at proper speed now, still no display
Browse files Browse the repository at this point in the history
  • Loading branch information
SaganRitual committed May 10, 2020
1 parent 27b7865 commit cdab266
Show file tree
Hide file tree
Showing 8 changed files with 230 additions and 168 deletions.
78 changes: 78 additions & 0 deletions Foil.xcodeproj/xcshareddata/xcschemes/Foil.xcscheme
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1120"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D4AC68B3245CF43F00917569"
BuildableName = "Foil.app"
BlueprintName = "Foil"
ReferencedContainer = "container:Foil.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D4AC68B3245CF43F00917569"
BuildableName = "Foil.app"
BlueprintName = "Foil"
ReferencedContainer = "container:Foil.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D4AC68B3245CF43F00917569"
BuildableName = "Foil.app"
BlueprintName = "Foil"
ReferencedContainer = "container:Foil.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,13 @@
<integer>0</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>
<dict>
<key>D4AC68B3245CF43F00917569</key>
<dict>
<key>primary</key>
<true/>
</dict>
</dict>
</dict>
</plist>
2 changes: 1 addition & 1 deletion Foil/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
Expand Up @@ -679,7 +679,7 @@
<!--Foil View Controller-->
<scene sceneID="hIz-AP-VOD">
<objects>
<viewController id="XfG-lQ-9wD" customClass="FoilViewController" customModule="Foil" sceneMemberID="viewController">
<viewController id="XfG-lQ-9wD" customClass="FoilViewController" customModule="Foil" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" wantsLayer="YES" id="m2S-Jp-Qdl" customClass="MTKView">
<rect key="frame" x="0.0" y="0.0" width="805" height="600"/>
<autoresizingMask key="autoresizingMask"/>
Expand Down
100 changes: 49 additions & 51 deletions Foil/FoilViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,24 @@ class FoilViewController: NSViewController, MTKViewDelegate {
assert(false)
}

let IntelGPUInMetalDevicesArray = 0
let RadeonGPUInMetalDevicesArray = 1

static let frameTime: Double = 1.0 / 60.0
static let second: Double = frameTime * 60.0
static let metersPerSecond: Double = 600.0

// Table with various simulation configurations. Apps would typically load simulation parameters
// such as these from a file or UI controls, but to simplify the sample and focus on Metal usage,
// this table is hardcoded
static let FoilSimulationConfigTable = [
// damping softening numBodies clusterScale velocityScale renderScale renderBodies simInterval simDuration
FoilSimulationConfig(damping: 1.0, softeningSqr: 1.000, numBodies: 16384, clusterScale: 1.54, velocityScale: 8, renderScale: 25.0, renderBodies: 16384, simInterval: 0.0160, simDuration: 500.0),
FoilSimulationConfig(damping: 1.0, softeningSqr: 0.100, numBodies: 16384, clusterScale: 0.32, velocityScale: 276, renderScale: 2.5, renderBodies: 16384, simInterval: 0.0006, simDuration: 5.0),
FoilSimulationConfig(damping: 1.0, softeningSqr: 1.000, numBodies: 16384, clusterScale: 0.68, velocityScale: 20, renderScale: 1700.0, renderBodies: 16384, simInterval: 0.0160, simDuration: 5.0),
FoilSimulationConfig(damping: 1.0, softeningSqr: 1.000, numBodies: 16384, clusterScale: 1.54, velocityScale: 8, renderScale: 25.0, renderBodies: 16384, simInterval: 0.0160, simDuration: 5.0),
FoilSimulationConfig(damping: 1.0, softeningSqr: 1.000, numBodies: 16384, clusterScale: 6.04, velocityScale: 0, renderScale: 300.0, renderBodies: 16384, simInterval: 0.0160, simDuration: 5.0),
FoilSimulationConfig(damping: 1.0, softeningSqr: 0.145, numBodies: 16384, clusterScale: 0.32, velocityScale: 272, renderScale: 2.5, renderBodies: 16384, simInterval: 0.0006, simDuration: 5.0)
FoilSimulationConfig(damping: 1.0, softeningSqr: 1.000, numBodies: 4096, clusterScale: 0.32, velocityScale: metersPerSecond / 30, renderScale: 2.5, renderBodies: 4096, simInterval: frameTime / 30, simDuration: 10.0 * second / 30),
FoilSimulationConfig(damping: 1.0, softeningSqr: 1.000, numBodies: 4096, clusterScale: 6.04, velocityScale: 0, renderScale: 75.0, renderBodies: 4096, simInterval: frameTime, simDuration: 10.0 * second),
FoilSimulationConfig(damping: 1.0, softeningSqr: 0.145, numBodies: 4096, clusterScale: 0.32, velocityScale: metersPerSecond / 30, renderScale: 2.5, renderBodies: 4096, simInterval: frameTime / 30, simDuration: 10.0 * second / 30),
FoilSimulationConfig(damping: 1.0, softeningSqr: 1.000, numBodies: 4096, clusterScale: 1.54, velocityScale: metersPerSecond / 30, renderScale: 75.0, renderBodies: 4096, simInterval: frameTime, simDuration: 10.0 * second),
FoilSimulationConfig(damping: 1.0, softeningSqr: 0.100, numBodies: 4096, clusterScale: 0.68, velocityScale: metersPerSecond / 30, renderScale: 1000.0, renderBodies: 4096, simInterval: frameTime, simDuration: 10.0 * second),
FoilSimulationConfig(damping: 1.0, softeningSqr: 1.000, numBodies: 4096, clusterScale: 1.54, velocityScale: metersPerSecond / 30, renderScale: 75.0, renderBodies: 4096, simInterval: frameTime, simDuration: 10.0 * second)
]

static let FoilNumSimulationConfigs = FoilSimulationConfigTable.count
Expand All @@ -33,41 +40,60 @@ class FoilViewController: NSViewController, MTKViewDelegate {
var renderer: FoilRenderer!
var simulation: FoilSimulation!

// The current time (in simulation time units) that the simulation has processed
var simulationTime: CFAbsoluteTime = 0

// When rendering is paused (such as immediately after a simulation has completed), the time
// to unpause and continue simulations.
var continuationTime: CFAbsoluteTime = 0

var computeDevice: MTLDevice!

// Index of the current simulation config in the simulation config table
var configNum = 0

// Currently running simulation config
var config: FoilSimulationConfig!

// Command queue used when simulation and renderer are using the same device.
// Set to nil when using different devices
var commandQueue: MTLCommandQueue!

// When true, stop running any more simulations (such as when the window closes).
var terminateAllSimulations = false

// When true, restart the current simulation if it was interrupted and data could not
// be retrieved
var restartSimulation = false

// UI showing current simulation name and percentage complete
@IBOutlet var _simulationName: NSTextField!
@IBOutlet var _simulationPercentage: NSTextField!

// Timer used to make the text fields blink when results have been completed
var blinker: Timer!

let viewControllerispatchQueue = DispatchQueue(
label: "viewController.q", qos: .default, attributes: [/*serial*/],
target: DispatchQueue.global(qos: .default)
)

let dataUpdateDispatchQueue = DispatchQueue(
label: "dataUpdate.q", qos: .default, attributes: [/*serial*/],
target: DispatchQueue.global(qos: .default)
)

override func viewDidLoad() {
super.viewDidLoad()
selectDevices()

_view.delegate = self
}

override var representedObject: Any? {
didSet { assert(false) }
}

static let FoilSecondsToPresentSimulationResults = CFTimeInterval(4.0)

override func viewDidAppear() { beginSimulation() }

override func viewDidDisappear() {
LikeObjcSync.synced(self) {
viewControllerispatchQueue.sync {
// Stop simulation if on another thread
self.simulation.halt = true;

Expand All @@ -81,39 +107,16 @@ class FoilViewController: NSViewController, MTKViewDelegate {

precondition(!availableDevices.isEmpty, "Metal is not supported on this Mac")

// Select compute device
for device in availableDevices {
if device.isRemovable {
// Select removable device if available since if there is one, it's probably the most
// powerful device available
computeDevice = device;
break;
} else if device.isHeadless {
// Select headless device since if there is one it's probably dedicated to compute
// tasks
computeDevice = device;
}
}

if computeDevice == nil {
guard let cd = MTLCreateSystemDefaultDevice() else { fatalError() }
computeDevice = cd
}

computeDevice = availableDevices[RadeonGPUInMetalDevicesArray]
NSLog("Selected compute device: \(computeDevice.name)")

// Select renderer device (stored as _view.device)

// Query for device driving the display
let key = NSDeviceDescriptionKey("NSScreenNumber")
let viewDisplayID = (_view.window?.screen?.deviceDescription[key] as? CGDirectDisplayID) ?? CGDirectDisplayID()

let rendererDevice = CGDirectDisplayCopyCurrentMetalDevice(viewDisplayID);
// Select renderer device
let rendererDevice = availableDevices[RadeonGPUInMetalDevicesArray]

if rendererDevice !== _view.device {
_view.device = rendererDevice;

NSLog("New render device: '\(_view.device!.name)'")
NSLog("New render device: '\(rendererDevice.name)'")

renderer = FoilRenderer(_view)
renderer.drawableSizeWillChange(size: _view.drawableSize)
Expand Down Expand Up @@ -151,12 +154,10 @@ class FoilViewController: NSViewController, MTKViewDelegate {

let updateHandler: (NSData, CFAbsoluteTime) -> () = {
// Update the renderer's position data so that it can show forward progress
// print("update handler st = \($1)")
self.updateWithNewPositionData(updateData: $0, forSimulationTime: $1)
}

let dataProvider: (NSData, NSData, CFAbsoluteTime) -> () = {
print("dataProvider st = \($2)")
self.handleFullyProvidedSetOfPositionData(positionData: $0, velocityData: $1, forSimulationTime: $2)
}

Expand All @@ -166,12 +167,12 @@ class FoilViewController: NSViewController, MTKViewDelegate {
/// 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
LikeObjcSync.synced(updateData) {
dataUpdateDispatchQueue.sync {
// Update the renderer's position data so that it can show forward progress
self.renderer.providePositionData(data: updateData)
}

LikeObjcSync.synced(self) {
viewControllerispatchQueue.sync {
// Lock around _simulation time since it will be accessed on another thread
self.simulationTime = simulationTime;
}
Expand All @@ -183,14 +184,12 @@ class FoilViewController: NSViewController, MTKViewDelegate {
positionData: NSData, velocityData: NSData,
forSimulationTime simulationTime: CFAbsoluteTime
) {
LikeObjcSync.synced(self) {
viewControllerispatchQueue.sync {
if self.terminateAllSimulations {
NSLog("Terminating all simulations")
return
}

print("here self.simulationTime = simulationTime: \(self.simulationTime) = \(simulationTime), \(config.simDuration)")

self.simulationTime = simulationTime;

if simulationTime >= config.simDuration {
Expand Down Expand Up @@ -231,6 +230,8 @@ class FoilViewController: NSViewController, MTKViewDelegate {
/// 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
Expand Down Expand Up @@ -303,18 +304,15 @@ class FoilViewController: NSViewController, MTKViewDelegate {

commandBuffer.popDebugGroup()

let st = simulationTime
simulationTime += Double(config.simInterval)
print("draw st before \(st) after \(simulationTime)")
} else {
print("no draw ish \(simulationTime)")
renderer.drawProvidedPositionDataWithNumBodies(numParticles: numBodies, inView: _view)
}

var percentComplete = 0

// Lock when using _simulationTime since it can be updated on a separate thread
LikeObjcSync.synced(self) {
viewControllerispatchQueue.sync {
percentComplete = Int((simulationTime / config.simDuration) * 100)
}

Expand Down
2 changes: 1 addition & 1 deletion Foil/LikeObjcSync.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Foundation

class LikeObjcSync {
class ikeObjcSync {
public class func synced(_ lock: Any, closure: () -> ()) {
objc_sync_enter(lock)
defer { objc_sync_exit(lock) }
Expand Down
66 changes: 39 additions & 27 deletions Renderer/FoilMathUtilities.swift
Original file line number Diff line number Diff line change
@@ -1,34 +1,46 @@
import simd

func generate_random_vector(min: Float, max: Float) -> vector_float3 {
let range = max - min;
enum FoilMath {
static func generateRandomNormalizedVector(_ min: Float, _ max: Float, _ maxlength: Float) -> vector_float3 {
var rand = vector_float3()

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;
repeat {
rand = generateRandomVector(min, max);
} while(simd_length(rand) > maxlength)

return vector_float3(x, y, z)
}
return simd_normalize(rand)
}

func matrix_ortho_left_hand(
left: Float, right: Float, bottom: Float, top: Float, nearZ: Float, farZ: Float
) -> matrix_float4x4 {
return matrix_make_rows(
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 );
}
static func generateRandomVector(_ min: Float, _ max: Float) -> vector_float3 {
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;

return vector_float3(x, y, z)
}

static func matrixOrthoLeftHand(
left: Float, right: Float, bottom: Float, top: Float, nearZ: Float, farZ: Float
) -> matrix_float4x4 {
return matriMakeRows(
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 );
}

func matrix_make_rows(
_ m00: Float, _ m10: Float, _ m20: Float, _ m30: Float,
_ m01: Float, _ m11: Float, _ m21: Float, _ m31: Float,
_ m02: Float, _ m12: Float, _ m22: Float, _ m32: Float,
_ m03: Float, _ m13: Float, _ m23: Float, _ m33: Float
) -> matrix_float4x4 {
return matrix_float4x4([
[ m00, m01, m02, m03 ], // each line here provides column data
[ m10, m11, m12, m13 ],
[ m20, m21, m22, m23 ],
[ m30, m31, m32, m33 ] ] )
static func matriMakeRows(
_ m00: Float, _ m10: Float, _ m20: Float, _ m30: Float,
_ m01: Float, _ m11: Float, _ m21: Float, _ m31: Float,
_ m02: Float, _ m12: Float, _ m22: Float, _ m32: Float,
_ m03: Float, _ m13: Float, _ m23: Float, _ m33: Float
) -> matrix_float4x4 {
return matrix_float4x4([
[ m00, m01, m02, m03 ], // each line here provides column data
[ m10, m11, m12, m13 ],
[ m20, m21, m22, m23 ],
[ m30, m31, m32, m33 ] ] )
}
}
Loading

0 comments on commit cdab266

Please sign in to comment.