-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Composable Pipeline Specialization #17373
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: main
Are you sure you want to change the base?
Conversation
cc5d27d
to
3b79eb0
Compare
still dying because of HashMap. Why?
3b79eb0
to
7e084d4
Compare
620170e
to
5a33a21
Compare
Ok(field_info) | ||
} | ||
|
||
fn get_struct_fields<'a>(ast: &'a DeriveInput, derive_name: &str) -> syn::Result<&'a Fields> { |
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.
u can use bevy_macro_utils::get_struct_fields. Probably also for more things here.
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.
I used a custom version originally for better error messages, but I should probably just upstream those changes to get_struct_fields
Co-authored-by: Tim Overbeek <158390905+Bleachfuel@users.noreply.github.com>
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.
How does this account for SpecializedMeshPipeline
which needs a MeshVertexBufferLayoutRef
that's derived from the mesh that's currently being specialized? This is the problem that I ran into when trying to make something similarly generic. Maybe we could have some kind of "extra data" that could piggyback along with the key? Or just add an extra parameter slot / associated type that's ()
for most implementations?
Currently, our specialization API works through a series of wrapper structs and traits, which make things confusing to follow and difficult to generalize.
This pr takes a different approach, where "specializers" (types that implement
Specialize
) are composable, but "flat" rather than composed of a series of wrappers. The key design choice is that specializers don't produce pipeline descriptors, but instead modify existing ones:This lets us use some derive magic to stick multiple specializers together:
This approach is much easier to understand, IMO, and also lets us separate concerns better. Specializers can be placed in fully separate crates/modules, and key computation can be shared as well.
The most significant change workflow-wise for this feature is that since specializers only modify descriptors, we need a "base" descriptor to work off of. This can either be manually supplied when constructing a
Specializer
(the new collection replacingSpecialized[Render/Compute]Pipelines
), or supplied by implementingHasBaseDescriptor
on a specializer. Seeexamples/shader/custom_phase_item.rs
for an example implementation.Testing
Showcase
What material specialization might look like after this change:
Migration Guide
For manual implementers
SpecializedRenderPipeline
->Specialize<RenderPipeline>
.SpecializedMeshPipeline
->Specialize<RenderPipeline>
SpecializedComputePipeline
->Specialize<ComputePipeline>
.SpecializedXPipelines<S>
->Specializer<X, S>
For derive macro usage
Derive macro names can't have generic parameters, so to derive
Specialize<RenderPipeline>
use#[derive(Specialize)]
and#[specialize(RenderPipeline)]
.To derive
Specialize<ComputePipeline>
use#[derive(Specialize)]
and#[specialize(ComputePipeline)]
.#[specialize(..targets)]
can take multiple specialize targets, or use#[specialize(all)]
to generate a fully generic implementation, at the cost of slightly worse error messages when the trait bounds aren't satisfied.Questions