-
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
base: trunk
Are you sure you want to change the base?
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. |
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.
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 |
module | ||
.special_types | ||
.predeclared_types | ||
.values() | ||
.any(|t| *t == handle) | ||
.any(|t| *t == ty) | ||
|| Some(ty) == module.special_types.external_texture_params |
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.
Again, not requesting a change, but this is weird. People will wonder why all the other special_types
aren't listed here too.
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.
Perhaps the other special_types
should in fact be listed here too? Looking at the input wgsl snapshot tests, eg here, the special types aren't actually declared in the source (they are in a comment just to show what they would look like). The respective TOML files specify not to run WGSL-out on them, but presumably if they did we would indeed want to skip emitting the declarations. Otherwise when parsing again with wgsl-in we would have duplicated declarations?
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.
…nal texture Use `Option::as_deref` as appropriate.
…nal texture Doc fixes.
…nal texture Minor refactor.
@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
Change `unimplemented!` for External images to `unreachable!`.
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!