Geometry Batching
[platform/core/uifw/dali-core.git] / dali / internal / update / manager / prepare-render-instructions.cpp
index bae7711..350d66e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include <dali/internal/update/manager/prepare-render-instructions.h>
 
 // INTERNAL INCLUDES
+#include <dali/public-api/shader-effects/shader-effect.h>
+#include <dali/public-api/actors/layer.h>
+#include <dali/integration-api/debug.h>
 #include <dali/internal/event/actors/layer-impl.h> // for the default sorting function
-#include <dali/internal/update/resources/resource-manager-declarations.h>
+#include <dali/internal/update/nodes/scene-graph-layer.h>
 #include <dali/internal/update/manager/sorted-layers.h>
 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
-#include <dali/internal/update/node-attachments/scene-graph-renderable-attachment.h>
-#include <dali/internal/update/nodes/scene-graph-layer.h>
+#include <dali/internal/update/rendering/scene-graph-texture-set.h>
+#include <dali/internal/update/resources/resource-manager-declarations.h>
 #include <dali/internal/render/common/render-item.h>
 #include <dali/internal/render/common/render-tracker.h>
 #include <dali/internal/render/common/render-instruction.h>
 #include <dali/internal/render/common/render-instruction-container.h>
-#include <dali/internal/render/renderers/scene-graph-renderer.h>
+#include <dali/internal/render/shaders/scene-graph-shader.h>
+#include <dali/internal/render/renderers/render-renderer.h>
+#include <dali/internal/render/renderers/render-property-buffer.h>
+#include <dali/internal/update/manager/geometry-batcher.h>
+
+namespace
+{
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gRenderListLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RENDER_LISTS");
+#endif
+}
 
 namespace Dali
 {
@@ -41,139 +54,103 @@ namespace SceneGraph
 {
 
 /**
- * Set flags for opaque renderlist
- * @param renderList to set the flags to
- * @param transparentRenderersExist is true if there is transparent renderers in this layer
- * @param stencilRenderablesExist is true if there are stencil renderers on this layer
- * @param depthTestDisabled whether depth test is disabled.
+ * Add a renderer to the list
+ * @param updateBufferIndex to read the model matrix from
+ * @param renderList to add the item to
+ * @param renderable Node-Renderer pair
+ * @param viewMatrix used to calculate modelview matrix for the item
+ * @param camera The camera used to render
+ * @param geometryBatcher The instance of the geometry batcher
+ * @param isLayer3d Whether we are processing a 3D layer or not
+ * @param cull Whether frustum culling is enabled or not
  */
-inline void SetOpaqueRenderFlags( RenderList& renderList, bool transparentRenderersExist, bool stencilRenderablesExist, bool depthTestDisabled )
+inline void AddRendererToRenderList( BufferIndex updateBufferIndex,
+                                     RenderList& renderList,
+                                     Renderable& renderable,
+                                     const Matrix& viewMatrix,
+                                     SceneGraph::Camera& camera,
+                                     GeometryBatcher& geometryBatcher,
+                                     bool isLayer3d,
+                                     bool cull )
 {
-  // Special optimization if depth test is disabled or if only one opaque rendered in the layer (for example background image)
-  // and this renderer does not need depth test against itself (for example a mesh actor)
-  // if this layer has got exactly one opaque renderer
-  // and this renderer is not interested in depth testing
-  // (i.e. is an image or text and not a model)
-  if ( ( (  renderList.Count() == 1 ) &&
-         (  !transparentRenderersExist ) &&
-         (  !renderList.GetRenderer( 0 )->RequiresDepthTest() ) ) ||
-       depthTestDisabled )
+  // discard renderable early if it belongs to the batch which has been consumed in during frame
+  Node* renderableNode = renderable.mNode;
+  const bool batchingValid( renderable.mRenderer->IsBatchingEnabled() && renderableNode->mBatchIndex != BATCH_NULL_HANDLE );
+  if( batchingValid && geometryBatcher.HasRendered( renderableNode->mBatchIndex ) )
   {
-    // no need to enable depth test or clear depth buffer
-    // if there's something transparent already rendered by previous layers,
-    // this opaque renderer will correctly draw on top of them since no depth test
-    renderList.ClearFlags();
+    return;
   }
-  else
-  {
-    // Prepare for rendering multiple opaque objects
-    unsigned int flags = RenderList::DEPTH_TEST | RenderList::DEPTH_WRITE | RenderList::DEPTH_CLEAR; // clear depth buffer, draw over the previously rendered layers;
 
-    renderList.ClearFlags();
-    renderList.SetFlags(flags);
-  }
+  bool inside( true );
+  const Node* batchParentNode = renderable.mNode->GetBatchParent();
+  const Node* node = ( renderable.mRenderer->IsBatchingEnabled() && batchParentNode ) ?
+        batchParentNode : renderableNode;
 
-  if( stencilRenderablesExist )
+  if ( cull && !renderable.mRenderer->GetShader().HintEnabled( Dali::Shader::Hint::MODIFIES_GEOMETRY ) )
   {
-    renderList.SetFlags( RenderList::STENCIL_TEST );
+    const Vector4& boundingSphere = node->GetBoundingSphere();
+    inside = (boundingSphere.w > Math::MACHINE_EPSILON_1000) &&
+             (camera.CheckSphereInFrustum( updateBufferIndex, Vector3(boundingSphere), boundingSphere.w ) );
   }
-}
 
-/**
- * Set the transparent flags on the renderlist
- * @param renderList to set the flags on
- * @param opaqueRenderersExist is true if there are opaque renderers on this layer
- * @param stencilRenderablesExist is true if there are stencil renderers on this layer
- * @param depthTestDisabled whether depth test is disabled.
- */
-inline void SetTransparentRenderFlags( RenderList& renderList, bool opaqueRenderersExist, bool stencilRenderablesExist, bool depthTestDisabled )
-{
-  renderList.ClearFlags();
-  // We don't need to write to the depth buffer, as transparent objects
-  // don't obscure each other.
-
-  if ( opaqueRenderersExist && !depthTestDisabled )
+  if( inside )
   {
-    // If there are a mix of opaque and transparent objects, the transparent
-    // objects should be rendered with depth test on to avoid background objects
-    // appearing in front of opaque foreground objects.
-
-    renderList.SetFlags( RenderList::DEPTH_TEST );
-  }
-
-  if( stencilRenderablesExist )
-  {
-    renderList.SetFlags( RenderList::STENCIL_TEST );
-  }
-}
-
+    if( batchingValid )
+    {
+      geometryBatcher.SetRendered( renderableNode->mBatchIndex );
+    }
 
-/**
- * Set flags for overlay renderlist
- * @param renderList to set the flags for
- * @param stencilRenderablesExist is true if there are stencil renderers on this layer
- */
-inline void SetOverlayRenderFlags( RenderList& renderList, bool stencilRenderablesExist )
-{
-  if(stencilRenderablesExist)
-  {
-    renderList.SetFlags(RenderList::STENCIL_TEST);
+    Renderer::Opacity opacity = renderable.mRenderer->GetOpacity( updateBufferIndex, *renderable.mNode );
+    if( opacity != Renderer::TRANSPARENT )
+    {
+      // Get the next free RenderItem
+      RenderItem& item = renderList.GetNextFreeItem();
+      item.mRenderer = &renderable.mRenderer->GetRenderer();
+      item.mNode = renderable.mNode;
+      item.mIsOpaque = (opacity == Renderer::OPAQUE);
+
+      if( isLayer3d )
+      {
+        item.mDepthIndex = renderable.mRenderer->GetDepthIndex();
+      }
+      else
+      {
+        item.mDepthIndex = renderable.mRenderer->GetDepthIndex() + static_cast<int>( renderable.mNode->GetDepth() ) * Dali::Layer::TREE_DEPTH_MULTIPLIER;
+      }
+      // save MV matrix onto the item
+      node->GetWorldMatrixAndSize( item.mModelMatrix, item.mSize );
+      Matrix::Multiply( item.mModelViewMatrix, item.mModelMatrix, viewMatrix );
+    }
   }
 }
 
 /**
- * Set flags for stencil renderlist
- * @param renderList to set the flags for
- */
-inline void SetStencilRenderFlags( RenderList& renderList )
-{
-  renderList.ClearFlags();
-  renderList.SetFlags(RenderList::STENCIL_CLEAR | RenderList::STENCIL_WRITE | RenderList::STENCIL_TEST);
-}
-
-/**
- * Add a renderer to the list
- * @param updateBufferIndex to read the model matrix from
- * @param renderList to add the item to
- * @param renderable attachment
- * @param viewMatrix used to calculate modelview matrix for the item
- */
-inline void AddRendererToRenderList( BufferIndex updateBufferIndex,
-                                     RenderList& renderList,
-                                     RenderableAttachment& renderable,
-                                     const Matrix& viewMatrix )
-{
-  const Renderer& renderer = renderable.GetRenderer();
-
-  // Get the next free RenderItem
-  RenderItem& item = renderList.GetNextFreeItem();
-  item.SetRenderer( const_cast< Renderer* >( &renderer ) );
-
-  // calculate MV matrix onto the item
-  Matrix& modelViewMatrix = item.GetModelViewMatrix();
-  const Matrix& worldMatrix = renderable.GetParent().GetWorldMatrix( updateBufferIndex );
-
-  Matrix::Multiply( modelViewMatrix, worldMatrix, viewMatrix );
-}
-
-/**
  * Add all renderers to the list
  * @param updateBufferIndex to read the model matrix from
  * @param renderList to add the items to
- * @param renderable attachments
+ * @param renderers to render
+ * NodeRendererContainer Node-Renderer pairs
  * @param viewMatrix used to calculate modelview matrix for the items
+ * @param camera The camera used to render
+ * @param geometryBatcher The instance of the geometry batcher
+ * @param isLayer3d Whether we are processing a 3D layer or not
+ * @param cull Whether frustum culling is enabled or not
  */
 inline void AddRenderersToRenderList( BufferIndex updateBufferIndex,
                                       RenderList& renderList,
-                                      RenderableAttachmentContainer& attachments,
-                                      const Matrix& viewMatrix )
+                                      RenderableContainer& renderers,
+                                      const Matrix& viewMatrix,
+                                      SceneGraph::Camera& camera,
+                                      GeometryBatcher* geometryBatcher,
+                                      bool isLayer3d,
+                                      bool cull)
 {
-  // Add renderer for each attachment
-  const RenderableAttachmentIter endIter = attachments.end();
-  for ( RenderableAttachmentIter iter = attachments.begin(); iter != endIter; ++iter )
+  DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, "AddRenderersToRenderList()\n");
+
+  unsigned int rendererCount( renderers.Size() );
+  for( unsigned int i(0); i<rendererCount; ++i )
   {
-    RenderableAttachment& attachment = **iter;
-    AddRendererToRenderList( updateBufferIndex, renderList, attachment, viewMatrix );
+    AddRendererToRenderList( updateBufferIndex, renderList, renderers[i], viewMatrix, camera, *geometryBatcher, isLayer3d, cull );
   }
 }
 
