Skip to content

Commit

Permalink
[Wave Size Range] Revise metadata representation (#165)
Browse files Browse the repository at this point in the history
The biggest change here is that the RangedWaveSize tag can have a first
element non-zero with the rest zero to represent the old WaveSizeTag
behavior. Added some clarification of metadata restrictions and error
generation as well.

Fixes #158
  • Loading branch information
pow2clk authored Mar 8, 2024
1 parent 1145845 commit 8b6e2e2
Showing 1 changed file with 76 additions and 50 deletions.
126 changes: 76 additions & 50 deletions proposals/0013-wave-size-range.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ This also preserves the ability to force the driver to choose your preferred

### HLSL additions

The existing `WaveSize` attribute gains a second overload:
The existing `WaveSize` attribute gains a new variant:

```HLSL
[WaveSize(<minWaveSize>, <maxWaveSize>, [prefWaveSize])]
Expand All @@ -83,15 +83,26 @@ Where `minWaveSize` is the minimum wave size supported by the shader

### DXIL Additions

The existing `WaveSize` value is stored as a metadata 32-bit integer constant.
To store the additional values, an additional metadata tag indicating a tuple of
three 32-bit integers representing the given parameters to `WaveSize`.
In the case where no preferred wave size is specified, the value zero will
indicate that nothing was specified.

| Tag | Constant | Value |
|-------------------------|----------|-------------------------|
|kDxilRangedWaveSizeTag | 23 |MD list: (i32, i32, i32) |
The existing metadata `kDxilWaveSizeTag`(11)
that takes only a single 32-bit integer constant is invalid in 6.8 shaders,
but will continue to be supported in earlier shader model versions.

The new metadata `kDxilRangedWaveSizeTag`(23) takes a tuple
of three 32-bit integers.
These values represent all potential parameters to `WaveSize`.
If all three values are non-zero, they represent the minimum, maximum,
and preferred wave sizes respectively.
If only the first two values are non-zero, they represent the minimum
and maximum respectively without a specified preferred size.
If only the first value is non-zero, it represents the legacy wave size as
introduced in Shader Model 6.6 and previously represented by `kDxilWaveSizeTag`.
In this case, the single non-zero value is effectively minimum, maximum and
preferred size in that it represents the only wave size supported by the shader.

| Tag | Constant | Value | Shader Models |
|-------------------------|----------|-------------------------|---------------|
|kDxilWaveSizeTag | 11 | i32 | <6.8 |
|kDxilRangedWaveSizeTag | 23 |MD list: (i32, i32, i32) | >=6.8 |

### SPIR-V Additions

Expand Down Expand Up @@ -125,16 +136,20 @@ These are where new or slightly altered errors are produced:

Validation should confirm:

* Each element in that is a power-of-two integer between 4 and 128 inclusive.
The third parameter may also be zero.
* The minimum wave size is less than the maximum wave size.
* The preferred wave size is zero or lies between the minimum and maximum.
* Where validator version is less than 1.8, fail on shaders that use
`RangedWaveSize`.
* Validation should fail in an entry has both `RangedWaveSize` and `WaveSize`
metadata.
* Where validator version is greater than or equal to 1.8, fail when The tuple
that the wave size range tag points to does not have exactly three elements.
* The metadata `kDxilRangedWaveSizeTag` points to a tuple of exactly three
elements.
* Each element of that tuple is a power-of-two integer between 4 and 128
inclusive or zero.
* However, the first element (minimum wave size) is not zero.
* The second element (maximum wave size) is greater than the first element
(minimum wave size) or zero.
* The third element (preferred wave size) is greater or equal to the first
element (minimum wave size) and less than or equal to the second element
(maximum wave size) or zero.
* Shaders with target shader model less than 6.8 that use
`kDxilRangedWaveSizeTag` should fail.
* Shaders with target shader model greater than or equal to 6.8 that use
`kDxilWaveSizeTag` should fail.

### Runtime Additions

Expand All @@ -144,70 +159,80 @@ No additions are needed here.
The PSV0 runtime data structure already contains both
`MinimumExpectedWaveLaneCount` and `MaximumExpectedWaveLaneCount` members that
can be used to transmit the minimum and maximum values to the runtime.
The existing single wave size value will continue to set both of these values to
that provided by the user.
The preferred value is not relevant to the runtime as it cannot result in
shader loading failure.

#### Device Capability

As a required feature, devices supporting the shader model it ships with are
As a required feature, devices supporting the Shader Model 6.8 are
required to respect the wave size restrictions indicated by the wave size range
metadata.

## Testing

### Correct Behavior Testing

Verify this compiler output:

1. The two parameter overload of `WaveSize` correctly transmits those values to a
metadata tuple with a zero third value that is pointed to by the correct tag
in the entry point attribute list.
2. The three parameter overload of `WaveSize` transmits those values as well as
the third in the same tuple.
3. That the PSV0 `MinimumExpectedWaveLaneCount` and `MaximumExpectedWaveLaneCount`
Verify the following compiler output:

1. The one parameter variant of `WaveSize` correctly produces a metadata tuple
pointed to by a `kDxilRangedWaveSizeTag` in the entry point attribute list with
the single value as the first element and the last two elements set to zero.
No `kDxilWaveSizeTag` should be produced.
2. The two parameter variant of `WaveSize` correctly produces a metadata tuple
pointed to by a `kDxilRangedWaveSizeTag` in the entry point attribute list with
the two values as the first two elements and the last element set to zero.
No `kDxilWaveSizeTag` should be produced.
3. The three parameter variant of `WaveSize` correctly produces a metadata tuple
pointed to by a `kDxilRangedWaveSizeTag` in the entry point attribute list with
all three values in their respective element locations.
No `kDxilWaveSizeTag` should be produced.
4. That the PSV0 `MinimumExpectedWaveLaneCount` and `MaximumExpectedWaveLaneCount`
values reflect those provided for the wave size range.

Note that the above must all use literal values for the parameters on account of
other compile-time contants being broken due to DXC bug
other compile-time constants being broken due to DXC bug
[#2188](https://github.com/microsoft/DirectXShaderCompiler/issues/2188).

#### Diagnostics Testing

1. Use the following invalid parameters each parameter location to `WaveSize`
and ensure that an appropriate error is produced:
1. Negative power-of-two integer
2. Floating point value
2. Floating-point value
3. non-compile-time constant integer
4. Integer less than 4
5. Integer greater than 128
4. Power-of-two integer less than 4
5. Power-of-two integer greater than 128
6. A non-power-of-two integer between 4 and 128
2. Add the following invalid `WaveSize` attributes to an compute shader entry
point and ensure that an appropriate error is produced:
1. no parameter list
2. an empty parameter list "()"
3. four parameters
1. No parameter list
2. An empty parameter list "()"
3. Four parameters
3. Try the following invalid `WaveSize` parameter value combinations and ensure
that an appropriate error is produced:
1. Set the minimum wave size equal to the maximum
2. Set the minimum wave size greater than the maximum
3. Set the preferred wave size to a value outside of the specified range
4. Combine multiples of the 1, 2 and 3 parameter `WaveSize` attribute overloads
1. The minimum wave size is equal to the maximum
2. The minimum wave size is greater than the maximum
3. The preferred wave size is a value outside of the specified range
4. Combine multiples of the 1, 2 and 3 parameter `WaveSize` attribute variants
with different values on the same entry point and ensure that an attribute
conflict error is produced.

### Validation Testing

Test that the following produce validation errors:

1. The wave size range tag pointing to anything but a tuple of 3
2. A tuple value is not an integer
3. A range tuple value is -4, 0, 1, 2, 3, 127, 129, or 256
4. A preferred tuple value is -4, 1, 2, 3, 127, 129, or 256
5. The minimum wave size value is equal to the maximum
6. The minimum wave size value is greater than the maximum
7. The preferred wave size is outside the specified range, but otherwise valid
1. The wave size range tag pointing to anything but a tuple of 3.
2. A tuple value is not an integer.
3. A range tuple value is -4, 0, 1, 2, 3, 127, 129, or 256.
4. A preferred tuple value is -4, 1, 2, 3, 127, 129, or 256.
5. The minimum wave size value is equal to the maximum, but otherwise valid.
6. The minimum wave size value is greater than the maximum, but otherwise valid.
7. The preferred wave size is outside the specified range, but otherwise valid.
8. Multiple metadata `kDxilRangedWaveSizeTag`s are in the same compiled shader.
9. A metadata `kDxilRangedWaveSizeTag` is included with a `kDxilWaveSizeTag` in
the same compiled shader.
10. Explicit validator versions before 1.8 used with `kDxilRangedWaveSizeTag`s
9. A metadata `kDxilWaveSizeTag` is used with 1.8 or greater validation.
10. Explicit validator versions before 1.8 used with `kDxilRangedWaveSizeTag`s.

### Execution Testing

Expand Down Expand Up @@ -318,6 +343,7 @@ Special thanks:

* Alan Baker
* Chris Bieneman
* Joshua Batista
* Martin Fuller
* Amar Patel
* Damyan Pepper
Expand Down

0 comments on commit 8b6e2e2

Please sign in to comment.