GPU Instancer:FAQ

From GurBu Wiki
Jump to: navigation, search

About | Features | Getting Started | Terminology | Best Practices | F.A.Q.

General Questions


What are the Minimum Requirements?


To provide the fastest possible performance, GPU Instancer utilizes indirect GPU instancing using Unity's DrawMeshInstancedIndirect API and Compute Shaders. Following are the minimum requirements for GPU instancing and Compute Shader support:


  • DirectX 11 or DirectX 12 and Shader Model 5.0 GPU (Windows, Windows Store)
  • Metal (macOS, iOS)
  • OpenGL Core 4.3 (Windows, Linux)
  • Vulkan (Android, Windows, Linux)
  • OpenGL ES 3.1 (Android 8.0 Oreo or later)
  • Modern Consoles (PS4, Xbox One)


Please also note that even though some integrated graphics cards may satisfy these requirements, they will not provide the boost you can get from GPU Instancing. Therefore, hardware with a dedicated GPU is recommended.


How does GPU Instancer work?



The aim of GPUI is to provide an easy to use interface to use indirect instancing without having to go through the learning curves of (or extensive development times of) GPU programming and Compute Shaders. To provide this, GPUI analyzes a prefab (or Unity terrain) and uses indirect instancing to render its instances (or detail/tree prototypes). Upon sending the mesh and material data to the GPU once, GPUI creates various GPU buffers and dispatches Compute Shaders on every frame to manipulate the instance data in these buffers. This approach takes the load completely off the CPU and uses the GPU for all rendering processes - so that the CPU threads work more efficiently for game scripts. GPUI also uses different optimization techniques to effectively work on different platforms; so that whether the target platform is a high-end PC, VR, or a modern mobile device, GPUI provides the best indirect instancing strategy.


If you're not familiar with these concepts, you can take a look at the Terminology Page for more information. In any case, here is a basic primer on GPU instancing:


(Indirect) GPU instancing works by sending mesh/material data to the GPU in a single draw call. This reduces the amount of batching to one even if there are hundreds or even thousands of the same mesh/material combination. This removes the bottleneck that occurs when sending mesh and material data from CPU to the GPU, and results in higher fps if there are many of the same mesh-material combinations. That is, GPU instancing helps in scenarios where you have many instances of the same game object.


How is GPUI Different from the Unity Material GPU Instancing Option?



Untiy provides instancing support by using the "Enable GPU instancing" option in Unity Standard and Surface shaders. When you use this option, Unity will handle frustum culling and culling by baked occlusion maps automatically. However, when using this option, Unity will group together instances and issue a draw call for every 500 instances in Direct3D and 125 instances in OpenGL ES 3, OpenGL Core, and Metal. The reason for this limitation is that Unity is aiming to support as many devices as possible, and older devices have a smaller GPU buffer size.


Other options in Unity are the DrawMeshInstanced and the DrawMeshInstancedIndirect scripting APIs. The former allows for 1023 instances per batch, and the latter does not have a limit. However, when using both of these options, you need to manage frustum, occlusion and distance culling for your instances manually.


GPU Instancer uses the indirect instancing method in the background and manages all culling operations in the GPU by making use of Compute Shaders. Furthermore, GPUI gives you a user friendly interface to add indirect instancing support for your Prefabs (with LOD groups, child hierarchies etc.) and your Unity Terrains in a few clicks - without writing any code. Since GPUI automatically generates a copy of the original shader of the material that it configures to work with itself, you are also not limited to using the Standard and Surface shaders and can use most custom shaders out of the box with it.


GPUI also builds additional features on its core by allowing you to use shadows, select shadow LODs, add/remove/update instances automatically, generate billboards and a lot more. Advanced features also include support for a no-game object workflow through an easy to use scripting API.


How can I convert shaders manually to support GPU Instancer?



GPUI has a system that automatically generates a converted version of most shaders to work with itself. This system keeps track of shader changes and handles re-conversions automatically as well. This includes most of the shaders created by shader creation editors like Amplify Shader Editor. But in some special cases, it might be needed to change the shader manually to support GPU Instancer. GPUI detects if a shader is compatible with it and will not generate a separate shader if that is the case. Here is the information you need to manually edit your shaders to support GPUI.


