2 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/update/manager/prepare-render-instructions.h>
22 #include <dali/public-api/shader-effects/shader-effect.h>
23 #include <dali/integration-api/debug.h>
24 #include <dali/internal/event/actors/layer-impl.h> // for the default sorting function
25 #include <dali/internal/update/effects/scene-graph-material.h>
26 #include <dali/internal/update/geometry/scene-graph-geometry.h>
27 #include <dali/internal/update/node-attachments/scene-graph-renderer-attachment.h>
28 #include <dali/internal/update/resources/resource-manager-declarations.h>
29 #include <dali/internal/update/manager/sorted-layers.h>
30 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
31 #include <dali/internal/update/node-attachments/scene-graph-renderable-attachment.h>
32 #include <dali/internal/update/nodes/scene-graph-layer.h>
33 #include <dali/internal/render/common/render-item.h>
34 #include <dali/internal/render/common/render-tracker.h>
35 #include <dali/internal/render/common/render-instruction.h>
36 #include <dali/internal/render/common/render-instruction-container.h>
37 #include <dali/internal/render/shaders/scene-graph-shader.h>
38 #include <dali/internal/render/renderers/scene-graph-renderer.h>
42 #if defined(DEBUG_ENABLED)
43 Debug::Filter* gRenderListLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RENDER_LISTS");
57 * Set flags for opaque renderlist
58 * @param renderList to set the flags to
59 * @param transparentRenderersExist is true if there is transparent renderers in this layer
60 * @param stencilRenderablesExist is true if there are stencil renderers on this layer
61 * @param depthTestDisabled whether depth test is disabled.
63 inline void SetOpaqueRenderFlags( RenderList& renderList, bool transparentRenderersExist, bool stencilRenderablesExist, bool depthTestDisabled )
65 //@todo MESH_REWORK Move RequiresDepthTest from render thread object to update thread object
67 renderList.SetInterleave(transparentRenderersExist);
69 // Special optimization if depth test is disabled or if only one opaque rendered in the layer (for example background image)
70 // and this renderer does not need depth test against itself (e.g. mesh)
71 // and if this layer has got exactly one opaque renderer
72 // and this renderer is not interested in depth testing
73 // (i.e. is an image and not a mesh)
74 if ( ( renderList.Count() == 1 ) &&
75 ( !transparentRenderersExist ) &&
76 ( !renderList.GetRenderer( 0 )->RequiresDepthTest() ) )
78 // no need to enable depth test or clear depth buffer
79 // if there's something transparent already rendered by previous layers,
80 // this opaque renderer will correctly draw on top of them since no depth test
81 renderList.ClearFlags();
82 renderList.SetInterleave(false);
84 else if( depthTestDisabled )
86 renderList.ClearFlags();
90 // Prepare for rendering multiple opaque objects
91 unsigned int flags = RenderList::DEPTH_BUFFER_ENABLED | RenderList::DEPTH_WRITE | RenderList::DEPTH_CLEAR; // clear depth buffer, draw over the previously rendered layers;
93 renderList.ClearFlags();
94 renderList.SetFlags(flags);
97 if( stencilRenderablesExist )
99 renderList.SetFlags( RenderList::STENCIL_BUFFER_ENABLED );
104 * Set the transparent flags on the renderlist
105 * @param renderList to set the flags on
106 * @param opaqueRenderersExist is true if there are opaque renderers on this layer
107 * @param stencilRenderablesExist is true if there are stencil renderers on this layer
108 * @param depthTestDisabled whether depth test is disabled.
110 inline void SetTransparentRenderFlags( RenderList& renderList, bool opaqueRenderersExist, bool stencilRenderablesExist, bool depthTestDisabled )
112 renderList.ClearFlags();
113 // We don't need to write to the depth buffer, as transparent objects
114 // don't obscure each other.
116 renderList.SetInterleave(opaqueRenderersExist);
117 if ( opaqueRenderersExist && !depthTestDisabled )
119 // If there are a mix of opaque and transparent objects, the transparent
120 // objects should be rendered with depth test on to avoid background objects
121 // appearing in front of opaque foreground objects.
122 renderList.SetFlags( RenderList::DEPTH_BUFFER_ENABLED );
125 if( stencilRenderablesExist )
127 renderList.SetFlags( RenderList::STENCIL_BUFFER_ENABLED );
133 * Set flags for overlay renderlist
134 * @param renderList to set the flags for
135 * @param stencilRenderablesExist is true if there are stencil renderers on this layer
137 inline void SetOverlayRenderFlags( RenderList& renderList, bool stencilRenderablesExist )
139 if(stencilRenderablesExist)
141 renderList.SetFlags(RenderList::STENCIL_BUFFER_ENABLED);
146 * Set flags for stencil renderlist
147 * @param renderList to set the flags for
149 inline void SetStencilRenderFlags( RenderList& renderList )
151 renderList.ClearFlags();
152 renderList.SetFlags(RenderList::STENCIL_CLEAR | RenderList::STENCIL_WRITE | RenderList::STENCIL_BUFFER_ENABLED );
156 * Add a renderer to the list
157 * @param updateBufferIndex to read the model matrix from
158 * @param renderList to add the item to
159 * @param renderable attachment
160 * @param viewMatrix used to calculate modelview matrix for the item
162 inline void AddRendererToRenderList( BufferIndex updateBufferIndex,
163 RenderList& renderList,
164 RenderableAttachment& renderable,
165 const Matrix& viewMatrix,
166 SceneGraph::CameraAttachment& cameraAttachment )
168 // Check for cull against view frustum
172 const Node& parentNode = renderable.GetParent();
173 const Matrix& worldMatrix = parentNode.GetWorldMatrix( updateBufferIndex );
174 Matrix::Multiply( mvm, worldMatrix, viewMatrix );
176 if ( RendererAttachment* rendererAttachment = dynamic_cast< RendererAttachment* >( &renderable ) )
178 if ( rendererAttachment->GetMaterial().GetShader()->GeometryHintEnabled( Dali::ShaderEffect::HINT_DOESNT_MODIFY_GEOMETRY ) )
180 // Get the geometry extents for frustum checking
181 const Vector3& position = worldMatrix.GetTranslation3();
182 const Geometry& geometry = rendererAttachment->GetGeometry();
183 const Vector3& localCenter = geometry.mCenter[ updateBufferIndex ];
184 const Vector3& size = parentNode.GetSize( updateBufferIndex );
185 Vector3 center = position + ( localCenter * size );
187 // If the size components are all the same, then we can do a quick bounding sphere check
188 if ( fabsf( size.x - size.y ) <= Math::MACHINE_EPSILON_1 * size.x )
190 inside = cameraAttachment.CheckSphereInFrustum( updateBufferIndex, center, geometry.mRadius[ updateBufferIndex ] * size.x );
195 // Check against AABB of model
196 inside = cameraAttachment.CheckAABBInFrustum( updateBufferIndex, center, geometry.mHalfExtents[ updateBufferIndex ] * size );
203 // Get the next free RenderItem
204 RenderItem& item = renderList.GetNextFreeItem();
205 const Renderer& renderer = renderable.GetRenderer();
206 item.SetRenderer( const_cast< Renderer* >( &renderer ) );
207 item.SetDepthIndex( renderable.GetDepthIndex() );
209 // save MV matrix onto the item
210 Matrix& modelViewMatrix = item.GetModelViewMatrix();
211 modelViewMatrix = mvm;
216 * Add all renderers to the list
217 * @param updateBufferIndex to read the model matrix from
218 * @param renderList to add the items to
219 * @param renderable attachments
220 * @param viewMatrix used to calculate modelview matrix for the items
222 inline void AddRenderersToRenderList( BufferIndex updateBufferIndex,
223 RenderList& renderList,
224 RenderableAttachmentContainer& attachments,
225 const Matrix& viewMatrix,
226 SceneGraph::CameraAttachment& cameraAttachment )
228 DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, "AddRenderersToRenderList()\n");
230 // Add renderer for each attachment
232 const RenderableAttachmentIter endIter = attachments.end();
233 for ( RenderableAttachmentIter iter = attachments.begin(); iter != endIter; ++iter )
235 RenderableAttachment& attachment = **iter;
236 AddRendererToRenderList( updateBufferIndex, renderList, attachment, viewMatrix, cameraAttachment );
238 DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, " List[%d].renderer = %p\n", index, &(attachment.GetRenderer()));
244 * Try to reuse cached renderitems from the renderlist
245 * This avoids recalculating the model view matrices in case this part of the scene was static
246 * An example case is a toolbar layer that rarely changes or a popup on top of the rest of the stage
247 * @param layer that is being processed
248 * @param renderList that is cached from frame N-1
249 * @param attachmentList that is being used
251 inline bool TryReuseCachedRenderers( Layer& layer,
252 RenderList& renderList,
253 RenderableAttachmentContainer& attachmentList )
255 bool retValue = false;
256 size_t renderableCount = attachmentList.size();
257 // check that the cached list originates from this layer and that the counts match
258 if( ( renderList.GetSourceLayer() == &layer )&&
259 ( renderList.GetCachedItemCount() == renderableCount ) )
261 // check that all the same renderers are there. This gives us additional security in avoiding rendering the wrong attachments
262 // Attachments are not sorted, but render list is so at this stage renderers may be in different order
263 // therefore we check a combined sum of all renderer addresses
264 size_t checkSumNew = 0;
265 size_t checkSumOld = 0;
266 for( size_t index = 0; index < renderableCount; ++index )
268 RenderableAttachment* attachment = attachmentList[ index ];
269 const Renderer& renderer = attachment->GetRenderer();
270 checkSumNew += size_t( &renderer );
271 checkSumOld += size_t( renderList.GetRenderer( index ) );
273 if( checkSumNew == checkSumOld )
275 // tell list to reuse its existing items
276 renderList.ReuseCachedItems();
285 * Function which sorts render items by depth index then by instance
286 * ptrs of shader/geometry/material.
289 * @return true if left item is greater than right
291 bool CompareItems( const RendererWithSortAttributes& lhs, const RendererWithSortAttributes& rhs )
293 // @todo MESH_REWORK Consider replacing all these sortAttributes with a single long int that
294 // encapsulates the same data (e.g. the middle-order bits of the ptrs)
295 if( lhs.renderItem->GetDepthIndex() == rhs.renderItem->GetDepthIndex() )
297 if( lhs.shader == rhs.shader )
299 if( lhs.material == rhs.material )
301 return lhs.geometry < lhs.geometry;
303 return lhs.material < rhs.material;
305 return lhs.shader < rhs.shader;;
307 return lhs.renderItem->GetDepthIndex() < rhs.renderItem->GetDepthIndex();
310 * Function which sorts the render items by depth index then by Z function,
311 * then by instance ptrs of shader/geometry/material.
314 * @return true if left item is greater than right
316 bool CompareItemsWithZValue( const RendererWithSortAttributes& lhs, const RendererWithSortAttributes& rhs )
318 // @todo MESH_REWORK Consider replacing all these sortAttributes with a single long int that
319 // encapsulates the same data (e.g. the middle-order bits of the ptrs)
321 if( lhs.renderItem->GetDepthIndex() == rhs.renderItem->GetDepthIndex() )
323 if( Equals(lhs.zValue, rhs.zValue) )
325 if( lhs.shader == rhs.shader )
327 if( lhs.material == rhs.material )
329 return lhs.geometry < lhs.geometry;
331 return lhs.material < rhs.material;
333 return lhs.shader < rhs.shader;;
335 return lhs.zValue > rhs.zValue;
337 return lhs.renderItem->GetDepthIndex() < rhs.renderItem->GetDepthIndex();
340 inline void SortOpaqueRenderItems(
341 BufferIndex bufferIndex,
342 RenderList& opaqueRenderList,
344 RenderItemSortingHelper& sortingHelper )
346 const size_t renderableCount = opaqueRenderList.Count();
347 // reserve space if needed
348 const unsigned int oldcapacity = sortingHelper.size();
349 if( oldcapacity < renderableCount )
351 sortingHelper.reserve( renderableCount );
352 // add real objects (reserve does not construct objects)
353 sortingHelper.insert( sortingHelper.begin() + oldcapacity,
354 (renderableCount - oldcapacity),
355 RendererWithSortAttributes() );
359 // clear extra elements from helper, does not decrease capability
360 sortingHelper.resize( renderableCount );
363 for( size_t index = 0; index < renderableCount; ++index )
365 RenderItem& item = opaqueRenderList.GetItem( index );
367 //@todo MESH_REWORK After merge of RenderableAttachment and RendererAttachment, should instead store the renderable ptr and get the fields directly
368 layer.opaqueRenderables[index]->SetSortAttributes( bufferIndex, sortingHelper[ index ] );
370 sortingHelper[ index ].zValue = 0;
371 sortingHelper[ index ].renderItem = &item;
374 // Sort the renderers by depth index, then by instance
375 std::stable_sort( sortingHelper.begin(), sortingHelper.end(), CompareItems );
377 DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, "Sorted Opaque List:\n");
379 // Repopulate the render items in the render list based on the sorting helper
380 RenderItemContainer::Iterator renderListIter = opaqueRenderList.GetContainer().Begin();
381 for( unsigned int index = 0; index < renderableCount; ++index, ++renderListIter )
383 *renderListIter = sortingHelper[ index ].renderItem;
384 DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, " sortedList[%d] = %p\n", sortingHelper[ index ].renderItem->GetRenderer() );
389 * Add opaque renderers from the layer onto the next free render list
390 * @param updateBufferIndex to use
391 * @param layer to get the renderers from
392 * @param viewmatrix for the camera from rendertask
393 * @param cameraAttachment to use the view frustum
394 * @param transparentRenderersExist is true if there is transparent renderers in this layer
395 * @param stencilRenderablesExist is true if there are stencil renderers on this layer
396 * @param disableDepthTest is true if depth test should be disabled on this layer
397 * @param instruction to fill in
398 * @param tryReuseRenderList whether to try to reuse the cached items from the instruction
400 inline void AddOpaqueRenderers( BufferIndex updateBufferIndex,
402 const Matrix& viewMatrix,
403 SceneGraph::CameraAttachment& cameraAttachment,
404 bool transparentRenderablesExist,
405 bool stencilRenderablesExist,
406 bool disableDepthTest,
407 RenderInstruction& instruction,
408 RendererSortingHelper& sortingHelper,
409 bool tryReuseRenderList )
411 const size_t renderableCount = layer.opaqueRenderables.size();
412 RenderList& opaqueRenderList = instruction.GetNextFreeRenderList( layer.opaqueRenderables.size() );
413 opaqueRenderList.SetClipping( layer.IsClipping(), layer.GetClippingBox() );
415 // try to reuse cached renderitems from last time around
416 if( tryReuseRenderList )
418 if( TryReuseCachedRenderers( layer, opaqueRenderList, layer.opaqueRenderables ) )
420 // reset the flags as other layers might have changed
421 // opaque flags can only be set after renderers are added
422 SetOpaqueRenderFlags( opaqueRenderList, transparentRenderablesExist, stencilRenderablesExist, disableDepthTest );
426 AddRenderersToRenderList( updateBufferIndex, opaqueRenderList, layer.opaqueRenderables, viewMatrix, cameraAttachment );
428 // opaque flags can only be set after renderers are added
429 SetOpaqueRenderFlags(opaqueRenderList, transparentRenderablesExist, stencilRenderablesExist, disableDepthTest );
431 // sorting is only needed if more than 1 item
432 if( renderableCount > 1 )
434 SortOpaqueRenderItems( updateBufferIndex, opaqueRenderList, layer, sortingHelper.opaque );
439 * Sort transparent render items
440 * @param transparentRenderList to sort
441 * @param layer where the renderers are from
442 * @param sortingHelper to use for sorting the renderitems (to avoid reallocating)
444 inline void SortTransparentRenderItems( BufferIndex bufferIndex, RenderList& transparentRenderList, Layer& layer, RenderItemSortingHelper& sortingHelper )
446 const size_t renderableCount = transparentRenderList.Count();
447 // reserve space if needed
448 const unsigned int oldcapacity = sortingHelper.size();
449 if( oldcapacity < renderableCount )
451 sortingHelper.reserve( renderableCount );
452 // add real objects (reserve does not construct objects)
453 sortingHelper.insert( sortingHelper.begin() + oldcapacity,
454 (renderableCount - oldcapacity),
455 RendererWithSortAttributes() );
459 // clear extra elements from helper, does not decrease capability
460 sortingHelper.resize( renderableCount );
463 // calculate the sorting value, once per item by calling the layers sort function
464 // Using an if and two for-loops rather than if inside for as its better for branch prediction
465 if( layer.UsesDefaultSortFunction() )
467 for( size_t index = 0; index < renderableCount; ++index )
469 RenderItem& item = transparentRenderList.GetItem( index );
471 //@todo MESH_REWORK After merge of RenderableAttachment and RendererAttachment, should instead store the renderable ptr and get the fields directly
472 layer.transparentRenderables[index]->SetSortAttributes( bufferIndex, sortingHelper[ index ] );
474 // the default sorting function should get inlined here
475 sortingHelper[ index ].zValue = Internal::Layer::ZValue( item.GetModelViewMatrix().GetTranslation3() );
477 // keep the renderitem pointer in the helper so we can quickly reorder items after sort
478 sortingHelper[ index ].renderItem = &item;
483 const Dali::Layer::SortFunctionType sortFunction = layer.GetSortFunction();
484 for( size_t index = 0; index < renderableCount; ++index )
486 RenderItem& item = transparentRenderList.GetItem( index );
488 layer.transparentRenderables[index]->SetSortAttributes( bufferIndex, sortingHelper[ index ] );
489 sortingHelper[ index ].zValue = (*sortFunction)( item.GetModelViewMatrix().GetTranslation3() );
491 // keep the renderitem pointer in the helper so we can quickly reorder items after sort
492 sortingHelper[ index ].renderItem = &item;
496 // sort the renderers back to front, Z Axis point from near plane to far plane
497 std::stable_sort( sortingHelper.begin(), sortingHelper.end(), CompareItemsWithZValue );
499 // reorder/repopulate the renderitems in renderlist to correct order based on sortinghelper
500 DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, "Sorted Transparent List:\n");
501 RenderItemContainer::Iterator renderListIter = transparentRenderList.GetContainer().Begin();
502 for( unsigned int index = 0; index < renderableCount; ++index, ++renderListIter )
504 *renderListIter = sortingHelper[ index ].renderItem;
505 DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, " sortedList[%d] = %p\n", index, sortingHelper[ index ].renderItem->GetRenderer() );
510 * Add transparent renderers from the layer onto the next free render list
511 * @param updateBufferIndex to use
512 * @param layer to get the renderers from
513 * @param viewmatrix for the camera from rendertask
514 * @param opaqueRenderablesExist is true if there are opaque renderers on this layer
515 * @param stencilRenderablesExist is true if there are stencil renderers on this layer
516 * @param instruction to fill in
517 * @param sortingHelper to use for sorting the renderitems (to avoid reallocating)
518 * @param tryReuseRenderList whether to try to reuse the cached items from the instruction
520 inline void AddTransparentRenderers( BufferIndex updateBufferIndex,
522 const Matrix& viewMatrix,
523 SceneGraph::CameraAttachment& cameraAttachment,
524 bool opaqueRenderablesExist,
525 bool stencilRenderablesExist,
526 RenderInstruction& instruction,
527 RendererSortingHelper& sortingHelper,
528 bool tryReuseRenderList )
530 const size_t renderableCount = layer.transparentRenderables.size();
531 RenderList& transparentRenderList = instruction.GetNextFreeRenderList( renderableCount );
532 transparentRenderList.SetClipping( layer.IsClipping(), layer.GetClippingBox() );
534 // transparent flags are independent of the amount of transparent renderers
535 SetTransparentRenderFlags( transparentRenderList, opaqueRenderablesExist, stencilRenderablesExist, layer.IsDepthTestDisabled() );
537 // try to reuse cached renderitems from last time around
538 if( tryReuseRenderList )
540 if( TryReuseCachedRenderers( layer, transparentRenderList, layer.transparentRenderables ) )
545 transparentRenderList.SetSourceLayer( &layer );
547 AddRenderersToRenderList( updateBufferIndex, transparentRenderList, layer.transparentRenderables, viewMatrix, cameraAttachment );
549 // sorting is only needed if more than 1 item
550 if( renderableCount > 1 )
552 SortTransparentRenderItems( updateBufferIndex, transparentRenderList, layer, sortingHelper.transparent );
557 * Add overlay renderers from the layer onto the next free render list
558 * @param updateBufferIndex to use
559 * @param layer to get the renderers from
560 * @param viewmatrix for the camera from rendertask
561 * @param stencilRenderablesExist is true if there are stencil renderers on this layer
562 * @param instruction to fill in
563 * @param tryReuseRenderList whether to try to reuse the cached items from the instruction
565 inline void AddOverlayRenderers( BufferIndex updateBufferIndex,
567 const Matrix& viewMatrix,
568 SceneGraph::CameraAttachment& cameraAttachment,
569 bool stencilRenderablesExist,
570 RenderInstruction& instruction,
571 bool tryReuseRenderList )
573 RenderList& overlayRenderList = instruction.GetNextFreeRenderList( layer.overlayRenderables.size() );
574 overlayRenderList.SetClipping( layer.IsClipping(), layer.GetClippingBox() );
575 SetOverlayRenderFlags( overlayRenderList, stencilRenderablesExist );
577 // try to reuse cached renderitems from last time around
578 if( tryReuseRenderList )
580 if( TryReuseCachedRenderers( layer, overlayRenderList, layer.overlayRenderables ) )
585 AddRenderersToRenderList( updateBufferIndex, overlayRenderList, layer.overlayRenderables, viewMatrix, cameraAttachment );
589 * Add stencil renderers from the layer onto the next free render list
590 * @param updateBufferIndex to use
591 * @param layer to get the renderers from
592 * @param viewmatrix for the camera from rendertask
593 * @param instruction to fill in
594 * @param tryReuseRenderList whether to try to reuse the cached items from the instruction
596 inline void AddStencilRenderers( BufferIndex updateBufferIndex,
598 const Matrix& viewMatrix,
599 SceneGraph::CameraAttachment& cameraAttachment,
600 RenderInstruction& instruction,
601 bool tryReuseRenderList )
603 RenderList& stencilRenderList = instruction.GetNextFreeRenderList( layer.stencilRenderables.size() );
604 stencilRenderList.SetClipping( layer.IsClipping(), layer.GetClippingBox() );
605 SetStencilRenderFlags( stencilRenderList );
607 // try to reuse cached renderitems from last time around
608 if( tryReuseRenderList )
610 if( TryReuseCachedRenderers( layer, stencilRenderList, layer.stencilRenderables ) )
615 AddRenderersToRenderList( updateBufferIndex, stencilRenderList, layer.stencilRenderables, viewMatrix, cameraAttachment );
619 * Prepare a single render instruction
620 * @param updateBufferIndex to use
621 * @param sortedLayers to prepare the instruction from
622 * @param renderTask to get the view matrix
623 * @param sortingHelper to use for sorting the renderitems (to avoid reallocating)
624 * @param renderTracker An optional render tracker object
625 * @param instructions container
627 void PrepareRenderInstruction( BufferIndex updateBufferIndex,
628 SortedLayerPointers& sortedLayers,
629 RenderTask& renderTask,
630 RendererSortingHelper& sortingHelper,
631 RenderTracker* renderTracker,
632 RenderInstructionContainer& instructions )
634 // Retrieve the RenderInstruction buffer from the RenderInstructionContainer
635 // then populate with instructions.
636 RenderInstruction& instruction = instructions.GetNextInstruction( updateBufferIndex );
637 renderTask.PrepareRenderInstruction( instruction, updateBufferIndex );
638 bool viewMatrixHasNotChanged = !renderTask.ViewMatrixUpdated();
640 const Matrix& viewMatrix = renderTask.GetViewMatrix( updateBufferIndex );
641 SceneGraph::CameraAttachment& cameraAttachment = renderTask.GetCameraAttachment();
643 const SortedLayersIter endIter = sortedLayers.end();
644 for ( SortedLayersIter iter = sortedLayers.begin(); iter != endIter; ++iter )
646 Layer& layer = **iter;
648 const bool stencilRenderablesExist( !layer.stencilRenderables.empty() );
649 const bool opaqueRenderablesExist( !layer.opaqueRenderables.empty() );
650 const bool transparentRenderablesExist( !layer.transparentRenderables.empty() );
651 const bool overlayRenderablesExist( !layer.overlayRenderables.empty() );
652 const bool disableDepthTest( layer.IsDepthTestDisabled() );
653 const bool tryReuseRenderList( viewMatrixHasNotChanged && layer.CanReuseRenderers(renderTask.GetCamera()) );
655 // Ignore stencils if there's nothing to test
656 if( stencilRenderablesExist &&
657 ( opaqueRenderablesExist || transparentRenderablesExist || overlayRenderablesExist ) )
659 AddStencilRenderers( updateBufferIndex, layer, viewMatrix, cameraAttachment, instruction, tryReuseRenderList );
662 if ( opaqueRenderablesExist )
664 AddOpaqueRenderers( updateBufferIndex,
668 transparentRenderablesExist,
669 stencilRenderablesExist,
673 tryReuseRenderList );
676 if ( transparentRenderablesExist )
678 AddTransparentRenderers( updateBufferIndex,
682 opaqueRenderablesExist,
683 stencilRenderablesExist,
686 tryReuseRenderList );
689 // @todo MESH_REWORK Mark opaque and transparent render lists as interleaveable.
690 // ( Saves having to have a pair of lists for each depth index )
692 if ( overlayRenderablesExist )
694 AddOverlayRenderers( updateBufferIndex, layer, viewMatrix, cameraAttachment, stencilRenderablesExist,
695 instruction, tryReuseRenderList );
699 instruction.mRenderTracker = renderTracker;
700 instruction.mCullMode = renderTask.GetCullMode();
702 // inform the render instruction that all renderers have been added and this frame is complete
703 instruction.UpdateCompleted();