Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

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:
    77
    how fixed it?