Unity 3 launched recently, and with Surface Shaders we made it much easier to handle lighting, shadowing & rendering paths pieces of shaders. But Unity can run on so many platforms (some having very different shader languages), yet you can write a shader once, and somehow it “just works” on all platforms. How do we do that? I’m going to talk about some behind-the-scenes technology involved in compiling shaders.
Unity 3是最近发布的,借助Surface Shaders,我们使处理着色器的照明,阴影和渲染路径变得更加容易。 但是Unity可以在许多平台上运行(某些平台使用的着色器语言非常不同),但是您可以编写一次着色器,并且某种程度上它“可以”在所有平台上运行。 我们该怎么做? 我将讨论一些有关编译着色器的幕后技术。
Warning: technical post ahead!
警告:技术职位提前!
Shading Languages
着色语言
There are two widely used shader languages out there: HLSL (or Cg, which is the same for practical purposes) and GLSL. Cg/HLSL is used by Direct3D, Xbox 360 and PS3. GLSL is used by mobile platforms (OpenGL ES 2.0), Mac OS X (OpenGL) and upcoming WebGL.
有两种广泛使用的着色器语言: HLSL (或Cg,实际用途相同)和GLSL 。 Direct3D,Xbox 360和PS3使用Cg / HLSL。 GLSL被移动平台(OpenGL ES 2.0),Mac OS X(OpenGL)和即将发布的WebGL使用。
Traditionally in Unity shaders are written in Cg/HLSL (there’s an option to write GLSL if you want to), so we had to find a way to take Cg shader and produce GLSL shader out of it. So you could write a shader like:
传统上,Unity着色器是用Cg / HLSL编写的(如果需要,可以选择编写GLSL),因此我们必须找到一种方法来提取Cg着色器并从中生成GLSL着色器。 因此,您可以编写如下的着色器:
1
23456 // ...vertex shader omittedsampler2D _MainTex;half4 _Color;half4 frag (float2 uv:TEXCOORD0) : COLOR {return tex2D (_MainTex, uv) * _Color;}
1
23456 // ...vertex shader omittedsampler2D _MainTex ;half4 _Color ;half4 frag ( float2 uv : TEXCOORD0 ) : COLOR {return tex2D ( _MainTex , uv ) * _Color ;}
…and somehow it would also work on mobile platforms on OpenGL ES 2.0. In short, you can do that in Unity 3. But if you want to know how that works, read on.
…并且以某种方式它也可以在OpenGL ES 2.0的移动平台上运行。 简而言之,您可以在Unity 3中做到这一点。但是,如果您想知道它是如何工作的,请继续阅读。
HLSL to GLSL Translator
HLSL到GLSL转换器
The two shading languages are similar in principle, but there are lots of subtle differences that make a regexp-based converter not quite work (regular expression based parsers are rarely a good idea by the way).
两种着色语言在原理上相似,但是有许多细微的差异,使得基于regexp的转换器无法正常工作(顺便说一句,基于正则表达式的解析器很少是个好主意 )。
So we took HLSL2GLSL, an existing open source project that ATI has made 4 years ago and seemingly abandoned. Turns out it needed some massaging to get it work, as well as a ton of bug fixes, missing features and general code cleanup. But hey, it seems to work now!
因此,我们采用了HLSL2GLSL ,这是ATI在4年前创建的一个现有开源项目,似乎已经放弃了。 事实证明,它需要一些按摩才能使其正常工作,以及大量的错误修复,功能缺失和常规代码清除。 但是,嘿,现在好像可以了!
Our fork of this translator, named “hlsl2glslfork”, is here: http://code.google.com/p/hlsl2glslfork/ (you can probably tell that I’m not too good at picking fancy names)
我们将此翻译的分支命名为“ hlsl2glslfork”,位于: http : //code.google.com/p/hlsl2glslfork/ (您可能会说我不太擅长选择花哨的名字)
So now we can translate Cg/HLSL shaders into GLSL, and we’re done? Turns out, not quite so.
现在,我们可以将Cg / HLSL着色器转换为GLSL,我们完成了吗? 事实并非如此。
GLSL Optimizer
GLSL优化器
The shaders produced by the translator work on mobile platforms (iOS/Android). However, some of them were running very slow. The OpenGL ES 2.0 drivers in the mobile platforms aren’t very good at optimizing shaders! Or rather, some of them are seriously bad at optimizing.
转换器产生的着色器可在移动平台(iOS / Android)上使用。 但是,其中一些运行非常缓慢。 移动平台中的OpenGL ES 2.0驱动程序在优化着色器方面不是很好! 或者更确切地说,其中一些在优化方面非常不利。
Suffice to say, something extremely simple like a particle shader was running 6 times slower than it should have. Six. Times. Ouch!
可以说,像粒子着色器这样的极其简单的东西的运行速度比其应有的速度慢6倍 。 六。 时间。 哎哟!
Almost by accident, I discovered that Mesa 3D guys are working on new GLSL compiler. I looked at the code and I liked it a lot; very hackable and “no bullshit” approach. So I took that Mesa’s GLSL compiler and made it output GLSL back after it has done all the optimizations (dead code removal, algebraic simplifications, constant propagation, constant folding, inlining and a bunch of other cryptic things that don’t mean anything to a normal person).
几乎是偶然,我发现Mesa 3D家伙正在开发新的GLSL编译器。 我看了一下代码,非常喜欢它。 非常容易破解且“胡说八道”的方法。 因此,我采用了Mesa的GLSL编译器,并在完成所有优化(死代码删除,代数简化,常数传播,常数折叠,内联以及其他对机器没有任何意义的其他事情)后,将其输出回GLSL。普通人)。
Here it is, named “GLSL Optimizer”: http://github.com/aras-p/glsl-optimizer (here’s my fancy-name-choosing in action again)
在这里,它被命名为“ GLSL Optimizer”: http : //github.com/aras-p/glsl-optimizer (这是我的幻想名称,再次在起作用)
The good news is that it solves the performance problems on iOS/Android platforms. Yay!
好消息是它解决了iOS / Android平台上的性能问题。 好极了!
Further work
进一步的工作
For mobile platforms, using appropriate precision qualifiers is very important for performance. If some value has low range and does not need high precision, using “lowp” (low precision) qualifier can potentially make the shader work much faster. In Unity 3.0 we do some automagic to put the appropriate precision, but we could be better at it. I’m experimenting with proper precision support in HLSL to GLSL translator and the GLSL Optimizer, so that fixed/half/float types in Cg/HLSL would come out as lowp/mediump/highp in the resulting GLSL… we’ll see how that turns out.
对于移动平台,使用适当的精度限定符对于性能非常重要。 如果某个值的范围较小且不需要高精度,则使用“ lowp”(低精度)限定符可能会使着色器工作得更快。 在Unity 3.0中,我们进行了一些自动调整以设置适当的精度,但是我们可以做得更好。 我正在HLSL到GLSL转换器和GLSL Optimizer中使用适当的精度支持进行试验,以便Cg / HLSL中的固定/半/浮点类型在生成的GLSL中会以lowp / mediump / highp的形式出现……我们将看到如何原来。
Maybe at some point in the future it would make sense to have the opposite translation tool? So one could write GLSL shaders, and they would be converted into Cg/HLSL for the other platforms…
也许在将来的某个时候,使用相反的翻译工具会有意义吗? 因此,可以编写GLSL着色器,并将其转换为其他平台的Cg / HLSL。
Oh, and next week Unity’s mobile tech. lead Renaldas “ReJ” Zioma is going to blog something technology related as well. Hear me ReJ? Now you have to do it!
哦,下周Unity的移动技术。 领导Renaldas“ ReJ” Zioma还将在博客中发布一些与技术相关的内容。 听到我ReJ吗? 现在,您必须这样做!
翻译自: https://blogs.unity3d.com/2010/10/20/shader-compilation-for-multiple-platforms/