【Unity】UIElements 渲染细节,比NGUI/UGUI/FairyGUI好在哪?
为什么要关注 UIElements ? 因为要有运行时版本了。 UIElements 在一开始推出的时候就在文档中提到将来会有运行时版本,但是具体什么时候没有说。
Unity运行时UI解决方案 还挺多, NGUI, UGUI, FairyGUI .
------------------------------
想到了一个之前看到的事情。就是一直再有新的东西出现~
------------------------------
UIElements for Runtime - 2019.3 ???? Early preview package
Simple Runtime UI - 2020.1 ???? Preview package
Rich Content UI - 2020.3 ✅ Verified package - Plan of intent
https://forum.unity.com/forums/uielements.178/
UI Roadmap https://forum.unity.com/threads/ui-roadmap.735338/
https://docs.unity3d.com/Packages/[email protected]/manual/index.html
现在可以安装尝试UI Builder 这个东西,但是文档,案例还是太少了
--------------------------------------------
https://www.bilibili.com/video/av47558897
中国官方的 UIWidgets 团队是有进行过吐槽的, 说 UIElements 是上世纪90年代 比较逻辑的开发模式 html + css
---------------------------------------------------
https://www.youtube.com/watch?v=zeCdVmfGUN0&feature=youtu.be
Built for performance: the UIElements Renderer – Unite Copenhagen 2019
在本技术讲座中,我们将描述UIElements渲染系统背后的科学,该系统是为保留模式(retained-mode)UI从头开始构建的。 它使用本书中的每个CPU / GPU技巧,在一毫秒之内即可在一个线程上在屏幕上渲染数千个不同的元素。 这个功能强大的UI性能和优化工具甚至在低端设备上也支持剪切和矢量图形等复杂功能。
The UI rendering problem
— UI is a rendering problem with unique characteristics
— Big tree of nested elements
— Depth-first rendering for proper composition
— Stateful system
— Mostly static, very localized changes
– E.g. element under the mouse
— Changes usually triggered by sparse events
– Mainly instigated by user input
— Involves different rendering/shading techniques
– e.g. solid shapes, sprites, text, borders
UI渲染问题
-UI是具有独特特征的渲染问题
-嵌套元素大树
-深度优先渲染以实现适当的合成
-有状态系统
-大多是静态的,非常局部的更改
-例如鼠标下方的元素
-通常是由稀疏事件触发的更改
-主要是由用户输入引起的
-涉及不同的渲染/着色技术,例如实体形状,子图形,文本,边框
How NOT to do a UI renderer
Every frame to render:
— Visit the entire visual tree depth-first
— Ask each element to draw itself after its layout
— Each element sets the proper state/material
– E.g. solid, textured, alpha-blended, text
— Element generates its vertices
– Accumulate vertices in a dynamic vertex buffer
— Issue draw-call
— Rinse and repeat
— This is called immediate-mode rendering
— This is how IMGUI operates
— Useless work repeated every frame
– Bad for energy
– planet Earth hates it
— Tough to optimize behind the curtain
– Can vertex cache (better)
– or even pixel cache (memory hungry)
— Not performance scalable
– Hence, only use for in-game debugging purposes
— If you don’t believe me, wait near the end of this presentation
如何不做UI渲染器
要渲染的每一帧:
—首先深度访问整个视觉树
—要求每个元素在布局后自行绘制
—每个元素设置适当的状态/材质
–例如 纯色,纹理,alpha混合,文本
—元素生成其顶点
–在动态顶点缓冲区中累积顶点
—发出Draw-Call
—冲洗并重复Rinse and repeat
—这称为即时模式渲染 immediate-mode
—这是IMGUI的操作方式
—每帧重复无用的工作
–不利于能源
–地球讨厌它
—很难地在幕后进行优化
–可以顶点缓存(更好)
–甚至像素缓存(内存不足)
—无法扩展性能
–因此,仅用于游戏内调试目的
—如果您不相信我,请在本演示文稿的结尾附近等待
以上说的不是UGUI/ NGUI 存在的问题, 是IMGUI 。
Unity UI(uGUI)
-在Unity 4.6中发布
—仅用于制作运行时UI
—表现不佳
用例
- 紧密耦合
-UI创建者难以使用
How to do a scalable UI renderer
— Benefit from the problem’s characterstics
— Spare updates > Only recompute what’s changed
— Ideally 0-cost when nothing has changed
— Minimal draw submission cost on CPU & GPU every frame
— Not achievable with IMGUI methodology
– Need something different
如何做一个可扩展的UI渲染器
—从问题的特征中受益
—备用更新>仅重新计算更改内容
—理想的没有任何变化时是零成本
—每帧CPU和GPU上最小的draw 提交成本
—使用IMGUI方法无法实现–需要有所不同...
保留模式UI:UIElements
— UIElements是Unity中即将推出的通用UI系统
—与IMGUI根本不同
—保留与即时
UIElements渲染器(UIR)
UIElements Renderer (UIR)
— UIR is the new rendering backend of UIElements
— A tiny team on the quest for best UI rendering performance
— Support all UIElements features
– Cascading style sheets (USS)
– SVG / infinite zoom
– Trees of thousands of elements
– Run on everything from desktop to low-end mobile
— All of the above @ great performance
— UIR是UIElements的新渲染后端
—寻求最佳UI渲染性能的小型团队
—支持所有UIElements功能
–级联样式表(USS)
– SVG /无限变焦
–成千上万的元素树
–在从台式机到低端移动设备的所有设备上运行
—以上所有@出色的性能
UIElements渲染器(UIR)
—不要重复处理东西
—最大限度地减少draw call的开销
—无状态变化
—无论大小,都对整个树进行一次draw call
—没有树访问每一帧 = O(1)渲染
—简单的着色器
—矛盾的目标
Optimizing materials/states (1/4)
— Different shaders (solid/textured/text/SVG)
— Different element properties (color/clipping/opacity)
— State changes can be implicitly quite expensive
– Not only because of draw-call split
— Cost paid by both CPU and GPU
Optimizing materials/states (2/4)
— Let’s aim to avoid state changes entirely!
— UIR Uber Shader! (UnityUIE.cginc)
– Can handle 95% of UI content
Optimizing materials/states (3/4)
— Complex shader, but…
— UI is historically fill-rate bound
– Vertex processing unit will sit idle in the meantime
— Vertex shader processes most of the complexity
— Pixel shader has dynamic branching
– But all pixels from the same element will take the same branch
– Divergence within a wavefront/warp is rare
— ! Balance work across processing units !
– State change cost moved from CPU to GPU
– Cost spread on the GPU over idle units
Optimizing materials/states (4/4)
— Duh, but what happens to element properties?
— Properties are split stored in either per-vertex data or per- element data on the GPU
— Textures are automatically atlassed by default
– Exceptions exist
— Per-element data is stored in textures too
– Retrieved by the vertex shader using vertex texturing when possible
优化材质/状态(1/4)
—不同的着色器(纯色/纹理/文本/ SVG)
—不同的元素属性(颜色/剪切/不透明度)
–状态更改可能隐含地非常昂贵
—不仅是因为draw-call分割
—由CPU和GPU支付的成本
优化材质/状态(2/4)
—我们的目标是完全避免状态变化!
— UIR Uber着色器! (UnityUIE.cginc)
–可以处理95%的UI内容
优化材质/状态(3/4)
—复杂的着色器,但是…
—UI历来是填充率 方面bound
–同时,顶点处理单元将处于空闲状态
—顶点着色器处理大多数复杂性
—像素着色器具有动态分支
–但是来自同一元素的所有像素将采用相同的分支
–波前/翘曲内的发散很少
—!在各个处理单元之间平衡工作!
–状态更改成本从CPU转移到GPU
–GPU上的成本分摊到空闲单元上
优化材质/状态(4/4)
— h,但是元素属性会怎样?
—将属性拆分存储在GPU的每个顶点数据或每个元素数据中
—默认情况下,纹理会自动加图集
–存在例外
—每个元素的数据也存储在纹理中
–在可能的情况下由顶点着色器使用顶点纹理获取
Optimizing draw-call count (1/5)
— State change reduction is great but not enough
— Single draw-call = all geometry stored sequentially in 1 VB/IB
— IMGUI already does that
– (though doesn’t benefit from it)
— But don’t want to repopulate full VB/IB on every element change
Optimizing draw-call count (2/5)
— Let’s allocate a large VB/IB
— Emplace geometry in this VB/IB as elements are added
– Keep a counter to the last filled vertex and just grow from there
— Unchanged elements keep their vertices/indices untouched across frames
— What happens when elements are removed or their geometry changes?
Optimizing draw-call count (3/5)
— UIR introduces GPU allocators to manage vertex/index allocations from VB/IB page(s)
— UIR GPU allocators guarantee sequential index ranges for consecutive elements in depth-first tree order
— If sequentiality can’t be honored for an allocation, it’s not the end of the world
– Issuing draw-calls without any state changes is at least 60x faster* than state-changing draw-calls * Measured on an old MALI400 OpenGL Android device Management Vertex Buffer Memory
Optimizing draw-call count (4/5)
— If an element changes its geometry, it is given a new space in the same VB/IB to fill its new vertices/indices
– Other elements geometry remains intact and untouched
— No need for double-buffering!
— Allocator keeps track of vertices in use by GPU
— Allocator defragments and re-sequences the allocations automatically once the GPU releases the memory
Optimizing draw-call count (5/5)
— UIR submits all this in 1 draw-call (~185 visual elements – 3886 tris)
优化draw-call数量(1/5)
—减少状态变化虽然很好,但还不够
— 一次绘图调用=将所有几何顺序存储在1 VB / IB中
— IMGUI已经做到了
–(尽管不能从中受益)
—但不想在每次元素更改时重新填充完整的VB / IB
优化draw-call数量(2/5)
—让我们分配一个大型的VB / IB
— 在VB / IB中将几何体作为元素添加
– 与最后填充的顶点保持相反,然后从那里开始增长
— 不变的元素使它们的顶点/索引在整个框架中保持不变
—移除元素或更改几何形状会发生什么?
优化draw-call数量(3/5)
— UIR引入了GPU分配器来管理VB / IB页面的顶点/索引分配
— UIR GPU分配器保证深度优先树顺序的连续元素的顺序索引范围
—如果不能按顺序进行分配,那不是世界末日
–发出状态不改变的绘图调用至少比状态变化的绘图调用快60倍* *在旧的MALI400 OpenGL Android设备管理顶点缓冲存储器上测量
优化draw-call数量(4/5)
—如果元素更改其几何形状,则会在同一VB / IB中为其提供一个新空间,以填充其新的顶点/索引
–其他元素的几何形状保持完好无损
—无需双重缓冲!
—分配器跟踪GPU使用的顶点
—一旦GPU释放内存,分配器便会自动对碎片进行碎片整理和重新排序
优化draw-call数量(5/5)
— UIR在1个DC中提交了所有这些内容(〜185个视觉元素– 3886 tris)
UIR的日常操作(1/2)
UIR的日常操作(2/2)
— Maintain a “render command list” of macro draw commands
– List progressively maintained, never fully regenerated
– Remember: never scale to visual tree size
— At render time, this command list is iterated to generate the necessary graphics API draw-call(s)
— Only visit actual render commands on a macro level
— Instead of iterating over the entire visual tree!
—维护宏绘制命令的“渲染命令列表”“render command list”
–列表逐步维护,从未完全重新生成
–请记住:永远不要缩放到视觉树的大小
—在渲染时,此命令列表被迭代以生成必要的图形API draw-call(s)
—仅在宏级别上访问实际的渲染命令
—而不是遍历整个可视树!
迄今为止的UIR
UIR so far
— 1 material able to express all UI constructs
— 1 vertex/index buffer to hold geometry
— 1 draw-call to rule them all
– Theoretical minimum cost for drawing
– Never have to visit the entire visual tree: O(1)
— Closely follows changes in visual tree – Cost is linear to changed elements count O(n) or better
– But wait, there is more…
—1种能够表达所有UI构造的材质
—1个顶点/索引缓冲区,用于保存几何
- 1个DrawCall 将他们全部统治
—drawing 的理论最低成本
—无需访问整个视觉树:O(1)
—紧跟视觉树的变化
—成本与元素数量O(n)或更好的变化成线性关系
—但是等等,还有更多…
UIR好处
UIR Goodies
— GPU-accelerated clipping
– Rectangular & arbitrary shape stencil-based clipping without breaking draw-calls and without mask textures (fully geometric)
— GPU skinning (a.k.a DynamicTransform)
– Fast transform path for dynamic/animated elements (move, rotation, scale)
— GPU-accelerated viewport operations
– Zoom/pan (infinite resolution)
— …
— GPU加速剪辑
–基于矩形和任意形状模具的剪切,而不会中断绘制调用并且没有蒙版纹理(完全几何)
—GPU外观(也称为DynamicTransform)
–动态/动画元素(移动,旋转,缩放)的快速变换路径
— GPU加速的视口操作
–缩放/平移(无限分辨率)
—…
使用UIR进行优化
Optimizing with UIR
— Optimizing for UIR does not require structural tree changes
— Communicate high-level intentions through hinting
— VisualElement.usageHints
– UsageHints.DynamicTransform
– UsageHints.GroupTransform
– … more will be exposed to accelerate hot-paths and commonly used UI features
— UIR will take those hints and optimize its internals accordingly
— Keep hints on elements that matter the most
– Optimization resources are limited on older devices (i.e. SM2/GLES2)
– SM3.5 unlocks stronger optimizations
— 6000 elements generating ~205,000 triangles UsageHint.None 163ms UsageHint.DynamicTransform 11.4ms
—针对UIR进行优化不需要更改结构树
—通过提示传达高层意图
— VisualElement.usageHints
– UsageHints.DynamicTransform
– UsageHints.GroupTransform
–…将展示更多内容以加速热路径和常用的UI功能
— UIR将接受这些提示并相应地优化其内部
-提示最重要的元素
–在较旧的设备(例如SM2 / GLES2)上,优化资源有限
- SM3.5解锁更强大的优化
使用UIR进行优化
— 6000个元素生成约205,000个三角形
UIR未来工作
— * UIR仍在大力开发中*
– 2019.3公开了VisualElement.generateVisualContent
— 无硬件MSAA的抗锯齿
— 3D世界整合
–双向:2D中的3D和3D中的2D
-新的用法提示可更好地指导性能
—公开定制材质
—用于UIR分析和优化的专家系统工具(Dr.PIX)
–捕获用户性能并对其进行分析以提出改进建议并捕获不正确的使用情况
—以及更多…
谢谢UIR开发团队
即将举行的UIElements讨论
—使用UIElements扩展编辑器星期二,下午2:00-下午2:45
—使用新的UI Builder构建游戏的UI,星期三,3:00 PM-3:45
Extending the Editor with UIElements – Unite Copenhagen 2019
What is IMGUI?
What is UIElements?
IMGUI
— IM = Immediate Mode
– Drawn every frame
– Can be slow
— All code stored together
– Functionality / Layout / Style
UIElements
— Updates only when needed
— Separation of concerns
– Functionality / Layout / Style split into different files
— New file types
– USS for Style (subset of CSS)
– uXML for Layout (subset of XML)