Behind pixels, when the Frame Debugger powerless Unity

http://www.manew.com/thread-92382-1-1.html

 

Version 5 from the start, Unity includes a new frame of visual debugging tools, Frame Debugger . This tool can help you solve a lot of graphics problems , the Z--Fighting , GPU state is not normal, render queue wrong, wrong mixing operation, excessive Draw Call , inefficient and so on. The state of the game compared to the list view, which provides more detailed information, by rendering events / steps and interaction checking, you can also learn a lot of GPU knowledge pipeline. Really, every developer should know about this tool.

 

In this issue, I will briefly describe Frame Debugger methods used, and then point out its deficiencies and other tools can make up for these issues. I'm not going to cover everything, just do a general overview of the content.


1. Frame debugger


Use Window-> Frame Debugger menu opens its main window, I suggest that while open frame debugger  and Game View  (game view). To do this you may need to make some adjustments to the layout of the window, I used to when debugging interface graphical display as follows:



 
Recommended layout (except for the Asset Store tab)
The proposed window layout (in addition to asset store tab)


Play the game into the state, to let you Toutongnaore, feeling unhappy position in the frame debugger window, click on the enable can get details of recently rendered frame.


Which consists of two main parts: the event, as well as details on its right side in. CPU events are basically sent to GPU command, very simple, after all, this can not be called to see the real API function, but the entire process of packaging displayed in chronological order. Most of which are clear and draw (opaque / transparent) geometry command body, but you can also note that more information, such as: the GUI rendering, shading, graphics, etc. and the corresponding number of callbacks.


After selecting an event, the details you can immediately get more information about the event panel. Comprising: a shader range and its logo, and rendering an output shader event attribute information. At the same time, the game will display objects in the view before the event to be rendered (including the current event oh). Below is an example



<ignore_js_op>  
Event example


2. Frame Debugger doing with?


Frame debugger provides us with some valuable information. Draw call sequence of events (that is,: Render Queue) is very important for the correctness of the rendering, if the game does not properly display elements to coarse, here you may find it is not properly placed in the rendering queue , resulting in premature or delayed rendering; particularly during development or custom shader Z write time (write depth buffer) and test parameter adjustment. With this tool solves many problems for me: to find out the problems due to forget to set the flag and rendering order which led to the sky box cover I shader output.


其次,相对的,你也可以在此查看draw call 的调用次数,并通过顶点 / 索引数量来间接衡量场景的渲染代价。当然,着色器 pass 数也有帮助意义,但其复杂度在此没有显示,这就要求你得有些基本常识了,所有这些信息都能帮助你提高场景的性能,比如:你会发现出于某些原因一些网格绘制未能进行静态 / 动态批处理。在我的例子中,你会发现通过使用材质图集来将两个图片精灵的 2 draw call 操作合并为 1 个。


第三,通过与Frame Debugger 交互,你可以快速学习 GPU 的体系架构知识并了解 Unity 渲染处理的流程。可以用键盘在不同的事件中跳转一步步查看场景的渲染过程。在之前的例子中,可以看到场景渲染开始于对三个缓存的清理(颜色、 z stencil),接着是不透明几何体(从前面到背面),天空盒子和透明几何体(从背面到前面)的渲染。


最后,你可以访问着色器属性以获得关于材质和着色器的更多信息,也可以得到被对象使用的数据的引用,如:材质。大多数人都没用过Unity 中的 advanced views,你可以在inspector中通过点击右上部的paragraph图标,并选择“Debug”来访问他们。


<ignore_js_op>  


Shader properties
着色器属性



2.  Caveats


