Conversation
|
@jrprice has some feedback about this concept that it's weird/unsatisfying. |
kvark
left a comment
There was a problem hiding this comment.
Can we please split these commits into separate PRs?
wgsl/index.bs
Outdated
|
|
||
| Note: That is, each member type must be a [=plain type=]. | ||
|
|
||
| A structure type is a <dfn>buffer-root</dfn> if it is used as the [=store type=] |
There was a problem hiding this comment.
This seems a bit strange, it's backwards. It says, the type depends on how it's used.
I guess one could describe type inference in a similar way, so it's not too exceptional
There was a problem hiding this comment.
An alternative would be that each struct definition could potentially expand into two SPIR-V constructs: one block and one non-block. Then it would be fine to use the same struct as both buffer-root and non-buffer-root.
It depends on how much you want to abstract away SPIR-V's "block" concept.
There was a problem hiding this comment.
Another alternative is to keep [[block]].
Thinking about this more, this change carries a SAaaD hazard (Spooky Action at a Distance): if you have a large module, and you decide to add a uniform binding for a particular struct, you may get an error in potentially a totally different place (where this structure was used before, but now is not valid).
There was a problem hiding this comment.
Agree for the PR as is. If the WGSL struct could expand into two SPIR-V structs I think it would avoid SAaaD?
There was a problem hiding this comment.
if SPIR-V has to split the structs, you don't need to define the whole "buffer-root" concept. While in general I'd be very wary against splitting types, the main complexity that comes with it is dealing with all the composite dependent types. In case of [[block]] there are not dependent types by definition, so splitting could be done without much blood lost.
Yeah, this builds on #2103, as preliminary work. |
|
I see now. Was expecting the base PR to be mentioned in the main description, but it wasn't. |
|
[process] |
wgsl/index.bs
Outdated
|
|
||
| Note: That is, each member type must be a [=plain type=]. | ||
|
|
||
| A structure type is a <dfn>buffer-root</dfn> if it is used as the [=store type=] |
There was a problem hiding this comment.
Another alternative is to keep [[block]].
Thinking about this more, this change carries a SAaaD hazard (Spooky Action at a Distance): if you have a large module, and you decide to add a uniform binding for a particular struct, you may get an error in potentially a totally different place (where this structure was used before, but now is not valid).
jrprice
left a comment
There was a problem hiding this comment.
TLDR: I'm fine with removing the [[block]] attribute, but I think the "buffer-root" concept is unnecessary.
As @kvark already mentioned, changing the type based on its usage seems backwards.
It feels much more natural to me to build up validation rules the other way, which would be consistent with how we currently describe other validation rules in the spec.
We usually (always?) determine where we can use a struct based on its contents, not the other way around.
e.g.
- if a struct contains an atomic, it can only be used in the Storage or Workgroup storage classes.
- if a struct is missing shader IO attributes, it cannot be used as an entry parameter or return type.
I don't see a compelling reason to do things differently here.
There are only three validation rules in this PR that use the term "buffer-root".
One of them is entirely redundant, and the other two could be trivially replaced with language that mentions "dynamically-sized array" instead.
I've added inline comments to highlight them.
If we were to make those changes, I /think/ that we could delete the any mention of "buffer-root" from this PR without losing any information about the semantics or validity of a WGSL module.
This suggests to me this "buffer-root" concept is unnecessary (though I appreciate there's some dependence here on how we would plan to support arrays-of-bindings).
This "buffer-root" concept also means that we're not actually getting rid of [[block]], we're just renaming it and making it implicit.
I don't think that this is an improvement over where we are today, since the author has to do extra work now to figure out where that block attribute is going to be applied.
For example, I agree with the action-at-a-distance concern that was already mentioned.
I don't like the notion that adding or removing a variable can make the definition of a struct invalid.
Finally, it also prevents us making further changes to allow Storage/Uniform buffers to use non-structure store types, which several people (myself included) would like to see.
wgsl/index.bs
Outdated
| * a matrix type | ||
| * an [=atomic type|atomic=] type | ||
| * an array type | ||
| * a [=structure=] type that is not a [=buffer-root=] |
There was a problem hiding this comment.
Instead of saying "not a buffer-root", this could say "does not contain a dynamically-sized array".
There was a problem hiding this comment.
Thanks for the feedback!
Done.
242b728 to
22a892b
Compare
|
The new commit is just a rebase. |
22a892b to
d8bbd15
Compare
| </table> | ||
|
|
||
| When specified, an element count expression |N| must: | ||
| The first element in an array is at index 0, and each successive element is at the next integer index. |
There was a problem hiding this comment.
Editorially it seemed to make sense to pull this upward.
| [SHORTNAME] defines the following attributes that can be applied to array types: | ||
| * [=attribute/stride=] | ||
|
|
||
| Restrictions on runtime-sized arrays: |
There was a problem hiding this comment.
The first two restrictions are replaced by uses of "fixed footprint" in the definitions of both array and structure types.
|
How is the implementation supposed to behave for this case? My understanding is that SPIR-V backend would have to generate 2 different stuctures for |
|
Wouldn't the argument to
It seems that newer version of SPIR-V would disallow using a |
|
Ok, so there is one |
|
I think so. That's what happens in GLSL with this small shader (that's a bit similar up to variables in #version 460
struct Foo {
int a;
int b[4];
};
layout(std430, binding=0) buffer MyFoo {
Foo foo;
};
void f(Foo a) {
}
void main()
{
f(foo);
} |
kvark
left a comment
There was a problem hiding this comment.
Ok, I'm cautiously optimistic about this. Hoping no surprises during implementation, assuming you thought this through :)
We discussed this internally, and the solution I think Tint is going to use is to wrap the So: struct Foo {
i : i32;
};
[[group(0), binding(0)]] var<uniform> ubo: Foo;
[[group(0), binding(1)]] var<storage, read_write> ssbo: Foo;
struct Bar {
foo: Foo;
};
fn func(f: Foo) {
ssbo.i = f.i;
x := ubo;
}Would internally translate to: struct Foo {
i : i32;
};
[[block]] // For internal / illustrative purposes only.
struct FooWrapper {
inner : Foo;
};
[[group(0), binding(0)]] var<uniform> ubo: FooWrapper;
[[group(0), binding(1)]] var<storage, read_write> ssbo: FooWrapper;
struct Bar {
foo: Foo;
};
fn func(f: Foo) {
ssbo.inner.i = f.i;
x := ubo.inner;
}This same transformation would work for non-structure |
|
Yes, that makes sense. Thanks @ben-clayton ! |
|
One thing to remember is if there's a runtime-sized array in the struct, then SPIR-V/Vulkan requires it to be in the outermost struct for an SSBO. But WGSL can't use that struct anywhere else anyway. Added this issue to the next agenda. |
|
Right, so this transformation doesn't apply to all storage/uniform structures, it excludes the ones with run-time arrays. That seems fine. |
Part of gpuweb#1534 Change-Id: I4bd26ca668c93d22c265a1ec99bdeadfdfcdfcd4
- Instead of adding various restrictions about where a runtime-sized array can appear, invent a "fixed footprint" concept for types. A runtime-sized array is not fixed-footprint, but other plain types are, provided they don't recursively contain runtime-sized arrays. - The only remaining restriction for runtime-sized arrays is that no expression may evaluate to a runtime-sized array. This is not redundant becuase we need to prevent allowing the Load Rule to kick in and cause a load of a runtime-sized array. - Remove the 'block' token. - Remove remove the attribute list from the start of the structure declaration grammar rule. - Also fix redundant text segments that crept in during an earlier rebase.
* Remove two paragraphs that are part of gpuweb#2103, the array-stride change.
Describe it as "plain type with fixed footprint".
This excludes atomic types, as already expressed by the entry in the storage classes table.
d6ae22b to
49b56fd
Compare
|
Rebased against main. No content change. |
…or workgroup variable Builds on gpuweb#2104 because that defines the useful concept of "fixed-footprint" type. * Refines "fixed-footprint" to add subcategory of "creation-fixed footprint", to mean a plain type whose memory footprint is fixed at shader creation time. The "fixed-footprint" remains defined as a plain type whose memory footprint is fixed by the pipline-creation time. * Allow element count on a fixed-size array to be an overridable module-scope constant. * Later I expect we'll have a proper category and name for pipeline-constexpr and we can patch this up at that time. * Previously "fixed-size array" meant element count was a shader-creatio-time constant. Now it allows pipeline-creation constant, so revisit all uses of "fixed-size array" and further qualify with "with creation-fixed footprint" in the intended places: In particular: - array element must be fixed-footprint. - structure member that is fixed-size array must be fixed-footprint * Note and provide examples that the store type for a workgroup variable may have an element count that is pipeline-overridable. It has fixed footprint but not necessarily creation-time fixed footprint. * Editorially emphasize that type constructors only create constructible types. Fixes: gpuweb#2024
|
Approved in 2021-11-30 meeting |
WGSL meeting minutes 2021-11-30
|
Base PR: #2103
Replace [[block]] with a buffer-root concept.
Part of #1534
Fixes #1008