This is happening on Unity 2020.1.0b14.4034, but I am unsure if the version is the issue
I have no idea why this is happening. I think might be related to the new ComputeBuffer.BeginWrite/EndWrite. I’ve attempted to change to SetData to test this theory, but SetData is also not working (not even on editor) for mysterious reasons (related https://forum.unity.com/threads/computebuffer-setdata-silently-fails.919826/ )
This could or could not be related to: Flickering when rendering
Or worse, this could be silently happening on the player: https://forum.unity.com/threads/d3d11-multiple-uploads-in-flight-for-buffer-0000020a3593b658-of-size-4194304-falling-back-to-slow.915953/
Images:
In Editor (Game Window, the grass does not render in the Scene view):
In Player:
Imgur: The magic of the Internet
The text full of numbers is the number of instances being sent in args for
Graphics.DrawMeshInstancedIndirect
The preprocessor leftover is my attempt to change it to SetData
Related Code
//#if UNITY_EDITOR
#define BeginEndWrite
//#endif
using GuedezGrassSystem;
using System;
using System.Linq;
using Unity.Burst;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Entities;
using Unity.Jobs;
using Unity.Mathematics;
using UnityEngine;
public class DrawContainer {
public ComputeBuffer _positions;
public ComputeBuffer _typelen;
public ComputeBuffer _bbnn;
public ComputeBuffer _argsBuffer;
//public ComputeBuffer _positions2;
//public ComputeBuffer _argsBuffer2;
public NativeArray<uint> args;
// public NativeArray<float3> _centersWrite;
public NativeArray<uint> _CountWrite;
public NativeArray<uint> _positionsWrite;
public NativeArray<uint> _typelenWrite;
public NativeArray<uint> _bbnnWrite;
public MaterialPropertyBlock block;
private bool castshadow;
private bool receiveshadow;
public NativeList<Entry> accumulator;
public NativeList<IntDist> entries;
public NativeList<int> sizeargs;
private bool _Writting = false;
public DrawContainer(bool castshadow, bool receiveshadow) {
block = new MaterialPropertyBlock();
this.castshadow = castshadow;
this.receiveshadow = receiveshadow;
args = new NativeArray<uint>(6, Allocator.Persistent);
sizeargs = new NativeList<int>(128, Allocator.Persistent);
accumulator = new NativeList<Entry>(1024, Allocator.Persistent);
entries = new NativeList<IntDist>(1024, Allocator.Persistent);
}
public void Dispose() {
if (accumulator.IsCreated) {
accumulator.Dispose();
entries.Dispose();
sizeargs.Dispose();
args.Dispose();
}
if (_positions != null && _positions.IsValid()) {
#if !BeginEndWrite
_CountWrite.Dispose();
_positionsWrite.Dispose();
_typelenWrite.Dispose();
_bbnnWrite.Dispose();
#else
if (_Writting) {
try {
_argsBuffer.EndWrite<uint>(5);
_positions.EndWrite<uint>((int)args[1]);
_typelen.EndWrite<uint>((int)args[1]);
_bbnn.EndWrite<uint>((int)args[1]);
} catch (Exception e) { }
}
#endif
_positions.Dispose();
_typelen.Dispose();
_bbnn.Dispose();
_argsBuffer.Dispose();
// _positions2.Dispose();
// _argsBuffer2.Dispose();
}
}
public void Prepare(uint numIndices, ComputeBuffer centers) {
args[0] = numIndices;
#if !BeginEndWrite
_positions = new ComputeBuffer(1024, 4, ComputeBufferType.Structured);
_typelen = new ComputeBuffer(1024, 4, ComputeBufferType.Structured);
_bbnn = new ComputeBuffer(1024, 4, ComputeBufferType.Structured);
_argsBuffer = new ComputeBuffer(5, 4, ComputeBufferType.IndirectArguments);
#else
_positions = new ComputeBuffer(1024, 4, ComputeBufferType.Structured, ComputeBufferMode.SubUpdates);
_typelen = new ComputeBuffer(1024, 4, ComputeBufferType.Structured, ComputeBufferMode.SubUpdates);
_bbnn = new ComputeBuffer(1024, 4, ComputeBufferType.Structured, ComputeBufferMode.SubUpdates);
_argsBuffer = new ComputeBuffer(5, 4, ComputeBufferType.IndirectArguments, ComputeBufferMode.SubUpdates);
#endif
#if !BeginEndWrite
_CountWrite = new NativeArray<uint>(5, Allocator.Persistent);
_positionsWrite = new NativeArray<uint>(_positions.count, Allocator.Persistent);
_typelenWrite = new NativeArray<uint>(_positions.count, Allocator.Persistent);
_bbnnWrite = new NativeArray<uint>(_positions.count, Allocator.Persistent);
#endif
//_positions2 = new ComputeBuffer(1024, 4, ComputeBufferType.Structured, ComputeBufferMode.SubUpdates);
// _argsBuffer2 = new ComputeBuffer(5, 4, ComputeBufferType.IndirectArguments, ComputeBufferMode.SubUpdates);
}
public void PrepareBlock() {
block.SetBuffer("position", _positions);
block.SetBuffer("TL", _typelen);
block.SetBuffer("BBDNN", _bbnn);
}
public void Draw(Material mat, Camera cam) {
// _centers.EndWrite<float3>(lastCount);
Mesh mesh = GrassSystem.baseMesh[0];
Bounds bounds1 = new Bounds(cam.transform.position, Vector3.one * 2500);
Graphics.DrawMeshInstancedIndirect(mesh, 0, mat, bounds1, _argsBuffer, 0, block,
castshadow ? UnityEngine.Rendering.ShadowCastingMode.TwoSided : UnityEngine.Rendering.ShadowCastingMode.Off, receiveshadow, 0, cam);
}
public struct Entry {
public WildGrassTilePointers tile;
public int start;
public short length;
public short centerIndex;
}
internal int Resize() {
#if !BeginEndWrite
if (Utils.RecreateIfSmaller(ref _positions, 4, (int)args[5], ComputeBufferType.Structured, ComputeBufferMode.Dynamic, 1.2f)) {
#else
if (Utils.RecreateIfSmaller(ref _positions, 4, (int)args[5], ComputeBufferType.Structured, ComputeBufferMode.SubUpdates, 1.2f)) {
#endif
#if !BeginEndWrite
_positionsWrite.Dispose();
_typelenWrite.Dispose();
_bbnnWrite.Dispose();
_positionsWrite = new NativeArray<uint>(_positions.count, Allocator.Persistent);
_typelenWrite = new NativeArray<uint>(_positions.count, Allocator.Persistent);
_bbnnWrite = new NativeArray<uint>(_positions.count, Allocator.Persistent);
#endif
}
//if (Utils.RecreateIfSmaller(ref _positions2, 4, (int)args[5], ComputeBufferType.Structured, ComputeBufferMode.SubUpdates, 1.2f)) {
//block.SetBuffer("position", _positions2);
//}
#if !BeginEndWrite
if (Utils.RecreateIfSmaller(ref _typelen, 4, (int)args[5], ComputeBufferType.Structured, ComputeBufferMode.Dynamic, 1.2f)) {
#else
if (Utils.RecreateIfSmaller(ref _typelen, 4, (int)args[5], ComputeBufferType.Structured, ComputeBufferMode.SubUpdates, 1.2f)) {
#endif
//block.SetBuffer("position", _positions);
}
#if !BeginEndWrite
if (Utils.RecreateIfSmaller(ref _bbnn, 4, (int)args[5], ComputeBufferType.Structured, ComputeBufferMode.Dynamic, 1.2f)) {
#else
if (Utils.RecreateIfSmaller(ref _bbnn, 4, (int)args[5], ComputeBufferType.Structured, ComputeBufferMode.SubUpdates, 1.2f)) {
#endif
//block.SetBuffer("position", _positions);
}
return _positions.count;
}
public void EndWrite() {
if (_Writting && args[1] > 0) {
#if BeginEndWrite
_argsBuffer.EndWrite<uint>(5);
_positions.EndWrite<uint>((int)args[1]);
_typelen.EndWrite<uint>((int)args[1]);
_bbnn.EndWrite<uint>((int)args[1]);
#endif
_Writting = false;
}
//if (_positionsWrite.IsCreated) {
// _positionsWrite.Dispose();
//}
//}
}
public void BeginWrite() {
if (!_Writting) {
#if BeginEndWrite
_CountWrite = _argsBuffer.BeginWrite<uint>(0, 5);
_positionsWrite = _positions.BeginWrite<uint>(0, _positions.count);
_typelenWrite = _typelen.BeginWrite<uint>(0, _typelen.count);
_bbnnWrite = _bbnn.BeginWrite<uint>(0, _bbnn.count);
#endif
//_positionsWrite = new NativeArray<uint>(_positions.count, Allocator.TempJob);
_Writting = true;
PrepareBlock();
//PrepareBlock();
}
}
public void Swap() {
//Utils.Swap(ref _positions, ref _positions2);
// Utils.Swap(ref _argsBuffer, ref _argsBuffer2);
}
public unsafe JobHandle Schedule(JobHandle inputDeps, int max_tiles) {
AccumulateJob job = new AccumulateJob();
job.accumulator = accumulator;
//job.max_size = max_grass;
job.positions = _positionsWrite.GetUnsafePtr();
job.type_lenghts = _typelenWrite.GetUnsafePtr();
job.bend_benddir_none_none = _bbnnWrite.GetUnsafePtr();
return job.ScheduleBatch(max_tiles, 32, inputDeps);
}
public void Clear() {
accumulator.Clear();
sizeargs.Clear();
entries.Clear();
}
internal void SetData() {
_argsBuffer.SetData(_CountWrite);
_positions.SetData(_positionsWrite, 0, 0, _positionsWrite.Length);
uint[] _positionsGet = new uint[_positionsWrite.Length];
_positions.GetData(_positionsGet);
_typelen.SetData(_typelenWrite, 0, 0, _positionsWrite.Length);
_bbnn.SetData(_bbnnWrite, 0, 0, _positionsWrite.Length);
}
//internal void Order() {
// tiles.Sort((T1, T2) => (int)(T1.dist - T2.dist));
//}
}
public class DrawContainerContainer {
public DrawContainer Close;
public DrawContainer Medium;
public DrawContainer Far;
public DrawContainerContainer() {
Close = new DrawContainer(true, true);//shadow
Medium = new DrawContainer(false, true);//no shadow cast
Far = new DrawContainer(false, false);//no shadow
}
internal void Dispose() {
Close.Dispose();
Medium.Dispose();
Far.Dispose();
}
internal void Prepare(uint numIndices, ComputeBuffer centers) {
Close.Prepare(numIndices, centers);
Medium.Prepare(numIndices, centers);
Far.Prepare(numIndices, centers);
}
}
[UpdateInGroup(typeof(LateSimulationSystemGroup))]
[UpdateAfter(typeof(ECSGrassBendDoBend))]
[UpdateAfter(typeof(ECSGrassBendDoCut))]
public class ECSDrawGrassSystemDoDraw : JobComponentSystem {
protected override JobHandle OnUpdate(JobHandle inputDeps) {
ECSDrawGrassSystem.combined.Complete();
for (int i = 0; i < ECSGrassSystem.configs.Length; i++) {
DrawContainerContainer cont = ECSGrassSystem.configs[i].container;
DrawContainer Close = cont.Close;
DrawContainer Medium = cont.Medium;
DrawContainer Far = cont.Far;
#if !BeginEndWrite
Close.SetData();
Medium.SetData();
Far.SetData();
#else
Close.EndWrite();
Medium.EndWrite();
Far.EndWrite();
#endif
}
return inputDeps;
}
}
public class ECSDrawGrassSystem : JobComponentSystem {
public Plane[] lastPlanes;
UpdateFrustrumCulling.FrustrumPlanes frustrumPlanes;
private WildGrassTilePointers EmptyTile;
private NativeArray<uint> EmptyArray;
public static JobHandle combined;
public const int ExtraGrassSize = 32000;
protected override void OnDestroy() {
base.OnDestroy();
if (EmptyArray.IsCreated) {
EmptyArray.Dispose();
}
}
protected unsafe override void OnCreate() {
base.OnCreate();
EmptyArray = new NativeArray<uint>(ExtraGrassSize, Allocator.Persistent);
for (int i = 0; i < EmptyArray.Length; i++) {
EmptyArray[i] = 0;
}
EmptyTile = new WildGrassTilePointers();
EmptyTile.Count = ExtraGrassSize;
IntPtr intPtr = new IntPtr(EmptyArray.GetUnsafeReadOnlyPtr());
EmptyTile.Positions = intPtr;
EmptyTile.TypesLenghts = intPtr;
EmptyTile.BendBendDirectionNoneNone = intPtr;
//Close.PrepareBlock();
//Medium.PrepareBlock();
//Far.PrepareBlock();
}
protected override JobHandle OnUpdate(JobHandle inputDeps) {
if (!combined.IsCompleted) {
combined.Complete();
}
if (ECSGrassSystem.configs.Length == 0) {
return inputDeps;
}
bool same = false;
Plane[] planes = GeometryUtility.CalculateFrustumPlanes(ECSGrassSystem.configs[0].cam);
if (lastPlanes != null && planes.SequenceEqual(lastPlanes)) {
same = true;
} else {
frustrumPlanes = new UpdateFrustrumCulling.FrustrumPlanes() {
Left = planes[0],
Right = planes[1],
Down = planes[2],
Up = planes[3],
Near = planes[4],
Far = planes[5]
};
}
lastPlanes = planes;
for (int i = 0; i < ECSGrassSystem.configs.Length; i++) {
var config = ECSGrassSystem.configs[i];
config.SetMaterial();
DrawContainerContainer cont = config.container;
DrawContainer Close = cont.Close;
DrawContainer Medium = cont.Medium;
DrawContainer Far = cont.Far;
Far.Draw(config.material, config.cam);
Medium.Draw(config.material, config.cam);
Close.Draw(config.material, config.cam);
if (same) {
continue;
}
int close_max = 0, medium_max = 0, far_max = 0;
BeginWriteEndWriteMethod(Close, Medium, Far, out close_max, out medium_max, out far_max);
Vector3 position = config.cam.transform.position;
EnsureCapacity(config, Close, Medium, Far);
int length = Close.accumulator.Length;
int length1 = Medium.accumulator.Length;
int length2 = Far.accumulator.Length;
ResizeAndClear(Close, Medium, Far);
FrustrumCheckerJob bounder = new FrustrumCheckerJob();
bounder.Frustrum = frustrumPlanes;
bounder.position = position;
bounder.Close = Close.entries.AsParallelWriter();
bounder.Medium = Medium.entries.AsParallelWriter();
bounder.Far = Far.entries.AsParallelWriter();
bounder.Source = config.ECSWildTiles;
bounder.Center = config._Centers;
JobHandle bounderhandle = bounder.ScheduleBatch(config.totalTiles, 32, inputDeps);
FPSDisplay.ExtraText = "Total blades of grass: " +
Close.args[1] + "(" + length + ")" + " | " +
Medium.args[1] + "(" + length1 + ")" + " | " +
Far.args[1] + "(" + length2 + ")" + " | " +
(Close.args[1] + Medium.args[1] + Far.args[1]);
combined = JobHandle.CombineDependencies(
ScheduleQueue(bounderhandle, Close, config, config.totalTiles, close_max),
ScheduleQueue(bounderhandle, Medium, config, config.totalTiles, medium_max),
ScheduleQueue(bounderhandle, Far, config, config.totalTiles, far_max));
}
return combined;
}
private static void BeginWriteEndWriteMethod(DrawContainer Close, DrawContainer Medium, DrawContainer Far, out int close_max, out int medium_max, out int far_max) {
close_max = Close.Resize();
medium_max = Medium.Resize();
far_max = Far.Resize();
Close.Swap();
Medium.Swap();
Far.Swap();
Close.BeginWrite();
Medium.BeginWrite();
Far.BeginWrite();
}
private static void ResizeAndClear(DrawContainer Close, DrawContainer Medium, DrawContainer Far) {
Close.Clear();
Medium.Clear();
Far.Clear();
}
private static void EnsureCapacity(GrassSystemConfig config, DrawContainer Close, DrawContainer Medium, DrawContainer Far) {
int count = config.totalTiles + 1;
if (Close.accumulator.Capacity < count) {
Close.accumulator.ResizeUninitialized((int)(count));
Close.entries.ResizeUninitialized((int)(count));
}
if (Medium.accumulator.Capacity < count) {
Medium.accumulator.ResizeUninitialized((int)(count));
Medium.entries.ResizeUninitialized((int)(count));
}
if (Far.accumulator.Capacity < count) {
Far.accumulator.ResizeUninitialized((int)(count));
Far.entries.ResizeUninitialized((int)(count));
}
int sc = count / 32 + 2;
if (Far.sizeargs.Capacity < sc) {
Close.sizeargs.ResizeUninitialized(sc);
Medium.sizeargs.ResizeUninitialized(sc);
Far.sizeargs.ResizeUninitialized(sc);
}
}
private JobHandle ScheduleQueue(JobHandle bounder, DrawContainer Close, GrassSystemConfig config, int maxCount, int max_grass) {
QueueTilesJob job = new QueueTilesJob();
job.empty_tile = EmptyTile;
job.Data = Close.entries;
job.CloseCount = Close.sizeargs.AsParallelWriter();
job.Close = Close.accumulator.AsParallelWriter();
job.Source = config.ECSWildTiles;
CountAndSumJob job2 = new CountAndSumJob();
job2.sizeargs = Close.sizeargs;
job2.args = Close.args;
job2._CountWrite = Close._CountWrite;
job2.max_size = job.max_size = max_grass;
return Close.Schedule(job2.Schedule(job.Schedule(bounder)), maxCount);
//NON BEGINWRITE METHOD
//CountAndSumJobSetData job2 = new CountAndSumJobSetData();
//job2.sizeargs = Close.sizeargs;
//job2.args = Close.args;
//job2.Schedule(job.Schedule(bounder)).Complete();
//if (Utils.RecreateIfSmaller(ref Close._positions, 4, (int)Close.args[1], ComputeBufferType.Structured, ComputeBufferMode.SubUpdates, 1.2f)) {
// Close.block.SetBuffer("position", Close._positions);
//}
//Close.PrepareBlock();
//config.SetMaterial();
//Close._positionsWrite = new NativeArray<uint>((int)Close.args[1], Allocator.TempJob);
//int closeargs = (int)Close.args[1];
//Close.Schedule(default, maxCount, (int)Close.args[1]).Complete();
//Close._positions.SetData(Close._positionsWrite);
//uint[] datacheck = new uint[Close._positions.count];
//Close._positions.GetData(datacheck);
//Close._positionsWrite.Dispose();
//Close._argsBuffer.SetData(Close.args);
//Close.Draw(config.material, config.cam);
//return default;
}
}
[BurstCompile]
public unsafe struct AccumulateJob : IJobParallelForBatch {//ParallelForBatch {
//public int max_size;
[ReadOnly] public NativeList<DrawContainer.Entry> accumulator;
[NativeDisableUnsafePtrRestriction] public void* positions;
[NativeDisableUnsafePtrRestriction] public void* type_lenghts;
[NativeDisableUnsafePtrRestriction] public void* bend_benddir_none_none;
public unsafe void Execute(int startIndex, int count) {
int end = startIndex + count;
for (int j = startIndex; j < end; j++) {
if (j >= accumulator.Length) {
return;
}
var offset = accumulator[j].start;
var size = accumulator[j].length;// math.min(max_size - offset, accumulator[j].length);
//if (max_size - offset < 1000 || size < 1) {
// continue;
//}
byte* offpositions = (byte*)positions;
offpositions += offset * 4;
byte* offtype_lenghts = (byte*)type_lenghts;
offtype_lenghts += offset * 4;
byte* offbend_benddir_none_none = (byte*)bend_benddir_none_none;
offbend_benddir_none_none += offset * 4;
UnsafeUtility.MemCpy(offpositions, accumulator[j].tile.Positions.ToPointer(), size * 4);
UnsafeUtility.MemCpy(offtype_lenghts, accumulator[j].tile.TypesLenghts.ToPointer(), size * 4);
UnsafeUtility.MemCpy(offbend_benddir_none_none, accumulator[j].tile.BendBendDirectionNoneNone.ToPointer(), size * 4);
}
}
}
[BurstCompile]
public struct FrustrumCheckerJob : IJobParallelForBatch {
public UpdateFrustrumCulling.FrustrumPlanes Frustrum;
public float3 position;
public NativeList<IntDist>.ParallelWriter Close;
public NativeList<IntDist>.ParallelWriter Medium;
public NativeList<IntDist>.ParallelWriter Far;
[NativeDisableContainerSafetyRestriction, ReadOnly] public NativeArray<WildGrassTilePointers> Source;
[NativeDisableContainerSafetyRestriction, ReadOnly] public NativeArray<float3> Center;
public unsafe void Execute(int startIndex, int count) {
int end = startIndex + count;
for (int j = startIndex; j < end; j++) {
WildGrassTilePointers tile = Source[j];
if (tile.Count == 0) {
continue;
}
Vector3 min = tile.bounds.min;
Vector3 max = tile.bounds.max;
if (CheckPlanes(min, max)) {
float d = Vector3.Distance(Center[j], position);
float x = Math.Max(0, d - 15) / 4;
int closestPower = Mathf.RoundToInt(Mathf.Pow(2, Mathf.Ceil(Mathf.Log(x, 2))));
d = Mathf.Min(64, Mathf.Max(1, closestPower));
if (d <= 4) {
Close.AddNoResize(new IntDist() { tile = (short)j, dist = (byte)d });
} else if (d < 32) {
Medium.AddNoResize(new IntDist() { tile = (short)j, dist = (byte)d });
} else {
Far.AddNoResize(new IntDist() { tile = (short)j, dist = (byte)d });
}
}
}
}
private bool CheckPlanes(float3 boundsMin, float3 boundsMax) {
Vector3 vmin, vmax;
for (int planeIndex = 0; planeIndex < 6; planeIndex++) {
var normal = Frustrum[planeIndex].normal;
var planeDistance = Frustrum[planeIndex].distance;
// X axis
if (normal.x < 0) {
vmin.x = boundsMin.x;
vmax.x = boundsMax.x;
} else {
vmin.x = boundsMax.x;
vmax.x = boundsMin.x;
}
// Y axis
if (normal.y < 0) {
vmin.y = boundsMin.y;
vmax.y = boundsMax.y;
} else {
vmin.y = boundsMax.y;
vmax.y = boundsMin.y;
}
// Z axis
if (normal.z < 0) {
vmin.z = boundsMin.z;
vmax.z = boundsMax.z;
} else {
vmin.z = boundsMax.z;
vmax.z = boundsMin.z;
}
var dot1 = normal.x * vmin.x + normal.y * vmin.y + normal.z * vmin.z;
if (dot1 + planeDistance < 0)
return false;
var dot2 = normal.x * vmax.x + normal.y * vmax.y + normal.z * vmax.z;
if (dot2 + planeDistance <= 0)
return true;
}
return true;
}
}
public struct IntDist : IComparable<IntDist> {
public byte dist;
public short tile;
public int CompareTo(IntDist other) {
return other.tile - tile;
}
}
[BurstCompile]
public struct QueueTilesJob : IJob {
[ReadOnly] public NativeList<IntDist> Data;
public NativeList<int>.ParallelWriter CloseCount;
public NativeList<DrawContainer.Entry>.ParallelWriter Close;
[NativeDisableContainerSafetyRestriction, ReadOnly] public NativeArray<WildGrassTilePointers> Source;
[NativeDisableUnsafePtrRestriction, ReadOnly] public WildGrassTilePointers empty_tile;
internal int max_size;
public unsafe void Execute() {
int TClose = 0;
int Count = Data.Length;
for (int j = 0; j < Count; j++) {
short center = Data[j].tile;
WildGrassTilePointers tile = Source[center];
if (tile.Count == 0) {
continue;
}
int l = tile.Count;
int d = Data[j].dist;
if (d == 64) {
l /= 16;
} else if (d == 32) {
l /= 8;
} else if (d >= 8) {
l /= 4;
} else if (d >= 2) {
l /= 2;
}
if (l > 0) {
int oldl = l;
if (TClose < max_size) {
if (TClose + l > max_size) {
l = max_size - TClose;
}
Close.AddNoResize(new DrawContainer.Entry() { tile = tile, start = TClose, length = (short)l, centerIndex = center });
}
TClose += oldl;
}
}
#if !BeginEndWrite
if (TClose < max_size) {
int l = ECSDrawGrassSystem.ExtraGrassSize;
if (TClose + l > max_size) {
l = max_size - TClose;
}
Close.AddNoResize(new DrawContainer.Entry() { tile = empty_tile, start = TClose, length = (short)l, centerIndex = 0 });
TClose += ECSDrawGrassSystem.ExtraGrassSize;
}
#endif
CloseCount.AddNoResize(TClose);
}
}
[BurstCompile]
public struct CountAndSumJob : IJob {
internal NativeList<int> sizeargs;
internal NativeArray<uint> args;
internal NativeArray<uint> _CountWrite;
internal int max_size;
public unsafe void Execute() {
int total = 0;
for (int i = 0; i < sizeargs.Length; i++) {
total += sizeargs[i];
}
// if (total != 0) {
_CountWrite[0] = args[0];
_CountWrite[1] = args[1] = math.max(0, (uint)(math.min(total, max_size)));
_CountWrite[2] = args[2];
_CountWrite[3] = args[3];
_CountWrite[4] = args[4];
args[5] = (uint)total;
// }
}
}
