Skip to content

Commit

Permalink
Fix the texture_binding_array, specialized_mesh_pipeline, and `cu…
Browse files Browse the repository at this point in the history
…stom_shader_instancing` examples after the bindless change. (#16641)

The bindless PR (#16368) broke some examples:

* `specialized_mesh_pipeline` and `custom_shader_instancing` failed
because they expect to be able to render a mesh with no material, by
overriding enough of the render pipeline to be able to do so. This PR
fixes the issue by restoring the old behavior in which we extract meshes
even if they have no material.

* `texture_binding_array` broke because it doesn't implement
`AsBindGroup::unprepared_bind_group`. This was tricky to fix because
there's a very good reason why `texture_binding_array` doesn't implement
that method: there's no sensible way to do so with `wgpu`'s current
bindless API, due to its multiple levels of borrowed references. To fix
the example, I split `MaterialBindGroup` into
`MaterialBindlessBindGroup` and `MaterialNonBindlessBindGroup`, and
allow direct custom implementations of `AsBindGroup::as_bind_group` for
the latter type of bind groups. To opt in to the new behavior, return
the `AsBindGroupError::CreateBindGroupDirectly` error from your
`AsBindGroup::unprepared_bind_group` implementation, and Bevy will call
your custom `AsBindGroup::as_bind_group` method as before.

## Migration Guide

* Bevy will now unconditionally call
`AsBindGroup::unprepared_bind_group` for your materials, so you must no
longer panic in that function. Instead, return the new
`AsBindGroupError::CreateBindGroupDirectly` error, and Bevy will fall
back to calling `AsBindGroup::as_bind_group` as before.
  • Loading branch information
pcwalton authored Dec 5, 2024
1 parent 73c6479 commit d3241c4
Show file tree
Hide file tree
Showing 5 changed files with 399 additions and 74 deletions.
66 changes: 54 additions & 12 deletions crates/bevy_pbr/src/material.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1038,24 +1038,24 @@ impl<M: Material> RenderAsset for PreparedMaterial<M> {
return Err(PrepareAssetError::RetryNextUpdate(material));
};

let method = match material.opaque_render_method() {
OpaqueRendererMethod::Forward => OpaqueRendererMethod::Forward,
OpaqueRendererMethod::Deferred => OpaqueRendererMethod::Deferred,
OpaqueRendererMethod::Auto => default_opaque_render_method.0,
};
let mut mesh_pipeline_key_bits = MeshPipelineKey::empty();
mesh_pipeline_key_bits.set(
MeshPipelineKey::READS_VIEW_TRANSMISSION_TEXTURE,
material.reads_view_transmission_texture(),
);

match material.unprepared_bind_group(
&pipeline.material_layout,
render_device,
material_param,
) {
Ok(unprepared) => {
let method = match material.opaque_render_method() {
OpaqueRendererMethod::Forward => OpaqueRendererMethod::Forward,
OpaqueRendererMethod::Deferred => OpaqueRendererMethod::Deferred,
OpaqueRendererMethod::Auto => default_opaque_render_method.0,
};
let mut mesh_pipeline_key_bits = MeshPipelineKey::empty();
mesh_pipeline_key_bits.set(
MeshPipelineKey::READS_VIEW_TRANSMISSION_TEXTURE,
material.reads_view_transmission_texture(),
);

bind_group_allocator.init(*material_binding_id, unprepared);
bind_group_allocator.init(render_device, *material_binding_id, unprepared);

Ok(PreparedMaterial {
binding: *material_binding_id,
Expand All @@ -1070,9 +1070,51 @@ impl<M: Material> RenderAsset for PreparedMaterial<M> {
phantom: PhantomData,
})
}

Err(AsBindGroupError::RetryNextUpdate) => {
Err(PrepareAssetError::RetryNextUpdate(material))
}

Err(AsBindGroupError::CreateBindGroupDirectly) => {
// This material has opted out of automatic bind group creation
// and is requesting a fully-custom bind group. Invoke
// `as_bind_group` as requested, and store the resulting bind
// group in the slot.
match material.as_bind_group(
&pipeline.material_layout,
render_device,
material_param,
) {
Ok(prepared_bind_group) => {
// Store the resulting bind group directly in the slot.
bind_group_allocator.init_custom(
*material_binding_id,
prepared_bind_group.bind_group,
prepared_bind_group.data,
);

Ok(PreparedMaterial {
binding: *material_binding_id,
properties: MaterialProperties {
alpha_mode: material.alpha_mode(),
depth_bias: material.depth_bias(),
reads_view_transmission_texture: mesh_pipeline_key_bits
.contains(MeshPipelineKey::READS_VIEW_TRANSMISSION_TEXTURE),
render_method: method,
mesh_pipeline_key_bits,
},
phantom: PhantomData,
})
}

Err(AsBindGroupError::RetryNextUpdate) => {
Err(PrepareAssetError::RetryNextUpdate(material))
}

Err(other) => Err(PrepareAssetError::AsBindGroupError(other)),
}
}

Err(other) => Err(PrepareAssetError::AsBindGroupError(other)),
}
}
Expand Down
Loading

0 comments on commit d3241c4

Please sign in to comment.