diff --git a/wgsl/index.bs b/wgsl/index.bs
index 8f30f98460..a8a4035537 100644
--- a/wgsl/index.bs
+++ b/wgsl/index.bs
@@ -1467,6 +1467,7 @@ The [=language extension=] names are:
* `'pointer_composite_access'`
* `'uniform_buffer_standard_layout'`
* `'subgroup_id'`
+* `'subgroup_uniformity'`
### Interpolation Type Names ### {#interpolation-type-names}
@@ -1938,6 +1939,15 @@ Extension names are not [=identifiers=]: they do not [=resolves|resolve=] to [=d
Allows the use of the [=built-in values/subgroup_id=] and [=built-in
values/num_subgroups=] built-in values when the [=extension/subgroups=]
extension is enabled.
+
| subgroup_uniformity
+ |
+ Adds an additional scope, subgroup, for [=uniform control flow=]
+ [[#subgroup-builtin-functions|subgroup]] and
+ [[#quad-builtin-functions|quad]] built-in functions to be all invocations
+ in the same [=subgroup=].
+
+ Note: The use of subgroup and quad built-in functions requires the
+ [=extension/subgroups=] extension to be enabled.
Note: The intent is that, over time, WGSL will define language extensions embodying all functionality in language extensions commonly supported at that time.
@@ -11272,11 +11282,20 @@ The analysis is what actually defines these concepts, and when a program is vali
For a given group of invocations:
- If all invocations in a given scope execute as if they are executing in lockstep at a given
- point in the program, that point is said to have uniform control flow.
- - For a [=compute shader stage=], the scope of uniform control flow is all invocations
- in the same [=compute shader stage/workgroup=].
- - For other shader stages, the scope of uniform control flow is all invocations for that
- [=entry point=] in the same [=draw command=].
+ point in the program, that point is said to have uniform control flow
+ for the given uniformity scope.
+ - Workgroup uniformity scope: For a [=compute shader
+ stage=], the uniformity scope is all invocations in the same [=compute
+ shader stage/workgroup=].
+ - Draw uniformity scope: For other shader stages, the
+ uniformity scope is all invocations for that [=entry point=] in the same
+ [=draw command=].
+ - Subgroup uniformity scope: If the
+ [=language_extension/subgroup_uniformity=] feature is supported, the
+ uniformity scope for [[#subgroup-builtin-functions|subgroup]] and
+ [[#quad-builtin-functions|quad]] built-in functions instead is all
+ invocations in the same [=subgroup=].
+
- If an expression is executed in uniform control flow, and all invocations compute the
same value, it is said to be a uniform value.
- If invocations hold the same value for a local variable at every point where it is live,
@@ -11287,6 +11306,15 @@ For a given group of invocations:
The remaining subsections specify a static analysis that verifies that
[[#collective-operations|collective operations]] are only executed in [=uniform
control flow=].
+If the [=language_extension/subgroup_uniformity=] feature is supported then
+there are multiple [=uniformity scopes=].
+This analysis is performed once for each scope.
+
+Note: The analysis is described as being executed once per scope, but
+implementations may perform a single analysis that includes each scope.
+[=Workgroup uniformity scope|Workgroup=] and [=draw uniformity scope|draw=]
+uniformity scopes are effectively equivalent since they operate on different
+shader stages and represent the largest uniformity scope in a shader stage.
The analysis assumes [=dynamic errors=] do not occur.
A shader stage with a [=dynamic error=] is already non-portable, no matter the outcome
@@ -11978,24 +12006,32 @@ Most built-in functions have tags of:
Here is the list of exceptions:
- A call to a function in [[#sync-builtin-functions]]:
- Has a [=function tag=] of [=NoRestriction=].
- - Has a [=call site tag=] of [=CallSiteRequiredToBeUniform.S|CallSiteRequiredToBeUniform.error=], with [=potential-trigger-set=]
- consisting of an unnamed [=diagnostic/triggering rule=].
- - Note: The triggering rule has no name, and so it cannot be filtered.
- - Additionally for the case of a call to [[#workgroupUniformLoad-builtin|workgroupUniformLoad]],
+ - Has a [=call site tag=] of:
+ - [=CallSiteRequiredToBeUniform.S|CallSiteRequiredToBeUniform.error=], with [=potential-trigger-set=]
+ consisting of an unnamed [=diagnostic/triggering rule=]
+ if [=language_extension/subgroup_uniformity=] is not supported or
+ the [=uniformity scope=] is not subgroup.
+ - Note: The triggering rule has no name, and so it cannot be filtered.
+ - [=CallSiteNoRestriction=] otherwise.
+ - Additionally if [=language_extension/subgroup_uniformity=] is not
+ supported or the [=uniformity scope=] is not subgroup, for a
+ call to [[#workgroupUniformLoad-builtin|workgroupUniformLoad]],
the parameter `p` has a [=parameter tag=] of [=ParameterRequiredToBeUniform.S|ParameterRequiredToBeUniform.error=],
with [=potential-trigger-set=] consisting of an unnamed [=diagnostic/triggering rule=].
- A call to a function in
[[#derivative-builtin-functions]], [[#texturesample]], [[#texturesamplebias]], and [[#texturesamplecompare]]:
- Has a [=function tag=] of [=ReturnValueMayBeNonUniform=].
- Has a [=call site tag=] as follows:
- - Let *DF* be the [=nearest enclosing diagnostic filter=] for the call site location and triggering rule [=trigger/derivative_uniformity=]
- - If *DF* exists, then let *S* be the *DF*'s new severity parameter.
- - If *S* is the severity [=severity/off=], the call site tag is [=CallSiteNoRestriction=].
- - Otherwise the call site tag is [=CallSiteRequiredToBeUniform.S=], with [=potential-trigger-set=]
+ - If [=language_extension/subgroup_uniformity=] is not supported or the [=uniformity scope=] is not subgroup
+ - Let *DF* be the [=nearest enclosing diagnostic filter=] for the call site location and triggering rule [=trigger/derivative_uniformity=]
+ - If *DF* exists, then let *S* be the *DF*'s new severity parameter.
+ - If *S* is the severity [=severity/off=], the call site tag is [=CallSiteNoRestriction=].
+ - Otherwise the call site tag is [=CallSiteRequiredToBeUniform.S=], with [=potential-trigger-set=]
+ consisting of a [=trigger/derivative_uniformity=] element.
+ - If there is no such *DF*,
+ the call site tag is [=CallSiteRequiredToBeUniform.S|CallSiteRequiredToBeUniform.error=], with [=potential-trigger-set=]
consisting of a [=trigger/derivative_uniformity=] element.
- - If there is no such *DF*,
- the call site tag is [=CallSiteRequiredToBeUniform.S|CallSiteRequiredToBeUniform.error=], with [=potential-trigger-set=]
- consisting of a [=trigger/derivative_uniformity=] element.
+ - [=CallSiteNoRestriction=] otherwise.
- A call to [[#textureload]]:
- Has a [=call site tag=] of [=CallSiteNoRestriction=]
- Has a [=function tag=] as follows:
@@ -12004,38 +12040,58 @@ Here is the list of exceptions:
- [=NoRestriction=] otherwise
- A call to a function in
[[#subgroup-builtin-functions]] or [[#quad-builtin-functions]]:
- - Has a [=function tag=] of [=ReturnValueMayBeNonUniform=].
+ - Has a [=function tag=] of:
+ - [=NoRestriction=] if the [=uniformity scope=] is subgroup and the function is one of the following:
+ - [[#subgroupadd-builtin|subgroupAdd]]
+ - [[#subgroupall-builtin|subgroupAll]]
+ - [[#subgroupand-builtin|subgroupAnd]]
+ - [[#subgroupany-builtin|subgroupAny]]
+ - [[#subgroupballot-builtin|subgroupBallot]]
+ - [[#subgroupbroadcast-builtin|subgroupBroadcast]]
+ - [[#subgroupbroadcastfirst-builtin|subgroupBroadcastFirst]]
+ - [[#subgroupmax-builtin|subgroupMax]]
+ - [[#subgroupmin-builtin|subgroupMin]]
+ - [[#subgroupmul-builtin|subgroupMul]]
+ - [[#subgroupor-builtin|subgroupOr]]
+ - [[#subgroupxor-builtin|subgroupXor]]
+ - [=ReturnValueMayBeNonUniform=] otherwise
- Let *DF* be the [=nearest enclosing diagnostic filter=] for the call site location and triggering rule [=trigger/subgroup_uniformity=]
- Has a [=call site tag=] as follows:
- - If *DF* exists, then let *S* be the *DF*'s new severity parameter.
- - If *S* is the severity [=severity/off=], the call site tag is [=CallSiteNoRestriction=].
- - Otherwise, the call site tag is [=CallSiteRequiredToBeUniform.S=], with [=potential-trigger-set=]
+ - If [=language_extension/subgroup_uniformity=] is not supported or the [=uniformity scope=] is subgroup then:
+ - If *DF* exists, then let *S* be the *DF*'s new severity parameter.
+ - If *S* is the severity [=severity/off=], the call site tag is [=CallSiteNoRestriction=].
+ - Otherwise, the call site tag is [=CallSiteRequiredToBeUniform.S=], with [=potential-trigger-set=]
+ consisting of a [=trigger/subgroup_uniformity=] element.
+ - If there is no such *DF*,
+ the call site tag is [=CallSiteRequiredToBeUniform.S|CallSiteRequiredToBeUniform.error=], with [=potential-trigger-set=]
consisting of a [=trigger/subgroup_uniformity=] element.
- - If there is no such *DF*,
- the call site tag is [=CallSiteRequiredToBeUniform.S|CallSiteRequiredToBeUniform.error=], with [=potential-trigger-set=]
- consisting of a [=trigger/subgroup_uniformity=] element.
+ - [=CallSiteNoRestriction=] otherwise.
- Additionally for the case of a call to [[#subgroupshuffleup-builtin|subgroupShuffleUp]] or [[#subgroupshuffledown-builtin|subgroupShuffleDown]],
the parameter `delta` has a [=parameter tag=] of:
- - If *DF* exists, then let *S* be *DF*'s new severity parameter.
- - If *S* is the severity [=severity/off=], the parameter tag is [=NoRestriction=].
- - Otherwise, the parameter tag is [=ParameterRequiredToBeUniform.S=] with [=potential-trigger-set=]
- consisting of a [=trigger/subgroup_uniformity=] element.
- - If there is no such *DF*,
- the parameter tag is [=ParameterRequiredToBeUniform.S|ParameterRequiredToBeUniform.error=], with [=potential-trigger-set=]
- consisting of a [=trigger/subgroup_uniformity=] element.
+ - If [=language_extension/subgroup_uniformity=] is not supported or the [=uniformity scope=] is subgroup then:
+ - If *DF* exists, then let *S* be *DF*'s new severity parameter.
+ - If *S* is the severity [=severity/off=], the parameter tag is [=NoRestriction=].
+ - Otherwise, the parameter tag is [=ParameterRequiredToBeUniform.S=] with [=potential-trigger-set=]
+ consisting of a [=trigger/subgroup_uniformity=] element.
+ - If there is no such *DF*,
+ the parameter tag is [=ParameterRequiredToBeUniform.S|ParameterRequiredToBeUniform.error=], with [=potential-trigger-set=]
+ consisting of a [=trigger/subgroup_uniformity=] element.
+ - [=NoRestriction=] otherwise.
- Additionally for the case of a call to [[#subgroupshufflexor-builtin|subgroupShuffleXor]],
the parameter `mask` has a [=parameter tag=] of:
- - If *DF* exists, then let *S* be *DF*'s new severity parameter.
- - If *S* is the severity [=severity/off=], the parameter tag is [=NoRestriction=].
- - Otherwise, the parameter tag is [=ParameterRequiredToBeUniform.S=] with [=potential-trigger-set=]
- consisting of a [=trigger/subgroup_uniformity=] element.
- - If there is no such *DF*,
- the parameter tag is [=ParameterRequiredToBeUniform.S|ParameterRequiredToBeUniform.error=], with [=potential-trigger-set=]
- consisting of a [=trigger/subgroup_uniformity=] element.
+ - If [=language_extension/subgroup_uniformity=] is not supported or the [=uniformity scope=] is subgroup then:
+ - If *DF* exists, then let *S* be *DF*'s new severity parameter.
+ - If *S* is the severity [=severity/off=], the parameter tag is [=NoRestriction=].
+ - Otherwise, the parameter tag is [=ParameterRequiredToBeUniform.S=] with [=potential-trigger-set=]
+ consisting of a [=trigger/subgroup_uniformity=] element.
+ - If there is no such *DF*,
+ the parameter tag is [=ParameterRequiredToBeUniform.S|ParameterRequiredToBeUniform.error=], with [=potential-trigger-set=]
+ consisting of a [=trigger/subgroup_uniformity=] element.
+ - [=NoRestriction=] otherwise.
Note: A WGSL implementation will ensure that if control flow prior to a
-function call is [=uniform control flow|uniform=], it will also be uniform
-after the function call.
+function call is [=uniform control flow|uniform=] for a particular scope, it
+will also be uniform after the function call.
### Uniformity Rules for Expressions ### {#uniformity-expressions}
@@ -12190,6 +12246,10 @@ The following built-in input variables are considered uniform:
- [=built-in values/subgroup_size=] when used in a [=compute shader stage=]
- [=built-in values/num_subgroups=]
+At [=subgroup uniformity scope=], the following built-in
+input variables are also considered uniform:
+- [=built-in values/subgroup_id=]
+
All other ones (see [=built-in values=]) are considered non-uniform.
Note: An author should avoid grouping the uniform built-in values together with
|