@@ -183,29 +160,28 @@ inline void AddRenderersToRenderList( BufferIndex updateBufferIndex,
  * An example case is a toolbar layer that rarely changes or a popup on top of the rest of the stage
  * @param layer that is being processed
  * @param renderList that is cached from frame N-1
- * @param attachmentList that is being used
+ * @param renderables list of renderables
  */
 inline bool TryReuseCachedRenderers( Layer& layer,
                                      RenderList& renderList,
-                                     RenderableAttachmentContainer& attachmentList )
+                                     RenderableContainer& renderables )
 {
   bool retValue = false;
-  size_t renderableCount = attachmentList.size();
+  size_t renderableCount = renderables.Size();
   // check that the cached list originates from this layer and that the counts match
   if( ( renderList.GetSourceLayer() == &layer )&&
       ( renderList.GetCachedItemCount() == renderableCount ) )
   {
-    // check that all the same renderers are there. This gives us additional security in avoiding rendering the wrong attachments
-    // Attachments are not sorted, but render list is so at this stage renderers may be in different order
+    // check that all the same renderers are there. This gives us additional security in avoiding rendering the wrong things
+    // Render list is sorted so at this stage renderers may be in different order
     // therefore we check a combined sum of all renderer addresses
     size_t checkSumNew = 0;
     size_t checkSumOld = 0;
     for( size_t index = 0; index < renderableCount; ++index )
     {
-      RenderableAttachment* attachment = attachmentList[ index ];
-      const Renderer& renderer = attachment->GetRenderer();
+      const Render::Renderer& renderer = renderables[index].mRenderer->GetRenderer();
       checkSumNew += size_t( &renderer );
-      checkSumOld += size_t( renderList.GetRenderer( index ) );
+      checkSumOld += size_t( &renderList.GetRenderer( index ) );
     }
     if( checkSumNew == checkSumOld )
     {
@@ -218,63 +194,87 @@ inline bool TryReuseCachedRenderers( Layer& layer,
 }
 
 /**
- * Add opaque renderers from the layer onto the next free render list
- * @param updateBufferIndex to use
- * @param layer to get the renderers from
- * @param viewmatrix for the camera from rendertask
- * @param transparentRenderersExist is true if there is transparent renderers in this layer
- * @param stencilRenderablesExist is true if there are stencil renderers on this layer
- * @param instruction to fill in
- * @param tryReuseRenderList whether to try to reuse the cached items from the instruction
+ * Function which sorts render items by depth index then by instance
+ * ptrs of shader/texture/geometry.
+ * @param lhs item
+ * @param rhs item
+ * @return true if left item is greater than right
  */
-inline void AddOpaqueRenderers( BufferIndex updateBufferIndex,
-                                Layer& layer,
-                                const Matrix& viewMatrix,
-                                bool transparentRenderablesExist,
-                                bool stencilRenderablesExist,
-                                RenderInstruction& instruction,
-                                bool tryReuseRenderList )
+bool CompareItems( const RendererWithSortAttributes& lhs, const RendererWithSortAttributes& rhs )
 {
-  RenderList& opaqueRenderList = instruction.GetNextFreeRenderList( layer.opaqueRenderables.size() );
-  opaqueRenderList.SetClipping( layer.IsClipping(), layer.GetClippingBox() );
-
-  // try to reuse cached renderitems from last time around
-  if( tryReuseRenderList )
+  if( lhs.renderItem->mDepthIndex == rhs.renderItem->mDepthIndex )
   {
-    if( TryReuseCachedRenderers( layer, opaqueRenderList, layer.opaqueRenderables ) )
+    if( lhs.shader == rhs.shader )
     {
-      // reset the flags as other layers might have changed
-      // opaque flags can only be set after renderers are added
-      SetOpaqueRenderFlags(opaqueRenderList, transparentRenderablesExist, stencilRenderablesExist, layer.IsDepthTestDisabled() );
-      return;
+      if( lhs.textureResourceId == rhs.textureResourceId )
+      {
+        return lhs.geometry < rhs.geometry;
+      }
+      return lhs.textureResourceId < rhs.textureResourceId;
     }
+    return lhs.shader < rhs.shader;
   }
-  AddRenderersToRenderList( updateBufferIndex, opaqueRenderList, layer.opaqueRenderables, viewMatrix );
-
-  // opaque flags can only be set after renderers are added
-  SetOpaqueRenderFlags(opaqueRenderList, transparentRenderablesExist, stencilRenderablesExist, layer.IsDepthTestDisabled() );
+  return lhs.renderItem->mDepthIndex < rhs.renderItem->mDepthIndex;
 }
-
 /**
- * Function which sorts based on the calculated depth values ordering them back to front
+ * Function which sorts the render items by Z function, then
+ * by instance ptrs of shader/texture/geometry.
  * @param lhs item
  * @param rhs item
  * @return true if left item is greater than right
  */
-bool SortByDepthSortValue( const RendererWithSortValue& lhs, const RendererWithSortValue& rhs )
+bool CompareItems3D( const RendererWithSortAttributes& lhs, const RendererWithSortAttributes& rhs )
 {
-  return lhs.first > rhs.first;
+  bool lhsIsOpaque = lhs.renderItem->mIsOpaque;
+  if( lhsIsOpaque ==  rhs.renderItem->mIsOpaque )
+  {
+    if( lhsIsOpaque )
+    {
+      //If both RenderItems are opaque, sort using shader, then texture then geometry
+      if( lhs.shader == rhs.shader )
+      {
+        if( lhs.textureResourceId == rhs.textureResourceId )
+        {
+          return lhs.geometry < rhs.geometry;
+        }
+        return lhs.textureResourceId < rhs.textureResourceId;
+      }
+      return lhs.shader < rhs.shader;
+    }
+    else
+    {
+      //If both RenderItems are transparent, sort using z,then shader, then texture, then geometry
+      if( Equals(lhs.zValue, rhs.zValue) )
+      {
+        if( lhs.shader == rhs.shader )
+        {
+          if( lhs.textureResourceId == rhs.textureResourceId )
+          {
+            return lhs.geometry < rhs.geometry;
+          }
+          return lhs.textureResourceId < rhs.textureResourceId;
+        }
+        return lhs.shader < rhs.shader;
+      }
+      return lhs.zValue > rhs.zValue;
+    }
+  }
+  else
+  {
+    return lhsIsOpaque;
+  }
 }
 
 /**
- * Sort transparent render items
- * @param transparentRenderList to sort
+ * Sort render items
+ * @param bufferIndex The buffer to read from
+ * @param renderList to sort
  * @param layer where the renderers are from
  * @param sortingHelper to use for sorting the renderitems (to avoid reallocating)
  */
-inline void SortTransparentRenderItems( RenderList& transparentRenderList, Layer& layer, RendererSortingHelper& sortingHelper )
+inline void SortRenderItems( BufferIndex bufferIndex, RenderList& renderList, Layer& layer, RendererSortingHelper& sortingHelper )
 {
-  const size_t renderableCount = transparentRenderList.Count();
+  const size_t renderableCount = renderList.Count();
   // reserve space if needed
   const unsigned int oldcapacity = sortingHelper.size();
   if( oldcapacity < renderableCount )
@@ -283,26 +283,29 @@ inline void SortTransparentRenderItems( RenderList& transparentRenderList, Layer
     // add real objects (reserve does not construct objects)
     sortingHelper.insert( sortingHelper.begin() + oldcapacity,
                           (renderableCount - oldcapacity),
-                          RendererWithSortValue( 0.0f, NULL ) );
+                          RendererWithSortAttributes() );
   }
   else
   {
     // clear extra elements from helper, does not decrease capability
     sortingHelper.resize( renderableCount );
   }
+
   // calculate the sorting value, once per item by calling the layers sort function
   // Using an if and two for-loops rather than if inside for as its better for branch prediction
   if( layer.UsesDefaultSortFunction() )
   {
     for( size_t index = 0; index < renderableCount; ++index )
     {
-      RenderItem& item = transparentRenderList.GetItem( index );
+      RenderItem& item = renderList.GetItem( index );
+
+      item.mRenderer->SetSortAttributes( bufferIndex, sortingHelper[ index ] );
+
       // the default sorting function should get inlined here
-      sortingHelper[ index ].first = Internal::Layer::ZValue(
-          item.GetModelViewMatrix().GetTranslation3(),
-          layer.transparentRenderables[ index ]->GetSortModifier() );
+      sortingHelper[ index ].zValue = Internal::Layer::ZValue( item.mModelViewMatrix.GetTranslation3() ) - item.mDepthIndex;
+
       // keep the renderitem pointer in the helper so we can quickly reorder items after sort
-      sortingHelper[ index ].second = &item;
+      sortingHelper[ index ].renderItem = &item;
     }
   }
   else
@@ -310,68 +313,84 @@ inline void SortTransparentRenderItems( RenderList& transparentRenderList, Layer
     const Dali::Layer::SortFunctionType sortFunction = layer.GetSortFunction();
     for( size_t index = 0; index < renderableCount; ++index )
     {
-      RenderItem& item = transparentRenderList.GetItem( index );
-      sortingHelper[ index ].first = (*sortFunction)(
-          item.GetModelViewMatrix().GetTranslation3(),
-          layer.transparentRenderables[ index ]->GetSortModifier() );
+      RenderItem& item = renderList.GetItem( index );
+
+      item.mRenderer->SetSortAttributes( bufferIndex, sortingHelper[ index ] );
+      sortingHelper[ index ].zValue = (*sortFunction)( item.mModelViewMatrix.GetTranslation3() ) - item.mDepthIndex;
+
       // keep the renderitem pointer in the helper so we can quickly reorder items after sort
-      sortingHelper[ index ].second = &item;
+      sortingHelper[ index ].renderItem = &item;
     }
   }
 
-  // sort the renderers back to front, Z Axis point from near plane to far plane
-  std::sort( sortingHelper.begin(), sortingHelper.end(), SortByDepthSortValue );
+  if( layer.GetBehavior() ==  Dali::Layer::LAYER_3D)
+  {
+    // sort the renderers back to front, Z Axis point from near plane to far plane
+    std::stable_sort( sortingHelper.begin(), sortingHelper.end(), CompareItems3D );
+  }
+  else
+  {
+    // sort the renderers based on DepthIndex
+    std::stable_sort( sortingHelper.begin(), sortingHelper.end(), CompareItems );
+  }
 
   // reorder/repopulate the renderitems in renderlist to correct order based on sortinghelper
-  RenderItemContainer::Iterator renderListIter = transparentRenderList.GetContainer().Begin();
+  DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, "Sorted Transparent List:\n");
+  RenderItemContainer::Iterator renderListIter = renderList.GetContainer().Begin();
   for( unsigned int index = 0; index < renderableCount; ++index, ++renderListIter )
   {
-    *renderListIter = sortingHelper[ index ].second;
+    *renderListIter = sortingHelper[ index ].renderItem;
+    DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, "  sortedList[%d] = %p\n", index, sortingHelper[ index ].renderItem->mRenderer);
   }
 }
 
 /**
- * Add transparent renderers from the layer onto the next free render list
+ * Add color renderers from the layer onto the next free render list
  * @param updateBufferIndex to use
  * @param layer to get the renderers from
  * @param viewmatrix for the camera from rendertask
- * @param opaqueRenderablesExist is true if there are opaque renderers on this layer
+ * @param camera to use the view frustum
  * @param stencilRenderablesExist is true if there are stencil renderers on this layer
  * @param instruction to fill in
  * @param sortingHelper to use for sorting the renderitems (to avoid reallocating)
+ * @param geometryBatcher the instance of the geometry batcher
  * @param tryReuseRenderList whether to try to reuse the cached items from the instruction
+ * @param cull Whether frustum culling is enabled or not
  */