在为一个客户工作期间,我也碰到了由于Frame Debugger 过于简洁的界面而导致的问题。我在 Unite 2016 Europe中与Unity的一些开发做了交流,他们也清楚这种情况,但针对未来是否打算对其进行扩展时他们并没表态。从我的经验看,主要的问题有:



  • 无法获得事件之后API调用的底层信息。就这个问题来说,Unity将事件作为一个黑盒处理了,因此,在特定的条件下你将很难对这个问题作出改进。
  • 无法获得每个事件中GPU管线的总体状态,只能得到关于几何体和材质的信息,而缺少在不同阶段,像顶点/几何体/片段着色器和栅格化器中的数据。
  • 无法真正的调试着色器。要么采用修改输出颜色来进行代码的可视化调试(比打印还遭罪)或者依赖像GLSL-Debugge类的外部软件。
  • 难以建立结果像素与写出这些像素的相应事件的关联。你得一步步检查究竟是哪个事件在像素中写入了错误的信息,在有大量的draw call调用时,这过程会相当耗时。
  • 缺少能够衡量每个draw     call效率的精确指示器,顶点/索引的数量并不是表征渲染效率的最好手段。尽管更多的顶点需要更大的带宽,但是在几何体上执行一个复杂的顶点着色器或代价高昂的状态转换性能可能会更差。
如果至此你还愿意继续看下去,可能你也在寻找针对以上问题的解决方案,使用一些补充性的其他工具怎么样呢?


4. RenderDoc


在进行了一些软件的测试后,我铁定可以为大家推荐几款。你工具箱里的首选必须是 RenderDoc,Crytek开发的一款免费工具,用于解决底层调用信息的问题,该工具使用了网络攻击者的经典做法:它建立一个虚拟的图形驱动作为中间人进行(MITM)捕获应用中的DX/GL/Vulkan调用并提供详细的调试信息。好消息是:该工具已经支持在Unity中原生集成,你只需在windows机器上安装RenderDoc并重启unity的编辑器即可。


本节俺的目标是为大家概述该工具的用法,让你充满兴趣的开始,使用时更加顺畅,而且少花电费。


我们开始吧,如果安装顺利,在游戏中你应该可以右键单击并在菜单中选择Load RenderDoc


<ignore_js_op>  


几秒钟后,进入播放模式,如果你对刚渲染的那帧感兴趣,点击最大化播放按钮左侧光头佬一样的新图标:


<ignore_js_op>  


接着切换到新打开的RenderDoc 窗口,双击自动捕捉的日志开始分析它:


<ignore_js_op>  


RenderDoc captured log


Rendoc捕捉日志


哇哦,这就是信息的大海啊,我会淹死的。冷静下来,一切都会顺利。现在你会在几千个窗口中得到所有帧的数据,表担心,下面我会继续讲解真正有趣的内容。



4.1. Event browser + API calls.
4.1 事件浏览器+API调用


该工具的优点就是能够获得每个事件的底层信息,事件浏览器就像Unity Frame Debugger 的一个扩展,其中还包括耗时(按毫秒计)和其他提示信息,能为衡量效率提供大量帮助。 RenderDoc 具有上下文敏感特征,也就是说,不论何时你选择一个事件,大部分其他窗口和区域将会显示仅与该事件相关的信息,其下的 API  调用窗口则列出了为处理该事件而调用的函数。


<ignore_js_op>  


RenderDoc: Event Browser + APIcalls


能得到这些耗时数据真的很棒!虽然它们可能不是绝对精确,但是具有相对准确性,也就是说,通过比较耗时你就能推断出哪些操作的draw call 需要优化。


4.2. Pipeline state.
管线状态


我经常怀疑渲染管线的工作模式,精巧的几何体是如何进入它的内部并转换为50 寸屏幕上像素的?好吧,不幸的是,在这个工具中你也无法得到一个用户友好的动画以展示其工作过程。


但确实有些 很好的免费工具可以做到。不过,不管怎样,RenderDoc能让你访问事件中的大量管线状态信息:input assembler,顶点///几何体/片段/计算着色器,栅格化器和输出合并器。相信俺的判断,RenderDoc不虚其名。


<ignore_js_op>  


RenderDoc: Pipelinestate for a pixel shader


 
<ignore_js_op>  


RenderDoc: Output Merger example



<ignore_js_op>  


RenderDoc: Rasterizer state



4.3. Mesh output
网格输出


RenderDoc 的另一项特征是可以通过顶点着色器的:输入输出位置,法线,纹理坐标等信息获取事件中渲染的网格数据。实际上,你可以用它抓取并保存3D 程序或游戏中正在渲染的网格,但在这边文章中我就不结合案例讲解了。


4.4. Texture viewer
纹理观察器


