external/vulkancts/modules/vulkan/ssbo/vktSSBOCornerCase.cpp \
external/vulkancts/modules/vulkan/ssbo/vktSSBOLayoutCase.cpp \
external/vulkancts/modules/vulkan/ssbo/vktSSBOLayoutTests.cpp \
+ external/vulkancts/modules/vulkan/subgroups/vktSubgroupUniformControlFlowTests.cpp \
external/vulkancts/modules/vulkan/subgroups/vktSubgroupsArithmeticTests.cpp \
external/vulkancts/modules/vulkan/subgroups/vktSubgroupsBallotBroadcastTests.cpp \
external/vulkancts/modules/vulkan/subgroups/vktSubgroupsBallotMasksTests.cpp \
dEQP-VK.subgroups.size_control.ray_tracing.allow_varying_subgroup_size
dEQP-VK.subgroups.size_control.ray_tracing.required_subgroup_size_max
dEQP-VK.subgroups.size_control.ray_tracing.required_subgroup_size_min
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge00
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge01
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge02
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge03
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge04
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge05
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge06
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge07
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge08
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge09
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge10
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge11
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge12
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge13
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge14
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge15
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge16
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge17
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge18
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge19
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge20
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial00
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial01
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial02
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial03
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial04
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial05
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial06
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial07
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial08
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial09
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial10
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial11
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial12
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial13
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial14
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial15
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial16
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial17
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial18
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial19
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial20
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge00
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge01
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge02
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge03
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge04
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge05
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge06
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge07
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge08
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge09
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge10
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge11
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge12
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge13
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge14
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge15
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge16
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge17
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge18
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge19
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge20
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial00
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial01
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial02
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial03
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial04
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial05
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial06
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial07
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial08
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial09
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial10
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial11
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial12
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial13
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial14
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial15
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial16
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial17
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial18
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial19
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial20
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge00
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge01
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge02
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge03
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge04
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge05
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge06
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge07
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge08
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge09
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge10
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge11
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge12
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge13
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge14
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge15
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge16
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge17
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge18
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge19
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge20
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial00
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial01
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial02
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial03
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial04
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial05
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial06
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial07
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial08
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial09
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial10
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial11
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial12
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial13
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial14
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial15
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial16
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial17
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial18
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial19
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial20
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge00
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge01
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge02
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge03
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge04
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge05
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge06
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge07
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge08
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge09
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge10
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge11
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge12
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge13
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge14
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge15
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge16
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge17
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge18
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge19
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge20
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial00
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial01
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial02
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial03
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial04
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial05
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial06
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial07
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial08
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial09
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial10
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial11
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial12
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial13
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial14
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial15
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial16
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial17
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial18
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial19
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial20
+dEQP-VK.subgroups.subgroup_uniform_control_flow.discard.subgroup_reconverge_discard00
dEQP-VK.subgroups.size_control.ray_tracing.allow_varying_subgroup_size
dEQP-VK.subgroups.size_control.ray_tracing.required_subgroup_size_max
dEQP-VK.subgroups.size_control.ray_tracing.required_subgroup_size_min
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge00
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge01
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge02
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge03
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge04
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge05
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge06
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge07
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge08
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge09
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge10
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge11
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge12
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge13
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge14
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge15
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge16
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge17
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge18
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge19
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge20
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial00
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial01
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial02
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial03
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial04
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial05
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial06
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial07
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial08
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial09
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial10
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial11
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial12
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial13
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial14
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial15
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial16
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial17
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial18
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial19
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial20
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge00
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge01
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge02
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge03
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge04
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge05
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge06
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge07
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge08
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge09
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge10
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge11
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge12
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge13
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge14
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge15
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge16
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge17
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge18
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge19
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge20
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial00
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial01
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial02
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial03
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial04
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial05
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial06
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial07
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial08
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial09
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial10
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial11
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial12
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial13
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial14
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial15
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial16
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial17
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial18
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial19
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial20
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge00
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge01
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge02
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge03
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge04
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge05
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge06
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge07
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge08
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge09
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge10
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge11
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge12
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge13
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge14
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge15
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge16
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge17
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge18
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge19
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge20
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial00
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial01
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial02
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial03
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial04
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial05
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial06
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial07
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial08
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial09
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial10
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial11
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial12
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial13
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial14
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial15
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial16
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial17
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial18
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial19
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial20
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge00
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge01
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge02
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge03
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge04
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge05
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge06
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge07
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge08
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge09
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge10
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge11
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge12
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge13
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge14
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge15
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge16
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge17
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge18
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge19
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge20
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial00
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial01
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial02
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial03
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial04
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial05
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial06
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial07
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial08
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial09
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial10
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial11
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial12
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial13
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial14
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial15
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial16
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial17
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial18
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial19
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial20
+dEQP-VK.subgroups.subgroup_uniform_control_flow.discard.subgroup_reconverge_discard00
--- /dev/null
+#!amber
+
+SHADER vertex vtex_shader GLSL TARGET_ENV spv1.3
+#version 430
+layout(location = 0) in vec3 position;
+void main() {
+ gl_Position = vec4(position, 1.0);
+}
+END
+
+SHADER fragment compare_shader GLSL TARGET_ENV spv1.3
+#version 430
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_vote : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+
+layout(location = 0) out int compare;
+layout(location = 1) out vec4 out1;
+layout(location = 2) out vec4 out2;
+void main() [[subgroup_uniform_control_flow]] {
+ bool inbounds = (gl_FragCoord.x < 128 || gl_FragCoord.y < 128);
+ bool elect = subgroupElect();
+ if (elect) {
+ out1 = vec4(1.0, 0, 0, 1.0);
+ } else if (inbounds) {
+ out2 = vec4(0, 1.0, 0, 1.0);
+ } else {
+ discard;
+ }
+
+ bool a = (!inbounds && elect);
+ bool b = subgroupElect() == elect;
+ compare = (b && !a) ? 1 : -1;
+}
+END
+
+SHADER fragment expect_shader GLSL TARGET_ENV spv1.3
+#version 430
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_vote : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+
+layout(location = 0) out int expect;
+void main() {
+ bool inbounds = (gl_FragCoord.x < 128 || gl_FragCoord.y < 128);
+ expect = inbounds ? 1 : -1;
+}
+END
+
+BUFFER position_buf DATA_TYPE vec3<float> DATA
+-1 -1 0
+-1 1 0
+ 1 -1 0
+END
+
+BUFFER expect DATA_TYPE int32 SIZE 65536 FILL -1
+BUFFER compare DATA_TYPE int32 SIZE 65536 FILL -1
+BUFFER out1 DATA_TYPE vec4<float> SIZE 65536 FILL -1
+BUFFER out2 DATA_TYPE vec4<float> SIZE 65536 FILL -1
+
+PIPELINE graphics compare_pipe
+ ATTACH vtex_shader
+ ATTACH compare_shader
+
+ VERTEX_DATA position_buf LOCATION 0
+ BIND BUFFER compare AS color LOCATION 0
+ BIND BUFFER out1 AS color LOCATION 1
+ BIND BUFFER out2 AS color LOCATION 2
+ FRAMEBUFFER_SIZE 256 256
+END
+
+PIPELINE graphics expect_pipe
+ ATTACH vtex_shader
+ ATTACH expect_shader
+
+ VERTEX_DATA position_buf LOCATION 0
+ BIND BUFFER expect AS color LOCATION 0
+ FRAMEBUFFER_SIZE 256 256
+END
+
+RUN expect_pipe DRAW_ARRAY AS TRIANGLE_LIST START_IDX 0 COUNT 3
+RUN compare_pipe DRAW_ARRAY AS TRIANGLE_LIST START_IDX 0 COUNT 3
+EXPECT compare EQ_BUFFER expect
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ if (gl_SubgroupInvocationID == 0) {
+ c.c[idx] += 4;
+ } else {
+ c.c[idx]++;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ do {
+ c.c[idx] = d.d[idx];
+ } while (!subgroupElect());
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ while (true) {
+ atomicAdd(c.c[0], 1);
+ if (subgroupElect())
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) volatile buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ if (gl_SubgroupInvocationID == 0) {
+ d.d[idx] += 4;
+ } else {
+ c.c[idx]++;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 != 0)
+ return;
+
+ if (gl_SubgroupInvocationID == 0) {
+ c.c[idx] += 4;
+ } else {
+ c.c[idx]++;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) volatile buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 != 0)
+ return;
+
+ if (gl_SubgroupInvocationID == 0) {
+ c.c[idx] += 4;
+ } else {
+ c.c[idx]++;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (c.c[idx] > 5)
+ return;
+
+ while (true) {
+ if (d.d[idx]++ > idx)
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+
+ uint c_val = 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ c_val = 10;
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 1
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ while (true) {
+ if (c.c[idx] > 5)
+ return;
+ if (d.d[idx]++ > idx)
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+
+ uint c_val = 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ c_val = 10;
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 1
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (uint i = 0; i < c.c[idx]; ++i) {
+ if (a.a[gl_SubgroupID] % 2 != 0)
+ return;
+
+ atomicAdd(d.d[idx], 1);
+ if (i == gl_SubgroupID % 4)
+ break;
+ }
+
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (int i = 0; i < c.c[0]; ++i) {
+ atomicAdd(d.d[idx], 1);
+ if (a.a[idx] < 10) {
+ if (a.a[idx] == 0)
+ atomicAdd(d.d[idx], 2);
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = 50;
+ if (gl_SubgroupID % 2 == 0) {
+ if (gl_SubgroupInvocationID == 0)
+ a_val = 0;
+ else
+ a_val = 5;
+ }
+ a.a[idx] = a_val;
+
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 FILL 1
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (int i = 0; i < c.c[0]; ++i) {
+ atomicAdd(d.d[idx], 1);
+ if (a.a[idx] >= 10)
+ break;
+
+ if (a.a[idx] == 0)
+ atomicAdd(d.d[idx], 2);
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = 50;
+ if (gl_SubgroupID % 2 == 0) {
+ if (gl_SubgroupInvocationID == 0)
+ a_val = 0;
+ else
+ a_val = 5;
+ }
+ a.a[idx] = a_val;
+
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 FILL 1
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (int i = 0; i < c.c[0]; ++i) {
+ atomicAdd(d.d[idx], 1);
+ if (a.a[idx] >= 10)
+ continue;
+
+ if (a.a[idx] == 0)
+ atomicAdd(d.d[idx], 2);
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = 50;
+ if (gl_SubgroupID % 2 == 0) {
+ if (gl_SubgroupInvocationID == 0)
+ a_val = 0;
+ else
+ a_val = 5;
+ }
+ a.a[idx] = a_val;
+
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 FILL 1
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 != 0)
+ return;
+
+ switch (c.c[idx]) {
+ case 0:
+ case 1:
+ atomicAdd(d.d[idx], 1);
+ break;
+ case 2:
+ d.d[idx] = gl_SubgroupID;
+ break;
+ default:
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ c.c[idx] = gl_SubgroupID % 4;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[idx] % 2 != 0)
+ return;
+
+ switch (c.c[idx]) {
+ case 0:
+ case 1:
+ atomicAdd(d.d[idx], 1);
+ break;
+ default:
+ d.d[idx] = gl_SubgroupID;
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ a.a[idx] = gl_SubgroupID;
+
+ c.c[idx] = gl_SubgroupID % 4;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ switch (a.a[idx]) {
+ case 1:
+ atomicAdd(d.d[idx], 1);
+ // fallthrough...
+ case 3:
+ return;
+ default:
+ atomicExchange(d.d[0], gl_SubgroupID);
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ a.a[idx] = gl_SubgroupID % 4;
+
+ c.c[idx] = gl_SubgroupID;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ switch (a.a[idx]) {
+ case 1:
+ atomicAdd(d.d[idx], 1);
+ break;
+ case 3:
+ return;
+ default:
+ switch (c.c[idx]) {
+ case 0:
+ case 1:
+ atomicExchange(d.d[0], gl_SubgroupID);
+ break;
+ case 2:
+ c.c[idx]++;
+ break;
+ default:
+ atomicAdd(d.d[1], 32);
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ break;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ a.a[idx] = gl_SubgroupID % 4;
+
+ c.c[idx] = gl_SubgroupID;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (int i = 0; i < c.c[0]; ++i) {
+ atomicAdd(d.d[idx], 1);
+ if (a.a[idx] < 10) {
+ if (a.a[idx] == 0)
+ atomicAdd(d.d[idx], 2);
+ b.b[256 * i + idx] = subgroupElect() ? 1 : 0;
+ }
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = 50;
+ if (gl_SubgroupID % 2 == 0) {
+ if (gl_SubgroupInvocationID == 0)
+ a_val = 0;
+ else
+ a_val = 5;
+ }
+ a.a[idx] = a_val;
+
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[256 * 0 + idx] = cmp_val;
+ compare.x[256 * 1 + idx] = cmp_val;
+ compare.x[256 * 2 + idx] = cmp_val;
+ compare.x[256 * 3 + idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 1024 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 1024 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) volatile buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+
+ if (gl_SubgroupInvocationID == 0) {
+ c.c[idx] += 4;
+ if (a.a[gl_SubgroupID] % 2 != 0)
+ return;
+ } else {
+ c.c[idx]++;
+ if (a.a[gl_SubgroupID] % 2 != 0)
+ return;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_vote : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint c_val = c.c[idx];
+ if (!subgroupAllEqual(c_val)) {
+ atomicAdd(d.d[0], 1);
+ if (c_val % 2 == 0) {
+ atomicAdd(d.d[idx], gl_SubgroupID);
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+
+ uint c_val = c.c[idx];
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ c_val = 10;
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 SERIES_FROM 0 INC_BY 1
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_vote : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint c_val = c.c[idx];
+ bool test = (c_val % 2) == 0;
+ if (subgroupAny(test)) {
+ atomicAdd(d.d[0], 1);
+ if (a.a[gl_SubgroupID] % 2 != 0)
+ return;
+
+ if (c_val % 2 == 0) {
+ atomicAdd(d.d[idx], gl_SubgroupID);
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+
+ uint c_val = c.c[idx];
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ c_val = 10;
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 SERIES_FROM 0 INC_BY 1
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_vote : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = a.a[idx];
+ if (a_val < 128) {
+ uint c_val = c.c[idx];
+ switch (c_val) {
+ case 0:
+ atomicAdd(d.d[idx], 1);
+ break;
+ case 1:
+ case 2:
+ if (a_val > 4) {
+ uint val = a_val;
+ for (uint i = 0; i < 4; ++i) {
+ val = atomicExchange(d.d[0], val);
+ if (c_val == 1) return;
+ }
+ } else if (a_val == 3) {
+ atomicAdd(d.d[1], gl_SubgroupID);
+ } else {
+ atomicAdd(d.d[2], gl_SubgroupInvocationID);
+ if (c_val == 1) return;
+ }
+ break;
+ default:
+ if (a.a[gl_SubgroupID] % 2 != 0) return;
+ atomicExchange(d.d[idx], c_val);
+ break;
+ }
+ } else if (a_val < 192) {
+ atomicExchange(d.d[idx], a_val);
+ uint c_val = c.c[idx];
+ if (subgroupAny(c_val == 0)) {
+ return;
+ } else {
+ uint val = atomicAdd(d.d[idx], gl_SubgroupInvocationID);
+ while (!subgroupElect()) {
+ val = atomicExchange(d.d[0], val);
+ }
+ if (val > 10) {
+ atomicAnd(d.d[idx], 0xff00ff00);
+ }
+ }
+ } else {
+ if (a.a[gl_SubgroupID] % 2 != 0) return;
+ }
+
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ uint c_val = c.c[idx];
+ if (a.a[idx] < 128) {
+ if (gl_SubgroupID % 2 != 0) {
+ c_val = 1;
+ } else {
+ c_val = gl_SubgroupInvocationID % 4;
+ if (c_val == 1) c_val += 4;
+ }
+ } else if (a.a[idx] < 192) {
+ if (gl_SubgroupInvocationID == 0 && gl_SubgroupID % 2 != 0) {
+ c_val = 0;
+ } else {
+ c_val = c_val + 1;
+ }
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 SERIES_FROM 0 INC_BY 1
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ if (gl_SubgroupInvocationID == 0) {
+ c.c[idx] += 4;
+ } else {
+ c.c[idx]++;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ do {
+ c.c[idx] = d.d[idx];
+ } while (!subgroupElect());
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ while (true) {
+ atomicAdd(c.c[0], 1);
+ if (subgroupElect())
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) volatile buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ if (gl_SubgroupInvocationID == 0) {
+ d.d[idx] += 4;
+ } else {
+ c.c[idx]++;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 == 0)
+ return;
+
+ if (gl_SubgroupInvocationID == 0) {
+ c.c[idx] += 4;
+ } else {
+ c.c[idx]++;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) volatile buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 == 0)
+ return;
+
+ if (gl_SubgroupInvocationID == 0) {
+ c.c[idx] += 4;
+ } else {
+ c.c[idx]++;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (c.c[idx] > 5)
+ return;
+
+ while (true) {
+ if (d.d[idx]++ > idx)
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+
+ uint c_val = 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ c_val = 10;
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 1
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ while (true) {
+ if (c.c[idx] > 5)
+ return;
+ if (d.d[idx]++ > idx)
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+
+ uint c_val = 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ c_val = 10;
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 1
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (uint i = 0; i < c.c[idx]; ++i) {
+ if (a.a[gl_SubgroupID] % 2 == 0)
+ return;
+
+ atomicAdd(d.d[idx], 1);
+ if (i == gl_SubgroupID % 4)
+ break;
+ }
+
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (int i = 0; i < c.c[0]; ++i) {
+ atomicAdd(d.d[idx], 1);
+ if (a.a[idx] < 10) {
+ if (a.a[idx] == 0)
+ atomicAdd(d.d[idx], 2);
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = 50;
+ if (gl_SubgroupID % 2 != 0) {
+ if (gl_SubgroupInvocationID == 0)
+ a_val = 0;
+ else
+ a_val = 5;
+ }
+ a.a[idx] = a_val;
+
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 FILL 1
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (int i = 0; i < c.c[0]; ++i) {
+ atomicAdd(d.d[idx], 1);
+ if (a.a[idx] >= 10)
+ break;
+
+ if (a.a[idx] == 0)
+ atomicAdd(d.d[idx], 2);
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = 50;
+ if (gl_SubgroupID % 2 != 0) {
+ if (gl_SubgroupInvocationID == 0)
+ a_val = 0;
+ else
+ a_val = 5;
+ }
+ a.a[idx] = a_val;
+
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 FILL 1
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (int i = 0; i < c.c[0]; ++i) {
+ atomicAdd(d.d[idx], 1);
+ if (a.a[idx] >= 10)
+ continue;
+
+ if (a.a[idx] == 0)
+ atomicAdd(d.d[idx], 2);
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = 50;
+ if (gl_SubgroupID % 2 != 0) {
+ if (gl_SubgroupInvocationID == 0)
+ a_val = 0;
+ else
+ a_val = 5;
+ }
+ a.a[idx] = a_val;
+
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 FILL 1
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 == 0)
+ return;
+
+ switch (c.c[idx]) {
+ case 0:
+ case 1:
+ atomicAdd(d.d[idx], 1);
+ break;
+ case 2:
+ d.d[idx] = gl_SubgroupID;
+ break;
+ default:
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ c.c[idx] = gl_SubgroupID % 4;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[idx] % 2 == 0)
+ return;
+
+ switch (c.c[idx]) {
+ case 0:
+ case 1:
+ atomicAdd(d.d[idx], 1);
+ break;
+ default:
+ d.d[idx] = gl_SubgroupID;
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ a.a[idx] = gl_SubgroupID;
+
+ c.c[idx] = gl_SubgroupID % 4;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ switch (a.a[idx]) {
+ case 0:
+ atomicAdd(d.d[idx], 1);
+ // fallthrough...
+ case 2:
+ return;
+ default:
+ atomicExchange(d.d[0], gl_SubgroupID);
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ a.a[idx] = gl_SubgroupID % 4;
+
+ c.c[idx] = gl_SubgroupID;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ switch (a.a[idx]) {
+ case 0:
+ atomicAdd(d.d[idx], 1);
+ break;
+ case 2:
+ return;
+ default:
+ switch (c.c[idx]) {
+ case 0:
+ case 1:
+ atomicExchange(d.d[0], gl_SubgroupID);
+ break;
+ case 2:
+ c.c[idx]++;
+ break;
+ default:
+ atomicAdd(d.d[1], 32);
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ break;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ a.a[idx] = gl_SubgroupID % 4;
+
+ c.c[idx] = gl_SubgroupID;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (int i = 0; i < c.c[0]; ++i) {
+ atomicAdd(d.d[idx], 1);
+ if (a.a[idx] < 10) {
+ if (a.a[idx] == 0)
+ atomicAdd(d.d[idx], 2);
+ b.b[238 * i + idx] = subgroupElect() ? 1 : 0;
+ }
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = 50;
+ if (gl_SubgroupID % 2 != 0) {
+ if (gl_SubgroupInvocationID == 0)
+ a_val = 0;
+ else
+ a_val = 5;
+ }
+ a.a[idx] = a_val;
+
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[238 * 0 + idx] = cmp_val;
+ compare.x[238 * 1 + idx] = cmp_val;
+ compare.x[238 * 2 + idx] = cmp_val;
+ compare.x[238 * 3 + idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 952 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 952 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) volatile buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+
+ if (gl_SubgroupInvocationID == 0) {
+ c.c[idx] += 4;
+ if (a.a[gl_SubgroupID] % 2 == 0)
+ return;
+ } else {
+ c.c[idx]++;
+ if (a.a[gl_SubgroupID] % 2 == 0)
+ return;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_vote : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint c_val = c.c[idx];
+ if (!subgroupAllEqual(c_val)) {
+ atomicAdd(d.d[0], 1);
+ if (c_val % 2 != 0) {
+ atomicAdd(d.d[idx], gl_SubgroupID);
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+
+ uint c_val = c.c[idx];
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ c_val = 10;
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 SERIES_FROM 0 INC_BY 1
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_vote : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint c_val = c.c[idx];
+ bool test = (c_val % 2) != 0;
+ if (subgroupAny(test)) {
+ atomicAdd(d.d[0], 1);
+ if (a.a[gl_SubgroupID] % 2 == 0)
+ return;
+
+ if (c_val % 2 != 0) {
+ atomicAdd(d.d[idx], gl_SubgroupID);
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+
+ uint c_val = c.c[idx];
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ c_val = 10;
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 SERIES_FROM 0 INC_BY 1
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_vote : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = a.a[idx];
+ if (a_val < 128) {
+ uint c_val = c.c[idx];
+ switch (c_val) {
+ case 0:
+ atomicAdd(d.d[idx], 1);
+ break;
+ case 1:
+ case 2:
+ if (a_val > 4) {
+ uint val = a_val;
+ for (uint i = 0; i < 4; ++i) {
+ val = atomicExchange(d.d[0], val);
+ }
+ } else if (a_val == 3) {
+ atomicAdd(d.d[1], gl_SubgroupID);
+ } else {
+ atomicAdd(d.d[2], gl_SubgroupInvocationID);
+ }
+ if (c_val == 1) return;
+ break;
+ default:
+ if (a.a[gl_SubgroupID] % 2 == 0) return;
+ atomicExchange(d.d[idx], c_val);
+ break;
+ }
+ } else if (a_val < 192) {
+ atomicExchange(d.d[idx], a_val);
+ uint c_val = c.c[idx];
+ if (subgroupAny(c_val == 0)) {
+ return;
+ } else {
+ uint val = atomicAdd(d.d[idx], gl_SubgroupInvocationID);
+ while (!subgroupElect()) {
+ val = atomicExchange(d.d[0], val);
+ }
+ if (val > 10) {
+ atomicAnd(d.d[idx], 0xff00ff00);
+ }
+ }
+ } else {
+ if (a.a[gl_SubgroupID] % 2 == 0) return;
+ }
+
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ uint c_val = c.c[idx];
+ if (a.a[idx] < 128) {
+ if (gl_SubgroupID % 2 == 0) {
+ c_val = 1;
+ } else {
+ c_val = gl_SubgroupInvocationID % 4;
+ if (c_val == 1) c_val += 4;
+ }
+ } else if (a.a[idx] < 192) {
+ if (gl_SubgroupInvocationID == 0 && gl_SubgroupID % 2 == 0) {
+ c_val = 0;
+ } else {
+ c_val = c_val + 1;
+ }
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 SERIES_FROM 0 INC_BY 1
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ if (gl_SubgroupInvocationID == 0) {
+ c.c[idx] += 4;
+ } else {
+ c.c[idx]++;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ do {
+ c.c[idx] = d.d[idx];
+ } while (!subgroupElect());
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ while (true) {
+ atomicAdd(c.c[0], 1);
+ if (subgroupElect())
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) volatile buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ if (gl_SubgroupInvocationID == 0) {
+ d.d[idx] += 4;
+ } else {
+ c.c[idx]++;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 != 0)
+ return;
+
+ if (gl_SubgroupInvocationID == 0) {
+ c.c[idx] += 4;
+ } else {
+ c.c[idx]++;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) volatile buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 != 0)
+ return;
+
+ if (gl_SubgroupInvocationID == 0) {
+ c.c[idx] += 4;
+ } else {
+ c.c[idx]++;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (c.c[idx] > 5)
+ return;
+
+ while (true) {
+ if (d.d[idx]++ > idx)
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+
+ uint c_val = 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ c_val = 10;
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 1
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ while (true) {
+ if (c.c[idx] > 5)
+ return;
+ if (d.d[idx]++ > idx)
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+
+ uint c_val = 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ c_val = 10;
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 1
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (uint i = 0; i < c.c[idx]; ++i) {
+ if (a.a[gl_SubgroupID] % 2 != 0)
+ return;
+
+ atomicAdd(d.d[idx], 1);
+ if (i == gl_SubgroupID % 4)
+ break;
+ }
+
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (int i = 0; i < c.c[0]; ++i) {
+ atomicAdd(d.d[idx], 1);
+ if (a.a[idx] < 10) {
+ if (a.a[idx] == 0)
+ atomicAdd(d.d[idx], 2);
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = 50;
+ if (gl_SubgroupID % 2 == 0) {
+ if (gl_SubgroupInvocationID == 0)
+ a_val = 0;
+ else
+ a_val = 5;
+ }
+ a.a[idx] = a_val;
+
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 FILL 1
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (int i = 0; i < c.c[0]; ++i) {
+ atomicAdd(d.d[idx], 1);
+ if (a.a[idx] >= 10)
+ break;
+
+ if (a.a[idx] == 0)
+ atomicAdd(d.d[idx], 2);
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = 50;
+ if (gl_SubgroupID % 2 == 0) {
+ if (gl_SubgroupInvocationID == 0)
+ a_val = 0;
+ else
+ a_val = 5;
+ }
+ a.a[idx] = a_val;
+
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 FILL 1
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (int i = 0; i < c.c[0]; ++i) {
+ atomicAdd(d.d[idx], 1);
+ if (a.a[idx] >= 10)
+ continue;
+
+ if (a.a[idx] == 0)
+ atomicAdd(d.d[idx], 2);
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = 50;
+ if (gl_SubgroupID % 2 == 0) {
+ if (gl_SubgroupInvocationID == 0)
+ a_val = 0;
+ else
+ a_val = 5;
+ }
+ a.a[idx] = a_val;
+
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 FILL 1
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 != 0)
+ return;
+
+ switch (c.c[idx]) {
+ case 0:
+ case 1:
+ atomicAdd(d.d[idx], 1);
+ break;
+ case 2:
+ d.d[idx] = gl_SubgroupID;
+ break;
+ default:
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ c.c[idx] = gl_SubgroupID % 4;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[idx] % 2 != 0)
+ return;
+
+ switch (c.c[idx]) {
+ case 0:
+ case 1:
+ atomicAdd(d.d[idx], 1);
+ break;
+ default:
+ d.d[idx] = gl_SubgroupID;
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ a.a[idx] = gl_SubgroupID;
+
+ c.c[idx] = gl_SubgroupID % 4;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ switch (a.a[idx]) {
+ case 1:
+ atomicAdd(d.d[idx], 1);
+ // fallthrough...
+ case 3:
+ return;
+ default:
+ atomicExchange(d.d[0], gl_SubgroupID);
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ a.a[idx] = gl_SubgroupID % 4;
+
+ c.c[idx] = gl_SubgroupID;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ switch (a.a[idx]) {
+ case 1:
+ atomicAdd(d.d[idx], 1);
+ break;
+ case 3:
+ return;
+ default:
+ switch (c.c[idx]) {
+ case 0:
+ case 1:
+ atomicExchange(d.d[0], gl_SubgroupID);
+ break;
+ case 2:
+ c.c[idx]++;
+ break;
+ default:
+ atomicAdd(d.d[1], 32);
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ break;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ a.a[idx] = gl_SubgroupID % 4;
+
+ c.c[idx] = gl_SubgroupID;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (int i = 0; i < c.c[0]; ++i) {
+ atomicAdd(d.d[idx], 1);
+ if (a.a[idx] < 10) {
+ if (a.a[idx] == 0)
+ atomicAdd(d.d[idx], 2);
+ b.b[256 * i + idx] = subgroupElect() ? 1 : 0;
+ }
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = 50;
+ if (gl_SubgroupID % 2 == 0) {
+ if (gl_SubgroupInvocationID == 0)
+ a_val = 0;
+ else
+ a_val = 5;
+ }
+ a.a[idx] = a_val;
+
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[256 * 0 + idx] = cmp_val;
+ compare.x[256 * 1 + idx] = cmp_val;
+ compare.x[256 * 2 + idx] = cmp_val;
+ compare.x[256 * 3 + idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 1024 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 1024 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) volatile buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+
+ if (gl_SubgroupInvocationID == 0) {
+ c.c[idx] += 4;
+ if (a.a[gl_SubgroupID] % 2 != 0)
+ return;
+ } else {
+ c.c[idx]++;
+ if (a.a[gl_SubgroupID] % 2 != 0)
+ return;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_vote : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint c_val = c.c[idx];
+ if (!subgroupAllEqual(c_val)) {
+ atomicAdd(d.d[0], 1);
+ if (c_val % 2 == 0) {
+ atomicAdd(d.d[idx], gl_SubgroupID);
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+
+ uint c_val = c.c[idx];
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ c_val = 10;
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 SERIES_FROM 0 INC_BY 1
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_vote : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint c_val = c.c[idx];
+ bool test = (c_val % 2) == 0;
+ if (subgroupAny(test)) {
+ atomicAdd(d.d[0], 1);
+ if (a.a[gl_SubgroupID] % 2 != 0)
+ return;
+
+ if (c_val % 2 == 0) {
+ atomicAdd(d.d[idx], gl_SubgroupID);
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+
+ uint c_val = c.c[idx];
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ c_val = 10;
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 SERIES_FROM 0 INC_BY 1
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_vote : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = a.a[idx];
+ if (a_val < 128) {
+ uint c_val = c.c[idx];
+ switch (c_val) {
+ case 0:
+ atomicAdd(d.d[idx], 1);
+ break;
+ case 1:
+ case 2:
+ if (a_val > 4) {
+ uint val = a_val;
+ for (uint i = 0; i < 4; ++i) {
+ val = atomicExchange(d.d[0], val);
+ if (c_val == 1) return;
+ }
+ } else if (a_val == 3) {
+ atomicAdd(d.d[1], gl_SubgroupID);
+ } else {
+ atomicAdd(d.d[2], gl_SubgroupInvocationID);
+ if (c_val == 1) return;
+ }
+ break;
+ default:
+ if (a.a[gl_SubgroupID] % 2 != 0) return;
+ atomicExchange(d.d[idx], c_val);
+ break;
+ }
+ } else if (a_val < 192) {
+ atomicExchange(d.d[idx], a_val);
+ uint c_val = c.c[idx];
+ if (subgroupAny(c_val == 0)) {
+ return;
+ } else {
+ uint val = atomicAdd(d.d[idx], gl_SubgroupInvocationID);
+ while (!subgroupElect()) {
+ val = atomicExchange(d.d[0], val);
+ }
+ if (val > 10) {
+ atomicAnd(d.d[idx], 0xff00ff00);
+ }
+ }
+ } else {
+ if (a.a[gl_SubgroupID] % 2 != 0) return;
+ }
+
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ uint c_val = c.c[idx];
+ if (a.a[idx] < 128) {
+ if (gl_SubgroupID % 2 != 0) {
+ c_val = 1;
+ } else {
+ c_val = gl_SubgroupInvocationID % 4;
+ if (c_val == 1) c_val += 4;
+ }
+ } else if (a.a[idx] < 192) {
+ if (gl_SubgroupInvocationID == 0 && gl_SubgroupID % 2 != 0) {
+ c_val = 0;
+ } else {
+ c_val = c_val + 1;
+ }
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 256 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 256 SERIES_FROM 0 INC_BY 1
+BUFFER d DATA_TYPE uint32 SIZE 256 FILL 4
+BUFFER compare DATA_TYPE uint32 SIZE 256 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ if (gl_SubgroupInvocationID == 0) {
+ c.c[idx] += 4;
+ } else {
+ c.c[idx]++;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ do {
+ c.c[idx] = d.d[idx];
+ } while (!subgroupElect());
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ while (true) {
+ atomicAdd(c.c[0], 1);
+ if (subgroupElect())
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) volatile buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ if (gl_SubgroupInvocationID == 0) {
+ d.d[idx] += 4;
+ } else {
+ c.c[idx]++;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 == 0)
+ return;
+
+ if (gl_SubgroupInvocationID == 0) {
+ c.c[idx] += 4;
+ } else {
+ c.c[idx]++;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) volatile buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 == 0)
+ return;
+
+ if (gl_SubgroupInvocationID == 0) {
+ c.c[idx] += 4;
+ } else {
+ c.c[idx]++;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (c.c[idx] > 5)
+ return;
+
+ while (true) {
+ if (d.d[idx]++ > idx)
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+
+ uint c_val = 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ c_val = 10;
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 1
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ while (true) {
+ if (c.c[idx] > 5)
+ return;
+ if (d.d[idx]++ > idx)
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+
+ uint c_val = 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ c_val = 10;
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 1
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (uint i = 0; i < c.c[idx]; ++i) {
+ if (a.a[gl_SubgroupID] % 2 == 0)
+ return;
+
+ atomicAdd(d.d[idx], 1);
+ if (i == gl_SubgroupID % 4)
+ break;
+ }
+
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (int i = 0; i < c.c[0]; ++i) {
+ atomicAdd(d.d[idx], 1);
+ if (a.a[idx] < 10) {
+ if (a.a[idx] == 0)
+ atomicAdd(d.d[idx], 2);
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = 50;
+ if (gl_SubgroupID % 2 != 0) {
+ if (gl_SubgroupInvocationID == 0)
+ a_val = 0;
+ else
+ a_val = 5;
+ }
+ a.a[idx] = a_val;
+
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 FILL 1
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (int i = 0; i < c.c[0]; ++i) {
+ atomicAdd(d.d[idx], 1);
+ if (a.a[idx] >= 10)
+ break;
+
+ if (a.a[idx] == 0)
+ atomicAdd(d.d[idx], 2);
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = 50;
+ if (gl_SubgroupID % 2 != 0) {
+ if (gl_SubgroupInvocationID == 0)
+ a_val = 0;
+ else
+ a_val = 5;
+ }
+ a.a[idx] = a_val;
+
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 FILL 1
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (int i = 0; i < c.c[0]; ++i) {
+ atomicAdd(d.d[idx], 1);
+ if (a.a[idx] >= 10)
+ continue;
+
+ if (a.a[idx] == 0)
+ atomicAdd(d.d[idx], 2);
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = 50;
+ if (gl_SubgroupID % 2 != 0) {
+ if (gl_SubgroupInvocationID == 0)
+ a_val = 0;
+ else
+ a_val = 5;
+ }
+ a.a[idx] = a_val;
+
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 FILL 1
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 == 0)
+ return;
+
+ switch (c.c[idx]) {
+ case 0:
+ case 1:
+ atomicAdd(d.d[idx], 1);
+ break;
+ case 2:
+ d.d[idx] = gl_SubgroupID;
+ break;
+ default:
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ c.c[idx] = gl_SubgroupID % 4;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[idx] % 2 == 0)
+ return;
+
+ switch (c.c[idx]) {
+ case 0:
+ case 1:
+ atomicAdd(d.d[idx], 1);
+ break;
+ default:
+ d.d[idx] = gl_SubgroupID;
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ a.a[idx] = gl_SubgroupID;
+
+ c.c[idx] = gl_SubgroupID % 4;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ switch (a.a[idx]) {
+ case 0:
+ atomicAdd(d.d[idx], 1);
+ // fallthrough...
+ case 2:
+ return;
+ default:
+ atomicExchange(d.d[0], gl_SubgroupID);
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ a.a[idx] = gl_SubgroupID % 4;
+
+ c.c[idx] = gl_SubgroupID;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ switch (a.a[idx]) {
+ case 0:
+ atomicAdd(d.d[idx], 1);
+ break;
+ case 2:
+ return;
+ default:
+ switch (c.c[idx]) {
+ case 0:
+ case 1:
+ atomicExchange(d.d[0], gl_SubgroupID);
+ break;
+ case 2:
+ c.c[idx]++;
+ break;
+ default:
+ atomicAdd(d.d[1], 32);
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ break;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ a.a[idx] = gl_SubgroupID % 4;
+
+ c.c[idx] = gl_SubgroupID;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (int i = 0; i < c.c[0]; ++i) {
+ atomicAdd(d.d[idx], 1);
+ if (a.a[idx] < 10) {
+ if (a.a[idx] == 0)
+ atomicAdd(d.d[idx], 2);
+ b.b[238 * i + idx] = subgroupElect() ? 1 : 0;
+ }
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = 50;
+ if (gl_SubgroupID % 2 != 0) {
+ if (gl_SubgroupInvocationID == 0)
+ a_val = 0;
+ else
+ a_val = 5;
+ }
+ a.a[idx] = a_val;
+
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[238 * 0 + idx] = cmp_val;
+ compare.x[238 * 1 + idx] = cmp_val;
+ compare.x[238 * 2 + idx] = cmp_val;
+ compare.x[238 * 3 + idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 952 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 952 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) volatile buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+
+ if (gl_SubgroupInvocationID == 0) {
+ c.c[idx] += 4;
+ if (a.a[gl_SubgroupID] % 2 == 0)
+ return;
+ } else {
+ c.c[idx]++;
+ if (a.a[gl_SubgroupID] % 2 == 0)
+ return;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_vote : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint c_val = c.c[idx];
+ if (!subgroupAllEqual(c_val)) {
+ atomicAdd(d.d[0], 1);
+ if (c_val % 2 != 0) {
+ atomicAdd(d.d[idx], gl_SubgroupID);
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+
+ uint c_val = c.c[idx];
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ c_val = 10;
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 SERIES_FROM 0 INC_BY 1
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_vote : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint c_val = c.c[idx];
+ bool test = (c_val % 2) != 0;
+ if (subgroupAny(test)) {
+ atomicAdd(d.d[0], 1);
+ if (a.a[gl_SubgroupID] % 2 == 0)
+ return;
+
+ if (c_val % 2 != 0) {
+ atomicAdd(d.d[idx], gl_SubgroupID);
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+
+ uint c_val = c.c[idx];
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ c_val = 10;
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 SERIES_FROM 0 INC_BY 1
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_vote : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = a.a[idx];
+ if (a_val < 128) {
+ uint c_val = c.c[idx];
+ switch (c_val) {
+ case 0:
+ atomicAdd(d.d[idx], 1);
+ break;
+ case 1:
+ case 2:
+ if (a_val > 4) {
+ uint val = a_val;
+ for (uint i = 0; i < 4; ++i) {
+ val = atomicExchange(d.d[0], val);
+ }
+ } else if (a_val == 3) {
+ atomicAdd(d.d[1], gl_SubgroupID);
+ } else {
+ atomicAdd(d.d[2], gl_SubgroupInvocationID);
+ }
+ if (c_val == 1) return;
+ break;
+ default:
+ if (a.a[gl_SubgroupID] % 2 == 0) return;
+ atomicExchange(d.d[idx], c_val);
+ break;
+ }
+ } else if (a_val < 192) {
+ atomicExchange(d.d[idx], a_val);
+ uint c_val = c.c[idx];
+ if (subgroupAny(c_val == 0)) {
+ return;
+ } else {
+ uint val = atomicAdd(d.d[idx], gl_SubgroupInvocationID);
+ while (!subgroupElect()) {
+ val = atomicExchange(d.d[0], val);
+ }
+ if (val > 10) {
+ atomicAnd(d.d[idx], 0xff00ff00);
+ }
+ }
+ } else {
+ if (a.a[gl_SubgroupID] % 2 == 0) return;
+ }
+
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 2, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ uint c_val = c.c[idx];
+ if (a.a[idx] < 128) {
+ if (gl_SubgroupID % 2 == 0) {
+ c_val = 1;
+ } else {
+ c_val = gl_SubgroupInvocationID % 4;
+ if (c_val == 1) c_val += 4;
+ }
+ } else if (a.a[idx] < 192) {
+ if (gl_SubgroupInvocationID == 0 && gl_SubgroupID % 2 == 0) {
+ c_val = 0;
+ } else {
+ c_val = c_val + 1;
+ }
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 SERIES_FROM 0 INC_BY 1
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ if (gl_SubgroupInvocationID == 0) {
+ c.c[idx] += 4;
+ } else {
+ c.c[idx]++;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ do {
+ c.c[idx] = d.d[idx];
+ } while (!subgroupElect());
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ while (true) {
+ atomicAdd(c.c[0], 1);
+ if (subgroupElect())
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) volatile buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ if (gl_SubgroupInvocationID == 0) {
+ d.d[idx] += 4;
+ } else {
+ c.c[idx]++;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 != 0)
+ return;
+
+ if (gl_SubgroupInvocationID == 0) {
+ c.c[idx] += 4;
+ } else {
+ c.c[idx]++;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) volatile buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 != 0)
+ return;
+
+ if (gl_SubgroupInvocationID == 0) {
+ c.c[idx] += 4;
+ } else {
+ c.c[idx]++;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (c.c[idx] > 5)
+ return;
+
+ while (true) {
+ if (d.d[idx]++ > idx)
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+
+ uint c_val = 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ c_val = 10;
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 1
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ while (true) {
+ if (c.c[idx] > 5)
+ return;
+ if (d.d[idx]++ > idx)
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+
+ uint c_val = 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ c_val = 10;
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 1
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (uint i = 0; i < c.c[idx]; ++i) {
+ if (a.a[gl_SubgroupID] % 2 != 0)
+ return;
+
+ atomicAdd(d.d[idx], 1);
+ if (i == gl_SubgroupID % 4)
+ break;
+ }
+
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (int i = 0; i < c.c[0]; ++i) {
+ atomicAdd(d.d[idx], 1);
+ if (a.a[idx] < 10) {
+ if (a.a[idx] == 0)
+ atomicAdd(d.d[idx], 2);
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = 50;
+ if (gl_SubgroupID % 2 == 0) {
+ if (gl_SubgroupInvocationID == 0)
+ a_val = 0;
+ else
+ a_val = 5;
+ }
+ a.a[idx] = a_val;
+
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 1
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (int i = 0; i < c.c[0]; ++i) {
+ atomicAdd(d.d[idx], 1);
+ if (a.a[idx] >= 10)
+ break;
+
+ if (a.a[idx] == 0)
+ atomicAdd(d.d[idx], 2);
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = 50;
+ if (gl_SubgroupID % 2 == 0) {
+ if (gl_SubgroupInvocationID == 0)
+ a_val = 0;
+ else
+ a_val = 5;
+ }
+ a.a[idx] = a_val;
+
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 1
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (int i = 0; i < c.c[0]; ++i) {
+ atomicAdd(d.d[idx], 1);
+ if (a.a[idx] >= 10)
+ continue;
+
+ if (a.a[idx] == 0)
+ atomicAdd(d.d[idx], 2);
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = 50;
+ if (gl_SubgroupID % 2 == 0) {
+ if (gl_SubgroupInvocationID == 0)
+ a_val = 0;
+ else
+ a_val = 5;
+ }
+ a.a[idx] = a_val;
+
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 1
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 != 0)
+ return;
+
+ switch (c.c[idx]) {
+ case 0:
+ case 1:
+ atomicAdd(d.d[idx], 1);
+ break;
+ case 2:
+ d.d[idx] = gl_SubgroupID;
+ break;
+ default:
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ c.c[idx] = gl_SubgroupID % 4;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[idx] % 2 != 0)
+ return;
+
+ switch (c.c[idx]) {
+ case 0:
+ case 1:
+ atomicAdd(d.d[idx], 1);
+ break;
+ default:
+ d.d[idx] = gl_SubgroupID;
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ a.a[idx] = gl_SubgroupID;
+
+ c.c[idx] = gl_SubgroupID % 4;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ switch (a.a[idx]) {
+ case 1:
+ atomicAdd(d.d[idx], 1);
+ // fallthrough...
+ case 3:
+ return;
+ default:
+ atomicExchange(d.d[0], gl_SubgroupID);
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ a.a[idx] = gl_SubgroupID % 4;
+
+ c.c[idx] = gl_SubgroupID;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ switch (a.a[idx]) {
+ case 1:
+ atomicAdd(d.d[idx], 1);
+ break;
+ case 3:
+ return;
+ default:
+ switch (c.c[idx]) {
+ case 0:
+ case 1:
+ atomicExchange(d.d[0], gl_SubgroupID);
+ break;
+ case 2:
+ c.c[idx]++;
+ break;
+ default:
+ atomicAdd(d.d[1], 32);
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ break;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ a.a[idx] = gl_SubgroupID % 4;
+
+ c.c[idx] = gl_SubgroupID;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (int i = 0; i < c.c[0]; ++i) {
+ atomicAdd(d.d[idx], 1);
+ if (a.a[idx] < 10) {
+ if (a.a[idx] == 0)
+ atomicAdd(d.d[idx], 2);
+ b.b[128 * i + idx] = subgroupElect() ? 1 : 0;
+ }
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = 50;
+ if (gl_SubgroupID % 2 == 0) {
+ if (gl_SubgroupInvocationID == 0)
+ a_val = 0;
+ else
+ a_val = 5;
+ }
+ a.a[idx] = a_val;
+
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[128 * 0 + idx] = cmp_val;
+ compare.x[128 * 1 + idx] = cmp_val;
+ compare.x[128 * 2 + idx] = cmp_val;
+ compare.x[128 * 3 + idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 512 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 512 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) volatile buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+
+ if (gl_SubgroupInvocationID == 0) {
+ c.c[idx] += 4;
+ if (a.a[gl_SubgroupID] % 2 != 0)
+ return;
+ } else {
+ c.c[idx]++;
+ if (a.a[gl_SubgroupID] % 2 != 0)
+ return;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_vote : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint c_val = c.c[idx];
+ if (!subgroupAllEqual(c_val)) {
+ atomicAdd(d.d[0], 1);
+ if (c_val % 2 == 0) {
+ atomicAdd(d.d[idx], gl_SubgroupID);
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+
+ uint c_val = c.c[idx];
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ c_val = 10;
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 SERIES_FROM 0 INC_BY 1
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_vote : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint c_val = c.c[idx];
+ bool test = (c_val % 2) == 0;
+ if (subgroupAny(test)) {
+ atomicAdd(d.d[0], 1);
+ if (a.a[gl_SubgroupID] % 2 != 0)
+ return;
+
+ if (c_val % 2 == 0) {
+ atomicAdd(d.d[idx], gl_SubgroupID);
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+
+ uint c_val = c.c[idx];
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ c_val = 10;
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 SERIES_FROM 0 INC_BY 1
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_vote : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = a.a[idx];
+ if (a_val < 128) {
+ uint c_val = c.c[idx];
+ switch (c_val) {
+ case 0:
+ atomicAdd(d.d[idx], 1);
+ break;
+ case 1:
+ case 2:
+ if (a_val > 4) {
+ uint val = a_val;
+ for (uint i = 0; i < 4; ++i) {
+ val = atomicExchange(d.d[0], val);
+ if (c_val == 1) return;
+ }
+ } else if (a_val == 3) {
+ atomicAdd(d.d[1], gl_SubgroupID);
+ } else {
+ atomicAdd(d.d[2], gl_SubgroupInvocationID);
+ if (c_val == 1) return;
+ }
+ break;
+ default:
+ if (a.a[gl_SubgroupID] % 2 != 0) return;
+ atomicExchange(d.d[idx], c_val);
+ break;
+ }
+ } else if (a_val < 192) {
+ atomicExchange(d.d[idx], a_val);
+ uint c_val = c.c[idx];
+ if (subgroupAny(c_val == 0)) {
+ return;
+ } else {
+ uint val = atomicAdd(d.d[idx], gl_SubgroupInvocationID);
+ while (!subgroupElect()) {
+ val = atomicExchange(d.d[0], val);
+ }
+ if (val > 10) {
+ atomicAnd(d.d[idx], 0xff00ff00);
+ }
+ }
+ } else {
+ if (a.a[gl_SubgroupID] % 2 != 0) return;
+ }
+
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ uint c_val = c.c[idx];
+ if (a.a[idx] < 128) {
+ if (gl_SubgroupID % 2 != 0) {
+ c_val = 1;
+ } else {
+ c_val = gl_SubgroupInvocationID % 4;
+ if (c_val == 1) c_val += 4;
+ }
+ } else if (a.a[idx] < 192) {
+ if (gl_SubgroupInvocationID == 0 && gl_SubgroupID % 2 != 0) {
+ c_val = 0;
+ } else {
+ c_val = c_val + 1;
+ }
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 SERIES_FROM 0 INC_BY 1
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ if (gl_SubgroupInvocationID == 0) {
+ c.c[idx] += 4;
+ } else {
+ c.c[idx]++;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 119 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 119 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 119 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ do {
+ c.c[idx] = d.d[idx];
+ } while (!subgroupElect());
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 119 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 119 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 119 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ while (true) {
+ atomicAdd(c.c[0], 1);
+ if (subgroupElect())
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 119 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 119 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 119 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) volatile buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ if (gl_SubgroupInvocationID == 0) {
+ d.d[idx] += 4;
+ } else {
+ c.c[idx]++;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 119 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 119 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 119 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 == 0)
+ return;
+
+ if (gl_SubgroupInvocationID == 0) {
+ c.c[idx] += 4;
+ } else {
+ c.c[idx]++;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 119 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 119 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 119 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) volatile buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 == 0)
+ return;
+
+ if (gl_SubgroupInvocationID == 0) {
+ c.c[idx] += 4;
+ } else {
+ c.c[idx]++;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 119 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 119 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 119 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (c.c[idx] > 5)
+ return;
+
+ while (true) {
+ if (d.d[idx]++ > idx)
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+
+ uint c_val = 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ c_val = 10;
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 119 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 119 FILL 1
+BUFFER compare DATA_TYPE uint32 SIZE 119 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ while (true) {
+ if (c.c[idx] > 5)
+ return;
+ if (d.d[idx]++ > idx)
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+
+ uint c_val = 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ c_val = 10;
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 119 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 119 FILL 1
+BUFFER compare DATA_TYPE uint32 SIZE 119 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (uint i = 0; i < c.c[idx]; ++i) {
+ if (a.a[gl_SubgroupID] % 2 == 0)
+ return;
+
+ atomicAdd(d.d[idx], 1);
+ if (i == gl_SubgroupID % 4)
+ break;
+ }
+
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 119 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 119 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 119 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (int i = 0; i < c.c[0]; ++i) {
+ atomicAdd(d.d[idx], 1);
+ if (a.a[idx] < 10) {
+ if (a.a[idx] == 0)
+ atomicAdd(d.d[idx], 2);
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = 50;
+ if (gl_SubgroupID % 2 != 0) {
+ if (gl_SubgroupInvocationID == 0)
+ a_val = 0;
+ else
+ a_val = 5;
+ }
+ a.a[idx] = a_val;
+
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 119 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 119 FILL 1
+BUFFER d DATA_TYPE uint32 SIZE 119 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 119 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (int i = 0; i < c.c[0]; ++i) {
+ atomicAdd(d.d[idx], 1);
+ if (a.a[idx] >= 10)
+ break;
+
+ if (a.a[idx] == 0)
+ atomicAdd(d.d[idx], 2);
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = 50;
+ if (gl_SubgroupID % 2 != 0) {
+ if (gl_SubgroupInvocationID == 0)
+ a_val = 0;
+ else
+ a_val = 5;
+ }
+ a.a[idx] = a_val;
+
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 119 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 119 FILL 1
+BUFFER d DATA_TYPE uint32 SIZE 119 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 119 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (int i = 0; i < c.c[0]; ++i) {
+ atomicAdd(d.d[idx], 1);
+ if (a.a[idx] >= 10)
+ continue;
+
+ if (a.a[idx] == 0)
+ atomicAdd(d.d[idx], 2);
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = 50;
+ if (gl_SubgroupID % 2 != 0) {
+ if (gl_SubgroupInvocationID == 0)
+ a_val = 0;
+ else
+ a_val = 5;
+ }
+ a.a[idx] = a_val;
+
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 FILL 1
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 == 0)
+ return;
+
+ switch (c.c[idx]) {
+ case 0:
+ case 1:
+ atomicAdd(d.d[idx], 1);
+ break;
+ case 2:
+ d.d[idx] = gl_SubgroupID;
+ break;
+ default:
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ c.c[idx] = gl_SubgroupID % 4;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 119 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 119 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 119 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[idx] % 2 == 0)
+ return;
+
+ switch (c.c[idx]) {
+ case 0:
+ case 1:
+ atomicAdd(d.d[idx], 1);
+ break;
+ default:
+ d.d[idx] = gl_SubgroupID;
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ a.a[idx] = gl_SubgroupID;
+
+ c.c[idx] = gl_SubgroupID % 4;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ switch (a.a[idx]) {
+ case 0:
+ atomicAdd(d.d[idx], 1);
+ // fallthrough...
+ case 2:
+ return;
+ default:
+ atomicExchange(d.d[0], gl_SubgroupID);
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ a.a[idx] = gl_SubgroupID % 4;
+
+ c.c[idx] = gl_SubgroupID;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ switch (a.a[idx]) {
+ case 0:
+ atomicAdd(d.d[idx], 1);
+ break;
+ case 2:
+ return;
+ default:
+ switch (c.c[idx]) {
+ case 0:
+ case 1:
+ atomicExchange(d.d[0], gl_SubgroupID);
+ break;
+ case 2:
+ c.c[idx]++;
+ break;
+ default:
+ atomicAdd(d.d[1], 32);
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ break;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ a.a[idx] = gl_SubgroupID % 4;
+
+ c.c[idx] = gl_SubgroupID;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 119 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 119 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 119 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (int i = 0; i < c.c[0]; ++i) {
+ atomicAdd(d.d[idx], 1);
+ if (a.a[idx] < 10) {
+ if (a.a[idx] == 0)
+ atomicAdd(d.d[idx], 2);
+ b.b[119 * i + idx] = subgroupElect() ? 1 : 0;
+ }
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = 50;
+ if (gl_SubgroupID % 2 != 0) {
+ if (gl_SubgroupInvocationID == 0)
+ a_val = 0;
+ else
+ a_val = 5;
+ }
+ a.a[idx] = a_val;
+
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[119 * 0 + idx] = cmp_val;
+ compare.x[119 * 1 + idx] = cmp_val;
+ compare.x[119 * 2 + idx] = cmp_val;
+ compare.x[119 * 3 + idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 119 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 476 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 119 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 476 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) volatile buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+
+ if (gl_SubgroupInvocationID == 0) {
+ c.c[idx] += 4;
+ if (a.a[gl_SubgroupID] % 2 == 0)
+ return;
+ } else {
+ c.c[idx]++;
+ if (a.a[gl_SubgroupID] % 2 == 0)
+ return;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 119 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 119 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 119 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_vote : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint c_val = c.c[idx];
+ if (!subgroupAllEqual(c_val)) {
+ atomicAdd(d.d[0], 1);
+ if (c_val % 2 != 0) {
+ atomicAdd(d.d[idx], gl_SubgroupID);
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+
+ uint c_val = c.c[idx];
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ c_val = 10;
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 119 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 119 SERIES_FROM 0 INC_BY 1
+BUFFER d DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER compare DATA_TYPE uint32 SIZE 119 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_vote : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint c_val = c.c[idx];
+ bool test = (c_val % 2) != 0;
+ if (subgroupAny(test)) {
+ atomicAdd(d.d[0], 1);
+ if (a.a[gl_SubgroupID] % 2 == 0)
+ return;
+
+ if (c_val % 2 != 0) {
+ atomicAdd(d.d[idx], gl_SubgroupID);
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+
+ uint c_val = c.c[idx];
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ c_val = 10;
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 119 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 119 SERIES_FROM 0 INC_BY 1
+BUFFER d DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER compare DATA_TYPE uint32 SIZE 119 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_vote : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = a.a[idx];
+ if (a_val < 128) {
+ uint c_val = c.c[idx];
+ switch (c_val) {
+ case 0:
+ atomicAdd(d.d[idx], 1);
+ break;
+ case 1:
+ case 2:
+ if (a_val > 4) {
+ uint val = a_val;
+ for (uint i = 0; i < 4; ++i) {
+ val = atomicExchange(d.d[0], val);
+ }
+ } else if (a_val == 3) {
+ atomicAdd(d.d[1], gl_SubgroupID);
+ } else {
+ atomicAdd(d.d[2], gl_SubgroupInvocationID);
+ }
+ if (c_val == 1) return;
+ break;
+ default:
+ if (a.a[gl_SubgroupID] % 2 == 0) return;
+ atomicExchange(d.d[idx], c_val);
+ break;
+ }
+ } else if (a_val < 192) {
+ atomicExchange(d.d[idx], a_val);
+ uint c_val = c.c[idx];
+ if (subgroupAny(c_val == 0)) {
+ return;
+ } else {
+ uint val = atomicAdd(d.d[idx], gl_SubgroupInvocationID);
+ while (!subgroupElect()) {
+ val = atomicExchange(d.d[0], val);
+ }
+ if (val > 10) {
+ atomicAnd(d.d[idx], 0xff00ff00);
+ }
+ }
+ } else {
+ if (a.a[gl_SubgroupID] % 2 == 0) return;
+ }
+
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ uint c_val = c.c[idx];
+ if (a.a[idx] < 128) {
+ if (gl_SubgroupID % 2 == 0) {
+ c_val = 1;
+ } else {
+ c_val = gl_SubgroupInvocationID % 4;
+ if (c_val == 1) c_val += 4;
+ }
+ } else if (a.a[idx] < 192) {
+ if (gl_SubgroupInvocationID == 0 && gl_SubgroupID % 2 == 0) {
+ c_val = 0;
+ } else {
+ c_val = c_val + 1;
+ }
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 119 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 119 SERIES_FROM 0 INC_BY 1
+BUFFER d DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER compare DATA_TYPE uint32 SIZE 119 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ if (gl_SubgroupInvocationID == 0) {
+ c.c[idx] += 4;
+ } else {
+ c.c[idx]++;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ do {
+ c.c[idx] = d.d[idx];
+ } while (!subgroupElect());
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ while (true) {
+ atomicAdd(c.c[0], 1);
+ if (subgroupElect())
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) volatile buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ if (gl_SubgroupInvocationID == 0) {
+ d.d[idx] += 4;
+ } else {
+ c.c[idx]++;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 != 0)
+ return;
+
+ if (gl_SubgroupInvocationID == 0) {
+ c.c[idx] += 4;
+ } else {
+ c.c[idx]++;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) volatile buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 != 0)
+ return;
+
+ if (gl_SubgroupInvocationID == 0) {
+ c.c[idx] += 4;
+ } else {
+ c.c[idx]++;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (c.c[idx] > 5)
+ return;
+
+ while (true) {
+ if (d.d[idx]++ > idx)
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+
+ uint c_val = 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ c_val = 10;
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 1
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ while (true) {
+ if (c.c[idx] > 5)
+ return;
+ if (d.d[idx]++ > idx)
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+
+ uint c_val = 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ c_val = 10;
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 1
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (uint i = 0; i < c.c[idx]; ++i) {
+ if (a.a[gl_SubgroupID] % 2 != 0)
+ return;
+
+ atomicAdd(d.d[idx], 1);
+ if (i == gl_SubgroupID % 4)
+ break;
+ }
+
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (int i = 0; i < c.c[0]; ++i) {
+ atomicAdd(d.d[idx], 1);
+ if (a.a[idx] < 10) {
+ if (a.a[idx] == 0)
+ atomicAdd(d.d[idx], 2);
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = 50;
+ if (gl_SubgroupID % 2 == 0) {
+ if (gl_SubgroupInvocationID == 0)
+ a_val = 0;
+ else
+ a_val = 5;
+ }
+ a.a[idx] = a_val;
+
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 1
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (int i = 0; i < c.c[0]; ++i) {
+ atomicAdd(d.d[idx], 1);
+ if (a.a[idx] >= 10)
+ break;
+
+ if (a.a[idx] == 0)
+ atomicAdd(d.d[idx], 2);
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = 50;
+ if (gl_SubgroupID % 2 == 0) {
+ if (gl_SubgroupInvocationID == 0)
+ a_val = 0;
+ else
+ a_val = 5;
+ }
+ a.a[idx] = a_val;
+
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 1
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (int i = 0; i < c.c[0]; ++i) {
+ atomicAdd(d.d[idx], 1);
+ if (a.a[idx] >= 10)
+ continue;
+
+ if (a.a[idx] == 0)
+ atomicAdd(d.d[idx], 2);
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = 50;
+ if (gl_SubgroupID % 2 == 0) {
+ if (gl_SubgroupInvocationID == 0)
+ a_val = 0;
+ else
+ a_val = 5;
+ }
+ a.a[idx] = a_val;
+
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 1
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 != 0)
+ return;
+
+ switch (c.c[idx]) {
+ case 0:
+ case 1:
+ atomicAdd(d.d[idx], 1);
+ break;
+ case 2:
+ d.d[idx] = gl_SubgroupID;
+ break;
+ default:
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ c.c[idx] = gl_SubgroupID % 4;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[idx] % 2 != 0)
+ return;
+
+ switch (c.c[idx]) {
+ case 0:
+ case 1:
+ atomicAdd(d.d[idx], 1);
+ break;
+ default:
+ d.d[idx] = gl_SubgroupID;
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ a.a[idx] = gl_SubgroupID;
+
+ c.c[idx] = gl_SubgroupID % 4;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ switch (a.a[idx]) {
+ case 1:
+ atomicAdd(d.d[idx], 1);
+ // fallthrough...
+ case 3:
+ return;
+ default:
+ atomicExchange(d.d[0], gl_SubgroupID);
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ a.a[idx] = gl_SubgroupID % 4;
+
+ c.c[idx] = gl_SubgroupID;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ switch (a.a[idx]) {
+ case 1:
+ atomicAdd(d.d[idx], 1);
+ break;
+ case 3:
+ return;
+ default:
+ switch (c.c[idx]) {
+ case 0:
+ case 1:
+ atomicExchange(d.d[0], gl_SubgroupID);
+ break;
+ case 2:
+ c.c[idx]++;
+ break;
+ default:
+ atomicAdd(d.d[1], 32);
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ break;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ a.a[idx] = gl_SubgroupID % 4;
+
+ c.c[idx] = gl_SubgroupID;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (int i = 0; i < c.c[0]; ++i) {
+ atomicAdd(d.d[idx], 1);
+ if (a.a[idx] < 10) {
+ if (a.a[idx] == 0)
+ atomicAdd(d.d[idx], 2);
+ b.b[128 * i + idx] = subgroupElect() ? 1 : 0;
+ }
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = 50;
+ if (gl_SubgroupID % 2 == 0) {
+ if (gl_SubgroupInvocationID == 0)
+ a_val = 0;
+ else
+ a_val = 5;
+ }
+ a.a[idx] = a_val;
+
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[128 * 0 + idx] = cmp_val;
+ compare.x[128 * 1 + idx] = cmp_val;
+ compare.x[128 * 2 + idx] = cmp_val;
+ compare.x[128 * 3 + idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 512 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 512 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) volatile buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+
+ if (gl_SubgroupInvocationID == 0) {
+ c.c[idx] += 4;
+ if (a.a[gl_SubgroupID] % 2 != 0)
+ return;
+ } else {
+ c.c[idx]++;
+ if (a.a[gl_SubgroupID] % 2 != 0)
+ return;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_vote : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint c_val = c.c[idx];
+ if (!subgroupAllEqual(c_val)) {
+ atomicAdd(d.d[0], 1);
+ if (c_val % 2 == 0) {
+ atomicAdd(d.d[idx], gl_SubgroupID);
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+
+ uint c_val = c.c[idx];
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ c_val = 10;
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 SERIES_FROM 0 INC_BY 1
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_vote : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint c_val = c.c[idx];
+ bool test = (c_val % 2) == 0;
+ if (subgroupAny(test)) {
+ atomicAdd(d.d[0], 1);
+ if (a.a[gl_SubgroupID] % 2 != 0)
+ return;
+
+ if (c_val % 2 == 0) {
+ atomicAdd(d.d[idx], gl_SubgroupID);
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+
+ uint c_val = c.c[idx];
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ c_val = 10;
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 SERIES_FROM 0 INC_BY 1
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_vote : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = a.a[idx];
+ if (a_val < 128) {
+ uint c_val = c.c[idx];
+ switch (c_val) {
+ case 0:
+ atomicAdd(d.d[idx], 1);
+ break;
+ case 1:
+ case 2:
+ if (a_val > 4) {
+ uint val = a_val;
+ for (uint i = 0; i < 4; ++i) {
+ val = atomicExchange(d.d[0], val);
+ if (c_val == 1) return;
+ }
+ } else if (a_val == 3) {
+ atomicAdd(d.d[1], gl_SubgroupID);
+ } else {
+ atomicAdd(d.d[2], gl_SubgroupInvocationID);
+ if (c_val == 1) return;
+ }
+ break;
+ default:
+ if (a.a[gl_SubgroupID] % 2 != 0) return;
+ atomicExchange(d.d[idx], c_val);
+ break;
+ }
+ } else if (a_val < 192) {
+ atomicExchange(d.d[idx], a_val);
+ uint c_val = c.c[idx];
+ if (subgroupAny(c_val == 0)) {
+ return;
+ } else {
+ uint val = atomicAdd(d.d[idx], gl_SubgroupInvocationID);
+ while (!subgroupElect()) {
+ val = atomicExchange(d.d[0], val);
+ }
+ if (val > 10) {
+ atomicAnd(d.d[idx], 0xff00ff00);
+ }
+ }
+ } else {
+ if (a.a[gl_SubgroupID] % 2 != 0) return;
+ }
+
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 != 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ uint c_val = c.c[idx];
+ if (a.a[idx] < 128) {
+ if (gl_SubgroupID % 2 != 0) {
+ c_val = 1;
+ } else {
+ c_val = gl_SubgroupInvocationID % 4;
+ if (c_val == 1) c_val += 4;
+ }
+ } else if (a.a[idx] < 192) {
+ if (gl_SubgroupInvocationID == 0 && gl_SubgroupID % 2 != 0) {
+ c_val = 0;
+ } else {
+ c_val = c_val + 1;
+ }
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 SERIES_FROM 0 INC_BY 1
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 1 0 0 0
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ if (gl_SubgroupInvocationID == 0) {
+ c.c[idx] += 4;
+ } else {
+ c.c[idx]++;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 119 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 119 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 119 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ do {
+ c.c[idx] = d.d[idx];
+ } while (!subgroupElect());
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 119 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 119 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 119 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ while (true) {
+ atomicAdd(c.c[0], 1);
+ if (subgroupElect())
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 119 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 119 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 119 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) volatile buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 != 0) {
+ if (gl_SubgroupInvocationID == 0) {
+ d.d[idx] += 4;
+ } else {
+ c.c[idx]++;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 119 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 119 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 119 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 == 0)
+ return;
+
+ if (gl_SubgroupInvocationID == 0) {
+ c.c[idx] += 4;
+ } else {
+ c.c[idx]++;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 119 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 119 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 119 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) volatile buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 == 0)
+ return;
+
+ if (gl_SubgroupInvocationID == 0) {
+ c.c[idx] += 4;
+ } else {
+ c.c[idx]++;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 119 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 119 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 119 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (c.c[idx] > 5)
+ return;
+
+ while (true) {
+ if (d.d[idx]++ > idx)
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+
+ uint c_val = 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ c_val = 10;
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 119 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 119 FILL 1
+BUFFER compare DATA_TYPE uint32 SIZE 119 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ while (true) {
+ if (c.c[idx] > 5)
+ return;
+ if (d.d[idx]++ > idx)
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+
+ uint c_val = 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ c_val = 10;
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 119 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 119 FILL 1
+BUFFER compare DATA_TYPE uint32 SIZE 119 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (uint i = 0; i < c.c[idx]; ++i) {
+ if (a.a[gl_SubgroupID] % 2 == 0)
+ return;
+
+ atomicAdd(d.d[idx], 1);
+ if (i == gl_SubgroupID % 4)
+ break;
+ }
+
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 119 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 119 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 119 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (int i = 0; i < c.c[0]; ++i) {
+ atomicAdd(d.d[idx], 1);
+ if (a.a[idx] < 10) {
+ if (a.a[idx] == 0)
+ atomicAdd(d.d[idx], 2);
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = 50;
+ if (gl_SubgroupID % 2 != 0) {
+ if (gl_SubgroupInvocationID == 0)
+ a_val = 0;
+ else
+ a_val = 5;
+ }
+ a.a[idx] = a_val;
+
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 119 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 119 FILL 1
+BUFFER d DATA_TYPE uint32 SIZE 119 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 119 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (int i = 0; i < c.c[0]; ++i) {
+ atomicAdd(d.d[idx], 1);
+ if (a.a[idx] >= 10)
+ break;
+
+ if (a.a[idx] == 0)
+ atomicAdd(d.d[idx], 2);
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = 50;
+ if (gl_SubgroupID % 2 != 0) {
+ if (gl_SubgroupInvocationID == 0)
+ a_val = 0;
+ else
+ a_val = 5;
+ }
+ a.a[idx] = a_val;
+
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 119 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 119 FILL 1
+BUFFER d DATA_TYPE uint32 SIZE 119 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 119 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (int i = 0; i < c.c[0]; ++i) {
+ atomicAdd(d.d[idx], 1);
+ if (a.a[idx] >= 10)
+ continue;
+
+ if (a.a[idx] == 0)
+ atomicAdd(d.d[idx], 2);
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = 50;
+ if (gl_SubgroupID % 2 != 0) {
+ if (gl_SubgroupInvocationID == 0)
+ a_val = 0;
+ else
+ a_val = 5;
+ }
+ a.a[idx] = a_val;
+
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 238 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 238 FILL 1
+BUFFER d DATA_TYPE uint32 SIZE 238 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 238 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[gl_SubgroupID] % 2 == 0)
+ return;
+
+ switch (c.c[idx]) {
+ case 0:
+ case 1:
+ atomicAdd(d.d[idx], 1);
+ break;
+ case 2:
+ d.d[idx] = gl_SubgroupID;
+ break;
+ default:
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ c.c[idx] = gl_SubgroupID % 4;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 119 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 119 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 119 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ if (a.a[idx] % 2 == 0)
+ return;
+
+ switch (c.c[idx]) {
+ case 0:
+ case 1:
+ atomicAdd(d.d[idx], 1);
+ break;
+ default:
+ d.d[idx] = gl_SubgroupID;
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ a.a[idx] = gl_SubgroupID;
+
+ c.c[idx] = gl_SubgroupID % 4;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ switch (a.a[idx]) {
+ case 0:
+ atomicAdd(d.d[idx], 1);
+ // fallthrough...
+ case 2:
+ return;
+ default:
+ atomicExchange(d.d[0], gl_SubgroupID);
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ a.a[idx] = gl_SubgroupID % 4;
+
+ c.c[idx] = gl_SubgroupID;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 128 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 128 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 128 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ switch (a.a[idx]) {
+ case 0:
+ atomicAdd(d.d[idx], 1);
+ break;
+ case 2:
+ return;
+ default:
+ switch (c.c[idx]) {
+ case 0:
+ case 1:
+ atomicExchange(d.d[0], gl_SubgroupID);
+ break;
+ case 2:
+ c.c[idx]++;
+ break;
+ default:
+ atomicAdd(d.d[1], 32);
+ break;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ break;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ a.a[idx] = gl_SubgroupID % 4;
+
+ c.c[idx] = gl_SubgroupID;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 119 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 119 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 119 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ for (int i = 0; i < c.c[0]; ++i) {
+ atomicAdd(d.d[idx], 1);
+ if (a.a[idx] < 10) {
+ if (a.a[idx] == 0)
+ atomicAdd(d.d[idx], 2);
+ b.b[119 * i + idx] = subgroupElect() ? 1 : 0;
+ }
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = 50;
+ if (gl_SubgroupID % 2 != 0) {
+ if (gl_SubgroupInvocationID == 0)
+ a_val = 0;
+ else
+ a_val = 5;
+ }
+ a.a[idx] = a_val;
+
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[119 * 0 + idx] = cmp_val;
+ compare.x[119 * 1 + idx] = cmp_val;
+ compare.x[119 * 2 + idx] = cmp_val;
+ compare.x[119 * 3 + idx] = cmp_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 119 FILL 0
+BUFFER b DATA_TYPE uint32 SIZE 476 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 119 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 476 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) volatile buffer C { uint c[]; } c;
+layout(set=0, binding=3) coherent buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+
+ if (gl_SubgroupInvocationID == 0) {
+ c.c[idx] += 4;
+ if (a.a[gl_SubgroupID] % 2 == 0)
+ return;
+ } else {
+ c.c[idx]++;
+ if (a.a[gl_SubgroupID] % 2 == 0)
+ return;
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 119 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER d DATA_TYPE uint32 SIZE 119 FILL 0
+BUFFER compare DATA_TYPE uint32 SIZE 119 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_vote : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint c_val = c.c[idx];
+ if (!subgroupAllEqual(c_val)) {
+ atomicAdd(d.d[0], 1);
+ if (c_val % 2 != 0) {
+ atomicAdd(d.d[idx], gl_SubgroupID);
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+
+ uint c_val = c.c[idx];
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ c_val = 10;
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 119 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 119 SERIES_FROM 0 INC_BY 1
+BUFFER d DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER compare DATA_TYPE uint32 SIZE 119 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_vote : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint c_val = c.c[idx];
+ bool test = (c_val % 2) != 0;
+ if (subgroupAny(test)) {
+ atomicAdd(d.d[0], 1);
+ if (a.a[gl_SubgroupID] % 2 == 0)
+ return;
+
+ if (c_val % 2 != 0) {
+ atomicAdd(d.d[idx], gl_SubgroupID);
+ }
+ b.b[idx] = subgroupElect() ? 1 : 0;
+ }
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = subgroupElect() ? 1 : 0;
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ a_val = 4;
+ }
+ compare.x[idx] = a_val;
+
+ uint c_val = c.c[idx];
+ if (a.a[gl_SubgroupID] % 2 == 0) {
+ c_val = 10;
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 119 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 119 SERIES_FROM 0 INC_BY 1
+BUFFER d DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER compare DATA_TYPE uint32 SIZE 119 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
--- /dev/null
+#!amber
+
+DEVICE_FEATURE SubgroupSizeControl.subgroupSizeControl
+DEVICE_FEATURE SubgroupSizeControl.computeFullSubgroups
+
+SHADER compute test GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_vote : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+#extension GL_EXT_subgroup_uniform_control_flow : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer B { uint b[]; } b;
+layout(set=0, binding=2) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=3) volatile buffer D { uint d[]; } d;
+
+void main()
+[[subgroup_uniform_control_flow]]
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint a_val = a.a[idx];
+ if (a_val < 128) {
+ uint c_val = c.c[idx];
+ switch (c_val) {
+ case 0:
+ atomicAdd(d.d[idx], 1);
+ break;
+ case 1:
+ case 2:
+ if (a_val > 4) {
+ uint val = a_val;
+ for (uint i = 0; i < 4; ++i) {
+ val = atomicExchange(d.d[0], val);
+ }
+ } else if (a_val == 3) {
+ atomicAdd(d.d[1], gl_SubgroupID);
+ } else {
+ atomicAdd(d.d[2], gl_SubgroupInvocationID);
+ }
+ if (c_val == 1) return;
+ break;
+ default:
+ if (a.a[gl_SubgroupID] % 2 == 0) return;
+ atomicExchange(d.d[idx], c_val);
+ break;
+ }
+ } else if (a_val < 192) {
+ atomicExchange(d.d[idx], a_val);
+ uint c_val = c.c[idx];
+ if (subgroupAny(c_val == 0)) {
+ return;
+ } else {
+ uint val = atomicAdd(d.d[idx], gl_SubgroupInvocationID);
+ while (!subgroupElect()) {
+ val = atomicExchange(d.d[0], val);
+ }
+ if (val > 10) {
+ atomicAnd(d.d[idx], 0xff00ff00);
+ }
+ }
+ } else {
+ if (a.a[gl_SubgroupID] % 2 == 0) return;
+ }
+
+ b.b[idx] = subgroupElect() ? 1 : 0;
+}
+END
+
+SHADER compute fill GLSL TARGET_ENV spv1.3
+#version 450 core
+#extension GL_KHR_shader_subgroup_basic : enable
+#extension GL_KHR_shader_subgroup_ballot : enable
+layout(local_size_x = 119, local_size_y = 1, local_size_z = 1) in;
+
+layout(set=0, binding=0) coherent buffer A { uint a[]; } a;
+layout(set=0, binding=1) coherent buffer C { uint c[]; } c;
+layout(set=0, binding=2) coherent buffer COMPARE { uint x[]; } compare;
+
+void main()
+{
+ uint idx = gl_SubgroupID * gl_SubgroupSize + gl_SubgroupInvocationID;
+ uint cmp_val = subgroupElect() ? 1 : 0;
+ if (gl_SubgroupID % 2 == 0) {
+ cmp_val = 4;
+ }
+ compare.x[idx] = cmp_val;
+
+ uint c_val = c.c[idx];
+ if (a.a[idx] < 128) {
+ if (gl_SubgroupID % 2 == 0) {
+ c_val = 1;
+ } else {
+ c_val = gl_SubgroupInvocationID % 4;
+ if (c_val == 1) c_val += 4;
+ }
+ } else if (a.a[idx] < 192) {
+ if (gl_SubgroupInvocationID == 0 && gl_SubgroupID % 2 == 0) {
+ c_val = 0;
+ } else {
+ c_val = c_val + 1;
+ }
+ }
+ c.c[idx] = c_val;
+}
+END
+
+BUFFER a DATA_TYPE uint32 SIZE 119 SERIES_FROM 0 INC_BY 1
+BUFFER b DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER c DATA_TYPE uint32 SIZE 119 SERIES_FROM 0 INC_BY 1
+BUFFER d DATA_TYPE uint32 SIZE 119 FILL 4
+BUFFER compare DATA_TYPE uint32 SIZE 119 FILL 4
+
+PIPELINE compute fill_pipe
+ ATTACH fill
+ SUBGROUP fill
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER compare AS storage DESCRIPTOR_SET 0 BINDING 2
+END
+
+PIPELINE compute test_pipe
+ ATTACH test
+ SUBGROUP test
+ FULLY_POPULATED on
+ REQUIRED_SIZE MIN
+ END
+
+ BIND BUFFER a AS storage DESCRIPTOR_SET 0 BINDING 0
+ BIND BUFFER b AS storage DESCRIPTOR_SET 0 BINDING 1
+ BIND BUFFER c AS storage DESCRIPTOR_SET 0 BINDING 2
+ BIND BUFFER d AS storage DESCRIPTOR_SET 0 BINDING 3
+END
+
+RUN fill_pipe 1 1 1
+RUN test_pipe 1 1 1
+
+EXPECT compare IDX 0 EQ 4 4 4 4
+EXPECT b EQ_BUFFER compare
+
vktSubgroupsBallotMasksTests.hpp
vktSubgroupsSizeControlTests.cpp
vktSubgroupsSizeControlTests.hpp
+ vktSubgroupUniformControlFlowTests.cpp
+ vktSubgroupUniformControlFlowTests.hpp
)
set(DEQP_VK_SUBGROUPS_LIBS
+ libamber
tcutil
vkutil
)
PCH(DEQP_VK_SUBGROUPS_SRCS ../pch.cpp)
+include_directories("../amber")
+include_directories("../../../../amber/src/include")
add_library(deqp-vk-subgroups STATIC ${DEQP_VK_SUBGROUPS_SRCS})
target_link_libraries(deqp-vk-subgroups ${DEQP_VK_SUBGROUPS_LIBS})
--- /dev/null
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2020 Google LLC
+ * Copyright (c) 2020 The Khronos Group Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Test new features in VK_KHR_shader_subgroup_uniform_control_flow
+ *//*--------------------------------------------------------------------*/
+
+#include <amber/amber.h>
+
+#include "tcuDefs.hpp"
+
+#include "vkDefs.hpp"
+#include "vkDeviceUtil.hpp"
+#include "vktTestGroupUtil.hpp"
+#include "vktAmberTestCase.hpp"
+#include "vktSubgroupUniformControlFlowTests.hpp"
+#include "vktTestGroupUtil.hpp"
+
+namespace vkt
+{
+namespace subgroups
+{
+namespace
+{
+
+struct Case
+{
+ Case(const char* b, const char* d, bool sw, bool use_ssc, vk::VkShaderStageFlagBits s, vk::VkSubgroupFeatureFlagBits o) :
+ basename(b),
+ description(d),
+ small_workgroups(sw),
+ use_subgroup_size_control(use_ssc),
+ stage(s)
+ {
+ operation = (vk::VkSubgroupFeatureFlagBits)(o | vk::VK_SUBGROUP_FEATURE_BASIC_BIT);
+ }
+ const char* basename;
+ const char* description;
+ bool small_workgroups;
+ bool use_subgroup_size_control;
+ vk::VkShaderStageFlagBits stage;
+ vk::VkSubgroupFeatureFlagBits operation;
+};
+
+struct CaseGroup
+{
+ CaseGroup(const char* the_data_dir, const char* the_subdir) : data_dir(the_data_dir), subdir(the_subdir) { }
+ void add(const char* basename, const char* description, bool small_workgroups, bool use_subgroup_size_control, vk::VkShaderStageFlagBits stage, vk::VkSubgroupFeatureFlagBits operation = vk::VK_SUBGROUP_FEATURE_BASIC_BIT)
+ {
+ cases.push_back(Case(basename, description, small_workgroups, use_subgroup_size_control, stage, operation));
+ }
+
+ const char* data_dir;
+ const char* subdir;
+ std::vector<Case> cases;
+};
+
+class SubgroupUniformControlFlowTestCase : public cts_amber::AmberTestCase
+{
+public:
+ SubgroupUniformControlFlowTestCase(tcu::TestContext& testCtx,
+ const char* name,
+ const char* description,
+ const std::string& readFilename,
+ bool small_workgroups,
+ bool use_subgroup_size_control,
+ vk::VkShaderStageFlagBits stage,
+ vk::VkSubgroupFeatureFlagBits operation) :
+ cts_amber::AmberTestCase(testCtx, name, description, readFilename),
+ m_small_workgroups(small_workgroups),
+ m_use_subgroup_size_control(use_subgroup_size_control),
+ m_stage(stage),
+ m_operation(operation)
+ { }
+
+ virtual void checkSupport(Context& ctx) const; // override
+private:
+ bool m_small_workgroups;
+ bool m_use_subgroup_size_control;
+ vk::VkShaderStageFlagBits m_stage;
+ vk::VkSubgroupFeatureFlagBits m_operation;
+};
+
+void SubgroupUniformControlFlowTestCase::checkSupport(Context& ctx) const
+{
+ // Check required extensions.
+ ctx.requireDeviceFunctionality("VK_KHR_shader_subgroup_uniform_control_flow");
+ if (m_use_subgroup_size_control)
+ {
+ ctx.requireDeviceFunctionality("VK_EXT_subgroup_size_control");
+ }
+
+ vk::VkPhysicalDeviceSubgroupProperties subgroupProperties;
+ subgroupProperties.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;
+ subgroupProperties.pNext = DE_NULL;
+
+ vk::VkPhysicalDeviceProperties2 properties2;
+ properties2.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
+ properties2.pNext = &subgroupProperties;
+
+ ctx.getInstanceInterface().getPhysicalDeviceProperties2(ctx.getPhysicalDevice(), &properties2);
+
+ vk::VkPhysicalDeviceSubgroupSizeControlFeaturesEXT subgroupSizeControlFeatures;
+ subgroupSizeControlFeatures.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES_EXT;
+ subgroupSizeControlFeatures.pNext = DE_NULL;
+
+ vk::VkPhysicalDeviceFeatures2 features2;
+ features2.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
+ features2.pNext = &subgroupSizeControlFeatures;
+
+ ctx.getInstanceInterface().getPhysicalDeviceFeatures2(ctx.getPhysicalDevice(), &features2);
+
+ // Check that the stage supports the required subgroup operations.
+ if ((m_stage & subgroupProperties.supportedStages) == 0)
+ {
+ TCU_THROW(NotSupportedError, "Device does not support subgroup operations in this stage");
+ }
+ if ((m_operation & subgroupProperties.supportedOperations) != m_operation)
+ {
+ TCU_THROW(NotSupportedError, "Device does not support required operations");
+ }
+
+ // For the compute shader tests, there are variants for implementations
+ // that support the subgroup size control extension and variants for those
+ // that do not. It is expected that computeFullSubgroups must be set for
+ // these tests if the extension is supported so tests are only supported
+ // for the extension appropriate version.
+ if (m_stage == vk::VK_SHADER_STAGE_COMPUTE_BIT)
+ {
+ if (m_use_subgroup_size_control)
+ {
+ if (subgroupSizeControlFeatures.computeFullSubgroups != VK_TRUE)
+ {
+ TCU_THROW(NotSupportedError, "Implementation does not support subgroup size control");
+ }
+ }
+ else
+ {
+ if (subgroupSizeControlFeatures.computeFullSubgroups == VK_TRUE)
+ {
+ TCU_THROW(NotSupportedError, "These tests are not enabled for subgroup size control implementations");
+ }
+ }
+ }
+
+ // The are large and small variants of the tests. The large variants
+ // require 256 invocations in a workgroup.
+ if (!m_small_workgroups)
+ {
+ vk::VkPhysicalDeviceProperties properties;
+ ctx.getInstanceInterface().getPhysicalDeviceProperties(ctx.getPhysicalDevice(), &properties);
+ if (properties.limits.maxComputeWorkGroupInvocations < 256)
+ {
+ TCU_THROW(NotSupportedError, "Device supported fewer than 256 invocations per workgroup");
+ }
+ }
+}
+
+void addTestsForAmberFiles(tcu::TestCaseGroup* tests, CaseGroup group)
+{
+ tcu::TestContext& testCtx = tests->getTestContext();
+ const std::string data_dir(group.data_dir);
+ const std::string subdir(group.subdir);
+ const std::string category = data_dir + "/" + subdir;
+ std::vector<Case> cases(group.cases);
+
+ for (unsigned i = 0; i < cases.size(); ++i)
+ {
+ const std::string file = std::string(cases[i].basename) + ".amber";
+ std::string readFilename("vulkan/amber/");
+ readFilename.append(category);
+ readFilename.append("/");
+ readFilename.append(file);
+ SubgroupUniformControlFlowTestCase* testCase =
+ new SubgroupUniformControlFlowTestCase(testCtx,
+ cases[i].basename,
+ cases[i].description,
+ readFilename,
+ cases[i].small_workgroups,
+ cases[i].use_subgroup_size_control,
+ cases[i].stage,
+ cases[i].operation);
+ DE_ASSERT(testCase != DE_NULL);
+ tests->addChild(testCase);
+ }
+}
+
+} // anonymous
+
+tcu::TestCaseGroup* createSubgroupUniformControlFlowTests(tcu::TestContext& testCtx)
+{
+ // There are four main groups of tests. Each group runs the same set of base
+ // shaders with minor variations. The groups are with or without compute full
+ // subgroups and a larger or smaller number of invocations. For each group of
+ // tests, shaders test either odd or even subgroups reconverge after
+ // diverging, without reconverging the whole workgroup. For the _partial
+ // tests, the workgroup is launched without a full final subgroup (not enough
+ // invocations).
+ //
+ // It is assumed that if an implementation does not support the compute full
+ // subgroups feature, that it will always launch full subgroups. Therefore,
+ // any given implementation only runs half of the tests. Implementations that
+ // do not support compute full subgroups cannot support the tests that enable
+ // it, while implementations that do support the feature will (likely) not
+ // pass the tests that do not enable the feature.
+
+ de::MovePtr<tcu::TestCaseGroup> uniformControlFlowTests(new tcu::TestCaseGroup(testCtx, "subgroup_uniform_control_flow", "VK_KHR_shader_subgroup_uniform_control_flow tests"));
+
+ // Location of the Amber script files under data/vulkan/amber source tree.
+ const char* data_dir = "subgroup_uniform_control_flow";
+ const char* large_dir = "large";
+ const char* small_dir = "small";
+ const char* large_control_dir = "large_control";
+ const char* small_control_dir = "small_control";
+
+ std::vector<bool> controls = {false, true};
+ for (unsigned c = 0; c < controls.size(); ++c)
+ {
+ // Full subgroups.
+ bool small = false;
+ bool control = controls[c];
+ vk::VkShaderStageFlagBits stage = vk::VK_SHADER_STAGE_COMPUTE_BIT;
+ const char* subdir = (control ? large_control_dir : large_dir);
+ CaseGroup group(data_dir, subdir);
+ group.add("subgroup_reconverge00", "if/else diverge", small, control, stage);
+ group.add("subgroup_reconverge01", "do while diverge", small, control, stage);
+ group.add("subgroup_reconverge02", "while true with break", small, control, stage);
+ group.add("subgroup_reconverge03", "if/else diverge, volatile", small, control, stage);
+ group.add("subgroup_reconverge04", "early return and if/else diverge", small, control, stage);
+ group.add("subgroup_reconverge05", "early return and if/else volatile", small, control, stage);
+ group.add("subgroup_reconverge06", "while true with volatile conditional break and early return", small, control, stage);
+ group.add("subgroup_reconverge07", "while true return and break", small, control, stage);
+ group.add("subgroup_reconverge08", "for loop atomics with conditional break", small, control, stage);
+ group.add("subgroup_reconverge09", "diverge in for loop", small, control, stage);
+ group.add("subgroup_reconverge10", "diverge in for loop and break", small, control, stage);
+ group.add("subgroup_reconverge11", "diverge in for loop and continue", small, control, stage);
+ group.add("subgroup_reconverge12", "early return, divergent switch", small, control, stage);
+ group.add("subgroup_reconverge13", "early return, divergent switch more cases", small, control, stage);
+ group.add("subgroup_reconverge14", "divergent switch, some subgroups terminate", small, control, stage);
+ group.add("subgroup_reconverge15", "switch in switch", small, control, stage);
+ group.add("subgroup_reconverge16", "for loop unequal iterations", small, control, stage);
+ group.add("subgroup_reconverge17", "if/else with nested returns", small, control, stage);
+ group.add("subgroup_reconverge18", "if/else subgroup all equal", small, control, stage, vk::VK_SUBGROUP_FEATURE_VOTE_BIT);
+ group.add("subgroup_reconverge19", "if/else subgroup any nested return", small, control, stage, vk::VK_SUBGROUP_FEATURE_VOTE_BIT);
+ group.add("subgroup_reconverge20", "deeply nested", small, control, stage);
+ const char* group_name = (control ? "large_full_control" : "large_full");
+ uniformControlFlowTests->addChild(createTestGroup(testCtx, group_name,
+ "Large Full subgroups",
+ addTestsForAmberFiles, group));
+
+ // Partial subgroup.
+ group = CaseGroup(data_dir, subdir);
+ group.add("subgroup_reconverge_partial00", "if/else diverge", small, control, stage);
+ group.add("subgroup_reconverge_partial01", "do while diverge", small, control, stage);
+ group.add("subgroup_reconverge_partial02", "while true with break", small, control, stage);
+ group.add("subgroup_reconverge_partial03", "if/else diverge, volatile", small, control, stage);
+ group.add("subgroup_reconverge_partial04", "early return and if/else diverge", small, control, stage);
+ group.add("subgroup_reconverge_partial05", "early return and if/else volatile", small, control, stage);
+ group.add("subgroup_reconverge_partial06", "while true with volatile conditional break and early return", small, control, stage);
+ group.add("subgroup_reconverge_partial07", "while true return and break", small, control, stage);
+ group.add("subgroup_reconverge_partial08", "for loop atomics with conditional break", small, control, stage);
+ group.add("subgroup_reconverge_partial09", "diverge in for loop", small, control, stage);
+ group.add("subgroup_reconverge_partial10", "diverge in for loop and break", small, control, stage);
+ group.add("subgroup_reconverge_partial11", "diverge in for loop and continue", small, control, stage);
+ group.add("subgroup_reconverge_partial12", "early return, divergent switch", small, control, stage);
+ group.add("subgroup_reconverge_partial13", "early return, divergent switch more cases", small, control, stage);
+ group.add("subgroup_reconverge_partial14", "divergent switch, some subgroups terminate", small, control, stage);
+ group.add("subgroup_reconverge_partial15", "switch in switch", small, control, stage);
+ group.add("subgroup_reconverge_partial16", "for loop unequal iterations", small, control, stage);
+ group.add("subgroup_reconverge_partial17", "if/else with nested returns", small, control, stage);
+ group.add("subgroup_reconverge_partial18", "if/else subgroup all equal", small, control, stage, vk::VK_SUBGROUP_FEATURE_VOTE_BIT);
+ group.add("subgroup_reconverge_partial19", "if/else subgroup any nested return", small, control, stage, vk::VK_SUBGROUP_FEATURE_VOTE_BIT);
+ group.add("subgroup_reconverge_partial20", "deeply nested", small, control, stage);
+ group_name = (control ? "large_partial_control" : "large_partial");
+ uniformControlFlowTests->addChild(createTestGroup(testCtx, group_name,
+ "Large Partial subgroups",
+ addTestsForAmberFiles, group));
+ }
+
+ for (unsigned c = 0; c < controls.size(); ++c)
+ {
+ // Full subgroups.
+ bool small = true;
+ bool control = controls[c];
+ vk::VkShaderStageFlagBits stage = vk::VK_SHADER_STAGE_COMPUTE_BIT;
+ const char* subdir = (control ? small_control_dir : small_dir);
+ CaseGroup group(data_dir, subdir);
+ group.add("small_subgroup_reconverge00", "if/else diverge", small, control, stage);
+ group.add("small_subgroup_reconverge01", "do while diverge", small, control, stage);
+ group.add("small_subgroup_reconverge02", "while true with break", small, control, stage);
+ group.add("small_subgroup_reconverge03", "if/else diverge, volatile", small, control, stage);
+ group.add("small_subgroup_reconverge04", "early return and if/else diverge", small, control, stage);
+ group.add("small_subgroup_reconverge05", "early return and if/else volatile", small, control, stage);
+ group.add("small_subgroup_reconverge06", "while true with volatile conditional break and early return", small, control, stage);
+ group.add("small_subgroup_reconverge07", "while true return and break", small, control, stage);
+ group.add("small_subgroup_reconverge08", "for loop atomics with conditional break", small, control, stage);
+ group.add("small_subgroup_reconverge09", "diverge in for loop", small, control, stage);
+ group.add("small_subgroup_reconverge10", "diverge in for loop and break", small, control, stage);
+ group.add("small_subgroup_reconverge11", "diverge in for loop and continue", small, control, stage);
+ group.add("small_subgroup_reconverge12", "early return, divergent switch", small, control, stage);
+ group.add("small_subgroup_reconverge13", "early return, divergent switch more cases", small, control, stage);
+ group.add("small_subgroup_reconverge14", "divergent switch, some subgroups terminate", small, control, stage);
+ group.add("small_subgroup_reconverge15", "switch in switch", small, control, stage);
+ group.add("small_subgroup_reconverge16", "for loop unequal iterations", small, control, stage);
+ group.add("small_subgroup_reconverge17", "if/else with nested returns", small, control, stage);
+ group.add("small_subgroup_reconverge18", "if/else subgroup all equal", small, control, stage, vk::VK_SUBGROUP_FEATURE_VOTE_BIT);
+ group.add("small_subgroup_reconverge19", "if/else subgroup any nested return", small, control, stage, vk::VK_SUBGROUP_FEATURE_VOTE_BIT);
+ group.add("small_subgroup_reconverge20", "deeply nested", small, control, stage);
+ const char* group_name = (control ? "small_full_control" : "small_full");
+ uniformControlFlowTests->addChild(createTestGroup(testCtx, group_name,
+ "Small Full subgroups",
+ addTestsForAmberFiles, group));
+
+ // Partial subgroup.
+ group = CaseGroup(data_dir, subdir);
+ group.add("small_subgroup_reconverge_partial00", "if/else diverge", small, control, stage);
+ group.add("small_subgroup_reconverge_partial01", "do while diverge", small, control, stage);
+ group.add("small_subgroup_reconverge_partial02", "while true with break", small, control, stage);
+ group.add("small_subgroup_reconverge_partial03", "if/else diverge, volatile", small, control, stage);
+ group.add("small_subgroup_reconverge_partial04", "early return and if/else diverge", small, control, stage);
+ group.add("small_subgroup_reconverge_partial05", "early return and if/else volatile", small, control, stage);
+ group.add("small_subgroup_reconverge_partial06", "while true with volatile conditional break and early return", small, control, stage);
+ group.add("small_subgroup_reconverge_partial07", "while true return and break", small, control, stage);
+ group.add("small_subgroup_reconverge_partial08", "for loop atomics with conditional break", small, control, stage);
+ group.add("small_subgroup_reconverge_partial09", "diverge in for loop", small, control, stage);
+ group.add("small_subgroup_reconverge_partial10", "diverge in for loop and break", small, control, stage);
+ group.add("small_subgroup_reconverge_partial11", "diverge in for loop and continue", small, control, stage);
+ group.add("small_subgroup_reconverge_partial12", "early return, divergent switch", small, control, stage);
+ group.add("small_subgroup_reconverge_partial13", "early return, divergent switch more cases", small, control, stage);
+ group.add("small_subgroup_reconverge_partial14", "divergent switch, some subgroups terminate", small, control, stage);
+ group.add("small_subgroup_reconverge_partial15", "switch in switch", small, control, stage);
+ group.add("small_subgroup_reconverge_partial16", "for loop unequal iterations", small, control, stage);
+ group.add("small_subgroup_reconverge_partial17", "if/else with nested returns", small, control, stage);
+ group.add("small_subgroup_reconverge_partial18", "if/else subgroup all equal", small, control, stage, vk::VK_SUBGROUP_FEATURE_VOTE_BIT);
+ group.add("small_subgroup_reconverge_partial19", "if/else subgroup any nested return", small, control, stage, vk::VK_SUBGROUP_FEATURE_VOTE_BIT);
+ group.add("small_subgroup_reconverge_partial20", "deeply nested", small, control, stage);
+ group_name = (control ? "small_partial_control" : "small_partial");
+ uniformControlFlowTests->addChild(createTestGroup(testCtx, group_name,
+ "Small Partial subgroups",
+ addTestsForAmberFiles, group));
+ }
+
+ // Discard test
+ CaseGroup group(data_dir, "discard");
+ group.add("subgroup_reconverge_discard00", "discard test", true, false, vk::VK_SHADER_STAGE_FRAGMENT_BIT);
+ uniformControlFlowTests->addChild(createTestGroup(testCtx, "discard",
+ "Discard tests",
+ addTestsForAmberFiles, group));
+
+ return uniformControlFlowTests.release();
+}
+
+} // subgroups
+} // vkt
--- /dev/null
+#ifndef _VKTSUBGROUPUNIFORMCONTROLFLOWTESTS_HPP
+#define _VKTSUBGROUPUNIFORMCONTROLFLOWTESTS_HPP
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2020 Google LLC
+ * Copyright (c) 2020 The Khronos Group Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief VK_KHR_shader_subgroup_uniform_control_flow tests
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+namespace subgroups
+{
+
+tcu::TestCaseGroup* createSubgroupUniformControlFlowTests (tcu::TestContext& testCtx);
+
+} // subgroups
+} // vkt
+
+#endif // _VKTSUBGROUPUNIFORMCONTROLFLOWTESTS_HPP
#include "vktSubgroupsShapeTests.hpp"
#include "vktSubgroupsBallotMasksTests.hpp"
#include "vktSubgroupsSizeControlTests.hpp"
+#include "vktSubgroupUniformControlFlowTests.hpp"
#include "vktTestGroupUtil.hpp"
namespace vkt
subgroupsTests->addChild(createSubgroupsShapeTests(testCtx));
subgroupsTests->addChild(createSubgroupsBallotMasksTests(testCtx));
subgroupsTests->addChild(createSubgroupsSizeControlTests(testCtx));
+ subgroupsTests->addChild(createSubgroupUniformControlFlowTests(testCtx));
}
} // anonymous
dEQP-VK.subgroups.size_control.ray_tracing.allow_varying_subgroup_size
dEQP-VK.subgroups.size_control.ray_tracing.required_subgroup_size_max
dEQP-VK.subgroups.size_control.ray_tracing.required_subgroup_size_min
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge00
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge01
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge02
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge03
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge04
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge05
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge06
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge07
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge08
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge09
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge10
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge11
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge12
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge13
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge14
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge15
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge16
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge17
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge18
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge19
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full.subgroup_reconverge20
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial00
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial01
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial02
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial03
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial04
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial05
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial06
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial07
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial08
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial09
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial10
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial11
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial12
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial13
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial14
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial15
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial16
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial17
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial18
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial19
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial.subgroup_reconverge_partial20
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge00
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge01
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge02
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge03
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge04
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge05
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge06
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge07
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge08
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge09
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge10
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge11
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge12
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge13
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge14
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge15
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge16
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge17
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge18
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge19
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_full_control.subgroup_reconverge20
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial00
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial01
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial02
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial03
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial04
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial05
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial06
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial07
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial08
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial09
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial10
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial11
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial12
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial13
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial14
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial15
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial16
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial17
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial18
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial19
+dEQP-VK.subgroups.subgroup_uniform_control_flow.large_partial_control.subgroup_reconverge_partial20
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge00
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge01
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge02
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge03
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge04
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge05
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge06
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge07
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge08
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge09
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge10
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge11
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge12
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge13
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge14
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge15
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge16
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge17
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge18
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge19
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full.small_subgroup_reconverge20
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial00
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial01
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial02
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial03
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial04
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial05
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial06
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial07
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial08
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial09
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial10
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial11
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial12
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial13
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial14
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial15
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial16
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial17
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial18
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial19
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial.small_subgroup_reconverge_partial20
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge00
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge01
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge02
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge03
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge04
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge05
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge06
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge07
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge08
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge09
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge10
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge11
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge12
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge13
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge14
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge15
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge16
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge17
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge18
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge19
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_full_control.small_subgroup_reconverge20
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial00
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial01
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial02
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial03
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial04
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial05
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial06
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial07
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial08
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial09
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial10
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial11
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial12
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial13
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial14
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial15
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial16
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial17
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial18
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial19
+dEQP-VK.subgroups.subgroup_uniform_control_flow.small_partial_control.small_subgroup_reconverge_partial20
+dEQP-VK.subgroups.subgroup_uniform_control_flow.discard.subgroup_reconverge_discard00