KhronosGroup / KhronosGroup/glslang
Compiling GL_AMD_shader_ballot generates SPIR-V with Groups capability
- Dominant language
- C++
- Stars
- 3.6k
- Forks
- 989
- Avg merge
- 1d 2h
- Merged PRs (30d)
- 31
Description
There's a discrepancy between SPV_AMD_shader_ballot and Glslang code generation for GL_AMD_shader_ballot. Summary: Glslang generates demand for Groups capability but SPV_AMD_shader_ballot does not enable that capability.
This causes a SPIR-V validation failure for a SPIRV-Cross test case
The example is https://github.com/KhronosGroup/SPIRV-Cross/blob/master/shaders/amd/shader_ballot_nonuniform_invocations.invalid.comp and copied here:
```GLSL
#version 450
#extension GL_AMD_shader_ballot : require
void main ()
{
float addInvocations = addInvocationsNonUniformAMD(0.0);
int minInvocations = minInvocationsNonUniformAMD(1);
uint maxInvocations = maxInvocationsNonUniformAMD(4);
}
```
Compiling with glslangValidator -V --target-env vulkan1.1 we get the following:
```
OpCapability Shader
OpCapability Groups
OpExtension "SPV_AMD_shader_ballot"
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %main "main"
OpExecutionMode %main LocalSize 1 1 1
OpSource GLSL 450
OpSourceExtension "GL_AMD_shader_ballot"
OpName %main "main"
OpName %addInvocations "addInvocations"
OpName %minInvocations "minInvocations"
OpName %maxInvocations "maxInvocations"
%void = OpTypeVoid
%3 = OpTypeFunction %void
%float = OpTypeFloat 32
%_ptr_Function_float = OpTypePointer Function %float
%float_0 = OpConstant %float 0
%uint = OpTypeInt 32 0
%uint_3 = OpConstant %uint 3
%int = OpTypeInt 32 1
%_ptr_Function_int = OpTypePointer Function %int
%int_1 = OpConstant %int 1
%_ptr_Function_uint = OpTypePointer Function %uint
%int_4 = OpConstant %int 4
%main = OpFunction %void None %3
%5 = OpLabel
%addInvocations = OpVariable %_ptr_Function_float Function
%minInvocations = OpVariable %_ptr_Function_int Function
%maxInvocations = OpVariable %_ptr_Function_uint Function
%12 = OpGroupFAddNonUniformAMD %float %uint_3 Reduce %float_0
OpStore %addInvocations %12
%17 = OpGroupSMinNonUniformAMD %int %uint_3 Reduce %int_1
OpStore %minInvocations %17
%21 = OpGroupSMaxNonUniformAMD %int %uint_3 Reduce %int_4
%22 = OpBitcast %uint %21
OpStore %maxInvocations %22
OpReturn
OpFunctionEnd
```
Running spirv-val --target-env vulkan1.1 we get this validation failure:
```
Capability Groups is not allowed by Vulkan 1.1 specification (or requires extension)
OpCapability Groups
```
Something is misaligned. The evidence:
- The [SPV_AMD_shader_ballot extension](http://htmlpreview.github.io/?https://github.com/KhronosGroup/SPIRV-Registry/blob/master/extensions/AMD/SPV_AMD_shader_ballot.html) does not say it enables the Groups capability. It says the extension is enabled with `OpExtension "SPV_AMD_shader_ballot"`.
- The OpGroupFAddNonUniformAMD (and other instructions) are listed in the JSON grammar file as being enabled *either* by the Groups capability or by the SPV_AMD_shader_ballot extension.
- By the rules in the grammar, it would be ok to remove `OpCapability Groups` from this module. In fact, when I do so it does validate correctly.
- The SPIR-V spec lists those AMD instructions as enabled by Groups, but otherwise as Reserved. (The extension is not mentioned.)
Now, we have a few choices:
- If we think the specs should stay the same, then Glslang should stop emitting the Groups capability in this case. But that is probably risky because I presume AMD is happy with the current code generation.
- If we think Glslang codegen is just fine for these cases, then we could update SPV_AMD_shader_ballot to say it enables the Groups capability. Along with that, update the JSON grammar to say Groups capability is enabled by the extension.
- This would also fix this validation failure: https://github.com/KhronosGroup/glslang/blob/master/Test/baseResults/spv.shaderBallotAMD.comp.out#L2
I think we need input from AMD: @sheredom @DominikWitczakAMD ?
Contributor guide
Research direction
Start by reproducing the GL_AMD_shader_ballot example with glslangValidator -V --target-env vulkan1.1 and checking it with spirv-val. Read Test/baseResults/spv.shaderBallotAMD.comp.out and compare the generated Groups capability with the SPV_AMD_shader_ballot specification and JSON grammar. Done means the specification, grammar, code generation, and validation behavior agree.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100