From 1aa620380b30c5e116a5c35bb7643ee906f4075e Mon Sep 17 00:00:00 2001 From: _Redstone_c_ Date: Sun, 31 Jan 2021 20:51:35 +0800 Subject: [PATCH] Job System - Done! --- Assets/Scenes/SampleScene.unity | 2 +- Assets/Script/Fractal.cs | 123 +++++++++++------- Assets/Script/PartGPU.hlsl | 8 +- Packages/manifest.json | 1 + Packages/packages-lock.json | 16 +++ .../BurstAotSettings_StandaloneWindows.json | 16 +++ ProjectSettings/ProjectSettings.asset | 3 +- 7 files changed, 116 insertions(+), 53 deletions(-) create mode 100644 ProjectSettings/BurstAotSettings_StandaloneWindows.json diff --git a/Assets/Scenes/SampleScene.unity b/Assets/Scenes/SampleScene.unity index 6eabfed..2a71772 100644 --- a/Assets/Scenes/SampleScene.unity +++ b/Assets/Scenes/SampleScene.unity @@ -150,7 +150,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: bef3764eec961e04db4297ce68f82391, type: 3} m_Name: m_EditorClassIdentifier: - depth: 6 + depth: 8 mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} material: {fileID: 2100000, guid: 8f3914ac4291e664ba60ae208ae66460, type: 2} --- !u!4 &197491476 diff --git a/Assets/Script/Fractal.cs b/Assets/Script/Fractal.cs index 06bab9d..a26f3cd 100644 --- a/Assets/Script/Fractal.cs +++ b/Assets/Script/Fractal.cs @@ -1,17 +1,56 @@ -using UnityEngine; +using Unity.Burst; +using Unity.Collections; +using Unity.Jobs; +using Unity.Mathematics; +using UnityEngine; + +using static Unity.Mathematics.math; +using quaternion = Unity.Mathematics.quaternion; public class Fractal : MonoBehaviour { + [BurstCompile(FloatPrecision.Standard, FloatMode.Fast, CompileSynchronously = true)] + private struct UpdateFractalLevelJob : IJobFor + { + public float spinAngleDelta; + public float scale; + + [ReadOnly] + public NativeArray parents; + + public NativeArray parts; + + [WriteOnly] + public NativeArray matrices; + + public void Execute(int i) + { + var parent = parents[i / 5]; + var part = parts[i]; + part.spinAngle += spinAngleDelta; + part.worldRotation = mul(parent.worldRotation, + mul(part.rotation, quaternion.RotateY(part.spinAngle)) + ); + part.worldPosition = + parent.worldPosition + + mul(parent.worldRotation, 1.5f * scale * part.direction); + parts[i] = part; + + float3x3 r = float3x3(part.worldRotation) * scale; + matrices[i] = float3x4(r.c0, r.c1, r.c2, part.worldPosition); + } + } + private struct FractalPart { - public Vector3 direction, worldPosition; - public Quaternion rotation, worldRotation; + public float3 direction, worldPosition; + public quaternion rotation, worldRotation; public float spinAngle; } - FractalPart[][] parts; + NativeArray[] parts; - Matrix4x4[][] matrices; + NativeArray[] matrices; [SerializeField, Range(1, 8)] int depth = 4; @@ -22,22 +61,16 @@ public class Fractal : MonoBehaviour [SerializeField] Material material = default; - static Vector3[] directions = + static float3[] directions = { - Vector3.up, - Vector3.right, - Vector3.left, - Vector3.forward, - Vector3.back + up(), right(), left(), forward(), back() }; - static Quaternion[] rotations = + static quaternion[] rotations = { - Quaternion.identity, - Quaternion.Euler(0f, 0f, -90f), - Quaternion.Euler(0f, 0f, 90f), - Quaternion.Euler(90f, 0f, 0f), - Quaternion.Euler(-90f, 0f, 0f) + quaternion.identity, + quaternion.RotateZ(-0.5f * PI), quaternion.RotateZ(0.5f * PI), + quaternion.RotateX(0.5f * PI), quaternion.RotateX(-0.5f * PI) }; private FractalPart CreatePart(int childIndex) @@ -57,21 +90,21 @@ public class Fractal : MonoBehaviour private void OnEnable() { - parts = new FractalPart[depth][]; - matrices = new Matrix4x4[depth][]; + parts = new NativeArray[depth]; + matrices = new NativeArray[depth]; matricesBuffers = new ComputeBuffer[depth]; - int stride = 16 * 4; + int stride = 12 * 4; for (int i = 0, length = 1; i < parts.Length; i++, length *= 5) { - parts[i] = new FractalPart[length]; - matrices[i] = new Matrix4x4[length]; + parts[i] = new NativeArray(length, Allocator.Persistent); + matrices[i] = new NativeArray(length, Allocator.Persistent); matricesBuffers[i] = new ComputeBuffer(length, stride); } parts[0][0] = CreatePart(0); for (int li = 1; li < parts.Length; li++) { - FractalPart[] levelParts = parts[li]; + NativeArray levelParts = parts[li]; for (int fpi = 0; fpi < levelParts.Length; fpi += 5) { for (int ci = 0; ci < 5; ci++) @@ -92,6 +125,8 @@ public class Fractal : MonoBehaviour for (int i = 0; i < matricesBuffers.Length; i++) { matricesBuffers[i].Release(); + parts[i].Dispose(); + matrices[i].Dispose(); } parts = null; matrices = null; @@ -109,45 +144,35 @@ public class Fractal : MonoBehaviour private void Update() { - float spinAngleDelta = 22.5f * Time.deltaTime; + float spinAngleDelta = 0.125f * PI * Time.deltaTime; FractalPart rootPart = parts[0][0]; rootPart.spinAngle += spinAngleDelta; - rootPart.worldRotation = - transform.rotation * - (rootPart.rotation * Quaternion.Euler(0f, rootPart.spinAngle, 0f)); + rootPart.worldRotation = mul(transform.rotation, + mul(rootPart.rotation, quaternion.RotateY(rootPart.spinAngle)) + ); rootPart.worldPosition = transform.position; parts[0][0] = rootPart; float objectScale = transform.lossyScale.x; - matrices[0][0] = Matrix4x4.TRS( - rootPart.worldPosition, rootPart.worldRotation, objectScale * Vector3.one - ); + float3x3 r = float3x3(rootPart.worldRotation) * objectScale; + matrices[0][0] = float3x4(r.c0, r.c1, r.c2, rootPart.worldPosition); float scale = objectScale; + JobHandle jobHandle = default; for (int li = 1; li < parts.Length; li++) { scale *= 0.5f; - FractalPart[] parentParts = parts[li - 1]; - FractalPart[] levelParts = parts[li]; - Matrix4x4[] levelMatrices = matrices[li]; - for (int fpi = 0; fpi < levelParts.Length; fpi++) + jobHandle = new UpdateFractalLevelJob { - var parent = parentParts[fpi / 5]; - var part = levelParts[fpi]; - part.spinAngle += spinAngleDelta; - part.worldRotation = - parent.worldRotation * - (part.rotation * Quaternion.Euler(0f, part.spinAngle, 0f)); - part.worldPosition = - parent.worldPosition + - parent.worldRotation * (1.5f * scale * part.direction); - levelParts[fpi] = part; - levelMatrices[fpi] = Matrix4x4.TRS( - part.worldPosition, part.worldRotation, scale * Vector3.one - ); - } + spinAngleDelta = spinAngleDelta, + scale = scale, + parents = parts[li - 1], + parts = parts[li], + matrices = matrices[li] + }.ScheduleParallel(parts[li].Length, 5, jobHandle); } + jobHandle.Complete(); - var bounds = new Bounds(rootPart.worldPosition, 3f * objectScale * Vector3.one); + var bounds = new Bounds(rootPart.worldPosition, float3(3f * objectScale)); for (int i = 0; i < matricesBuffers.Length; i++) { ComputeBuffer buffer = matricesBuffers[i]; diff --git a/Assets/Script/PartGPU.hlsl b/Assets/Script/PartGPU.hlsl index 34ea0c3..7b0bcdf 100644 --- a/Assets/Script/PartGPU.hlsl +++ b/Assets/Script/PartGPU.hlsl @@ -1,10 +1,14 @@ #if defined(UNITY_PROCEDURAL_INSTANCING_ENABLED) - StructuredBuffer _Matrices; + StructuredBuffer _Matrices; #endif void ConfigureProcedural () { #if defined(UNITY_PROCEDURAL_INSTANCING_ENABLED) - unity_ObjectToWorld = _Matrices[unity_InstanceID]; + float3x4 m = _Matrices[unity_InstanceID]; + unity_ObjectToWorld._m00_m01_m02_m03 = m._m00_m01_m02_m03; + unity_ObjectToWorld._m10_m11_m12_m13 = m._m10_m11_m12_m13; + unity_ObjectToWorld._m20_m21_m22_m23 = m._m20_m21_m22_m23; + unity_ObjectToWorld._m30_m31_m32_m33 = float4(0.0, 0.0, 0.0, 1.0); #endif } diff --git a/Packages/manifest.json b/Packages/manifest.json index bff4d1c..144a5cb 100644 --- a/Packages/manifest.json +++ b/Packages/manifest.json @@ -1,5 +1,6 @@ { "dependencies": { + "com.unity.burst": "1.4.4", "com.unity.render-pipelines.universal": "7.5.3", "com.unity.textmeshpro": "2.1.3", "com.unity.modules.ai": "1.0.0", diff --git a/Packages/packages-lock.json b/Packages/packages-lock.json index 10c33ec..d4d1861 100644 --- a/Packages/packages-lock.json +++ b/Packages/packages-lock.json @@ -1,5 +1,21 @@ { "dependencies": { + "com.unity.burst": { + "version": "1.4.4", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.mathematics": "1.2.1" + }, + "url": "https://packages.unity.cn" + }, + "com.unity.mathematics": { + "version": "1.2.1", + "depth": 1, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.cn" + }, "com.unity.render-pipelines.core": { "version": "7.5.3", "depth": 1, diff --git a/ProjectSettings/BurstAotSettings_StandaloneWindows.json b/ProjectSettings/BurstAotSettings_StandaloneWindows.json new file mode 100644 index 0000000..2144f6d --- /dev/null +++ b/ProjectSettings/BurstAotSettings_StandaloneWindows.json @@ -0,0 +1,16 @@ +{ + "MonoBehaviour": { + "Version": 3, + "EnableBurstCompilation": true, + "EnableOptimisations": true, + "EnableSafetyChecks": false, + "EnableDebugInAllBuilds": false, + "UsePlatformSDKLinker": false, + "CpuMinTargetX32": 0, + "CpuMaxTargetX32": 0, + "CpuMinTargetX64": 0, + "CpuMaxTargetX64": 0, + "CpuTargetsX32": 6, + "CpuTargetsX64": 72 + } +} diff --git a/ProjectSettings/ProjectSettings.asset b/ProjectSettings/ProjectSettings.asset index 451ef12..cb5b420 100644 --- a/ProjectSettings/ProjectSettings.asset +++ b/ProjectSettings/ProjectSettings.asset @@ -584,7 +584,8 @@ PlayerSettings: webGLWasmStreaming: 0 scriptingDefineSymbols: {} platformArchitecture: {} - scriptingBackend: {} + scriptingBackend: + Standalone: 0 il2cppCompilerConfiguration: {} managedStrippingLevel: {} incrementalIl2cppBuild: {}