GLSL中如何引用结构体?代码简化及性能疑问
GLSL中结构体局部变量的性能与代码简化问题
GLSL不支持C++风格的引用,这会让重复访问数组内结构体成员的代码显得冗余。比如这段重复写shadow.cascade[i]的代码:
for (int i=0; i<numCascades; ++i) { if (eyeDistance < shadow.cascade[i].end) { vec3 sc = eyePos*shadow.cascade[i].transform; // ...many more references to "shadow.cascade[i]" here } }
我们本能会想写成C++引用的形式来简化,但GLSL不支持:
for (int i=0; i<numCascades; ++i) { const ShadowCascade& cascade = shadow.cascade[i]; if (eyeDistance < cascade.end) { vec3 sc = eyePos*cascade.transform; // ...many more references to "cascade" here } }
那换成不带引用的局部变量赋值写法,会不会有性能损耗?结构体会不会像C++那样被复制到局部变量里?
for (int i=0; i<numCascades; ++i) { const ShadowCascade cascade = shadow.cascade[i]; if (eyeDistance < cascade.end) { vec3 sc = eyePos*cascade.transform; // ...many more references to "cascade" here } }
关于性能损耗的问题
不会有性能损耗。GLSL的GPU编译器(不管是NVIDIA、AMD还是Intel的实现)都会做常量传播、冗余访问消除这类优化,尤其是你用const修饰了这个局部变量,编译器能明确识别出你只是在复用shadow.cascade[i]的成员,不会真的把整个结构体复制到局部存储中。最终编译生成的GPU指令,和直接写shadow.cascade[i]是完全一致的。
GLSL中简化这类代码的常用方法
- 优先用
const局部变量赋值:就是你上面写的这种写法,既解决了代码冗余问题,又有类型安全保障,还不会引入性能问题,是最推荐的方案。 - 不要用
#define:宏是文本替换,没有类型检查,容易在复杂场景下引入难以排查的bug,完全没必要用它来做代码简化。 - 如果你用的是GLSL 4.30及以上版本,还可以考虑把结构体数组封装到接口块中,但这更多是管理数据结构的方式,对循环内的代码简化帮助不大,核心还是用
const局部变量来别名数组元素。
内容的提问来源于stack exchange,提问作者Chifti Saidi
相关产品推荐
相关产品推荐

