Search Unity

  1. Unity Asset Manager is now available in public beta. Try it out now and join the conversation here in the forums.
    Dismiss Notice

Passing Array To Shader

Discussion in '5.4 Beta' started by Stuffe, Mar 19, 2016.

  1. Stuffe

    Stuffe

    Joined:
    Aug 29, 2014
    Posts:
    9
    I downloaded the Beta specifically because I need this:
    "Shader uniform array support. Uniform arrays can be set by new array APIs on MaterialPropertyBlock. Maximum array size is 1023. The old way of setting array elements by using number-suffixed names is deprecated."

    I assume the api would be material.SetArray("name", array), but that doesn't work. Is the functionality there and does anyone know how to use it?

    Also the above note was from 5.4.0b1, but I am 5.4.10b, which I assume should also have that functionality?
     
  2. Stuffe

    Stuffe

    Joined:
    Aug 29, 2014
    Posts:
    9
    I finally figured it out, the feature is there it was just me being confused. For future reference, you can't SetFloatArray on a material directly, you have to do it on a MaterialPropertyBlock and then pass that to the renderer of the object. This was a bit confusing since you can do for example SetFloat directly on the material. Anyways, the following should work:

    var materialProperty = new MaterialPropertyBlock();
    float[] floatArray= new float[] {0f, 1f};

    materialProperty.SetFloatArray("arrayName", floatArray);
    gameObject.GetComponent<Renderer> ().SetPropertyBlock (materialProperty);

    then in the shader you simply use:
    uniform float arrayName[2];
     
  3. Prodigga

    Prodigga

    Joined:
    Apr 13, 2011
    Posts:
    1,123
    So we can't set, say, set a global array of floats? Shader. SetGlobalArray***** (float, vector, etc)

    Also, since the material property block applies to the renderer and not the material, we can't have all renderers that are being renderer with a certain material share the array, right? We'd have to set the array for each renderer, which I assume would.be costly and it would break any dynamic batching. That's not very useful :(
     
  4. Stuffe

    Stuffe

    Joined:
    Aug 29, 2014
    Posts:
    9
    I can't say for sure, but I don't think that is possible :/ Also yes I think you would have to pass the material proberty to each renderer and that does sound like it should break dynamic batching :/
    You probably have to use a hack like pass the data with setTexture (large overhead) or maybe setBuffer (requires DirectX 11 i think) on the material if the above limitations doesn't work with you want to do.

    Hopefully they will add this method to the material directly soon also!
     
  5. Prodigga

    Prodigga

    Joined:
    Apr 13, 2011
    Posts:
    1,123
    I am using a global texture (RGBAFloat format) to pass 256 values to my shader. It works, but it would be more efficient to by pass texture sampling and all that other junk in my shader if I could just have an array of vector's accessible to me directly.
     
  6. tomaszek

    tomaszek

    Joined:
    Jun 18, 2009
    Posts:
    3,862
  7. Prodigga

    Prodigga

    Joined:
    Apr 13, 2011
    Posts:
    1,123
    Ah, nice find!

    If it works like the other global methods, it seems perfect.
     
  8. MV10

    MV10

    Joined:
    Nov 6, 2015
    Posts:
    1,889
  9. JibbSmart

    JibbSmart

    Joined:
    Feb 18, 2013
    Posts:
    26
    The maximum array size seems a little arbitrary. Does anyone know if we can have multiple arrays of size 1023 in one shader? Can we query the hardware to discern what limitations there are for the amount of data we pass in to our shader in Unity? I can't find the info I'm looking for online -- nor can I test it conclusively without testing on all GPUs I want to support.
     
  10. zeroyao

    zeroyao

    Unity Technologies

    Joined:
    Mar 28, 2013
    Posts:
    169
    Hi,

    With the latest beta there are also SetFloatArray/SetVectorArray/SetMatrixArray on Material class. I haven't checked the implementation but I think array values are not serialized with the Material object.

    Yes you can have multiple arrays of size 1023 in one shader. This limitation is rather from our internal implementation than the hardware. If you put an array in a constant buffer, you are also limited by the maximum size of a constant buffer, which is 64KB for D3D11 and 16KB for OpenGL.
     
    chadiik, gracezhu, sanmn19 and 2 others like this.
  11. JibbSmart

    JibbSmart

    Joined:
    Feb 18, 2013
    Posts:
    26
    Oh, excellent! That's really handy. Thank you for the prompt reply and helpful info :)