工作上遇到vulkan的一个扩展“VK_EXT_shader_subgroup_vote”,很讨厌的是在安卓GPU上,不支持这个扩展。所以研究了下这个扩展到底是如何使用的。
根据vulkan文档和OpenGL文档描述,提供了内置函数来计算一个group中一组布尔条件的组合,涉及到三个函数:
1) OpSubgroupAnyKHR/anyInvocationARB(bool value)
对于这个函数,如果在group中,至少有一个线程对于value 的条件成立,则返回true。否则就是false。
2) OpSubgroupAllKHR/allInvocationsARB(bool value)
对于这个函数,如果在group中,如果所有的线程对于value 的条件成立,则返回true。否则就是false。
3) OpSubgroupAllEqualKHR/allInvocationsEqualARB(bool value)
对于这个函数,如果在group中,如果所有的线程对于value 的条件值都一样,则返回true。否则就是false。
测试代码
1)OpSubgroupAnyKHR/anyInvocationARB
设置每个groupsize为8.
void main() {
uint x = gl_GlobalInvocationID.x;
output_arr[x] = uint(anyInvocationARB(x == 7));
}
输出为:
0,1
1,1
2,1
3,1
4,1
5,1
6,1
7,1
8,0
9,0
10,0
11,0
12,0
13,0
14,0
15,0
对于第一个group,有线程id等于7的条件,所以0~7的输出为1,8~15输出为0
2)OpSubgroupAllKHR/allInvocationsARB(bool value)
layout(local_size_x = 8) in;
void main() {
uint x = gl_GlobalInvocationID.x;
output_arr[x] = uint(allInvocationsARB(x == 7));
}
结果为:
0,0
1,0
2,0
3,0
4,0
5,0
6,0
7,0
8,0
9,0
10,0
11,0
12,0
13,0
14,0
15,0
显然,对于条件,group中都没办法都满足,所以输出全为0.
3)OpSubgroupAllEqualKHR/allInvocationsEqualARB(bool value)
layout(local_size_x = 8) in;
void main() {
uint x = gl_GlobalInvocationID.x;
output_arr[x] = uint(allInvocationsEqualARB(x == 9));
}
输出结果:
0,1
1,1
2,1
3,1
4,1
5,1
6,1
7,1
8,0
9,0
10,0
11,0
12,0
13,0
14,0
15,0
16,1
17,1
18,1
19,1
20,1
21,1
22,1
23,1
对于第一个group,因为x==9的结果都是false,也就是group内所有的结果相等,所以0~7输出为1.
对于第二个group,因为有个x==9的结果为true,但其他为false,所以8~15输出为0.
对于第二个group,因为x==9的结果都是false,所以16~23输出为1.
用法大致如上吧。