-
Notifications
You must be signed in to change notification settings - Fork 1.1k
[naga hlsl-out] HLSL implemention of external textures #7826
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
636c40c
to
78d8574
Compare
78d8574
to
681f342
Compare
Rebased and updated |
681f342
to
bb06952
Compare
bb06952
to
f9cbe75
Compare
Rebased on trunk since #7822 is landed. |
f9cbe75
to
2084c01
Compare
Rebased on trunk since #7823 has landed, and regenerated snapshot output. |
Not a request for a change, just some thoughts: Does In the long term, I'm wondering if Naga doesn't need two IRs, one designed around front-end needs, and a second around backend needs, with a lowering pass between them. The lowering code could be shared by backends, but it would take parameters indicating which transformations the backends needed. One such transformation might be, "lower external textures to ordinary textures and parameter blocks". Others might be the HLSL access rewriting, or the unrestricted pointer parameters rewrites. |
@jamienicol Do the doc changes in |
7741fba
to
611c3c9
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The first commit, "[naga] Generate special type for external texture params buffer", looks good to me.
@jamienicol In 17f8bf8 I was trying to reduce the repetition in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The second commit, "[naga] Reserve names for each plane and params buffer of external texture", looks good to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The log message for the third commit - the long one - is superb, but it belongs in the code, not in the commit message.
Sorry - still reviewing that final commit. |
They look great, modulo a typo which I've fixed in 5f90c8e |
I believe the important contents of it is all in the code, spread around various places as appropriate. But a single high-level overview of how external textures are implemented for HLSL in the code somewhere doesn't sound like a bad thing. Any suggestions for where to put this? |
No, it doesn't need to be in the IR. The benefit of it being there is that we don't have to duplicate its declaration in each backend, and it takes care of fiddly bits such as adding padding, packing a (You're right to point out a confusing difference in how the code as-is handles my params struct vs existing special types, which I've replied to above.) I'm afraid I don't know what "axiomatically rooted" means. But FWIW our tests would explode if somebody made that change to compaction and it would be quickly caught in CI. None of this is required, and if you think the weirdness outweighs the benefits I am more than happy to emit the declarations in the backends instead. |
Also pushed 84d4f0e which makes your |
16c971e
to
d5a4687
Compare
Hmm. This doesn't properly ensure that |
0eee109
to
2c5b18a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems to me that sample_transform
must be a transform that takes the (0,0) - (1,1) square to an axis-aligned rectangle that lies within (0,0) - (1,1), because otherwise the use of min
and max
to compute bounds
in nagaTextureSampleBaseClampToEdge
doesn't work.
If that's correct, could we get that commented? Perhaps the doc comment for SpecialTypes::external_texture_params
would be a good place.
Is it really the case that |
@jamienicol I think Naga does support I should have caught this in the review for #7822, sorry about that. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All right! Just some minor comments.
Yes this is correct. I think
This is really the case. Perhaps we could do the equivalent of what we do in the sample case, eg transform (0,0)..(texture_size - 1) and then clamp within that rect. But that's more instructions, and I seem to recall there was an issue with that approach anyway although unfortunately I can no longer remember the specifics
I'll see if I can fix this |
I filed #8027 for actually implementing binding array support |
65e338e
to
2527383
Compare
@jamienicol Okay, I pushed one more doc tweak, but this looks good to go. The binding array check looked right to me. Thanks!! |
89b337c
to
c3aa17e
Compare
During wgsl lowering, if we encounter an external texture type then generate the `ExternalTextureParams` struct. This will be required by most Naga backends to implement external textures. This type is not actually used by wgsl-in or the IR. However, generating it in Naga IR ensures tricky details such as member alignment are handled for us. wgsl-out must ensure it does *not* generate code for this type, as it handles external textures natively.
…ture Adds new `NameKey` variants `ExternalTextureGlobalVariable` and `ExternalTextureFunctionArgument`, like their non-external-texture cousins but additionally keyed by either being a specific plane index or params buffer. For each external texture global variable or function argument reserve additional names for 3 planes and the params buffer. For Naga backends which must represent external textures as multiple variables/arguments, this will allow them to uniquely name each one.
This adds HLSL backend support for `ImageClass::External` (ie WGSL's `external_texture` texture type). For each external texture global variable in the IR, we declare 3 `Texture2D` globals as well as a `cbuffer` for the params. The additional bindings required by these are found in the newly added `external_texture_binding_map`. Unique names for each can be obtained using `NameKey::ExternalTextureGlobalVariable`. For functions that contain ImageQuery::Size, ImageLoad, or ImageSample expressions for external textures, ensure we have generated wrapper functions for those expressions. When emitting code for the expressions themselves, simply insert a call to the wrapper function. For size queries, we return the value provided in the params struct. If that value is [0, 0] then we query the size of the plane 0 texture and return that. For load and sample, we sample the textures based on the number of planes specified in the params struct. If there is more than one plane we additionally perform YUV to RGB conversion using the provided matrix. Unfortunately HLSL does not allow structs to contain textures, meaning we are unable to wrap the 3 textures and params struct variables in a single variable that can be passed around. For our wrapper functions we therefore ensure they take the three textures and the params as consecutive arguments. Likewise, when declaring user-defined functions with external texture arguments, we expand the single external texture argument into 4 consecutive arguments. (Using NameKey::ExternalTextureFunctionArgument to ensure unique names for each.) Thankfully external textures can only be used as either global variables or function arguments. This means we only have to handle the `Expression::GlobalVariable` and `Expression::FunctionArgument` cases of `write_expr()`. Since in both cases we know the external texture can only be an argument to either a user-defined function or one of our wrapper functions, we can simply emit the names of the variables for each three textures and the params struct in a comma-separated list.
…ternal textures For simplicity's sake our initial implementation of external textures will not support binding arrays of external textures. We should therefore reject any shaders which use them during validation. Their implementation will be tracked in gfx-rs#8027. naga/src/valid/type.rs JJ: JJ: Lines starting with "JJ:" (like this one) will be removed.
c3aa17e
to
bb7a4e0
Compare
This adds MSL backend support for `ImageClass::External`. (ie WGSL's `external_texture` texture type). This is implemented very similarily to the HLSL implementation in gfx-rs#7826. Each external texture global variable is lowered to 3 `texture2d`s and a buffer of type NagaExternalTextureParams. As usual in Naga's MSL backend, these are passed as arguments to the entry point. The bindings for each of these arguments are provided via the usual binding map, using a new `BindExternalTextureTarget` variant of `BindTarget`. Unlike HLSL, MSL allows textures to be used as fields in structs. We therefore immediately wrap these variables in a `NagaExternalTextureWrapper` struct. This wrapper can then conveniently be passed to either user-defined functions or builtin implementations that accept an external texture. The WGSL builtins `textureDimensions()`, `textureLoad()`, and `textureSampleBaseClampToEdge()` are implemented using wrapper functions using the regular `write_wrapped_functions()` machinery.
This adds MSL backend support for `ImageClass::External`. (ie WGSL's `external_texture` texture type). This is implemented very similarily to the HLSL implementation in #7826. Each external texture global variable is lowered to 3 `texture2d`s and a buffer of type NagaExternalTextureParams. As usual in Naga's MSL backend, these are passed as arguments to the entry point. The bindings for each of these arguments are provided via the usual binding map, using a new `BindExternalTextureTarget` variant of `BindTarget`. Unlike HLSL, MSL allows textures to be used as fields in structs. We therefore immediately wrap these variables in a `NagaExternalTextureWrapper` struct. This wrapper can then conveniently be passed to either user-defined functions or builtin implementations that accept an external texture. The WGSL builtins `textureDimensions()`, `textureLoad()`, and `textureSampleBaseClampToEdge()` are implemented using wrapper functions using the regular `write_wrapped_functions()` machinery.
Connections
Depends on #7822
Part of #4386
Description
HLSL implementation of external textures
Testing
Snapshot tests. Manual testing.
Squash or Rebase?
Rebase after manually squashing any
fixup
commits that arise from reviewChecklist
cargo fmt
.taplo format
.cargo clippy --tests
. If applicable, add:--target wasm32-unknown-unknown
cargo xtask test
to run tests.CHANGELOG.md
entry.Still not changelog worthy but getting close!