Skip to content

WGSL 2020 07 07

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


Mehmet Oguz Derin

:𐰆𐰍𐰔 :

⌨️ Scribe
Google Meet




WGSL Issues


Open Issues
Marked Issues


Meeting Issues

Tentative Agenda

  • Action item review:
    • Microsoft on #644
    • David on #774?
    • David on #572
  • Add select builtin function (#907)
  • Task: Define short circuiting for && and || (#675)
  • Describe module constants, including pipeline-overrideable (#886)
  • entry_point_decl should be an annotation on the function (#662)
  • WGSL should require storage buffers to be a host-shareable storable type. (#877)
  • shaders: semantics of "discard" (#361)
  • Interface matching rules (#644)
  • Packed vector types (#780)
  • C-like declaration order (#677)
  • Explicit layout needs more than Offset: ArrayStride and matrix attributes (#773)
  • No explicit grammar for decorations (#689)
  • Use brackets for array types (#854)
  • Forbid --x (#801)
  • Support #line directive (#606)
  • wgsl: fix and elaborate scoping rules (#890)

📋 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

Action item review

  • Microsoft on #644
  • David on #774?
  • David on #572
    • DN: PR out for review #886 in the agenda

Add select builtin function (#907)

  • DJ: All approved. Done.

Task: Define short circuiting for && and || (#675)

  • MM: Gets trick if doing && of two vectors but vectors are constructors or constructors take arguments which are function calls.
  • DN: Point is if they short circuit or not. Doesn’t make sense in the vector case as what values do you check against false. In scalar it’s obvious, but vector is not. HLSL doesn’t short circuit in vector case, not sure about scalar. All over the map in various languages.
  • MM: Two possible directions. A) && does short-circuit for scalar but not for vector. B) && only works for scalars. Compile error if used on vectors. If you want && on vectors then use & and that never short circuits.
  • DN: I like that. So, & as a binary op in C does not operate on booleans but we should make it work on booleans exactly as you said
  • KN: Fair amount of precedent here where languages have & operate on booleans unlike C.
  • JG: Like c++
  • DN: So && and || are scalar only.
  • MM: Intuitively I’d expect && to work for vectors. In one world would have same for && on scalars and vectors and the other … (missed). We don’t have a position but there are arguments on both sides. Not a straightforward situation.
  • DN: Preference is to not have different short circuiting behaviours for the same token as you write it.
  • JG: LIke having && be the logical we’re used too. If we want an operator for non-logical we should use &. That’s the best match. Even matches how and or or works in a bitwise functionality. Using it on vec4<bool> or vec4<int> all makes sense. That’s exactly what GLSL does.
  • RM: I agree too.

Describe module constants, including pipeline-overrideable (#886)

  • DN: Tried to codify what we discussed last time. Choices around if a default value should be specified and I went that direction. One thing to note is that the grammar doesn’t allow a constant as the size of an array doesn’t have all the functionality of SPIR-V, but does match better with Metal. Shouldn't affect the interface.
  • MM: Why did you make the = const_expr required?
    DN: Attribute on a const definitions and a const definition always has an initializer expression.
  • MM: How about having module constants without a default value. It’s a compile error if the JS author doesn’t specify a value.
  • DN: Didn't see that as an advantage. It’s one of two styles, up for debate.
  • DM: I like compile errors. Seems like a good idea.
  • DN: When I look at a module with the spec constants in it I’m looking at, in principle, an example which should work out of the box. I can read the code and see what it should be doing. Essentially an example so you can simulate it in your head. Without the defaults there is more guess work. Kind of an exemplar. Metal went the opposite way.
  • MM: Argument you mean is to allow defaults, not necessarily to require defaults. Might want the other way if the shader author doesn’t actually know a good value. So, they put in 0 and you get a broken shader. You want the contract of if you use this shader you must provide this value.
  • DN:I could go either way. Up to the committee.

entry_point_decl should be an annotation on the function (#662)

  • MM: Comment from Dzmitry so you’d prefer the authors write single line wrapper functions?
  • DM: Yes.
  • MM: Put in list syntax as I thought group would prefer it.
  • DJ: Next step is to turn this into a PR
  • MM: If the group thinks this is worth pursuing
  • JG: FOr those of us who have prototyped language implementations we don’t expect any overhead from these split out overheads. To me, hte option to me for having a entry point wrapper that calls into the function we want is nicer then the other thing to me. That’s my preference from a style standpoint. We don’t have any concerns about performance or compat or cannonicalization do we? We could cannonicalizle if we wanted too?
    DN: That sounds right?
  • MM: Your canonicalization was smart enough it could figure out it’s calling an entry point
  • KN: This proposal with multiple stubs is 99% equivalent to having separate entry point calls for each function definition. I prefer that style which is a personal opinion
  • JG: That’s fair. One nice thing is you get checking we don’t have duplicate entry points so they’re first class functions not annotations on functions. So the indirection glue layter of attributes is thinner
  • MM: Another difference is most shaders aren’t going to have different attributes pointing to one entry point. This is a corner case so having the corner case match what you describe is fine, in the common case the annotations are next to the entry point.
  • DM: I see it that entry points are part of the interface like location and binding information. Interface is mostly described in annotations.
  • JG: Seems reasonable. Sounds like we have enough consensus to have a PR
  • MM: Ok, and will make it not a big list in square brackets.
  • KN: The examples say compute boids with arguments but there are no arguments there?
  • JG: So there is no arguments to pass around, so you can inline that function in the emitted code.

WGSL should require storage buffers to be a host-shareable storable type. (#877)

  • DS: I blame David for making me do this :)
  • DN: There was a PR for host-sharable types. That is the first step for transferring data.
  • DN: This is a placeholder for text that needs to be written.
  • DN: Scalars, vectors, matrices, arrays of those things. Excludes bools and textures and samplers.
  • DM: Can we put samplers into our structs and pass them around?
  • DN: No
  • MM: We said we’d forbid it now, but look at it later. There is a performance hit.
  • DM: I’m wondering about the arguments to a function. Metal allows you to pass the samplers around as arguments.
  • JG: Requires non-pure functions.
  • MM: I thought this requirement came from SPIR-V. When you sample you have to name the sampler, so it makes it impossible to make a function that operates on any sampler.
  • DN: Yes, requirement comes from Vulkan. [explanation missed]
  • DN: In general, don’t treat an opaque thing as if it is a regular value.
  • JG: Sounds like we are in “Needs Investigation”

shaders: semantics of "discard" (#361)

  • MM: The three different backend languages have different definitions of discard. Discard is different then an early return because the blending step after the fragment shader doesn’t execute if you hit a discard statement. Early return would still blend after the fragment shader. We need this but they mean different things on the backend language.
  • JG: Mostly HLSL vs everyone else.
  • MM: Our thought, HLSL keeps these invocations alive as they might participate in derivatives but they don’t have side effects, writes to buffers don’t happen. In other APIs if you use derivatives after the discard it’s undefined behaviour
  • JG: The D3D behaviour is a complete implementation of the SPIR-V version. Undefined means maybe it works. Can center on figuring out how to do the thing everyone implements.
  • MM: Our initial thought is the uniformity rules should reject programs where derivatives aren’t used in uniform control flow which would restrict programs where one part of a quad is discarded.
  • JG: So treat kill as a uniformity hasserd?
  • MM: Kill is like super return.
  • DM: So that matches what David proposed?
    DN: This is a subtle thing that Myles described accurately. There is a SPIR-V extension to act like HLSL, but if it’s a uniformity thing then it doesn’t matter. Having it as super return is implementable as you can write code to make that happen.
  • KN: Seems clear there is only one direction to go. Should there be some way in the language that a function should discard? You would want to know if a function can cause a discard. The function causes everything to become non-uniform.
  • JG: Could be an annotation. uniform-flow function or something.
  • RM: The analysis would already be tracking that, but explicit detection for the programmer to assert that’s the case would be reasonable.
  • JG: The const of uniform
  • MM: It’s like throws. If anything you call throws then you have to declare as throws.
  • JG: MOre like const or no-except. Asserting the function doesn't do a thing.
  • KN: Could do it either way, but no-except is the closest analogy.
  • MM: So rather than saying this thing might discard, authors say this other thing will not discard.
  • DN: Would prefer the first, as that’s the less common case.
  • JG: Well, then you have to annotate?
  • DN: Why are we introducing this thing we have to analyze anyway?
    KN: Depends if you’re going to do the analysis anyway. If you’re going to discard must add a ‘may-discard’ then it’s local to the function. Or you say we’re going to do the analysis anyway but you have the annotation for explicit case that the function should not except
  • RM: Analysis can’t be local to function and must walk up the call graph. Must track how uniformity of result relates to the uniformity of the arguments. Tracks discard more closely as we can know we discard if arguments 1 and 3 are uniform. Fine adding annotation for the programmer to assert something is true but the analysis would be more fine grained.
  • KN: Then not necessary to add the annotation.
  • JG: Would like to see it as an optional opt-in but not how we do analysis.
  • KN: Not super important to have it now.
  • MM: So no additional keyword.
  • JG: That’s right.
  • DS: So this is same as the “kill” keyword?
  • JG: I like “discard” better.
  • DS: I picked “kill” from SPIR-V. Fine with renaming.

Interface matching rules (#644)

  • MM: To Microsoft, do you need anything for this or will this come eventually?
    GR: No more info from then the face to face. May have more detail the interface matching rules will push things to the end. Nothing is likely to change, there is possibly some cleverness that could be done on the backend. Not sure much could mitigate the issue. Are we sure the division of labour is not the same in other implementations, not sure why it’s a D3D specific issue.
  • DN: Can't remember what we want more info on.
  • GR: There was concern with regards to amount of work at module vs shader creation time.
  • MM: Right, when you say you don’t expect anything to change, you mean you expect that pipeline creation will always do the lion share of work?
    GR: Not sure how I’d characterize the proportions, but that it would be more I don't see that changing. I think some folks wanted a different answer but I don't think it will change.
    JG: It’s the harsh reality.
  • MM: Allows us to be a bit more flexible on D3D.
  • DJ: Also unblocks us from going to spec text. Reading minutes, waiting for Microsoft to come up with a description before going ahead.
  • GR: To be clear, we haven’t done that, and are willing to provide, but I don't think it will change the final result. If it’s relevant to the amount of work in each stage, that is something we could focus on. Given the circumstances I don’t promise a return date on this but it’s something we could provide.
  • MM: Maybe we should go forward with the agreement from DM with 3 bullet points. Then if Microsoft comes up with new evidence we can change.
  • GR: Can you point me to that.
  • MM: Yes issue #644 comment …. (link)
  • GR: There was some discussion with regards to which outputs you couldn’t use in terms of ordering.
  • MM: I think the question was if the vertex shader emits 3 output variables and the fragment only wants to read the 2nd two does the fragment shader still have to list the first one.
  • GR: The way I read this is it doesn’t say anything about that so it doesn’t is the current plan?
    MM: Yes current plan is it doesn’t have to which means D3D backend has to do most work in pipeline creation not shader creation. Sunk cost.
  • GR: That’s going to increase the cost of course. One thing I remember is that there didn’t seem like there was much traction in making the restriction the same as D3d such that you would have to list the first one.
  • MM: I didn't know that was a proposal, should we discuss that?
  • GR: Mentioned it, but this is something that would mitigate it, then it works as it works.
  • MM: To determine if we want the restriction would need to know how much it buys us in the HLSL path, if it’s like 1% probably not worth it.
  • GR: Thinking of potential options. I can commit to adding a comment saying the timeframe in which we can answer that question. If the timeframe is unacceptable then I agree we go ahead with the previous proposal and we’ll deal with it.
  • MM: Sounds good to me.
  • DN: We’d talked about location ideas, Myles you said you wanted them sparse. That may be an issue for us. The number of locations is small like 16 to 64. Thinking how to re-map across, I may have to do a bunch of work at pipeline creation to re-number, which happens at pipeline creation. If I remember correctly I may want to put a finger on this to solve later.
  • MM: Can fix with spec constants?
    DN: No as locations are not spec constants.
  • DM: Would like to hear more about work at pipeline creation
  • DN: If I have a vertex shader with outputs a 4,5,6 and a fragment shader with 300,400,500 then I have to re-write parts of the shader before I create the shader so it fits into Vulkan on how it express. Now I’m tweaking the shader at pipeline creation instead of something at shader creation time.
  • MM: At a previous conversation someone mentioned vulkan was sparse?
    DN: This might have been a mistake.
  • DM: What’s the ideal scenario? Having SPIR-V module created at module creation?
    DN: Ideally had spir-v to driver at shader module creation time. Driver can do stuff. At pipeline creation time may have a small number of patches for things like spec constants and hopefully that’s well contained. The driver shader compiler could do more work up front which is what I want to hit.
  • MM: same with us
  • DM: So waiting for more details from DN and Microsoft
  • MM: Difference between having array sparse and limit of 64 and having it not be sparse.
  • DN: Right. I’ll put a comment on the vulkan limitations and think through when i Need to touch the SPIR-V in the ideal case.

Packed vector types (#780)

  • Not ready to discuss

C-like declaration order (#677)

  • Not enough time to discuss

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

Shift Operators (#827, #828)

  • GN: Consensus was forming around if you require cast. Using the lowest bits for the type in question and ignoring others whether it’s over large or negative. Haven’t officially decided to take this up, should we?
  • DJ: Two issues, one on too large and one on negative shifts.
  • GR: So JK had an issue with the cast, if you have a signed you have to cast to unsigned. His point being if you take the lower bits it just works. I think getting an error that the sign is going to be ignored is better for the developer. Then they can decide if they need to cast or fix the value that should be in there.
  • MM: This 827 or 828
  • GR: They’re both related
  • KN: This is 827
  • GR: The only way what I said is true is if we take the solution of only using the lower bits for 828 which is why they’re related. (Or least significant instead of lower)
  • MM: Played with shader toy on negative shifts and behaviour appears to be undefined. Also played with c++ and it did the same thing
  • GR: A real no-persons lands
  • MM: If we’re discussing negative shifts, I’d go with no
  • GR: So then if you use a signed value as the right hand side of the sift
  • MM: Should be a type error.
  • GR: Agree with that, but there is conflict
  • JG: If we’re going to ignore the bits anyway, the type system is only giving us half the info.
  • GR: Not sure what you mean
  • JG: If you try to shift by -1 what’s the difference between that and shifting by UINT_MAX?
    GR: In terms of the outcome? Nothing. In terms of what gets done by the shader nothing. But if you’re passing something in and saying I know this is -1 and i want a negative shift and you get an error saying you should use the case you know there is dragons
  • DM: It’s ambiguous if it’s reverse shift or something else
  • JG: Should be at least a warning but I’d prefer an error.
  • DN: Let's go with error.
  • KN: We can always take a error out later
  • MM: How are warnings even exposed to JS
    JG: Through the mechanisms given, same way error text is surfaced, but not an error an info. Basically could construct a polyfill linter that errors on warning.
  • MM: Can we resolve?
    JG: Let's make it an error.
  • GR: So passing unsigned as RHS is an error. And do we agree for 828 that we should only use the least significant bits?
  • DN: Seems fine to me
  • RN: …
  • DN: Implies to mask as you pass down.
Clone this wiki locally