Search Unity

Resolved HoloLens 2 + DrawMeshInstancedIndirect + Single Pass Instanced Rendering

Discussion in 'Shaders' started by lady_magnetic, Mar 3, 2021.

  1. lady_magnetic

    lady_magnetic

    Joined:
    Apr 15, 2020
    Posts:
    3
    Hello,
    I have project where I need to render a large collection of objects on the hololens 2. For this purpose I experimented with Graphics.DrawMeshInstanced and Graphics.DrawMeshInstancedIndirect. Due to performance I chose the latter.

    My project is configured with the "old" XR-Settings (Settings -> Player -> XR-Settings, Windows Mixed Reality).
    When setting the stereo rendering mode to "Single Pass", everything looks fine, but when I switch to "Single Pass Instanced" the data rendered via DrawMeshInstancedIndirect does not align. Otherwise everything else looks correct. It only affects the meshes rendered by DrawMeshInstancedIndirect.

    I assume it has something to do with an incorrect setup for the right and left eye in my shader, but I have no clue what I need to do to fix this issue. I am using Unity 2019.4.8 + URP + MRTK Toolkit.

    Custom shade code (partially):
    Code (CSharp):
    1.  
    2. [...]
    3. struct appdata
    4. {
    5.    float4 vertex : POSITION;
    6.    float4 normal : NORMAL;
    7.  
    8.    UNITY_VERTEX_INPUT_INSTANCE_ID
    9. };
    10.  
    11. struct v2f
    12. {
    13.    float4 vertex : SV_POSITION;
    14.    fixed4 color : COLOR0;
    15.  
    16.    UNITY_VERTEX_OUTPUT_STEREO
    17. };
    18.  
    19. struct MeshProperties
    20. {
    21.    float4x4 mat;
    22.    float4 color;
    23. };
    24.  
    25. StructuredBuffer<MeshProperties> _Properties;
    26.  
    27. v2f vert(appdata v, uint instanceID: SV_InstanceID)
    28. {
    29.    v2f o;
    30.  
    31.    UNITY_SETUP_INSTANCE_ID(v);
    32.    UNITY_INITIALIZE_OUTPUT(v2f, o);
    33.    UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
    34.  
    35.    // position
    36.    float4 position =  mul(_Properties[instanceID].mat, v.vertex);
    37.    o.vertex  = mul(UNITY_MATRIX_VP, position);
    38. // I used UnityObjectToClipPos(position); before, but that gave the same result
    39.  
    40.    // color
    41. [...] // code for the color, basicly I adjust the color from the properties array to add a simple lighting effect
    42.  
    43.    return o;
    44. }
    45.  
    46. fixed4 frag(v2f i) : SV_Target
    47. {
    48.    return i.color;
    49. }
    50.  
    The MeshProperties Struct correspondeds to the one I use in C# Code and contains the TRS Data of the mesh.
    Code (CSharp):
    1.  
    2. internal struct MeshProperties
    3.         {
    4.             public Matrix4x4 trsData;
    5.             public Vector4 color;
    6.  
    7.             public static int Size()
    8.             {
    9.                 return
    10.                     sizeof(float) * 4 * 4 + // matrix;
    11.                     sizeof(float) * 4;      // color;
    12.             }
    13.         }
    14.  
    https://docs.unity3d.com/Manual/SinglePassStereoRenderingHoloLens.html states that "... you will have to manually double the instance count contained in your compute buffers." if using Graphics.DrawProceduralIndirect().
    I do not really know how this function is used or what it does, but maybe it also applies to DrawMeshInstancedIndirect, as this approach uses compute buffers, too?
     
  2. ferrous

    ferrous

    Joined:
    Dec 31, 2012
    Posts:
    17
    Hey, I ran into this same issue, and that blurb from the documentation is sparse and confused me too. What I found out is that they are expecting interleaved values, so I had to double the size of my computebuffer and then double the entries one by one so they are in memory like:
    start with 5 instances like so
    1,2,3,4,5
    change to:
    1,1, 2,2,3,3,4,4,5,5

    EDIT: In fact when I ran into this problem this post was the first thing I came across in my searches, so wanted to share the answer.
     
  3. lady_magnetic

    lady_magnetic

    Joined:
    Apr 15, 2020
    Posts:
    3
    Thank you very much for your help!
     
  4. jessespectar

    jessespectar

    Joined:
    May 7, 2020
    Posts:
    1
  5. FreshlyBrewed

    FreshlyBrewed

    Joined:
    Nov 12, 2019
    Posts:
    4
    I just came across this problem today and would like to provide a code example for future reference:

    as mentioned in the docs and explained by @ferrous, an easy solution is to duplicate your data in the buffer. In my code I introduced a boolean to declare if the data should be duplicated to support stereo rendering:
    Code (CSharp):
    1. // Here, you may want to check if stereo rendering is enabled
    2. protected bool UseStereoBuffer => true;
    3.  
    4. // Use x2 factor for stereo rendering
    5. protected int StereoBufferSizeFactor => (UseStereoBuffer ? 2 : 1);
    When it comes to building the buffer I duplicate the data accordingly:
    Code (CSharp):
    1. // Double your buffer size if stereo rendering is enabled
    2. var size = bufferSize * StereoBufferSizeFactor;
    3. meshPropertiesBuffer = new ComputeBuffer(size, MeshProperties.Size());
    4. MeshProperties[] meshProperties = new MeshProperties[size];
    5.  
    6. // Set up the args buffer
    7. uint[] args = new uint[5] {0, 0, 0, 0, 0};
    8. args[0] = (uint) mesh.GetIndexCount(0);
    9. args[1] = (uint) size;
    10. args[2] = (uint) mesh.GetIndexStart(0);
    11. args[3] = (uint) mesh.GetBaseVertex(0);
    12. argsBuffer = new ComputeBuffer(1, args.Length * sizeof(uint), ComputeBufferType.IndirectArguments);
    13. argsBuffer.SetData(args);
    14.  
    15. // Set up the mesh data buffer
    16. for(int i = 0; i < size; i += StereoBufferSizeFactor)
    17. {
    18.     meshProperties[i] = GetMyBufferData(i);
    19.     // Duplicate data for stereo rendering
    20.     if (UseStereoBuffer) meshProperties[i + 1] = meshProperties[i];
    21. }
    There may be better ways to solve this that do not rely on actually duplicating the data in memory but it works and is relatively easy to implement.
     
    jessespectar, sewy and hschulte like this.