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

从版本5开始,Unity包含了一个全新的可视化帧调试工具,Frame Debugger。该工具能帮你解决很多图形方面的问题,Z-fighting,GPU状态不正常,渲染队列错误、混合操作错误,过多的draw call,效率低下等等。相比游戏视图中的状态列表,它提供了更加详尽的信息,通过与渲染事件/步骤的交互和检查,你也能学习到大量GPU管线的相关知识。真地,每个开发人员都应该了解这个工具。
本期内容中,我会简要的叙述Frame Debugger的使用方法,并在之后指出其不足之处和其他可以弥补这些问题的工具。我不打算面面俱到,只是对这些内容做一个总体概览。
1.  使用Frame debugger
使用Window-> Frame Debugger菜单打开其主窗口,我建议同时打开frame debugger 和game view (游戏视图)。为此你可能需要对窗口布局做些调整,本人用来调试图形显示时的界面如下图:
 
Recommended layout (except for the Asset Store tab)
建议的窗口布局(除了资源商店标签页)
使游戏进入播放状态,来到让你头痛脑热、心情不爽的位置,在frame debugger窗口中,点击enable就能得到最近渲染帧的细节信息。
其中包含了两个主要部分:事件,以及在其右侧的详细信息。事件中基本上都是CPU发送给GPU的命令,相当的简单,毕竟在此无法看到真正被调用的API函数,只是将整个过程按照时间顺序打包显示出来。其中大部分是清除和绘制(不透明/透明)几何体的命令,但是你也可以注意到更多的信息,如:GUI渲染,阴影处理,图形效果等以及相应的回调次数。
在选择一个事件后,你可以立即在details面板中得到关于该事件的详细信息。包括:着色器范围和其标志,渲染输出事件和着色器属性信息。同时,游戏视图会显示在该事件发生前已被渲染的对象(包括当前事件哦)。下面是一个例子
<ignore_js_op> 
Event example
2. Frame Debugger干嘛用?
Frame debugger为我们提供了一些有价值的信息。绘制事件的调用顺序(也即是:渲染队列)对渲染的正确性十分重要,如果游戏中的元素未能正确的显示粗来,在此你就可能发现它未被正确的放入渲染队列中,从而导致过早或延迟渲染;特别是在进行自定义着色器开发或Z write(深度缓冲写入)参数调整和测试时。通过这个工具为我解决了不少问题:查找出由于忘掉设置标志位和渲染次序而导致天空盒子覆盖了俺着色器输出的问题。
个。
第三,通过与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是有差别的,但只有少数人确切知道这会对性能产生影响,虽然大多数情形下是一样的。不过既然我们手边有工具,何不一探究竟?
次后,它占据了几乎全部的视野,因此可以想见,其中有许多无需绘制的部分,代码如下:
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合并处理导致了更高的驱动开销和带宽开销。
个FPS。这个问题可以通过最近发布的Vulkan API予以解决
6. Conclusions
结论
RenderDoc既不是一个完善的工具更无法替代Unity 的frame debugger,它只是一个完善性工具,你可以方便的使用它获取需要的底层信息,能用到什么程度也是很有趣的,但你走的越远,问题就越复杂,此时你必须对GPU的硬件体系有充分的了解。
我得承认,使用renderDoc是个耗时的活,因此要记住:先做性能测试,然后再进行针对性的优化。95%的情况下你都可以用Unity自带的framedebugger完成调试,但为了那可能使你生活立即变得不幸福的5%你也得做好万全准备。
请将这些工具和性能测试器结合在一起使用,实际中总会有些琐碎的情况,不知道瓶颈源自何处,特别是在一个缺少调试手段的平台进行开发时。
一如既往,感谢您反馈并提出问题!

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

