# CGI Studio Optimization Techniques

This chapter describes performance optimization techniques for Candera based applications.

# Rendering Only Updated Content

#### <a class="anchor" id="bkmrk--6"></a>Description

This chapter briefly describes how to achieve performance optimization by rendering only updated content.

#### **Introduction**

##### <a class="anchor" id="bkmrk--8"></a>Invalidation Introduction

Basic principles for composing graphical content:

<div class="contents" id="bkmrk-place-content-which-"><div class="contents"><div class="textblock">- Place content which is never changed in an own scene and render it to an own layer.
- Partition content which is frequently changed by widgets or animations. Use several cameras for this purpose.
- If rarely modified graphical content is part of a dynamic scenery then think about using <span style="color: rgb(230, 126, 35);">[Texture Render Targets](https://doc316en.candera.eu/books/candera/page/multiple-render-targets)</span>.

</div></div></div>##### <a class="anchor" id="bkmrk--9"></a>How is it done?

In the render loop of the application all Widgets are updated by calling [Candera::WidgetBase::Update()](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_widget_base.html#ad7891efa29f51b34e2566ff4804c59e3). The basic render loop looks like this:

```
  // 3D Render Loop

    // handle input events
    // ...

    // update animations by calling AnimationDispatcher::DispatchTime()
    if (m_animationDispatcher3D != 0) {
      m_animationDispatcher3D->SetWorldTimeMs(nowMs);
      m_animationDispatcher3D->DispatchTime();
    }

    // update all widgets
    CgiApp::GetInstance().Update();

    Renderer::RenderAllCameras();

  // end 3D Render Loop
```

The widgets must now implement a mechanism to tell the application whether associated graphical content needs to be rendered. The following pages explain two ways to achieve this:

<div class="contents" id="bkmrk-use-candera%3A%3Acamera%3A"><div class="textblock">- <span style="color: rgb(230, 126, 35);">[Use Candera::Camera::SetRenderingEnabled() / Candera::Camera2D::SetRenderingEnabled()](https://doc316en.candera.eu/link/375#bkmrk-use-setrenderingenab)</span>
- <span style="color: rgb(230, 126, 35);">[Explicitely Pick Camera to Render](https://doc316en.candera.eu/link/375#bkmrk-pick-camera-to-rende)</span>

</div></div>####   
**Use SetRenderingEnabled()**   


##### <a class="anchor" id="bkmrk--10"></a>Use Candera::Camera::SetRenderingEnabled() / Candera::Camera2D::SetRenderingEnabled()

The example below shows how in CGIApplication all 3D cameras are turned off in first step of render loop.

```
void CgiApp3dGc::Update() {
    Base::Update();
   
  // Turn off all cameras
    UInt32 cameraCount = Renderer::GetCameraCount();
    for (UInt32 i = 0; i < cameraCount; i++)
    {
        Camera* cam = Renderer::GetCamera(i);
        cam->SetRenderingEnabled(false);
    }

    // Update widgets in all visible scenes
    WidgetBase* widget = 0;
    Vector<SceneContext*>::ConstIterator it = m_sceneContexts.ConstBegin();
    for (; it != m_sceneContexts.ConstEnd(); it++) {
        if ((*it) != 0 && (*it)->GetScene() != 0 && (*it)->GetScene()->IsRenderingEnabled()) {
            widget = (*it)->GetFirstWidget();
            while (widget != 0) {
                widget->Update();
                widget = (*it)->GetNextWidget();
            }
        }
    }
}
```

The [Candera::Widget::Update()](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_widget_base.html#ad7891efa29f51b34e2566ff4804c59e3) method needs to be implemented such that the recently turned off camera is turned on again whenever rendering is required. The [Candera::Camera](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_camera.html "A Camera provides Modelview and Projection matrices. Camera is a Transformable.* The eye point is set...") can be either set as a widget property or retrieved inside the scene by masking the widget and the associated camera with the same [Candera::ScopeMask](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_scope_mask.html "The class ScopeMask allows scene graph nodes to form conceptual groups independent of the scene graph...") value.

```
void SampleBaseWidget3D::InvalidateCamera(bool value)
{
  m_camera->SetRenderingEnabled(true);
}
```

```
void MyWidget::Update()
{
  // update graphical content from cached property value(s)
  //...

  Base::InvalidateCamera(true);
}
```

#### **Pick Camera to Render**

##### Explicitly Pick Camera to Render

Another method is to maintain a list of cameras by the application.

The render loop has to be changed

<div class="contents" id="bkmrk-to-call-candera%3A%3Aren"><div class="textblock">- to call Candera::Renderer::RenderCamera( Camera \* camera )
- instead of [Candera::Renderer::RenderAllCameras()](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_renderer.html#aed822ba1d66620f2d1e794973e30f354).

</div></div><div class="contents" id="bkmrk-the-application-need"><div class="textblock"><dl class="note"><dd><p class="callout info">The application needs to take care on <span style="color: rgb(230, 126, 35);">[Render Buffer Swapping](https://doc316en.candera.eu/link/1050#bkmrk-render-buffer-swappi)</span>.</p>

</dd></dl></div></div>

# Multi Frequency Rendering

#### <a id="bkmrk--9"></a>Description

This chapter briefly describes the Multi Frequency Rendering technique supported by [Candera](http://dev.doc.cgistudio.at/APILINK/namespace_candera.html "[DataBinding_RefTypeSample]").   
It allows to split rendering of complex parts to several frames, to achieve an overall higher frame rate.

#### **Introduction**

##### <a class="anchor" id="bkmrk--10"></a>Multi Frequency Rendering Introduction

Multi Frequency Rendering allows using different update rates for multiple render targets. For example

<div class="contents" id="bkmrk-fix-framerate-for-tu"><div class="contents"><div class="contents"><div class="textblock">- Fix framerate for tubes.
- Adaptive framerate for center use case.
- Details of entire content are preserved.

</div></div></div></div><div drawio-diagram="1945"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676868292.png" alt=""/></div>

<div class="contents" id="bkmrk--1"><div class="contents"><div class="textblock">  
</div></div></div>##### <a class="anchor" id="bkmrk--12"></a>Workflow

<div class="contents" id="bkmrk-cgi-analyzer-sceneco"><div class="contents"><div class="textblock"><table border="0"><tbody><tr><td align="center">**CGI Analyzer**</td><td align="center">**SceneComposer**</td><td align="center">**Application**</td></tr><tr><td style="vertical-align: middle;">[![09_mfranalyzer.png](https://doc316en.candera.eu/uploads/images/gallery/2023-02/scaled-1680-/nIy09-mfranalyzer.png)](https://doc316en.candera.eu/uploads/images/gallery/2023-02/nIy09-mfranalyzer.png)

</td><td style="vertical-align: middle;">[![09_mfrscenecomposer.png](https://doc316en.candera.eu/uploads/images/gallery/2023-02/scaled-1680-/09-mfrscenecomposer.png)](https://doc316en.candera.eu/uploads/images/gallery/2023-02/09-mfrscenecomposer.png)

</td><td style="vertical-align: middle;">[![09_mfrapplication.png](https://doc316en.candera.eu/uploads/images/gallery/2023-02/scaled-1680-/09-mfrapplication.png)](https://doc316en.candera.eu/uploads/images/gallery/2023-02/09-mfrapplication.png)

</td></tr><tr><td align="left">CGI Analyzer determines benchmark values for each node of a scene given. The benchmarks are exported to a \*.crsms file.</td><td align="left">The benchmarks are assigned to nodes benchmark property. SceneComposer stores nodes incl. benchmark values in Asset File.</td><td align="left">The Application renders multiple cameras with different framerates with help of Benchmark-CameraRenderStrategy.</td></tr></tbody></table>

</div></div></div>##### <a class="anchor" id="bkmrk--13"></a>Candera::CameraRenderStrategy

The following sections explain how an application can use the [Candera::CameraRenderStrategy](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_camera_render_strategy.html "The abstract class CameraRenderStrategy is intended to be derived in order to tell the Renderer...") to implement multi frequency rendering based on given benchmark values within the scene tree.

##### <a class="anchor" id="bkmrk--14"></a>References

For details about how to calculate benchmark values and how to assign them to a scene tree, please refer to:

<div class="contents" id="bkmrk-cgi-analyzer_user_ma"><div class="textblock">- **CGI-Analyzer\_User\_Manual.pdf**: Calculate benchmark values and export to a \*.crsms file.
- <span style="color: rgb(230, 126, 35);">**[SceneComposer Help](https://doc316en.candera.eu/books/import-of-resources/page/import-benchmarks)**</span>: Import benchmark values from a \*.crsms file into a given solution.

</div></div>####   
**Candera - Camera Render Strategy**

##### <a class="anchor" id="bkmrk--15"></a>Partitioning Render Passes

A Camera render pass renders all scene nodes in one sweep.  
[Candera::CameraRenderStrategy](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_camera_render_strategy.html "The abstract class CameraRenderStrategy is intended to be derived in order to tell the Renderer...") enables to partition a Camera render pass, if e.g. complete processing in one frame is not possible.

##### <a class="anchor" id="bkmrk--16"></a>Examples of Usage

<div class="contents" id="bkmrk-omit-rendering-of-no"><div class="contents"><div class="contents"><div class="textblock">- Omit rendering of nodes with low priority like decorations.
- Multi Frequency Rendering: Suspend and continue Camera render pass next time Camera renders. Unless render pass is complete, render target is not swapped.

</div></div></div></div><div drawio-diagram="1950"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676868435.png" alt=""/></div>

<div class="contents" id="bkmrk--3"><div class="contents"><div class="textblock">  
</div></div></div>Both, [Candera::BreakNodeCameraRenderStrategy](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_break_node_camera_render_strategy.html "The BreakNodeCameraRenderStrategy is an implementation of the abstract class CameraRenderStrategy. The rendering of the nodes is done until it reaches a node that is in the list of break nodes (See function AddBreakNode).") and [Candera::BenchmarkCameraRenderStrategy](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_benchmark_camera_render_strategy.html "The class BenchmarkCameraRenderStrategy is an implementation of the abstract class CameraRenderStrate...") are concrete implementations of the interface [Candera::CameraRenderStrategy](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_camera_render_strategy.html "The abstract class CameraRenderStrategy is intended to be derived in order to tell the Renderer...") to cover most typical Camera render pass partitioning.

####   
**Candera - Break Node Camera Render Strategy**

##### <a class="anchor" id="bkmrk--18"></a>Splitting Render Pass on specific Break Nodes

The [Candera::BreakNodeCameraRenderStrategy](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_break_node_camera_render_strategy.html "The BreakNodeCameraRenderStrategy is an implementation of the abstract class CameraRenderStrategy. The rendering of the nodes is done until it reaches a node that is in the list of break nodes (See function AddBreakNode).") is populated with a list of arbitrary break nodes.  
Defined by RenderPassAction a break node can pause or stop a Camera render pass, if encountered.

```
breakNodeStrategy = new BreakNodeCameraRenderStrategy();
breakNodeStrategy->AddBreakNode(node4);
breakNodeStrategy->AddBreakNode(node7);
breakNodeStrategy->SetRenderPassActionOnBreakNode(renderPassAction);
camera->SetCameraRenderStrategy(breakNodeStrategy);
```

<div drawio-diagram="1952"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676868541.png" alt=""/></div>

<div class="contents" id="bkmrk-back-to-the-menu-1"></div>####   
**Candera - Benchmark Camera Render Strategy**

##### <a class="anchor" id="bkmrk--20"></a>Splitting Render Pass on Benchmark Threshold Values

Each node has a benchmark property that describes a custom reference value for render duration.  
During Camera render pass benchmarks are accumulated until threshold of [Candera::BenchmarkCameraRenderStrategy](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_benchmark_camera_render_strategy.html "The class BenchmarkCameraRenderStrategy is an implementation of the abstract class CameraRenderStrate...") is reached. RenderPassAction defines to suspend or stop render pass.

```
benchmarkStrategy = new BenchmarkCameraRenderStrategy(); 
node1->SetRenderBenchmark(250.0f); 
node2->SetRenderBenchmark(330.0f); 
node3->SetRenderBenchmark(220.0f); 
node4->SetRenderBenchmark(400.0f); 
node5->SetRenderBenchmark(390.0f); 
benchmarkStrategy->SetThreshold(1000.0f);
benchmarkStrategy->SetRenderPassActionOnThreshold(renderPassAction);
camera->SetCameraRenderStrategy(benchmarkStrategy);
```

<div drawio-diagram="1953"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676868597.png" alt=""/></div>

<div class="contents" id="bkmrk--7"><div class="textblock">  
</div></div>####   
**Candera - Render Pass Actions**

##### <a class="anchor" id="bkmrk--22"></a>Render Pass Actions

<div class="contents" id="bkmrk-proceed-render-pass-"><div class="textblock"><table border="0" cellpadding="5"><tbody><tr><td align="center" valign="top" width="33%">[![09_mfrrenderpassaction1.png](https://doc316en.candera.eu/uploads/images/gallery/2023-02/scaled-1680-/09-mfrrenderpassaction1.png)](https://doc316en.candera.eu/uploads/images/gallery/2023-02/09-mfrrenderpassaction1.png)

</td><td align="center" valign="top" width="33%">[![09_mfrrenderpassaction2.png](https://doc316en.candera.eu/uploads/images/gallery/2023-02/scaled-1680-/09-mfrrenderpassaction2.png)](https://doc316en.candera.eu/uploads/images/gallery/2023-02/09-mfrrenderpassaction2.png)

</td><td align="center" valign="top" width="33%">[![09_mfrrenderpassaction3.png](https://doc316en.candera.eu/uploads/images/gallery/2023-02/scaled-1680-/09-mfrrenderpassaction3.png)](https://doc316en.candera.eu/uploads/images/gallery/2023-02/09-mfrrenderpassaction3.png)

</td></tr><tr><td align="center">**Proceed Render Pass**</td><td align="center">**Pause Render Pass**</td><td align="center">**Stop Render Pass**</td></tr><tr><td align="left">Proceeds Rendering. Rendering is not interrupted. Break nodes are ignored.</td><td align="left">Pauses rendering. The next time the Camera is rendered it restarts from the node that has been paused. Swaps render target when Camera completes.  
Usage: Entire content captured by Camera shall be displayed</td><td align="left">Stops rendering. The next time the Camera renders it restarts from the very first node in render order. Swaps render target at each render cycle.  
Usage: Nodes with lower priority shall be omitted.</td></tr></tbody></table>

</div></div>####   
**Example - Multi Frequency Rendering**

##### <a class="anchor" id="bkmrk--23"></a>Example: Different Frame Rates for several Cameras

<div class="contents" id="bkmrk-fix-framerate-for-sp"><div class="contents"><div class="textblock">- Fix framerate for speedometer.
- Adaptive framerate for car.
- Details of entire content is preserved.

</div></div></div>##### <a class="anchor" id="bkmrk--24"></a>Cycle 1

<div class="contents" id="bkmrk-camera-1-%3A-renders-t"><div class="contents"><div class="textblock"><table border="0"><tbody><tr><td>[![09_mfrcycle1.png](https://doc316en.candera.eu/uploads/images/gallery/2023-02/scaled-1680-/09-mfrcycle1.png)](https://doc316en.candera.eu/uploads/images/gallery/2023-02/09-mfrcycle1.png)

</td></tr><tr><td>Camera 1 : Renders the speedometer and swaps render target.  
Camera 2 : Renders car until benchmark threshold is exceeded. Render target is not swapped.</td></tr></tbody></table>

</div></div></div>##### <a class="anchor" id="bkmrk--25"></a>Cycle 2

<div class="contents" id="bkmrk-camera-1-%3A-renders-t-0"><div class="textblock"><table border="0"><tbody><tr><td>[![09_mfrcycle2.png](https://doc316en.candera.eu/uploads/images/gallery/2023-02/scaled-1680-/09-mfrcycle2.png)](https://doc316en.candera.eu/uploads/images/gallery/2023-02/09-mfrcycle2.png)

</td></tr><tr><td>Camera 1 : Renders the speedometer and swaps render target.  
Camera 2 : Completes render pass and swaps render target. Thus Camera2 renders with half frames per second (FPS) than Camera1.</td></tr></tbody></table>

</div></div>####   
**Multi Frequency Rendering in 2D**

Analogous to [Candera::CameraRenderStrategy](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_camera_render_strategy.html "The abstract class CameraRenderStrategy is intended to be derived in order to tell the Renderer..."), there is an abstract class [Candera::Camera2DRenderStrategy](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_camera2_d_render_strategy.html "The abstract class Camera2DRenderStrategy is intended to be derived in order to tell the Renderer2D...") available.

This class is intended to be derived to tell the [Candera::Renderer2D](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_renderer2_d.html "The class Renderer2D represents the unique Candera 2D render interface to the application. Each render call shall be triggered via the Renderer2D interface."), if rendering shall proceed, pause, or stop for a given node in a camera's render pass.

##### <a class="anchor" id="bkmrk--26"></a>BreakNodeCamera2DRenderStrategy

In difference to 3D, [Candera](http://dev.doc.cgistudio.at/APILINK/namespace_candera.html "[DataBinding_RefTypeSample]") 2D Engine only provides a [Candera::BreakNodeCamera2DRenderStrategy](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_break_node_camera2_d_render_strategy.html "The BreakNodeCamera2DRenderStrategy is an implementation of the abstract class Camera2DRenderStrategy...") to split a 2D render pass along specific break nodes.

####   
**Limitations**

##### <a class="anchor" id="bkmrk--27"></a>MFR animation issue

Using an AnimationReq-Message in combination with MFR results in an wrong output since the animation progresses during each partial drawn frame. One idea is to check if the view uses MFR and if used the view would provide it's own AnimationTime-Dispatcher which only gets updated during the Update call. The animation for this view would then be added to this time dispatcher. This allows to use animations as long as they only affect a single scene.

##### <a class="anchor" id="bkmrk--28"></a>MFR transition issue

Using a Scene-Transition in combination with MFR results in an wrong output since the transition progresses during each partial drawn frame. Transitions should check the status of the camera and only perform a modification if the Render-Pass is complete. This would allow transitions to be used if only one Scene is active per Render-Target. To allow multiple scenes per Render-Target (more common case) all Cameras in the transition need to be "synced".

# VRAM Upload Culling

#### <a class="anchor" id="bkmrk--1"></a>Description

This chapter briefly describes how to use scope masks for uploading only dedicated content to VRAM.

#### **VRAM Upload using Scope Masks**

content to VRAM in succeeding steps.

##### <a class="anchor" id="bkmrk--3"></a>VRAM Upload Policies

Refer to <span style="color: rgb(230, 126, 35);">[Startup and Asset Management](https://doc316en.candera.eu/books/candera/page/startup-and-asset-management-LUu)</span> for how to load scenes from assets and upload to VRAM with the default upload policy [Candera::ContentLoader::DefaultUploadPolicy](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_content_loader.html#aeac726ed65d6cdb88644422ec9c5b0d2a374ada9b6b3da92611ff8e707530b68f "creates scene data in System RAM and uploads the asset data to VRAM").

To implement VRAM upload culling with scopes, use [Candera::ContentLoader::NoVramUploadPolicy](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_content_loader.html#aeac726ed65d6cdb88644422ec9c5b0d2a8646da23e8199f2db5a21b82b1ae1978 "creates scene data in System RAM but does not upload anything to VRAM") and upload dedicated content based on scope masks later.

##### <a class="anchor" id="bkmrk--4"></a>Scoping Concept

Refer to <span style="color: rgb(230, 126, 35);">[Scoping](https://doc316en.candera.eu/books/scene-design/chapter/scoping)</span> how to use and configure scope masks in SceneComposer.

####   
**Code Example**

The following scene graph is a simple example where two parts of the scene have different scopes. Think about a use case where one part of the scene has to be displayed immediately after loading the scene and the second part has to be displayed only later in some special situations. To save time for uploading the content to VRAM not all of the content has to be uploaded immediately.

<div drawio-diagram="1944"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676867547.png" alt=""/></div>

<div class="contents" id="bkmrk--0"><div class="contents"><div class="textblock">  
</div></div></div>##### <a class="anchor" id="bkmrk--6"></a>Using NoVramUploadPolicy

Loading the scene from the asset has to be triggered without loading the content to VRAM.

```
using namespace Candera;

<a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_content_loader.html" title="Encapsulates routines for scene content handling.">ContentLoader</a>& contentLoader = <a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_content_loader.html#a8d2faf2ac0af84444a4de43845c2e03e">ContentLoader::GetInstance</a>();
<a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_content_loader.html#abcb5725d1db1cae643a7d2e9fed85b91">ContentLoader::BuildState</a> buildState = contentLoader.BuildSceneContext("Scene", <a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_content_loader.html#aeac726ed65d6cdb88644422ec9c5b0d2a8646da23e8199f2db5a21b82b1ae1978" title="creates scene data in System RAM but does not upload anything to VRAM">ContentLoader::NoVramUploadPolicy</a>);
if (buildState == <a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_content_loader.html#abcb5725d1db1cae643a7d2e9fed85b91ac464d449fddc8a968cacd4f660dbd097" title="Completed.">ContentLoader::Completed</a>) {
    <a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_scene_context.html" title="Encapsulates main objects that define a scene context an application can operate on. These objects are:">SceneContext</a>* sceneContext = contentLoader.GetSceneContext("Scene");
    <a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_scene.html" title="The class Scene represents a top level scene graph node. Multiple Scenes are allowed. A Scene can not be part of any other Scene. To render a Scene, at least one Camera must be part of this Scene and the Camera must have rendering enabled. A Scene can have more than one Camera. Note: Lights added to a Scene apply for that Scene only and do not affect 3D objects in any other Scene.">Scene</a>* scene = sceneContext-><a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_scene_context.html#a895f11e8ee586e4e10649838cfd12dd7">GetScene</a>();
}
```

##### <a class="anchor" id="bkmrk--7"></a>Upload Nodes with Scope 1

```
using namespace Candera;

<a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_scope_mask.html" title="The class ScopeMask allows scene graph nodes to form conceptual groups independent of the scene graph...">ScopeMask</a> scopeMask1(false);            // all scopes are disabled...
scopeMask1.SetScopeEnabled(1, true);    // ...and only scope 1 gets enabled.
scene-><a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_scene.html#a324480706f8e985675e5fea454381150">Upload</a>(scopeMask1);
```

The scene can be rendered now as long as those nodes with scope 2 are not needed (e.g. rendering is disabled).

##### <a class="anchor" id="bkmrk--8"></a>Deferred Upload of Nodes with Scope 2

```
using namespace Candera;

<a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_scope_mask.html" title="The class ScopeMask allows scene graph nodes to form conceptual groups independent of the scene graph...">ScopeMask</a> scopeMask2(false);
scopeMask2.SetScopeEnabled(2, true);
scene-><a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_scene.html#a324480706f8e985675e5fea454381150">Upload</a>(scopeMask2);
```

Now the whole scene is uploaded to VRAM and can be rendered completely.

<div class="contents" id="bkmrk-in-that-simple-use-c"><div class="textblock"><dl class="note"><dt>  
</dt><dd><p class="callout info">In that simple use case the scopes are already set to the nodes e.g. during design phase in SceneComposer. The scopes can also be set during runtime by calling [Candera::Node::SetScopeMask()](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_node.html#a96af0d7869cd7b35b7f2a0a35a70a1f1) or [Candera::Node::SetScopeEnabled()](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_node.html#abefd359cba7184aec9f2ebd7b9ab31e0).</p>

<p class="callout info">This example is written for [Candera](http://dev.doc.cgistudio.at/APILINK/namespace_candera.html "[DataBinding_RefTypeSample]") 3D, for 2D please refer to [Candera::Scene2D::Upload()](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_scene2_d.html#a1d21f1e09ea51bd1ac741fc5ae8d2e3b), [Candera::Node2D::SetScopeMask()](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_node2_d.html#af111a4667a3507d78b01814c6e132281) and [Candera::Node2D::SetScopeEnabled()](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_node2_d.html#aaa166796aff943249b32e4c2ad7e20ae).</p>

</dd></dl></div></div>

# Occlusion Queries and Occlusion Culling

#### <a class="anchor" id="bkmrk--1"></a>Description

In scenes containing nodes with lots of vertices or expensive fragment shaders, the rendering speed can be drastically improved by avoiding to render occluded objects. For this purpose [Candera](http://dev.doc.cgistudio.at/APILINK/namespace_candera.html "[DataBinding_RefTypeSample]") offers the Occlusion Queries and Occlusion Culling, which are described on this page.

#### **Occlusion Queries**

##### <a class="anchor" id="bkmrk--2"></a>Overview

Occlusion queries are the collective name for a particular type of queries, which are useful to detect whether an object is visible or not. They interrogate asynchronously the Render Device to determine whether the scoped rendering commands pass the depth test and if so, how many samples pass. Occlusion queries are typically used to enable features like occlusion culling and varying lens flare or bloom intensity.

<div class="contents" id="bkmrk-queries-are-related-"><div class="contents"><div class="textblock"><dl class="note"><dt></dt><dd><p class="callout info">Queries are related to one specific rendering context and must not be uploaded to multiple contexts.</p>

</dd><dd></dd></dl></div></div></div>##### <a class="anchor" id="bkmrk--3"></a>Occlusion Query Types

There are three types of occlusion queries:

<div class="contents" id="bkmrk-query%3A%3Aqueryanysampl"><div class="contents"><div class="textblock">- [Query::QueryAnySamplesPassed](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_query.html#aeef30513e21344092b50c82f7ddf6ccda7141400f708d270e4f8b95b4ca3f5a7f "Query determines if any sample passes the depth test."): query determines, if any sample passes the depth test.
- [Query::QueryAnySamplesPassedConservative](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_query.html#aeef30513e21344092b50c82f7ddf6ccdaa69721a27042afb9796561f3a7d17099 "Similar to QueryAnySamplesPassed type, but less precise for queries performance's sake..."): similar to QueryAnySamplesPassed type except that the implementation may use a less accurate algorithm, which may be faster, but at the cost of more false positives.
- [Query::QueryTransformFeedbackPrimitivesWritten](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_query.html#aeef30513e21344092b50c82f7ddf6ccda9d24a7bd8b750118dc44517bc7b82cba "Query determines how many vertices have been written into bound transform feedback buffer(s)..."): query determines how many vertices have been written into bound transform feedback buffer.

</div></div></div>##### <a class="anchor" id="bkmrk--4"></a>Conditional Rendering Example

The figure below depicts the demand for occlusion queries to determine and subsequently discard occluded objects in a highly populated scene:

<div drawio-diagram="1943"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676863030.png" alt=""/></div>

<div class="contents" id="bkmrk--0"><div class="contents"><div class="textblock">  
</div></div></div>Find below an abstract code sample for occlusion queries to obtain information whether any pixels have been rendered or not:

```
SharedPointer<Query> query;
query = <a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_query.html#ad85249a37de10608cb92612c8c7784e6">Query::Create</a>(<a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_query.html#aeef30513e21344092b50c82f7ddf6ccda7141400f708d270e4f8b95b4ca3f5a7f" title="Query determines if any sample passes the depth test.">Query::QueryAnySamplesPassed</a>);
query.Upload();
query.Begin(); 

// Do some rendering here.

query.End(); 

// Process other operations to provide GPU with sufficient time to complete query or skip query evaluation, if result is not available yet.

if (query.IsResultAvailable()) {
    if (query.GetResult() > 0)) {
        // Samples have been written to framebuffer while query was active, this is between query.Begin() and query.End().
        // In case low resolution model was rendered, render next frame with high resolution model.
    }
    else {
        // No sample has been written to framebuffer while query was active.
        // In case high resolution model was rendered, render next frame with low resolution model.
    }
}
```

####   
**Occlusion Culling**

##### <a class="anchor" id="bkmrk--6"></a>Overview

Occlusion Culling is a feature that disables rendering of objects when they are not currently seen by the camera because they are obscured by other objects. The feature can be enabled by setting the render strategy for camera to [OcclusionCullingCameraRenderStrategy](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_occlusion_culling_camera_render_strategy.html "The class OcclusionCullingCameraRenderStrategy is an implementation of the abstract class CameraRende..."). During the rendering, all nodes initialized by the strategy will issue occlusion queries. If query results are available from the previous frame, they are evaluated and all nodes deemed occluded will have their bounding box rendered invisibly instead of the node itself. Visible nodes, or nodes not having a QueryProperty attached, will be rendered as usual. A new query to determine visibility for the next frame will be issued regardless the result of the previous query.

<div class="contents" id="bkmrk-a-performance-increa"><div class="contents"><div class="textblock"><dl class="note"><dd><p class="callout info">A performance increase by using occlusion culling can only be expected when objects occlude each other, and occluded objects consist of lots of vertices, have expensive fragment shaders, or both.</p>

</dd></dl></div></div></div>##### <a class="anchor" id="bkmrk--7"></a>Workflow

<div class="contents" id="bkmrk-attach-an-occlusionc"><div class="contents"><div class="contents"><div class="textblock">- Attach an [OcclusionCullingCameraRenderStrategy](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_occlusion_culling_camera_render_strategy.html "The class OcclusionCullingCameraRenderStrategy is an implementation of the abstract class CameraRende...") to the camera.

<div class="fragment">  
</div></div></div></div></div>```
    m_occlusionCullingStrategy = CANDERA_NEW(OcclusionCullingCameraRenderStrategy)();
    m_camera->SetCameraRenderStrategy(m_occlusionCullingStrategy);
```

<div class="contents" id="bkmrk-initialize-the-rootn"><div class="contents"><div class="contents"><div class="textblock"><div class="fragment">  
</div>- Initialize the rootNode's subtree for use by the render strategy.

<div class="fragment">  
</div></div></div></div></div>```
    m_occlusionCullingStrategy->Initialize(m_group, <a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_query.html#aeef30513e21344092b50c82f7ddf6ccdaa69721a27042afb9796561f3a7d17099" title="Similar to QueryAnySamplesPassed type, but less precise for queries performance's sake...">Query::QueryAnySamplesPassedConservative</a>);
```

<div class="contents" id="bkmrk-this-camera-render-s"><div class="contents"><div class="textblock"><dl class="note"><dd><dl class="note"><dd><p class="callout info">This camera render strategy requires nodes to have a valid bounding box. This camera render strategy reaches its full potential when nodes were sorted front to back first.</p>

</dd></dl></dd><dd></dd></dl></div></div></div><div class="contents" id="bkmrk-render-camera-m_gdu-"><div class="contents"><div class="contents"><div class="textblock">- Render camera ```
        m_gdu->ToRenderTarget3D()->Activate();
        RenderDevice::ClearDepthBuffer(1.0f);
        <a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_renderer.html#aed822ba1d66620f2d1e794973e30f354">Renderer::RenderAllCameras</a>();
    ```

- [OcclusionCullingCameraRenderStrategy](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_occlusion_culling_camera_render_strategy.html "The class OcclusionCullingCameraRenderStrategy is an implementation of the abstract class CameraRende...") interface provides also methods to get the number of occluded and non-occluded nodes since last render pass by using the methods [OcclusionCullingCameraRenderStrategy::GetOccludedNodesCount()](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_occlusion_culling_camera_render_strategy.html#a11ffc92413b74687427d05eee20be52c) and [OcclusionCullingCameraRenderStrategy::GetVisibleNodesCount()](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_occlusion_culling_camera_render_strategy.html#a26d3bf20b6c9bc588efe5e4aa52e29a5).

- Before destroying the render strategy remove the association with nodes by calling the [OcclusionCullingCameraRenderStrategy::Reset()](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_occlusion_culling_camera_render_strategy.html#a214a77f084e490f73e74eb107f7556e0) method

<div class="fragment">  
</div></div></div></div></div>```
    m_occlusionCullingStrategy->Reset(m_group);
    CANDERA_DELETE(m_occlusionCullingStrategy);
```

<div class="contents" id="bkmrk-the-nodes-removed-fr"><div class="contents"><div class="textblock"><dl class="note"><dd><p class="callout info">The nodes removed from the subtree are automatically detached from the render strategy</p>

</dd></dl></div></div></div>##### <a class="anchor" id="bkmrk--8"></a>Occlusion Culling in SceneComposer

Refer to chapter<span style="color: rgb(230, 126, 35);"> [Occlusion Culling](https://doc316en.candera.eu/link/130#bkmrk-%C2%A0occlusion-culling-0)</span> to see how to configure occlusion culling in SceneComposer.

# Bitmap Compression

#### Introduction

Bitmap compression aims to improve the application performance by reducing the bandwidth consumption and asset size and also by speeding up the bitmaps load and upload.

Candera supports following formats for compressing bitmaps, that are described in detail on this page:

- <span style="color: rgb(0, 0, 0);">Run-legth Encoding </span>
- <span style="color: rgb(0, 0, 0);">Color Look-Up Table </span>
- <span style="color: rgb(0, 0, 0);">Erricson Texture Compression </span>

#### **Run-legth Encoding**

##### <a class="anchor" id="bkmrk--1"></a>Description

**Run-length encoding** (RLE) is a simple form of data compression in which runs of data are stored as a single data value and count, rather than as the original run. This is most useful on data that contains many such runs so, the content of the data will affect the compression ratio achieved by RLE. Although most RLE algorithms cannot achieve the high compression ratios of the more advanced compression methods, RLE is both easy to implement and quick to execute, making it a good alternative to either using a complex compression algorithm or leaving the image data uncompressed.

##### <a class="anchor" id="bkmrk--2"></a>RLE compression example

For example, consider an image containing plain black text on a solid white background. There will be many long runs of white pixels in the blank space, and many short runs of black pixels within the text. A hypothetical scan line, with B representing a black pixel and W representing white, might read as follows:

```
    WWWWWWWWWWBBWWWWWBWWWWWWWWWWW

```

With a run-length encoding (RLE) data compression algorithm applied to the above hypothetical scan line, it can be rendered as follows:

```
    10W2B5W1B11W

```

The run-length code represents the original 30 characters in only 13.

##### <a class="anchor" id="bkmrk--3"></a>RLE Compression in SC

You can take advantage of using the RLE compression on a bitmap by setting an appropriate pair of converter and format for its bitmap profile as described in the SceneComposer documentation in the <span style="color: rgb(230, 126, 35);">[Bitmap Profile](https://doc316en.candera.eu/books/solution-handling/page/bitmap-profile)</span> chapter.

####   
**Color Look-Up Table**

##### <a class="anchor" id="bkmrk--4"></a>Description

A **color lookup table** (CLUT) is a table which associates a numeric pixel value with a color to be displayed on the output device. The color is typically specified as a mixture of varying levels of alpha, red, green, and blue, and thus a color lookup table will usually contain three or four components for each possible pixel value. The number of entries in the palette determines the maximum number of colours which can appear simultaneously in the bitmap. Changes to the palette affect the whole image at once and can be used to produce special effects which would be much slower to produce by updating pixels.

##### <a class="anchor" id="bkmrk--5"></a>CLUT Example

For instance, if a CLUT bitmap has a palette of 256 available colors, the index can be represented by an 8-bit value. The color table is then used to lookup a corresponding 24-bit color value (eight bits of red, green, and blue). Thus, comparing to a full RGB color bitmap, the CLUT bitmap size is roughly one-third.

<div drawio-diagram="1858"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676624256.png" alt=""/></div>

<div class="contents" id="bkmrk--0"><div class="contents"><div class="textblock">  
</div></div></div>The key to the efficiency of the indexed color approach is limiting the number of colors that can be represented.

##### <a class="anchor" id="bkmrk--7"></a>CLUT Compression in SC

In order to use CLUT compression, set the bitmap with a bitmap profile that uses an appropriate converter and one of the 72 preset CLUT compressions as format. Please consult in the SceneComposer documentation the <span style="color: rgb(230, 126, 35);">[Bitmap Profile](https://doc316en.candera.eu/books/solution-handling/page/bitmap-profile)</span> chapter for more details.

####   
**Erricson Texture Compression**

##### <a class="anchor" id="bkmrk--8"></a>Description

**Ericsson Texture Compression** (ETC) is a lossy texture compression scheme which was mandated as part of the OpenGL ES specification for the versions **3.0** and **4.3**. The original 'ETC1' compression scheme provides 6x compression of 24-bit RGB data and it does not support the compression of images with Alpha components. 'ETC2' is an updated version of 'ETC1' which offers higher quality than its predecessor and also introduces support for alpha pixels and R-/RG- textures.

ETC2 allows for more textures to fit in video memory, leads to less traffic on the bus for higher performance and lower power consumption, and it becomes cheaper to transit textures over networks.

The following ETC2 codecs are supported in [Candera](http://dev.doc.cgistudio.at/APILINK/namespace_candera.html "[DataBinding_RefTypeSample]"):

<div class="contents" id="bkmrk-candera%3A%3Abitmap%3A%3Aetc"><div class="contents"><div class="textblock">- [Candera::Bitmap::Etc2CompressedRgbPixelFormat](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_bitmap.html#a0028006b9fd5b6e630bc6aca572603cba46051977a6b00299db944cb2b398fd2f "4 bpp compressed RGB") : Compresses RGB888 data.
- [Candera::Bitmap::Etc2EacCompressedRgbaPixelFormat](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_bitmap.html#a0028006b9fd5b6e630bc6aca572603cba1e1416879d629186bb86392df53fb873 "8 bpp compressed RGBA") : Compresses RGBA8888 data with full alpha support.
- [Candera::Bitmap::Etc2Alpha1CompressedRgbaPixelFormat](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_bitmap.html#a0028006b9fd5b6e630bc6aca572603cba7d473bd019630a4cfd4153ccb30e4521 "4 bpp compressed RGBA with binary Alpha values") : Compresses RGBA data where pixels are either fully transparent or fully opaque.

</div></div></div>sRGB variants of the above codecs are also available.

EAC is built on the same principles as ETC1/ETC2 but is used for one- or two-channel data. The following EAC codecs are supported:

<div class="contents" id="bkmrk-candera%3A%3Abitmap%3A%3Aeac"><div class="contents"><div class="textblock">- [Candera::Bitmap::EacCompressedUnsignedRPixelFormat](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_bitmap.html#a0028006b9fd5b6e630bc6aca572603cba447be8300c1f43a03411c80e5ed302cf "4 bpp compressed single channel unsigned R format") : 4 bpp compressed single channel unsigned R format
- [Candera::Bitmap::EacCompressedSignedRPixelFormat](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_bitmap.html#a0028006b9fd5b6e630bc6aca572603cbac2fb78a1508e725fcbc20ceb8d57d7cc "4 bpp compressed single channel signed R format (can preserve 0 exactly)") : 4 bpp compressed single channel signed R format (can preserve 0 exactly)
- [Candera::Bitmap::EacCompressedUnsignedRGPixelFormat](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_bitmap.html#a0028006b9fd5b6e630bc6aca572603cba1082969c6760b1bac6f2b8293e861283 "8 bpp compressed two channel unsigned RG format") : 8 bpp compressed two channel unsigned RG format
- [Candera::Bitmap::EacCompressedSignedRGPixelFormat](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_bitmap.html#a0028006b9fd5b6e630bc6aca572603cbaf0c9b02e215af0f20d0b6089433f8ce8 "8 bpp compressed two channel signed RG format (can preserve 0 exactly)") : 8 bpp compressed two channel signed RG format (can preserve 0 exactly)

</div></div></div>##### <a class="anchor" id="bkmrk--9"></a>ETC2/EAC Compression in SC

Please consult in the SceneComposer documentation the chapter <span style="color: rgb(230, 126, 35);">[Import .KTX Image Format](https://doc316en.candera.eu/link/1101#bkmrk-import-file-formats)</span>, to find out how to generate and import ETC2/EAC compressed textures.

# Drawcall Batching/Geometry Instancing

#### <a class="anchor" id="bkmrk--7"></a>Description

This chapter describes how Candera's Drawcall Batching utilizes Geometry Instancing and how to set it up.

#### **Introduction**

OpenGL ES3.0 introduced a feature called Geometry Instancing. With this feature, a vertex buffer can be drawn several times using a single draw call. This single draw call uses exactly one shader and render state for all instances of that vertex buffer. The instances can have different shader parameters to individually customize their appearance on screen. Basically, this feature renders multiple copies of the same mesh at once, with the ability to parameterize each copy.

##### <a class="anchor" id="bkmrk--8"></a>Use Case

Whenever objects share a mesh, render state, shader and textures, these are potential candidates for geometry instancing. E.g. trees that only have a different size and color, houses which share the same shader using a uniform as an offset for a shared texture atlas, street lamps, or any other recurring or repeating geometry that only differs in shader parameters is a use case for geometry instancing.

##### <a class="anchor" id="bkmrk--9"></a>Motivation

Submitting drawcalls to the GPU is a relatively slow operation due to the necessary overhead caused by OpenGL and the driver. When drawing thousands of small objects individually, chances are that this overhead is leaving the GPU underutilized, and thus becoming a bottleneck. In such a scenario, batching several objects together to be submitted in a single drawcall decreases the total CPU overhead to be performed, which in turn increases overall performance.

<div class="contents" id="bkmrk-the-gpu-still-has-to"><div class="textblock"><dl class="note"><dt></dt><dd><p class="callout info">The GPU still has to perform the same amount of work, so if the bottleneck of your application is the GPU (e.g. pixel or vertex operations are the limiting factor), don't expect significant performance gains by using geometry instancing.</p>

</dd></dl></div></div>####   
**Geometry Instancing and Shaders**  


Dedicated shaders are required to utilize geometry instancing. In a shader the reserved keyword *gl\_InstanceID* represents the index of the instance currently being rendered. This index can be used to fetch instance specific parameters from arrays of uniforms.

Example of a geometry instancing vertex shader:

```
/* Uniforms */
#define MAX_INSTANCE_COUNT 100                 // Used for the size of the uniform arrays
uniform mat4 u_MVPMatrix[MAX_INSTANCE_COUNT];  // Model-View-Projection matrices for each instance
uniform vec4 u_Color[MAX_INSTANCE_COUNT];      // Color for each instance

/* Attributes */
in vec4 a_Position;

/* Varyings */
out mediump vec4 v_Color;

void main(void)
{
    /* Transform vertex into world space using the MVP matrix of the instance indexed by gl_InstanceID */
    gl_Position = u_MVPMatrix[gl_InstanceID] * a_Position;

    /* Pass the color of the instance indexed by gl_InstanceID to the pixel shader */
    v_Color = u_Color[gl_InstanceID];
}
```

The pixel shader for the vertex shader above:

```
in mediump vec4 v_Color;
out mediump vec4 FragColor;

void main(void)
{    
    FragColor = v_Color;
}
```

<div class="contents" id="bkmrk-opengl-es3.0-pixel-s"><div class="contents"><div class="textblock"><div class="fragment">  
</div><dl class="note"><dt></dt><dd><p class="callout info">OpenGL ES3.0 pixel shaders can only index uniform arrays using a constant index. Therefore the vertex shader has to index and pass any uniforms required by the pixel shader.</p>

</dd></dl></div></div></div>This shader uses a different color and model view projection matrix for each instance of the mesh. It supports drawing of up to 100 (MAX\_INSTANCE\_COUNT) instances. Therefore the model view projection matrix array and the color array have a size of 100 to hold the individual values for each instance. The maximum array size that can be used depends on the total number of uniforms in the shader as well as the target platform.

<div class="contents" id="bkmrk-array-sizes-that-are"><div class="contents"><div class="textblock"><dl class="note"><dt></dt><dd><p class="callout info">Array sizes that are too big for the platform will not throw an error during shader compilation, but only during linking the shader. Therefore you have to export shader binaries to verify if the shader can be used on your target platform.</p>

</dd></dl></div></div></div>#### **Geometry Instancing in Candera**  


Candera does not expose geometry instancing explicitly, instead it is used automatically (if possible). This approach is called **Drawcall Batching**.   
After renderable objects have been culled and sorted (ideally by the BatchOrderCriterion to produce as big sequences of batchable objects as possible), the Renderer identifies sequences of objects that can be batched, and submits those objects in a single drawcall using geometry instancing. Each such sequence is a batch. Each batch corresponds to one draw call.

##### <a class="anchor" id="bkmrk--10"></a>Prerequisites for Drawcall Batching

The following list of prerequisites must be met to facilitate draw call batching in [Candera](http://dev.doc.cgistudio.at/APILINK/namespace_candera.html "[DataBinding_RefTypeSample]"):

<div class="contents" id="bkmrk-the-target-platform-"><div class="contents"><div class="textblock">- The target platform must support geometry instancing (i.e. OpenGL ES3.0 or better).
- The object must be a Mesh or PointSprite (Billboard, LineList, MorphingMesh are currently not supported).
- The object must have an Appearance.
- The Appearance must not be a multi-pass appearance.
- The Appearance must have a Shader with a maximum instance count bigger than 1. I.e. the shader supports instancing.
- The Appearance must have a ShaderParamSetter.
- The ShaderParamSetter must support instancing. (Candera's ShaderParamSetter and GenericShaderParamSetter support instancing. Existing custom AbstractShaderParamSetter implementations will need to be adapted to support instancing.) 
    - If a GenericShaderParamSetter is used with lights activation enabled, the light coordinate space must be World space.
- Objects to be batched must share: 
    - the VertexBuffer
    - the RenderMode
    - the Shader
    - the Textures

</div></div></div><div class="contents" id="bkmrk-if-objects-share-an-"><div class="contents"><div class="textblock"><dl class="note"><dd><p class="callout info">If objects share an Appearance, they automatically share the RenderMode, Shader, and Textures, too.</p>

</dd></dl></div></div></div>##### <a class="anchor" id="bkmrk--11"></a>How to increase the Drawcall Batching rate.

Share as much vertex buffers and appearances between objects as possible. If sharing the appearance is not possible (e.g. because different materials, and/or shader parameter setters have to be used, which results in different appearances), share as much shaders, render modes and textures as possible.

The Renderer does not alter the order of contents of RenderOrderBins. In order to maximize the drawcall batching rate (i.e. the amount of objects that are batched versus the total amount of objects), objects have to be sorted by the criteria matching the prerequisites listed above. Candera'a BatchOrderCriterion offers two sorting modes to facilitate batching:

<div class="contents" id="bkmrk-sort-by-appearance-s"><div class="contents"><div class="textblock">- Sort by Appearance
- Sort by Shader and RenderMode

</div></div></div>Both modes sort by the Batchable flag (used by Mesh and PointSprite), the VertexBuffex, and either Appearance or Shader plus RenderMode to produce batches.

#### **Drawcall Batching in SceneComposer**

To configure SceneComposer solutions for drawcall batching, the following steps have to be performed:

##### <a class="anchor" id="bkmrk--12"></a>Use an instanceable shader

The shader of an object must support instancing. See <span style="color: rgb(230, 126, 35);">[this section](https://doc316en.candera.eu/link/380#bkmrk-geometry-instancing--0)</span> for a detailed explanation.

If a shader was recognized as instanceable by SceneComposer, "Max Instance Count" listed in the Properties of the Shader is bigger than one. The shader in the following example is able to draw batches of up to 50 instances.

<div drawio-diagram="1848"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676622527.png" alt=""/></div>

<div class="contents" id="bkmrk--0"><div class="contents"><div class="textblock"><div class="image">  
</div></div></div></div>##### <a class="anchor" id="bkmrk--14"></a>Configure the Uniform Setter

If the shader uses lighting, the Light Coordinate Space must be set to World.

<div drawio-diagram="1849"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676622549.png" alt=""/></div>

<div class="contents" id="bkmrk--2"><div class="contents"><div class="textblock"><div class="image">  
</div></div></div></div>##### <a class="anchor" id="bkmrk--16"></a>Share Assets

To utilize drawcall batching, vertex buffers, shaders, render modes and textures have to be shared as detailed in <span style="color: rgb(230, 126, 35);">[this section](#bkmrk-geometry-instancing--0)</span>.

SceneComposer offers the option to optimize asset usage by identifying assets that are identical and substituting these assets by a single shared instance. After selecting a node or a group, and pressing the right mouse button, the following context menu will appear:

<div drawio-diagram="1850"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676622577.png" alt=""/></div>

<div class="contents" id="bkmrk-selecting-%22node-atta"><div class="contents"><div class="textblock"><div class="image">Selecting "Node Attachment Optimization" will launch the following window, where you can select which assets should be optimized, and initiate the optimization:  
</div><div class="image"><div drawio-diagram="1851"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676622590.png" alt=""/></div>

</div></div></div></div><div class="contents" id="bkmrk--4"><div class="contents"><div class="textblock"><div class="image">  
</div></div></div></div>##### <a class="anchor" id="bkmrk--19"></a>Sort Render Order Bins using the Batch Order Sort Criterion

To maximize the [batching rate](http://dev.doc.cgistudio.at/APILINK/_p_i_d__a_p_p_d_e_v_t_u_t_chapter_09_drawcall_batching_03.html#BatchingRate), use "Batch Order" as the Render Order Bin's sort criterion.

<div drawio-diagram="1852"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676622607.png" alt=""/></div>

<div class="contents" id="bkmrk-if-the-scene-uses-a-"><div class="contents"><div class="textblock">If the scene uses a lot of different appearances (e.g. with different Materials), that share a shader, render mode, and textures, the batch order criterion "SortByShaderAndRenderMode" might achieve a better batching rate then "SortByAppearance". Use the Renderer Statistics to verify which criterion works best with the given content.  
</div></div></div><div class="contents" id="bkmrk-a-render-strategy-se"><div class="contents"><div class="textblock"><dl class="note"><dd><p class="callout info">A Render Strategy set on a camera can influence batching. E.g. the Occlusion Culling, and the Benchmark Render Strategy do not utilize drawcall batching due to their specific needs.</p>

</dd><dd></dd></dl></div></div></div>#####   


##### <a class="anchor" id="bkmrk--21"></a>Renderer Statistics

The Renderer Statistics window (which can be opened via View-&gt;Renderer Statistics), provides per frame information about what is being drawn by the cameras in the current scene. The values are updated in realtime, and directly correspond to the rendering performed in the "Display" window.

<div drawio-diagram="1853"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676622641.png" alt=""/></div>

<div class="contents" id="bkmrk-in-this-example-231-"><div class="contents"><div class="textblock"><div class="image">In this example 231 cubes are rendered using 5 draw calls. All 231 cubes are batched (i.e. instanced), therefore they are counted as "batched draw calls".  
</div></div></div></div>

# Courier Specific

#### **MFR - Multi-Frequency Rendering in Courier**   


Multi-Frequency rendering in [Courier](http://dev.doc.cgistudio.at/APILINK/namespace_courier.html) can be used to create custom sort criteria for the render jobs.

By default, the [Courier::RenderJobStrategy](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_render_job_strategy.html) sorts them like this:

<div class="contents" id="bkmrk-offscreen-render-job"><div class="contents"><div class="textblock">- offscreen render jobs before Display render jobs.
- 2d render jobs before 3d render jobs
- clear render jobs before normal view render jobs
- lower camera sequence number before higher camera sequence number

</div></div></div>One can create a custom sort criteria, simply by deriving from [Courier::RenderJobStrategy](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_render_job_strategy.html) and then use the [Courier::Renderer::SetRenderJobStrategy()](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_renderer.html#a2f24a34cfa676ab7fd71ca48edc4f5f3 "Set a custom RenderJobStrategy.") method to use this custom one.IE: SampleApp.cpp mRenderer.SetRenderJobStrategy(CANDERA\_NEW(PriorityRenderJobStrategy)(1000));

For example, PriorityRenderStrategy class uses such a custom sort criteria.

In this sample, the PriorityRenderStrategy demonstrates the ability to use the Renderer to sort the render targets depending on the layer they are on, and the sequence number of the associated camera.

```
bool PriorityRenderJobStrategy::IsPriorityRenderJob(const <a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_render_job.html">Courier::RenderJob</a>& renderJob) const
{
    bool res;
    if (renderJob.IsClear()) {
        res = IsPriorityRenderTarget(renderJob.GetGdu());
        return res;
    }
    res = GetRenderJobCameraSequenceNumber(renderJob) <= m_lastPriorityCameraSequenceNumber;
    return res;
}

// ------------------------------------------------------------------------
bool PriorityRenderJobStrategy::IsPriorityRenderTarget(<a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_gdu.html">Courier::Gdu</a>* gdu) const
{
    for (FeatStd::Int i = 0; i < m_priorityRenderTargets.Size(); ++i) {
        if (gdu == m_priorityRenderTargets[i]) {
            return true;
        }
    }
    return false;
}
```

Also as you can see in RenderTargetPerformanceData class, we can compute the cost of rendering a frame and see how many frame drops we had.

The PriorityRenderStrategy uses two other classes, PriorityCamera2DRenderStrategy and PriorityCamera3DRenderStrategy which are derived from RendererListenerBase, and [Candera::Camera2DRenderStrategy](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_camera2_d_render_strategy.html "The abstract class Camera2DRenderStrategy is intended to be derived in order to tell the Renderer2D...") and these classes compute the render cost for each node.

Example of the application running:

<div drawio-diagram="1824"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676621611.png" alt=""/></div>

<div class="contents" id="bkmrk--0"><div class="contents"><div class="textblock"><div class="image">  
</div><div class="image">  
</div></div></div></div>As you can see, the FPS is kept the same for all the layers, but the drops vary depending on the Layer/Nodes/Camera Sequence Number of each render target, some of the render jobs being skipped by the custom sort criteria in the PriorityRenderStrategy class.

In the sample output, red arrows mark skipped render jobs:

<div drawio-diagram="1825"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676621631.png" alt=""/></div>

<div class="contents" id="bkmrk--2"><div class="contents"><div class="textblock"><div class="image">  
</div></div></div></div>##### <a class="anchor" id="bkmrk--17"></a>SceneComposer solution

In this demo application, there are three layers: Layer0, Layer1 and Layer2 displayed bellow:

<div drawio-diagram="1827"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676621655.png" alt=""/></div>

<div class="contents" id="bkmrk--4"><div class="contents"><div class="textblock"><div class="image">  
</div></div></div></div>For Layer 2 – which has the most content – the backgrounds, the respective cameras have the highest Sequence Number to have priority being rendered.

<div drawio-diagram="1828"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676621683.png" alt=""/></div>

<div class="contents" id="bkmrk--6"><div class="textblock"><div class="image">  
</div></div></div>#### **Invalidation**   


##### <a class="anchor" id="bkmrk--20"></a>Description

[Courier](http://dev.doc.cgistudio.at/APILINK/namespace_courier.html) introduces an invalidation mechanism by providing [Courier::FrameworkWidget::Invalidate](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_framework_widget.html#a40c3fcf4c499f73e8e9156bef1f78a79 "Invalidates the parent view.") and [Courier::View::Invalidate](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_view.html#ab0c2b9e33adfb550d0ad840d082b1955) methods, which shall be called if ViewScenes Candera::Camera(s) shall be rendered. Only enabled and invalidated cameras will be rendered. Cameras can be enabled/disabled by sending the appropriate [Courier::ActivationReqMsg](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_activation_req_msg.html) or by manually maintaining the state of the cameras via widget implementation.

The invalidation of the cameras causes appending a [Courier::RenderJob](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_render_job.html) to a [Courier::RenderJobs](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_render_jobs.html) array inside the [Courier::Renderer](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_renderer.html). This array is then used for rendering the cameras when [Courier::RenderComponent](http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___f_o_u_n_d_a_t_i_o_n.html#ga111beafd1fd94fe52d99eda8c752bcbf "RenderComponent renders both 2D and 3D Views.") executes the Render method. If the render counter of a RenderJob reaches 0 then the RenderJob is removed from the array of RenderJobs. If a new RenderJob is appended with an already existing RenderJob for this camera, the older entry will be removed.

2D and 3D RenderJobs are processed in their own arrays. This is necessary because of above threading configuration scenarios.   
Every Candera::Rendertarget used by a rendered camera will be swapped once after rendering the cameras.

A more specific method of invalidation is the usage of the methods:

<div class="contents" id="bkmrk-courier%3A%3Aviewscene2d"><div class="contents"><div class="textblock">- [Courier::ViewScene2D::Invalidate](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_view_scene2_d.html#aa5d29150c17c8b7c3029229f323c20d3)([Candera::Camera2D](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_camera2_d.html "A camera defines the view to the scene. At least one Camera2D has to be added to a 2D scene graph and...") \* invalidatedCamera, UInt8 renderCounter = cDefaultRenderCounter)
- [Courier::ViewScene3D::Invalidate](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_view_scene3_d.html#afe6364fea300839ec5c7147212cc8fb2)([Candera::Camera](http://dev.doc.cgistudio.at/APILINK/class_candera_1_1_camera.html "A Camera provides Modelview and Projection matrices. Camera is a Transformable.* The eye point is set...") \* invalidatedCamera, UInt8 renderCounter = cDefaultRenderCounter)

</div></div></div>Those methods allow invalidating the specified cameras (not necessarily all cameras of a view) and might also be used in the widget implementations. The widget has therefore use method [Courier::FrameworkWidget::GetParentView](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_framework_widget.html#a54ff7d5327313cf9350937c0b2868c0c "Returns the parent view."), cast the returned pointer to ViewScene2D or ViewScene3D and then call the appropriate 2D or 3D Invalidation method.

##### <a class="anchor" id="bkmrk--21"></a>Update &amp; Invalidation Sample

For example the BindeableValueWidget in our GettingStarted App invalidates if the bound value has changed and it shall be redrawn.

```
void <a class="code" href="http://dev.doc.cgistudio.at/APILINK/class_bindable_value_widget_base.html#a5da105c5b7bcdbde7322baa16b036906">BindableValueWidget::OnChanged</a>(Candera::UInt32 propertyId)
{
    if(!mBuffered) {
        if(propertyId == ValuePropertyId) {
            UpdateValue(GetValue());
        }
        <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___c_o_u_r_i_e_r___v_i_s_u_a_l_i_z_a_t_i_o_n.html#ggaf0e93dc4242f607c3c8d13dafd036af9a7e58b417e215e88881554ef892d19906">Invalidate</a>();
    }
}
```

<div class="contents" id="bkmrk--7"><div class="contents"><div class="textblock"><div class="fragment">  
</div>---

</div></div></div>##### <a class="anchor" id="bkmrk--22"></a>Invalidation in General

Most views are not overlapping, so there is no dependency between the displayed view. However, depending on the design, this may not always be the case.

The following examples demonstrate various combinations of overlapping views and their dependencies regarding invalidation:

##### <a class="anchor" id="bkmrk--23"></a>Example 1

<div class="contents" id="bkmrk-whenever-view2-is-in"><div class="contents"><div class="contents"><div class="textblock"><table border="0" style="width: 100%;"><tbody><tr><td style="width: 37.3334%;">[![invalidation1.png](https://doc316en.candera.eu/uploads/images/gallery/2023-02/scaled-1680-/invalidation1.png)](https://doc316en.candera.eu/uploads/images/gallery/2023-02/invalidation1.png)

</td><td style="vertical-align: top; width: 62.6666%;" valign="top">Whenever View2 is invalidated, View1 must be invalidated too, because they are overlapping. View3 has to be invalidated as well, because it is overlapping with View2.

<table border="0"><tbody><tr><td colspan="3">View2 is invalidated</td></tr><tr><td>-&gt;</td><td colspan="2">Overlap with View1</td></tr><tr><td>-&gt;</td><td colspan="2">View 1 must be invalidated</td></tr><tr><td>  
</td><td>-&gt;</td><td>Overlap with View3</td></tr><tr><td>  
</td><td>-&gt;</td><td>View3 must be invalidated</td></tr></tbody></table>

</td></tr></tbody></table>

</div></div></div></div><div drawio-diagram="1836"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676621892.png" alt=""/></div>

<div class="contents" id="bkmrk--9"><div class="contents"><div class="textblock">  
</div></div></div>When a ViewContainer ("Folder" in SceneComposer) is invalidated, all its child views are invalidated.  
View1-3 can set an invalidation dependency to the ViewGroup "Folder" to implement the mutual invalidation.

##### <a class="anchor" id="bkmrk--25"></a>Example 2

This is a possible solution for a shared background: Split the background into multiple views.

<div class="contents" id="bkmrk-view2-is-invalidated"><div class="contents"><div class="contents"><div class="textblock"><table border="1" style="border-collapse: collapse; width: 100%; border-width: 0px;"><tbody><tr><td style="width: 42.507%; border-width: 0px;">[![invalidation3.png](https://doc316en.candera.eu/uploads/images/gallery/2023-02/scaled-1680-/invalidation3.png)](https://doc316en.candera.eu/uploads/images/gallery/2023-02/invalidation3.png)

</td><td style="vertical-align: top; width: 57.493%; border-width: 0px;" valign="top">View2 is invalidated  
-&gt; Overlap with View 1.1  
-&gt; View 1.1 must be invalidated  
  
View 3 is invalidated  
-&gt; Overlap with View 1.2  
-&gt; View 1.2 must be invalidated  
</td></tr></tbody></table>

</div></div></div></div><div drawio-diagram="1838"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676621966.png" alt=""/></div>

<div class="contents" id="bkmrk--11"><div class="contents"><div class="textblock">  
</div></div></div>##### <a class="anchor" id="bkmrk--27"></a>Example 3

Sometimes overlap can not be avoided because of the design.

<div class="contents" id="bkmrk-an-invalidation-depe"><div class="contents"><div class="textblock"><table border="1" style="border-collapse: collapse; width: 100%; border-width: 0px;"><tbody><tr><td style="width: 41.1797%; border-width: 0px;">[![invalidation5.png](https://doc316en.candera.eu/uploads/images/gallery/2023-02/scaled-1680-/invalidation5.png)](https://doc316en.candera.eu/uploads/images/gallery/2023-02/invalidation5.png)

</td><td style="vertical-align: top; width: 58.8203%; border-width: 0px;" valign="top">An invalidation dependency between all 3 views exists.

**Possible solution:**  
Use multiple hardware layers if available.

If only 1 hardware layer is available, invalidation dependencies must be set.

</td></tr></tbody></table>

</div></div></div><div drawio-diagram="1840"><img src="https://doc316en.candera.eu/uploads/images/drawio/2023-02/drawing-4-1676622017.png" alt=""/></div>

<div class="textblock" id="bkmrk--13"></div><div class="textblock" id="bkmrk--14"></div>#### **Wakeup Render Mechanism** 

##### <a class="anchor" id="bkmrk--29"></a>Description

[Courier::RenderConfiguration::UseWakeUpRenderMechanism](http://dev.doc.cgistudio.at/APILINK/class_courier_1_1_render_configuration.html#a0d6faf01325c97dd10e92aaf12fc9815): The default value for this is false. If this is set to true, each widget should call WakeUpAllRenderComponents() whenever a property setter is called. Otherwise the Update method will not be called if the RenderComponent is currently in sleep mode. If implemented correctly this setting will result in the best possible performance optimization, therefore it can be recommended.