Surface Shaders


...
SubShader {
    ...
    CGPROGRAM
    #include "UnityCG.cginc"
    #include "GPUInstancer/Resources/Shaders/Include/GPUInstancerInclude.cginc"
    #pragma instancing_options procedural:setupGPUI
    ...
    ENDCG
}
...


Since the #pragma multi_compile_instancing directive is automatically added to the generated code from surface shaders, you do not need to include it. However, if you have a additional passes (such as a shadowcaster pass), you need to add support to these passes as well (see Vertex/fragment Shaders below)


Vertex/fragment Shaders

For all passes:


...
Pass {
    ...
    CGPROGRAM
    #include "UnityCG.cginc"
    #include "GPUInstancer/Resources/Shaders/Include/GPUInstancerInclude.cginc"
    #pragma multi_compile_instancing
    #pragma instancing_options procedural:setupGPUI
    ...
    ENDCG
}
...


You also need to add instancing setup to your input structs and vertex functions if you don't already have it:


struct appdata_custom
{
    ...
    UNITY_VERTEX_INPUT_INSTANCE_ID
}


v2f vert( appdata_custom v )
{
    v2f o;
    UNITY_SETUP_INSTANCE_ID(v);
    ...
    return o;
}


SRP Shaders

You need to reference the SRP includes you need and add GPUI support afterwards. Here is an example which uses LWRP:

HLSLPROGRAM
...
#include "LWRP/ShaderLibrary/InputSurfacePBR.hlsl"
#include "LWRP/ShaderLibrary/LightweightPassLit.hlsl"
#include "GPUInstancer/Resources/Shaders/Include/GPUInstancerInclude.cginc"
#pragma instancing_options procedural:setupGPUI
ENDHLSL


Amplify Shader Editor directives

It is important to add support from the ASE window rather than the code since ASE would overwrite your changes if you save the shader again. You can use the following additional directives:


Amplify Shader Editor Directives for GPUI


What are the Build Settings for Android platforms?



Build Settings for Android


GPUI relies heavily on Compute Shaders for its operations in the GPU. In mobile platforms, Compute Shaders are usually supported by the higher-end devices. The requirement for Compute Shaders in the Android systems is at least Open GL ES 3.1 or the Vulkan API.


GPUI does not need any additional settings when targeting Vulkan; however, you need to enable Open GL ES 3.1 support when targeting the Open GL ES API.


To do this, you can simply enable the Require ES3.1 checkbox under:

Edit->Project Settings->Player->Other Settings.


Otherwise Unity will disable the Compute Shaders and your build will run without GPUI enabled.


Please also note that older versions of Unity have some bugs for some of the GPU models on Android devices. If you're working on an Android game, it is recommended to use the latest Unity version.


How can I Increase Billboard Visibility Distances Beyond Manager Limits?



The max billboard distance is tied to the Max Tree Distance property of the manager if you are using the Tree Manager - or if you are using the Prefab Manager, it is tied to the Max Distance property of the prototype. The Tree Manager limits you to 2500 where the Prefab Manager limits to 10000.

If you need more visibility distance, you can edit the limitations of the corresponding managers from the following lines in the GPUInstancerEditorConstants.cs


public static readonly float MAX_TREE_DISTANCE = 2500;
public static readonly float MAX_PREFAB_DISTANCE = 10000;


Troubleshooting


Instances don't Show / Show at Incorrect Locations when Using a Custom Shader



If you are using a custom vertex/fragment shader, the shader needs to be setup for instancing. GPUI sets shaders up for working with itself, but cannot automate general instancing setup since there is no good way to generalize this.


If you are using a custom shader on your instances, or if you are using an asset from the Asset Store, this will most likely be the reason why your instances do not show correctly. To setup your shaders with GPUI in this case, you can take a look at setting vertex/fragment shaders up manually to work with GPU Instancer.


Shadows on the Prefab Instances Look Blocky/Wrong



Using the Shadow Pass of the Original Shader