-inline void AddTransparentRenderers( BufferIndex updateBufferIndex,
-                                     Layer& layer,
-                                     const Matrix& viewMatrix,
-                                     bool opaqueRenderablesExist,
-                                     bool stencilRenderablesExist,
-                                     RenderInstruction& instruction,
-                                     RendererSortingHelper& sortingHelper,
-                                     bool tryReuseRenderList )
+inline void AddColorRenderers( BufferIndex updateBufferIndex,
+                               Layer& layer,
+                               const Matrix& viewMatrix,
+                               SceneGraph::Camera& camera,
+                               bool stencilRenderablesExist,
+                               RenderInstruction& instruction,
+                               RendererSortingHelper& sortingHelper,
+                               GeometryBatcher& geometryBatcher,
+                               bool tryReuseRenderList,
+                               bool cull)
 {
-  const size_t renderableCount = layer.transparentRenderables.size();
-  RenderList& transparentRenderList = instruction.GetNextFreeRenderList( renderableCount );
-  transparentRenderList.SetClipping( layer.IsClipping(), layer.GetClippingBox() );
-  // transparent flags are independent of the amount of transparent renderers
-  SetTransparentRenderFlags( transparentRenderList, opaqueRenderablesExist, stencilRenderablesExist, layer.IsDepthTestDisabled() );
+  RenderList& renderList = instruction.GetNextFreeRenderList( layer.colorRenderables.Size() );
+  renderList.SetClipping( layer.IsClipping(), layer.GetClippingBox() );
+  renderList.SetSourceLayer( &layer );
+  renderList.SetHasColorRenderItems( true );
 
   // try to reuse cached renderitems from last time around
   if( tryReuseRenderList )
   {
-    if( TryReuseCachedRenderers( layer, transparentRenderList, layer.transparentRenderables ) )
+    if( TryReuseCachedRenderers( layer, renderList, layer.colorRenderables ) )
     {
       return;
     }
   }
-  transparentRenderList.SetSourceLayer( &layer );
 
-  AddRenderersToRenderList( updateBufferIndex, transparentRenderList, layer.transparentRenderables, viewMatrix );
+  AddRenderersToRenderList( updateBufferIndex, renderList, layer.colorRenderables, viewMatrix, camera, &geometryBatcher, layer.GetBehavior() == Dali::Layer::LAYER_3D, cull );
+  SortRenderItems( updateBufferIndex, renderList, layer, sortingHelper );
 
-  // sorting is only needed if more than 1 item
-  if( renderableCount > 1 )
+  // Setup the render flags for stencil.
+  renderList.ClearFlags();
+  if( stencilRenderablesExist )
   {
-    SortTransparentRenderItems( transparentRenderList, layer, sortingHelper );
+    // Note: SetFlags does not overwrite, it ORs, so ClearFlags() is also required.
+    renderList.SetFlags( RenderList::STENCIL_BUFFER_ENABLED );
   }
 }
 
