diff --git a/crest/Assets/Crest/Crest-Examples/Shared/Scripts/Collision/OceanSampleDisplacementDemo.cs b/crest/Assets/Crest/Crest-Examples/Shared/Scripts/Collision/OceanSampleDisplacementDemo.cs
index 0a4587a65..d3bac3444 100644
--- a/crest/Assets/Crest/Crest-Examples/Shared/Scripts/Collision/OceanSampleDisplacementDemo.cs
+++ b/crest/Assets/Crest/Crest-Examples/Shared/Scripts/Collision/OceanSampleDisplacementDemo.cs
@@ -2,7 +2,9 @@
// This file is subject to the MIT License as seen in the root of this folder structure (LICENSE)
+using System;
using Crest;
+using Unity.Collections;
using UnityEngine;
///
@@ -26,13 +28,22 @@ public class OceanSampleDisplacementDemo : MonoBehaviour
public float _minGridSize = 0f;
GameObject[] _markerObjects = new GameObject[3];
- Vector3[] _markerPos = new Vector3[3];
- Vector3[] _resultDisps = new Vector3[3];
- Vector3[] _resultNorms = new Vector3[3];
- Vector3[] _resultVels = new Vector3[3];
+ NativeArray _markerPos;
+ NativeArray _resultDisps;
+ NativeArray _resultNorms;
+ NativeArray _resultVels;
float _samplesRadius = 5f;
+ private void Start()
+ {
+ _markerPos = new NativeArray(3, Allocator.Persistent);
+ _resultDisps = new NativeArray(3, Allocator.Persistent);
+ _resultNorms = new NativeArray(3, Allocator.Persistent);
+ _resultVels = new NativeArray(3, Allocator.Persistent);
+
+ }
+
void Update()
{
if (OceanRenderer.Instance == null)
@@ -52,7 +63,7 @@ void Update()
var collProvider = OceanRenderer.Instance.CollisionProvider;
- var status = collProvider.Query(GetHashCode(), _minGridSize, _markerPos, _resultDisps, _resultNorms, _resultVels);
+ var status = collProvider.Query(GetHashCode(), _minGridSize, ref _markerPos, ref _resultDisps, ref _resultNorms, ref _resultVels, true);
if (collProvider.RetrieveSucceeded(status))
{
diff --git a/crest/Assets/Crest/Crest/Scripts/Collision/CollProvider.cs b/crest/Assets/Crest/Crest/Scripts/Collision/CollProvider.cs
index d3605c19b..47e3201f1 100644
--- a/crest/Assets/Crest/Crest/Scripts/Collision/CollProvider.cs
+++ b/crest/Assets/Crest/Crest/Scripts/Collision/CollProvider.cs
@@ -4,6 +4,7 @@
// NOTE: DWP2 depends on this file. Any API changes need to be communicated to the DWP2 authors in advance.
+using Unity.Collections;
using UnityEngine;
namespace Crest
@@ -22,7 +23,12 @@ public interface ICollProvider
/// Float array of water heights at the query positions. Pass null if this information is not required.
/// Water normals at the query positions. Pass null if this information is not required.
/// Water surface velocities at the query positions. Pass null if this information is not required.
- int Query(int i_ownerHash, float i_minSpatialLength, Vector3[] i_queryPoints, float[] o_resultHeights, Vector3[] o_resultNorms, Vector3[] o_resultVels);
+ int Query(int i_ownerHash,
+ float i_minSpatialLength,
+ ref NativeArray i_queryPoints,
+ ref NativeArray o_resultHeights,
+ ref NativeArray o_resultNorms,
+ ref NativeArray o_resultVels);
///
/// Query water physical data at a set of points. Pass in null to any out parameters that are not required.
@@ -33,7 +39,14 @@ public interface ICollProvider
/// Displacement vectors for water surface points that will displace to the XZ coordinates of the query points. Water heights are given by sea level plus the y component of the displacement.
/// Water normals at the query positions. Pass null if this information is not required.
/// Water surface velocities at the query positions. Pass null if this information is not required.
- int Query(int i_ownerHash, float i_minSpatialLength, Vector3[] i_queryPoints, Vector3[] o_resultDisps, Vector3[] o_resultNorms, Vector3[] o_resultVels);
+ ///
+ int Query(int i_ownerHash,
+ float i_minSpatialLength,
+ ref NativeArray i_queryPoints,
+ ref NativeArray o_resultDisps,
+ ref NativeArray o_resultNorms,
+ ref NativeArray o_resultVels,
+ bool useNormals);
///
/// Check if query results could be retrieved successfully using return code from Query() function
diff --git a/crest/Assets/Crest/Crest/Scripts/Collision/CollProviderBakedFFT.cs b/crest/Assets/Crest/Crest/Scripts/Collision/CollProviderBakedFFT.cs
index da919d51d..f0d2993ef 100644
--- a/crest/Assets/Crest/Crest/Scripts/Collision/CollProviderBakedFFT.cs
+++ b/crest/Assets/Crest/Crest/Scripts/Collision/CollProviderBakedFFT.cs
@@ -72,7 +72,9 @@ class QueryData
/// position data will be created. This will force any running jobs to complete. The jobs will be kicked off in LateUpdate,
/// so this should be called before the kick-off, such as from Update.
///
- public int RegisterQueryPoints(int ownerHash, Vector3[] queryPoints, int dataToWriteThisFrame)
+ public int RegisterQueryPoints(int ownerHash,
+ ref NativeArray queryPoints,
+ int dataToWriteThisFrame)
{
var numQuads = (queryPoints.Length + 3) / 4;
@@ -222,7 +224,7 @@ public CollProviderBakedFFT(FFTBakedData data)
}
}
- bool RetrieveHeights(int i_ownerHash, float[] o_resultHeights)
+ bool RetrieveHeights(int i_ownerHash, NativeArray o_resultHeights)
{
// Return data - get segment from finished jobs
if (o_resultHeights != null && _queryDataHeights._segmentRegistryQueriesResults.TryGetValue(i_ownerHash, out var computedQuerySegment))
@@ -238,7 +240,7 @@ bool RetrieveHeights(int i_ownerHash, float[] o_resultHeights)
return false;
}
- bool RetrieveDisps(int i_ownerHash, Vector3[] o_resultDisps)
+ bool RetrieveDisps(int i_ownerHash, NativeArray o_resultDisps)
{
// Return data - get segment from finished jobs
if (o_resultDisps != null && _queryDataDisps._segmentRegistryQueriesResults.TryGetValue(i_ownerHash, out var computedQuerySegment))
@@ -258,7 +260,7 @@ bool RetrieveDisps(int i_ownerHash, Vector3[] o_resultDisps)
return false;
}
- bool RetrieveNorms(int i_ownerHash, Vector3[] o_resultNorms)
+ bool RetrieveNorms(int i_ownerHash, NativeArray o_resultNorms)
{
if (o_resultNorms != null && _queryDataNorms._segmentRegistryQueriesResults.TryGetValue(i_ownerHash, out var computedQuerySegment))
{
@@ -277,7 +279,7 @@ bool RetrieveNorms(int i_ownerHash, Vector3[] o_resultNorms)
return false;
}
- bool RetrieveVels(int i_ownerHash, Vector3[] o_resultVels)
+ bool RetrieveVels(int i_ownerHash, NativeArray o_resultVels)
{
if (o_resultVels != null && _queryDataVels._segmentRegistryQueriesResults.TryGetValue(i_ownerHash, out var computedQuerySegment))
{
@@ -294,14 +296,12 @@ bool RetrieveVels(int i_ownerHash, Vector3[] o_resultVels)
return false;
}
- public int Query(
- int i_ownerHash,
+ public int Query(int i_ownerHash,
float i_minSpatialLength,
- Vector3[] i_queryPoints,
- float[] o_resultHeights,
- Vector3[] o_resultNorms,
- Vector3[] o_resultVels
- )
+ ref NativeArray i_queryPoints,
+ ref NativeArray o_resultHeights,
+ ref NativeArray o_resultNorms,
+ ref NativeArray o_resultVels)
{
var dataCopiedOutHeights = RetrieveHeights(i_ownerHash, o_resultHeights);
var dataCopiedOutNorms = RetrieveNorms(i_ownerHash, o_resultNorms);
@@ -309,15 +309,15 @@ Vector3[] o_resultVels
if (o_resultHeights != null)
{
- _queryDataHeights.RegisterQueryPoints(i_ownerHash, i_queryPoints, 1 - _dataBeingUsedByJobs);
+ _queryDataHeights.RegisterQueryPoints(i_ownerHash, ref i_queryPoints, 1 - _dataBeingUsedByJobs);
}
if (o_resultNorms != null)
{
- _queryDataNorms.RegisterQueryPoints(i_ownerHash, i_queryPoints, 1 - _dataBeingUsedByJobs);
+ _queryDataNorms.RegisterQueryPoints(i_ownerHash, ref i_queryPoints, 1 - _dataBeingUsedByJobs);
}
if (o_resultVels != null)
{
- _queryDataVels.RegisterQueryPoints(i_ownerHash, i_queryPoints, 1 - _dataBeingUsedByJobs);
+ _queryDataVels.RegisterQueryPoints(i_ownerHash, ref i_queryPoints, 1 - _dataBeingUsedByJobs);
}
var allCopied = (dataCopiedOutHeights || o_resultHeights == null)
@@ -327,14 +327,13 @@ Vector3[] o_resultVels
return allCopied ? (int)QueryStatus.Success : (int)QueryStatus.ResultsNotReadyYet;
}
- public int Query(
- int i_ownerHash,
+ public int Query(int i_ownerHash,
float i_minSpatialLength,
- Vector3[] i_queryPoints,
- Vector3[] o_resultDisps,
- Vector3[] o_resultNorms,
- Vector3[] o_resultVels
- )
+ ref NativeArray i_queryPoints,
+ ref NativeArray o_resultDisps,
+ ref NativeArray o_resultNorms,
+ ref NativeArray o_resultVels,
+ bool useNormals)
{
var dataCopiedOutDisps = RetrieveDisps(i_ownerHash, o_resultDisps);
var dataCopiedOutNorms = RetrieveNorms(i_ownerHash, o_resultNorms);
@@ -342,15 +341,15 @@ Vector3[] o_resultVels
if (o_resultDisps != null)
{
- _queryDataDisps.RegisterQueryPoints(i_ownerHash, i_queryPoints, 1 - _dataBeingUsedByJobs);
+ _queryDataDisps.RegisterQueryPoints(i_ownerHash, ref i_queryPoints, 1 - _dataBeingUsedByJobs);
}
if (o_resultNorms != null)
{
- _queryDataNorms.RegisterQueryPoints(i_ownerHash, i_queryPoints, 1 - _dataBeingUsedByJobs);
+ _queryDataNorms.RegisterQueryPoints(i_ownerHash, ref i_queryPoints, 1 - _dataBeingUsedByJobs);
}
if (o_resultVels != null)
{
- _queryDataVels.RegisterQueryPoints(i_ownerHash, i_queryPoints, 1 - _dataBeingUsedByJobs);
+ _queryDataVels.RegisterQueryPoints(i_ownerHash, ref i_queryPoints, 1 - _dataBeingUsedByJobs);
}
var allCopied = (dataCopiedOutDisps || o_resultDisps == null)
diff --git a/crest/Assets/Crest/Crest/Scripts/Collision/CollProviderNull.cs b/crest/Assets/Crest/Crest/Scripts/Collision/CollProviderNull.cs
index cb8181efb..7781b36bc 100644
--- a/crest/Assets/Crest/Crest/Scripts/Collision/CollProviderNull.cs
+++ b/crest/Assets/Crest/Crest/Scripts/Collision/CollProviderNull.cs
@@ -2,6 +2,7 @@
// This file is subject to the MIT License as seen in the root of this folder structure (LICENSE)
+using Unity.Collections;
using UnityEngine;
namespace Crest
@@ -11,7 +12,13 @@ namespace Crest
///
public class CollProviderNull : ICollProvider
{
- public int Query(int i_ownerHash, float i_minSpatialLength, Vector3[] i_queryPoints, Vector3[] o_resultDisps, Vector3[] o_resultNorms, Vector3[] o_resultVels)
+ public int Query(int i_ownerHash,
+ float i_minSpatialLength,
+ ref NativeArray i_queryPoints,
+ ref NativeArray o_resultDisps,
+ ref NativeArray o_resultNorms,
+ ref NativeArray o_resultVels,
+ bool useNormals)
{
if (o_resultDisps != null)
{
@@ -40,7 +47,12 @@ public int Query(int i_ownerHash, float i_minSpatialLength, Vector3[] i_queryPoi
return 0;
}
- public int Query(int i_ownerHash, float i_minSpatialLength, Vector3[] i_queryPoints, float[] o_resultHeights, Vector3[] o_resultNorms, Vector3[] o_resultVels)
+ public int Query(int i_ownerHash,
+ float i_minSpatialLength,
+ ref NativeArray i_queryPoints,
+ ref NativeArray o_resultHeights,
+ ref NativeArray o_resultNorms,
+ ref NativeArray o_resultVels)
{
if (o_resultHeights != null)
{
diff --git a/crest/Assets/Crest/Crest/Scripts/Collision/FlowProvider.cs b/crest/Assets/Crest/Crest/Scripts/Collision/FlowProvider.cs
index 024941e9d..39ff5cd95 100644
--- a/crest/Assets/Crest/Crest/Scripts/Collision/FlowProvider.cs
+++ b/crest/Assets/Crest/Crest/Scripts/Collision/FlowProvider.cs
@@ -2,6 +2,7 @@
// This file is subject to the MIT License as seen in the root of this folder structure (LICENSE)
+using Unity.Collections;
using UnityEngine;
namespace Crest
@@ -17,8 +18,12 @@ public interface IFlowProvider
/// Unique ID for calling code. Typically acquired by calling GetHashCode().
/// The min spatial length of the object, such as the width of a boat. Useful for filtering out detail when not needed. Set to 0 to get full available detail.
/// The world space points that will be queried.
+ ///
/// Water surface flow velocities at the query positions.
- int Query(int i_ownerHash, float i_minSpatialLength, Vector3[] i_queryPoints, Vector3[] o_resultFlows);
+ int Query(int i_ownerHash,
+ float i_minSpatialLength,
+ ref NativeArray i_queryPoints,
+ ref NativeArray o_resultFlows);
///
/// Check if query results could be retrieved successfully using return code from Query() function
diff --git a/crest/Assets/Crest/Crest/Scripts/Collision/FlowProviderNull.cs b/crest/Assets/Crest/Crest/Scripts/Collision/FlowProviderNull.cs
index bba826696..855353258 100644
--- a/crest/Assets/Crest/Crest/Scripts/Collision/FlowProviderNull.cs
+++ b/crest/Assets/Crest/Crest/Scripts/Collision/FlowProviderNull.cs
@@ -2,6 +2,7 @@
// This file is subject to the MIT License as seen in the root of this folder structure (LICENSE)
+using Unity.Collections;
using UnityEngine;
namespace Crest
@@ -11,7 +12,10 @@ namespace Crest
///
public class FlowProviderNull : IFlowProvider
{
- public int Query(int i_ownerHash, float i_minSpatialLength, Vector3[] i_queryPoints, Vector3[] o_resultFlows)
+ public int Query(int i_ownerHash,
+ float i_minSpatialLength,
+ ref NativeArray i_queryPoints,
+ ref NativeArray o_resultFlows)
{
if (o_resultFlows != null)
{
diff --git a/crest/Assets/Crest/Crest/Scripts/Collision/QueryBase.cs b/crest/Assets/Crest/Crest/Scripts/Collision/QueryBase.cs
index cfd454f04..79ef839ed 100644
--- a/crest/Assets/Crest/Crest/Scripts/Collision/QueryBase.cs
+++ b/crest/Assets/Crest/Crest/Scripts/Collision/QueryBase.cs
@@ -7,7 +7,9 @@
// - Half minGridSize
using System.Collections.Generic;
+using Unity.Burst;
using Unity.Collections;
+using Unity.Collections.LowLevel.Unsafe;
using UnityEngine;
using UnityEngine.Rendering;
@@ -18,6 +20,7 @@ namespace Crest
/// the data and then transferring back the results asynchronously. An exception to this is water surface velocities - these can
/// not be computed on the GPU and are instead computed on the CPU by retaining last frames' query results and computing finite diffs.
///
+ [BurstCompile]
public abstract class QueryBase
{
protected int _kernelHandle;
@@ -49,16 +52,16 @@ public abstract class QueryBase
public const int MAX_QUERY_COUNT_DEFAULT = 4096;
int _maxQueryCount = MAX_QUERY_COUNT_DEFAULT;
- Vector3[] _queryPosXZ_minGridSize = new Vector3[MAX_QUERY_COUNT_DEFAULT];
+ NativeArray _queryPosXZ_minGridSize;
///
/// Holds information about all query points. Maps from unique hash code to position in point array.
///
- class SegmentRegistrar
+ struct SegmentRegistrar
{
// Map from guids to (segment start index, segment end index, frame number when query was made)
- public Dictionary _segments = new Dictionary();
- public int _numQueries = 0;
+ public NativeParallelHashMap _segments;
+ public int _numQueries;
}
///
@@ -70,18 +73,20 @@ class SegmentRegistrarRingBuffer
// Requests in flight plus 2 held values, plus one current
readonly static int s_poolSize = s_maxRequests + 2 + 1;
- SegmentRegistrar[] _segments = new SegmentRegistrar[s_poolSize];
+ SegmentRegistrar[] _segments;
public int _segmentRelease = 0;
public int _segmentAcquire = 0;
- public SegmentRegistrar Current => _segments[_segmentAcquire];
+ public ref SegmentRegistrar Current => ref _segments[_segmentAcquire];
public SegmentRegistrarRingBuffer()
{
+ _segments = new SegmentRegistrar[s_poolSize];
for (int i = 0; i < _segments.Length; i++)
{
_segments[i] = new SegmentRegistrar();
+ _segments[i]._segments = new NativeParallelHashMap(16, Allocator.Persistent);
}
}
@@ -183,6 +188,7 @@ public void ClearAll()
{
_segments[i]._numQueries = 0;
_segments[i]._segments.Clear();
+ _segments[i]._segments.Dispose();
}
}
}
@@ -191,17 +197,17 @@ public void ClearAll()
NativeArray _queryResults;
float _queryResultsTime = -1f;
- Dictionary _resultSegments;
+ NativeParallelHashMap _resultSegments;
NativeArray _queryResultsLast;
float _queryResultsTimeLast = -1f;
- Dictionary _resultSegmentsLast;
+ NativeParallelHashMap _resultSegmentsLast;
struct ReadbackRequest
{
public AsyncGPUReadbackRequest _request;
public float _dataTimestamp;
- public Dictionary _segments;
+ public NativeParallelHashMap _segments;
}
List _requests = new List();
@@ -223,7 +229,11 @@ public QueryBase()
if (_maxQueryCount != OceanRenderer.Instance._lodDataAnimWaves.Settings.MaxQueryCount)
{
_maxQueryCount = OceanRenderer.Instance._lodDataAnimWaves.Settings.MaxQueryCount;
- _queryPosXZ_minGridSize = new Vector3[_maxQueryCount];
+ _queryPosXZ_minGridSize = new NativeArray(_maxQueryCount, Allocator.Persistent);
+ }
+ else
+ {
+ _queryPosXZ_minGridSize = new NativeArray(MAX_QUERY_COUNT_DEFAULT, Allocator.Persistent);
}
_computeBufQueries = new ComputeBuffer(_maxQueryCount, 12, ComputeBufferType.Default);
@@ -244,39 +254,101 @@ public QueryBase()
protected abstract void BindInputsAndOutputs(PropertyWrapperComputeStandalone wrapper, ComputeBuffer resultsBuffer);
+
///
/// Takes a unique request ID and some world space XZ positions, and computes the displacement vector that lands at this position,
/// to a good approximation. The world space height of the water at that position is then SeaLevel + displacement.y.
///
- protected bool UpdateQueryPoints(int i_ownerHash, float i_minSpatialLength, Vector3[] queryPoints, Vector3[] queryNormals)
+ protected bool UpdateQueryPoints(int i_ownerHash,
+ float i_minSpatialLength,
+ NativeArray queryPoints,
+ NativeArray queryNormals,
+ bool useNormals)
{
- if (queryPoints.Length + _segmentRegistrarRingBuffer.Current._numQueries > _maxQueryCount)
+ unsafe
{
- Debug.LogError($"Crest: Max query count ({_maxQueryCount}) exceeded, increase the max query count in the Animated Waves Settings to support a higher number of queries.");
+ var args = new UQPArgs()
+ {
+ i_ownerHash = i_ownerHash,
+ i_minSpatialLength = i_minSpatialLength,
+ queryPoints = queryPoints,
+ queryNormals = queryNormals,
+ useNormals = (byte)(useNormals ? 1 : 0),
+ sqrrbNumQueries = _segmentRegistrarRingBuffer.Current._numQueries,
+ _maxQueryCount = _maxQueryCount,
+ sqrrbCurrentSegments = _segmentRegistrarRingBuffer.Current._segments,
+ _queryPosXZ_minGridSize = _queryPosXZ_minGridSize
+ };
+ var ret = UpdateQueryPoints(UnsafeUtility.AddressOf(ref args));
+
+ _segmentRegistrarRingBuffer.Current._numQueries = args.sqrrbNumQueries;
+ _segmentRegistrarRingBuffer.Current._segments = args.sqrrbCurrentSegments;
+ _queryPosXZ_minGridSize = args._queryPosXZ_minGridSize;
+ return ret;
+ }
+ }
+
+ /*
+ * The below little dance is required to pass native collections as arguments to burst-compiled static functions
+ * on the main thread in unity 22.1 and below. It mirrors what the job system does internally for job structs.
+ * Basically, in 22.1 and below, native collections all have DisposeSentinel objects in them, which
+ * _technically_ makes them managed objects, and which Burst will therefore not accept as arguments to a
+ * Burst-entrypoint static function.
+ *
+ * However, Burst can compile code *using* native collections just fine, which is how bursted jobs can work.
+ * We just need to trick it into having access to them, which we do via UnsafeUtility.AsRef.
+ *
+ * The only difference between what this does and what the job system does is that the job system sets the
+ * disposesentinel fields to null when it copies the job struct to the worker threads, whereas we aren't copying
+ * them anyway, so we just leave them alone.
+ *
+ * In 22.2, DisposeSentinel is no longer a class, and so this can likely be revisited.
+ */
+ struct UQPArgs
+ {
+ public int i_ownerHash;
+ public float i_minSpatialLength;
+ public NativeArray queryPoints;
+ public NativeArray queryNormals;
+ public byte useNormals;
+ public int sqrrbNumQueries;
+ public int _maxQueryCount;
+ public NativeParallelHashMap sqrrbCurrentSegments;
+ public NativeArray _queryPosXZ_minGridSize;
+ }
+
+ [BurstCompile]
+ protected static unsafe bool UpdateQueryPoints(void *args)
+ {
+ ref var realargs = ref UnsafeUtility.AsRef(args);
+
+ if (realargs.queryPoints.Length + realargs.sqrrbNumQueries > realargs._maxQueryCount)
+ {
+ Debug.LogError($"Crest: Max query count ({realargs._maxQueryCount}) exceeded, increase the max query count in the Animated Waves Settings to support a higher number of queries.");
return false;
}
var segmentRetrieved = false;
// We'll send in 3 points to get normals
- var countPts = (queryPoints != null ? queryPoints.Length : 0);
- var countNorms = (queryNormals != null ? queryNormals.Length : 0);
+ var countPts = realargs.queryPoints.Length;
+ var countNorms = (realargs.useNormals != 0 ? realargs.queryNormals.Length : 0);
var countTotal = countPts + countNorms * 3;
- if (_segmentRegistrarRingBuffer.Current._segments.TryGetValue(i_ownerHash, out var segment))
+ if (realargs.sqrrbCurrentSegments.TryGetValue(realargs.i_ownerHash, out var segment))
{
var segmentSize = segment.y - segment.x + 1;
if (segmentSize == countTotal)
{
// Update frame count
segment.z = Time.frameCount;
- _segmentRegistrarRingBuffer.Current._segments[i_ownerHash] = segment;
+ realargs.sqrrbCurrentSegments[realargs.i_ownerHash] = segment;
segmentRetrieved = true;
}
else
{
- _segmentRegistrarRingBuffer.Current._segments.Remove(i_ownerHash);
+ realargs.sqrrbCurrentSegments.Remove(realargs.i_ownerHash);
}
}
@@ -288,39 +360,42 @@ protected bool UpdateQueryPoints(int i_ownerHash, float i_minSpatialLength, Vect
if (!segmentRetrieved)
{
- if (_segmentRegistrarRingBuffer.Current._segments.Count >= s_maxGuids)
+ if (realargs.sqrrbCurrentSegments.Count() >= s_maxGuids)
{
Debug.LogError("Crest: Too many guids registered with CollProviderCompute. Increase s_maxGuids.");
return false;
}
- segment.x = _segmentRegistrarRingBuffer.Current._numQueries;
+ segment.x = realargs.sqrrbNumQueries;
segment.y = segment.x + countTotal - 1;
segment.z = Time.frameCount;
- _segmentRegistrarRingBuffer.Current._segments.Add(i_ownerHash, segment);
+ realargs.sqrrbCurrentSegments.Add(realargs.i_ownerHash, segment);
- _segmentRegistrarRingBuffer.Current._numQueries += countTotal;
+ realargs.sqrrbNumQueries += countTotal;
//Debug.Log("Crest: Added points for " + guid);
}
// The smallest wavelengths should repeat no more than twice across the smaller spatial length. Unless we're
// in the last LOD - then this is the best we can do.
- float minWavelength = i_minSpatialLength / 2f;
+ float minWavelength = realargs.i_minSpatialLength / 2f;
float samplesPerWave = 2f;
float minGridSize = minWavelength / samplesPerWave;
- if (countPts + segment.x > _queryPosXZ_minGridSize.Length)
+ if (countPts + segment.x > realargs._queryPosXZ_minGridSize.Length)
{
Debug.LogError("Crest: Too many wave height queries. Increase Max Query Count in the Animated Waves Settings.");
return false;
}
+ Vector3 tmp;
for (int pointi = 0; pointi < countPts; pointi++)
{
- _queryPosXZ_minGridSize[pointi + segment.x].x = queryPoints[pointi].x;
- _queryPosXZ_minGridSize[pointi + segment.x].y = queryPoints[pointi].z;
- _queryPosXZ_minGridSize[pointi + segment.x].z = minGridSize;
+ tmp = realargs._queryPosXZ_minGridSize[pointi + segment.x];
+ tmp.x = realargs.queryPoints[pointi].x;
+ tmp.y = realargs.queryPoints[pointi].z;
+ tmp.z = minGridSize;
+ realargs._queryPosXZ_minGridSize[pointi + segment.x] = tmp;
}
// To compute each normal, post 3 query points
@@ -328,17 +403,23 @@ protected bool UpdateQueryPoints(int i_ownerHash, float i_minSpatialLength, Vect
{
var arrIdx = segment.x + countPts + 3 * normi;
- _queryPosXZ_minGridSize[arrIdx + 0].x = queryNormals[normi].x;
- _queryPosXZ_minGridSize[arrIdx + 0].y = queryNormals[normi].z;
- _queryPosXZ_minGridSize[arrIdx + 0].z = minGridSize;
+ tmp = realargs._queryPosXZ_minGridSize[arrIdx + 0];
+ tmp.x = realargs.queryNormals[normi].x;
+ tmp.y = realargs.queryNormals[normi].z;
+ tmp.z = minGridSize;
+ realargs._queryPosXZ_minGridSize[arrIdx + 0] = tmp;
- _queryPosXZ_minGridSize[arrIdx + 1].x = queryNormals[normi].x + s_finiteDiffDx;
- _queryPosXZ_minGridSize[arrIdx + 1].y = queryNormals[normi].z;
- _queryPosXZ_minGridSize[arrIdx + 1].z = minGridSize;
+ tmp = realargs._queryPosXZ_minGridSize[arrIdx + 1];
+ tmp.x = realargs.queryNormals[normi].x + s_finiteDiffDx;
+ tmp.y = realargs.queryNormals[normi].z;
+ tmp.z = minGridSize;
+ realargs._queryPosXZ_minGridSize[arrIdx + 1] = tmp;
- _queryPosXZ_minGridSize[arrIdx + 2].x = queryNormals[normi].x;
- _queryPosXZ_minGridSize[arrIdx + 2].y = queryNormals[normi].z + s_finiteDiffDx;
- _queryPosXZ_minGridSize[arrIdx + 2].z = minGridSize;
+ tmp = realargs._queryPosXZ_minGridSize[arrIdx + 2];
+ tmp.x = realargs.queryNormals[normi].x;
+ tmp.y = realargs.queryNormals[normi].z + s_finiteDiffDx;
+ tmp.z = minGridSize;
+ realargs._queryPosXZ_minGridSize[arrIdx + 2] = tmp;
}
return true;
@@ -364,9 +445,12 @@ public void CompactQueryStorage()
///
/// Copy out displacements, heights, normals. Pass null if info is not required.
///
- protected bool RetrieveResults(int guid, Vector3[] displacements, float[] heights, Vector3[] normals)
+ protected bool RetrieveResults(int guid,
+ NativeArray displacements,
+ NativeArray heights,
+ NativeArray normals)
{
- if (_resultSegments == null)
+ if (!_resultSegments.IsCreated)
{
return false;
}
@@ -379,18 +463,18 @@ protected bool RetrieveResults(int guid, Vector3[] displacements, float[] height
}
var countPoints = 0;
- if (displacements != null) countPoints = displacements.Length;
- if (heights != null) countPoints = heights.Length;
- if (displacements != null && heights != null) Debug.Assert(displacements.Length == heights.Length);
- var countNorms = (normals != null ? normals.Length : 0);
+ if (displacements.Length > 0) countPoints = displacements.Length;
+ if (heights.Length > 0) countPoints = heights.Length;
+ if (displacements.Length > 0 && heights.Length > 0) Debug.Assert(displacements.Length == heights.Length);
+ var countNorms = normals.Length;
if (countPoints > 0)
{
// Retrieve Results
- if (displacements != null) _queryResults.Slice(segment.x, countPoints).CopyTo(displacements);
+ if (displacements.Length > 0) _queryResults.Slice(segment.x, countPoints).CopyTo(displacements);
// Retrieve Result heights
- if (heights != null)
+ if (heights.Length > 0)
{
var seaLevel = OceanRenderer.Instance.SeaLevel;
for (int i = 0; i < countPoints; i++)
@@ -412,8 +496,9 @@ protected bool RetrieveResults(int guid, Vector3[] displacements, float[] height
var px = dx + _queryResults[firstNorm + 3 * i + 1];
var pz = dz + _queryResults[firstNorm + 3 * i + 2];
- normals[i] = Vector3.Cross(p - px, p - pz).normalized;
- normals[i].y *= -1f;
+ var tmp = Vector3.Cross(p - px, p - pz).normalized;
+ tmp.y *= -1f;
+ normals[i] = tmp;
}
}
@@ -424,20 +509,50 @@ protected bool RetrieveResults(int guid, Vector3[] displacements, float[] height
/// Compute time derivative of the displacements by calculating difference from last query. More complicated than it would seem - results
/// may not be available in one or both of the results, or the query locations in the array may change.
///
- protected int CalculateVelocities(int i_ownerHash, Vector3[] results)
+ protected unsafe int CalculateVelocities(int i_ownerHash, NativeArray results)
{
+ var args = new CVArgs()
+ {
+ i_ownerHash = i_ownerHash,
+ _queryResultsTime = _queryResultsTime,
+ _queryResultsTimeLast = _queryResultsTimeLast,
+ _resultSegments = _resultSegments,
+ _resultSegmentsLast = _resultSegmentsLast,
+ results = results,
+ _queryResults = _queryResults,
+ _queryResultsLast = _queryResultsLast
+ };
+ return CalculateVelocities(UnsafeUtility.AddressOf(ref args));
+ }
+
+ //see comment on UQPArgs as to why we are doing this dance
+ struct CVArgs
+ {
+ public int i_ownerHash;
+ public float _queryResultsTime;
+ public float _queryResultsTimeLast;
+ public NativeParallelHashMap _resultSegments;
+ public NativeParallelHashMap _resultSegmentsLast;
+ public NativeArray results;
+ public NativeArray _queryResults;
+ public NativeArray _queryResultsLast;
+ }
+ [BurstCompile]
+ protected static unsafe int CalculateVelocities(void* args)
+ {
+ ref var realargs = ref UnsafeUtility.AsRef(args);
// Need at least 2 returned results to do finite difference
- if (_queryResultsTime < 0f || _queryResultsTimeLast < 0f)
+ if (realargs._queryResultsTime < 0f || realargs._queryResultsTimeLast < 0f)
{
return 1;
}
- if (!_resultSegments.TryGetValue(i_ownerHash, out var segment))
+ if (!realargs._resultSegments.TryGetValue(realargs.i_ownerHash, out var segment))
{
return (int)QueryStatus.RetrieveFailed;
}
- if (!_resultSegmentsLast.TryGetValue(i_ownerHash, out var segmentLast))
+ if (!realargs._resultSegmentsLast.TryGetValue(realargs.i_ownerHash, out var segmentLast))
{
return (int)QueryStatus.NotEnoughDataForVels;
}
@@ -448,16 +563,16 @@ protected int CalculateVelocities(int i_ownerHash, Vector3[] results)
return (int)QueryStatus.VelocityDataInvalidated;
}
- var dt = _queryResultsTime - _queryResultsTimeLast;
+ var dt = realargs._queryResultsTime - realargs._queryResultsTimeLast;
if (dt < 0.0001f)
{
return (int)QueryStatus.InvalidDtForVelocity;
}
- var count = results.Length;
+ var count = realargs.results.Length;
for (var i = 0; i < count; i++)
{
- results[i] = (_queryResults[i + segment.x] - _queryResultsLast[i + segmentLast.x]) / dt;
+ realargs.results[i] = (realargs._queryResults[i + segment.x] - realargs._queryResultsLast[i + segmentLast.x]) / dt;
}
return 0;
@@ -554,19 +669,27 @@ public void CleanUp()
_queryResults.Dispose();
_queryResultsLast.Dispose();
+ _queryPosXZ_minGridSize.Dispose();
+
_segmentRegistrarRingBuffer.ClearAll();
}
- public int Query(int i_ownerHash, float i_minSpatialLength, Vector3[] i_queryPoints, Vector3[] o_resultDisps, Vector3[] o_resultNorms, Vector3[] o_resultVels)
+ public int Query(int i_ownerHash,
+ float i_minSpatialLength,
+ ref NativeArray i_queryPoints,
+ ref NativeArray o_resultDisps,
+ ref NativeArray o_resultNorms,
+ ref NativeArray o_resultVels,
+ bool useNormals)
{
var result = (int)QueryStatus.OK;
- if (!UpdateQueryPoints(i_ownerHash, i_minSpatialLength, i_queryPoints, o_resultNorms != null ? i_queryPoints : null))
+ if (!UpdateQueryPoints(i_ownerHash, i_minSpatialLength, i_queryPoints, i_queryPoints, useNormals))
{
result |= (int)QueryStatus.PostFailed;
}
- if (!RetrieveResults(i_ownerHash, o_resultDisps, null, o_resultNorms))
+ if (!RetrieveResults(i_ownerHash, o_resultDisps, default, o_resultNorms))
{
result |= (int)QueryStatus.RetrieveFailed;
}
@@ -584,7 +707,7 @@ public bool RetrieveSucceeded(int queryStatus)
return (queryStatus & (int)QueryStatus.RetrieveFailed) == 0;
}
- public int ResultGuidCount => _resultSegments != null ? _resultSegments.Count : 0;
+ public int ResultGuidCount => _resultSegments.Count();
public int RequestCount => _requests != null ? _requests.Count : 0;
}
diff --git a/crest/Assets/Crest/Crest/Scripts/Collision/QueryDisplacements.cs b/crest/Assets/Crest/Crest/Scripts/Collision/QueryDisplacements.cs
index c6af4a99e..a4f9afde3 100644
--- a/crest/Assets/Crest/Crest/Scripts/Collision/QueryDisplacements.cs
+++ b/crest/Assets/Crest/Crest/Scripts/Collision/QueryDisplacements.cs
@@ -2,6 +2,7 @@
// This file is subject to the MIT License as seen in the root of this folder structure (LICENSE)
+using Unity.Collections;
using UnityEngine;
namespace Crest
@@ -28,21 +29,27 @@ protected override void BindInputsAndOutputs(PropertyWrapperComputeStandalone wr
ShaderProcessQueries.SetBuffer(_kernelHandle, OceanRenderer.sp_cascadeData, OceanRenderer.Instance._bufCascadeDataTgt);
}
- public int Query(int i_ownerHash, float i_minSpatialLength, Vector3[] i_queryPoints, float[] o_resultHeights, Vector3[] o_resultNorms, Vector3[] o_resultVels)
+ public int Query(int i_ownerHash,
+ float i_minSpatialLength,
+ ref NativeArray i_queryPoints,
+ ref NativeArray o_resultHeights,
+ ref NativeArray o_resultNorms,
+ ref NativeArray o_resultVels)
{
var result = (int)QueryStatus.OK;
+ var useNormals = o_resultNorms.Length > 0;
- if (!UpdateQueryPoints(i_ownerHash, i_minSpatialLength, i_queryPoints, o_resultNorms != null ? i_queryPoints : null))
+ if (!UpdateQueryPoints(i_ownerHash, i_minSpatialLength, i_queryPoints, useNormals ? i_queryPoints : default, useNormals))
{
result |= (int)QueryStatus.PostFailed;
}
- if (!RetrieveResults(i_ownerHash, null, o_resultHeights, o_resultNorms))
+ if (!RetrieveResults(i_ownerHash, default, o_resultHeights, o_resultNorms))
{
result |= (int)QueryStatus.RetrieveFailed;
}
- if (o_resultVels != null)
+ if (o_resultVels.Length > 0)
{
result |= CalculateVelocities(i_ownerHash, o_resultVels);
}
diff --git a/crest/Assets/Crest/Crest/Scripts/Collision/QueryFlow.cs b/crest/Assets/Crest/Crest/Scripts/Collision/QueryFlow.cs
index 921e6009a..01e264106 100644
--- a/crest/Assets/Crest/Crest/Scripts/Collision/QueryFlow.cs
+++ b/crest/Assets/Crest/Crest/Scripts/Collision/QueryFlow.cs
@@ -2,6 +2,7 @@
// This file is subject to the MIT License as seen in the root of this folder structure (LICENSE)
+using Unity.Collections;
using UnityEngine;
namespace Crest
@@ -23,9 +24,15 @@ protected override void BindInputsAndOutputs(PropertyWrapperComputeStandalone wr
ShaderProcessQueries.SetBuffer(_kernelHandle, sp_ResultFlows, resultsBuffer);
}
- public int Query(int i_ownerHash, float i_minSpatialLength, Vector3[] i_queryPoints, Vector3[] o_resultFlows)
+ public int Query(int i_ownerHash,
+ float i_minSpatialLength,
+ ref NativeArray i_queryPoints,
+ ref NativeArray o_resultFlows)
{
- return Query(i_ownerHash, i_minSpatialLength, i_queryPoints, o_resultFlows, null, null);
+ var norms = default(NativeArray);
+ var vels = default(NativeArray);
+
+ return Query(i_ownerHash, i_minSpatialLength, ref i_queryPoints, ref o_resultFlows, ref norms, ref vels, false);
}
}
}
diff --git a/crest/Assets/Crest/Crest/Scripts/Collision/RayTraceHelper.cs b/crest/Assets/Crest/Crest/Scripts/Collision/RayTraceHelper.cs
index 8161409a5..b9c14df90 100644
--- a/crest/Assets/Crest/Crest/Scripts/Collision/RayTraceHelper.cs
+++ b/crest/Assets/Crest/Crest/Scripts/Collision/RayTraceHelper.cs
@@ -2,6 +2,7 @@
// This file is subject to the MIT License as seen in the root of this folder structure (LICENSE)
+using Unity.Collections;
using UnityEngine;
namespace Crest
@@ -12,8 +13,8 @@ namespace Crest
///
public class RayTraceHelper
{
- Vector3[] _queryPos;
- Vector3[] _queryResult;
+ NativeArray _queryPos;
+ NativeArray _queryResult;
float _rayLength;
float _rayStepSize;
@@ -41,8 +42,17 @@ public RayTraceHelper(float rayLength, float rayStepSize = 2f)
Debug.LogWarning($"Crest: RayTraceHelper: ray steps exceed maximum ({maxStepCount}), step size increased to {_rayStepSize} to reduce step count.");
}
- _queryPos = new Vector3[stepCount];
- _queryResult = new Vector3[stepCount];
+ if (_queryPos.IsCreated)
+ {
+ _queryPos.Dispose();
+ }
+ _queryPos = new NativeArray(stepCount, Allocator.Persistent);
+ if (_queryResult.IsCreated)
+ {
+ _queryResult.Dispose();
+ }
+
+ _queryResult = new NativeArray(stepCount, Allocator.Persistent);
}
///
@@ -57,12 +67,6 @@ public void Init(Vector3 i_rayOrigin, Vector3 i_rayDirection)
_queryPos[i] = i_rayOrigin + i * _rayStepSize * i_rayDirection;
}
- var rect = new Rect();
- rect.xMin = Mathf.Min(_queryPos[0].x, _queryPos[_queryPos.Length - 1].x);
- rect.yMin = Mathf.Min(_queryPos[0].z, _queryPos[_queryPos.Length - 1].z);
- rect.xMax = Mathf.Max(_queryPos[0].x, _queryPos[_queryPos.Length - 1].x);
- rect.yMax = Mathf.Max(_queryPos[0].z, _queryPos[_queryPos.Length - 1].z);
-
// Waves go max double along min length. Thats too much - only allow half of a wave per step.
_minLength = _rayStepSize * 4f;
}
@@ -76,7 +80,9 @@ public bool Trace(out float o_distance)
{
o_distance = -1f;
- var status = OceanRenderer.Instance.CollisionProvider.Query(GetHashCode(), _minLength, _queryPos, _queryResult, null, null);
+ var norms = default(NativeArray);
+ var vels = default(NativeArray);
+ var status = OceanRenderer.Instance.CollisionProvider.Query(GetHashCode(), _minLength, ref _queryPos, ref _queryResult, ref norms, ref vels, false);
if (!OceanRenderer.Instance.CollisionProvider.RetrieveSucceeded(status))
{
diff --git a/crest/Assets/Crest/Crest/Scripts/Collision/SamplingHelpers.cs b/crest/Assets/Crest/Crest/Scripts/Collision/SamplingHelpers.cs
index 28bba63ea..5d522bd85 100644
--- a/crest/Assets/Crest/Crest/Scripts/Collision/SamplingHelpers.cs
+++ b/crest/Assets/Crest/Crest/Scripts/Collision/SamplingHelpers.cs
@@ -2,7 +2,11 @@
// This file is subject to the MIT License as seen in the root of this folder structure (LICENSE)
+using System;
+using Unity.Burst;
+using Unity.Collections;
using UnityEngine;
+using Object = UnityEngine.Object;
namespace Crest
{
@@ -10,12 +14,25 @@ namespace Crest
/// Helper to obtain the ocean surface height at a single location per frame. This is not particularly efficient to sample a single height,
/// but is a fairly common case.
///
+ [BurstCompile]
public class SampleHeightHelper
{
- Vector3[] _queryPos = new Vector3[1];
- Vector3[] _queryResult = new Vector3[1];
- Vector3[] _queryResultNormal = new Vector3[1];
- Vector3[] _queryResultVel = new Vector3[1];
+ Vector3 _queryPos;
+ private Vector3 _queryResult;
+ private Vector3 _queryResultNormal;
+ private Vector3 _queryResultVel;
+
+ //these are only ever used on the main thread, and they're filled in when they're used, so we only need one
+ //global copy of them. if we had one for every sample height helper, we would spend forever creating and
+ //destroying nativearrays. consider revisiting this when 22.2 is the minspec, because then nativearray becomes
+ //fully unmanaged.
+
+ //also, obviously revisit if their usage is ever jobified.
+ static NativeArray _tmpqueryPos;
+ static NativeArray _tmpqueryResult;
+ static NativeArray _tmpqueryResultNormal;
+ static NativeArray _tmpqueryResultVel;
+ private static bool HaveRegisteredDomainUnload = false;
float _minLength = 0f;
@@ -33,7 +50,25 @@ public class SampleHeightHelper
/// Pass true if calling from FixedUpdate(). This will omit a warning when there on multipled-FixedUpdate frames.
public void Init(Vector3 i_queryPos, float i_minLength = 0f, bool allowMultipleCallsPerFrame = false, Object context = null)
{
- _queryPos[0] = i_queryPos;
+ _queryPos = i_queryPos;
+ if (!_tmpqueryPos.IsCreated)
+ _tmpqueryPos = new NativeArray(1, Allocator.Persistent);
+
+ if (!_tmpqueryResult.IsCreated)
+ {
+ _tmpqueryResult = new NativeArray(1, Allocator.Persistent);
+ }
+
+ if (!_tmpqueryResultNormal.IsCreated)
+ {
+ _tmpqueryResultNormal = new NativeArray(1, Allocator.Persistent);
+ }
+
+ if (!_tmpqueryResultVel.IsCreated)
+ {
+ _tmpqueryResultVel = new NativeArray(1, Allocator.Persistent);
+ }
+
_minLength = i_minLength;
#if UNITY_EDITOR
@@ -42,9 +77,26 @@ public void Init(Vector3 i_queryPos, float i_minLength = 0f, bool allowMultipleC
Debug.LogWarning($"Crest: SampleHeightHelper.Init() called multiple times in one frame which is not expected. Each SampleHeightHelper object services a single height query per frame. To perform multiple queries, create multiple SampleHeightHelper objects or use the CollProvider.Query() API directly. (_lastFrame = {_lastFrame})", context);
}
_lastFrame = OceanRenderer.FrameCount;
+
+ //if we do this registration on every init, it wastes lots of time and garbage. but if we never do it,
+ //we leak memory. so, do it once if we can't tell that we've done it before.
+ if (!HaveRegisteredDomainUnload)
+ {
+ AppDomain.CurrentDomain.DomainUnload -= OnDomainUnload;
+ AppDomain.CurrentDomain.DomainUnload += OnDomainUnload;
+ HaveRegisteredDomainUnload = true;
+ }
#endif
}
+ private static void OnDomainUnload(object sender, EventArgs e)
+ {
+ _tmpqueryPos.Dispose();
+ _tmpqueryResult.Dispose();
+ _tmpqueryResultNormal.Dispose();
+ _tmpqueryResultVel.Dispose();
+ }
+
///
/// Call this to do the query. Can be called only once after Init().
///
@@ -57,15 +109,36 @@ public bool Sample(out float o_height)
return false;
}
- var status = collProvider.Query(GetHashCode(), _minLength, _queryPos, _queryResult, null, null);
+ if (!DoQueryAndRetrieveSucceeded(out o_height, collProvider, _minLength, _queryPos, out var queryResult, GetHashCode())) return false;
+
+ return true;
+ }
+
+
+ private static bool DoQueryAndRetrieveSucceeded(out float o_height, ICollProvider collProvider, float minLength, Vector3 queryPos, out Vector3 queryResult, int selfHashCode)
+ {
+ var oResultNorms = new NativeArray();
+ var oResultVels = new NativeArray();
+ _tmpqueryPos[0] = queryPos;
+
+ var status = collProvider.Query(selfHashCode,
+ minLength,
+ ref _tmpqueryPos,
+ ref _tmpqueryResult,
+ ref oResultNorms,
+ ref oResultVels,
+ false);
if (!collProvider.RetrieveSucceeded(status))
{
o_height = OceanRenderer.Instance.SeaLevel;
+ queryResult = _tmpqueryResult[0];
return false;
}
- o_height = _queryResult[0].y + OceanRenderer.Instance.SeaLevel;
+ queryResult = _tmpqueryResult[0];
+
+ o_height = queryResult.y + OceanRenderer.Instance.SeaLevel;
return true;
}
@@ -80,7 +153,17 @@ public bool Sample(out float o_height, out Vector3 o_normal)
return false;
}
- var status = collProvider.Query(GetHashCode(), _minLength, _queryPos, _queryResult, _queryResultNormal, null);
+ NativeArray oResultVels = new NativeArray();
+ _tmpqueryPos[0] = _queryPos;
+ var status = collProvider.Query(GetHashCode(),
+ _minLength,
+ ref _tmpqueryPos,
+ ref _tmpqueryResult,
+ ref _tmpqueryResultNormal,
+ ref oResultVels,
+ true);
+ _queryResult = _tmpqueryResult[0];
+ _queryResultNormal = _tmpqueryResultNormal[0];
if (!collProvider.RetrieveSucceeded(status))
{
@@ -89,8 +172,8 @@ public bool Sample(out float o_height, out Vector3 o_normal)
return false;
}
- o_height = _queryResult[0].y + OceanRenderer.Instance.SeaLevel;
- o_normal = _queryResultNormal[0];
+ o_height = _queryResult.y + OceanRenderer.Instance.SeaLevel;
+ o_normal = _queryResultNormal;
return true;
}
@@ -106,7 +189,19 @@ public bool Sample(out float o_height, out Vector3 o_normal, out Vector3 o_surfa
return false;
}
- var status = collProvider.Query(GetHashCode(), _minLength, _queryPos, _queryResult, _queryResultNormal, _queryResultVel);
+ _tmpqueryPos[0] = _queryPos;
+
+ var status = collProvider.Query(GetHashCode(),
+ _minLength,
+ ref _tmpqueryPos,
+ ref _tmpqueryResult,
+ ref _tmpqueryResultNormal,
+ ref _tmpqueryResultVel,
+ true);
+
+ _queryResult = _tmpqueryResult[0];
+ _queryResultNormal = _tmpqueryResultNormal[0];
+ _queryResultVel = _tmpqueryResultVel[0];
if (!collProvider.RetrieveSucceeded(status))
{
@@ -116,9 +211,9 @@ public bool Sample(out float o_height, out Vector3 o_normal, out Vector3 o_surfa
return false;
}
- o_height = _queryResult[0].y + OceanRenderer.Instance.SeaLevel;
- o_normal = _queryResultNormal[0];
- o_surfaceVel = _queryResultVel[0];
+ o_height = _queryResult.y + OceanRenderer.Instance.SeaLevel;
+ o_normal = _queryResultNormal;
+ o_surfaceVel = _queryResultVel;
return true;
}
@@ -133,7 +228,18 @@ public bool Sample(out Vector3 o_displacementToPoint, out Vector3 o_normal, out
o_surfaceVel = Vector3.zero;
return false;
}
- var status = collProvider.Query(GetHashCode(), _minLength, _queryPos, _queryResult, _queryResultNormal, _queryResultVel);
+
+ _tmpqueryPos[0] = _queryPos;
+ var status = collProvider.Query(GetHashCode(),
+ _minLength,
+ ref _tmpqueryPos,
+ ref _tmpqueryResult,
+ ref _tmpqueryResultNormal,
+ ref _tmpqueryResultVel,
+ true);
+ _queryResult = _tmpqueryResult[0];
+ _queryResultNormal = _tmpqueryResultNormal[0];
+ _queryResultVel = _tmpqueryResultVel[0];
if (!collProvider.RetrieveSucceeded(status))
{
@@ -143,9 +249,9 @@ public bool Sample(out Vector3 o_displacementToPoint, out Vector3 o_normal, out
return false;
}
- o_displacementToPoint = _queryResult[0];
- o_normal = _queryResultNormal[0];
- o_surfaceVel = _queryResultVel[0];
+ o_displacementToPoint = _queryResult;
+ o_normal = _queryResultNormal;
+ o_surfaceVel = _queryResultVel;
return true;
}
@@ -157,8 +263,12 @@ public bool Sample(out Vector3 o_displacementToPoint, out Vector3 o_normal, out
///
public class SampleFlowHelper
{
- Vector3[] _queryPos = new Vector3[1];
- Vector3[] _queryResult = new Vector3[1];
+ private Vector3 _queryPos;
+ Vector3 _queryResult;
+
+ //see comment on SampleHeightHelper about why these are static and more
+ private static NativeArray _tmpQueryPos;
+ private static NativeArray _tmpQueryResult;
float _minLength = 0f;
@@ -170,7 +280,16 @@ public class SampleFlowHelper
/// pass in the boats width. Larger objects will filter out detailed flow information.
public void Init(Vector3 i_queryPos, float i_minLength)
{
- _queryPos[0] = i_queryPos;
+ _queryPos = i_queryPos;
+ if (!_tmpQueryPos.IsCreated)
+ {
+ _tmpQueryPos = new NativeArray(1, Allocator.Persistent);
+ }
+
+ if (!_tmpQueryResult.IsCreated)
+ {
+ _tmpQueryResult = new NativeArray(1, Allocator.Persistent);
+ }
_minLength = i_minLength;
}
@@ -185,8 +304,9 @@ public bool Sample(out Vector2 o_flow)
o_flow = Vector2.zero;
return false;
}
- var status = flowProvider.Query(GetHashCode(), _minLength, _queryPos, _queryResult);
-
+ _tmpQueryPos[0] = _queryPos;
+ var status = flowProvider.Query(GetHashCode(), _minLength, ref _tmpQueryPos, ref _tmpQueryResult);
+ _queryResult = _tmpQueryResult[0];
if (!flowProvider.RetrieveSucceeded(status))
{
o_flow = Vector2.zero;
@@ -194,8 +314,8 @@ public bool Sample(out Vector2 o_flow)
}
// We don't support float2 queries unfortunately, so unpack from float3
- o_flow.x = _queryResult[0].x;
- o_flow.y = _queryResult[0].z;
+ o_flow.x = _queryResult.x;
+ o_flow.y = _queryResult.z;
return true;
}
diff --git a/crest/Assets/Crest/Crest/Scripts/Collision/VisualiseCollisionArea.cs b/crest/Assets/Crest/Crest/Scripts/Collision/VisualiseCollisionArea.cs
index ee51ada20..90c492b5c 100644
--- a/crest/Assets/Crest/Crest/Scripts/Collision/VisualiseCollisionArea.cs
+++ b/crest/Assets/Crest/Crest/Scripts/Collision/VisualiseCollisionArea.cs
@@ -2,6 +2,7 @@
// This file is subject to the MIT License as seen in the root of this folder structure (LICENSE)
+using Unity.Collections;
using UnityEngine;
namespace Crest
@@ -37,11 +38,11 @@ public class VisualiseCollisionArea : MonoBehaviour
[SerializeField]
bool _useNormals;
- float[] _resultHeights;
- Vector3[] _resultDisps;
- Vector3[] _resultNorms;
+ NativeArray _resultHeights;
+ NativeArray _resultDisps;
+ NativeArray _resultNorms;
- Vector3[] _samplePositions;
+ NativeArray _samplePositions;
void Update()
{
@@ -52,15 +53,15 @@ void Update()
if (_resultHeights == null || _resultHeights.Length != _steps * _steps)
{
- _resultHeights = new float[_steps * _steps];
+ _resultHeights = new NativeArray(_steps * _steps, Allocator.Persistent);
}
if (_resultDisps == null || _resultDisps.Length != _steps * _steps)
{
- _resultDisps = new Vector3[_steps * _steps];
+ _resultDisps = new NativeArray(_steps * _steps, Allocator.Persistent);
}
if (_resultNorms == null || _resultNorms.Length != _steps * _steps)
{
- _resultNorms = new Vector3[_steps * _steps];
+ _resultNorms = new NativeArray(_steps * _steps, Allocator.Persistent);
for (int i = 0; i < _resultNorms.Length; i++)
{
@@ -69,7 +70,7 @@ void Update()
}
if (_samplePositions == null || _samplePositions.Length != _steps * _steps)
{
- _samplePositions = new Vector3[_steps * _steps];
+ _samplePositions = new NativeArray(_steps * _steps, Allocator.Persistent);
}
var collProvider = OceanRenderer.Instance.CollisionProvider;
@@ -78,16 +79,17 @@ void Update()
{
for (int j = 0; j < _steps; j++)
{
- _samplePositions[j * _steps + i] = new Vector3(((i + 0.5f) - _steps / 2f) * _stepSize, 0f, ((j + 0.5f) - _steps / 2f) * _stepSize);
- _samplePositions[j * _steps + i].x += transform.position.x;
- _samplePositions[j * _steps + i].z += transform.position.z;
+ var tmp = new Vector3(((i + 0.5f) - _steps / 2f) * _stepSize, 0f, ((j + 0.5f) - _steps / 2f) * _stepSize);
+ tmp.x += transform.position.x;
+ tmp.z += transform.position.z;
+ _samplePositions[j * _steps + i] = tmp;
}
}
if (_useDisplacements)
{
- if (collProvider.RetrieveSucceeded(collProvider.Query(GetHashCode(), _objectWidth, _samplePositions, _resultDisps, _useNormals ? _resultNorms : null, null)))
- {
+ var oResultVels = new NativeArray();
+ if (collProvider.RetrieveSucceeded(collProvider.Query(GetHashCode(), _objectWidth, ref _samplePositions, ref _resultDisps, ref _resultNorms, ref oResultVels, _useNormals))) {
for (int i = 0; i < _steps; i++)
{
for (int j = 0; j < _steps; j++)
@@ -105,8 +107,8 @@ void Update()
}
else
{
- if (collProvider.RetrieveSucceeded(collProvider.Query(GetHashCode(), _objectWidth, _samplePositions, _resultHeights, _useNormals ? _resultNorms : null, null)))
- {
+ var oResultVels = new NativeArray();
+ if (collProvider.RetrieveSucceeded(collProvider.Query(GetHashCode(), _objectWidth, ref _samplePositions, ref _resultHeights, ref _resultNorms, ref oResultVels))) {
for (int i = 0; i < _steps; i++)
{
for (int j = 0; j < _steps; j++)
diff --git a/crest/Assets/Crest/Crest/Scripts/Crest.asmdef b/crest/Assets/Crest/Crest/Scripts/Crest.asmdef
index 17ffb0703..a259f4577 100644
--- a/crest/Assets/Crest/Crest/Scripts/Crest.asmdef
+++ b/crest/Assets/Crest/Crest/Scripts/Crest.asmdef
@@ -5,11 +5,12 @@
"Unity.Postprocessing.Runtime",
"Unity.InputSystem",
"Unity.Mathematics",
- "Unity.Burst"
+ "Unity.Burst",
+ "Unity.Collections"
],
"includePlatforms": [],
"excludePlatforms": [],
- "allowUnsafeCode": false,
+ "allowUnsafeCode": true,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
diff --git a/crest/Assets/Crest/Crest/Scripts/Interaction/BoatProbes.cs b/crest/Assets/Crest/Crest/Scripts/Interaction/BoatProbes.cs
index bf187f628..c82da428f 100644
--- a/crest/Assets/Crest/Crest/Scripts/Interaction/BoatProbes.cs
+++ b/crest/Assets/Crest/Crest/Scripts/Interaction/BoatProbes.cs
@@ -5,6 +5,7 @@
// Shout out to @holdingjason who posted a first version of this script here: https://github.com/huwb/crest-oceanrender/pull/100
using System;
+using Unity.Collections;
using UnityEngine;
#if ENABLE_INPUT_SYSTEM
using UnityEngine.InputSystem;
@@ -83,9 +84,9 @@ class DebugFields
float _totalWeight;
- Vector3[] _queryPoints;
- Vector3[] _queryResultDisps;
- Vector3[] _queryResultVels;
+ NativeArray _queryPoints;
+ NativeArray _queryResultDisps;
+ NativeArray _queryResultVels;
SampleFlowHelper _sampleFlowHelper = new SampleFlowHelper();
@@ -102,9 +103,9 @@ private void Start()
CalcTotalWeight();
- _queryPoints = new Vector3[_forcePoints.Length + 1];
- _queryResultDisps = new Vector3[_forcePoints.Length + 1];
- _queryResultVels = new Vector3[_forcePoints.Length + 1];
+ _queryPoints = new NativeArray(_forcePoints.Length + 1, Allocator.Persistent);
+ _queryResultDisps = new NativeArray(_forcePoints.Length + 1, Allocator.Persistent);
+ _queryResultVels = new NativeArray(_forcePoints.Length + 1, Allocator.Persistent);
}
void CalcTotalWeight()
@@ -165,7 +166,8 @@ void UpdateWaterQueries(ICollProvider collProvider)
}
_queryPoints[_forcePoints.Length] = transform.position;
- collProvider.Query(GetHashCode(), ObjectWidth, _queryPoints, _queryResultDisps, null, _queryResultVels);
+ var oResultNorms = new NativeArray();
+ collProvider.Query(GetHashCode(), ObjectWidth, ref _queryPoints, ref _queryResultDisps, ref oResultNorms, ref _queryResultVels, false);
if (_debug._drawQueries)
{
diff --git a/crest/Assets/Crest/Crest/Scripts/LodData/LodDataMgr.cs b/crest/Assets/Crest/Crest/Scripts/LodData/LodDataMgr.cs
index d0131ca6a..1e123036c 100644
--- a/crest/Assets/Crest/Crest/Scripts/LodData/LodDataMgr.cs
+++ b/crest/Assets/Crest/Crest/Scripts/LodData/LodDataMgr.cs
@@ -223,12 +223,13 @@ protected void SubmitDraws(int lodIdx, CommandBuffer buf)
var drawList = RegisterLodDataInputBase.GetRegistrar(GetType());
foreach (var draw in drawList)
{
- if (!draw.Value.Enabled)
+ var value = draw.Value;
+ if (!value.Enabled)
{
continue;
}
- draw.Value.Draw(this, buf, 1f, 0, lodIdx);
+ value.Draw(this, buf, 1f, 0, lodIdx);
}
}
diff --git a/crest/Packages/manifest.json b/crest/Packages/manifest.json
index 9cf6112c3..bfab4133f 100644
--- a/crest/Packages/manifest.json
+++ b/crest/Packages/manifest.json
@@ -4,6 +4,7 @@
"com.unity.2d.sprite": "1.0.0",
"com.unity.2d.tilemap": "1.0.0",
"com.unity.burst": "1.6.5",
+ "com.unity.collections": "1.3.1",
"com.unity.ide.rider": "3.0.14",
"com.unity.ide.visualstudio": "2.0.15",
"com.unity.ide.vscode": "1.2.5",