Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Compute Shader during design mode

Discussion in 'Shaders' started by Cherubim79, Nov 29, 2017.

  1. Cherubim79

    Cherubim79

    Joined:
    May 3, 2014
    Posts:
    56
    I'm building some components in Unity that use Compute Shaders but I want them to be designable during Edit Mode.

    This one just draws a couple of circles on the screen right now, it's the start for a simple open source data-driven animated pie chart I'm making. I'm recreating my library VirtualUI using the latest Compute Shaders and then work on having it use JSON against web-based services to bring in data.

    http://virtualui.codeplex.com


    I've got some buffers allocated at the class level and have the ExecuteInEditMode attribute on it, but during edit mode I get warnings about Garbage Collection and it messes up my RWStructuredBuffers. I thought maybe having it re-init my buffers during edit mode would do the trick but it doesn't, sometimes the buffer just goes away.

    During runtime it works fine though, I'd just like it running right in Edit mode so that it's more visually designable. This is what I've got so far just on a simple test, works fine except sometimes the garbage collector calls early and so in Scene mode it'll just sit there with no visual because the buffer has already been disposed automatically by the garbage collector and the warnings pop up.

    Is there any way to tell the Garbage Collector to not come around until I explicitly tell it to do so? There may be chocolate in a wrapper still that's edible. :p

    Code (csharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using System.Linq;
    5. using UnityEngine;
    6.  
    7. [ExecuteInEditMode]
    8. public class PieChart : MonoBehaviour {
    9.  
    10.     public float[] MockupData = { 20f, 60f, 50f, 30f };
    11.     public float Radius = 5.0f;
    12.     public float HoleRadius = 1.0f;
    13.     public int StepsPerAngle = 10;
    14.  
    15.     public ComputeShader ComputeShaderPieChart;
    16.  
    17.     ComputeBuffer inputBuffer;
    18.     ComputeBuffer percentBuffer;
    19.  
    20.     ComputeBuffer pointsInner;
    21.     ComputeBuffer pointsOuter;
    22.  
    23.     int kernel;
    24.     float[] percentageData;
    25.     Vector3[] PointsInner;
    26.     Vector3[] PointsOuter;
    27.  
    28.     public Material PieMaterial;
    29.     public Material InnerMaterial;
    30.  
    31.     // Use this for initialization
    32.     void Start () {
    33.         Init();
    34.     }
    35.  
    36.     void Init() {
    37.         percentageData = new float[MockupData.Length];
    38.         for (int z = 0; z < MockupData.Length; z++)
    39.         {
    40.             percentageData[z] = MockupData[z] / MockupData.Sum();
    41.         }
    42.         PointsInner = new Vector3[360 * StepsPerAngle];
    43.         PointsOuter = new Vector3[360 * StepsPerAngle];
    44.  
    45.         pointsInner = new ComputeBuffer(360 * StepsPerAngle, sizeof(float) * 3);
    46.         pointsOuter = new ComputeBuffer(360 * StepsPerAngle, sizeof(float) * 3);
    47.         inputBuffer = new ComputeBuffer(MockupData.Length, sizeof(float));
    48.         percentBuffer = new ComputeBuffer(percentageData.Length, sizeof(float));
    49.  
    50.         kernel = ComputeShaderPieChart.FindKernel("CSMain");
    51.  
    52.         ComputeShaderPieChart.SetBuffer(kernel, "InputData", inputBuffer);
    53.         ComputeShaderPieChart.SetBuffer(kernel, "PercentageData", percentBuffer);
    54.         ComputeShaderPieChart.SetBuffer(kernel, "PointsInner", pointsInner);
    55.         ComputeShaderPieChart.SetBuffer(kernel, "PointsOuter", pointsOuter);
    56.         inputBuffer.SetData(MockupData);
    57.         percentBuffer.SetData(percentageData);
    58.         pointsInner.SetData(PointsInner);
    59.         pointsOuter.SetData(PointsOuter);
    60.  
    61.     }
    62.  
    63.     void EditorUpdate() {
    64.         Init();
    65.         PlayerUpdate();
    66.     }
    67.  
    68.     void PlayerUpdate() {
    69.         ComputeShaderPieChart.SetFloat("Radius", Radius);
    70.         ComputeShaderPieChart.SetFloat("HoleRadius", HoleRadius);
    71.         ComputeShaderPieChart.SetInt("StepsPerAngle", StepsPerAngle);
    72.  
    73.         ComputeShaderPieChart.Dispatch(kernel, 1, 1, 1);
    74.  
    75.         PieMaterial.SetPass(0);
    76.         PieMaterial.SetBuffer("buffer", pointsOuter);
    77.         InnerMaterial.SetPass(0);
    78.         InnerMaterial.SetBuffer("buffer", pointsInner);
    79.     }
    80.    
    81.     // Update is called once per frame
    82.     void Update () {
    83.         if (!Application.isPlaying && Application.isEditor)
    84.             EditorUpdate();
    85.         else
    86.             PlayerUpdate();
    87.     }
    88.  
    89.     private void OnDestroy()
    90.     {
    91.         if (pointsInner != null) pointsInner.Release();
    92.         if (pointsOuter != null) pointsOuter.Release();
    93.         if (inputBuffer != null) inputBuffer.Release();
    94.         if (percentBuffer != null) percentBuffer.Release();
    95.     }
    96.  
    97.     void OnRenderObject() {
    98.         PieMaterial.SetPass(0);
    99.         Graphics.DrawProcedural(MeshTopology.Points, 1, 360 * StepsPerAngle);
    100.         InnerMaterial.SetPass(0);
    101.         Graphics.DrawProcedural(MeshTopology.Points, 1, 360 * StepsPerAngle);
    102.     }
    103. }
    104.  
     
  2. LennartJohansen

    LennartJohansen

    Joined:
    Dec 1, 2014
    Posts:
    2,394
    Sometimes unity clears these buffers if you save the scene. Could it be related to this?

    Did you see any other system to when you loose the buffer content.

    you can connect to the save events and set up the buffers again

    Code (csharp):
    1.  
    2.    EditorSceneManager.sceneSaving += OnSceneSaving;
    3.    EditorSceneManager.sceneSaved += OnSceneSaved;
    4.  
     
    Cherubim79 likes this.
  3. Cherubim79

    Cherubim79

    Joined:
    May 3, 2014
    Posts:
    56
    Certainly can't hurt, this is happening without saving though. After I started looking around at when it's actually glitching it's happening whenever you move the mouse into Unity's other GUI menus like the Inspector or Assets/Project it glitches for a frame when you first mouseover.

    So I did something like this and it improves a bit at least there's no warnings because it will destroy the buffers on every render if you're in the editor, but the glitching still happens.

    Code (csharp):
    1.  
    2.     void OnRenderObject() {
    3.         if (pointsInner == null || pointsOuter == null) return;
    4.  
    5.         PieMaterial.SetPass(0);
    6.         Graphics.DrawProcedural(MeshTopology.Points, 1, 360 * StepsPerAngle);
    7.         InnerMaterial.SetPass(0);
    8.         Graphics.DrawProcedural(MeshTopology.Points, 1, 360 * StepsPerAngle);
    9.  
    10.         if (!Application.isPlaying && Application.isEditor)
    11.             OnDestroy();
    12.     }
    13.  
    Here's some pics of what's happening, only happens on the frame when you first move the mouse over to the GUI windows and back.
    https://imgur.com/a/cRfo3
     
  4. Cherubim79

    Cherubim79

    Joined:
    May 3, 2014
    Posts:
    56


    So here's where we're at right now. Got an Area chart with a Compute and a Vertex/Frag shader running in design mode. Works great but crashes my whole system at random on occasion. Sometimes when exiting from Play mode sometimes if I've let the MacBook go into standby. Works great during runtime the problem is all happening during design mode.

    Here's the code surely I'm doing something wrong here but I can't figure out what. Fresh out of ideas.

    Tried the sceneSaved one caused some kind of exception that it was trying to access the AreaChart and it was already destroyed.

    Compute Shader:
    Code (CSharp):
    1. // Each #kernel tells which function to compile; you can have many kernels
    2. #pragma kernel CSMain
    3. #pragma kernel CSBuildFaces
    4. #pragma kernel CSBuildInteriorFaces
    5.  
    6. struct QuadPoint
    7. {
    8.     float3 vertex;
    9.     float3 normal;
    10.     float4 color;
    11.     float2 uv;
    12. };
    13.  
    14. struct Quad
    15. {
    16.     QuadPoint bl;
    17.     QuadPoint tl;
    18.     QuadPoint br;
    19.  
    20.     QuadPoint tl2;
    21.     QuadPoint tr;
    22.     QuadPoint br2;
    23. };
    24.  
    25. StructuredBuffer<float> DataPoints;
    26. RWStructuredBuffer<float3> StagedDataExpanded;
    27. RWStructuredBuffer<Quad> FrontQuads;
    28. RWStructuredBuffer<Quad> BackQuads;
    29. RWStructuredBuffer<Quad> TopQuads;
    30. RWStructuredBuffer<Quad> BottomQuads;
    31. RWStructuredBuffer<Quad> LeftQuads;
    32. RWStructuredBuffer<Quad> RightQuads;
    33. float TotalWidth;
    34. float TotalHeight;
    35. int LengthDataPoints;
    36. int StepsPerDataPoint;
    37. float MinDataPoint;
    38. float MaxDataPoint;
    39. float ZDistance;
    40. float4 ChartColor;
    41. float BottomPadding;
    42. float3 LocalScale;
    43. float3 LocalPosition;
    44. float4x4 WorldMatrix;
    45. float AnimationTime;
    46.  
    47. float3 GetTriangleNormal(float3 a, float3 b, float3 c) {
    48.     float3 edge1 = b-a;
    49.     float3 edge2 = c-a;
    50.     float3 normal = cross(edge1,edge2);
    51.     return normal;
    52. }
    53.  
    54. QuadPoint GetQuadPoint(float3 vertex, float2 uv, int f, float3 vec2, float3 vec3, int flipped, float4 color) {
    55.     QuadPoint q;
    56.     q.vertex = vertex;
    57.     q.normal = GetTriangleNormal(vertex,vec2,vec3);
    58.     q.color = color;
    59.     if (flipped == 1) q.normal = -1 * q.normal;
    60.     q.uv = uv;
    61.     return q;
    62. }
    63.  
    64. float3 CalculateBezierPoint(float t, float3 p0, float3 p1, float3 p2, float3 p3)
    65. {
    66.     float u = 1 - t;
    67.     float tt = t * t;
    68.     float uu = u * u;
    69.     float uuu = uu * u;
    70.     float ttt = tt * t;
    71.  
    72.     float3 p = uuu * p0; //first term
    73.  
    74.     p += 3 * uu * t * p1; //second term
    75.     p += 3 * u * tt * p2; //third term
    76.     p += ttt * p3; //fourth term
    77.  
    78.     return p;
    79. }
    80.  
    81. float3 GetChartPoint(int cstep, int index) {
    82.     int currentstep = StepsPerDataPoint * index;
    83.     int nextstep    = StepsPerDataPoint * (index + 1);
    84.     int totalsteps  = StepsPerDataPoint * LengthDataPoints;
    85.  
    86.     float x1  = float(currentstep) / float(totalsteps) * TotalWidth;
    87.     float x2  = float(nextstep) / float(totalsteps) * TotalWidth;
    88.     float mid = ((x2 - x1) / 2);
    89.  
    90.     float miny = MinDataPoint;
    91.     float maxy = MaxDataPoint;
    92.     float delta = 0 - miny;
    93.     miny += delta;
    94.     maxy += delta;
    95.     float y1 = DataPoints[index];
    96.     y1 += delta;
    97.     float y2 = DataPoints[index + 1];
    98.     y2 += delta;
    99.     float heightdata = MaxDataPoint - MinDataPoint;
    100.     float multiplier = TotalHeight / heightdata;
    101.     y1 *= multiplier;
    102.     y2 *= multiplier;
    103.     y1 *= AnimationTime;
    104.     y2 *= AnimationTime;
    105.  
    106.     float3 p0 = float3(x1,y1,0);
    107.     float3 p3 = float3(x2,y2,0);
    108.     float3 p1 = p0 + float3(mid,0,0);
    109.     float3 p2 = p3 - float3(mid,0,0);
    110.     float t = float(cstep) / float(StepsPerDataPoint);
    111.     return CalculateBezierPoint(t, p0, p1, p2, p3);
    112. }
    113.  
    114. [numthreads(1,1,1)]
    115. void CSMain (uint3 id : SV_DispatchThreadID)
    116. {
    117.     if (LengthDataPoints < 2) return;
    118.     for (int s=0;s<StepsPerDataPoint;s++) {
    119.         for (int z=0;z<LengthDataPoints - 1;z++) {
    120.             float3 current = GetChartPoint(s,z);
    121.             int offset = z * StepsPerDataPoint + s;
    122.             StagedDataExpanded[offset] = current;
    123.         }
    124.     }
    125. }
    126.  
    127. [numthreads(1,1,1)]
    128. void CSBuildFaces (uint3 id : SV_DispatchThreadID)
    129. {
    130.     if (LengthDataPoints < 2) return;
    131.     int s = id.x; // step
    132.     int z = id.y; // data point
    133.  
    134.     if (s == StepsPerDataPoint && z >= LengthDataPoints - 1) return;
    135.  
    136.     int offset1 = z * StepsPerDataPoint + s;
    137.     int offset2 = offset1 + 1;
    138.     if (offset2 >= LengthDataPoints * StepsPerDataPoint) offset2 = LengthDataPoints * StepsPerDataPoint - 1;
    139.  
    140.     float3 datapoint1 = StagedDataExpanded[offset1];
    141.     float3 datapoint2 = StagedDataExpanded[offset2];
    142.  
    143.     float miny = MinDataPoint;
    144.     float maxy = MaxDataPoint;
    145.  
    146.     float delta = 0 - miny;
    147.  
    148.     float heightdata = maxy - miny;
    149.     float h1 = datapoint1.y / heightdata;
    150.     float h2 = datapoint2.y / heightdata;
    151.  
    152.     float4 color = ChartColor;
    153.  
    154.     int totalsteps = LengthDataPoints * StepsPerDataPoint;
    155.     int us1 = z * StepsPerDataPoint + s;
    156.     int us2 = us1 + s;
    157.     float u1 = float(us1) / float(totalsteps);
    158.     float u2 = float(us2) / float(totalsteps);
    159.  
    160.     Quad q;
    161.  
    162.     QuadPoint qtl;
    163.     QuadPoint qtr;
    164.     QuadPoint qbl;
    165.     QuadPoint qbr;
    166.  
    167.     float4x4 wmatrix = WorldMatrix;
    168.     float3 scale = LocalScale;
    169.     float3 position = LocalPosition;
    170.  
    171.     float bottompad = BottomPadding * AnimationTime;
    172.     float3 tl = datapoint1 + float3(0,bottompad,0);
    173.     float3 tr = datapoint2 + float3(0,bottompad,0);
    174.     float3 bl = tl;
    175.     bl.y = 0;
    176.     float3 br = tr;
    177.     br.y = 0;
    178.     tl.z += ZDistance;
    179.     tr.z += ZDistance;
    180.     bl.z += ZDistance;
    181.     br.z += ZDistance;
    182.     tl = mul(wmatrix,tl * scale) * scale + position;
    183.     tr = mul(wmatrix,tr * scale) * scale + position;
    184.     bl = mul(wmatrix,bl * scale) * scale + position;
    185.     br = mul(wmatrix,br * scale) * scale + position;
    186.  
    187.     qtl = GetQuadPoint(tl, float2(u1,h1), 0, tr, br, 0, color);
    188.     qtr = GetQuadPoint(tr, float2(u2,h2), 0, br, bl, 0, color);
    189.     qbl = GetQuadPoint(bl, float2(u1,0),  0, tl, tr, 0, color);
    190.     qbr = GetQuadPoint(br, float2(u2,0),  0, bl, tl, 0, color);
    191.  
    192.     q.bl = qbl;
    193.     q.tl = qtl;
    194.     q.br  = qbr;
    195.     q.tl2 = qtl;
    196.     q.tr = qtr;
    197.     q.br2 = qbr;
    198.  
    199.     uint qoffset = z * StepsPerDataPoint + s;
    200.  
    201.     FrontQuads[qoffset] = q;
    202.  
    203.     tl = datapoint1 + float3(0,bottompad,0);
    204.     tr = datapoint2 + float3(0,bottompad,0);
    205.     bl = tl;
    206.     bl.y = 0;
    207.     br = tr;
    208.     br.y = 0;
    209.     tl.z -= ZDistance;
    210.     tr.z -= ZDistance;
    211.     bl.z -= ZDistance;
    212.     br.z -= ZDistance;
    213.     tl = mul(wmatrix,tl * scale) * scale + position;
    214.     tr = mul(wmatrix,tr * scale) * scale + position;
    215.     bl = mul(wmatrix,bl * scale) * scale + position;
    216.     br = mul(wmatrix,br * scale) * scale + position;
    217.  
    218.     qtl = GetQuadPoint(tl, float2(u1,h1), 0, tr, br, 1, color);
    219.     qtr = GetQuadPoint(tr, float2(u2,h2), 0, br, bl, 1, color);
    220.     qbl = GetQuadPoint(bl, float2(u1,0),  0, tl, tr, 1, color);
    221.     qbr = GetQuadPoint(br, float2(u2,0),  0, bl, tl, 1, color);
    222.  
    223.     q.bl = qbl;
    224.     q.tl = qtl;
    225.     q.br  = qbr;
    226.     q.tl2 = qtl;
    227.     q.tr = qtr;
    228.     q.br2 = qbr;
    229.  
    230.     BackQuads[qoffset] = q;
    231.  
    232.     tl = datapoint1 + float3(0,bottompad,0);
    233.     tr = datapoint2 + float3(0,bottompad,0);
    234.     bl = tl;
    235.     br = tr;
    236.     tl.z += ZDistance;
    237.     tr.z += ZDistance;
    238.     bl.z -= ZDistance;
    239.     br.z -= ZDistance;
    240.     tl = mul(wmatrix,tl * scale) * scale + position;
    241.     tr = mul(wmatrix,tr * scale) * scale + position;
    242.     bl = mul(wmatrix,bl * scale) * scale + position;
    243.     br = mul(wmatrix,br * scale) * scale + position;
    244.  
    245.     qtl = GetQuadPoint(tl, float2(u1,h1), 0, tr, br, 0, color);
    246.     qtr = GetQuadPoint(tr, float2(u2,h2), 0, br, bl, 0, color);
    247.     qbl = GetQuadPoint(bl, float2(u1,0),  0, tl, tr, 0, color);
    248.     qbr = GetQuadPoint(br, float2(u2,0),  0, bl, tl, 0, color);
    249.  
    250.     q.bl = qbl;
    251.     q.tl = qtl;
    252.     q.br  = qbr;
    253.     q.tl2 = qtl;
    254.     q.tr = qtr;
    255.     q.br2 = qbr;
    256.  
    257.     TopQuads[qoffset] = q;
    258.  
    259.     tl = datapoint1 + float3(0,bottompad,0);
    260.     tr = datapoint2 + float3(0,bottompad,0);
    261.     tl.y = 0;
    262.     tr.y = 0;
    263.     bl = tl;
    264.     br = tr;
    265.     tl.z += ZDistance;
    266.     tr.z += ZDistance;
    267.     bl.z -= ZDistance;
    268.     br.z -= ZDistance;
    269.     tl = mul(wmatrix,tl * scale) * scale + position;
    270.     tr = mul(wmatrix,tr * scale) * scale + position;
    271.     bl = mul(wmatrix,bl * scale) * scale + position;
    272.     br = mul(wmatrix,br * scale) * scale + position;
    273.  
    274.     qtl = GetQuadPoint(tl, float2(u1,h1), 0, tr, br, 1, color);
    275.     qtr = GetQuadPoint(tr, float2(u2,h2), 0, br, bl, 1, color);
    276.     qbl = GetQuadPoint(bl, float2(u1,0),  0, tl, tr, 1, color);
    277.     qbr = GetQuadPoint(br, float2(u2,0),  0, bl, tl, 1, color);
    278.  
    279.     q.bl = qbl;
    280.     q.tl = qtl;
    281.     q.br  = qbr;
    282.     q.tl2 = qtl;
    283.     q.tr = qtr;
    284.     q.br2 = qbr;
    285.  
    286.     BottomQuads[qoffset] = q;
    287. }
    288.  
    289. [numthreads(1,1,1)]
    290. void CSBuildInteriorFaces(uint3 id : SV_DispatchThreadID)
    291. {
    292.     if (LengthDataPoints < 2) return;
    293.     int offset1 = 0;
    294.     int offset2 = ((LengthDataPoints - 1) * StepsPerDataPoint) - 1;
    295.  
    296.     float3 datapoint1 = StagedDataExpanded[offset1];
    297.     float3 datapoint2 = StagedDataExpanded[offset2];
    298.     float miny = MinDataPoint;
    299.     float maxy = MaxDataPoint;
    300.  
    301.     float delta = 0 - miny;
    302.  
    303.     float heightdata = maxy - miny;
    304.     float h1 = datapoint1.y / heightdata;
    305.     float h2 = datapoint2.y / heightdata;
    306.     float zdist = ZDistance;
    307.     float multiplier = TotalHeight / heightdata;
    308.  
    309.     float4x4 wmatrix = WorldMatrix;
    310.     float3 scale = LocalScale;
    311.     float3 position = LocalPosition;
    312.  
    313.     float bottompad = BottomPadding * AnimationTime;
    314.  
    315.     float st1 = 1;
    316.     float st2 = 1;
    317.     float z1 = zdist;
    318.     float z2 = -1 * zdist;
    319.     float y1 = st1 * h1;
    320.     float y2 = st2 * h2;
    321.     y1 = datapoint1.y + bottompad;
    322.     y2 = datapoint2.y + bottompad;
    323.     float x1 = 0;
    324.     float x2 = datapoint2.x;
    325.  
    326.     Quad q;
    327.  
    328.     QuadPoint qtl;
    329.     QuadPoint qtr;
    330.     QuadPoint qbl;
    331.     QuadPoint qbr;
    332.  
    333.     float3 tl = float3(x1,y1,z1);
    334.     float3 tr = float3(x1,y1,z2);
    335.     float3 bl = float3(x1,0,z1);
    336.     float3 br = float3(x1,0,z2);
    337.     float u1 = 0;
    338.     float u2 = 1;
    339.  
    340.     float4 color = ChartColor;
    341.     //color = float4(1,1,1,1);
    342.  
    343.     tl = mul(wmatrix,tl * scale) * scale + position;
    344.     tr = mul(wmatrix,tr * scale) * scale + position;
    345.     bl = mul(wmatrix,bl * scale) * scale + position;
    346.     br = mul(wmatrix,br * scale) * scale + position;
    347.  
    348.     qtl = GetQuadPoint(tl, float2(u1,1), 0, tr, br, 0, color);
    349.     qtr = GetQuadPoint(tr, float2(u2,1), 0, br, bl, 0, color);
    350.     qbl = GetQuadPoint(bl, float2(u1,0), 0, tl, tr, 0, color);
    351.     qbr = GetQuadPoint(br, float2(u2,0), 0, bl, tl, 0, color);
    352.  
    353.     q.bl = qbl;
    354.     q.tl = qtl;
    355.     q.br  = qbr;
    356.     q.tl2 = qtl;
    357.     q.tr = qtr;
    358.     q.br2 = qbr;
    359.  
    360.     LeftQuads[0] = q;
    361.  
    362.     //color = float4(1,1,1,1);
    363.  
    364.     tl = float3(x2,y2,z1);
    365.     tr = float3(x2,y2,z2);
    366.     bl = float3(x2,0,z1);
    367.     br = float3(x2,0,z2);
    368.     tl = mul(wmatrix,tl * scale) * scale + position;
    369.     tr = mul(wmatrix,tr * scale) * scale + position;
    370.     bl = mul(wmatrix,bl * scale) * scale + position;
    371.     br = mul(wmatrix,br * scale) * scale + position;
    372.  
    373.     qtl = GetQuadPoint(tl, float2(u1,1), 0, tr, br, 0, color);
    374.     qtr = GetQuadPoint(tr, float2(u2,1), 0, br, bl, 0, color);
    375.     qbl = GetQuadPoint(bl, float2(u1,0), 0, tl, tr, 0, color);
    376.     qbr = GetQuadPoint(br, float2(u2,0), 0, bl, tl, 0, color);
    377.  
    378.     q.bl = qbl;
    379.     q.tl = qtl;
    380.     q.br  = qbr;
    381.     q.tl2 = qtl;
    382.     q.tr = qtr;
    383.     q.br2 = qbr;
    384.  
    385.     RightQuads[0] = q;
    386. }
    Area Chart Script:
    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using System.Linq;
    5. using System.Runtime.InteropServices;
    6. using UnityEditor.SceneManagement;
    7. using UnityEngine;
    8.  
    9. [ExecuteInEditMode]
    10. public class AreaChart : MonoBehaviour {
    11.  
    12.     public struct QuadPoint
    13.     {
    14.         public Vector3 vertex;
    15.         public Vector3 normal;
    16.         public Vector4 color;
    17.         public Vector2 uv;
    18.     }
    19.  
    20.     public struct Quad
    21.     {
    22.         public QuadPoint tl;
    23.         public QuadPoint tr;
    24.         public QuadPoint bl;
    25.         public QuadPoint bl2;
    26.         public QuadPoint br;
    27.         public QuadPoint tr2;
    28.     };
    29.  
    30.     public float[] GetFloat(Matrix4x4 mat)
    31.     {
    32.         return new float[] {
    33.             mat.GetRow(0).x, mat.GetRow(0).y, mat.GetRow(0).z, mat.GetRow(0).w,
    34.             mat.GetRow(1).x, mat.GetRow(1).y, mat.GetRow(1).z, mat.GetRow(1).w,
    35.             mat.GetRow(2).x, mat.GetRow(2).y, mat.GetRow(2).z, mat.GetRow(2).w,
    36.             mat.GetRow(3).x, mat.GetRow(3).y, mat.GetRow(3).z, mat.GetRow(3).w
    37.         };
    38.     }
    39.  
    40.     ComputeShader shaderChart;
    41.  
    42.     ComputeBuffer bufDataPoints;
    43.     ComputeBuffer bufStagedDataExpanded;
    44.     ComputeBuffer bufQuadsFront;
    45.     ComputeBuffer bufQuadsBack;
    46.     ComputeBuffer bufQuadsTop;
    47.     ComputeBuffer bufQuadsBottom;
    48.     ComputeBuffer bufQuadsLeft;
    49.     ComputeBuffer bufQuadsRight;
    50.  
    51.     string main = "CSMain";
    52.     string build = "CSBuildFaces";
    53.     string interior = "CSBuildInteriorFaces";
    54.     int kernel;
    55.     int kernelbuild;
    56.     int kernelinterior;
    57.     int datalength;
    58.  
    59.     public float TotalWidth = 100f;
    60.     public float TotalHeight = 20f;
    61.     public int StepsPerDataPoint = 10;
    62.     public float[] DataPoints = { 1f, 5f, 0f, 9f };
    63.     public string[] DataLabels = { "Value 1", "Moo", "Piggy", "Chevy" };
    64.     public float ZDistance = 1f;
    65.     public float BottomPadding = 1f;
    66.     public Color ChartColor = Color.red;
    67.     public float AnimationTime = 1f;
    68.  
    69.     public Material ChartMaterial;
    70.  
    71.     // Use this for initialization
    72.     void Start () {
    73.         Init();
    74.         EditorSceneManager.sceneSaving += (scene, path) => {
    75.             Init();
    76.         };
    77.         EditorSceneManager.sceneSaved += (scene) => {
    78.             //Init();
    79.         };
    80.     }
    81.  
    82.     void Init() {
    83.         InitShader();
    84.         InitBuffers();
    85.         SetBuffers();
    86.     }
    87.  
    88.     void InitShader() {
    89.         shaderChart = Resources.Load<ComputeShader>("AreaChartCompute");
    90.         kernel = shaderChart.FindKernel(main);
    91.         kernelbuild = shaderChart.FindKernel(build);
    92.         kernelinterior = shaderChart.FindKernel(interior);
    93.     }
    94.  
    95.     void InitBuffers() {
    96.         if (shaderChart == null)
    97.             InitShader();
    98.  
    99.         datalength = DataPoints.Length;
    100.         bufDataPoints = new ComputeBuffer(DataPoints.Length, sizeof(float));
    101.         bufStagedDataExpanded = new ComputeBuffer(DataPoints.Length * StepsPerDataPoint, sizeof(float) * 3);
    102.         bufQuadsFront = new ComputeBuffer(DataPoints.Length * StepsPerDataPoint, Marshal.SizeOf(typeof(QuadPoint)) * 6);
    103.         bufQuadsBack = new ComputeBuffer(DataPoints.Length * StepsPerDataPoint, Marshal.SizeOf(typeof(QuadPoint)) * 6);
    104.         bufQuadsTop = new ComputeBuffer(DataPoints.Length * StepsPerDataPoint, Marshal.SizeOf(typeof(QuadPoint)) * 6);
    105.         bufQuadsBottom = new ComputeBuffer(DataPoints.Length * StepsPerDataPoint, Marshal.SizeOf(typeof(QuadPoint)) * 6);
    106.         bufQuadsLeft = new ComputeBuffer(1, Marshal.SizeOf(typeof(QuadPoint)) * 6);
    107.         bufQuadsRight = new ComputeBuffer(1, Marshal.SizeOf(typeof(QuadPoint)) * 6);
    108.     }
    109.  
    110.     void SetBuffers() {
    111.         if (bufDataPoints == null)
    112.             InitBuffers();
    113.  
    114.         shaderChart.SetFloat("TotalWidth", TotalWidth * ((float)(DataPoints.Length - 1) / (float)(DataPoints.Length - 2)));
    115.         shaderChart.SetFloat("TotalHeight", TotalHeight);
    116.         shaderChart.SetInt("LengthDataPoints", DataPoints.Length);
    117.         shaderChart.SetInt("StepsPerDataPoint", StepsPerDataPoint);
    118.         shaderChart.SetFloat("MinDataPoint", DataPoints.Min());
    119.         shaderChart.SetFloat("MaxDataPoint", DataPoints.Max());
    120.         shaderChart.SetFloat("ZDistance", ZDistance);
    121.         shaderChart.SetVector("ChartColor", ChartColor);
    122.         shaderChart.SetFloat("BottomPadding", BottomPadding);
    123.         shaderChart.SetVector("LocalPosition", transform.localPosition);
    124.         shaderChart.SetVector("LocalScale", transform.localScale);
    125.         shaderChart.SetFloats("WorldMatrix", GetFloat(transform.worldToLocalMatrix));
    126.         shaderChart.SetFloat("AnimationTime", AnimationTime);
    127.  
    128.         Action<int> setbuffers = new Action<int>((arg1) =>
    129.         {
    130.             shaderChart.SetBuffer(arg1, "DataPoints", bufDataPoints);
    131.             shaderChart.SetBuffer(arg1, "StagedDataExpanded", bufStagedDataExpanded);
    132.             shaderChart.SetBuffer(arg1, "FrontQuads", bufQuadsFront);
    133.             shaderChart.SetBuffer(arg1, "BackQuads", bufQuadsBack);
    134.             shaderChart.SetBuffer(arg1, "TopQuads", bufQuadsTop);
    135.             shaderChart.SetBuffer(arg1, "BottomQuads", bufQuadsBottom);
    136.             shaderChart.SetBuffer(arg1, "LeftQuads", bufQuadsLeft);
    137.             shaderChart.SetBuffer(arg1, "RightQuads", bufQuadsRight);
    138.         });
    139.         setbuffers(kernel);
    140.         setbuffers(kernelbuild);
    141.         setbuffers(kernelinterior);
    142.  
    143.         bufDataPoints.SetData(DataPoints);
    144.     }
    145.  
    146.     // Update is called once per frame
    147.     void Update () {
    148.         SetBuffers();
    149.  
    150.         shaderChart.Dispatch(kernel, 1, 1, 1);
    151.         shaderChart.Dispatch(kernelbuild, StepsPerDataPoint, DataPoints.Length, 1);
    152.         shaderChart.Dispatch(kernelinterior, 1, 1, 1);
    153.     }
    154.  
    155.     private void OnRenderObject()
    156.     {
    157.         if (ChartMaterial == null) return;
    158.         if (DataPoints == null) return;
    159.         ChartMaterial.SetPass(0);
    160.         ChartMaterial.SetBuffer("quadsFront", bufQuadsFront);
    161.         ChartMaterial.SetBuffer("quadsBack", bufQuadsBack);
    162.         ChartMaterial.SetBuffer("quadsTop", bufQuadsTop);
    163.         ChartMaterial.SetBuffer("quadsBottom", bufQuadsBottom);
    164.         int vcount = (DataPoints.Length - 1) * StepsPerDataPoint;
    165.         vcount *= 6; // quad points per quad
    166.         vcount -= 6;
    167.         Graphics.DrawProcedural(MeshTopology.Triangles, vcount, 4);
    168.         ChartMaterial.SetPass(1);
    169.         ChartMaterial.SetBuffer("quadsLeft", bufQuadsLeft);
    170.         ChartMaterial.SetBuffer("quadsRight", bufQuadsRight);
    171.         vcount = 6; // quad points per quad
    172.         Graphics.DrawProcedural(MeshTopology.Triangles, vcount, 2);
    173.     }
    174.  
    175.     private void OnDestroy()
    176.     {
    177.         if (bufDataPoints != null) bufDataPoints.Release();
    178.         if (bufStagedDataExpanded != null) bufStagedDataExpanded.Release();
    179.         if (bufQuadsFront != null) bufQuadsFront.Release();
    180.         if (bufQuadsBack != null) bufQuadsBack.Release();
    181.         if (bufQuadsTop != null) bufQuadsTop.Release();
    182.         if (bufQuadsBottom != null) bufQuadsBottom.Release();
    183.         if (bufQuadsLeft != null) bufQuadsLeft.Release();
    184.         if (bufQuadsRight != null) bufQuadsRight.Release();
    185.     }
    186. }
    Vertex/Frag Shader this one's a tad messy got some unused variables did a lot of experimenting but works:
    Code (CSharp):
    1. // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
    2.  
    3. // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
    4.  
    5. Shader "Custom/PieChartVertexFrag" {
    6.     Properties
    7.     {
    8.         _AnimationTime ("Animation Time", Range(0,1)) = 1
    9.         _ColorTop ("Color Top", Color) = (1,1,1,1)
    10.         _DiffuseDampen ("Diffuse Dampening", Range(0,1)) = 0.5
    11.     }
    12.  
    13.     SubShader
    14.     {
    15.         Tags {"Queue"="Transparent" "RenderType"="Transparent" }
    16.         Tags {"LightMode"="ShadowCaster"}
    17.         LOD 200
    18.         Blend SrcAlpha OneMinusSrcAlpha
    19.         ZTest Off
    20.         ZWrite Off
    21.         Cull Off
    22.         Pass
    23.         {
    24.             CGPROGRAM
    25.             #pragma target 4.5
    26.  
    27.             #include "UnityCG.cginc"
    28.             #include "Lighting.cginc"
    29.  
    30.             #pragma vertex vert
    31.             #pragma fragment frag
    32.  
    33.             struct QuadPoint
    34.             {
    35.                 float3 vertex;
    36.                 float3 normal;
    37.                 float4 color;
    38.                 float2 uv;
    39.             };
    40.  
    41.             struct VS_INPUT
    42.             {
    43.                 uint vertex_id : SV_VertexID;
    44.                 uint instance_id : SV_InstanceID;
    45.             };
    46.          
    47.             // Pixel shader input
    48.             struct PS_INPUT
    49.             {
    50.                 float3 vertex : POSITION1;
    51.                 float4 position : SV_POSITION;
    52.                 float4 color : COLOR;
    53.                 float3 normal : NORMAL;
    54.                 float2 screenpos : TEXCOORD1;
    55.             };
    56.  
    57.             struct Input {
    58.                 float2 uv_MainTex;
    59.             };
    60.  
    61.             // Properties variables
    62.             uniform float _DiffuseDampen;
    63.             uniform float4 _ColorTop;
    64.             uniform float _AnimationTime;
    65.  
    66.             // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
    67.             // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
    68.             // #pragma instancing_options assumeuniformscaling
    69.             UNITY_INSTANCING_CBUFFER_START(Props)
    70.                 // put more per-instance properties here
    71.                 //_ColorLow ("Color Slow Speed", Color) = (0, 0, 0.5, 0.3)
    72.                 //_ColorHigh ("Color High Speed", Color) = (1, 0, 0, 0.3)
    73.                 //UNITY_DEFINE_INSTANCED_PROP(fixed4, _ColorLow)
    74.             UNITY_INSTANCING_CBUFFER_END
    75.  
    76.             StructuredBuffer<QuadPoint> quads;
    77.  
    78.             StructuredBuffer<QuadPoint> quadsFront;
    79.             StructuredBuffer<QuadPoint> quadsBack;
    80.             StructuredBuffer<QuadPoint> quadsTop;
    81.             StructuredBuffer<QuadPoint> quadsBottom;
    82.  
    83.             // Vertex shader
    84.             PS_INPUT vert(VS_INPUT i)
    85.             {
    86.                 //Blend SrcAlpha One
    87.  
    88.                 PS_INPUT o = (PS_INPUT)0;
    89.  
    90.                 // Position
    91.                 uint inst = i.instance_id;
    92.                 uint v_id = i.vertex_id;
    93.  
    94.                 QuadPoint q;
    95.                 if (inst == 0) {
    96.                     q = quadsFront[v_id];
    97.                 }
    98.                 else if (inst == 1) {
    99.                     q = quadsBack[v_id];
    100.                 }
    101.                 else if (inst == 2) {
    102.                     q = quadsTop[v_id];
    103.                 }
    104.                 else if (inst == 3) {
    105.                     q = quadsBottom[v_id];
    106.                 }
    107.                 o.normal = q.normal;
    108.                 float3 test3 = normalize(UnityObjectToClipPos(float4(q.vertex, 1.0f)));
    109.  
    110.                 o.position = UnityObjectToClipPos(float4(q.vertex, 1.0f));
    111.                 o.vertex = test3;
    112.  
    113.  
    114.                 // get vertex normal in world space
    115.                 half3 worldNormal = UnityObjectToWorldNormal(o.normal);
    116.                 // dot product between normal and light direction for
    117.                 // standard diffuse (Lambert) lighting
    118.                 half nl = max(0, dot(worldNormal, _WorldSpaceLightPos0.xyz));
    119.                 // factor in the light color
    120.                 float4 diffuse = nl * _LightColor0;
    121.                 //diffuse.rgb += ShadeSH9(half4(worldNormal,1));
    122.  
    123.                 o.color = q.color + (diffuse * _DiffuseDampen);
    124.                 //o.color = q.color;
    125.                 return o;
    126.             }
    127.  
    128.             static const float PI = 3.14159265f;
    129.  
    130.             // Pixel shader
    131.             float4 frag(PS_INPUT i) : COLOR
    132.             {
    133.                 // Will be used for attenuation.
    134.                 float dist = length(_WorldSpaceLightPos0.xyz - i.vertex);
    135.                 // Get a lighting direction vector from the light to the vertex.
    136.                 float3 lightVector = normalize(_WorldSpaceLightPos0.xyz - i.vertex);
    137.                 // Calculate the dot product of the light vector and vertex normal. If the normal and light vector are
    138.                 // pointing in the same direction then it will get max illumination.
    139.                 float diffuse2 = max(dot(i.normal, lightVector), 0.1);
    140.                 // Add attenuation.
    141.                 diffuse2 *= (1.0 / (1.0 + (0.25 * dist * dist)));
    142.                 float4 pos = i.position;
    143.                 float r = 1;
    144.                 r = pos.y / _ScreenParams.y;
    145.                 i.color += float4(_ColorTop.rgb * r, 0);
    146.                 i.color.a *= _AnimationTime;
    147.                 return i.color;
    148.             }
    149.          
    150.             ENDCG
    151.         }
    152.         Pass {
    153.             CGPROGRAM
    154.             #pragma target 4.5
    155.  
    156.             #include "UnityCG.cginc"
    157.             #include "Lighting.cginc"
    158.  
    159.             #pragma vertex vert
    160.             #pragma fragment frag
    161.  
    162.             struct QuadPoint
    163.             {
    164.                 float3 vertex;
    165.                 float3 normal;
    166.                 float4 color;
    167.                 float2 uv;
    168.             };
    169.  
    170.             struct VS_INPUT
    171.             {
    172.                 uint vertex_id : SV_VertexID;
    173.                 uint instance_id : SV_InstanceID;
    174.             };
    175.          
    176.             // Pixel shader input
    177.             struct PS_INPUT
    178.             {
    179.                 float3 vertex : POSITION1;
    180.                 float4 position : SV_POSITION;
    181.                 float4 color : COLOR;
    182.                 float3 normal : NORMAL;
    183.                 float2 screenpos : TEXCOORD1;
    184.             };
    185.  
    186.             struct Input {
    187.                 float2 uv_MainTex;
    188.             };
    189.  
    190.             // Properties variables
    191.             uniform float _DiffuseDampen;
    192.             uniform float4 _ColorTop;
    193.             uniform float _AnimationTime;
    194.  
    195.             // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
    196.             // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
    197.             // #pragma instancing_options assumeuniformscaling
    198.             UNITY_INSTANCING_CBUFFER_START(Props)
    199.                 // put more per-instance properties here
    200.                 //_ColorLow ("Color Slow Speed", Color) = (0, 0, 0.5, 0.3)
    201.                 //_ColorHigh ("Color High Speed", Color) = (1, 0, 0, 0.3)
    202.                 //UNITY_DEFINE_INSTANCED_PROP(fixed4, _ColorLow)
    203.             UNITY_INSTANCING_CBUFFER_END
    204.  
    205.             StructuredBuffer<QuadPoint> quadsLeft;
    206.             StructuredBuffer<QuadPoint> quadsRight;
    207.  
    208.             // Vertex shader
    209.             PS_INPUT vert(VS_INPUT i)
    210.             {
    211.                 //Blend SrcAlpha One
    212.  
    213.                 PS_INPUT o = (PS_INPUT)0;
    214.  
    215.                 // Position
    216.                 uint inst = i.instance_id;
    217.                 uint v_id = i.vertex_id;
    218.  
    219.                 QuadPoint q;
    220.                 if (inst == 0) {
    221.                     q = quadsLeft[v_id];
    222.                 }
    223.                 else if (inst == 1) {
    224.                     q = quadsRight[v_id];
    225.                 }
    226.                 o.normal = q.normal;
    227.                 float3 test3 = normalize(UnityObjectToClipPos(float4(q.vertex, 1.0f)));
    228.  
    229.                 o.position = UnityObjectToClipPos(float4(q.vertex, 1.0f));
    230.                 o.vertex = test3;
    231.  
    232.  
    233.                 // get vertex normal in world space
    234.                 half3 worldNormal = UnityObjectToWorldNormal(o.normal);
    235.                 // dot product between normal and light direction for
    236.                 // standard diffuse (Lambert) lighting
    237.                 half nl = max(0, dot(worldNormal, _WorldSpaceLightPos0.xyz));
    238.                 // factor in the light color
    239.                 float4 diffuse = nl * _LightColor0;
    240.                 //diffuse.rgb += ShadeSH9(half4(worldNormal,1));
    241.  
    242.                 o.color = q.color + (diffuse * _DiffuseDampen);
    243.                 //o.color = q.color;
    244.                 return o;
    245.             }
    246.  
    247.             static const float PI = 3.14159265f;
    248.  
    249.             // Pixel shader
    250.             float4 frag(PS_INPUT i) : COLOR
    251.             {
    252.                 // Will be used for attenuation.
    253.                 float dist = length(_WorldSpaceLightPos0.xyz - i.vertex);
    254.                 // Get a lighting direction vector from the light to the vertex.
    255.                 float3 lightVector = normalize(_WorldSpaceLightPos0.xyz - i.vertex);
    256.                 // Calculate the dot product of the light vector and vertex normal. If the normal and light vector are
    257.                 // pointing in the same direction then it will get max illumination.
    258.                 float diffuse2 = max(dot(i.normal, lightVector), 0.1);
    259.                 // Add attenuation.
    260.                 diffuse2 *= (1.0 / (1.0 + (0.25 * dist * dist)));
    261.                 float4 pos = i.position;
    262.                 float r = 1;
    263.                 r = pos.y / _ScreenParams.y;
    264.                 i.color += float4(_ColorTop.rgb * r, 0);
    265.                 i.color.a *= _AnimationTime;
    266.                 return i.color;
    267.             }
    268.          
    269.             ENDCG
    270.         }
    271.     }
    272.  
    273.     Fallback Off
    274. }
     
  5. Cherubim79

    Cherubim79

    Joined:
    May 3, 2014
    Posts:
    56
    Oh if you guys want to give some general feedback and input on this project that's cool too. Figured something like this could help game devs who want to put in charting and stats in the leaderboards and such for games and I want to do regular every day things in Unity like looking at weather charts, sports stats, stuff like that.
     
  6. GoGoGadget

    GoGoGadget

    Joined:
    Sep 23, 2013
    Posts:
    864
    There is System.GC.Collect(); (which obviously calls the GC, therefore possibly 'stalling' it for a bit) but nothing that stops it. Only other thing I could think of to maybe try plugging around in is execution orders, maybe try and call all your compute shader stuff at one of the camera callbacks to see if that does anything rather than just Update().

    Overall looks like a really cool project! I'd be a bit scared using compute shaders in production on anything that's not widely tested to be honest, but I could see this being useful for some sort of UI plugin.
     
    Cherubim79 likes this.
  7. Cherubim79

    Cherubim79

    Joined:
    May 3, 2014
    Posts:
    56
    Thanks! Hoping the project will turn out quite nice for the community and help folks make some great apps and games.

    Trying out putting it all on OnRenderObject like you suggested, including the shader instantiation, seems to work fine so far I might want to do a little more testing to see if it hangs, usually hangs when I've been in the editor view for a maybe several minutes. Sometimes when coming back from play mode everything looks glitchy until you move the mouse around. Does get a tad glitchy for a frame when saving. So I'm wondering if in some state there's stale data or buffers of some sort laying around. I totally forgot about GC.Collect(), haven't used it in a good while, thanks for the refresher that may come in handy.
     
    GoGoGadget likes this.
  8. Cherubim79

    Cherubim79

    Joined:
    May 3, 2014
    Posts:
    56
    The scene view seems to get glitchy on exactly the frame after you save, right until you move the mouse or press the keyboard. So something's happening there, sometimes it gets into an infinite pinwheel on the Mac and I have to restart Unity. At least it seems to have moved past system freeze-ups since I moved everything to OnRenderObject in my testing today. So that's a plus. Can't tell whether it's a bug in my code or in Unity though, if Unity I'll hope it gets cleared up in the next release, only a minor annoyance as long as it doesn't freeze up the whole machine.

    Speaking of pinwheel...
     
  9. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    858
    Did anyone find a stable solution for use of ComputeBuffers in Editor mode?
     
  10. Cherubim79

    Cherubim79

    Joined:
    May 3, 2014
    Posts:
    56
    I never did, I also noticed some problems with dispatch calls returning once started without getting the full result on large data sets. Seems like there are still a lot of things that need to be worked out with compute shaders.
     
  11. c6burnz

    c6burnz

    Joined:
    Jun 22, 2014
    Posts:
    5
    Just my 2 cents, since I found this thread. I have not experienced these issues in Windows and everything is stable for me all through 2018.x. Perhaps these issues are somehow related to Unity's lower level Metal API usage, or system hibernation? I mainly test OSX at runtime, and not very much at design time. But, I am manipulating fairly big data sets at edit time and at runtime using compute dispatches. Of course "big" is relative, but I have fed structured buffers that were over 1G through various compute kernels, and also displayed them in surface shaders during edit and play mode. All of this while rendering a full scene otherwise that pushes a 1080 TI to its limits. My desktop system never hibernates, but I do leave Unity open for weeks on end and I've never had an issue like this. I've had one-off glitches but seldom and nothing that follows a reproducible pattern.

    The only thing I do differently in my monobehaviour is that I use OnEnable and OnDisable for setup and cleanup, mainly because I like to be able to turn things off/on and to be able to force setup/cleanup. But I don't think that has any bearing, as I've seen others using Start / OnDestroy as well. The important thing is ensuring valid buffers are bound before dispatch (as opposed to just at initialization), which it does seem that you are doing. Otherwise you will get odd things happening when switching between edit/play and saving the scene (I assume that during serialization/deserialization buffers are unbound, and probably many other things happen at that time as well to try to ensure the validity of serialized data).
     
  12. BradZoob

    BradZoob

    Joined:
    Feb 12, 2014
    Posts:
    66
    Compute in Edit mode still seems pretty weird, either no Async callbacks generated or a 30-60 second delay. When it works it works, but inconsistent to say the least.