public void Render(Rect topRect, Matrix4x4 projection) { s_RenderSampler.Begin(); m_Stats = new ChainBuilderStats(); m_Stats.elementsAdded += m_StatsElementsAdded; m_Stats.elementsRemoved += m_StatsElementsRemoved; m_Stats.clipListCleanup += m_StatsClipListCleanup; m_Stats.transformListCleanup += m_StatsTransformListCleanup; m_Stats.visualListCleanup += m_StatsVisualListCleanup; m_StatsElementsAdded = m_StatsElementsRemoved = 0; m_StatsClipListCleanup = m_StatsTransformListCleanup = m_StatsVisualListCleanup = 0; if (atlasManager?.RequiresReset() == true) { atlasManager.Reset(); // May cause a dirty repaint } m_DirtyID++; var clearDirty = ~(RenderDataDirtyTypes.Clipping | RenderDataDirtyTypes.ClippingHierarchy); VisualElement dirty = m_FirstDirtyClipping; s_ClipProcessingSampler.Begin(); while (dirty != null) { if (dirty.renderChainData.isInChain && dirty.renderChainData.dirtyID != m_DirtyID) { Implementation.RenderEvents.ProcessOnClippingChanged(this, dirty, m_DirtyID, device, ref m_Stats); } dirty.renderChainData.dirtiedValues &= clearDirty; var old = dirty; dirty = dirty.renderChainData.nextDirtyClipping; old.renderChainData.nextDirtyClipping = null; } s_ClipProcessingSampler.End(); m_FirstDirtyClipping = m_LastDirtyClipping = null; m_DirtyID++; clearDirty = ~(RenderDataDirtyTypes.Transform | RenderDataDirtyTypes.Size); dirty = m_FirstDirtyTransformOrSize; s_TransformProcessingSampler.Begin(); while (dirty != null) { if (dirty.renderChainData.isInChain && dirty.renderChainData.dirtyID != m_DirtyID) { Implementation.RenderEvents.ProcessOnTransformOrSizeChanged(this, dirty, m_DirtyID, device, ref m_Stats); } dirty.renderChainData.dirtiedValues &= clearDirty; var old = dirty; dirty = dirty.renderChainData.nextDirtyTransformOrSize; old.renderChainData.nextDirtyTransformOrSize = null; } s_TransformProcessingSampler.End(); m_FirstDirtyTransformOrSize = m_LastDirtyTransformOrSize = null; m_DirtyID++; clearDirty = ~(RenderDataDirtyTypes.Visuals | RenderDataDirtyTypes.VisualsHierarchy); dirty = m_FirstDirtyVisuals; s_VisualsProcessingSampler.Begin(); while (dirty != null) { if (dirty.renderChainData.isInChain && dirty.renderChainData.dirtyID != m_DirtyID) { Implementation.RenderEvents.ProcessOnVisualsChanged(this, dirty, m_DirtyID, ref m_Stats); } dirty.renderChainData.dirtiedValues &= clearDirty; var old = dirty; dirty = dirty.renderChainData.nextDirtyVisuals; old.renderChainData.nextDirtyVisuals = null; } s_VisualsProcessingSampler.End(); m_FirstDirtyVisuals = m_LastDirtyVisuals = null; ProcessTextRegen(true); if (m_FontWasReset) { // We regenerate the text when the font texture was reset since we don't have any guarantees // the the glyphs are going to end up at the same spot in the texture. // Up to two passes may be necessary with time-slicing turned off to fully update the text. const int kMaxTextPasses = 2; for (int i = 0; i < kMaxTextPasses; ++i) { if (!m_FontWasReset) { break; } m_FontWasReset = false; ProcessTextRegen(false); } } atlasManager?.Update(); // Commit new requests if any if (BeforeDrawChain != null) { BeforeDrawChain(device); } Exception immediateException = null; device.DrawChain(m_FirstCommand, topRect, projection, atlasManager?.atlas, ref immediateException); s_RenderSampler.End(); if (immediateException != null) { throw immediateException; } if (drawStats) { DrawStats(); } }
public void ProcessChanges() { s_MarkerProcess.Begin(); m_Stats = new ChainBuilderStats(); m_Stats.elementsAdded += m_StatsElementsAdded; m_Stats.elementsRemoved += m_StatsElementsRemoved; m_StatsElementsAdded = m_StatsElementsRemoved = 0; if (shaderInfoAllocator.isReleased) { RecreateDevice(); // The shader info texture was released, recreate the device to start fresh } if (m_DrawInCameras && m_StaticIndex < 0) { m_StaticIndex = RenderChainStaticIndexAllocator.AllocateIndex(this); } else if (!m_DrawInCameras && m_StaticIndex >= 0) { RenderChainStaticIndexAllocator.FreeIndex(m_StaticIndex); m_StaticIndex = -1; } if (OnPreRender != null) { OnPreRender(); } bool atlasWasReset = false; if (atlasManager?.RequiresReset() == true) { atlasManager.Reset(); // May cause a dirty repaint atlasWasReset = true; } if (vectorImageManager?.RequiresReset() == true) { vectorImageManager.Reset(); atlasWasReset = true; } // Although shaderInfoAllocator uses an atlas internally, it doesn't need to // reset it due to any of the current reasons that the atlas is reset for, thus we don't do it. if (atlasWasReset) { RepaintAtlassedElements(); } int dirtyClass; RenderDataDirtyTypes dirtyFlags; RenderDataDirtyTypes clearDirty; m_DirtyTracker.dirtyID++; dirtyClass = (int)RenderDataDirtyTypeClasses.Clipping; dirtyFlags = RenderDataDirtyTypes.Clipping | RenderDataDirtyTypes.ClippingHierarchy; clearDirty = ~dirtyFlags; s_MarkerClipProcessing.Begin(); for (int depth = m_DirtyTracker.minDepths[dirtyClass]; depth <= m_DirtyTracker.maxDepths[dirtyClass]; depth++) { VisualElement ve = m_DirtyTracker.heads[depth]; while (ve != null) { VisualElement veNext = ve.renderChainData.nextDirty; if ((ve.renderChainData.dirtiedValues & dirtyFlags) != 0) { if (ve.renderChainData.isInChain && ve.renderChainData.dirtyID != m_DirtyTracker.dirtyID) { Implementation.RenderEvents.ProcessOnClippingChanged(this, ve, m_DirtyTracker.dirtyID, ref m_Stats); } m_DirtyTracker.ClearDirty(ve, clearDirty); } ve = veNext; m_Stats.dirtyProcessed++; } } s_MarkerClipProcessing.End(); m_DirtyTracker.dirtyID++; dirtyClass = (int)RenderDataDirtyTypeClasses.Opacity; dirtyFlags = RenderDataDirtyTypes.Opacity; clearDirty = ~dirtyFlags; s_MarkerOpacityProcessing.Begin(); for (int depth = m_DirtyTracker.minDepths[dirtyClass]; depth <= m_DirtyTracker.maxDepths[dirtyClass]; depth++) { VisualElement ve = m_DirtyTracker.heads[depth]; while (ve != null) { VisualElement veNext = ve.renderChainData.nextDirty; if ((ve.renderChainData.dirtiedValues & dirtyFlags) != 0) { if (ve.renderChainData.isInChain && ve.renderChainData.dirtyID != m_DirtyTracker.dirtyID) { Implementation.RenderEvents.ProcessOnOpacityChanged(this, ve, m_DirtyTracker.dirtyID, ref m_Stats); } m_DirtyTracker.ClearDirty(ve, clearDirty); } ve = veNext; m_Stats.dirtyProcessed++; } } s_MarkerOpacityProcessing.End(); m_DirtyTracker.dirtyID++; dirtyClass = (int)RenderDataDirtyTypeClasses.TransformSize; dirtyFlags = RenderDataDirtyTypes.Transform | RenderDataDirtyTypes.ClipRectSize; clearDirty = ~dirtyFlags; s_MarkerTransformProcessing.Begin(); for (int depth = m_DirtyTracker.minDepths[dirtyClass]; depth <= m_DirtyTracker.maxDepths[dirtyClass]; depth++) { VisualElement ve = m_DirtyTracker.heads[depth]; while (ve != null) { VisualElement veNext = ve.renderChainData.nextDirty; if ((ve.renderChainData.dirtiedValues & dirtyFlags) != 0) { if (ve.renderChainData.isInChain && ve.renderChainData.dirtyID != m_DirtyTracker.dirtyID) { Implementation.RenderEvents.ProcessOnTransformOrSizeChanged(this, ve, m_DirtyTracker.dirtyID, ref m_Stats); } m_DirtyTracker.ClearDirty(ve, clearDirty); } ve = veNext; m_Stats.dirtyProcessed++; } } s_MarkerTransformProcessing.End(); m_BlockDirtyRegistration = true; // Processing visuals may call generateVisualContent, which must be restricted to the allowed operations m_DirtyTracker.dirtyID++; dirtyClass = (int)RenderDataDirtyTypeClasses.Visuals; dirtyFlags = RenderDataDirtyTypes.Visuals | RenderDataDirtyTypes.VisualsHierarchy; clearDirty = ~dirtyFlags; s_MarkerVisualsProcessing.Begin(); for (int depth = m_DirtyTracker.minDepths[dirtyClass]; depth <= m_DirtyTracker.maxDepths[dirtyClass]; depth++) { VisualElement ve = m_DirtyTracker.heads[depth]; while (ve != null) { VisualElement veNext = ve.renderChainData.nextDirty; if ((ve.renderChainData.dirtiedValues & dirtyFlags) != 0) { if (ve.renderChainData.isInChain && ve.renderChainData.dirtyID != m_DirtyTracker.dirtyID) { Implementation.RenderEvents.ProcessOnVisualsChanged(this, ve, m_DirtyTracker.dirtyID, ref m_Stats); } m_DirtyTracker.ClearDirty(ve, clearDirty); } ve = veNext; m_Stats.dirtyProcessed++; } } s_MarkerVisualsProcessing.End(); m_BlockDirtyRegistration = false; // Done with all dirtied elements m_DirtyTracker.Reset(); ProcessTextRegen(true); if (m_FontWasReset) { // We regenerate the text when the font texture was reset since we don't have any guarantees // the the glyphs are going to end up at the same spot in the texture. // Up to two passes may be necessary with time-slicing turned off to fully update the text. const int kMaxTextPasses = 2; for (int i = 0; i < kMaxTextPasses; ++i) { if (!m_FontWasReset) { break; } m_FontWasReset = false; ProcessTextRegen(false); } } // Commit new requests for atlases if any atlasManager?.Commit(); vectorImageManager?.Commit(); shaderInfoAllocator.IssuePendingAtlasBlits(); device?.OnFrameRenderingBegin(); s_MarkerProcess.End(); }
public void Render(Rect viewport, Matrix4x4 projection) { s_RenderSampler.Begin(); m_Stats = new ChainBuilderStats(); m_Stats.elementsAdded += m_StatsElementsAdded; m_Stats.elementsRemoved += m_StatsElementsRemoved; m_StatsElementsAdded = m_StatsElementsRemoved = 0; if (OnPreRender != null) { OnPreRender(); } bool atlasWasReset = false; if (atlasManager?.RequiresReset() == true) { atlasManager.Reset(); // May cause a dirty repaint atlasWasReset = true; } if (vectorImageManager?.RequiresReset() == true) { vectorImageManager.Reset(); atlasWasReset = true; } if (atlasWasReset) { RepaintAtlassedElements(); } m_DirtyTracker.dirtyID++; var dirtyClass = (int)RenderDataDirtyTypeClasses.Clipping; var dirtyFlags = RenderDataDirtyTypes.Clipping | RenderDataDirtyTypes.ClippingHierarchy; var clearDirty = ~dirtyFlags; s_ClipProcessingSampler.Begin(); for (int depth = m_DirtyTracker.minDepths[dirtyClass]; depth <= m_DirtyTracker.maxDepths[dirtyClass]; depth++) { VisualElement ve = m_DirtyTracker.heads[depth]; while (ve != null) { VisualElement veNext = ve.renderChainData.nextDirty; if ((ve.renderChainData.dirtiedValues & dirtyFlags) != 0) { if (ve.renderChainData.isInChain && ve.renderChainData.dirtyID != m_DirtyTracker.dirtyID) { Implementation.RenderEvents.ProcessOnClippingChanged(this, ve, m_DirtyTracker.dirtyID, device, ref m_Stats); } m_DirtyTracker.ClearDirty(ve, clearDirty); } ve = veNext; } } s_ClipProcessingSampler.End(); m_DirtyTracker.dirtyID++; dirtyClass = (int)RenderDataDirtyTypeClasses.Opacity; dirtyFlags = RenderDataDirtyTypes.Opacity; clearDirty = ~dirtyFlags; s_OpacityProcessingSampler.Begin(); for (int depth = m_DirtyTracker.minDepths[dirtyClass]; depth <= m_DirtyTracker.maxDepths[dirtyClass]; depth++) { VisualElement ve = m_DirtyTracker.heads[depth]; while (ve != null) { VisualElement veNext = ve.renderChainData.nextDirty; if ((ve.renderChainData.dirtiedValues & dirtyFlags) != 0) { if (ve.renderChainData.isInChain && ve.renderChainData.dirtyID != m_DirtyTracker.dirtyID) { Implementation.RenderEvents.ProcessOnOpacityChanged(this, ve, m_DirtyTracker.dirtyID, ref m_Stats); } m_DirtyTracker.ClearDirty(ve, clearDirty); } ve = veNext; } } s_OpacityProcessingSampler.End(); m_DirtyTracker.dirtyID++; dirtyClass = (int)RenderDataDirtyTypeClasses.TransformSize; dirtyFlags = RenderDataDirtyTypes.Transform | RenderDataDirtyTypes.Size; clearDirty = ~dirtyFlags; s_TransformProcessingSampler.Begin(); for (int depth = m_DirtyTracker.minDepths[dirtyClass]; depth <= m_DirtyTracker.maxDepths[dirtyClass]; depth++) { VisualElement ve = m_DirtyTracker.heads[depth]; while (ve != null) { VisualElement veNext = ve.renderChainData.nextDirty; if ((ve.renderChainData.dirtiedValues & dirtyFlags) != 0) { if (ve.renderChainData.isInChain && ve.renderChainData.dirtyID != m_DirtyTracker.dirtyID) { Implementation.RenderEvents.ProcessOnTransformOrSizeChanged(this, ve, m_DirtyTracker.dirtyID, device, ref m_Stats); } m_DirtyTracker.ClearDirty(ve, clearDirty); } ve = veNext; } } s_TransformProcessingSampler.End(); m_BlockDirtyRegistration = true; // Processing visuals may call generateVisualContent, which must be restricted to the allowed operations m_DirtyTracker.dirtyID++; dirtyClass = (int)RenderDataDirtyTypeClasses.Visuals; dirtyFlags = RenderDataDirtyTypes.Visuals | RenderDataDirtyTypes.VisualsHierarchy; clearDirty = ~dirtyFlags; s_VisualsProcessingSampler.Begin(); for (int depth = m_DirtyTracker.minDepths[dirtyClass]; depth <= m_DirtyTracker.maxDepths[dirtyClass]; depth++) { VisualElement ve = m_DirtyTracker.heads[depth]; while (ve != null) { VisualElement veNext = ve.renderChainData.nextDirty; if ((ve.renderChainData.dirtiedValues & dirtyFlags) != 0) { if (ve.renderChainData.isInChain && ve.renderChainData.dirtyID != m_DirtyTracker.dirtyID) { Implementation.RenderEvents.ProcessOnVisualsChanged(this, ve, m_DirtyTracker.dirtyID, ref m_Stats); } m_DirtyTracker.ClearDirty(ve, clearDirty); } ve = veNext; } } s_VisualsProcessingSampler.End(); m_BlockDirtyRegistration = false; // Done with all dirtied elements m_DirtyTracker.Reset(); ProcessTextRegen(true); if (m_FontWasReset) { // We regenerate the text when the font texture was reset since we don't have any guarantees // the the glyphs are going to end up at the same spot in the texture. // Up to two passes may be necessary with time-slicing turned off to fully update the text. const int kMaxTextPasses = 2; for (int i = 0; i < kMaxTextPasses; ++i) { if (!m_FontWasReset) { break; } m_FontWasReset = false; ProcessTextRegen(false); } } // Commit new requests for atlases if any atlasManager?.Commit(); vectorImageManager?.Commit(); if (BeforeDrawChain != null) { BeforeDrawChain(device); } Exception immediateException = null; device.DrawChain(m_FirstCommand, viewport, projection, atlasManager?.atlas, vectorImageManager?.atlas, (panel as BaseVisualElementPanel).scaledPixelsPerPoint, ref immediateException); s_RenderSampler.End(); if (immediateException != null) { throw immediateException; } if (drawStats) { DrawStats(); } }
public void ProcessChanges() { s_MarkerProcess.Begin(); m_Stats = new ChainBuilderStats(); m_Stats.elementsAdded += m_StatsElementsAdded; m_Stats.elementsRemoved += m_StatsElementsRemoved; m_StatsElementsAdded = m_StatsElementsRemoved = 0; int dirtyClass; RenderDataDirtyTypes dirtyFlags; RenderDataDirtyTypes clearDirty; m_DirtyTracker.dirtyID++; dirtyClass = (int)RenderDataDirtyTypeClasses.Clipping; dirtyFlags = RenderDataDirtyTypes.Clipping | RenderDataDirtyTypes.ClippingHierarchy; clearDirty = ~dirtyFlags; s_MarkerClipProcessing.Begin(); for (int depth = m_DirtyTracker.minDepths[dirtyClass]; depth <= m_DirtyTracker.maxDepths[dirtyClass]; depth++) { VisualElement ve = m_DirtyTracker.heads[depth]; while (ve != null) { VisualElement veNext = ve.renderChainData.nextDirty; if ((ve.renderChainData.dirtiedValues & dirtyFlags) != 0) { if (ve.renderChainData.isInChain && ve.renderChainData.dirtyID != m_DirtyTracker.dirtyID) { Implementation.RenderEvents.ProcessOnClippingChanged(this, ve, m_DirtyTracker.dirtyID, ref m_Stats); } m_DirtyTracker.ClearDirty(ve, clearDirty); } ve = veNext; m_Stats.dirtyProcessed++; } } s_MarkerClipProcessing.End(); m_DirtyTracker.dirtyID++; dirtyClass = (int)RenderDataDirtyTypeClasses.Opacity; dirtyFlags = RenderDataDirtyTypes.Opacity | RenderDataDirtyTypes.OpacityHierarchy; clearDirty = ~dirtyFlags; s_MarkerOpacityProcessing.Begin(); for (int depth = m_DirtyTracker.minDepths[dirtyClass]; depth <= m_DirtyTracker.maxDepths[dirtyClass]; depth++) { VisualElement ve = m_DirtyTracker.heads[depth]; while (ve != null) { VisualElement veNext = ve.renderChainData.nextDirty; if ((ve.renderChainData.dirtiedValues & dirtyFlags) != 0) { if (ve.renderChainData.isInChain && ve.renderChainData.dirtyID != m_DirtyTracker.dirtyID) { Implementation.RenderEvents.ProcessOnOpacityChanged(this, ve, m_DirtyTracker.dirtyID, ref m_Stats); } m_DirtyTracker.ClearDirty(ve, clearDirty); } ve = veNext; m_Stats.dirtyProcessed++; } } s_MarkerOpacityProcessing.End(); m_DirtyTracker.dirtyID++; dirtyClass = (int)RenderDataDirtyTypeClasses.Color; dirtyFlags = RenderDataDirtyTypes.Color; clearDirty = ~dirtyFlags; s_MarkerColorsProcessing.Begin(); for (int depth = m_DirtyTracker.minDepths[dirtyClass]; depth <= m_DirtyTracker.maxDepths[dirtyClass]; depth++) { VisualElement ve = m_DirtyTracker.heads[depth]; while (ve != null) { VisualElement veNext = ve.renderChainData.nextDirty; if ((ve.renderChainData.dirtiedValues & dirtyFlags) != 0) { if (ve.renderChainData.isInChain && ve.renderChainData.dirtyID != m_DirtyTracker.dirtyID) { Implementation.RenderEvents.ProcessOnColorChanged(this, ve, m_DirtyTracker.dirtyID, ref m_Stats); } m_DirtyTracker.ClearDirty(ve, clearDirty); } ve = veNext; m_Stats.dirtyProcessed++; } } s_MarkerColorsProcessing.End(); m_DirtyTracker.dirtyID++; dirtyClass = (int)RenderDataDirtyTypeClasses.TransformSize; dirtyFlags = RenderDataDirtyTypes.Transform | RenderDataDirtyTypes.ClipRectSize; clearDirty = ~dirtyFlags; s_MarkerTransformProcessing.Begin(); for (int depth = m_DirtyTracker.minDepths[dirtyClass]; depth <= m_DirtyTracker.maxDepths[dirtyClass]; depth++) { VisualElement ve = m_DirtyTracker.heads[depth]; while (ve != null) { VisualElement veNext = ve.renderChainData.nextDirty; if ((ve.renderChainData.dirtiedValues & dirtyFlags) != 0) { if (ve.renderChainData.isInChain && ve.renderChainData.dirtyID != m_DirtyTracker.dirtyID) { Implementation.RenderEvents.ProcessOnTransformOrSizeChanged(this, ve, m_DirtyTracker.dirtyID, ref m_Stats); } m_DirtyTracker.ClearDirty(ve, clearDirty); } ve = veNext; m_Stats.dirtyProcessed++; } } s_MarkerTransformProcessing.End(); jobManager.CompleteNudgeJobs(); m_BlockDirtyRegistration = true; // Processing visuals may call generateVisualContent, which must be restricted to the allowed operations m_DirtyTracker.dirtyID++; dirtyClass = (int)RenderDataDirtyTypeClasses.Visuals; dirtyFlags = RenderDataDirtyTypes.AllVisuals; clearDirty = ~dirtyFlags; s_MarkerVisualsProcessing.Begin(); for (int depth = m_DirtyTracker.minDepths[dirtyClass]; depth <= m_DirtyTracker.maxDepths[dirtyClass]; depth++) { VisualElement ve = m_DirtyTracker.heads[depth]; while (ve != null) { VisualElement veNext = ve.renderChainData.nextDirty; if ((ve.renderChainData.dirtiedValues & dirtyFlags) != 0) { if (ve.renderChainData.isInChain && ve.renderChainData.dirtyID != m_DirtyTracker.dirtyID) { Implementation.RenderEvents.ProcessOnVisualsChanged(this, ve, m_DirtyTracker.dirtyID, ref m_Stats); } m_DirtyTracker.ClearDirty(ve, clearDirty); } ve = veNext; m_Stats.dirtyProcessed++; } } jobManager.CompleteConvertMeshJobs(); jobManager.CompleteClosingMeshJobs(); opacityIdAccelerator.CompleteJobs(); s_MarkerVisualsProcessing.End(); m_BlockDirtyRegistration = false; vertsPool.Reset(); indicesPool.Reset(); // Done with all dirtied elements m_DirtyTracker.Reset(); // Commit new requests for atlases if any atlas?.InvokeUpdateDynamicTextures(panel); // TODO: For a shared atlas + drawInCameras, postpone after all updates have occurred. vectorImageManager?.Commit(); shaderInfoAllocator.IssuePendingStorageChanges(); device?.OnFrameRenderingBegin(); s_MarkerProcess.End(); }