我正在开发一款大型游戏,当你在游戏世界中移动时,它会在关卡数据(包括着色器)中流动。因为着色器是在编译/链接时或在第一次使用时,我不希望在帧速率上出现问题。
我的着色器编译和链接工作在一个单独的线程上,它有自己的open-gl上下文。但是我无法让着色器的预热在单独的线程上工作(这样在首次使用着色器时没有性能损失。)
在iOS或OpenGL文档中,任何地方都没有提到预热。然而,它在OpenGL ES分析器中提到(从xcode分析时可用的仪器之一)。在这个工具中,每次使用之前没有用于渲染某些内容的着色器渲染某些内容时,我会收到“在预热阶段之外编译的着色器”警告。 “扩展细节”说明了这一点:
“OpenGL ES Analyzer检测到一个着色器编译,它不是初始预热阶段的一部分。着色器编译可能是一个耗时的操作。要避免它们,请预热所有用于渲染的着色器。为此,请在您的预制过程中进行预热应用程序启动并使用每个要使用的着色器程序执行绘图调用,使用任何gl状态设置,着色器程序将与。状态一起使用,例如混合,颜色掩码,逻辑运算,多重放大,纹理格式和点原始状态都可以影响着色器编译。“
“汇编”一词在这里有点令人困惑。顶点和片段着色器已经编译,程序已经链接。但是第一次使用给定的OpenGL状态渲染某些东西时,它会在着色器上做更多工作,以便针对该状态对其进行优化。
我有代码通过在首次使用之前渲染零大小的三角形来预热着色器。
如果我使用与正常渲染相同的Open GL上下文编译,链接和预热主线程上的着色器,那么它可以工作。但是,如果我在具有单独的Open GL上下文的后台线程上执行此操作,则它不起作用(它在首次使用时仍会收到Analyzer警告)。
所以......可能是在单独的上下文中预先设置着色器对其他上下文没有影响。或者可能是我没有所有相同的状态设置单独的上下文。可能需要设置很多潜在的Open GL状态。我正在后台线程上使用屏幕外渲染缓冲区,因此可以将其视为状态的一部分。
有没有人成功地在后台线程上进行预热?
答案 0 :(得分:8)
老实说,直到昨天我才对这件事情一无所知,虽然我已经在我的引擎优化工作了一段时间。所以,首先,谢谢你的提示:)。
从那时起我就开始研究着色器变暖的主题,而且我找不到很多东西。
我在标题为“ATI OpenGL编程和优化指南”的文档中提到了官方的AMD文档:
这是一个摘录,指的是着色器变暖:
引用:
虽然R500本身支持片段着色单元中的流量控制,但R300和R400 asics没有。 R300和R400的静态流量控制由驱动程序编译模拟 未使用的条件和基于设置常量的展开循环。即使是R500 asics系列 本机支持流控制,驱动程序仍将尝试编译静态流条件启用 它重新组织着色器指令以便更好地进行指令调度。驱动程序也会尝试缓存 远离已编译的着色器,以便为预期重用而设置特定的静态流条件。所以当 编写一个使用静态流控制的片段程序,建议“加热”着色器缓存 通过在使用公共静态条件的第一帧上渲染虚拟三角形 与着色器生命相关的排列。
我发现的最佳解释如下:
http://fgiesen.wordpress.com/2011/07/01/a-trip-through-the-graphics-pipeline-2011-part-1/
引用:
顺便说一下,这也是您第一次使用新着色器或资源时经常看到延迟的原因;很多创建/编译工作都是由驱动程序推迟的,只有在实际需要时才会执行(你不会相信某些应用程序创建了多少未使用的垃圾!)。图形程序员知道故事的另一面 - 如果你想确保实际创建某些东西(而不是只保留内存),你需要发出一个虚拟绘图调用,用它来“加热”。丑陋和烦人,但自从我1999年第一次开始使用3D硬件以来就是这种情况 - 这意味着,在这一点上它几乎是生活中的事实,所以要习惯它。 :)
在这个演示文稿中,提到了cryteck引擎如何在远程引擎上执行它,尽管它主要与DirectX有关。
http://www.powershow.com/view/11f2b1-MzUxN/Far_Cry_and_DirectX_flash_ppt_presentation
我希望这些链接在某种程度上有所帮助。