我在尝试理解着色器语言中参数传递的实现方式。
我已经阅读了几篇文章和文档,但仍然有些疑问。特别是,我正在尝试理解与 C++
函数调用之间的区别,并着重关注性能方面的问题。
HLSL、Cg
和 GLSL
之间存在一些细微差异,但我想底层实现相当相似。
目前我所理解的:
- 除非另有规定,否则函数参数始终是按值传递的(即使是矩阵也是如此?)
- 在这种情况下,按值传递并不具有与
C++
相同的含义。不支持递归,因此不使用栈,并且大多数函数都是内联的,参数直接放入寄存器中。 - 默认情况下,函数通常都是内联的(
HLSL
),或者至少内联关键字总是受编译器尊重的(Cg
)
以上观点是否正确?
现在有两个具体问题:
将矩阵作为函数参数传递
inline float4 DoSomething(in Mat4x4 mat, in float3 vec) { ... }
考虑上面的函数,在 C++
中,这将是可怕的,最好使用引用:const Mat4x4&
。
那么在着色器中呢?这是一种不好的方法吗?我读到过例如可以使用 inout
限定符来按引用传递矩阵,但实际上它意味着被调用的函数将修改该矩阵..
参数数量(和类型)是否有任何影响?例如,使用具有有限参数集的函数是否更好?或避免传递矩阵? 在这里,
inout
修改器是否是提高性能的有效方法?如果是,任何人都知道典型编译器如何实现此操作吗?在这方面,
HLSL
和GLSL
之间有何区别? 有人对此有什么提示吗?
inout
并不是一种性能优化,而是GLSL中最接近引用的东西。实际上,正确的行为是在调用时复制数据,在返回时复制数据,但是优化编译器不会浪费时间进行不必要的复制,除非你像这里所示那样做某些事情。这回到了我在答案中讨论的内容,限定符本身并不重要,而是你传递的变量所做的事情真正重要。 - Andon M. ColemanFoo(myMat, myMat)
的意图。对于我们来说,聪明的编译器是一个黑盒子。但不要太认真地认为编译器会“复制”mat4的实例,因为规范并没有这样说。 - Chameleon