像素迷踪,当Unity的Frame Debugger力不从心时的更多相关文章

  1. Unity Frame Debugger连接Android真机调试

    当用Profiler分析到不是代码导致的性能问题,当前场景最大的性能瓶颈是渲染时,或者自己写的Shader要调试时,都可以用Frame Debugger进行调试. 按下列步骤设置打包,既可以用Prof ...

  2. 20190703_创建 unity 的配置节处理程序时出错: The type name or alias Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension

    创建 unity 的配置节处理程序时出错: The type name or alias Microsoft.Practices.Unity.InterceptionExtension.Configu ...

  3. 【Unity_UWP】Unity 工程发布win10 UWP 时的本地文件读取 (下篇)

    Universal Windows Platform(UWP)是微软Windows10专用的通用应用平台,其目的在于在统一操作系统下控制所有智能电子设备. 自从Unity 5.2之后,配合VS 201 ...

  4. unity 3d 生成apk文件时,设置图标

    如图所示:注意红线标注部分: 如果安装到手机之后,程序的图标还是unity的默认图标,重启手机即可.

  5. unity调用安卓打包apk时的错误unable to convert classes into dex format

    出现这种问题一般是由于有重复的文件所致,看下unity报的错误那些文件重复了,把重复的文件删了即可 例如,将eclipse中的安卓工程bin\class导出jar包时,会将下面的.class文件打包, ...

  6. unity项目build成webgl时选择生成目录(解决方法)

    在unity里点击File>>Build Settings...>>勾选你要生成的Scenes>>选择webgl>>后面Development Buil ...

  7. Unity调用Windows对话框保存时另存为弹框

    Unity开发VR之Vuforia 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- ...

  8. 【Unity_UWP】Unity 工程发布win10 UWP 时的本地文件读取 (上篇)

    Universal Windows Platform(UWP)是微软Windows10专用的通用应用平台,其目的在于在统一操作系统下控制所有智能电子设备. 自从Unity 5.2之后,配合VS 201 ...

  9. unity 调用 .dll 或 .so时遇到的问题

    1.32位的 .dll 无法在64位的unity编辑器下运行. System.DllNotFoundException: xxx  , 64位的程序运行32位的dll是会报这种错 2.Failed t ...

随机推荐

  1. git add提交时关于 LF will be replaced by CRLF in 问题出现的原因以及解决方式

    最近在新创建的github项目中add新框架代码时,出现了LF will be replaced by CRLF in的问题,以下为问题截图 查阅资料才知道,LF和FRLF是两种不同的换行格式,这个警 ...

  2. docker 容器和镜像常用命令整理

  3. 【开发工具】- Xshell工具的下载和安装

    下载地址:https://www.netsarang.com/zh/free-for-home-school/ Xshell 是一个强大的安全终端模拟软件,它支持SSH1, SSH2, 以及Micro ...

  4. 当ajax都完成后执行方法

    <!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>& ...

  5. 关于maven中版本控制问题

    之前我们说过Maven的版本分为快照和稳定版本,快照版本使用在开发的过程中,方便于团队内部交流学习.而所说的稳定版本,理想状态下是项目到了某个比较稳定的状态,这个稳定包含了源代码和构建都要稳定. ma ...

  6. 安装opencv出现的问题

    ImportError: DLL load failed***** 1,pip uninstall opencv-python 卸载2,pip install opencv-contrib-pytho ...

  7. MySQL Lock--MySQL加锁学习2

    准备测试数据: ## 开启InnoDB Monitor SET GLOBAL innodb_status_output=ON; SET GLOBAL innodb_status_output_lock ...

  8. openwrt配置strongswan对接hillstone ipsec的笔记

    一.主要参考资料: https://openwrt.org/docs/guide-user/services/vpn/ipsec/strongswan/roadwarrior https://open ...

  9. STM32+IAR 解决Error[Pe147]: declaration is incompatible with "__nounwind __interwork __softfp unsigned

    在IAR中编译STM32工程,遇到 Error[Pe147]: declaration is incompatible with "__nounwind __interwork __soft ...

  10. HTML&CSS基础-CSS的语法

    HTML&CSS基础-CSS的语法 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.dome.html源代码 <!DOCTYPE html> <html ...