Search Unity

AppendStructuredBuffer read in Vertex Shader produces wrong result

Discussion in 'Shaders' started by genetic_priest, Mar 11, 2021.

  1. genetic_priest

    genetic_priest

    Joined:
    Jan 17, 2021
    Posts:
    5
    Hello everyone!
    Faced issue on attempt to use AppendStructuredBuffer with indirect instanced rendering. On high level code looks following way:
    Code (CSharp):
    1. //create buffer
    2. VisibleParticleIndexes = new ComputeBuffer(maxParticles, sizeof(uint), ComputeBufferType.Append);
    3. VisibleParticleIndexes .SetCounterValue(0);
    4. ...
    5. //Determining indexes
    6. VisibleParticleIndexes.SetCounterValue(0);
    7. commandBuffer.Clear();
    8. commandBuffer.SetComputeBufferParam(ObjectShader, Visibility_ID, "VisibleObjectIndexes", VisibleObjectIndexes);
    9. commandBuffer.SetComputeBufferParam(ObjectShader, Visibility_ID, "ObjectIndexes", ObjectIndexes);
    10. commandBuffer.DispatchCompute(ObjectShader, Visibility_ID, numGroups, 1, 1);
    11. Graphics.ExecuteCommandBuffer(commandBuffer);
    12. ...
    13. //Rendering
    14. public void Draw(Camera cam, Mesh mesh, Material material, int layer, ref ComputeBuffer visibleObjectIndexes)
    15. {
    16.     uint[] args = new uint[5] { 0, 0, 0, 0, 0 };
    17.     args[0] = mesh.GetIndexCount(0);
    18.     indirectArgumentsBuffer.SetData(args);
    19.     //setting actual size of visible particles
    20.     ComputeBuffer.CopyCount(visibleParticleIndexes, indirectArgumentsBuffer, sizeof(int));
    21.     material.SetBuffer("VisibleObjectIndexes", visibleObjectIndexes);
    22.     material.SetBuffer("Objects", Objects);
    23.     Graphics.DrawMeshInstancedIndirect(mesh, 0, material, bounds, indirectArgumentsBuffer, 0, null, castShadow,  recieveShadow, layer, cam);
    24. }
    25.  
    Then how it is used in shaders:
    Code (CSharp):
    1.  
    2. //Visibility_ID shader
    3. StructuredBuffer<float4> ObjectIndexes;
    4.  
    5. AppendStructuredBuffer<int> VisibleObjectIndexes;
    6. [numthreads(BLOCK_DIM, 1, 1)]
    7. void Visibility(int3 DTid : SV_DispatchThreadID)
    8. {
    9.     //some calculations
    10.     VisibleObjectIndexes.Append(visibleObjectID);
    11. }
    12. ...
    13. //instanced rendering shader
    14. Shader "Objects"
    15. {
    16.     SubShader
    17.     {
    18.         Pass
    19.         {
    20.             CGPROGRAM
    21.             #pragma enable_d3d11_debug_symbols
    22.             #pragma vertex VSMain
    23.             #pragma fragment FMain
    24.             #pragma multi_compile_instancing
    25.             #pragma instancing_options procedural:setup
    26.              
    27.             #include "UnityCG.cginc"
    28.  
    29.             struct PSOut
    30.             {
    31.                 half4 color : COLOR;
    32.                 float depth : DEPTH;
    33.             };
    34.  
    35.             struct VIn
    36.             {
    37.                 float4 position : POSITION;
    38.                 UNITY_VERTEX_INPUT_INSTANCE_ID
    39.             };
    40.  
    41.             struct VOut
    42.             {
    43.                 float4 position : SV_POSITION;
    44.                 float2 minmax : TEXCOORD0;
    45.                 int gridID : Output;
    46.             };
    47.             //without this function procedural generation does not work, no proper permutation generated
    48.             void setup()  
    49.             {
    50.             }
    51.  
    52.             StructuredBuffer<int> VisibleObjectIndexes;
    53.             StructuredBuffer<Object> Objects;
    54.  
    55.             VOut VSMain(VIn input)
    56.             {
    57.                 VOut output;
    58. #ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED
    59.                 UNITY_SETUP_INSTANCE_ID(input);
    60.                 output.objectID = VisibleObjectIndexes[unity_InstanceID];
    61.                 Object object= Object[output.gridID];
    62.                 float3 pos = object.pos;
    63.                 float3 extent = object.size;
    64.  
    65.                 //manually extending mesh with per object parameters
    66.                 unity_ObjectToWorld._11_21_31_41 = float4(extent.x, 0, 0, 0);
    67.                 unity_ObjectToWorld._12_22_32_42 = float4(0, extent.y, 0, 0);
    68.                 unity_ObjectToWorld._13_23_33_43 = float4(0, 0, extent.z, 0);
    69.                 unity_ObjectToWorld._14_24_34_44 = float4(pos, 1);
    70.                 unity_WorldToObject = unity_ObjectToWorld;
    71.                 unity_WorldToObject._14_24_34 *= -1;
    72.                 unity_WorldToObject._11_22_33 = 1.0f / unity_WorldToObject._11_22_33;
    73. #endif
    74.                 return output;
    75.             }
    76.  
    77.             PSOut FMain(VOut input)
    78.             {
    79.                 PSOut fo;
    80. #ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED
    81.                 UNITY_SETUP_INSTANCE_ID(input);
    82.                 fo.color = Objects[unity_InstanceID];
    83. #endif
    84.                 return fo;
    85.             }
    86.             ENDCG
    87.         }
    88.     }
    89. }
    90.  
    Maybe I missed smth in code but general idea is:
    1. Determine visible objects IDs
    2. Set visible count in indirect buffer
    3. Draw some mesh and modify it according on per object info.

    The problem I faced here is that incorrect result when I read AppendBuffer VisibleObjectIndexes. I use RenderDoc for captures and it produces different result for
    output.objectID = VisibleObjectIndexes[unity_InstanceID]; 
    which is different from what it shows in resource view.
    Also rendering is totally incorrect.
    I did not find any examples showing how to read AppendBuffer correctly - almost all examples related to reading back to CPU which is not my case.
    Do I miss something like clearing AppendBuffer - but if I reset its count then why should I do it?
    Any examples, especially with indirect instanced rendering?
     
  2. flyer19

    flyer19

    Joined:
    Aug 26, 2016
    Posts:
    126
    how fixed it?