By default, GPUI uses a custom, lightweight "shadows only" shader to render the shadows of the prototypes that are defined on a Prefab Manager. Using this shader helps increase the shadow performance slightly more; especially if the original shader is using a shadow pass generated by a surface shader (using the addshadow directive). In most cases this shader is enough to render the prototype flawlessly; however, if the original shader uses vertex animation and/or alpha cutoff, then the shadows might not look right. Typical cases of this are when adding tree prefabs. In these cases you can enable the Shadow with Original Shader option under the Shadow settings for the prototype (in the Prefab Manager). This will use the shadow pass of the original shaders of the prefab and the shadows should then look right.



Batch Counts are Higher than without GPUI



Increased batch counts usually means that there are prototypes with very few instance counts that are registered to the Prefab Manager.


GPUI works best with prefabs that have high instance counts. The reason for this is related to the nature of GPU instancing. Since prefabs with low instance counts will not gain a noticeable performance boost from GPU Instancing, it is usually better to let Unity handle their rendering. Unity uses draw call batching techniques on the background (such as dynamic batching). These techniques depend on the CPU to run and tax their operations on the CPU memory. When there are many instances of the same prefabs, these operations turn out to be too costly and the reduction in batch counts dwarf in comparison to GPU Instancing. But where the instance counts are noticeably low, the cost on the CPU when using these techniques becomes trivial - yet they will still reduce batch and draw call counts. While using GPU instancing, on the other hand, since meshes are not combined, every mesh/material combination will always be one draw call.


In short, the lowest batch counts (and the best performance gain) can be achieved by using GPUI with high instance counts. Therefore, rendering everything with GPUI where some prefabs have very few instance counts is not recommended.


The rule of thumb to keep in mind is to have only the prefabs that have high instance counts rendering with GPUI, while minimizing the amount of prototypes as much as possible. For more information on instance counts, you can check the page for best practices.


Shader Variant not Showing in Build



This issue can be solved by changing the material on your prefab to use the GPUI version of the shader (e.g. "GPUInstancer/Standard (Specular setup)") instead of the original (e.g. "Standard (Specular setup)").


The issue here is related to the way Unity handles shader variants. GPUI uses it's own version of the Standard Specular Shader, and switches to this shader at play mode. This shader is in the /resources folder, so it enters the build. However, since you are using the the variant (e.g. cutout) of the original shader, and Unity does not see the GPUI version of this variant on the prefab, it ignores this variant for the GPUI version during build time.


This is true for all the shaders that feature a variant via the "#pragma shader_feature" keyword.


GPUI not working while targeting Android platforms



Disabling OpenGL ES 3.0 Emulation in Android Projects

GPU Instancer requires OpenGL ES 3.1 or Vulkan API for Android platforms. Unity Editor currently can not emulate GLES 3.1. It emulates GLES 3.0 which does not support Compute Shaders. So currently it is not possible to test GPU Instancer with GLES 3.1 at Unity Editor.


If you leave the Emulation mode on, and if you try running your scene with a GPUI manager in it, Unity will throw the following error in the console and GPUI will be deactivated:


Target Graphics API does not support Compute Shaders. Please refer to Minimum Requirements on GPUInstancer/ReadMe.txt for detailed information.


In order to solve this, you can use Unity Editor in No Emulation mode as shown in the picture to the right and make your mobile tests with a build. The editor will then run in the original mode of your operating system (e.g. Direct3D 11 on Windows).


Please also note that Unity switches back to the emulation mode regularly, so you might need to switch back often.


For information on how to use build settings for Android devices you can look at this section.


Compatibility with Other Assets

GPU Instancer has out of the box compatibility with some other Unity Asset Store assets, and also integration with some others. With some assets, however, it will simply not work together because of the nature of the two assets. Assets that rely on Mesh Combining or those that come with their own GPU Instancing solutions fall into this later category.


As Gurbu Technologies, we are always up to integration with other assets. If you are an Asset Store developer, please contact us and we can investigate possible integrations.


In this section, you can find a list of assets that are already known to work or not with GPUI.


Amplify Shader Editor

