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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice
  4. Dismiss Notice

Bug Is ComputeShader.SetConstantBuffer working?

Discussion in 'Shaders' started by cecarlsen, Mar 25, 2022.

  1. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    848
    I can't seem to find working examples of how to use ComputeShader.SetConstantBuffer. An attempt was made in this thread, but I'm afraid no one saw it because it was posted in a different forum.

    Well, I can't get it to work either. Testing in Unity 2020.3.

    Am I doing it wrong?

    In the example below I get "Result is: 0. Should be: 3".

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Runtime.InteropServices;
    3.  
    4. public class ConstantBufferTest : MonoBehaviour
    5. {
    6.     [SerializeField] ComputeShader _cs;
    7.  
    8.     struct OnceConstants
    9.     {
    10.         public int value1;
    11.         public int value2;
    12.     }
    13.  
    14.     void Start()
    15.     {
    16.         int executeKernel = _cs.FindKernel( "Execute" );
    17.  
    18.         // Create and set buffers.
    19.         int onceSize = Marshal.SizeOf( typeof( OnceConstants ) );
    20.         var onceBuffer = new ComputeBuffer( 1, onceSize, ComputeBufferType.Constant );
    21.         var resultBuffer = new ComputeBuffer( 1, sizeof( int ) );
    22.         _cs.SetBuffer( executeKernel, "_ResultBuffer", resultBuffer );
    23.         _cs.SetConstantBuffer( "Once", onceBuffer, offset: 0, onceSize );
    24.  
    25.         // Upload constants.
    26.         onceBuffer.SetData(
    27.             new OnceConstants[]{
    28.                 new OnceConstants() {
    29.                     value1 = 1,
    30.                     value2 = 2,
    31.                 }
    32.             }
    33.         );
    34.  
    35.         // Execute shader.
    36.         _cs.Dispatch( executeKernel, 1, 1, 1 );
    37.  
    38.         // Read back and log.
    39.         int[] resultData = new int[ 1 ];
    40.         resultBuffer.GetData( resultData );
    41.         Debug.Log( "Result is: " + resultData[0] + ". Should be: " + ( 1 + 2 ) );
    42.  
    43.         // Clean up after the party.
    44.         onceBuffer.Release();
    45.         resultBuffer.Release();
    46.     }
    47. }
    And the ComputeShader:

    Code (CSharp):
    1. #include "UnityCG.cginc"
    2.  
    3. #pragma kernel Execute
    4.  
    5. RWStructuredBuffer<int> _ResultBuffer;
    6.  
    7. CBUFFER_START( Once )
    8.     int value1;
    9.     int value2;
    10. CBUFFER_END
    11.  
    12. [numthreads(1,1,1)]
    13. void Execute()
    14. {
    15.     _ResultBuffer[ 0 ] = value1 + value2;
    16.     //_ResultBuffer[ 0 ] = 1 + 2; // This works
    17. }
     
    Last edited: Mar 26, 2022
  2. grizzly

    grizzly

    Joined:
    Dec 5, 2012
    Posts:
    356
    Your code looks fine and can confirm that it works as expected in 2021.1, so it must be a bug.
     
    cecarlsen likes this.
  3. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    848
    Thank you so much for testing it. I just tested in 2021.2 and that does not work for me. Downloading 2021.1 now to test that as well.

    Could you by any chance post the working compiled shader?
     
  4. grizzly

    grizzly

    Joined:
    Dec 5, 2012
    Posts:
    356
    Code (CSharp):
    1. **** Platform Direct3D 11:
    2. Compiled code for kernel Execute
    3. keywords: <none>
    4. binary blob size 228:
    5. //
    6. // Generated by Microsoft (R) D3D Shader Disassembler
    7. //
    8. //
    9. // Input signature:
    10. //
    11. // Name                 Index   Mask Register SysValue  Format   Used
    12. // -------------------- ----- ------ -------- -------- ------- ------
    13. // no Input
    14. //
    15. // Output signature:
    16. //
    17. // Name                 Index   Mask Register SysValue  Format   Used
    18. // -------------------- ----- ------ -------- -------- ------- ------
    19. // no Output
    20.       cs_5_0
    21.       dcl_globalFlags refactoringAllowed
    22.       dcl_constantbuffer CB0[1], immediateIndexed
    23.       dcl_uav_structured u0, 4
    24.       dcl_temps 1
    25.       dcl_thread_group 1, 1, 1
    26.    0: iadd r0.x, cb0[0].y, cb0[0].x
    27.    1: store_structured u0.x, l(0), l(0), r0.x
    28.    2: ret
    29. // Approximately 0 instruction slots used
     
  5. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    848
    This is a true mystery.

    Thank you for the compiled shader @grizzly. It is identical with the one I get in 2021.1.28f1. But it does not work.

    I have updated my graphics driver (RTX2080). Updated Windows. Restarted. Reinstalled Unity. Clean project. No packages, no nothing. I am really out of ideas at this point.

    EDIT:
    I also tried using Visual Studio Code instead of Visual Studio Editor.
     
    Last edited: Mar 26, 2022
  6. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    848
    @grizzly I have now tested on two Windows 10 machines with Unity 2021.1.16f1 and 2021.1.28f1. None of them work.

    What version of 2021.1 exactly worked for you?
     
    Last edited: Mar 26, 2022
  7. grizzly

    grizzly

    Joined:
    Dec 5, 2012
    Posts:
    356
    That is strange. Tested here on an old Win 7 Dx11 1060 machine using Unity 2021.1.3f1. Previous versions have also worked for me, so I would suggest filing a bug :)
     

    Attached Files:

  8. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    848
    Thanks @grizzly, much appreciated.

    It does not work in 2021.1.3f1 for me. I really have no clue what could be the cause at this point.
     
  9. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    848
    Testing the script above in the newly published Unity 2021.2.17f1 on Windows, Editor runtime.

    - Target platform: "Windows, Mac, Linux".
    Graphics API for "Windows, Mac, Linux": DX11.
    Not working.

    - Target platform: "Windows, Mac, Linux".
    Graphics API for "Windows, Mac, Linux": Vulcan.
    Not working.

    - Target platform:"Android".
    Graphics API for "Windows, Mac, Linux": DX11 (the Editor).
    Graphics API for "Android": OpenGLES3.
    Not working.

    - Target platform:"Android".
    Graphics API for "Windows, Mac, Linux": DX11 (the Editor).
    Graphics API for "Android": Vulcan.
    Not working and sometimes crashing.

    - Target platform:"Android".
    Graphics API for "Windows, Mac, Linux": Vulcan (the Editor). Note: Oculus XR requires DX11.
    Graphics API for "Android": Vulcan.
    Not working.
     
    Last edited: Mar 29, 2022
  10. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    848
    I made a bug report.
    CASE 1416880
     
    aleksandrk and grizzly like this.
  11. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    848
    The issue persists in 2022.2.0a11
     
  12. Neran28

    Neran28

    Joined:
    Mar 14, 2016
    Posts:
    15
    Same here, does not work with Unity 2021.2.10. Constant Buffer values are just 0.
    Cbuffers work in a standalone application outside of Unity though.

    Is there an alternative solution to set a block of data in a compute shader? In openGL for example you can use structs as uniforms and upload the struct data. Is this also possible with compute shaders in d3d11 or only possible with cbuffers?
     
  13. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    1,670
    Yep, same here. Constant buffers in compute shaders do not seem to work. Tried declaring them with cbuffer as well as the CBUFFER_START/CBUFFER_END macros, but their data is always zero. (Unity 2021.3.0f1, macOS)
     
    Last edited: Jul 19, 2022
  14. sebas77

    sebas77

    Joined:
    Nov 4, 2011
    Posts:
    1,600
    Hey I think I am having the same with 2021.3.9. What's going on?
     
  15. sebas77

    sebas77

    Joined:
    Nov 4, 2011
    Posts:
    1,600
    you say it works with 2021.1 but not with 2021.2

    between the two releases

    Graphics.RenderMeshInstanced

    has been introduced

    My bet is on this new code, I have to check if it works using it.
     
  16. Przemyslaw_Zaworski

    Przemyslaw_Zaworski

    Joined:
    Jun 9, 2017
    Posts:
    314
    Minimal working example.

    Tested with Unity 2022.2.0b2, and RTX 2070 (drivers 516.94) with Windows 10 64-bit

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Runtime.InteropServices;
    3.  
    4. public class ConstantBuffer : MonoBehaviour
    5. {
    6.     [SerializeField] ComputeShader _ComputeShader;
    7.  
    8.     struct Element
    9.     {
    10.         public int Index;
    11.         public int Radius;
    12.     }
    13.  
    14.     void Start()
    15.     {
    16.         if (_ComputeShader == null) return;
    17.         ComputeBuffer constantBuffer = new ComputeBuffer(1, Marshal.SizeOf(typeof(Element)), ComputeBufferType.Constant);
    18.         ComputeBuffer structuredBuffer = new ComputeBuffer(1, Marshal.SizeOf(typeof(System.Int32)), ComputeBufferType.Structured);
    19.         _ComputeShader.SetConstantBuffer("_ConstantBuffer", constantBuffer, 0, Marshal.SizeOf(typeof(Element)));
    20.         _ComputeShader.SetBuffer(0, "_StructuredBuffer", structuredBuffer);
    21.         constantBuffer.SetData(new Element[]{new Element() {Index = 1, Radius = 2}});
    22.         _ComputeShader.Dispatch(0, 1, 1, 1 );
    23.         int[] result = new int[1];
    24.         structuredBuffer.GetData( result );
    25.         Debug.Log( "Result is: " + result[0] + ". Should be: " + ( 1 + 2 ));
    26.         constantBuffer.Release();
    27.         structuredBuffer.Release();
    28.     }
    29. }
    Code (CSharp):
    1. #pragma kernel CSMain
    2.  
    3. RWStructuredBuffer<int> _StructuredBuffer;
    4.  
    5. cbuffer _ConstantBuffer
    6. {
    7.     int Index;
    8.     int Radius;
    9. };
    10.  
    11. [numthreads(1,1,1)]
    12. void CSMain (uint3 id : SV_DispatchThreadID)
    13. {
    14.     _StructuredBuffer[0] = Index + Radius;
    15. }
    upload_2022-10-10_20-25-33.png
     
    cecarlsen likes this.
  17. Ascended_Fern

    Ascended_Fern

    Joined:
    Jan 26, 2018
    Posts:
    2
    Maybe it got fixed in 2022, as this exact code does not work on 2021.3.
     
    arkano22 likes this.
  18. Ascended_Fern

    Ascended_Fern

    Joined:
    Jan 26, 2018
    Posts:
    2
    Update: I got this case to work in 2021LTS by calling SetConstantBuffer("ConstantBuffer",constantBuffer,0,sizeof(int)*4).
    My compute buffer itself is declared with the same count and stride.
    I think you need to bind a multiple of 16bytes and require padding for 2 ints, likely because of this : https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-packing-rules

    Hope this helps people trying to make this works.

    For the people at Unity: Rather than the fix workaround apparently in 2022.2.0a14, wouldn't it be better to check that the size parameter is a multiple of 16 and give a warning or error if it isn't and/or pad the data automatically (might not be desirable I'm sure you need have a lot of additional constraints on your side)
     
    Averyu and sebas77 like this.