Search Unity

[Solved?]Graphics.DrawMeshInstancedIndirect not working on the Player, but working on Editor

Discussion in 'Scripting' started by Guedez, Jul 5, 2020.

  1. Guedez

    Guedez

    Joined:
    Jun 1, 2012
    Posts:
    827
    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: https://forum.unity.com/threads/flickering-when-rendering.914459/
    Or worse, this could be silently happening on the player: https://forum.unity.com/threads/d3d...-of-size-4194304-falling-back-to-slow.915953/
    Images:
    In Editor (Game Window, the grass does not render in the Scene view):

    In Player:
    https://i.imgur.com/dOMyZIw.png
    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
    Code (CSharp):
    1. //#if UNITY_EDITOR
    2. #define BeginEndWrite
    3. //#endif
    4. using GuedezGrassSystem;
    5. using System;
    6. using System.Linq;
    7. using Unity.Burst;
    8. using Unity.Collections;
    9. using Unity.Collections.LowLevel.Unsafe;
    10. using Unity.Entities;
    11. using Unity.Jobs;
    12. using Unity.Mathematics;
    13. using UnityEngine;
    14.  
    15. public class DrawContainer {
    16.     public ComputeBuffer _positions;
    17.     public ComputeBuffer _typelen;
    18.     public ComputeBuffer _bbnn;
    19.     public ComputeBuffer _argsBuffer;
    20.     //public ComputeBuffer _positions2;
    21.     //public ComputeBuffer _argsBuffer2;
    22.     public NativeArray<uint> args;
    23.  
    24.     //   public NativeArray<float3> _centersWrite;
    25.     public NativeArray<uint> _CountWrite;
    26.     public NativeArray<uint> _positionsWrite;
    27.     public NativeArray<uint> _typelenWrite;
    28.     public NativeArray<uint> _bbnnWrite;
    29.  
    30.     public MaterialPropertyBlock block;
    31.     private bool castshadow;
    32.     private bool receiveshadow;
    33.  
    34.  
    35.     public NativeList<Entry> accumulator;
    36.     public NativeList<IntDist> entries;
    37.     public NativeList<int> sizeargs;
    38.     private bool _Writting = false;
    39.  
    40.     public DrawContainer(bool castshadow, bool receiveshadow) {
    41.         block = new MaterialPropertyBlock();
    42.         this.castshadow = castshadow;
    43.         this.receiveshadow = receiveshadow;
    44.         args = new NativeArray<uint>(6, Allocator.Persistent);
    45.         sizeargs = new NativeList<int>(128, Allocator.Persistent);
    46.  
    47.         accumulator = new NativeList<Entry>(1024, Allocator.Persistent);
    48.         entries = new NativeList<IntDist>(1024, Allocator.Persistent);
    49.     }
    50.  
    51.     public void Dispose() {
    52.         if (accumulator.IsCreated) {
    53.             accumulator.Dispose();
    54.             entries.Dispose();
    55.             sizeargs.Dispose();
    56.             args.Dispose();
    57.         }
    58.         if (_positions != null && _positions.IsValid()) {
    59. #if !BeginEndWrite
    60.             _CountWrite.Dispose();
    61.             _positionsWrite.Dispose();
    62.             _typelenWrite.Dispose();
    63.             _bbnnWrite.Dispose();
    64. #else
    65.             if (_Writting) {
    66.                 try {
    67.                     _argsBuffer.EndWrite<uint>(5);
    68.                     _positions.EndWrite<uint>((int)args[1]);
    69.                     _typelen.EndWrite<uint>((int)args[1]);
    70.                     _bbnn.EndWrite<uint>((int)args[1]);
    71.                 } catch (Exception e) { }
    72.             }
    73. #endif
    74.             _positions.Dispose();
    75.             _typelen.Dispose();
    76.             _bbnn.Dispose();
    77.             _argsBuffer.Dispose();
    78.             // _positions2.Dispose();
    79.             // _argsBuffer2.Dispose();
    80.         }
    81.     }
    82.  
    83.     public void Prepare(uint numIndices, ComputeBuffer centers) {
    84.         args[0] = numIndices;
    85. #if !BeginEndWrite
    86.         _positions = new ComputeBuffer(1024, 4, ComputeBufferType.Structured);
    87.         _typelen = new ComputeBuffer(1024, 4, ComputeBufferType.Structured);
    88.         _bbnn = new ComputeBuffer(1024, 4, ComputeBufferType.Structured);
    89.         _argsBuffer = new ComputeBuffer(5, 4, ComputeBufferType.IndirectArguments);
    90. #else
    91.         _positions = new ComputeBuffer(1024, 4, ComputeBufferType.Structured, ComputeBufferMode.SubUpdates);
    92.         _typelen = new ComputeBuffer(1024, 4, ComputeBufferType.Structured, ComputeBufferMode.SubUpdates);
    93.         _bbnn = new ComputeBuffer(1024, 4, ComputeBufferType.Structured, ComputeBufferMode.SubUpdates);
    94.         _argsBuffer = new ComputeBuffer(5, 4, ComputeBufferType.IndirectArguments, ComputeBufferMode.SubUpdates);
    95. #endif
    96. #if !BeginEndWrite
    97.         _CountWrite = new NativeArray<uint>(5, Allocator.Persistent);
    98.         _positionsWrite = new NativeArray<uint>(_positions.count, Allocator.Persistent);
    99.         _typelenWrite = new NativeArray<uint>(_positions.count, Allocator.Persistent);
    100.         _bbnnWrite = new NativeArray<uint>(_positions.count, Allocator.Persistent);
    101. #endif
    102.         //_positions2 = new ComputeBuffer(1024, 4, ComputeBufferType.Structured, ComputeBufferMode.SubUpdates);
    103.         //  _argsBuffer2 = new ComputeBuffer(5, 4, ComputeBufferType.IndirectArguments, ComputeBufferMode.SubUpdates);
    104.     }
    105.  
    106.     public void PrepareBlock() {
    107.         block.SetBuffer("position", _positions);
    108.         block.SetBuffer("TL", _typelen);
    109.         block.SetBuffer("BBDNN", _bbnn);
    110.     }
    111.  
    112.     public void Draw(Material mat, Camera cam) {
    113.         //    _centers.EndWrite<float3>(lastCount);
    114.         Mesh mesh = GrassSystem.baseMesh[0];
    115.         Bounds bounds1 = new Bounds(cam.transform.position, Vector3.one * 2500);
    116.  
    117.         Graphics.DrawMeshInstancedIndirect(mesh, 0, mat, bounds1, _argsBuffer, 0, block,
    118. castshadow ? UnityEngine.Rendering.ShadowCastingMode.TwoSided : UnityEngine.Rendering.ShadowCastingMode.Off, receiveshadow, 0, cam);
    119.  
    120.     }
    121.  
    122.     public struct Entry {
    123.         public WildGrassTilePointers tile;
    124.         public int start;
    125.         public short length;
    126.         public short centerIndex;
    127.     }
    128.  
    129.     internal int Resize() {
    130.  
    131. #if !BeginEndWrite
    132.         if (Utils.RecreateIfSmaller(ref _positions, 4, (int)args[5], ComputeBufferType.Structured, ComputeBufferMode.Dynamic, 1.2f)) {
    133. #else
    134.         if (Utils.RecreateIfSmaller(ref _positions, 4, (int)args[5], ComputeBufferType.Structured, ComputeBufferMode.SubUpdates, 1.2f)) {
    135. #endif
    136. #if !BeginEndWrite
    137.             _positionsWrite.Dispose();
    138.             _typelenWrite.Dispose();
    139.             _bbnnWrite.Dispose();
    140.             _positionsWrite = new NativeArray<uint>(_positions.count, Allocator.Persistent);
    141.             _typelenWrite = new NativeArray<uint>(_positions.count, Allocator.Persistent);
    142.             _bbnnWrite = new NativeArray<uint>(_positions.count, Allocator.Persistent);
    143. #endif
    144.         }
    145.         //if (Utils.RecreateIfSmaller(ref _positions2, 4, (int)args[5], ComputeBufferType.Structured, ComputeBufferMode.SubUpdates, 1.2f)) {
    146.         //block.SetBuffer("position", _positions2);
    147.         //}
    148. #if !BeginEndWrite
    149.         if (Utils.RecreateIfSmaller(ref _typelen, 4, (int)args[5], ComputeBufferType.Structured, ComputeBufferMode.Dynamic, 1.2f)) {
    150. #else
    151.         if (Utils.RecreateIfSmaller(ref _typelen, 4, (int)args[5], ComputeBufferType.Structured, ComputeBufferMode.SubUpdates, 1.2f)) {
    152. #endif
    153.             //block.SetBuffer("position", _positions);
    154.         }
    155. #if !BeginEndWrite
    156.         if (Utils.RecreateIfSmaller(ref _bbnn, 4, (int)args[5], ComputeBufferType.Structured, ComputeBufferMode.Dynamic, 1.2f)) {
    157. #else
    158.         if (Utils.RecreateIfSmaller(ref _bbnn, 4, (int)args[5], ComputeBufferType.Structured, ComputeBufferMode.SubUpdates, 1.2f)) {
    159. #endif
    160.             //block.SetBuffer("position", _positions);
    161.         }
    162.         return _positions.count;
    163.     }
    164.     public void EndWrite() {
    165.         if (_Writting && args[1] > 0) {
    166. #if BeginEndWrite
    167.             _argsBuffer.EndWrite<uint>(5);
    168.             _positions.EndWrite<uint>((int)args[1]);
    169.             _typelen.EndWrite<uint>((int)args[1]);
    170.             _bbnn.EndWrite<uint>((int)args[1]);
    171. #endif
    172.             _Writting = false;
    173.         }
    174.         //if (_positionsWrite.IsCreated) {
    175.         //    _positionsWrite.Dispose();
    176.         //}
    177.         //}
    178.     }
    179.     public void BeginWrite() {
    180.         if (!_Writting) {
    181. #if BeginEndWrite
    182.             _CountWrite = _argsBuffer.BeginWrite<uint>(0, 5);
    183.             _positionsWrite = _positions.BeginWrite<uint>(0, _positions.count);
    184.             _typelenWrite = _typelen.BeginWrite<uint>(0, _typelen.count);
    185.             _bbnnWrite = _bbnn.BeginWrite<uint>(0, _bbnn.count);
    186. #endif
    187.             //_positionsWrite = new NativeArray<uint>(_positions.count, Allocator.TempJob);
    188.             _Writting = true;
    189.             PrepareBlock();
    190.             //PrepareBlock();
    191.         }
    192.     }
    193.  
    194.     public void Swap() {
    195.         //Utils.Swap(ref _positions, ref _positions2);
    196.         // Utils.Swap(ref _argsBuffer, ref _argsBuffer2);
    197.     }
    198.  
    199.     public unsafe JobHandle Schedule(JobHandle inputDeps, int max_tiles) {
    200.         AccumulateJob job = new AccumulateJob();
    201.         job.accumulator = accumulator;
    202.         //job.max_size = max_grass;
    203.         job.positions = _positionsWrite.GetUnsafePtr();
    204.         job.type_lenghts = _typelenWrite.GetUnsafePtr();
    205.         job.bend_benddir_none_none = _bbnnWrite.GetUnsafePtr();
    206.         return job.ScheduleBatch(max_tiles, 32, inputDeps);
    207.     }
    208.  
    209.     public void Clear() {
    210.         accumulator.Clear();
    211.         sizeargs.Clear();
    212.         entries.Clear();
    213.     }
    214.  
    215.     internal void SetData() {
    216.         _argsBuffer.SetData(_CountWrite);
    217.         _positions.SetData(_positionsWrite, 0, 0, _positionsWrite.Length);
    218.         uint[] _positionsGet = new uint[_positionsWrite.Length];
    219.         _positions.GetData(_positionsGet);
    220.         _typelen.SetData(_typelenWrite, 0, 0, _positionsWrite.Length);
    221.         _bbnn.SetData(_bbnnWrite, 0, 0, _positionsWrite.Length);
    222.     }
    223.  
    224.     //internal void Order() {
    225.     //    tiles.Sort((T1, T2) => (int)(T1.dist - T2.dist));
    226.     //}
    227. }
    228.  
    229. public class DrawContainerContainer {
    230.     public DrawContainer Close;
    231.     public DrawContainer Medium;
    232.     public DrawContainer Far;
    233.     public DrawContainerContainer() {
    234.         Close = new DrawContainer(true, true);//shadow
    235.         Medium = new DrawContainer(false, true);//no shadow cast
    236.         Far = new DrawContainer(false, false);//no shadow
    237.     }
    238.  
    239.     internal void Dispose() {
    240.         Close.Dispose();
    241.         Medium.Dispose();
    242.         Far.Dispose();
    243.     }
    244.  
    245.     internal void Prepare(uint numIndices, ComputeBuffer centers) {
    246.         Close.Prepare(numIndices, centers);
    247.         Medium.Prepare(numIndices, centers);
    248.         Far.Prepare(numIndices, centers);
    249.     }
    250. }
    251.  
    252. [UpdateInGroup(typeof(LateSimulationSystemGroup))]
    253. [UpdateAfter(typeof(ECSGrassBendDoBend))]
    254. [UpdateAfter(typeof(ECSGrassBendDoCut))]
    255. public class ECSDrawGrassSystemDoDraw : JobComponentSystem {
    256.     protected override JobHandle OnUpdate(JobHandle inputDeps) {
    257.         ECSDrawGrassSystem.combined.Complete();
    258.         for (int i = 0; i < ECSGrassSystem.configs.Length; i++) {
    259.             DrawContainerContainer cont = ECSGrassSystem.configs[i].container;
    260.  
    261.             DrawContainer Close = cont.Close;
    262.             DrawContainer Medium = cont.Medium;
    263.             DrawContainer Far = cont.Far;
    264.  
    265. #if !BeginEndWrite
    266.             Close.SetData();
    267.             Medium.SetData();
    268.             Far.SetData();
    269. #else
    270.             Close.EndWrite();
    271.             Medium.EndWrite();
    272.             Far.EndWrite();
    273. #endif
    274.         }
    275.         return inputDeps;
    276.     }
    277. }
    278. public class ECSDrawGrassSystem : JobComponentSystem {
    279.     public Plane[] lastPlanes;
    280.     UpdateFrustrumCulling.FrustrumPlanes frustrumPlanes;
    281.     private WildGrassTilePointers EmptyTile;
    282.     private NativeArray<uint> EmptyArray;
    283.  
    284.     public static JobHandle combined;
    285.     public const int ExtraGrassSize = 32000;
    286.  
    287.     protected override void OnDestroy() {
    288.         base.OnDestroy();
    289.         if (EmptyArray.IsCreated) {
    290.             EmptyArray.Dispose();
    291.         }
    292.     }
    293.  
    294.     protected unsafe override void OnCreate() {
    295.         base.OnCreate();
    296.  
    297.  
    298.         EmptyArray = new NativeArray<uint>(ExtraGrassSize, Allocator.Persistent);
    299.         for (int i = 0; i < EmptyArray.Length; i++) {
    300.             EmptyArray[i] = 0;
    301.         }
    302.         EmptyTile = new WildGrassTilePointers();
    303.         EmptyTile.Count = ExtraGrassSize;
    304.         IntPtr intPtr = new IntPtr(EmptyArray.GetUnsafeReadOnlyPtr());
    305.         EmptyTile.Positions = intPtr;
    306.         EmptyTile.TypesLenghts = intPtr;
    307.         EmptyTile.BendBendDirectionNoneNone = intPtr;
    308.  
    309.         //Close.PrepareBlock();
    310.         //Medium.PrepareBlock();
    311.         //Far.PrepareBlock();
    312.     }
    313.  
    314.     protected override JobHandle OnUpdate(JobHandle inputDeps) {
    315.         if (!combined.IsCompleted) {
    316.             combined.Complete();
    317.         }
    318.         if (ECSGrassSystem.configs.Length == 0) {
    319.             return inputDeps;
    320.         }
    321.         bool same = false;
    322.         Plane[] planes = GeometryUtility.CalculateFrustumPlanes(ECSGrassSystem.configs[0].cam);
    323.         if (lastPlanes != null && planes.SequenceEqual(lastPlanes)) {
    324.             same = true;
    325.         } else {
    326.             frustrumPlanes = new UpdateFrustrumCulling.FrustrumPlanes() {
    327.                 Left = planes[0],
    328.                 Right = planes[1],
    329.                 Down = planes[2],
    330.                 Up = planes[3],
    331.                 Near = planes[4],
    332.                 Far = planes[5]
    333.             };
    334.         }
    335.         lastPlanes = planes;
    336.         for (int i = 0; i < ECSGrassSystem.configs.Length; i++) {
    337.             var config = ECSGrassSystem.configs[i];
    338.             config.SetMaterial();
    339.             DrawContainerContainer cont = config.container;
    340.  
    341.             DrawContainer Close = cont.Close;
    342.             DrawContainer Medium = cont.Medium;
    343.             DrawContainer Far = cont.Far;
    344.  
    345.             Far.Draw(config.material, config.cam);
    346.             Medium.Draw(config.material, config.cam);
    347.             Close.Draw(config.material, config.cam);
    348.             if (same) {
    349.                 continue;
    350.             }
    351.             int close_max = 0, medium_max = 0, far_max = 0;
    352.             BeginWriteEndWriteMethod(Close, Medium, Far, out close_max, out medium_max, out far_max);
    353.  
    354.             Vector3 position = config.cam.transform.position;
    355.  
    356.             EnsureCapacity(config, Close, Medium, Far);
    357.  
    358.             int length = Close.accumulator.Length;
    359.             int length1 = Medium.accumulator.Length;
    360.             int length2 = Far.accumulator.Length;
    361.  
    362.             ResizeAndClear(Close, Medium, Far);
    363.  
    364.             FrustrumCheckerJob bounder = new FrustrumCheckerJob();
    365.             bounder.Frustrum = frustrumPlanes;
    366.             bounder.position = position;
    367.             bounder.Close = Close.entries.AsParallelWriter();
    368.             bounder.Medium = Medium.entries.AsParallelWriter();
    369.             bounder.Far = Far.entries.AsParallelWriter();
    370.             bounder.Source = config.ECSWildTiles;
    371.             bounder.Center = config._Centers;
    372.             JobHandle bounderhandle = bounder.ScheduleBatch(config.totalTiles, 32, inputDeps);
    373.  
    374.             FPSDisplay.ExtraText = "Total blades of grass: " +
    375.                 Close.args[1] + "(" + length + ")" + " | " +
    376.                 Medium.args[1] + "(" + length1 + ")" + " | " +
    377.                 Far.args[1] + "(" + length2 + ")" + " | " +
    378.                 (Close.args[1] + Medium.args[1] + Far.args[1]);
    379.  
    380.             combined = JobHandle.CombineDependencies(
    381.                 ScheduleQueue(bounderhandle, Close, config, config.totalTiles, close_max),
    382.                 ScheduleQueue(bounderhandle, Medium, config, config.totalTiles, medium_max),
    383.                 ScheduleQueue(bounderhandle, Far, config, config.totalTiles, far_max));
    384.         }
    385.         return combined;
    386.     }
    387.  
    388.     private static void BeginWriteEndWriteMethod(DrawContainer Close, DrawContainer Medium, DrawContainer Far, out int close_max, out int medium_max, out int far_max) {
    389.  
    390.         close_max = Close.Resize();
    391.         medium_max = Medium.Resize();
    392.         far_max = Far.Resize();
    393.         Close.Swap();
    394.         Medium.Swap();
    395.         Far.Swap();
    396.         Close.BeginWrite();
    397.         Medium.BeginWrite();
    398.         Far.BeginWrite();
    399.     }
    400.  
    401.     private static void ResizeAndClear(DrawContainer Close, DrawContainer Medium, DrawContainer Far) {
    402.         Close.Clear();
    403.         Medium.Clear();
    404.         Far.Clear();
    405.     }
    406.  
    407.     private static void EnsureCapacity(GrassSystemConfig config, DrawContainer Close, DrawContainer Medium, DrawContainer Far) {
    408.         int count = config.totalTiles + 1;
    409.         if (Close.accumulator.Capacity < count) {
    410.             Close.accumulator.ResizeUninitialized((int)(count));
    411.             Close.entries.ResizeUninitialized((int)(count));
    412.         }
    413.         if (Medium.accumulator.Capacity < count) {
    414.             Medium.accumulator.ResizeUninitialized((int)(count));
    415.             Medium.entries.ResizeUninitialized((int)(count));
    416.         }
    417.         if (Far.accumulator.Capacity < count) {
    418.             Far.accumulator.ResizeUninitialized((int)(count));
    419.             Far.entries.ResizeUninitialized((int)(count));
    420.         }
    421.         int sc = count / 32 + 2;
    422.         if (Far.sizeargs.Capacity < sc) {
    423.             Close.sizeargs.ResizeUninitialized(sc);
    424.             Medium.sizeargs.ResizeUninitialized(sc);
    425.             Far.sizeargs.ResizeUninitialized(sc);
    426.         }
    427.     }
    428.  
    429.     private JobHandle ScheduleQueue(JobHandle bounder, DrawContainer Close, GrassSystemConfig config, int maxCount, int max_grass) {
    430.         QueueTilesJob job = new QueueTilesJob();
    431.         job.empty_tile = EmptyTile;
    432.         job.Data = Close.entries;
    433.         job.CloseCount = Close.sizeargs.AsParallelWriter();
    434.         job.Close = Close.accumulator.AsParallelWriter();
    435.         job.Source = config.ECSWildTiles;
    436.  
    437.         CountAndSumJob job2 = new CountAndSumJob();
    438.         job2.sizeargs = Close.sizeargs;
    439.         job2.args = Close.args;
    440.         job2._CountWrite = Close._CountWrite;
    441.  
    442.         job2.max_size = job.max_size = max_grass;
    443.  
    444.         return Close.Schedule(job2.Schedule(job.Schedule(bounder)), maxCount);
    445.  
    446.         //NON BEGINWRITE METHOD
    447.  
    448.         //CountAndSumJobSetData job2 = new CountAndSumJobSetData();
    449.         //job2.sizeargs = Close.sizeargs;
    450.         //job2.args = Close.args;
    451.  
    452.         //job2.Schedule(job.Schedule(bounder)).Complete();
    453.  
    454.         //if (Utils.RecreateIfSmaller(ref Close._positions, 4, (int)Close.args[1], ComputeBufferType.Structured, ComputeBufferMode.SubUpdates, 1.2f)) {
    455.         //    Close.block.SetBuffer("position", Close._positions);
    456.         //}
    457.         //Close.PrepareBlock();
    458.         //config.SetMaterial();
    459.         //Close._positionsWrite = new NativeArray<uint>((int)Close.args[1], Allocator.TempJob);
    460.         //int closeargs = (int)Close.args[1];
    461.         //Close.Schedule(default, maxCount, (int)Close.args[1]).Complete();
    462.         //Close._positions.SetData(Close._positionsWrite);
    463.         //uint[] datacheck = new uint[Close._positions.count];
    464.         //Close._positions.GetData(datacheck);
    465.         //Close._positionsWrite.Dispose();
    466.         //Close._argsBuffer.SetData(Close.args);
    467.         //Close.Draw(config.material, config.cam);
    468.         //return default;
    469.     }
    470. }
    471.  
    472. [BurstCompile]
    473. public unsafe struct AccumulateJob : IJobParallelForBatch {//ParallelForBatch {
    474.     //public int max_size;
    475.     [ReadOnly] public NativeList<DrawContainer.Entry> accumulator;
    476.     [NativeDisableUnsafePtrRestriction] public void* positions;
    477.     [NativeDisableUnsafePtrRestriction] public void* type_lenghts;
    478.     [NativeDisableUnsafePtrRestriction] public void* bend_benddir_none_none;
    479.     public unsafe void Execute(int startIndex, int count) {
    480.         int end = startIndex + count;
    481.         for (int j = startIndex; j < end; j++) {
    482.             if (j >= accumulator.Length) {
    483.                 return;
    484.             }
    485.             var offset = accumulator[j].start;
    486.             var size = accumulator[j].length;// math.min(max_size - offset, accumulator[j].length);
    487.             //if (max_size - offset < 1000 || size < 1) {
    488.             //    continue;
    489.             //}
    490.             byte* offpositions = (byte*)positions;
    491.             offpositions += offset * 4;
    492.             byte* offtype_lenghts = (byte*)type_lenghts;
    493.             offtype_lenghts += offset * 4;
    494.             byte* offbend_benddir_none_none = (byte*)bend_benddir_none_none;
    495.             offbend_benddir_none_none += offset * 4;
    496.             UnsafeUtility.MemCpy(offpositions, accumulator[j].tile.Positions.ToPointer(), size * 4);
    497.             UnsafeUtility.MemCpy(offtype_lenghts, accumulator[j].tile.TypesLenghts.ToPointer(), size * 4);
    498.             UnsafeUtility.MemCpy(offbend_benddir_none_none, accumulator[j].tile.BendBendDirectionNoneNone.ToPointer(), size * 4);
    499.         }
    500.     }
    501. }
    502.  
    503. [BurstCompile]
    504. public struct FrustrumCheckerJob : IJobParallelForBatch {
    505.     public UpdateFrustrumCulling.FrustrumPlanes Frustrum;
    506.     public float3 position;
    507.     public NativeList<IntDist>.ParallelWriter Close;
    508.     public NativeList<IntDist>.ParallelWriter Medium;
    509.     public NativeList<IntDist>.ParallelWriter Far;
    510.     [NativeDisableContainerSafetyRestriction, ReadOnly] public NativeArray<WildGrassTilePointers> Source;
    511.     [NativeDisableContainerSafetyRestriction, ReadOnly] public NativeArray<float3> Center;
    512.  
    513.     public unsafe void Execute(int startIndex, int count) {
    514.         int end = startIndex + count;
    515.         for (int j = startIndex; j < end; j++) {
    516.             WildGrassTilePointers tile = Source[j];
    517.             if (tile.Count == 0) {
    518.                 continue;
    519.             }
    520.             Vector3 min = tile.bounds.min;
    521.             Vector3 max = tile.bounds.max;
    522.             if (CheckPlanes(min, max)) {
    523.                 float d = Vector3.Distance(Center[j], position);
    524.                 float x = Math.Max(0, d - 15) / 4;
    525.                 int closestPower = Mathf.RoundToInt(Mathf.Pow(2, Mathf.Ceil(Mathf.Log(x, 2))));
    526.                 d = Mathf.Min(64, Mathf.Max(1, closestPower));
    527.                 if (d <= 4) {
    528.                     Close.AddNoResize(new IntDist() { tile = (short)j, dist = (byte)d });
    529.                 } else if (d < 32) {
    530.                     Medium.AddNoResize(new IntDist() { tile = (short)j, dist = (byte)d });
    531.                 } else {
    532.                     Far.AddNoResize(new IntDist() { tile = (short)j, dist = (byte)d });
    533.                 }
    534.             }
    535.         }
    536.     }
    537.  
    538.  
    539.     private bool CheckPlanes(float3 boundsMin, float3 boundsMax) {
    540.         Vector3 vmin, vmax;
    541.         for (int planeIndex = 0; planeIndex < 6; planeIndex++) {
    542.             var normal = Frustrum[planeIndex].normal;
    543.             var planeDistance = Frustrum[planeIndex].distance;
    544.             // X axis
    545.             if (normal.x < 0) {
    546.                 vmin.x = boundsMin.x;
    547.                 vmax.x = boundsMax.x;
    548.             } else {
    549.                 vmin.x = boundsMax.x;
    550.                 vmax.x = boundsMin.x;
    551.             }
    552.             // Y axis
    553.             if (normal.y < 0) {
    554.                 vmin.y = boundsMin.y;
    555.                 vmax.y = boundsMax.y;
    556.             } else {
    557.                 vmin.y = boundsMax.y;
    558.                 vmax.y = boundsMin.y;
    559.             }
    560.             // Z axis
    561.             if (normal.z < 0) {
    562.                 vmin.z = boundsMin.z;
    563.                 vmax.z = boundsMax.z;
    564.             } else {
    565.                 vmin.z = boundsMax.z;
    566.                 vmax.z = boundsMin.z;
    567.             }
    568.  
    569.             var dot1 = normal.x * vmin.x + normal.y * vmin.y + normal.z * vmin.z;
    570.             if (dot1 + planeDistance < 0)
    571.                 return false;
    572.  
    573.             var dot2 = normal.x * vmax.x + normal.y * vmax.y + normal.z * vmax.z;
    574.             if (dot2 + planeDistance <= 0)
    575.                 return true;
    576.         }
    577.  
    578.         return true;
    579.     }
    580. }
    581. public struct IntDist : IComparable<IntDist> {
    582.     public byte dist;
    583.     public short tile;
    584.  
    585.     public int CompareTo(IntDist other) {
    586.         return other.tile - tile;
    587.     }
    588. }
    589. [BurstCompile]
    590. public struct QueueTilesJob : IJob {
    591.     [ReadOnly] public NativeList<IntDist> Data;
    592.     public NativeList<int>.ParallelWriter CloseCount;
    593.     public NativeList<DrawContainer.Entry>.ParallelWriter Close;
    594.     [NativeDisableContainerSafetyRestriction, ReadOnly] public NativeArray<WildGrassTilePointers> Source;
    595.     [NativeDisableUnsafePtrRestriction, ReadOnly] public WildGrassTilePointers empty_tile;
    596.     internal int max_size;
    597.  
    598.     public unsafe void Execute() {
    599.         int TClose = 0;
    600.         int Count = Data.Length;
    601.         for (int j = 0; j < Count; j++) {
    602.             short center = Data[j].tile;
    603.             WildGrassTilePointers tile = Source[center];
    604.             if (tile.Count == 0) {
    605.                 continue;
    606.             }
    607.             int l = tile.Count;
    608.             int d = Data[j].dist;
    609.             if (d == 64) {
    610.                 l /= 16;
    611.             } else if (d == 32) {
    612.                 l /= 8;
    613.             } else if (d >= 8) {
    614.                 l /= 4;
    615.             } else if (d >= 2) {
    616.                 l /= 2;
    617.             }
    618.             if (l > 0) {
    619.                 int oldl = l;
    620.                 if (TClose < max_size) {
    621.                     if (TClose + l > max_size) {
    622.                         l = max_size - TClose;
    623.                     }
    624.                     Close.AddNoResize(new DrawContainer.Entry() { tile = tile, start = TClose, length = (short)l, centerIndex = center });
    625.                 }
    626.                 TClose += oldl;
    627.             }
    628.         }
    629. #if !BeginEndWrite
    630.         if (TClose < max_size) {
    631.             int l = ECSDrawGrassSystem.ExtraGrassSize;
    632.             if (TClose + l > max_size) {
    633.                 l = max_size - TClose;
    634.             }
    635.             Close.AddNoResize(new DrawContainer.Entry() { tile = empty_tile, start = TClose, length = (short)l, centerIndex = 0 });
    636.             TClose += ECSDrawGrassSystem.ExtraGrassSize;
    637.         }
    638. #endif
    639.         CloseCount.AddNoResize(TClose);
    640.     }
    641. }
    642. [BurstCompile]
    643. public struct CountAndSumJob : IJob {
    644.     internal NativeList<int> sizeargs;
    645.     internal NativeArray<uint> args;
    646.     internal NativeArray<uint> _CountWrite;
    647.     internal int max_size;
    648.  
    649.     public unsafe void Execute() {
    650.         int total = 0;
    651.         for (int i = 0; i < sizeargs.Length; i++) {
    652.             total += sizeargs[i];
    653.         }
    654.         // if (total != 0) {
    655.         _CountWrite[0] = args[0];
    656.         _CountWrite[1] = args[1] = math.max(0, (uint)(math.min(total, max_size)));
    657.         _CountWrite[2] = args[2];
    658.         _CountWrite[3] = args[3];
    659.         _CountWrite[4] = args[4];
    660.         args[5] = (uint)total;
    661.         // }
    662.     }
    663. }
     
    Last edited: Jul 5, 2020
  2. Zer0Cool

    Zer0Cool

    Joined:
    Oct 24, 2014
    Posts:
    203
    Its only a guess, but the edtior camera uses another frustum (culling) area than the ingame camera and therefore in the editor the grass details will not be culled. So i assume there is a failure in the frustum culling code of your shader or compute shader (depends on where the culling mechanism is computed). I had similar problems at the time where i programmed such a system.
     
    Guedez likes this.
  3. Guedez

    Guedez

    Joined:
    Jun 1, 2012
    Posts:
    827
    My bad, the picture I posted is not showing it, but the editor screenshot is the Game window maximized. The grass don't render in the scene view
     
  4. Guedez

    Guedez

    Joined:
    Jun 1, 2012
    Posts:
    827
    Turns out the code that made so I not set the material properties every cycle was the reason. It used to work fine with it

    Code (CSharp):
    1.     public void SetMaterial() {//only runs every frame because I need this to run when I change the shader during runtime
    2.         if (requires_material_update) {//otherwise I would never even run SetMaterial every frame
    3. #if !UNITY_EDITOR
    4.             requires_material_update = false;
    5. #endif
    6.             material.SetBuffer("centers", Centers);
    7.             material.SetBuffer("lenght", Lenght);
    8.             material.SetBuffer("bend", Bend);
    9.             material.SetBuffer("rotations", GrassTile.rotations);
    10.             material.SetBuffer("types", GrassSystem.types);
    11.             material.SetFloat("_V_Time", EverydayEngine.GameEngine.CurrentGameTime);
    12.             material.SetFloat("_S_Time", StaticFlags.GameEngine_TimeFactor);
    13.  
    14.         }
    15.     }
    changing to 'fixes' it:
    Code (CSharp):
    1.     public void SetMaterial() {//running every frame
    2.         material.SetBuffer("centers", Centers);
    3.         material.SetBuffer("lenght", Lenght);
    4.         material.SetBuffer("bend", Bend);
    5.         material.SetBuffer("rotations", GrassTile.rotations);
    6.         material.SetBuffer("types", GrassSystem.types);
    7.         material.SetFloat("_V_Time", EverydayEngine.GameEngine.CurrentGameTime);
    8.         material.SetFloat("_S_Time", StaticFlags.GameEngine_TimeFactor);
    9.     }
     
    Zer0Cool likes this.