天天看点

Optimizing Shader Load Time 优化Shader加载时间 性能系列6

Optimizing Shader Load Time 优化Shader加载时间

本文档主要是对Unity官方手册的个人理解与总结(其实以翻译记录为主:>)

仅作为个人学习使用,不得作为商业用途,欢迎转载,并请注明出处。

文章中涉及到的操作都是基于Unity2018.3版本

参考链接:https://docs.unity3d.com/Manual/OptimizingShaderLoadTime.html

Shaders are small programs that execute on the GPU, and loading them can take some time. Each individual GPU program typically does not take much time to load, but shaders often have a lot of “variants” internally.

着色器是在GPU上执行的小程序,加载它们需要一些时间。每个单独的GPU程序通常不会花费太多的时间去加载,但是着色器内部通常有很多“变体”。

For example, the Standard shader, if fully compiled, ends up being many thousands of slightly different GPU programs. This creates two potential problems:

例如,标准(Standard ) 着色器,如果完全编译,最终会变成成千上万个稍微不同的GPU程序。这就产生了两个潜在的问题:

  • Large numbers of these shader variants increase game build time, and game data size.

    大量的这些着色器变体增加了游戏构建时间和游戏数据大小。

  • Loading large numbers of shader variants during game is slow and takes up memory.

    在游戏中加载大量的着色器变体会很慢,并且会占用内存。

Shader build time stripping

剥离着色器构建时间

While building the game, Unity can detect that some of the internal shader variants are not used by the game, and skip them from build data. Build-time stripping is done for:

在构建游戏时,Unity可以检测到一些内部着色器变体没有被游戏使用,并从构建数据中跳过它们。剥离构建时间是做:

  • Individual shader features, for shaders that use #pragma shader_feature. If none of the used materials use a particular variant, then it is not included into the build. See internal shader variants documentation. Out of built-in shaders, the Standard shader uses this.

    独立的着色器特性,着色器使用#pragma shader_feature。如果使用过的材质没有使用特定的变体,那么它就不被包含在构建中。请参阅内部着色器变体文档。除了内置的着色器,标准的着色器也使用这个。

  • Shader variants to handle Fog and Lightmapping modes not used by any of the scenes are not included into the game data. See Graphics Settings if you want to override this behavior.

    如果所有场景都未使用雾和光照图模式,那么在游戏数据中将不会包含相应的着色器变体。如果要重写此行为,请查看图形设置。

Combination of the above often substantially cuts down on shader data size. For example, a fully compiled Standard shader would take several hundred megabytes, but in typical projects it often ends up taking just a couple megabytes (and is often compressed further by the application packaging process).

以上的组合通常会大大减少着色器数据的大小。例如,一个完全编译的标准着色器需要几百兆字节,但是在典型的项目中,它通常只需要几兆字节(并且经常被应用程序打包过程进一步压缩)。

Default Unity shader loading behavior

默认的Unity着色器加载行为

Under all default settings, Unity loads the shaderlab Shader object into memory, but does not create the internal shader variants until they are actually needed.

在所有的默认设置下,Unity将shaderlab Shader对象加载到内存中,但是直到真正需要时才创建内部的Shader变体。

This means that shader variants that are included into the game build can still potentially be used, but there’s no memory or load time cost paid until they are needed. For example, shaders always include a variant to handle point lights with shadows, but if you never end up using a point light with shadows in your game, then there’s no point in loading this particular variant.

这意味着包含在游戏构建中的着色器变体仍然可以被使用,但是在需要它们之前不需要支出内存或加载时间。例如,着色器总是包含一个变体来处理带有阴影的点光源,但是如果你在游戏中从未使用过带有阴影的点光源,那么就没有加载这个特定的变体。

One downside of this default behavior, however, is a possible hiccup for when some shader variant is needed for the first time - since a new GPU program code has to be loaded into the graphics driver. This is often undesirable during gameplay, so Unity has ShaderVariantCollection assets to help solve that.

不过,这种默认行为的一个缺点是,当首次需要某些着色器变体时,可能会出现峰值——因为必须将新的GPU程序代码加载到图形驱动程序中。这在游戏运行时中是不受欢迎的,所以Unity有ShaderVariantCollection资产来帮助解决这个问题。

Shader Variant Collections

Shader变体集

ShaderVariantCollection is an asset that is basically a list of Shaders, and for each of them, a list of Pass types and shader keyword combinations to load.

ShaderVariantCollection是一个资产,它基本上是一个着色器列表,对于每个着色器,一个通道类型列表和要加载的着色器关键字组合列表。

Optimizing Shader Load Time 优化Shader加载时间 性能系列6

To help with creating these assets based on actually used shaders and their variants, the editor can track which shaders and their variants are actually used. In Graphics Settings, there is a button to create a new ShaderVariantCollection out of currently tracked shaders, or to clear the currently tracked shader list.

为了帮助基于实际使用的着色器及其变体创建这些资产,编辑器可以跟踪哪些着色器及其变体被实际使用。在图形设置中,有一个按钮可以从当前跟踪的着色器中创建一个新的ShaderVariantCollection,或者清除当前跟踪的着色器列表。

Optimizing Shader Load Time 优化Shader加载时间 性能系列6

Once you have some ShaderVariantCollection assets, you can set for these variants to be automatically preloaded while loading the application (under Preloaded Shaders list in Graphics Settings), or you can preload an individual shader variant collection from a script.

一旦你有了ShaderVariantCollection的资产,你可以设置这些变体在加载应用程序时自动预加载(在图形设置的预加载着色器列表下),或者你可以从一个脚本预加载一个单独的着色器变量集合。

The Preloaded Shaders list is intended for frequently used shaders. Shader variants that are listed there the are loaded into memory for entire lifetime of the application. This may use significant amount of memory for ShaderVariantCollections assets that include large number of variants. To avoid that, ShaderVariantCollection assets should be created at smaller granularity and loaded from a script. One strategy is to record used shader variants for each scene, save them into separate ShaderVariantCollections assets and load them on scene startup.

预加载着色器列表是为经常使用的着色器设计的。这里列出的着色器变体将在应用程序的整个生命周期内加载到内存中。这可能会为包含大量变体的ShaderVariantCollections资产使用大量内存。为了避免这种情况,应该以更小的粒度创建ShaderVariantCollection资产,并从脚本加载。一种策略是记录每个场景中使用的着色器变体,将它们保存到单独的ShaderVariantCollections资产中,并在场景启动时加载它们。

继续阅读