-
Notifications
You must be signed in to change notification settings - Fork 42
Rough proposal collecting thoughts on uniformity #405
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
This has been sitting around in my checkout for close to a year, and I've been meaning to finish dumping thoughts into it and post it for wider review and feedback. So here goes! Please be gentle, it's real rough.
* A _dispatch_ represents the full set of threads spawned from a CPU API | ||
invocation. | ||
* A _thread group_ represents a subset of a dispatch that can execute | ||
concurrently. | ||
* A _wave_ represents a subset of a thread group that represents in a single | ||
SIMD processor. | ||
* A _quad_ represents a grouping of four adjacent threads in a wave. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Worth including Vulkan terminology here as well?
Uniformity of data and control flow are central concepts to SIMT execution | ||
models, and is required for correct execution of shader programs. Despite | ||
the importance of this fundamental property it is not represented in any | ||
explicit way in the HLSL language. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe mention that this requires backend compilers to attempt to analyse for uniformity?
* `group_uniform` | ||
* `simd_uniform` | ||
* `quad_uniform` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It'd be good to explain how these relate to the dispatch, thread group, wave etc. scopes that were defined above.
* `group_uniform` | ||
* `simd_uniform` | ||
* `quad_uniform` | ||
* non-uniform (default state with no associated keyword) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be nice to have a way to explicitly mark non-uniform? Would leave open possibility of a "strict" mode where uniformity annotations are required and would allow developers to make their intent more explicit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I need to think on this. My intent was that we would only have a strict mode, so explicit uniformity would be required everywhere that requires uniformity, and that no annotation would mean non-uniform. With that approach I'm not sure how an explicit non_uniform
helps, but maybe I'm missing something.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm mainly wanting to avoid developers having to come up with naming or commenting conventions to document non-uniformity in their code, so I see it filling a role more like the signed
keyword. (Although I expect now to be educated that signed
actually does something more than I think it does)
within a control flow block, the control flow is said to be _uniform control | ||
flow_. | ||
|
||
## Motivation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd love to know what, if anything, this proposal does to NonUniformResourceIndex.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should cease to exist, and I should capture that.
|
||
## Proposed solution | ||
|
||
### Uniformity as a Type Qualifier |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are there alternative approachs to using type qualifiers? I think doing so means we need to change the grammar?
Could something like:
group_uniform<int> myValue
Be made to work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we have a template and non-template spelling that don't use the same words we could do something similar. For example:
template<typename T>
using GroupUniform = group_uniform T
Would simply enable:
GroupUniform<int> MyInt;
Co-authored-by: Damyan Pepper <[email protected]>
Co-authored-by: Damyan Pepper <[email protected]>
Co-authored-by: Damyan Pepper <[email protected]>
Co-authored-by: Damyan Pepper <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One more note for myself here:
The [[hlsl::required_uniform(..)]]
attribute should imply to a function that it's initial control flow uniformity is the value set, otherwise all non-entry functions should assume default uniformity as non-uniform. Entry functions should assume default group
uniformity.
The uniformity of each control flow block should be the intersection of the uniformity of the parent block and the condition (if any) that the block be entered.
Possibly related, it might also be worth talking about the whole "dynamic uniform" vs. "subgroup uniform" behavior. As dumb as it sounds, is Basically, what are drivers/hardware allowed to pack together into waves? This sort of packing is more common in the draw side of things (SV_InstanceID is infamously not uniform), but so far it's been very undefined. |
* `group_uniform` | ||
* `simd_uniform` | ||
* `quad_uniform` | ||
* non-uniform (default state with no associated keyword) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any merit to having a command_uniform
scope or similar indicating uniformity across all thread groups? E.g. for constants? There are, to my knowledge, some implementations that care about this (at least outside of DX12).
Compile-time constants and Groupshared variable declarations imply | ||
`group_uniform` uniformity. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should constant buffer/SRV data also be automatically marked this way? They're supposed to be read-only and non-volatile for the lifetime of the shader AFAIU.
Uniformity qualifiers may be applied on shader inputs. When applied to an input | ||
the compiler will diagnose known cases where the qualifier mismatches, and it | ||
will trust the user in other cases. A runtime validation may be added to catch | ||
incorrect source annotations. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be good to have some sort of interaction with NonUniformResourceIndex
documented - feels like these qualifiers could just outright replace it.
A new "UniformityReduction" cast will reduce the uniform scope allowing | ||
conversion of one uniformity scope to another uniformity scope as long as the | ||
source scope has a greater uniformity scope. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Something i'm missing here is what happens if you did, e.g.:
group_uniform int a;
simd_uniform int b;
int c = a * b;
I would expect c to automatically be treated as simd_uniform (i.e. the smaller of the scopes) as the result, but that's not spelled out here AFAICT.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh wait now I look again that's what the next two sentences are saying - perhaps worth an example?
This has been sitting around in my checkout for close to a year, and I've been meaning to finish dumping thoughts into it and post it for wider review and feedback. So here goes!
Please be gentle, it's real rough.