Conversation
|
I believe that the SPIR-V backend to dxc has had to solve a similar problem: Was the approach here considered? |
|
@damyanp the approach you linked to requires changing the source (by adding the "[[vk::binding(X[, Y])]]" attributes), which is something we are trying to avoid in order to preserve compatibility with existing code bases. @litherum thank you for writing this up!
I think some of the backends (Dx12, Metal-without-argument-buffers) would still require us to defer the shader creation to the pipeline creation time, since this is where the layout is known. But having the API shaped in a way that at least allows an implementation to do this work ahead of time is good.
If the "space" qualifier is already provided, wouldn't we want to just use it directly? In what case would an extra mapping be needed? My understanding was that we only want to do this to support shaders that were written for DX11 resource model to begin with. Did you consider just mapping "u2", "t0", etc as a key instead of the whole "register(x, y)"? |
|
@kvark - dxc has several strategies, one of which involves changing the source code. There's also a bunch of command line parameters that can be passed to dxc to control the policy of how the registers are remapped. My thinking is that anyone who already has shaders that they're compiling with dxc but using with vulkan will have figured out what parameters they need to pass to dxc in order to configure a set of registers that work with that style of binding model. Can you help me understand why DX12 would need to understand the layout in order to compile the shader? In DX12 the shader can be compiled to bytecode without knowing the layout. When the bytecode is passed to the driver while creating the pipeline state object the layout is required. Or am I missing something? |
|
Offhand, I think you (@damyanp) are right that this mapping could be at pipeline creation instead of shader module creation. (In the world, of course, where WHLSL is what's used to create a shader module.) |
|
@damyanp command line options is not a choice we could consider here, since no command line is involved. And the fact that the users already know the mapping they need is one of the reasons we went with Vulkan-like binding model to begin with. This PR is making a concrete proposal on how the users would communicate this information (that they already know) to us.
Problem originates from the limitation of DX12 that samplers and non-samplers can live in the same descriptor heap. Before calling SPIRV-Cross we (in gfx-rs) are setting up the resource overrides accordingly, and this is where the pipeline layout is needed. That is to say, it's been a while since I looked in depth at that logic piece, so we might find a way to improve that. |
|
They could be arguments in a dictionary instead of actual command line args. But the actual semantics of those command line arguments (assuming you're talking about |
|
I would argue that requiring developers to manually list out a mapping for all shader registers is also very compat focused. The whole point of this overrides API is to provide a way to adapt a shader written for one binding model to work with a different binding model. We would also expect that any shader specifically written for WebGPU would not need this modification applied. My expectation here is that the implementation for this would effectively modify the source code that's passed to the WHLSL compiler, and could easily be implemented outside of WebGPU. Given this, I'm unsure that this should be a first-class API. |
nit: Would make more sense to me to just make it invalid. Also, that semantic or requirement should be in the spec (as comment or prose) |
Correct; this entire API is optional.
Not without a parser written in JS/WASM, which places an undue burden on web developers. |
Well, that only has to be written once :) This translation could happen even earlier on in the process - before the shader is even loaded into the browser, for example. I would like to see WebGPU and WHLSL agree on the binding model. If we want to provide paths to help port non-WHLSL shaders to WHLSL then that's great, but I don't think that this conversion belongs in WebGPU. |
|
This is basically the crux of what I wanted to say in the meeting (but didn't have time). While HLSL compatibility is important to some users of the API, having incompatibilities only in bindings seems acceptable to me - it's a tiny volume of changes for an existing engine, especially given they have to also rewrite all of the non-shader code. For those that really want to run totally unmodified, they're going to have to use a translation layer anyway, and that translation layer would be able to do this extra work. |
I, too, would like to see WebGPU and WHLSL agree on the binding model. However, I believe that ship has sailed in #188. |
|
I'd like to continue seeing if we can find a way to have WHLSL feel like a more natural shading language for WebGPU. On another note though, I'm wondering how we'd expect someone who has a load of HLSL shaders that they compile with dxc to spir-v using the various -fvt-*-shift compiler options generate the appropriate mapping tables to work with this API? It looks like they'd have to build up a mapping table listing every possible remapping. Can we improve on this? |
|
Discussed at 8 July 2019 teleconference |
|
Rebased over #365 (and squashed, sorry) |
|
|
||
| <script type=idl> | ||
| dictionary GPUShaderSemantic { | ||
| required DOMString type; // "u", "s", "t", "b" |
|
|
||
| dictionary GPUShaderModuleDescriptor : GPUObjectDescriptorBase { | ||
| required GPUShaderCode code; | ||
| sequence<GPUOverriddenBindPoint>? overriddenBindPoints = null; |
There was a problem hiding this comment.
nit: should probably be
sequence<GPUOverriddenBindPoint> overriddenBindPoints = [];
| Note: While the choice of shader language is undecided, | ||
| `GPUShaderModuleDescriptor` will temporarily accept both text and binary input. | ||
|
|
||
| #### Bind Point Renaming #### {#bind-point-renaming} |
There was a problem hiding this comment.
FYI: Added this header for you when I did the rebase
|
This was discussed at the 15 July 2019 teleconference. |
|
I think we all agreed to close this and make the changes in WHLSL. Closing! |
* Port the renderPass resolve tests from GLSL to WGSL * Update src/webgpu/api/operation/render_pass/resolve.spec.ts
Due to the resolution that the WebGPU API's binding model should not be modified to match the shading language's binding model, and due to the fact that backwards compatibility with existing HLSL code is important, this patch adds an "adapter" to bridge between the two binding models. This adapter exists in the Javascript API, because we're trying to minimize the number of places that existing shaders have to be updated.
The proposal is fairly simple: provide a mapping of strings (of the form
register(u2, space1)) to the two-level binding model used in the API. This mapping is provided in theGPUShaderModuleso compilation can be done as early as possible and doesn't have to be deferred until pipeline creation time.This new map is optional, so authors which already have a source file which adheres to WebGPU's binding model don't need to supply anything. If this field is not present, it behaves as if the map has 0 fields in it. For every field that is present, compilation is expected to behave as if the WHLSL semantic is replaced with the associated value. For every semantic in the source shader, if a mapping is not present for it, it behaves as if the binding comes from the digit after the type character (the
2inregister(u2, space1)) and the bindGroup comes from thespace(the1inregister(u2, space1)).If honoring this mapping would cause duplicate binding points, the program is in error (we don't try again without the mapping; the mapping, when specified, is required to be applied). If two parameters in the source program (before the mapping) have duplicate semantics, the program is in error.
SPIR-V would just ignore this new field.
This renaming allows for mapping a parameter from one bind group to another. This is so that a WHLSL program with all its parameters in the same
spacecan spread those parameters out across multiple bind groups.Also considered: Instead of the keys being strings, they could be a dictionary containing 3 fields: binding, bind group, and type. However, this has less flexibility for further binding model advances in the future, doesn't map well to WebIDL, and is less obvious to a WHLSL author which variable maps to which entry in the map.
Usage:
Preview | Diff