通过制服打破 GLSL 循环
Breaking out of GLSL loops via a uniform
我想在浏览器中计算 GLSL 中浮点矩阵的每行最小值,大约 1000 行,4000 列。
基于之前的答案(参见 ),我使用了 for
循环。但是我想对上限使用统一的,这在 WebGL GLSL ES 1.0 中是不可能的。这是因为行的长度是在片段着色器之后定义的,我想避免弄乱 #DEFINE
s.
所以我发现这个解决方法 - 固定周期长度和由制服定义的 if/break
- 工作正常:
#define MAX_INT 65536
void main(void) {
float m = 0.0;
float k = -1.0;
int r = 40;
for(int i = 0; i < MAX_INT; ++i){
float ndx = floor(gl_FragCoord.y) * float(r) + float(i);
float a = getPoint(values, dimensions, ndx).x;
m = m > a ? m : a;
if (i >= r) { break; }
};
}
现在的问题是:这有很大的缺点吗?是不是我在做一些奇怪的事情并且遗漏了什么?
我相信,但我不完全确定,唯一的风险是 driver/gpu 仍然会进行长循环。
举个例子想象这个循环
uniform int limit;
void main() {
float sum = 0;
for (int i = 0; i < 3; ++i) {
sum += texture2D(tex, vec2(float(i) / 3, 0)).r;
if (i >= limit) {
break;
}
}
gl_FragColor = vec4(sum);
}
可以re-written被driver这样
uniform int limit;
void main() {
float sum = 0;
for (int i = 0; i < 3; ++i) {
float temp = texture2D(tex, vec2(float(i) / 3, 0)).r;
sum += temp * step(float(i), float(limit));
}
gl_FragColor = vec4(sum);
}
没有分支机构。我不知道这样的 drivers/gpus 是否仍然存在没有条件,但是循环需要 const 整数表达式的想法是这样可以删除分支 and/or 循环 un-rolled在编译时,如果 driver/GPU 决定做任何一个。
uniform int limit;
void main() {
float sum = 0;
sum += step(float(0), float(limit)) * texture2D(tex, vec2(float(0) / 3, 0)).r;
sum += step(float(1), float(limit)) * texture2D(tex, vec2(float(1) / 3, 0)).r;
sum += step(float(2), float(limit)) * texture2D(tex, vec2(float(2) / 3, 0)).r;
gl_FragColor = vec4(sum);
}
此外,顺便说一句,上面的具体示例不会输出任何内容,因此大多数 driver 会将整个着色器变成 no-op。
我想在浏览器中计算 GLSL 中浮点矩阵的每行最小值,大约 1000 行,4000 列。
基于之前的答案(参见 for
循环。但是我想对上限使用统一的,这在 WebGL GLSL ES 1.0 中是不可能的。这是因为行的长度是在片段着色器之后定义的,我想避免弄乱 #DEFINE
s.
所以我发现这个解决方法 - 固定周期长度和由制服定义的 if/break
- 工作正常:
#define MAX_INT 65536
void main(void) {
float m = 0.0;
float k = -1.0;
int r = 40;
for(int i = 0; i < MAX_INT; ++i){
float ndx = floor(gl_FragCoord.y) * float(r) + float(i);
float a = getPoint(values, dimensions, ndx).x;
m = m > a ? m : a;
if (i >= r) { break; }
};
}
现在的问题是:这有很大的缺点吗?是不是我在做一些奇怪的事情并且遗漏了什么?
我相信,但我不完全确定,唯一的风险是 driver/gpu 仍然会进行长循环。
举个例子想象这个循环
uniform int limit;
void main() {
float sum = 0;
for (int i = 0; i < 3; ++i) {
sum += texture2D(tex, vec2(float(i) / 3, 0)).r;
if (i >= limit) {
break;
}
}
gl_FragColor = vec4(sum);
}
可以re-written被driver这样
uniform int limit;
void main() {
float sum = 0;
for (int i = 0; i < 3; ++i) {
float temp = texture2D(tex, vec2(float(i) / 3, 0)).r;
sum += temp * step(float(i), float(limit));
}
gl_FragColor = vec4(sum);
}
没有分支机构。我不知道这样的 drivers/gpus 是否仍然存在没有条件,但是循环需要 const 整数表达式的想法是这样可以删除分支 and/or 循环 un-rolled在编译时,如果 driver/GPU 决定做任何一个。
uniform int limit;
void main() {
float sum = 0;
sum += step(float(0), float(limit)) * texture2D(tex, vec2(float(0) / 3, 0)).r;
sum += step(float(1), float(limit)) * texture2D(tex, vec2(float(1) / 3, 0)).r;
sum += step(float(2), float(limit)) * texture2D(tex, vec2(float(2) / 3, 0)).r;
gl_FragColor = vec4(sum);
}
此外,顺便说一句,上面的具体示例不会输出任何内容,因此大多数 driver 会将整个着色器变成 no-op。