KhronosGroup / KhronosGroup/glslang

Compiling GL_AMD_shader_ballot generates SPIR-V with Groups capability

Open
#1,763 1 comment 0 reactions 0 assignees View on GitHub
question
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.