- 1 General Questions
- 1.1 What are the Minimum Requirements?
- 1.2 How does GPU Instancer work?
- 1.3 How is GPUI Different from the Unity Material GPU Instancing Option?
- 1.4 How can I convert shaders manually to support GPU Instancer?
- 1.5 What are the Build Settings for Android platforms?
- 1.6 How can I Increase Billboard Visibility Distances Beyond Manager Limits?
- 1.7 How can I Setup my Instances to have Material Variations on them?
- 1.8 How Can I (Automatically) Add/Remove Prototype Instances
- 1.9 How Can I Use a no-GameObject Workflow?
- 1.10 How Can I Change the Camera at Runtime?
- 2 Troubleshooting
- 2.1 Instances don't Show / Show at Incorrect Locations when Using a Custom Shader
- 2.2 Shadows on the Prefab Instances Look Blocky/Wrong
- 2.3 Batch Counts are Higher than without GPUI
- 2.4 GPUI not working while targeting Android platforms
- 2.5 With Projectors in my Scene, I see Artifacts/Performance Hit
- 2.6 Transperent Materials Look Inside-Out/Back-to-Front when Used on Prototypes
- 3 Compatibility with Other Assets
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 may 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.
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)
For all passes:
You also need to add instancing setup to your input structs and vertex functions if you don't already have it:
You need to reference the SRP includes you need and add GPUI support afterwards. Here is an example which uses LWRP:
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:
What are the Build Settings for Android platforms?
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 GPUI settings window:
Edit -> Preferences -> GPU Instancer
How can I Setup my Instances to have Material Variations on them?
GPU Instancing works by drawing a single mesh and material combination multiple times on the screen. This is why GPUI creates its prototypes from Prefab definitions where it uses the mesh and material information for each renderer the Prefab has and issues drawcalls for them seperately. Thus, out of the box, there would not be any variations for the materials of the prefab instances. However, GPUI offers a solution for having material variations through the GPU Instancer API. The included demo scene ColorVariationsDemo is intended as an example usage of this, so you can take a look at it to get started. Please note, however, that this is an advanced feature and will require you to do some scripting and shader editing.
To setup instance based variations, you basically need to define a buffer, register this buffer to the GPUI prototype instances (and the Prefab Manager) and modify your shader to accept this buffer. The contents of the buffer (variations) can then be set and updated during runtime. Therefore, the setup has a C# scripting part and a shader scripting part:
1. On the MonoBehaviour Script:
Here you can define the buffer and register it to the GPUI instances and a Prefab Manager. You can then update the instances through the GPU Instancer API to make GPUI use this buffer for variations of the instance material. The following example generates a number of GPUI prototype instances, defines a color variations buffer and registers it to the GPUI instances in the Start method. It then updates the buffer with random colors in the Update method, making the generated instances change to a random color every update without breaking instancing. The required references are to the GPUI Prototype (the Prefab itself can be assigned for this since the GPUI prototype component lives on the Prefab) and the active Prefab Manager in the scene.
The important parts are as follows:
Defining the name of the varitation buffer (it is important to notice that the name of this buffer must match the StructuredBuffer on the shader exactly):
private string bufferName = "colorBuffer";
Defining the variation buffer to the Prefab Manager. Please note that you define which type of variation you will use while defining the prototype variation buffer to the manager. In this example, we use a [CODE]Vector4[/CODE] since we are using color variation. This is a generic method and you can read more on it from its API documentation.
GPUInstancerAPI.DefinePrototypeVariationBuffer<Vector4>(prefabManager, prefab.prefabPrototype, bufferName);
Registering the variation buffer per instance:
And updating the variation buffer later on if you wish:
GPUInstancerAPI.UpdateVariation(prefabManager, goList[Random.Range(0, goList.Count)], bufferName, (Vector4)Random.ColorHSV());
2. On the Material's Shader:
For this setup to work, you also need the shader that the material will use to recognize the buffer you have defined above. This can be achieved by defining a [CODE]StructuredBuffer[/CODE] property in the shader with exactly the same name as you defined the buffer in the MonoBehaviour script.
You can define the structured buffer among the shader properties as such:
And then use it as you wish by referencing the instance by its unity_InstanceID from the gpuiTransformationMatrix StructuredBuffer. This is where the instance matrices are stored by GPUI in the GPU. The following example, in line with the color variations example, modifies the Albedo of the surface shader in the surf function with the variations buffer:
The important part here is getting the variation buffer index of the instance by accessing the GPUI prototype instance matrices with the unity_InstanceID:
uint index = gpuiTransformationMatrix[unity_InstanceID];
And using that index to access the variation in the buffer:
col = colorBuffer[index];
How Can I (Automatically) Add/Remove Prototype Instances
GPU Instancer allows you to add and remove instances during runtime. This can be done automatically without writing any additional code, in which case GPUI will keep track of new instantiations (or destroying) of the prefab instances and will handle the prototype GPU buffers accordingly. For more control, you can also use the API to handle this yourself - or completely register and initialize the managers with exactly the instances you want. You can see below how to use each option:
1. The easiest way to add/remove instances at runtime is to enable Auto. Add/Remove Instances option under the Runtime Settings.
When this is enabled, the Prefab Manager will add a component called GPUInstancerPrefabRuntimeHandler on the prefab object and will handle all runtime changes automatically when new instances are instantiated or existing ones are destroyed.
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.
3. Alternatively, you can use the GPU Instancer API to register the prefab instances and reinitialize the Prefab Manager for complete control. This can be done by first calling the RegisterPrefabInstanceList method and then calling the InitializeGPUInstancer method.
The following code demonstrates how this can be done:
public class GPUIRegisterPrefabInstances : MonoBehaviour
// Keeping a static reference to the manager so it can be shared between scenes.
public static GPUInstancerPrefabManager prefabManager;
// The list of prefab instances in scene
public List<GPUInstancerPrefab> prefabInstanceList;
// In this example we fill the list in the Reset method which works when adding the component for the first time (or using the reset command in the inspector).
// You can fill the list in any way you want.
public void Reset()
// Add prefabs in the scene to the list
prefabInstanceList = new List<GPUInstancerPrefab>(FindObjectsOfType<GPUInstancerPrefab>());
// Find the prefab manager and set it to the static property
if(prefabManager == null && GPUInstancerAPI.GetActiveManagers() != null)
GPUInstancerManager manager = GPUInstancerAPI.GetActiveManagers().Find(m => m is GPUInstancerPrefabManager);
prefabManager = (GPUInstancerPrefabManager)manager;
// Register the prefab instance list to the manager
if (prefabManager != null && prefabManager.isActiveAndEnabled)
How Can I Use a no-GameObject Workflow?
GPU Instancer allows you to work with a no-GameObject workflow to maximize your scene performance. By using this workflow, you can render prefab instances without instantiating GameObjects and therefore not using any CPU time for them. Please not that this is an advanced feature and requires a good understanding of Transformation Matrices and GPU Instancing.
The basic idea behind this workflow is supplying an array of Matrix4x4s to the GPU Instancer API to initialize the instances. The included demo scene PrefabsWithoutGameObjects is designed to demonstrate an example usage of this workflow, so it can be a good starting point.
The below script is also is an example that demonstrates a basic usage. What this script does is to first initialize the GPU Instancer Prefab Manager with matrix data that represents transforms at ranfom positions inside a radius of 15 units in the Awake method. Then, if a key is pressed, it updates the matrices with new random positions:
public class NoGameObject : MonoBehaviour
// reference to Prefab Manager
public GPUInstancerPrefabManager prefabManager;
// reference to prefab
public GPUInstancerPrefab prefab;
// size of array and buffers
public int bufferSize;
// transform data array
private Matrix4x4 _matrix4x4Array;
// Use this for initialization
void Awake ()
// initialize the array with the max size
_matrix4x4Array = new Matrix4x4[bufferSize];
// set the data of the array
for (int i = 0; i < _matrix4x4Array.Length; i++)
_matrix4x4Array[i] = Matrix4x4.TRS(Random.insideUnitSphere * 15, Quaternion.identity, Vector3.one);
// initialize the buffers with array
GPUInstancerAPI.InitializeWithMatrix4x4Array(prefabManager, prefab.prefabPrototype, _matrix4x4Array);
private void Update()
// change the data of the array
for (int i = 0; i < _matrix4x4Array.Length; i++)
_matrix4x4Array[i] = Matrix4x4.TRS(Random.insideUnitSphere * 15, Quaternion.identity, Vector3.one);
// update buffers
GPUInstancerAPI.UpdateVisibilityBufferWithMatrix4x4Array(prefabManager, prefab.prefabPrototype, _matrix4x4Array);
How Can I Change the Camera at Runtime?
GPUI keeps a reference to the scene camera, and auto-detects the cameras with the "Main Camera" tag. You can also specify a specific camera for use with a given manager. However, if you wish to switch cameras at runtime, you need to call the SetCamera API method from your script right after you enable/instantiate your new camera.
Alternatively, you can add the included GPUInstancerCameraHandler component on your cameras to have GPUI automatically handle this for you.
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
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.
GPUI not working while targeting Android platforms
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.
With Projectors in my Scene, I see Artifacts/Performance Hit
Unity Projectors can cause a performance hit and/or artifacts on the screen when using GPU Instancer. The reason for this is related to how Unity handles projectors internally. There is, however, a very easy solution to workaround this by using Layers. The steps are as follows:
1) You can start by creating a new Layer (e.g. GPUIRenderingLayer)
2) Setting this Layer to the prefabs are enough for prefab instancing with Prefab Manager, Tree Manager and for the prefab type prototypes in the Detail Manager.
3) For the Detail Textures, you can set this new Layer to the Detail Texture Layer of the Detail Manager.
4) You can then set the projector to ignore the GPUI Rendering Layer as shown in the picture to the left.
Transperent Materials Look Inside-Out/Back-to-Front when Used on Prototypes
Materials with transparency can result in unexpected behavior when used with GPU Instancer. Since GPU instancing works by treating all instances as the same, the GPU draws one mesh multiple times without any regard to draw ordering. This will result in wrong draw orders while using transparency, and the typical result would be inside-out or back-to-front looking prototype instances. This can be solved by implementing a form of OIT approximation. Please note, however, that GPUI currently does not include such an implementation so if you are willing to use transparent objects with GPUI, you should manually implement an OIT solution.
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.
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
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:
Tools -> GPU Instancer -> Integration -> Add MapMagic Integration
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.
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.
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:
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)
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.
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.
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.