这是我的菜,将事件中的输入和输出纹理进行可视化展示。包括渲染到纹理或其他中间缓冲数据,在你使用中间缓冲进行图像效果处理时会非常有趣,此外,这也也能能节省纹理空间。



<ignore_js_op>  


RenderDoc: Texture viewer


4.5. Pixel debugging
像素级调试


在帧缓冲中,错误渲染的坏像素覆盖正确像素的情况并不少见,大多数开发者都碰到过这种噩梦,坏像素在场景中留下的奇怪感受让我们意识到有问题发生了,但却不知原因何在,就是赶脚不对!如何确认我们的猜想并找出问题所在…


是的,以下是该问题的解法:选择一个像素,点击histroy (得到一个在帧缓冲中向那个像素写入信息的事件序列)或者 debug (调试它的像素着色器)。调试这些问题需要真正的技术大牛,你需要汇编知识,并对像素着色器的反汇编后的版本有一定了解。


<ignore_js_op>  


RenderDoc: Pixel selection
RenderDoc:像素选择


<ignore_js_op>  


RenderDoc: Pixel’s history
RenderDoc: 像素历史


 


<ignore_js_op>  
RenderDoc: shader debugger



 



5. Example
示例


有些同学会怀疑在实际工作中搞出性能分析器意义何在。我这就告诉你:非常必要。在不确定某项特性的性能影响时,使用性能分析器做下测试,不论是frame debugger ,或者必要的话,动用 RenderDoc 等类似工具都会对你的工作大有裨益。


我们来看个示例。不是所有人都知道在脚本中访问材质和访问渲染器的shaderMaterial 是有差别的,但只有少数人确切知道这会对性能产生影响,虽然大多数情形下是一样的。不过既然我们手边有工具,何不一探究竟?


我们的测试场景只有一个精灵,反复使用相同的transform 实例化 10000 次后,它占据了几乎全部的视野,因此可以想见,其中有许多无需绘制的部分,代码如下:


void Start () {

               for(int i = 0; i < NumberSprites; ++i)

                {

 

                                varsprite = Instantiate(Sprite);

                               sprite.transform.parent= transform;

                                varsharedMaterial = sprite.sharedMaterial;

                // Uncomment me for creating amaterial copy per sprite.

                                //varmat = sprite.material;

               }

}


访问sharedMaterial 时很流畅,该材质仅有一个,并在所有精灵实例中共享;而访问 material 时,就需要为每个精灵创建一个单独的材质,这样就无法对 Draw call 进行批处理,使用 renderDoc 查看 Render.TransparentGeometry 函数的分析结果如下:
<ignore_js_op>  


我觉得RenerDoc 给出的时间开销可信度不高。材质的读取好像根本不准确,我也不知道这个示例中真实的硬件循环调用次数,我也查看了 Unity 的性能测试器。但无论哪种情况下,共享材质对比实例化新的材质,第二个实现方式都因为无法将 draw call 合并处理导致了更高的驱动开销和带宽开销。


真正代价高昂的是drawcall 中的状态转换,而不是 drawcall 本身的数量。在使用 Material.SetColor 为每个精灵设置了不同的随机颜色后,我注意到又掉了 2 FPS 。这个问题可以通过最近发布的 Vulkan API予以解决


6. Conclusions
结论


RenderDoc 既不是一个完善的工具更无法替代Unity  frame debugger ,它只是一个完善性工具,你可以方便的使用它获取需要的底层信息,能用到什么程度也是很有趣的,但你走的越远,问题就越复杂,此时你必须对 GPU 的硬件体系有充分的了解。


我得承认,使用renderDoc 是个耗时的活,因此要记住:先做性能测试,然后再进行针对性的优化。 95% 的情况下你都可以用 Unity 自带的 framedebugger 完成调试,但为了那可能使你生活立即变得不幸福的 5% 你也得做好万全准备。


请将这些工具和性能测试器结合在一起使用,实际中总会有些琐碎的情况,不知道瓶颈源自何处,特别是在一个缺少调试手段的平台进行开发时。


一如既往,感谢您反馈并提出问题!


原文链接:
http://www.gamasutra.com/blogs/R ... nough_RenderDoc.php

Guess you like

Origin www.cnblogs.com/alps/p/11227931.html