Search Unity

[RELEASED] GPU Instancer

Discussion in 'Assets and Asset Store' started by LouskRad, May 3, 2018.

  1. Monorio1

    Monorio1

    Joined:
    Dec 10, 2018
    Posts:
    17
    Hi and thanks for the quick reply. I'm using the deffered path already and the engine version is 2018.3.2f1. I can confirm that the problem is present in both rendering path. As said in a previous post Louskrad, someone had a similar black mesh problem and he mentionned that if vertex offset was used in the shader you needed to declare the UNITY_VERTEX_INPUT_INSTANCE_ID in the input structure. Could this be related? My other assets are working fine in the system. Only the grass which is made using a shader of Amplify is problematic. I inspected the file and no where is UNITY_VERTEX_INPUT_INSTANCE_ID declared. There's a mention of it however in Unity.cginc, but I'm not entirely if it's being used or declared. I wish I could send a sample but this is a project under NDA currently.
     
  2. Bamfax

    Bamfax

    Joined:
    Jun 12, 2016
    Posts:
    52
    The ComputeBuffer is overflowing by 1408 bytes. The SetData() tries to put too much data in to. If it's a TRS Array being uploaded, it is probably 22 too many instances in the Matrix4x4[] as the ComputeBuffer has space in it.
     
  3. Bamfax

    Bamfax

    Joined:
    Jun 12, 2016
    Posts:
    52
    Just stumbled over the same and would like to second @sebas77 here. Having to call GPUInstancerAPI.InitializeWithMatrix4x4Array() on all prototypes after every new prototype was added does not feel convenient.

    Would it be possible to get something like this?
    Code (CSharp):
    1. //*at start*
    2. GPUInstancerAPI.InitializeGPUInstancer(PrefabManager, true);
    3.  
    4. //...somewhen later...
    5. //*at adding a new prototype*
    6. GPUInstancerPrefabPrototype newPrototype = prefabManager.DefineGameObjectAsPrefabPrototypeAtRuntime(prefab);
    7. prefabManager.InitializeRuntimeDataAndBuffers_OnlyThisPrototype(newPrototype, true);
    That would allow to keep the prototype initialization code to the constructor of this specific prototype. Evading to call re-init on every prototype each time a new protype was added. As this probably also clears out all the transformationMatrixVisibilityBuffer on all prototypes.
     
    Last edited: Apr 5, 2019
  4. Bamfax

    Bamfax

    Joined:
    Jun 12, 2016
    Posts:
    52
    :)

    upload_2019-4-6_1-48-42.png
     
    GurhanH likes this.
  5. GurhanH

    GurhanH

    Joined:
    Apr 24, 2017
    Posts:
    539
    It might be related. In most cases, ASE uses appdata_full as the vertex input, which already contains UNITY_VERTEX_INPUT_INSTANCE_ID. But if you have a custom input which does not contain it, you can take a look at this wiki document for information on how to add it manually. Otherwise I can not tell much without seeing the shader code.
     
  6. GurhanH

    GurhanH

    Joined:
    Apr 24, 2017
    Posts:
    539
    Thank you for the feedback. As it was mentioned after @sebas77 's request, we started working on it:

    We are adding a new overload for the InitializeGPUInstancer API method where you can initialize a specific prefab prototype.
    We are also changing the InitializeWithMatrix4x4Array API method so that you do not have to call the InitializeGPUInstancer before calling this method. It will automatically initialize the runtime data and buffers for the given prototype, if it was not initialized before.

    It might take a while before we release the update. Please contact us by e-mail if you wish the get the changes beforehand.
     
  7. sebas77

    sebas77

    Joined:
    Nov 4, 2011
    Posts:
    1,644
    Thanks all for the feedback, I still didn't get the compute buffer overflow problem. I have minimal experience with compute shaders and I wasn't aware of compute buffer maximum size. Is then the 64k something that I can change? If so how? Also I wonder if there is a more compact way to upload the matrix information.
     
  8. Bamfax

    Bamfax

    Joined:
    Jun 12, 2016
    Posts:
    52
    Awesome, many thanks for that!
     
  9. Bamfax

    Bamfax

    Joined:
    Jun 12, 2016
    Posts:
    52
    ComputeBuffer length is set at its construction and stays that length until re-constructed (https://docs.unity3d.com/ScriptReference/ComputeBuffer-ctor.html).
    The TRS buffers in GPUI are set per prototype (please correct where I am mistaken) and include base size and extra buffer length that where set in editor on the prototype.
    wiki: "Please keep in mind that the Add/Remove Instances At Runtime option should be enabled in the prototype definition for this API methods to work. Also, Extra Buffer Size should have a high enough number to add all the prefab instances generated at runtime."
    The length of 64000 comes from the instance count which seems to have been set here to 10000 (base instance count + extra instance count).

    (Un-)Management of those GPU resource (shaders, computeshaders, buffers) is rigid stuff and GPUI does an awesome job of hiding that stuff away and still offering flexible interfaces to it.

    > Also I wonder if there is a more compact way to upload the matrix information.
    Second this again, regarding bridging from computeshader buffers into GPUI buffers. I guess I have to many buffers floating around (trs and variations), doing micromanagement of them on CPU side.
    Regarding atomic adds to the computeshader and shader buffers, I was thinking of toying around with SetDataPartial() offered by GPUIUtility, which seems to be an option here.
    Another aspect was how I could be more flexible with initializing buffers on computeshader side and GPUI side - they are all maximum length right now, as I do not know up ahead which prototype will get added how many instances. I was thinking about using Append/ConsumeBuffers to bridge from computeshader side to GPUI.
    Just in short right now, need to think about that in more detail.
     
  10. sebas77

    sebas77

    Joined:
    Nov 4, 2011
    Posts:
    1,644
    Cool thanks, I surely wasn't getting to 10k instances in my demo, so I must have some bugs in my code somewhere
     
  11. lod3

    lod3

    Joined:
    Mar 21, 2012
    Posts:
    679
    Been following this thread best I can, so sorry if I missed it, but is SpeedTree support only for terrains? If so, any plans to allow them to be used with the Prefab Manager? I don't use a terrain.
     
  12. viemr

    viemr

    Joined:
    Oct 24, 2016
    Posts:
    3
    Does GPUI have support for drawprocedural in combination with compute shader?
     
  13. sebas77

    sebas77

    Joined:
    Nov 4, 2011
    Posts:
    1,644
    I need the
    UpdateVisibilityBufferWithMatrix4x4Array to use SetDataPartial. ATM I am just overriding the standard one, but I wonder if this is the b est way to do it and if you are going to add the support for partial buffer upload
     
  14. PicturesInDark

    PicturesInDark

    Joined:
    Jun 13, 2013
    Posts:
    89
    Hi newly .... ummm If I disable shadows, quads, billboards in detail manager I have worst performance that without GPU instancer .... If I don't check "Import Grass" in GPU Instancer MapMagic Integration I also I have worst performance that without GPU instancer (better than before). And the difference between using GPU Instancer and not using it is worst in very High and Ultra Quality.

    I do not want you to misunderstand me, I'm not saying that the product is bad, I just want to understand what I have to do to gain performance on the scene.

    I always speaking of final compiled .... in editor with GPU Instancer I get the sames FPS but minor batches. However, the trees shadows dissapear with GPU Instancer, even if that are maked in Tree Manager
     
    Last edited: Apr 8, 2019
  15. GurhanH

    GurhanH

    Joined:
    Apr 24, 2017
    Posts:
    539
    You can use GPUI with SpeedTree prefabs without terrains, using the Prefab Manager. All three managers that come with GPUI support SpeedTrees. You can take a look at this wiki document for information on GPUI managers.

    Unfortunately procedural geometries can not be used with GPU Instancing. GPUI uses DrawMeshInstancedIndirect method and requires a predefined mesh.

    The best way would be to use the GetTransformDataBuffer API and use the ComputeBuffer.SetData method for partial upload. We did not add this method, because it is better to call it directly and the API already provides access to the buffer itself.

    MapMagic's demo tree shader does not have GPU Instancing setup, which causes the trees to render incorrectly, and also lowers the GPU performance. You need to add the UNITY_SETUP_INSTANCE_ID to the vert methods in each pass to include the setup:

    Code (CSharp):
    1. v2f vert(appdata_full v)
    2. {
    3.     v2f o;
    4.     UNITY_SETUP_INSTANCE_ID(v); // GPU Instancing setup
    5.     ...
    6. }
    You can take a look at this wiki document for further information on this.
     
  16. Monorio1

    Monorio1

    Joined:
    Dec 10, 2018
    Posts:
    17
    I simplified the shader to it's most basic form:
    upload_2019-4-8_15-48-47.png

    It's flagging me this warning message:
    upload_2019-4-8_15-49-22.png

    Here's the generated shader file from Amplify
    Thanks for the help
     

    Attached Files:

  17. lod3

    lod3

    Joined:
    Mar 21, 2012
    Posts:
    679
    I should've posted this image with my original post. It pops up when trying to add a SpeedTree prefab to the Prefab Manager:

    gpui.jpg

    Update: I nested the SpeedTree prefab into an empty gameobject which allowed Prefab Manager to register it. While there is an FPS boost, both wind and LODs have stopped, so not sure if that is the correct way to go about it.
     
    Last edited: Apr 9, 2019
  18. sebas77

    sebas77

    Joined:
    Nov 4, 2011
    Posts:
    1,644
    I noticed the GPUI code relies on the Physx module. What do you use physic for?
     
  19. LouskRad

    LouskRad

    Joined:
    Feb 18, 2014
    Posts:
    904
    Hi there, and thanks for the shader.

    Looks like the issue is that you are using Instanced Protperites in your shader (e.g. "Normal Intensity"). Your shader should work if you change these instanced properties to Property.

    If you need to use instance based variations, you can take a look at the wiki documentation on this, and check the included ColorVariationsDemo scene for an example.
     
  20. LouskRad

    LouskRad

    Joined:
    Feb 18, 2014
    Posts:
    904
    Hi there,

    GPUI Prefab Managers accept prefabs, and not model prefabs.

    You can take a look at this previous forum post for a detailed explanation on this:
    https://forum.unity.com/threads/released-gpu-instancer.529746/page-7#post-3773164

    In short, when you import a model to your project (in your case a SpeedTree model), it is imported to the project as a model prefab. You can see a small white rectangle on the icon of model prefabs. If you drag and drop this model prefab to your scene, and drag the created GameObject from the hierarchy window and drop it back to the project window, you create a prefab. The Prefab Manager accepts these prefabs.

    Here is a GIF that demonstrates how to do this with a SpeedTree model:
    https://gurbu.com/gpuinstancer/gif/conifer.gif

    Both wind and LODs should work as expected if you add the SpeedTree to the Prefab Manager as a prefab like this.
     
  21. LouskRad

    LouskRad

    Joined:
    Feb 18, 2014
    Posts:
    904
    Hi there,

    GPUI references the Rigidbody Unity class in various cases to handle rigidbodies on the prefabs. The PhysX module dependency is introduced by the Rigidbody class.
     
  22. Monorio1

    Monorio1

    Joined:
    Dec 10, 2018
    Posts:
    17
    Thank you for the answer, really appreciate the support. You deserve that 5 star rating. That did fix it.
     
    LouskRad likes this.
  23. lod3

    lod3

    Joined:
    Mar 21, 2012
    Posts:
    679
    That did it. Thank you. Had just assumed the .spm SpeedTree files were prefabs themselves.
     
    LouskRad likes this.
  24. sebas77

    sebas77

    Joined:
    Nov 4, 2011
    Posts:
    1,644
    What is the purpose of this? Handling automatically transforms? Do you handle hierarchy transformations too?
     
  25. sebas77

    sebas77

    Joined:
    Nov 4, 2011
    Posts:
    1,644
    a little favor to ask: can you make the folders asmdef friendly so that editor and client code are easy to separate?
     
  26. LouskRad

    LouskRad

    Joined:
    Feb 18, 2014
    Posts:
    904
    GPUI's purpose of referencing the Rigidbody class is mostly rudimentary. In most cases, it is used to strip the component and in some cases it is cached to turn the component back on when desired (e. g. the Modification Collider tool). GPUI only handles transforms that are defined as prototypes. That is, child transforms use fixed local position, scale and rotation unless they are also defined as prototypes.

    That makes sense, we will look into this. For now, taking the GPUInstancer/Scripts/Editor folder out of the Scripts folder (GPUInstancer/Editor/) should serve the same effect if you put the asmdef file inside the GPUInstancer/Scripts/ folder.
     
    sebas77 likes this.
  27. RendermediaUK

    RendermediaUK

    Joined:
    Jan 14, 2015
    Posts:
    2
    Hi. Since the new update, Culling Max Distance slider seems to be locked at 100 maximum units, this used to be a much larger number before the update. Is there a quick way for us to increase this number to a larger value? Not sure which value in which script would need to be changed.

    Thanks
     
  28. ivabibliocad

    ivabibliocad

    Joined:
    Jan 11, 2014
    Posts:
    80
    Hello, I have a situation where I think GPU instancer can help?
    I have a big island ( real construction project) where I need to show 10 000 trees and 100 buildings. These all have to work for Oculus Rift VR. At the moment all the buildings, and textures have been optimize to the extent I'm on 45 fps, but I soon as I place the speed trees it goes down to 15 fps. So the big question is if GPU instancer could help me increase that frame rate with those many trees and could I also do something about the buildings?
    Thanks for the suppport!
     
  29. LouskRad

    LouskRad

    Joined:
    Feb 18, 2014
    Posts:
    904
    Hi there,
    If you are using a Detail or a Tree Manager, there are two Max Distance settings: one that effects the manager globally, and one that is prototype based. When you increase the global setting for the manager, you also set the maximum that you can increase for the prototype based Max Distances.

    Also, if you wish to further increase the Max Distances that you can set for the managers, you can use the GPU Instancer Preferences window to do so.
     
  30. LouskRad

    LouskRad

    Joined:
    Feb 18, 2014
    Posts:
    904
    Hi there,

    If your trees and and buildings use meshes with VR compatible polygon counts, you would see an increase, but if you are using, for example, SpeedTree hero models for your trees, or buildings with very high vertex counts, you would be GPU bound while rendering geometry in VR and GPU instancing would not help as much.
     
  31. ivabibliocad

    ivabibliocad

    Joined:
    Jan 11, 2014
    Posts:
    80
    Howwww new concept for me here... Yes I use a hero model, just one... But then what are the settings you recomend for exporting that tree to unity correctly to then Use GPU instancer to optimize it even more??
    Thanks for the help!
     
  32. ahmed_decoy

    ahmed_decoy

    Joined:
    May 19, 2013
    Posts:
    58
    Hey @LouskRad

    Does GPU Instancer work on the Nintendo Switch? If not, any plans to support in future?
     
  33. LouskRad

    LouskRad

    Joined:
    Feb 18, 2014
    Posts:
    904
    In general, using a tree with a lower polygon count than a hero model would be advisable, especially so since you are targeting VR platforms. You could also edit the LOD Group switch percentages to favor higher level LODs over lower ones with high detail.

    As far as GPUI is concerned, there are no extra steps necessary for optimization specific to SpeedTrees. However, you can take a look at this wiki page to read about best practices when using GPUI.
     
  34. LouskRad

    LouskRad

    Joined:
    Feb 18, 2014
    Posts:
    904
    Hi there,

    We did not test GPUI with Nintendo Switch, but it is not listed in the listed supported platforms for Compute Shaders in the Unity documentation.

    Since GPUI relies heavily on Compute Shaders, it would not work on platforms where Compute Shaders are not supported.
     
  35. MaximilianPs

    MaximilianPs

    Joined:
    Nov 7, 2011
    Posts:
    322
    I see that it can work with MapMagic, can it support Terrain Former too? :)
    I ask 'cause my terrain is splitted in a grid of 7 by 7 terrains.
     
  36. LouskRad

    LouskRad

    Joined:
    Feb 18, 2014
    Posts:
    904
    Hi there,

    The MapMagic integration was developed as a special case because of MapMagic's infinite terrain generation at runtime.

    GPUI works with multiple finite terrains by simply adding a Detail/Tree Manager to each terrain. We have not tested GPUI with the Terrain Former Asset, but from its description it looks like it is used to edit Unity terrains in the editor. If this is the case, there is no reason why they shouldn't work together since GPUI does not introduce any restrictions on how you sculpt your terrains.
     
    MaximilianPs likes this.
  37. sebas77

    sebas77

    Joined:
    Nov 4, 2011
    Posts:
    1,644
    I am sorry to take so much of your time with my questions, know that I really appreciate it:

    I read that GPUInstancer is compatible with the projector. I would like to know more about it asking semi-related questions. Remember that I haven't been not a graphic programmer for a very long time, so I am quite outdated with modern approaches. I would like to know:

    - Is it possible to access to a Depth/Normal buffer with GPUInstancer? If yes how?
    - Is it possible to modify the pipeline some how, if so how?
    - would you suggest to use the built-in projector with GPUInstancer or create our own shader? (however we would need the depth/normal buffer for it)

    Edit: total unrelated question, but I prefer to not create another post:

    1) somehow I broke the rendering and I can't understand why (hence the questions above), the error I get is:
    Cannot find instanced shader for : Lightweight Render Pipeline/Lit. Using Standard shader instead.
    UnityEngine.Debug:LogWarning(Object)
    GPUInstancer.GPUInstancerShaderBindings:GetInstancedShader(String) (at Assets/Code/Libraries/GPUInstancer/Client/Scripts/Core/DataModel/GPUInstancerShaderBindings.cs:65)
    2) I have the same problem on a custom made shader with Shader Graph, and I am not sure how to integrate GPU instancer with ShaderGraph made shaders.
     
    Last edited: Apr 17, 2019
  38. Bamfax

    Bamfax

    Joined:
    Jun 12, 2016
    Posts:
    52
    Also another one from my side: I stumbled yet again over the symptom that, using an a little bit more heavy ComputeShader construct (now on the boids demo), shuffling several different prefabs into GPUI, the Game windows has all GPUI objects disappear when pausing the editor. The scene window still shows everything nicely. Everything reappears when unpausing. The boids demo as shipped does not exhibit this behavior.
    In the past I also had this happen on other projects with similar computeshaders when the unity window looses focus. A workaround which worked is swap buffers to CPU side upon focus change.
    I never really looked into this. Would someone have an idea where this may come from? I feels a little like DMII buffers are only kept alive if being actively filled by a computeshader. Maybe they are also swapped out in favor of the application having focus (but then I would think they should come back themselves, which they don't).
    Thanks for possible hints.
     
  39. Bamfax

    Bamfax

    Joined:
    Jun 12, 2016
    Posts:
    52
    > Is it possible to access to a Depth/Normal buffer with GPUInstancer? If yes how?
    They have that / similar on the youtube videos. "HI Z Occlusion Debugger". Starting at 4:44


    > "Generate Shader Variant Collection" enabled, what is it? As something to do with the precompiled shaders?
    Not really smart with it, but #pragma multicompile" may make unity to generate thousands of variants of a shader. E.g. generating all standard shader variants makes my desktop explode. So a collection seems to be a collection of "the variants you a actually using". GPUI also has to handle shader variants I would think due to gpui shader recompilation / includes for instancing.

    > Cannot find instanced shader for...
    Probably shaders are instanced to allow filling with individual properties. Maybe the base shader (which is being instanced) did not compile e.g. due to not finding includes? Often had shader errors not being thrown on the console, just showing on the inspector when the shader is selected. Somewhere towards / around 2018.1/.2/.3 shaders have become increasingly verbose.
     
    Last edited: Apr 17, 2019
  40. sebas77

    sebas77

    Joined:
    Nov 4, 2011
    Posts:
    1,644
    thanks @Bamfax The sudden appearing problem with the LWRP lit shader not found is persisting and I cannot figure out why. Nothing work between reimporting/reinstall gpu instancer. Now I am debugging to understand what's going on.

    About the shader variant collection, I was more wondering if I have to do something with it or just let it be. I.E.: do I have to add it in the list of precompiled shader to load at start? Do I have to do something with the following window?

    upload_2019-4-17_11-38-7.png

    Edit: I'll check the video, but I am not sure if it will answer my question about decals/projectors. Also I am still not sure what to do with custom generated shader graph shaders
     
  41. Bamfax

    Bamfax

    Joined:
    Jun 12, 2016
    Posts:
    52
    Uh, you are on SRP LWRP? Have not made it there yet, so cannot be of much help.
    If there's a
    ComputeShader convertCS = Instantiate(Resources.Load("ConvertShader")) as ComputeShader;

    somewhere, then my assumption could fit. If not, then I'm out of guesses.
     
  42. sebas77

    sebas77

    Joined:
    Nov 4, 2011
    Posts:
    1,644
    OK finally my problem with the not found shader has been fixed just drag and dropping directly the prefab in the prefab manager. I didn't realise I am forced to do so as I am using a pipeline that doesn't involve the use of GPUI Prefab Manager.

    I still need to know what to you suggest me to do with decal/projectors and how to handle custom shadergraph shader.
     
    Last edited: Apr 17, 2019
  43. jjobby

    jjobby

    Joined:
    Nov 28, 2009
    Posts:
    161
  44. Ryan-Hayle

    Ryan-Hayle

    Joined:
    Feb 16, 2014
    Posts:
    142
    Tools -> GPU Instancer -> Integration -> Add MapMagic Integration

    I see it, but it is disabled?
    Unity 2019.1, GPU Instancer 1.1 and Map Magic 1.10.1
     
  45. GurhanH

    GurhanH

    Joined:
    Apr 24, 2017
    Posts:
    539
    Hi @sebas77
    - You can access the Camara's Depth Texture the same way you do without GPU Instancer. However, when using Forward rendering mode, you might need to set the custom depth-normals shader which was introduced in the v1.1.0 update, so that the instances are setup correctly during depth rendering.
    - You can also use the same technique (changing depth-normals shader), if you wish to modify the depth texture.
    - Built-in unity projector does not always play well with indirect GPU instancing. That's why we recommend to ignore the layers for GPUI prototypes. But if you need to include the GPUI prototypes, adding a custom shader which includes the GPUI setup should solve the problem.

    1) When you move the GPUI folders or add/update LWRP/HDRP packages, there is a chance that the shader references might get broken during import.
    Easiest way to solve this is to clear the shader bindings from Tools -> GPU Instancer -> Clear Shader Bindings. And when you open a GPUI manager with prototypes that use these shaders, they will be auto converted again.
    But this won't help if you do not have a manager in your scene. We will look into making shader conversion accessible in the editor without using managers (probably through a menu item).
    2) ShaderGraphs currently can not be auto-converted to support GPUI. However, we are preparing nodes which can be added to the ShaderGraph that will inject the code required for GPUI setup. It will be available soon.
     
  46. GurhanH

    GurhanH

    Joined:
    Apr 24, 2017
    Posts:
    539
    Hi @Bamfax
    This is actually the intended behaviour :) When the game is paused GPUI makes the rendering calls only to the Scene View camera. So when the Game View is updated, it does not show the GPUI prototypes. This is also true for the Boids demo, they will disapear as soon as the Game view is updated when the editor is paused.
    The first reason for this is that GPUI makes its calculations for a single camera, and when the game is paused, we switch this camera with the Scene View because this is the most common usage. The second reason is that rendering to both cameras slows down the editor during pause mode.
    If you want to render the same way to the Game View during pause mode, you can do so by changing the following line of code:
    GPUInstancerEditorSimulator.cs Line 125
    from this:
    Code (CSharp):
    1. gpuiManager.UpdateBuffers(sceneViewCameraData);
    to this:
    Code (CSharp):
    1. gpuiManager.UpdateBuffers(gpuiManager.cameraData);
    We will look into this and perhaps add it as an option.
     
    Bamfax likes this.
  47. GurhanH

    GurhanH

    Joined:
    Apr 24, 2017
    Posts:
    539
  48. GurhanH

    GurhanH

    Joined:
    Apr 24, 2017
    Posts:
    539
    Hi @Ryan-Hayle
    Do you have the MapMagic component in the scene? GPUI searches for the MapMagic component and if it can not find it, this option is disabled.
     
  49. Bamfax

    Bamfax

    Joined:
    Jun 12, 2016
    Posts:
    52
    Awesome, thank you for the clarification and details. I was confused by the similarity of the described bug which happened to me in the past, and learning now that this is unrelated and intended is indeed very nice as is. Thank you.
     
    LouskRad likes this.
  50. sebas77

    sebas77

    Joined:
    Nov 4, 2011
    Posts:
    1,644
    OK so the plan is to use the custom depth-normal shader and read from the camera's depth texture in a custom shader that we are going to create to project decals.

    1) I did use the Clear Shader Bindings and it didn't help. Currently my scene has always a GPUIManager even if doesn't have any prefab registered. Currently drag and drop is the only solution I found

    2) Thanks for this!