GPUI works out of the box with ASE shaders. GPUI creates a copy of your ASE shader and configures it to work with itself. Any updates will also be reflected on the created shader. At runtime, GPUI use this converted shader for its prototypes where the material has the original shader. However, if you don't want your shader to be duplicated, you can also check the above description to see how you can manually use the directives necessary for GPUI in your ASE shaders.


Please note, however, that Unity does not support tessellation and GPU instancing at the same time, so tessellated ASE shaders won't work with GPUI as well.


Amplify Impostors

Using a Custom Billboard (Amplify Impostors)


GPUI works out of the box with Amplify Impostors. You can define any Impostor Prefab as a GPUI prototype. GPUI will also use the impostor if it is an a LOD level of the prefab.


Alternatively, you can use the Use Custom Billboard option under the Billboard Settings in all managers and assign the mesh and material that you can generate with Amplify Impostors. This will allow you to keep using GPUI's billboard settings for the selected prototype but render the billboard with Amplify Impostors.


MapMagic World Generator

GPUI - MapMagic Integration

GPU Instancer has a built-in integration with MapMagic World Generator. To use GPUI in your MapMagic Terrains, , you can use the following menu item:


GPU Instancer -> Integration -> Add MapMagic Integraton


Please note that GPUI checks the scripting define symbols in the player settings to determine whether you have MapMagic installed. If you don't have MapMagic, you will not see this menu item. If you have MapMagic, however, and if you don't see the integration menu item, the scripting define symbol might not be added to your player settings for some reason. In that case, you can manually add it by opening your Unity Player Settings (Edit -> Project Settings -> Player) and entering ;MAPMAGIC at the end of your scripting define symbols line.


When you add the integration from the menu, GPUI will add a GameObject to your scene with the options showing you what you want to import to GPUI from the MapMagic generation ruleset in the scene. You can then check the options you wish and click Import. This will turn the integration object into what looks like a combined version of all the GPUI Managers, and you can use the settings as you normally would in those managers.


This is all you need to do to render your MapMagic terrains with GPUI. If at any time you change or edit the MapMagic ruleset, you can click Import again and the changes will reflect on the integration as well.


Gaia

GPUI - Gaia Integration

GPU Instancer has a built-in integration with Gaia. If you wish to use Gaia generated terrains with GPUI, you can use the GX tab under the Gaia Manager to add all desired GPUI managers to your scene.


When you add the The Detail and the Tree Managers this way, it is exactly like adding them from the GPU Instancer Menu. They are there only for convenience.


When you use Add the Prefab Manager from the GX menu, however, GPUI shows you a window that is similar to GPUI's Scene Prefab Importer tool. Using this window, however, instead of the prefab instances in your scene, you are presented with prefab instances that come from the Gaia ruleset that that is defined in the scene.


We recommended you to check the Best Practices Page before using Gaia with GPUI - especially the section on Detail instancing - to get the most out of GPUI.


AQUAS

AQUAS works out of the box with GPU Instancer. However, the AQUAS water planes use two Projectors for water caustics - and these projectors cause a performance hit when using GPU Instancer. There is a very easy solution to overcome this; the steps are as follows:


Creating a Layer for GPUI

1) GPUI includes a feature where you can define a layer that you wish to use for the texture details in the Detail Manager. So you can create a new Layer first (e.g. GPUIRenderingLayer)

Defining the Rendering Layer in the Manager

2) Then set this new Layer to the Detail Texture Layer of the Detail Manager. For all prefabs, GPUI uses the layer of the prefab for this purpose.

Aquas Caustics Projectors

3) Finally, you can set this as the Ignore Layer for the AQUAS caustic projectors. There are two of them under the Aquas Water Plane object.

Ignoring the GPUI Rendering Layer in the Projector

4) You can set ignore the GPUI Rendering Layer as shown in the picture to the left.


Vegetation Studio / Vegetation Studio (Pro)

Since Vegetation Studio uses its own rendering system, it is not possible for GPUI and VS to work on the same objects. However, if you wish to use VS and GPUI together, you can still use GPUI for prefabs that you do not define in VS.