@@ -380,20 +399,33 @@ inline void AddTransparentRenderers( BufferIndex updateBufferIndex,
  * @param updateBufferIndex to use
  * @param layer to get the renderers from
  * @param viewmatrix for the camera from rendertask
+ * @param camera to use
  * @param stencilRenderablesExist is true if there are stencil renderers on this layer
  * @param instruction to fill in
  * @param tryReuseRenderList whether to try to reuse the cached items from the instruction
+ * @param cull Whether frustum culling is enabled or not
  */
 inline void AddOverlayRenderers( BufferIndex updateBufferIndex,
                                  Layer& layer,
                                  const Matrix& viewMatrix,
+                                 SceneGraph::Camera& camera,
                                  bool stencilRenderablesExist,
                                  RenderInstruction& instruction,
-                                 bool tryReuseRenderList )
+                                 RendererSortingHelper& sortingHelper,
+                                 bool tryReuseRenderList,
+                                 bool cull )
 {
-  RenderList& overlayRenderList = instruction.GetNextFreeRenderList( layer.overlayRenderables.size() );
+  RenderList& overlayRenderList = instruction.GetNextFreeRenderList( layer.overlayRenderables.Size() );
   overlayRenderList.SetClipping( layer.IsClipping(), layer.GetClippingBox() );
-  SetOverlayRenderFlags( overlayRenderList, stencilRenderablesExist );
+  overlayRenderList.SetSourceLayer( &layer );
+  overlayRenderList.SetHasColorRenderItems( false );
+
+  //Set render flags
+  overlayRenderList.ClearFlags();
+  if(stencilRenderablesExist)
+  {
+    overlayRenderList.SetFlags(RenderList::STENCIL_BUFFER_ENABLED);
+  }
 
   // try to reuse cached renderitems from last time around
   if( tryReuseRenderList )
@@ -403,7 +435,8 @@ inline void AddOverlayRenderers( BufferIndex updateBufferIndex,
       return;
     }
   }
