Skip to content

WGSL 2020 07 28

François Daoust edited this page Dec 2, 2020 · 1 revision
Dean Jackson


Dan Sinclair


⌨️ Scribe
Google Meet




WGSL Issues


Open Issues
Marked Issues


Meeting Issues

Tentative Agenda

  • 2020-07-21 Action item review:
    • DN: Will try row and column in SPIR-V (#910) Matrix specific stuff in #922
    • MM: Will look for matrix requirements in MSL (#910)
    • GR: Will look at matrix requirements in HLSL/DXIL (#910)
    • Apple: Will look into validating grammar on CI
    • DS: Move stride decoration into type_decl
    • DS: Remove NumWorkgroups from grammar, update bug to handle post MVP.
    • JG: Will update builtin PR to fixup merge conflicts.
  • Use brackets for array types (#854)
  • Vertex and Instance ID and base ID builtins. (#901)
  • Constant propagation (#905)
  • Add stride array decoration. (#910)
  • Validation rules for WGSL modules: binding collisions (#889)
  • Add popcount and reverse_bits integer built-in functions (#947)
  • Explicit layout needs more than Offset: ArrayStride and matrix attributes (#773)
  • Allow struct_decl to have a name. (#952)
  • Interface matching rules (#644)
  • Extern declarations (#883)

📋 Attendance

WIP, the list of all the people invited to the meeting. In bold, the people that have been seen in the meeting:

  • Apple
    • Dean Jackson
    • Fil Pizlo
    • Myles C. Maxfield
    • Robin Morisset
  • Google
    • Dan Sinclair
    • David Neto
    • Kai Ninomiya
    • Ryan Harrison
    • Sarah Mashayekhi
  • Intel
    • Yunchao He
    • Narifumi Iwamoto
  • Microsoft
    • Damyan Pepper
    • Rafael Cintron
    • Greg Roth
    • Michael Dougherty
    • Tex Riddell
  • Mozilla
    • Dzmitry Malyshau
    • Jeff Gilbert
  • Joshua Groves
  • Mehmet Oguz Derin
  • Timo de Kort
  • Lukasz Pasek
  • Tyler Larson
  • Lukasz Pasek
  • Pelle Johnsen
  • Matijs Toonen

⚖️ Discussion

2020-07-21 Action item review

  • AI(DN): Will try row and column in SPIR-V.
    • DN: Populating issue #922 with notes on how SPIR-V and vulkan do it. Investigating putting annotation on type. Column major straightforward, row-major end up doing scatter/gather operations. In SPIR-V the pointer for the two types of vector have the same types. The pointer to the vector has a stride, implicit or explicit. For row-major is stride of matrix. End up having matrices having layout and pointer to vector having layout. Or, MSL looks to only support column-major, so could just drop row-major. GLSL has both. HLSL has both. MSL only has native column major. Without row-major dont’ need layout information as you can specify the natural layout. Done GLSL experiments to verify understanding. Writing same example for HLSL
    • TR: I think not having row-major layout is a great idea. Source of a lot of pain to have different ways to layout the matrices. No real good justification as can multiply in the other direction. Just pain and suffering. Support single layout.
    • MM: Me too
    • JG: True for 4x4 but non 4x4, especially non-square, row/column major orientation changes packing
    • TR: Can always just pack the equivalent. Put components wanted, change operations that operate on the matrix to compensate for hte layout
    • JG: Is that how it works in SPIR-V? In GLSL it is a property of the binding.
    • DN: Yes it is. If I’m understanding Tex, if you want tighter packing store the transpose and transpose
    • TR: Yea, falls away when it becomes scalar ops. So not less efficient
    • JG: Except the copies
    • TR: If you have them in transposed then identical as far as storage goes, same layout. Then an understanding in shader, just like type where you annotate layout, you have to do the transpose.
    • JG: Yes, but you have to do the transpose
    • TR: Right, but those are translated into scalar ops anyway
    • JG: So you think it’s optimized away
    • TR: Essentially just intermediate transformations which aren’t meaningful once it gets down to the lower level
    • JG: No meaningful for other work in shader unless you’re mostly working with matrices
    • DN: May end up memory bound
    • JG: Have to do load/store swizzles and if the rest of the workload is light, maybe matters.
    • TR: How is it not essentially equivalent to the annotation and storing the components that way? Instead of having the compiler do the transposition, the developer handles it. There is one logical layout for the matrix
    • JG: A 3x4 and a 4x3 there are 2 ways to pack, one for column and one for row and you may pick one for better pjacking
    • TR: Right, but need to work with shader, either to transpose or the compiler does it for you or the developer does the transpose
    • JG: But if you forbid column major then have to unpack yourself and hope it’s optimized out. Equivalent in complexity.
    • DJ: Do we want to make this a real issue and discuss formally?
    • JG: Yes
    • MM: Isn’t it already? #773
    • TR: One of the problems with matrix orientation is it gives the shader code the illusion that indexing the column vector, more confusing in HLSL due to things being reversed. Accessing a column and it’s packed row-major you're having to do these scatter/gather operations and the simple operation in the shader which looks like vector accessor isn’t, they’re separate disparate components. WIthout multiple layouts simple operation is just accessing a vector. This magic is high level stuff. Doing the multiply in the reverse order for the transposed version could also be done. Reverse operator sides for the transpose
    • JG: Bellwether is presence/absence in SPIR-V
    • MM: Exact same thing for metal.
    • JG: Looking at being able to do both is a potential feature. Depending on underlying platform, if the majority support them, sways opinion one way, or if don’t sways the other. Seems to imply a narrow use case if only one uses, but maybe more general if others use it
    • RM: Not sure if simple majority is enough. A feature in WGSL that can’t easily compile ….
    • JG: Let me be clear, this is influencing opinion on if this is interesting. If everyone supports we should default to support. If no-one or someone has difficulty we should not support it
    • RM: Dont’ think it’s supported in MSL but don’t know how hard it would be to polyfill. Doesn’t seem trivial.
    • MM: If you had a sequence of matrix multiplies the language would say right associative. To emulate in metal would multiply as if left associative. Would be difficult to do assuming the path to emulation would be represent the transform matrix as a matrix type and change the ops. Another way, don’t represent the matrix as matrix, but as array but then lose builtins for matrix ops. Can’t think of any way to emulate the other layout that would be reasonable.
    • TR: Is Metal similar to GLSL where it’s column-major matrices
    • MM: Yes.
    • DM: Either need to implement rotation in SPIR-V to WGSL or WGSL to metal. One of two places have to have the logic. Choosing the simpler api makes it more understandable and portable. Support Davids suggestion and keep it column major. Extend later if there is demand.
    • DN: If we want to support porting existing GLSL row-major content then the complexity of transforming into column-major would expand into the ops Tex was mentioning and would be about the same complexity. I think it’s OK to have column-major only for now and tooling can solve the translation from existing content. Keeping it simple has major benefits.
    • TR: Also really don’t like vector with a stride. Vectors are tightly packed, point of vector over array
    • DN: Can we make the call that column-major is good for MVP and re-visit after.
    • JG: Yea, sure.
    • DS: What does that mean, no matrix stride, no row-major no column-major
    • MM: A matrix in MSL isn’t flexible.
    • DS: Still need array stride, just none of the other ones
    • DN: Yes.
    • DJ: Seems to cover next to AI’s as well.
  • AI(MM) Will look for matrix requirements in MSL.
  • AI(GR) Will look at similar in HLSL/DXIL
  • AI(Apple) Will look into validating grammar on CI.
    • In progress
  • AI(DS): Move stride decoration into type_decl
    • DONE
  • AI(DS): Remove NumWorkgroups from grammar, update bug to handle post MVP.
    • DONE
  • AI(JG): Will update builtin PR to fixup merge conflicts.
    • In progress

Use brackets for array types (#854)

  • MM: A simple change, doesn’t change semantics or meanings, just a different way of spelling the types. Two benefits to using [], 1- familiarity to existing shading languages. Every popular shading language uses []. 2- Brevity. The word array<> is long, [] is short. Proposing changing array<f2,2> to f32[2]
  • JG: Can we make it syntax sugaring
  • MM: You mean have both
  • JG: Yes.
  • RM: Seems reasonable.
  • JG: Looking towards generics, always disappointed when interacting with c++ arrays. Being able to work with a templated type is better. Having array as a templated type, even if only template that users can’t make templates …
  • MM: Two responses. 1- believe this does not cause us to have the same pain as c++. Intentionally not asking to rename ptr to *. Only array. Much of c++ problem is the * on the right and [] on right.
  • JG: Not just that, also declaring an argument that is a reference to an array is clunky. Dealing with unsized arrays isn’t really a thing.
  • MM:Both of these proposals wouldn't change semantics. Still value types, unsized arrays work same way
  • JG: Thinking forward, switching to [] is easier today but puts us on a local maxim not global maxima.
  • MM: Would be comfortable with both
  • DS: WHy doesn’t MSL use [] for arrays of textures?
  • MM: It is related to uniform access. Can’t remember exactly.
  • DS: Will we be required to do it both ways?
  • MM: Making them syntactic sugar makes the most sense. In the future possible to make <> more expressive. For now sugar would be fine.
  • DN: Concern starts with attributes on the array type but the arrayness is after the base type. Putting the attribute to the left is ambiguous, so want array []’s before and so the attributes are obviously attached to the array. [] to the left avoids ambiguity and have pure left to right parsing. Similar to go. If we have it as sugar then not as concerned then no-ambiguity.
  • MM: Two repsponses. Main is familiarity so would lose that. Second, could put more stuff inside the []’s. Then not ambiguous. Instead of ….
  • DN: Like that less then on left, but less concerned if sugar.
  • JG: Would be nice to have desugar escape hatch. Then can talk about it in terms of arrays. If saying, I have a list of int’s then easy to do and familiar to everyone.
  • DN: Still have to make rule about attributes on left what they apply too. I think they apply to the element?
  • MM: Can you write an example we can talk about?
  • JG: Maybe a strided array of vec4 but if the attribute was associated to the element not array then saying the vec4 has a stride
  • MM: Don’t have any opinions about this. There is a related question about nested arrays and if you can put a stride on the inner of a nested array. Less important the the general goal of naming as used too.
  • JG: Would weakly prefer only one way to do things. If the readability is super important in some cases, as long as we have this other more complex and explicit escape hatch.
  • DN: Need a proposal on how the attributes apply to the array.
  • MM: Sure, can we, for the sake of argument, at least propose saying that one way of solving is if you want to use the sugar, there are no attributes. The sugar is less expressive than the existing.
  • DN: That’s fine, but makes it less regular. Both examples above would be invalid because you can’t have the attribute to the left of the type
  • MM: Yes.
  • DM: One thing that isn’t clear, is the stride part of the type? Can you assign an array with a stride to an array without the stride
  • DN: Let’s treat that separately, came up in Matrix discussion. I’d say yes, stridness is only a storage property. Would be a type checking rule to allow the copy in.
  • DM: I think it does affect it. It’s contagious if it requires the stride matches. If so, there are much less usefulness of shorthand if the stride requires to be matched
  • MM: I’m happy with what David said. Distinct types but can assign one to the other and does a gather/scatter. Invisible if the receiving type isn’t in memory.
  • TR: I imagine you’d be strict with pointer but not necessarily value types
  • DN: Yes.
  • MM: One relevant thing, in metal the strided arrays are going to be arrays of structs with extra padding members. So, would be distinct types.
  • DM: Ok, so if we proceed with David's procedure then we should re-visit having stride attributes on type and just put it on the field of the host shareable structure. Everywhere else it doesn’t matter.
  • MM: That sounds good.
  • DN: You’d have to make sure all the pointer address calculations retain the stride information so you can skip the right number of bytes when moving over elements. So, get a ptr to the struct member and then say index by 5 elements still need to know that pointer strides. Could say only affects the pointer types instead of the types themselves. May end up with a bunch of validation elsewhere. The lump is in the carpet somewhere.
  • DM: Ok.
  • TR: Does seem to be a property of pointers and layout of struct members. Less a property of value types. Somewhat arbitrary decision.
  • DJ: At this point, i think we should wait for the proposal and come back to it.
  • MM: Didn’t hear the group speaking with one voice on direction. Maybe write two proposals and pick one.
  • JG: I like proposals.
  • DN: What are the 2 proposals. 1- array with no attributes before the type 2- is …
  • MM: Myles finds place to stick the attributes.
  • DJ: Sounds good.

Vertex and Instance ID and base ID builtins. (#901)

  • JG: This is a nightmare ….
  • DJ: Hard to discuss without Corentin
  • JG: At core, underlying apis have different behaviours so can’t use their builtins. We have to decide what we’re doing. Need to decide both what we’re doing and what that means for running on different backends. The core is that on some of the backends, like D3D12 Vertex and Instance ID start from 0 regardless of the draw offset. It’s the 0th you’re drawing. On other platforms, saying start at vertex 1000 the base vertex id is 1000. Can’t run on both d3d and metal without that extra data in the vertex shader for a draw call. Dzmitry Mentioned using specialization constants but that takes up space.
  • TR: Desired model, starting from 0 or …
  • JG: Proposal is we’re limited by d3d 12 and should name things reasonably and just pick one.
  • MM: Would be willing to emulate whatever because it’s cheap. Emulation requires passing 1-2 extra shaders which isn’t a big deal in MSL. Then a preamble on the shader would be a multiply. Should be cheap enough to be fine.
  • DM: We can either work around d3d12 or work around MSL and Vulkan. Would rather only work around in D3D12 and provide non-zero instance and vertex id. Seen cases where people use as a cheap push constant so you can use that constant in the buffer
  • JG: Use the base instance without data?
  • DM: Yea.
  • TR: Requires another constant to provide that value on D3D
  • JG: Right, we’d provide the constant and they’d think they’re clever on D3D when not
  • MM: may need that constant for other reasons
  • JG: Like for validation?
  • MM: Don’t remember D3D, in MSL have to pass extra data anyway so have to provide the data anyway
  • JG: Should try to adopt the Metal/Vulkan model. They look the same to me but haven’t looked in detail. See if we don’t run into issues polyfilling elsewhere. Only reason for a different choice is if emulation is slow on D3D12 but fast to emulate D3D12 on metal or vulkan. For moving forward, we can do it efficiently on D3D12.
  • TR: Requires extra constant buffers …
  • JG: Are they a limited resource, like in low end configurations?
  • TR: I think we have a maximum number but can’t remember limit
  • JG: 4 would be a problem
  • TR: 16 at a minimum but can’t remember cap bits.
  • JG: Myles may be right and everywhere we have to shove data and becomes part of preamble and is equally slow everywhere.
  • TR: Right
  • DM: Thinking allocate 2 root contents
  • MM: If the signature is big enough
  • TR: Right
  • JG: Should we try that? The fullest solution maybe to do an investigation to see what it looks like
  • MM: We did that with WHLSL we made it match HLSL and the emulation was cheap on metal which doesn’t deal with root signatures and constants. Don’t know if it’s harder on D3D.
  • JG: Gut saying we should do the metal/vulkan way and if we run into issues, we hopefully run into them before signing off on MVP and can’t do backwards compatibility changes. I think we should make a jump and see if anything changes during prototyping.
  • TR: As much as saying do D3D way other decisions to make it align with vulkan is good to be consistent.

Constant propagation (#905)

  • RM: As far as I can tell, the question is about constexpr and how we can do compilations at compile time and use the results for array bounds and things. Metal got this for free as it’s c++ so it uses the c++ machinery. Don’t think we can do anything nearly that easy in WGSL. Considering the amount of work in constexpr and the time it took to make good I believe it might be useful someday but seems high risk and high effort for MVP. Recommend delaying and see if we can make due without for now.
  • DM: Sounds fine to me. For some context, was brought up when contributor was building GLSL frontend. Wanted to think if we shoudl lift that logic to WGSL. Since doing that makes it more complexity let’s not do it. Complexity lives in GLSL frontend.
  • DJ: I will close this.

Add stride array decoration. (#910)

  • DS: Moved to type in PR. Do we still want there?
    DN: Yes, but with special assignability rules to come later.
  • DS: Any objections to landing stride PR?
    DM: Still not clear if worth it vs annotation the field. David brought up a good concern and we should determine if it’s easy to address. If you have a ptr and take the address of struct array field. The ptr knows what stride it needs. So, could be addressable without putting stride in all array declarations.
  • MM: Can youtube a pointer to something in WGSL?
  • DN: We do, write the name of the variable and use the …. Syntax. The primitive you have is a pointer and what you do with it is a load or store.
  • MM: Right.
  • DN: All that is subtle and isn’t spelled out. It’s an implied thing, not something you write directly. THere is no & but it’s what you’re doing at a primitive level.
  • MM: With this PR the stride is part of the type. When you write the code the left side has to have the stride. So this PR solves the problem.
  • JG: Seems to make the most sense it’s a property of the type and you inherit from the type. Won’t have virtual pointers to things with different strides. Might have that solved otherwise without re-assignable pointers. If we have re-assignable pointers then not sure how implementable on the field is. Would have to load into an intermediary.
  • MM: A func with arguments which are pointers to arrays and pass in arrays with different strides then have to specialize the function. Seems like something the group is against.
  • DN: Not allowed in vulkan. Can’t take a pointer to the middle of a thing inside a storage buffer and pass into a function. Need extra functionality to make that work.
  • JG: That’s the most constrained thing and attaching to the type gives us that.
  • TR: Don’t understand how it would look as an annotation on member for multi-dimensional arrays if not on type. Can see how it works on type, it’s verbose, but don’t see how it works on member. Would prefer on member.
  • DM: Good point. Maybe we should proceed with PR.
  • JG: If we have more progress, could constrain even more. Can still talk about it.
  • MM: [[stride=42]] array&lt;[[stride=4]] array&lt;f32>>. What this PR would entail. Can use typedef if you want nicer.
  • JG: Take PR as is or other changes?
  • DM: Weird it’s part of the type but for assigning implicit conversions?
  • JG: Not sure if we do
  • DN: Loading from strided array becomes a non-strided array type
  • MM: Loading an element ro the array
  • DN: Loading an array of 4 elements you get a value which is an array of 4 elements without stride.
  • MM: Assigning array to another arry the two strides don’t have to match because the = operator does the load/store magic which hides this complexity.
  • JG: Isn’t this a 3rd templated parameter?
  • TR: See it as not part of the basic canonical type. But decoration on the type so the canonical type matches but for sake and load and store which has a variable which has this decoration which tells you how to do that and pointers have to inherit some kind of real information. Maybe pointers have a templated stride but not the array value?
  • DN: And you have the same thing with struct offset. If you have layout information or not it’s the same buffer.
  • MM: So, what's the next step?
  • DN: Accept this and will write text on how it works. I’ll assume we have this assignabilty rule we’ve proposed.
  • JG: We’ll capture that in this PR?
    DN: No, new.
  • JG: Right so take this PR. Do we have an issue?
  • DN: I’ll file one, or there is an existing pointer issue.
  • MM: There is a describe how pointers work task. Unsure why talking about pointers as they don’t have strides.

Next Meeting

(DS won’t be here)

Validation rules for WGSL modules: binding collisions (#889)

Add popcount and reverse_bits integer built-in functions (#947)

Explicit layout needs more than Offset: ArrayStride and matrix attributes (#773)

Allow struct_decl to have a name. (#952)

Interface matching rules (#644)

Extern declarations (#883)

Action Items

AI(Apple) Will look into validating grammar on CI.

AI(JG): Will update builtin PR to fixup merge conflicts.

AI(MM): Make a proposal (or two) for #854

AI(DN): Find or file an issue related to pointers on #910

Clone this wiki locally