-
Notifications
You must be signed in to change notification settings - Fork 353
Remove the requirement to have entry points #1340
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
Conversation
|
What can you do with a shader with no entry point? |
|
You can validate it :) |
|
I've spent the last 2 days converting glsl shaders to wgsl, and this validation has caught a whole bunch of cases where I forgot to annotate main with an entry point. I think it has value. Why not just add a flag to the compiler to say dont-warn-if-no-entry-point, if validation of the rest of the code is what you want? In terms of passing a WGSL shader to WebGPU, I really don't see a good reason why you'd not want the compiler to scream? |
I disagree. This has very little to do with a validation error in question. You may equally likely to forget to annotate another entry point in a module (with otherwise at least one annotated entry point), and nothing will guard you against that. I'd argue that this missing annotation is not a problem at WGSL level. It's still a valid WGSL module if your entry point functions are not exposed as entry points. It's a shader interface problem, so it has to be validated wrt the pipeline (a shader is used in). |
|
I'm also not even sure if all backend compilers support compiling a shader without an entry point. |
|
@ben-clayton nobody is producing HLSL or MSL at |
|
Okay, so the picked entry point is late determined, but still there has to a an entry point for the shader compile to ever succeed, so I still think catching the case of no-entrypoints early in the pipeline still makes sense. If we supported shader linking of multiple modules, then I'd certainly agree this would be undesirable, but as far as I'm aware, we don't. |
|
@ben-clayton the general terminology we've been trying to use is:
|
|
I'm with Ben here, I'd prefer if we kept the validation. While the shader maybe invalid if you provided the wrong entry point, it's definitely invalid if you don't provide an entry point. So, determining here that the shader just cannot work seems like the right thing to do to me. We can validate later that the content of the shader is expected. If we decide to have linkable shaders in the end, we can relax the rule without causing breaking backwards compatibility. |
|
@dj2 entry points are a part of the shader interface, and should be validated as such. There is no need to try validating that ahead of time, it helps nobody at all. |
|
But you can't do anything with the shader, so what's the point? |
|
Would you want the following code be failing at runtime based on the user input? struct ShaderOptions {
blits: bool,
copies: bool,
};
...
self.shader_options = ShaderOptions::from_user_input();
let code = compose_shader(&self.shader_options); // builds shader code based on what needs to be included
let shader = device.createShaderModule(code); // <----- important bit
let blit_pipeline = if self.shader_options.blits {
Some(device.createComputePipeline(shader, "cs_blit"))
} else { None };
let copy_pipeline = if self.shader_options.copies {
Some(device.createComputePipeline(shader, "cs_copy"))
} else { None };Allowing modules with no entry points makes us more generic from the developer point of view. It also doesn't cost us anything - in fact, it has negative cost! |
|
Another example: imagine we have documentation about the shader code, perhaps even the very spec we are writing. Imagine that every piece of code there has a little "Play" button that copies it into another tab with some sort of a shader playground (like Rust docs do), where you can see how it gets transformed into native APIs, analyze the control flow uniformity, etc. Your pieces of code may be as short as: var<private> x: i32;And of course the playground would do the shader validation as the first step. So would we be forced to inject a dummy entry point in each of the snippets? Again, extra work that doesn't do any benefit. Both of my points essentially converge to the fact that supporting no-entry-points is more tool-friendly (and it doesn't cost us anything). |
|
#1340 (comment) - If you're forced to deal with a no-entry-point error at Your argument about tooling is more compelling to me, but I think your tooling example extends beyond entry points. If we want to support compiling WGSL without a full shader program for tooling purposes, then I think no-entry-points is just one of many things you'd have to solve. FYI: Shader playground now supports WGSL. This was based on a PR from a few months ago, so the language has changed quite a bit in the meantime. I'll try and get it updated again once some of the larger language changes have landed. |
I'm not sure I understand the example, that shader would have to have 2 entry points, so it would validate fine? It would fail at pipeline creation time if those entry points don't exist. |
If |
|
I just got stabbed in the back - SPIR-V doesn't like this either:
Et tu, Brute? |
|
Ah, I see. That makes sense to me as a good reason to drop the validation at that point. |
|
Right, you won't be able to generate the SPIR-V until the pipeline creation. |
|
Or you could just enable the linkage capability and do a no-op "link" step later which just strips it? |
|
I suspect the SPIR-V rule may originate from the fact that both GLSL and HLSL producers of SPIR-V had the entry point guaranteed (i.e. it's explicitly specified for HLSL, and it's implicit for GLSL), and it was expected to only have one entry point. I don't think it's needed in SPIR-V either, but it's fairly easy to work around in the backend for us. |
|
Given that SPIR-V requires the entry point in shader module, I think we should keep this validation in place. The example posted can still be done, just conditionally create the shader module instead of unconditionally. |
|
@dj2 going back to this main concern you had:
We don't want to intercept it because we don't know what the user intention is. There actually was a very similar discussion in WebGPU on zero-sized buffers - #546. It was not without controversy, but the resolution is there: we want to allow them even if the user doesn't do anything useful with them. So there is a precedent here. Reason is the same as I stated - some user code may be structured in a way that may have or have not some stuff inside the shader module, and there is no need to make it a special case where nothing ends up in the shader module. In terms of our target and input languages, the situation isn't clear, so we are free to take any direction:
|
|
For the SPIR-V output, injecting a fake entry point seems ... wrong? We're faking things to make a module which is invalid anyway. If we don't create a shader module, what does that mean? It fails to create, but then were does the error happen? In pipeline create, but how do we know why the shader module failed to create, we would have lost the error by this point. It still feels like requiring an entry point is the right way to go. Your code example above can be refactored to only create the shader module under the same conditions as you create the pipeline, so we aren't removing the ability to do what you want to do. |
I don't think that weird workaround is needed. I think instead WGSL shaders could be defined to translate to SPIR-V-with-Linkage (even though we don't have a way to do linking on the API side (yet)). Is this reasonable? |
I didn't say we are removing any ability. I pointed to an example where the validation error is sneaking up on the unaware user. If it's an implementation detail that SPIR-V doesn't like it, we shouldn't force it on users. The workarounds are fairly simple. In return we get a slightly simpler spec, one less test, and better composability of the API. Consider another case. The user has entry points, but all of them are invalid to use because they use WGSL features that are not enabled on the device. Say, f64 computations. So technically, at shader module creation you know they aren't going to be able to create any pipelines with it. Do you really want this to be an error at Keep in mind that in this case you can't generate a valid SPIR-V, since it requires at least one entry point, and you can't include the entry points that would make SPIR-V invalid on this device. So you'd basically have to do exactly the same kind of workarounds anyway: either add a dummy entry point, or not attempt to pass the SPIR-V to the device until the pipeline creation. You have to have this already. |
|
If you know you can't generate valid backend code, then yes, it should be a validation error, at least in my opinion. |
But you can't specify this at WGSL level! Because WGSL doesn't know which features are enabled on the device. Because the entry points are a part of the shader interface, they aren't self-contained in the shader module, and therefore their presence shouldn't be validated at So the rule under question here is useless: it doesn't prevent a shader module that has entry points, but which happen to be gated by the device features. If you want to produce an error in this case, anyway, we'd need to talk about a validation rule in the host WebGPU API, not in WGSL. So the rule in WGSL can be removed either way. ... And if you don't want this rule in the host API, then the implementations would need to implement the workarounds (suggested here) anyway, so there is no cost in removing the rule from WGSL. |
|
Sure, the generated SPIR-V may not work with your device capabilities and that should be validated at the pipeline creation time. The SPIR-V is still valid, it just isn't compatible with that pipeline combination. If the SPIR-V has no entry point it just isn't valid. The rule isn't useless. The SPIR-V without entry points is invalid. SPIR-V with entry points is valid, it just may conflict with the pipeline creation. |
|
That's true. However, for us, SPIR-V being valid by itself doesn't mean anything. SPIR-V is an internal representation of a shader in the Vulkan backend. There is nothing requiring the SPIR-V to be valid before it's passed to the Do you intent to call the SPIR-V validator on produced SPIR-V in Dawn, even if you are not going to pass it to |
|
Except, WGSL is being spec'd in terms of SPIR-V. So, generating invalid SPIR-V, to me, means you've got invalid WGSL. |
|
@dj2 the specification is not an algorithm of converting WGSL to SPIR-V. It can define operations in terms of opcodes, since it helps clarity, but it doesn't spell out all the details of the conversion process. An entry point in WGSL is still an entry point in SPIR-V, there is no problem here. There are always implementation details on how exactly a SPIR-V is generated. And same applies to HLSL and MSL. |
|
A WGSL program without an entry point is useless. |
Have I completely misunderstood #1064 then? The point is to allow doing more work up front, if the technology permits, and given more (browser) development investment. |
It is a P0 for us to be able to generate MSL at |
|
I don't understand why this is hard. If a WGSL program doesn't have any entry points, when a compiler wants to compile it to SPIR-V, just ... don't generate any SPIR-V. |
|
Related: #1404 |
My comment was about the actual state of things today. We aren't generating MSL or HLSL at this moment, Google doesn't, and there are no immediate plans to do so. The discussion in #1064 didn't come to a consensus on how to get there. Besides, this isn't a problem for MSL - it's totally fine to build a library with no entry points. |
We have immediate plans to do so 😎 |
|
Not sure what you mean, we generate both MSL and HLSL in Tint. It is not enabled by default in Chrome yet, but we're working on enabling it in the near future. |
|
I think Dzmitry meant "inside createShaderModule" |
WGSL meeting minutes 2021-02-02
|
WGSL meeting minutes 2021-02-16
|
|
Discussed on WGSL 29-03-2021 meeting, agreed to proceed. |
WGSL meeting minutes 2021-03-29
|
See #1333 for some context. I don't think either tools or users gain anything from this validation rule. It doesn't need to be there.