我刚从WWDC 2016的"金属中有什么新东西"视频中了解到function_constants,并且很多次提到UberShaders.我想创建一个片段超级着色器,可以用于不同类型的传递,如simplePassThrough,defferred等.以下是我想要使用它的方法.
constant int passType [[function_constant(0)]];
constant bool simplePassThrough = (passType == 0);
constant bool forwardShading = (passType == 1);
constant bool deferredShading = (passType == 2);
fragment FragmentOutStruct UberFragmentShader()
{
FragmentOutputStruct frgOut;
if (simplePassThrough) {
// Update frgOut
} else if (forwardShading) {
// Update frgOut
} else if (deferredShading) {
// Update frgOut
}
return frgOut;
}
Run Code Online (Sandbox Code Playgroud)
这是正确的方法吗?如果我使用这种方法,我最终编译的MTLFunction是否会看到太多分支?
是的,你走在正确的轨道上.(正如@warrenm已经注意到的那样.但是要扩大他的答案......)
您的示例与介绍函数常量的WWDC16会话中的Apple显示基本相同:您的"分支"都直接从函数常量值派生,这意味着着色器编译器可以(当您构建应用程序时)生成IR变体代码中依赖于函数常量值的每条可能路径.
在这里,你要传递int到着色器,但这并不意味着它必须编译2 32个着色器变体 - 编译器可以进行一些静态分析,并看到有四个可能的代码路径基于该值(0,1 ,2,以及其他任何东西,其中最后一个if完全忽略了陈述并返回frgOut).
在运行时,Metal框架根据您为常量传递的值确定要发送到GPU的四个着色器中的哪一个,因此在着色器/ GPU上没有分支.例如,如果传递的值为1,则运行的着色器基本上如下所示:
fragment FragmentOutStruct UberFragmentShader() {
FragmentOutputStruct frgOut;
// Update frgOut per `if (forwardShading)` chunk of original shader source
return frgOut;
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,该着色器中没有分支.
| 归档时间: |
|
| 查看次数: |
344 次 |
| 最近记录: |