-  AddRenderersToRenderList( updateBufferIndex, overlayRenderList, layer.overlayRenderables, viewMatrix );
+  AddRenderersToRenderList( updateBufferIndex, overlayRenderList, layer.overlayRenderables, viewMatrix, camera, NULL, layer.GetBehavior() == Dali::Layer::LAYER_3D, cull );
+  SortRenderItems( updateBufferIndex, overlayRenderList, layer, sortingHelper );
 }
 
 /**
@@ -411,18 +444,27 @@ inline void AddOverlayRenderers( BufferIndex updateBufferIndex,
  * @param updateBufferIndex to use
  * @param layer to get the renderers from
  * @param viewmatrix for the camera from rendertask
+ * @param camera to use
  * @param instruction to fill in
  * @param tryReuseRenderList whether to try to reuse the cached items from the instruction
+ * @param cull Whether frustum culling is enabled or not
  */
 inline void AddStencilRenderers( BufferIndex updateBufferIndex,
                                  Layer& layer,
                                  const Matrix& viewMatrix,
+                                 SceneGraph::Camera& camera,
                                  RenderInstruction& instruction,
-                                 bool tryReuseRenderList )
+                                 bool tryReuseRenderList,
+                                 bool cull )
 {
-  RenderList& stencilRenderList = instruction.GetNextFreeRenderList( layer.stencilRenderables.size() );
+  RenderList& stencilRenderList = instruction.GetNextFreeRenderList( layer.stencilRenderables.Size() );
   stencilRenderList.SetClipping( layer.IsClipping(), layer.GetClippingBox() );
-  SetStencilRenderFlags( stencilRenderList );
+  stencilRenderList.SetSourceLayer( &layer );
+  stencilRenderList.SetHasColorRenderItems( false );
+
+  //Set render flags
+  stencilRenderList.ClearFlags();
+  stencilRenderList.SetFlags(RenderList::STENCIL_CLEAR | RenderList::STENCIL_WRITE | RenderList::STENCIL_BUFFER_ENABLED );
 
   // try to reuse cached renderitems from last time around
   if( tryReuseRenderList )
@@ -432,24 +474,16 @@ inline void AddStencilRenderers( BufferIndex updateBufferIndex,
       return;
     }
   }
