-
Notifications
You must be signed in to change notification settings - Fork 327
Designing a uniformity opt-out #3554
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
Comments
For Unity shaders, the important part of the opt-out design is that shader translators like Tint or Naga can generate the opt-outs, as we will not be able to author the source shaders with the extra information. |
Looking at WGSL 2022-10-25 Minutes it starts with trying to make the escape hatch as local as possible, and then it returns to marking blocks as unsafe-like. In contrast, just having unsafe function versions maximizes locality. What is the motivation for marking blocks of code as unsafe-like instead of just having unsafe functions? I do not see any benefit at all from the marking of blocks of code over having unsafe function variants. |
We should also consider how uniformity might evolve in the future when designing this feature. Along those lines, two future directions come to mind:
Descriptor arrays in Vulkan require dynamically uniform access by default. There is a non-uniform capability, but that leads to less efficient code so indicating that type of access is likely useful to indicate. Additional scopes are more future looking. I believe this will be useful for future features like subgroups, but might rely on underlying language extensions. These two features make me leans towards using an attribute over new builtin names. It would be awkward to have builtins for each scope and wouldn't work at all for descriptor array access. I personally prefer either attributes or builtins over a new statement type. Attributes have the extra advantage of being able to attached to more things than statements. For example, we could attach an attribute to a function parameter without having the statement opt-out cover a whole function. |
I think it's worth fleshing out a critical-user-journey of how this is used. For example, the "programmer knows better, imprecise analysis at fault" case:
Concretely, this is the original program: @group(0) @binding(0) var t: texture_2d<f32>;
@group(0) @binding(1) var s: sampler;
@fragment
fn main(
@builtin(position) p: vec4<f32>,
@location(0) f: f32
) {
if (f<0) {
let c = textureSample(t, s, p.xy);
}
} Compiling with Tint, we get:
So in step 3 the programmer sanitizes the uniformity analysis, e.g. by declaring that they know that the @group(0) @binding(0) var t: texture_2d<f32>;
@group(0) @binding(1) var s: sampler;
@fragment
fn main(
@builtin(position) p: vec4<f32>,
@uniform @location(0) f: f32 // Programmer says they know the 'f' value is uniform.
) {
if (f<0) {
let c = textureSample(t, s, p.xy);
}
} Benefits:
Another interesting case: "programmer knows better, accepts tradeoff in quality due to the incorrectly computed implicit derivative". In this scenario "just" silencing the analysis might be a better match for programmer intent. It would actually be a lie to assert in the source code that a value is uniform when the programmer knows it isn't uniform. |
Where could you put an attribute? We have a lot of choices in the design space:
I'm reminded again that SPIR-V has |
I like the attribute approach described here by @dneto0. I also like the ability to supply the uniform scope (like group, subgroup, quad) with something like To build on it, I think a name like I don't think we should be making it normal to call functions that require a level of uniformity that it isn't actually present, and just rely on implementations to have some predictable fallback behavior when requirements are violated. If someone is doing that, they should fix the shader code. Regarding this debate between variable/expression attributes vs. function, block, or built-in variant based opt-out, I think the variable/expression attribute fits into the uniformity analysis story most cleanly, and potentially provides many benefits down the line. I think that provably uniform can be tracked separately from user-asserted assumptions as well. The downside is that if the different needed uniformity scopes are not properly captured/expressed with the attribute, a user would be required to "lie" about uniformity in some cases (promising a value is fully uniform rather than subgroup or quad uniform which might be all that was true and required). This "lie" could lead to invalid assumptions about uniformity on anything dependent on this value, and failures if those assumptions are checked or enforced at runtime. So this approach requires a lot more work to achieve a full solution. The function/block based opt-out seems to just turn off the error for sensitive operations in a given scope, and built-in variants are similar for the operations themselves. This means either a) uniformity analysis will still be wrong about some unknown number of things, uncorrected by the opt-out mechanism, or b) we just give a blanket pass to code that actually violates the rules. It doesn't leave behind the detailed information required to document where precisely the uniform analysis is too conservative (or just can't know), allow the runtime to catch the introduction of a new source of non-uniformity that wasn't intentional (help catch real bugs), or allow for uniform-aware codegen / optimizations as highlighted by prior comments. Given these trade-offs, I wonder if a global opt-out could be provided until a proper attribute-on-value based approach was ready and robust, after which the global opt-out could eventually be deprecated. Code using global opt-out could be prevented from running in some less trusted mode, or without some compatibility setting in some future, or assumptions could be verified/enforced with extra runtime cost. Putting properly-scoped attributes on the originating source of (analysis-based) potential non-uniformity could reduce assumption validation/enforcement overhead for a "safe" mode as well. |
WGSL 2022-11-01 Minutes
|
Follow up comment: I recently found out about Vulkan's uniformity requirement for barrier being "dynamic uniform". My previous assumption that attributes on values would be sufficient is not valid for the "dynamic uniform" case. Here's a pseudocode example for "dynamic uniform" if (a()) {
// a() is not uniform, and exec here is not uniform
} else {
// exec here is not uniform
if (b()) {
// b() is not uniform, and exec here is not uniform
} else {
// exec is dynamic uniform here due to (compiler unknown) dependency between a() and b()
// uniform if and only if a() is false and b() is false.
// if (!a() && !b()) on any thread, then this is true for *all* threads.
barrier();
}
// exec here is not uniform
} So if "dynamic uniform" is to be supported, it seems that some form of attribute on the barrier() call, or on the block, or on a function wrapping the barrier() call, is necessary. No value or expression attribute will suffice in this case.
|
WGSL 2022-11-08 Minutes
|
To make sure I understand the concern, I wanted to make this more concrete. The example is meaningful if some invocations reach the barrier. So So: var<workgroup> w: i32;
fn a() -> bool { return (w & 1) == 0; } // w is even
fn b() -> bool { return (w & 3) == 0; } // w is a multiple of 4
@compute @workgroup(3)
fn main(@builtin(local_invocation_index) lid: u32) {
if (lid==0) { w = 1; } // falsify a() and b()
workgroupBarrier();
// now copy the example code fragment from above.
if (a()) {
// a() is not uniform, and exec here is not uniform. [[1]]
} else {
// exec here is not uniform [[2]]
if (b()) {
// b() is not uniform, and exec here is not uniform. [[3]]
} else {
// [[4]]
// exec is dynamic uniform here due to (compiler unknown) dependency between a() and b()
// uniform if and only if a() is false and b() is false.
// if (!a() && !b()) on any thread, then this is true for *all* threads.
workgroupBarrier();
}
// exec here is not uniform. [[5]]
}
} And now I see @tex3d's point.
That's a very nice demonstration that getting what we want when we only have "BLAH IS UNIFORM" attributes forces us to lie at least a little bit. |
In internal discussions a 4th option has come been expressed (that I wasn't aware of until recently), which is a mashup of the other three:
Formally this is like option 3's Google doesn't have an opinion on this yet. We're still talking. |
After internal discussion, Google requires a coarse grain control to be present. Our preference for the coarse grain control is an option on CreateShaderModule (i.e. not in the shader, and so it's out of band). We suggest a name such as |
what about the uniform issues coming from barriers (be it fragment, vertex or compute shading) ? |
WGSL only has compute barriers. It would be possible to have a separate feature for barrier opt-out, but there is less consensus about that being a requirement. |
WGSL 2022-11-15 Minutes
|
It's a fine-grain control that disables uniformity errors for fragment shader builtins that ordinarily are required to execute in uniform control flow. Updates those functions to say they yield an indeterminate value when invoked in non-uniform control flow. Contributes to: gpuweb#3554
It's a fine-grain control that disables uniformity errors for fragment shader builtins that ordinarily are required to execute in uniform control flow. Updates those functions to say they yield an indeterminate value when invoked in non-uniform control flow. Contributes to: gpuweb#3554
I hope this thread is the right place to discuss this, apologies if it is not. I'm personally very interested in having the ability to use a "persistent threads" style of GPU usage to process irregular workloads through WebGPU, where threads are kept spinning until the irregular workload is done. In particular, I'm interested in job switching within a single kernel (which I believe is a style referred to as "uberkernels" in the literature). This relies on workgroup coherence, which in the classical persistent threads style would be ensured by picking a workgroup size that matches exactly the subgroup/warp/wavefront size of the device. However, this information is not (and I suspect will never be) available through WebGPU's API. I believe I can work around this by picking a "worst-case" workgroup size of 64 and then use a barrier to achieve the desired coherence with acceptable overhead. Below is a contrived example of the sort of behavior I'm looking to achieve: const JOB_ADD_1 = 0u;
const JOB_ADD_2 = 1u;
const JOB_EXIT = 2u;
@group(0) @binding(0)
var<storage, read_write> data: array<u32>;
var<workgroup> iterations: u32;
var<workgroup> job: u32;
var<workgroup> count: atomic<u32>;
@compute @workgroup_size(64, 1, 1)
fn main(@builtin(workgroup_id) workgroup_id: vec3<u32>, @builtin(local_invocation_index) local_index: u32) {
loop {
if local_index == 0 {
if iterations >= 20 {
data[workgroup_id.x] = atomicLoad(&count);
job = JOB_EXIT;
} else if iterations >= 10 {
job = JOB_ADD_2;
}
iterations += 1;
}
workgroupBarrier();
if job == JOB_ADD_1 {
atomicAdd(&count, 1);
} else if job == JOB_ADD_2 {
atomicAdd(&count, 2);
} else { // JOB_EXIT
return;
}
}
} (As an aside, I believe the barrier to in actuality occur in uniform control flow in this example, though I understand why conservative static analysis would not be able to prove that. However, I must admit that I don't fully understand the description of uniformity analysis in the spec. Is my intuition here correct, or am I misunderstanding something?) Currently, this works on Chromium, but it warns that " |
@RSSchermer I don't think you need an opt-out style escape hatch to satisfy the uniformity analysis for this code. Instead, you will be able to use the The updated logic would look something like this:
|
@jrprice Thank you! That looks very interesting, I wasn't aware. Yes, I do believe that would enable the kinds of kernels I have in mind. |
1. Localized opt-out: Add unchecked_uniformity attribute It's a fine-grain control that disables uniformity errors for fragment shader builtins that ordinarily are required to execute in uniform control flow. Updates those functions to say they yield an indeterminate value when invoked in non-uniform control flow. 2. Coarse-grain opt out: Add 'fragmentShaderDerivativesCheckedUniformity' boolean field defaulting `true`, in GPUShaderModuleDescriptor When false, weakens the uniformity analysis so no uniformity error is generated for derivative-based collective operations. Fixed: gpuweb#3554
#3644 proposes both a fine-grain and a coarse-grain opt-out mechanism for fragment shader derivatives.
|
WGSL 2022-11-22 Minutes
|
Is the plan still to consider @uniform to mean that the annotated value is uniform across the entire draw call? Because that'll also force programmers to lie if they branch on a value that is constant across any given primitive (say thanks to "flat" interpolation) but not the same for all primitives in the draw. |
That is not in #3644 |
Google’s position has evolved:
|
WGSL 2022-12-06 Minutes
|
Diagnostics may be "filtered" both locally and globally. A filter can drop a matching diagnostic, or change its severity level. Fixes: gpuweb#3554
Diagnostics may be "filtered" both globally and over a range of source text. A filter can drop a matching diagnostic, or change its severity level. Future versions of WGSL can drop a rule too. Created "diagnostic rule name" token class - They are spelled like identifier-like things but are not explicitly enumerated in the spec. Fixes: gpuweb#3554
WGSL 2022-12-13 Minutes
|
Diagnostics may be "filtered" both globally and over a range of source text. A filter can drop a matching diagnostic, or change its severity level. Future versions of WGSL can drop a rule too. Created "diagnostic rule name" token class - They are spelled like identifier-like things but are not explicitly enumerated in the spec. Fixes: gpuweb#3554
…ound statements This implements option C from gpuweb#3689 It removes the ability to apply range diagnostic filters directly to expressions. Fixes gpuweb#3554 gpuweb#3689
- Define diagnostics, each having: - severity: error, warning, info, off - triggering rule - triggering location - The spec names certain triggering rules. Currently only "derivative_uniformity" is defined, and it defaults to "error" severity. - Uniformity section is updated generally to say that analysis failures trigger a "uniformity failure", instead of "rejects the program". In one place, say that uniformity failure for deriviative builtins trigger derivative_uniformity at the call site of that builtin; and that uniformity failures for barrier builtins trigger a shader-creation error. - Triggering rules are named like identifiers. - Define diagnostic filters, which have - affected range: span of source text - new severity - triggering rule - Filters with an unknown triggering rule are ignored. - There are global filters, which are given as directives at the top of the module (mixed in with enables). - There are "range" filters, which are given as @diagnostic attributes before: control flow statements, switch bodies, function declarations, and compound statements. - @diagnostic attributes may be given more than once on a particular object. But they must not "conflict", meaning have the same range and triggering rule, but different "new severity". - The affected ranges of diagnostic filters perfectly nest, by constrution. - To apply a filter to a diagnostic: - the triggering location must fall in the affected range - they must have the same triggering rule - the severity of the diagnostic is updated to the one specified in the filter. - Define a step-wise process for processing triggered filters, roughly: 1. For each diagnostic with triggering rule R, apply the diagnostic filter for rule R whose affected range is smallest but also encloses the diagnostic's triggering location, if one exists. 2. Discard "off" diagnostics. 3. For each rule R, all but one "info" diagnostic for R may be discarded. 4. For each rule R, all but one "warning" diagnostic for R may be discarded. If there is such a diagnostic, all the info messages for R may be discarded. 5. If there is at least one error diagnostic, all other diagnostics may be discarded. Generate either a shader-creation or pipeline-creation error. 6. Diagnostics generated during shader-creation are reported in the messsages member of the GPUConpilationInfo object. 7. Error diagnostics generated during pipeline-creation are reported to the enclosing GPU error scope. Fixes: gpuweb#3554 gpuweb#3689
- Define diagnostics, each having: - severity: error, warning, info, off - triggering rule - triggering location - The spec names certain triggering rules. Currently only "derivative_uniformity" is defined, and it defaults to "error" severity. - Uniformity section is updated generally to say that analysis failures trigger a "uniformity failure", instead of "rejects the program". In one place, say that uniformity failure for deriviative builtins trigger derivative_uniformity at the call site of that builtin; and that uniformity failures for barrier builtins trigger a shader-creation error. - Triggering rules are named like identifiers. - Define diagnostic filters, which have - affected range: span of source text - new severity - triggering rule - Filters with an unknown triggering rule are ignored. - There are global filters, which are given as directives at the top of the module (mixed in with enables). - There are "range" filters, which are given as @diagnostic attributes before: control flow statements, switch bodies, function declarations, and compound statements. - @diagnostic attributes may be given more than once on a particular object. But they must not "conflict", meaning have the same range and triggering rule, but different "new severity". - The affected ranges of diagnostic filters perfectly nest, by constrution. - To apply a filter to a diagnostic: - the triggering location must fall in the affected range - they must have the same triggering rule - the severity of the diagnostic is updated to the one specified in the filter. - Define a step-wise process for processing triggered filters, roughly: 1. For each diagnostic with triggering rule R, apply the diagnostic filter for rule R whose affected range is smallest but also encloses the diagnostic's triggering location, if one exists. 2. Discard "off" diagnostics. 3. For each rule R, all but one "info" diagnostic for R may be discarded. 4. For each rule R, all but one "warning" diagnostic for R may be discarded. If there is such a diagnostic, all the info messages for R may be discarded. 5. If there is at least one error diagnostic, all other diagnostics may be discarded. Generate either a shader-creation or pipeline-creation error. 6. Diagnostics generated during shader-creation are reported in the messsages member of the GPUConpilationInfo object. 7. Error diagnostics generated during pipeline-creation are reported to the enclosing GPU error scope. Fixes: gpuweb#3554 gpuweb#3689
WGSL 2023-01-10 Minutes
|
WGSL 2023-01-17 Minutes
|
- Define diagnostics, each having: - severity: error, warning, info, off - triggering rule - triggering location - The spec names certain triggering rules. Currently only "derivative_uniformity" is defined, and it defaults to "error" severity. - Uniformity section is updated generally to say that analysis failures trigger a "uniformity failure", instead of "rejects the program". In one place, say that uniformity failure for deriviative builtins trigger derivative_uniformity at the call site of that builtin; and that uniformity failures for barrier builtins trigger a shader-creation error. - Triggering rules are named like identifiers. - Define diagnostic filters, which have - affected range: span of source text - new severity - triggering rule - Filters with an unknown triggering rule are ignored. - There are global filters, which are given as directives at the top of the module (mixed in with enables). - There are "range" filters, which are given as @diagnostic attributes before: control flow statements, switch bodies, function declarations, and compound statements. - @diagnostic attributes may be given more than once on a particular object. But they must not "conflict", meaning have the same range and triggering rule, but different "new severity". - The affected ranges of diagnostic filters perfectly nest, by constrution. - To apply a filter to a diagnostic: - the triggering location must fall in the affected range - they must have the same triggering rule - the severity of the diagnostic is updated to the one specified in the filter. - Define a step-wise process for processing triggered filters, roughly: 1. For each diagnostic with triggering rule R, apply the diagnostic filter for rule R whose affected range is smallest but also encloses the diagnostic's triggering location, if one exists. 2. Discard "off" diagnostics. 3. For each rule R, all but one "info" diagnostic for R may be discarded. 4. For each rule R, all but one "warning" diagnostic for R may be discarded. If there is such a diagnostic, all the info messages for R may be discarded. 5. If there is at least one error diagnostic, all other diagnostics may be discarded. Generate either a shader-creation or pipeline-creation error. 6. Diagnostics generated during shader-creation are reported in the messsages member of the GPUConpilationInfo object. 7. Error diagnostics generated during pipeline-creation are reported to the enclosing GPU error scope. Fixes: gpuweb#3554 gpuweb#3689
- Define diagnostics, each having: - severity: error, warning, info, off - triggering rule - triggering location - The spec names certain triggering rules. Currently only "derivative_uniformity" is defined, and it defaults to "error" severity. - Uniformity section is updated generally to say that analysis failures trigger a "uniformity failure", instead of "rejects the program". In one place, say that uniformity failure for deriviative builtins trigger derivative_uniformity at the call site of that builtin; and that uniformity failures for barrier builtins trigger a shader-creation error. - Triggering rules are named like identifiers. - Define diagnostic filters, which have - affected range: span of source text - new severity - triggering rule - Filters with an unknown triggering rule are ignored. - There are global filters, which are given as directives at the top of the module (mixed in with enables). - There are "range" filters, which are given as @diagnostic attributes before: control flow statements, switch bodies, function declarations, and compound statements. - @diagnostic attributes may be given more than once on a particular object. But they must not "conflict", meaning have the same range and triggering rule, but different "new severity". - The affected ranges of diagnostic filters perfectly nest, by constrution. - To apply a filter to a diagnostic: - the triggering location must fall in the affected range - they must have the same triggering rule - the severity of the diagnostic is updated to the one specified in the filter. - Define a step-wise process for processing triggered filters, roughly: 1. For each diagnostic with triggering rule R, apply the diagnostic filter for rule R whose affected range is smallest but also encloses the diagnostic's triggering location, if one exists. 2. Discard "off" diagnostics. 3. For each rule R, all but one "info" diagnostic for R may be discarded. 4. For each rule R, all but one "warning" diagnostic for R may be discarded. If there is such a diagnostic, all the info messages for R may be discarded. 5. If there is at least one error diagnostic, all other diagnostics may be discarded. Generate either a shader-creation or pipeline-creation error. 6. Diagnostics generated during shader-creation are reported in the messsages member of the GPUConpilationInfo object. 7. Error diagnostics generated during pipeline-creation are reported to the enclosing GPU error scope. Fixes: gpuweb#3554 gpuweb#3689
Fixing #3689 fixes this. |
- Define diagnostics, each having: - severity: error, warning, info, off - triggering rule - triggering location - The spec names certain triggering rules. Currently only "derivative_uniformity" is defined, and it defaults to "error" severity. - Uniformity section is updated generally to say that analysis failures trigger a "uniformity failure", instead of "rejects the program". In one place, say that uniformity failure for deriviative builtins trigger derivative_uniformity at the call site of that builtin; and that uniformity failures for barrier builtins trigger a shader-creation error. - Triggering rules are named like identifiers. - Define diagnostic filters, which have - affected range: span of source text - new severity - triggering rule - Filters with an unknown triggering rule are ignored. - There are global filters, which are given as directives at the top of the module (mixed in with enables). - There are "range" filters, which are given as @diagnostic attributes before: control flow statements, switch bodies, function declarations, and compound statements. - @diagnostic attributes may be given more than once on a particular object. But they must not "conflict", meaning have the same range and triggering rule, but different "new severity". - The affected ranges of diagnostic filters perfectly nest, by constrution. - To apply a filter to a diagnostic: - the triggering location must fall in the affected range - they must have the same triggering rule - the severity of the diagnostic is updated to the one specified in the filter. - Define a step-wise process for processing triggered filters, roughly: 1. For each diagnostic with triggering rule R, apply the diagnostic filter for rule R whose affected range is smallest but also encloses the diagnostic's triggering location, if one exists. 2. Discard "off" diagnostics. 3. For each rule R, all but one "info" diagnostic for R may be discarded. 4. For each rule R, all but one "warning" diagnostic for R may be discarded. If there is such a diagnostic, all the info messages for R may be discarded. 5. If there is at least one error diagnostic, all other diagnostics may be discarded. Generate either a shader-creation or pipeline-creation error. 6. Diagnostics generated during shader-creation are reported in the messsages member of the GPUConpilationInfo object. 7. Error diagnostics generated during pipeline-creation are reported to the enclosing GPU error scope. Fixes: gpuweb#3554 gpuweb#3689
- Define diagnostics, each having: - severity: error, warning, info, off - triggering rule - triggering location - The spec names certain triggering rules. Currently only "derivative_uniformity" is defined, and it defaults to "error" severity. - Uniformity section is updated generally to say that analysis failures trigger a "uniformity failure", instead of "rejects the program". In one place, say that uniformity failure for deriviative builtins trigger derivative_uniformity at the call site of that builtin; and that uniformity failures for barrier builtins trigger a shader-creation error. - Triggering rules are named like identifiers. - Define diagnostic filters, which have - affected range: span of source text - new severity - triggering rule - Filters with an unknown triggering rule are ignored. - There are global filters, which are given as directives at the top of the module (mixed in with enables). - There are "range" filters, which are given as @diagnostic attributes before: control flow statements, switch bodies, function declarations, and compound statements. - @diagnostic attributes may be given more than once on a particular object. But they must not "conflict", meaning have the same range and triggering rule, but different "new severity". - The affected ranges of diagnostic filters perfectly nest, by constrution. - To apply a filter to a diagnostic: - the triggering location must fall in the affected range - they must have the same triggering rule - the severity of the diagnostic is updated to the one specified in the filter. - Define a step-wise process for processing triggered filters, roughly: 1. For each diagnostic with triggering rule R, apply the diagnostic filter for rule R whose affected range is smallest but also encloses the diagnostic's triggering location, if one exists. 2. Discard "off" diagnostics. 3. For each rule R, all but one "info" diagnostic for R may be discarded. 4. For each rule R, all but one "warning" diagnostic for R may be discarded. If there is such a diagnostic, all the info messages for R may be discarded. 5. If there is at least one error diagnostic, all other diagnostics may be discarded. Generate either a shader-creation or pipeline-creation error. 6. Diagnostics generated during shader-creation are reported in the messsages member of the GPUConpilationInfo object. 7. Error diagnostics generated during pipeline-creation are reported to the enclosing GPU error scope. Fixes: gpuweb#3554 gpuweb#3689
- Define diagnostics, each having: - severity: error, warning, info, off - triggering rule - triggering location - The spec names certain triggering rules. Currently only "derivative_uniformity" is defined, and it defaults to "error" severity. - Uniformity section is updated generally to say that analysis failures trigger a "uniformity failure", instead of "rejects the program". In one place, say that uniformity failure for deriviative builtins trigger derivative_uniformity at the call site of that builtin; and that uniformity failures for barrier builtins trigger a shader-creation error. - Triggering rules are named like identifiers. - Define diagnostic filters, which have - affected range: span of source text - new severity - triggering rule - Filters with an unknown triggering rule are ignored. - There are global filters, which are given as directives at the top of the module (mixed in with enables). - There are "range" filters, which are given as @diagnostic attributes before: control flow statements, switch bodies, function declarations, and compound statements. - @diagnostic attributes may be given more than once on a particular object. But they must not "conflict", meaning have the same range and triggering rule, but different "new severity". - The affected ranges of diagnostic filters perfectly nest, by constrution. - To apply a filter to a diagnostic: - the triggering location must fall in the affected range - they must have the same triggering rule - the severity of the diagnostic is updated to the one specified in the filter. - Define a step-wise process for processing triggered filters, roughly: 1. For each diagnostic with triggering rule R, apply the diagnostic filter for rule R whose affected range is smallest but also encloses the diagnostic's triggering location, if one exists. 2. Discard "off" diagnostics. 3. For each rule R, all but one "info" diagnostic for R may be discarded. 4. For each rule R, all but one "warning" diagnostic for R may be discarded. If there is such a diagnostic, all the info messages for R may be discarded. 5. If there is at least one error diagnostic, all other diagnostics may be discarded. Generate either a shader-creation or pipeline-creation error. 6. Diagnostics generated during shader-creation are reported in the messsages member of the GPUConpilationInfo object. 7. Error diagnostics generated during pipeline-creation are reported to the enclosing GPU error scope. Fixes: gpuweb#3554 gpuweb#3689
- Define diagnostics, each having: - severity: error, warning, info, off - triggering rule - triggering location - The spec names certain triggering rules. Currently only "derivative_uniformity" is defined, and it defaults to "error" severity. - Uniformity section is updated generally to say that analysis failures trigger a "uniformity failure", instead of "rejects the program". In one place, say that uniformity failure for deriviative builtins trigger derivative_uniformity at the call site of that builtin; and that uniformity failures for barrier builtins trigger a shader-creation error. - Triggering rules are named like identifiers. - Define diagnostic filters, which have - affected range: span of source text - new severity - triggering rule - Filters with an unknown triggering rule are ignored. - There are global filters, which are given as directives at the top of the module (mixed in with enables). - There are "range" filters, which are given as @diagnostic attributes before: control flow statements, switch bodies, function declarations, and compound statements. - @diagnostic attributes may be given more than once on a particular object. But they must not "conflict", meaning have the same range and triggering rule, but different "new severity". - The affected ranges of diagnostic filters perfectly nest, by constrution. - To apply a filter to a diagnostic: - the triggering location must fall in the affected range - they must have the same triggering rule - the severity of the diagnostic is updated to the one specified in the filter. - Define a step-wise process for processing triggered filters, roughly: 1. For each diagnostic with triggering rule R, apply the diagnostic filter for rule R whose affected range is smallest but also encloses the diagnostic's triggering location, if one exists. 2. Discard "off" diagnostics. 3. For each rule R, all but one "info" diagnostic for R may be discarded. 4. For each rule R, all but one "warning" diagnostic for R may be discarded. If there is such a diagnostic, all the info messages for R may be discarded. 5. If there is at least one error diagnostic, all other diagnostics may be discarded. Generate either a shader-creation or pipeline-creation error. 6. Diagnostics generated during shader-creation are reported in the messsages member of the GPUConpilationInfo object. 7. Error diagnostics generated during pipeline-creation are reported to the enclosing GPU error scope. Fixes: gpuweb#3554 gpuweb#3689
- Define diagnostics, each having: - severity: error, warning, info, off - triggering rule - triggering location - The spec names certain triggering rules. Currently only "derivative_uniformity" is defined, and it defaults to "error" severity. - Uniformity section is updated generally to say that analysis failures trigger a "uniformity failure", instead of "rejects the program". In one place, say that uniformity failure for deriviative builtins trigger derivative_uniformity at the call site of that builtin; and that uniformity failures for barrier builtins trigger a shader-creation error. - Triggering rules are named like identifiers. - Define diagnostic filters, which have - affected range: span of source text - new severity - triggering rule - Filters with an unknown triggering rule are ignored. - There are global filters, which are given as directives at the top of the module (mixed in with enables). - There are "range" filters, which are given as @diagnostic attributes before: control flow statements, switch bodies, function declarations, and compound statements. - @diagnostic attributes may be given more than once on a particular object. But they must not "conflict", meaning have the same range and triggering rule, but different "new severity". - The affected ranges of diagnostic filters perfectly nest, by constrution. - To apply a filter to a diagnostic: - the triggering location must fall in the affected range - they must have the same triggering rule - the severity of the diagnostic is updated to the one specified in the filter. - Define a step-wise process for processing triggered filters, roughly: 1. For each diagnostic with triggering rule R, apply the diagnostic filter for rule R whose affected range is smallest but also encloses the diagnostic's triggering location, if one exists. 2. Discard "off" diagnostics. 3. For each rule R, all but one "info" diagnostic for R may be discarded. 4. For each rule R, all but one "warning" diagnostic for R may be discarded. If there is such a diagnostic, all the info messages for R may be discarded. 5. If there is at least one error diagnostic, all other diagnostics may be discarded. Generate either a shader-creation or pipeline-creation error. 6. Diagnostics generated during shader-creation are reported in the messsages member of the GPUConpilationInfo object. 7. Error diagnostics generated during pipeline-creation are reported to the enclosing GPU error scope. Fixes: gpuweb#3554 gpuweb#3689
- Define diagnostics, each having: - severity: error, warning, info, off - triggering rule - triggering location - The spec names certain triggering rules. Currently only "derivative_uniformity" is defined, and it defaults to "error" severity. - Uniformity section is updated generally to say that analysis failures trigger a "uniformity failure", instead of "rejects the program". In one place, say that uniformity failure for deriviative builtins trigger derivative_uniformity at the call site of that builtin; and that uniformity failures for barrier builtins trigger a shader-creation error. - Triggering rules are named like identifiers. - Define diagnostic filters, which have - affected range: span of source text - new severity - triggering rule - Filters with an unknown triggering rule are ignored. - There are global filters, which are given as directives at the top of the module (mixed in with enables). - There are "range" filters, which are given as @diagnostic attributes before: control flow statements, switch bodies, function declarations, and compound statements. - @diagnostic attributes may be given more than once on a particular object. But they must not "conflict", meaning have the same range and triggering rule, but different "new severity". - The affected ranges of diagnostic filters perfectly nest, by constrution. - To apply a filter to a diagnostic: - the triggering location must fall in the affected range - they must have the same triggering rule - the severity of the diagnostic is updated to the one specified in the filter. - Define a step-wise process for processing triggered filters, roughly: 1. For each diagnostic with triggering rule R, apply the diagnostic filter for rule R whose affected range is smallest but also encloses the diagnostic's triggering location, if one exists. 2. Discard "off" diagnostics. 3. For each rule R, all but one "info" diagnostic for R may be discarded. 4. For each rule R, all but one "warning" diagnostic for R may be discarded. If there is such a diagnostic, all the info messages for R may be discarded. 5. If there is at least one error diagnostic, all other diagnostics may be discarded. Generate either a shader-creation or pipeline-creation error. 6. Diagnostics generated during shader-creation are reported in the messsages member of the GPUConpilationInfo object. 7. Error diagnostics generated during pipeline-creation are reported to the enclosing GPU error scope. Fixes: gpuweb#3554 gpuweb#3689
…structs and compound statements (#3713) Add diagnostics, derivative uniformity failures trigger diagnostics Fixes: #3554 #3689 - Define diagnostics, each having: - severity: error, warning, info, off - triggering rule - triggering location - The spec names certain triggering rules. Currently only "derivative_uniformity" is defined, and it defaults to "error" severity. - When named, triggering rules are named like identifiers. - There is an unnamed trigger rule, used for error diagnostics that are not filterable. An example is a uniformity failure on a barrier call in a compute shader. - Uniformity section is updated generally to say that analysis failures trigger a "uniformity failure", instead of "rejects the program". In one place, say that uniformity failure for deriviative builtins trigger derivative_uniformity at the call site of that builtin; and that uniformity failures for barrier builtins trigger a shader-creation error. - Triggering rules are named like identifiers. - Define diagnostic filters, which have - affected range: span of source text - new severity - triggering rule - Filters with an unknown triggering rule are ignored. - There are global filters, which are given as directives at the top of the module (mixed in with enables). - There are "range" filters, which are given as @diagnostic attributes before: control flow statements, switch bodies, function declarations, and compound statements. - @diagnostic attributes may be given more than once on a particular object. But they must not "conflict", meaning have the same range and triggering rule, but different "new severity". - The affected ranges of diagnostic filters perfectly nest, by constrution. - To apply a filter to a diagnostic: - the triggering location must fall in the affected range - they must have the same triggering rule - the severity of the diagnostic is updated to the one specified in the filter. - Define a step-wise process for processing triggered filters, roughly: 1. For each diagnostic with triggering rule R, apply the diagnostic filter for rule R whose affected range is smallest but also encloses the diagnostic's triggering location, if one exists. 2. Discard "off" diagnostics. 3. For each rule R, all but one "info" diagnostic for R may be discarded. 4. For each rule R, all but one "warning" diagnostic for R may be discarded. If there is such a diagnostic, all the info messages for R may be discarded. 5. If there is at least one error diagnostic, all other diagnostics may be discarded. Generate either a shader-creation or pipeline-creation error. 6. Diagnostics generated during shader-creation are reported in the messsages member of the GPUConpilationInfo object. 7. Error diagnostics generated during pipeline-creation are reported to the enclosing GPU error scope. - Incorporate diagnostic severities into uniformity analysis - Define a "potential-trigger-set" as the set of trigger rules that might be triggered at locations we've already analyzed, but due to the non-uniformity of a value or flow that is yet to be analyzed. There are only two possible members: - derivative_uniformity - an unnamed triggering rule, for unfilterable uniformity requirements for compute shader barrier-like synchronization - The *RequiredToBeUniform nodes are expanded into one for each of the diagnostic severities that can be reported to the application. - This fixes which diagnostcs are triggered, from which triggering locations. - Each is associated with a "potentially-triggered-set". - Introduce new parameter return tag * Splits parameter tag into two: * parameter tag for pure uniformity requirements * parameter return tag for effects on return value * Update analysis to refer to two tags appropriately - Define "nearest enclosing diagnostic filter" for a source location and triggering rule, when taken as a pair. - Call site tag for derivative-using functions is taken from the neareset enclosing diagnostic filter. - Clarify affected range of diagnostics applied at the start of the syntactic form. They also apply to any *other* diagnostics listed at the start of *that* syntactic form. This matters if/when we add a "unrecognized diagnostic" triggering rule. Per feedback from James Price. - Clarify the wording of the overall uniformity analysis algorithm. - No order of analysis is implied - Simplify wording for definition of parameter tag, pointer parameter tag. Use bullet points. - Don't early exit from the severity loop when triggering diagnostics for uniformity failures. - Note that keeping the graph for a function is useful for providing informative diagnostics. - Say that a "call site" location is specifically the source location for the first token in the parsed call_phrase grammar rule. - The attribute multiplicity exception belongs in the row for @diagnostic Co-authored-by: Alan Baker <[email protected]> Co-authored-by: Jim Blandy <[email protected]>
Split from #3479
This issue is for discussion of a design for a uniformity opt out mechanism.
There have been three proposals (to my knowledge):
@uniform
).unchecked_uniformity { ... }
).uniform_textureSample(...)
).CC @jimblandy
The text was updated successfully, but these errors were encountered: