Commit Graph

144 Commits

Author SHA1 Message Date
JMS55
b89387d820 Merge commit '2bddbdfd7c920d1ea61245dcdb7ff1c155e6b03b' into dlss3 2025-07-15 11:31:14 -04:00
andriyDev
2bddbdfd7c
Use RenderStartup for all basic cases in bevy_core_pipeline. (#20002)
# Objective

- Progress towards #19887.

## Solution

- Convert `FromWorld` impls into systems.
- Run those systems in `RenderStartup`.

## Testing

- Ran `bloom_3d`, `auto_exposure`, `depth_of_field`, `motion_blur`,
`skybox`, `post_processing`, and `tonemapping` examples and they all
work :)
2025-07-15 07:10:43 +00:00
andriyDev
2824bd5f6e
Use RenderStartup in bevy_sprite. (#20147)
# Objective

- Progress towards #19887.

## Solution

- Convert FromWorld implementations into systems.
- Move any resource "manipulation" from `Plugin::finish` to systems.
- Add `after` dependencies to any uses of these resources (basically all
`SpritePipeline`).

## Testing

- Ran the `sprite`, and `mesh2d_manual` example and it worked.
2025-07-15 06:30:34 +00:00
Christian Hughes
2be3bc5310
Improve node encapsulation in ScheduleGraph (#20119)
# Objective

- Part of #20115

We want to encapsulate each part of `ScheduleGraph` into its own
specific struct to make parts of it easier to reuse and maintain.

## Solution

- Pulled `ScheduleGraph::systems` and `ScheduleGraph::system_conditions`
into a `Systems` struct and added a field for this new struct to
`ScheduleGraph`
- Broke up `ScheduleGraph::uninit` into `Systems::uninit` and
`SystemSets::uninit` to eliminate `ScheduleGraph`'s direct field access
of these types
- Removed node and condition accessors from `ScheduleGraph`; the same
operations are now available on `Systems` and `SystemSets` instead
(accessible via their `pub` fields on `ScheduleGraph`)
- Moved `Systems`, `SystemSets`, `SystemNode`, `SystemWithAccess`, and
`ConditionWithAccess` into a separate file.

## Testing

Added two new tests covering the API surface of `Systems` and
`SystemSets`, respectively.

---------

Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com>
2025-07-15 06:29:52 +00:00
Tim
4e9e78c31e
Split BufferedEvent from Event (#20101)
# Objective

> I think we should axe the shared `Event` trait entirely
It doesn't serve any functional purpose, and I don't think it's useful
pedagogically
@alice-i-cecile on discord

## Solution

- Remove `Event` as a supertrait of `BufferedEvent`
- Remove any `Event` derives that were made unnecessary
- Update release notes

---------

Co-authored-by: SpecificProtagonist <vincentjunge@posteo.net>
2025-07-14 21:31:48 +00:00
atlv
e0383a0b96
Add zstd release note (#20053)
# Objective

- Add a release note for the new zstd backend.
- Doing so, I realized it was really cumbersome to enable this feature
because we default-enable ruzstd AND make it take precedence if both are
enabled. We can improve ux a bit by making the optional feature take
precedence when both are enabled. This still doesnt remove the unneeded
dependency, but oh well.

Note: it would be nice to have a way to make zstd_c not do anything when
building wasm, but im not sure theres a way to do that, as it seems like
it would need negative features.

---------

Co-authored-by: Jan Hohenheim <jan@hohenheim.ch>
2025-07-14 20:53:26 +00:00
atlv
1e057d8419
Add release note for light textures (#20023)
# Objective

- Fixes #19982

## Solution

- add note

## Testing

- left as an exercise for the reader
2025-07-14 20:47:45 +00:00
andriyDev
6e3739ac96
Use RenderStartup for bevy_pbr for some basic cases. (#19999)
# Objective

- Progress towards #19887.

## Solution

- For cases that don't need to conditionally add systems, we can just
replace FromWorld impls with systems and then add those systems to
`RenderStartup`.

## Testing

- I ran the `lightmaps`, `reflection_probes`, `deferred_rendering`,
`volumetric_fog`, and `wireframe` examples.
2025-07-14 20:28:03 +00:00
JMS55
84936cad55
Fix visibility (re)use in Solari DI (#20113)
# Objective
Fixes the re(use) of visibility in Solari's ReSTIR DI. 

The paper I based things off of didn't (seem) to use visibility in their
resampling
https://yusuketokuyoshi.com/papers/2024/Efficient_Visibility_Reuse_for_Real-time_ReSTIR_(Supplementary_Document).pdf,
only shading, but factoring it into the resampling improves things a
lot.

---

## Showcase
Before:
<img width="2564" height="1500" alt="image"
src="https://github.com/user-attachments/assets/15fa7941-ab68-47bc-9bbc-42ca55359046"
/>

After: 
<img width="2564" height="1500" alt="image"
src="https://github.com/user-attachments/assets/6fe52ed0-7832-41c1-b1cd-e8c8d9825e51"
/>
2025-07-13 19:33:09 +00:00
Talin
ace0114bdd
Changing the notification protocol for core_widgets. (#20086)
Notifications now include the source entity. This is useful for
callbacks that are responsible for more than one widget.

Part of #19236 

This is an incremental change only: I have not altered the fundamental
nature of callbacks, as this is still in discussion. The only change
here is to include the source entity id with the notification.

The existing examples don't leverage this new field, but that will
change when I work on the color sliders PR.

I have been careful not to use the word "events" in describing the
notification message structs because they are not capital-E `Events` at
this time. That may change depending on the outcome of discussions.

@alice-i-cecile
2025-07-13 17:25:11 +00:00
JMS55
e5aa94132c
Solari initial GI (#20020)
# Objective
- Add 1-bounce RT GI

## Solution

- Implement a very very basic version of ReSTIR GI
https://d1qx31qr3h6wln.cloudfront.net/publications/ReSTIR%20GI.pdf
- Pretty much a copy of the ReSTIR DI code, but adjusted for GI. 
- Didn't implement add more spatial samples, or do anything needed for
better quality.
- Didn't try to improve perf at all yet (it's actually faster than DI
though, unfortunately 😅)
- Didn't spend any time cleaning up the shared abstractions between
DI/GI

---

## Showcase
<img width="2564" height="1500" alt="image"
src="https://github.com/user-attachments/assets/1ff7be1c-7d7d-4e53-8aa6-bcec1553db3f"
/>
2025-07-13 17:23:38 +00:00
JMS55
d962a370a6 Release notes 2025-07-11 11:53:44 -04:00
JMS55
27f40ef4ba Merge commit '20dfae9a2d07038bda2921f82af50ded6151c3de' into dlss3 2025-07-11 11:37:26 -04:00
atlv
cfb679a752
Add a release note for scene types refactor (#20051)
Its really barebones but I'm not sure what else to write.

---------

Co-authored-by: Robert Swain <robert.swain@gmail.com>
2025-07-11 07:34:06 +00:00
andriyDev
c9c8964857
Add release notes and a migration guide for RenderStartup. (#20024)
# Objective

- Document #19887 changes.

## Solution

- Just some writing for Mwriting Monday!

---------

Co-authored-by: atlv <email@atlasdostal.com>
2025-07-09 23:40:42 +00:00
Talin
f2d25355c3
SliderPrecision component (#20032)
This PR adds a `SliderPrecision` component that lets you control the
rounding when dragging a slider.

Part of #19236
2025-07-09 20:06:58 +00:00
JMS55
6f9114be60
Merge branch 'main' into dlss3 2025-07-09 11:48:00 -07:00
JMS55
e202226952
Update release-content/release-notes/dlss.md
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-07-09 11:42:19 -07:00
Daniel Skates
d45ae74286
Add frame_time graph to fps_overlay v2 (#19277)
# Objective

- Rebase of https://github.com/bevyengine/bevy/pull/12561 , note that
this is blocked on "up-streaming
[iyes_perf_ui](https://crates.io/crates/iyes_perf_ui)" , but that work
seems to also be stalled

> Frame time is often more important to know than FPS but because of the
temporal nature of it, just seeing a number is not enough. Seeing a
graph that shows the history makes it easier to reason about
performance.

## Solution

> This PR adds a bar graph of the frame time history.
> 
> Each bar is scaled based on the frame time where a bigger frame time
will give a taller and wider bar.
> 
> The color also scales with that frame time where red is at or bellow
the minimum target fps and green is at or above the target maximum frame
rate. Anything between those 2 values will be interpolated between green
and red based on the frame time.
> 
> The algorithm is highly inspired by this article:
https://asawicki.info/news_1758_an_idea_for_visualization_of_frame_times

## Testing

- Ran `cargo run --example fps_overlay --features="bevy_dev_tools"`

---------

Co-authored-by: IceSentry <c.giguere42@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-07-09 16:59:21 +00:00
JMS55
8084745c25
Merge branch 'main' into dlss3 2025-07-08 18:57:26 -07:00
JMS55
e2d8a9e08b Fix another link 2025-07-08 21:56:11 -04:00
JMS55
baa26682e9 Switch link to https://github.com/bevyengine/dlss_wgpu 2025-07-08 21:18:41 -04:00
Talin
aa87581cce
Change CoreWidgets plugin to plugin group. (#20036)
What it says on the tin. :)
2025-07-09 01:07:49 +00:00
JMS55
fda09d19c7 Fix typo 2025-07-08 11:56:50 -04:00
andriyDev
09ccedd244
Clean up several miscellaneous uses of weak_handle. (#19408)
# Objective

- Related to #19024.

## Solution

- This is a mix of several ways to get rid of weak handles. The primary
strategy is putting strong asset handles in resources that the rendering
code clones into its pipelines (or whatever).
- This does not handle every remaining case, but we are slowly clearing
them out.

## Testing

- `anti_aliasing` example still works.
- `fog_volumes` example still works.
2025-07-08 06:45:40 +00:00
JMS55
04f488bc47 Update release notes 2025-07-07 22:28:51 -04:00
JMS55
1b714636ab Merge commit '5e3927ba489f597dd189f63286dc7985840db1b5' into dlss3 2025-07-07 21:40:01 -04:00
AlephCubed
3aed85a88b
Rename send_event and similar methods to write_event (#20017)
Fixes: #18963
Follows up on: #17977
Adopts: #18966

In 0.16, `EventWriter::send` was renamed to `EventWriter::write`, but
many methods were missed (sorry about that). This completes that
refactor by renaming all `send` methods and internals.

| Old | New |

|-------------------------------------|--------------------------------------|
| `World::send_event` | `World::write_event` |
| `World::send_event_default` | `World::write_event_default` |
| `World::send_event_batch` | `World::write_event_batch` |
| `DeferredWorld::send_event` | `DeferredWorld::write_event` |
| `DeferredWorld::send_event_default` |
`DeferredWorld::write_event_default` |
| `DeferredWorld::send_event_batch` | `DeferredWorld::write_event_batch`
|
| `Commands::send_event` | `Commmands::write_event` |
| `Events::send` | `Events::write` |
| `Events::send_default` | `Events::write_default` |
| `Events::send_batch` | `Events::write_batch` |
| `RemovedComponentEvents::send` | `RemovedComponentEvents::write` |
| `command::send_event` | `commmand::write_event` |
| `SendBatchIds` | `WriteBatchIds` |

---------

Co-authored-by: shwwwa <shwwwa.dev@gmail.com>
2025-07-07 22:05:16 +00:00
ickshonpe
5ea0e4004f
HSL and HSV interpolation for UI gradients (#19992)
# Objective

Add interpolation in HSL and HSV colour spaces for UI gradients.

## Solution
Added new variants to `InterpolationColorSpace`: `Hsl`, `HslLong`,
`Hsv`, and `HsvLong`, along with mix functions to the `gradients` shader
for each of them.

#### Limitations
* Didn't include increasing and decreasing path support, it's not
essential and can be done in a follow up if someone feels like it.

* The colour conversions should really be performed before the colours
are sent to the shader but it would need more changes and performance is
good enough for now.

## Testing

```cargo run --example gradients```
2025-07-07 20:08:51 +00:00
eugineerd
3b6d01972b
Unify filtering by id in EntityClonerBuilder (#19977)
# Objective
#19649 introduced new `*_if_new` and `*_by_bundle_id_*` variations to
`EntityClonerBuilder` filtering functionality, which resulted in
increase in method permutations - there are now 8 allow variants to
support various id types and 2 different insert modes.

## Solution
This PR introduces a new trait `FilterableIds` to unify all id types and
their `IntoIterator` implementations, which is somewhat similar to
`WorldEntityFetch`. It supports `TypeId`, `ComponentId` and `BundleId`,
allowing us to reduce the number of `allow` methods to 4: `allow`,
`allow_if_new`, `allow_by_ids`, `allow_by_ids_if_new`. The function
signature is a bit less readable now, but the docs mention types that
can be passed in.

## Testing
All existing tests pass, performance is unchanged.

---------

Co-authored-by: urben1680 <55257931+urben1680@users.noreply.github.com>
2025-07-07 20:00:37 +00:00
Lucas Franca
80b059c815
Extract members of PickingPlugin and PointerInputPlugin into new types (#19078)
# Objective

`PickingPlugin` and `PointerInputPlugin` were kinda weird being both a
plugin and a resource.

## Solution

Extract the resource functionality of `PickingPlugin` and
`PointerInputPlugin` into new resources

## Testing

`mesh_picking` and `sprite_picking`

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Jan Hohenheim <jan@hohenheim.ch>
2025-07-07 19:40:25 +00:00
andriyDev
2c6cf9a597
Run RenderStartup in/before extract instead of after it. (#19926)
# Objective

- Fixes #19910.

## Solution

- First, allow extraction function to be FnMut instead of Fn. FnMut is a
superset of Fn anyway, and we only ever call this function once at a
time (we would never call this in parallel for different pairs of worlds
or something).
- Run the `RenderStartup` schedule in the extract function with a flag
to only do it once.
- Remove all the `MainRender` stuff.

One sad part here is that now the `RenderStartup` blocks extraction. So
for pipelined rendering, our simulation will be blocked on the first
frame while we set up all the rendering resources. I don't see this as a
big loss though since A) that is fundamentally what we want here -
extraction **has to** run after `RenderStartup`, and the only way to do
better is to somehow run `RenderStartup` in parallel with the first
simulation frame, and B) without `RenderStartup` the **entire** app was
blocked on initializing render resources during Plugin construction - so
we're not really losing anything here.

## Testing

- I ran the `custom_post_processing` example (which was ported to use
`RenderStartup` in #19886) and it still works.
2025-07-07 01:31:40 +00:00
JMS55
cf1a1f7b7f Add note about DlssSupported 2025-07-06 18:07:16 -04:00
JMS55
6b960b0d7f Modify release notes 2025-07-06 18:03:36 -04:00
JMS55
bf56980080 Add release notes 2025-07-06 17:53:36 -04:00
atlv
1579256709
Rename light visibility class (#19986)
# Objective

- prepare bevy_light for split
- make struct named better
- put it where it belongs

## Solution

- do those things

## Testing

- 3d_scene, lighting

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-07-06 19:04:30 +00:00
Giacomo Stevanato
8e89511e47
Remove Bundle::register_required_components (#19967)
# Objective

- `Bundle::register_required_components` is not used anywhere, let's
remove it
2025-07-06 18:15:28 +00:00
atlv
bd5f924290
Split bevy_camera out of bevy_render (#19949)
# Objective

- get closer to being able to load gltfs without using bevy_render

## Solution

- Split bevy_camera out of bevy_render
- Builds on #19943
- Im sorry for the big diff, i tried to minimize it as much as i can by
using re-exports. This also prevents most breaking changes, but there
are still a couple.

## Testing

- 3d_scene looks good
2025-07-04 23:31:16 +00:00
Daniel Skates
560429ebd9
Observer trigger refactor (#19935)
# Objective

- The usage of ComponentId is quite confusing: events are not
components. By newtyping this, we can prevent stupid mistakes, avoid
leaking internal details and make the code clearer for users and engine
devs reading it.
- Adopts https://github.com/bevyengine/bevy/pull/19755

---------

Co-authored-by: oscar-benderstone <oscarbenderstone@gmail.com>
Co-authored-by: Oscar Bender-Stone <88625129+oscar-benderstone@users.noreply.github.com>
2025-07-04 16:27:21 +00:00
ickshonpe
b01de70bdd
bevy_ui_render crate (#18703)
# Objective

Move Bevy UI's rendering into a dedicated crate.

Motivations:
* Allow the UI renderer to be used with other UI frameworks than
`bevy_ui`.
* Allow for using alternative renderers like Vello with `bevy_ui`.
* It's difficult for rendering contributors to make changes and
improvements to the UI renderer as it requires in-depth knowledge of the
UI implementation.

## Solution

Move the `render` and `ui_material` modules from `bevy_ui` into a new
crate `bevy_ui_render`.

## Testing

Important examples to check are `testbed_ui`, `testbed_full_ui`,
`ui_material`, `viewport_node` and `gradients`.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-07-03 23:36:35 +00:00
Chris Russell
6e918f56d8
Have System::run_unsafe return Result. (#19145)
# Objective

Allow combinator and pipe systems to delay validation of the second
system, while still allowing the second system to be skipped.

Fixes #18796

Allow fallible systems to be used as one-shot systems, reporting errors
to the error handler when used through commands.

Fixes #19722

Allow fallible systems to be used as run conditions, including when used
with combinators. Alternative to #19580.

Always validate parameters when calling the safe
`run_without_applying_deferred`, `run`, and `run_readonly` methods on a
`System`.

## Solution

Have `System::run_unsafe` return a `Result`.  

We want pipe systems to run the first system before validating the
second, since the first system may affect whether the second system has
valid parameters. But if the second system skips then we have no output
value to return! So, pipe systems must return a `Result` that indicates
whether the second system ran.

But if we just make pipe systems have `Out = Result<B::Out>`, then
chaining `a.pipe(b).pipe(c)` becomes difficult. `c` would need to accept
the `Result` from `a.pipe(b)`, which means it would likely need to
return `Result` itself, giving `Result<Result<Out>>`!

Instead, we make *all* systems return a `Result`! We move the handling
of fallible systems from `IntoScheduleConfigs` and `IntoObserverSystem`
to `SystemParamFunction` and `ExclusiveSystemParamFunction`, so that an
infallible system can be wrapped before being passed to a combinator.

As a side effect, this enables fallible systems to be used as run
conditions and one-shot systems.

Now that the safe `run_without_applying_deferred`, `run`, and
`run_readonly` methods return a `Result`, we can have them perform
parameter validation themselves instead of requiring each caller to
remember to call them. `run_unsafe` will continue to not validate
parameters, since it is used in the multi-threaded executor when we want
to validate and run in separate tasks.

Note that this makes type inference a little more brittle. A function
that returns `Result<T>` can be considered either a fallible system
returning `T` or an infallible system returning `Result<T>` (and this is
important to continue supporting `pipe`-based error handling)! So there
are some cases where the output type of a system can no longer be
inferred. It will work fine when directly adding to a schedule, since
then the output type is fixed to `()` (or `bool` for run conditions).
And it will work fine when `pipe`ing to a system with a typed input
parameter.

I used a dedicated `RunSystemError` for the error type instead of plain
`BevyError` so that skipping a system does not box an error or capture a
backtrace.
2025-07-03 21:48:09 +00:00
Christian Hughes
ebf87f56ef
Use SlotMaps to store systems and system sets in Schedules (#19352)
# Objective

- First step towards #279

## Solution

Makes the necessary internal data structure changes in order to allow
system removal to be added in a future PR: `Vec`s storing systems and
system sets in `ScheduleGraph` have been replaced with `SlotMap`s.

See the included migration guide for the required changes.

## Testing

Internal changes only and no new features *should* mean no new tests are
requried.
2025-07-03 18:50:54 +00:00
Talin
870490808d
Feathers toggle switches. (#19928)
# Objective

This is the Feathers toggle switch widget (without animation).

Part of #19236 

### Showcase

<img width="143" alt="toggles"
src="https://github.com/user-attachments/assets/c04afc06-5a57-4bc6-8181-99efbd1bebef"
/>
2025-07-03 01:09:31 +00:00
andriyDev
f95f42b44a
Allow calling add_render_graph_node on World. (#19912)
# Objective

- This unblocks some work I am doing for #19887.

## Solution

- Rename `RenderGraphApp` to `RenderGraphExt`.
- Implement `RenderGraphExt` for `World`.
- Change `SubApp` and `App` to call the `World` impl.
2025-07-02 14:56:18 +00:00
andriyDev
d05c435848
Replace Handle::Weak with Handle::Uuid. (#19896)
# Objective

- Progress towards #19024.

## Solution

- Remove `Handle::Weak`!

If users were relying on `Handle::Weak` for some purpose, they can
almost certainly replace it with raw `AssetId` instead. If they cannot,
they can make their own enum that holds either a Handle or an AssetId.
In either case, we don't need weak handles!

Sadly we still need Uuid handles since we rely on them for "default"
assets and "invalid" assets, as well as anywhere where a component wants
to impl default with a non-defaulted asset handle. One step at a time
though!
2025-07-02 14:40:35 +00:00
ickshonpe
a949867a1c
UI z-ordering fix (#19691)
# Objective

During the migration to required components a lot of things were changed
around and somehow the draw order for some UI elements ended up
depending on the system ordering in `RenderSystems::Queue`, which can
sometimes result in the elements being drawn in the wrong order.

Fixes #19674

## Solution

* Added some more `stack_z_offsets` constants and used them to enforce
an explicit ordering.
* Removed the `stack_index: u32` field from `ExtractedUiNodes` and
replaced it with a `z_order: f32` field.

These changes should fix all the ordering problems. 

## Testing

I added a nine-patched bordered node with a navy background color to the
slice section of the `testbed_ui` example.
The border should always be drawn above the background color.
2025-07-01 19:20:07 +00:00
ickshonpe
5e8aa7986b
Newtyped ScrollPosition (#19881)
# Objective

Change `ScrollPosition` to newtype `Vec2`. It's easier to work with a
`Vec2` wrapper than individual fields.

I'm not sure why this wasn't newtyped to start with. Maybe the intent
was to support responsive coordinates eventually but that probably isn't
very useful or straightforward to implement. And even if we do want to
support responsive coords in the future, it can newtype `Val2`.

## Solution

Change `ScrollPosition` to newtype `Vec2`. 

Also added some extra details to the doc comments.

## Testing

Try the `scroll` example.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-07-01 17:41:48 +00:00
Talin
b980d4ac22
Feathers checkbox (#19900)
Adds checkbox and radio buttons to feathers.

Showcase:

<img width="378" alt="feathers-checkbox-radio"
src="https://github.com/user-attachments/assets/76d35589-6400-49dd-bf98-aeca2f39a472"
/>
2025-07-01 06:59:14 +00:00
Talin
7b6c5f4431
Change core widgets to use callback enum instead of option (#19855)
# Objective

Because we want to be able to support more notification options in the
future (in addition to just using registered one-shot systems), the
`Option<SystemId>` notifications have been changed to a new enum,
`Callback`.

@alice-i-cecile
2025-07-01 03:23:38 +00:00
Emerson Coskey
bdd3ef71b8
Composable Pipeline Specialization (#17373)
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 is that specializers don't *produce*
pipeline descriptors, but instead *modify* existing ones:

```rs
pub trait Specialize<T: Specializable> {
    type Key: SpecializeKey;
    
    fn specialize(
        &self, 
        key: Self::Key, 
        descriptor: &mut T::Descriptor
    ) -> Result<Canonical<Self::Key>, BevyError>;
}
```

This lets us use some derive magic to stick multiple specializers
together:

```rs
pub struct A;
pub struct B;

impl Specialize<RenderPipeline> for A { ... }
impl Specialize<RenderPipeline> for A { ... }

#[derive(Specialize)]
#[specialize(RenderPipeline)]
struct C {
    // specialization is applied in struct field order
    applied_first: A,
    applied_second: B,
}

type C::Key = (A::Key, B::Key);

```

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 only real breaking change here 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 replacing `Specialized[Render/Compute]Pipelines`), or
supplied by implementing `HasBaseDescriptor` on a specializer. See
`examples/shader/custom_phase_item.rs` for an example implementation.

## Testing

- Did some simple manual testing of the derive macro, it seems robust.

---

## Showcase

```rs
#[derive(Specialize, HasBaseDescriptor)]
#[specialize(RenderPipeline)]
pub struct SpecializeMeshMaterial<M: Material> {
    // set mesh bind group layout and shader defs
    mesh: SpecializeMesh,
    // set view bind group layout and shader defs
    view: SpecializeView,
    // since type SpecializeMaterial::Key = (), 
    // we can hide it from the wrapper's external API
    #[key(default)]
    // defer to the GetBaseDescriptor impl of SpecializeMaterial, 
    // since it carries the vertex and fragment handles
    #[base_descriptor]
    // set material bind group layout, etc
    material: SpecializeMaterial<M>,
}

// implementation generated by the derive macro
impl <M: Material> Specialize<RenderPipeline> for SpecializeMeshMaterial<M> {
    type Key = (MeshKey, ViewKey);

    fn specialize(
        &self, 
        key: Self::Key, 
        descriptor: &mut RenderPipelineDescriptor
    ) -> Result<Canonical<Self::Key>, BevyError>  {
        let mesh_key = self.mesh.specialize(key.0, descriptor)?;
        let view_key = self.view.specialize(key.1, descriptor)?;
        let _ = self.material.specialize((), descriptor)?;
        Ok((mesh_key, view_key));
    }
}

impl <M: Material> HasBaseDescriptor<RenderPipeline> for SpecializeMeshMaterial<M> {
    fn base_descriptor(&self) -> RenderPipelineDescriptor {
        self.material.base_descriptor()
    }
}
```

---------

Co-authored-by: Tim Overbeek <158390905+Bleachfuel@users.noreply.github.com>
2025-07-01 01:32:44 +00:00