-  AddRenderersToRenderList( updateBufferIndex, stencilRenderList, layer.stencilRenderables, viewMatrix );
+  AddRenderersToRenderList( updateBufferIndex, stencilRenderList, layer.stencilRenderables, viewMatrix, camera, NULL, layer.GetBehavior() == Dali::Layer::LAYER_3D, cull );
 }
 
-/**
- * Prepare a single render instruction
- * @param updateBufferIndex to use
- * @param sortedLayers to prepare the instruction from
- * @param renderTask to get the view matrix
- * @param sortingHelper to use for sorting the renderitems (to avoid reallocating)
- * @param renderTracker An optional render tracker object
- * @param instructions container
- */
 void PrepareRenderInstruction( BufferIndex updateBufferIndex,
                                SortedLayerPointers& sortedLayers,
                                RenderTask& renderTask,
                                RendererSortingHelper& sortingHelper,
-                               RenderTracker* renderTracker,
-                               RenderInstructionContainer& instructions )
+                               bool cull,
+                               RenderInstructionContainer& instructions,
+                               GeometryBatcher& geometryBatcher )
 {
   // Retrieve the RenderInstruction buffer from the RenderInstructionContainer
   // then populate with instructions.
@@ -458,58 +492,46 @@ void PrepareRenderInstruction( BufferIndex updateBufferIndex,
   bool viewMatrixHasNotChanged = !renderTask.ViewMatrixUpdated();
 
   const Matrix& viewMatrix = renderTask.GetViewMatrix( updateBufferIndex );
+  SceneGraph::Camera& camera = renderTask.GetCamera();
 
   const SortedLayersIter endIter = sortedLayers.end();
   for ( SortedLayersIter iter = sortedLayers.begin(); iter != endIter; ++iter )
   {
     Layer& layer = **iter;
 
-    const bool stencilRenderablesExist( !layer.stencilRenderables.empty() );
-    const bool opaqueRenderablesExist( !layer.opaqueRenderables.empty() );
-    const bool transparentRenderablesExist( !layer.transparentRenderables.empty() );
-    const bool overlayRenderablesExist( !layer.overlayRenderables.empty() );
-    const bool tryReuseRenderList( viewMatrixHasNotChanged && layer.CanReuseRenderers(renderTask.GetCamera()) );
+    const bool stencilRenderablesExist( !layer.stencilRenderables.Empty() );
+    const bool colorRenderablesExist( !layer.colorRenderables.Empty() );
+    const bool overlayRenderablesExist( !layer.overlayRenderables.Empty() );
+    const bool tryReuseRenderList( viewMatrixHasNotChanged && layer.CanReuseRenderers( &renderTask.GetCamera() ) );
 
     // Ignore stencils if there's nothing to test
     if( stencilRenderablesExist &&
-        ( opaqueRenderablesExist || transparentRenderablesExist || overlayRenderablesExist ) )
+        ( colorRenderablesExist || overlayRenderablesExist ) )
     {
-      AddStencilRenderers( updateBufferIndex, layer, viewMatrix, instruction, tryReuseRenderList );
+      AddStencilRenderers( updateBufferIndex, layer, viewMatrix, camera, instruction, tryReuseRenderList, cull );
     }
 
-    if ( opaqueRenderablesExist )
+    if ( colorRenderablesExist )
     {
-      AddOpaqueRenderers( updateBufferIndex,
-                          layer,
-                          viewMatrix,
-                          transparentRenderablesExist,
-                          stencilRenderablesExist,
-                          instruction,
-                          tryReuseRenderList );
-    }
-
-    if ( transparentRenderablesExist )
-    {
-      AddTransparentRenderers( updateBufferIndex,
-                               layer,
-                               viewMatrix,
-                               opaqueRenderablesExist,
-                               stencilRenderablesExist,
-                               instruction,
-                               sortingHelper,
-                               tryReuseRenderList );
+      AddColorRenderers( updateBufferIndex,
+                         layer,
+                         viewMatrix,
+                         camera,
+                         stencilRenderablesExist,
+                         instruction,
+                         sortingHelper,
+                         geometryBatcher,
+                         tryReuseRenderList,
+                         cull );
     }
 
     if ( overlayRenderablesExist )
     {
-      AddOverlayRenderers( updateBufferIndex, layer, viewMatrix, stencilRenderablesExist,
-                           instruction, tryReuseRenderList );
+      AddOverlayRenderers( updateBufferIndex, layer, viewMatrix, camera, stencilRenderablesExist,
+                           instruction, sortingHelper, tryReuseRenderList, cull );
     }
   }
 
-  instruction.mRenderTracker = renderTracker;
-  instruction.mCullMode = renderTask.GetCullMode();
-
   // inform the render instruction that all renderers have been added and this frame is complete
   instruction.UpdateCompleted();
 }