Remove Shader weak_handles from bevy_ui. (#19393)

# Objective

- Related to #19024

## Solution

- Use the new `load_shader_library` macro for the shader libraries and
`embedded_asset`/`load_embedded_asset` for the "shader binaries" in
`bevy_ui`.

## Testing

- `box_shadow` example still works.
- `gradient` example is broken at head (see #19384) - but otherwise
gives the same result in the console.
- `ui_materials` example still works.
- `ui_texture_slice` example still works.

P.S. I don't think this needs a migration guide. Technically users could
be using the `pub` weak handles, but there's no actual good use for
them, so omitting it seems fine. Alternatively, we could mix this in
with the migration guide notes for #19137.
This commit is contained in:
andriyDev 2025-05-27 15:32:40 -07:00 committed by GitHub
parent 846cec9ed2
commit e8c2a5af66
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 49 additions and 77 deletions

View File

@ -34,20 +34,12 @@ use bytemuck::{Pod, Zeroable};
use super::{stack_z_offsets, UiCameraMap, UiCameraView, QUAD_INDICES, QUAD_VERTEX_POSITIONS};
pub const BOX_SHADOW_SHADER_HANDLE: Handle<Shader> =
weak_handle!("d2991ecd-134f-4f82-adf5-0fcc86f02227");
/// A plugin that enables the rendering of box shadows.
pub struct BoxShadowPlugin;
impl Plugin for BoxShadowPlugin {
fn build(&self, app: &mut App) {
load_internal_asset!(
app,
BOX_SHADOW_SHADER_HANDLE,
"box_shadow.wgsl",
Shader::from_wgsl
);
embedded_asset!(app, "box_shadow.wgsl");
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
render_app
@ -115,6 +107,7 @@ impl Default for BoxShadowMeta {
#[derive(Resource)]
pub struct BoxShadowPipeline {
pub view_layout: BindGroupLayout,
pub shader: Handle<Shader>,
}
impl FromWorld for BoxShadowPipeline {
@ -129,7 +122,10 @@ impl FromWorld for BoxShadowPipeline {
),
);
BoxShadowPipeline { view_layout }
BoxShadowPipeline {
view_layout,
shader: load_embedded_asset!(world, "box_shadow.wgsl"),
}
}
}
@ -170,13 +166,13 @@ impl SpecializedRenderPipeline for BoxShadowPipeline {
RenderPipelineDescriptor {
vertex: VertexState {
shader: BOX_SHADOW_SHADER_HANDLE,
shader: self.shader.clone(),
entry_point: "vertex".into(),
shader_defs: shader_defs.clone(),
buffers: vec![vertex_layout],
},
fragment: Some(FragmentState {
shader: BOX_SHADOW_SHADER_HANDLE,
shader: self.shader.clone(),
shader_defs,
entry_point: "fragment".into(),
targets: vec![Some(ColorTargetState {

View File

@ -34,19 +34,11 @@ use bytemuck::{Pod, Zeroable};
use super::shader_flags::BORDER_ALL;
pub const UI_GRADIENT_SHADER_HANDLE: Handle<Shader> =
weak_handle!("10116113-aac4-47fa-91c8-35cbe80dddcb");
pub struct GradientPlugin;
impl Plugin for GradientPlugin {
fn build(&self, app: &mut App) {
load_internal_asset!(
app,
UI_GRADIENT_SHADER_HANDLE,
"gradient.wgsl",
Shader::from_wgsl
);
embedded_asset!(app, "gradient.wgsl");
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
render_app
@ -103,6 +95,7 @@ impl Default for GradientMeta {
#[derive(Resource)]
pub struct GradientPipeline {
pub view_layout: BindGroupLayout,
pub shader: Handle<Shader>,
}
impl FromWorld for GradientPipeline {
@ -117,7 +110,10 @@ impl FromWorld for GradientPipeline {
),
);
GradientPipeline { view_layout }
GradientPipeline {
view_layout,
shader: load_embedded_asset!(world, "gradient.wgsl"),
}
}
}
@ -192,13 +188,13 @@ impl SpecializedRenderPipeline for GradientPipeline {
RenderPipelineDescriptor {
vertex: VertexState {
shader: UI_GRADIENT_SHADER_HANDLE,
shader: self.shader.clone(),
entry_point: "vertex".into(),
shader_defs: shader_defs.clone(),
buffers: vec![vertex_layout],
},
fragment: Some(FragmentState {
shader: UI_GRADIENT_SHADER_HANDLE,
shader: self.shader.clone(),
shader_defs,
entry_point: "fragment".into(),
targets: vec![Some(ColorTargetState {

View File

@ -14,7 +14,7 @@ use crate::{
ComputedNodeTarget, Outline, ResolvedBorderRadius, TextShadow, UiAntiAlias,
};
use bevy_app::prelude::*;
use bevy_asset::{load_internal_asset, weak_handle, AssetEvent, AssetId, Assets, Handle};
use bevy_asset::{AssetEvent, AssetId, Assets};
use bevy_color::{Alpha, ColorToComponents, LinearRgba};
use bevy_core_pipeline::core_2d::graph::{Core2d, Node2d};
use bevy_core_pipeline::core_3d::graph::{Core3d, Node3d};
@ -23,6 +23,7 @@ use bevy_ecs::prelude::*;
use bevy_ecs::system::SystemParam;
use bevy_image::prelude::*;
use bevy_math::{FloatOrd, Mat4, Rect, UVec4, Vec2, Vec3, Vec3Swizzles, Vec4Swizzles};
use bevy_render::load_shader_library;
use bevy_render::render_graph::{NodeRunError, RenderGraphContext};
use bevy_render::render_phase::ViewSortedRenderPhases;
use bevy_render::renderer::RenderContext;
@ -100,8 +101,6 @@ pub mod stack_z_offsets {
pub const MATERIAL: f32 = 0.18267;
}
pub const UI_SHADER_HANDLE: Handle<Shader> = weak_handle!("7d190d05-545b-42f5-bd85-22a0da85b0f6");
#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)]
pub enum RenderUiSystems {
ExtractCameraViews,
@ -123,7 +122,7 @@ pub enum RenderUiSystems {
pub type RenderUiSystem = RenderUiSystems;
pub fn build_ui_render(app: &mut App) {
load_internal_asset!(app, UI_SHADER_HANDLE, "ui.wgsl", Shader::from_wgsl);
load_shader_library!(app, "ui.wgsl");
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
return;

View File

@ -1,3 +1,4 @@
use bevy_asset::{load_embedded_asset, Handle};
use bevy_ecs::prelude::*;
use bevy_image::BevyDefault as _;
use bevy_render::{
@ -13,6 +14,7 @@ use bevy_render::{
pub struct UiPipeline {
pub view_layout: BindGroupLayout,
pub image_layout: BindGroupLayout,
pub shader: Handle<Shader>,
}
impl FromWorld for UiPipeline {
@ -41,6 +43,7 @@ impl FromWorld for UiPipeline {
UiPipeline {
view_layout,
image_layout,
shader: load_embedded_asset!(world, "ui.wgsl"),
}
}
}
@ -84,13 +87,13 @@ impl SpecializedRenderPipeline for UiPipeline {
RenderPipelineDescriptor {
vertex: VertexState {
shader: super::UI_SHADER_HANDLE,
shader: self.shader.clone(),
entry_point: "vertex".into(),
shader_defs: shader_defs.clone(),
buffers: vec![vertex_layout],
},
fragment: Some(FragmentState {
shader: super::UI_SHADER_HANDLE,
shader: self.shader.clone(),
shader_defs,
entry_point: "fragment".into(),
targets: vec![Some(ColorTargetState {

View File

@ -12,7 +12,6 @@ use bevy_ecs::{
};
use bevy_image::BevyDefault as _;
use bevy_math::{FloatOrd, Mat4, Rect, Vec2, Vec4Swizzles};
use bevy_render::sync_world::{MainEntity, TemporaryRenderEntity};
use bevy_render::{
extract_component::ExtractComponentPlugin,
globals::{GlobalsBuffer, GlobalsUniform},
@ -23,16 +22,14 @@ use bevy_render::{
view::*,
Extract, ExtractSchedule, Render, RenderSystems,
};
use bevy_render::{
load_shader_library,
sync_world::{MainEntity, TemporaryRenderEntity},
};
use bevy_sprite::BorderRect;
use bevy_transform::prelude::GlobalTransform;
use bytemuck::{Pod, Zeroable};
pub const UI_MATERIAL_SHADER_HANDLE: Handle<Shader> =
weak_handle!("b5612b7b-aed5-41b4-a930-1d1588239fcd");
const UI_VERTEX_OUTPUT_SHADER_HANDLE: Handle<Shader> =
weak_handle!("1d97ca3e-eaa8-4bc5-a676-e8e9568c472e");
/// Adds the necessary ECS resources and render logic to enable rendering entities using the given
/// [`UiMaterial`] asset type (which includes [`UiMaterial`] types).
pub struct UiMaterialPlugin<M: UiMaterial>(PhantomData<M>);
@ -48,18 +45,10 @@ where
M::Data: PartialEq + Eq + Hash + Clone,
{
fn build(&self, app: &mut App) {
load_internal_asset!(
app,
UI_VERTEX_OUTPUT_SHADER_HANDLE,
"ui_vertex_output.wgsl",
Shader::from_wgsl
);
load_internal_asset!(
app,
UI_MATERIAL_SHADER_HANDLE,
"ui_material.wgsl",
Shader::from_wgsl
);
load_shader_library!(app, "ui_vertex_output.wgsl");
embedded_asset!(app, "ui_material.wgsl");
app.init_asset::<M>()
.register_type::<MaterialNode<M>>()
.add_plugins((
@ -135,8 +124,8 @@ pub struct UiMaterialBatch<M: UiMaterial> {
pub struct UiMaterialPipeline<M: UiMaterial> {
pub ui_layout: BindGroupLayout,
pub view_layout: BindGroupLayout,
pub vertex_shader: Option<Handle<Shader>>,
pub fragment_shader: Option<Handle<Shader>>,
pub vertex_shader: Handle<Shader>,
pub fragment_shader: Handle<Shader>,
marker: PhantomData<M>,
}
@ -166,13 +155,13 @@ where
let mut descriptor = RenderPipelineDescriptor {
vertex: VertexState {
shader: UI_MATERIAL_SHADER_HANDLE,
shader: self.vertex_shader.clone(),
entry_point: "vertex".into(),
shader_defs: shader_defs.clone(),
buffers: vec![vertex_layout],
},
fragment: Some(FragmentState {
shader: UI_MATERIAL_SHADER_HANDLE,
shader: self.fragment_shader.clone(),
shader_defs,
entry_point: "fragment".into(),
targets: vec![Some(ColorTargetState {
@ -205,13 +194,6 @@ where
label: Some("ui_material_pipeline".into()),
zero_initialize_workgroup_memory: false,
};
if let Some(vertex_shader) = &self.vertex_shader {
descriptor.vertex.shader = vertex_shader.clone();
}
if let Some(fragment_shader) = &self.fragment_shader {
descriptor.fragment.as_mut().unwrap().shader = fragment_shader.clone();
}
descriptor.layout = vec![self.view_layout.clone(), self.ui_layout.clone()];
@ -238,18 +220,20 @@ impl<M: UiMaterial> FromWorld for UiMaterialPipeline<M> {
),
);
let load_default = || load_embedded_asset!(asset_server, "ui_material.wgsl");
UiMaterialPipeline {
ui_layout,
view_layout,
vertex_shader: match M::vertex_shader() {
ShaderRef::Default => None,
ShaderRef::Handle(handle) => Some(handle),
ShaderRef::Path(path) => Some(asset_server.load(path)),
ShaderRef::Default => load_default(),
ShaderRef::Handle(handle) => handle,
ShaderRef::Path(path) => asset_server.load(path),
},
fragment_shader: match M::fragment_shader() {
ShaderRef::Default => None,
ShaderRef::Handle(handle) => Some(handle),
ShaderRef::Path(path) => Some(asset_server.load(path)),
ShaderRef::Default => load_default(),
ShaderRef::Handle(handle) => handle,
ShaderRef::Path(path) => asset_server.load(path),
},
marker: PhantomData,
}

View File

@ -30,19 +30,11 @@ use binding_types::{sampler, texture_2d};
use bytemuck::{Pod, Zeroable};
use widget::ImageNode;
pub const UI_SLICER_SHADER_HANDLE: Handle<Shader> =
weak_handle!("10cd61e3-bbf7-47fa-91c8-16cbe806378c");
pub struct UiTextureSlicerPlugin;
impl Plugin for UiTextureSlicerPlugin {
fn build(&self, app: &mut App) {
load_internal_asset!(
app,
UI_SLICER_SHADER_HANDLE,
"ui_texture_slice.wgsl",
Shader::from_wgsl
);
embedded_asset!(app, "ui_texture_slice.wgsl");
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
render_app
@ -116,6 +108,7 @@ pub struct UiTextureSliceImageBindGroups {
pub struct UiTextureSlicePipeline {
pub view_layout: BindGroupLayout,
pub image_layout: BindGroupLayout,
pub shader: Handle<Shader>,
}
impl FromWorld for UiTextureSlicePipeline {
@ -144,6 +137,7 @@ impl FromWorld for UiTextureSlicePipeline {
UiTextureSlicePipeline {
view_layout,
image_layout,
shader: load_embedded_asset!(world, "ui_texture_slice.wgsl"),
}
}
}
@ -180,13 +174,13 @@ impl SpecializedRenderPipeline for UiTextureSlicePipeline {
RenderPipelineDescriptor {
vertex: VertexState {
shader: UI_SLICER_SHADER_HANDLE,
shader: self.shader.clone(),
entry_point: "vertex".into(),
shader_defs: shader_defs.clone(),
buffers: vec![vertex_layout],
},
fragment: Some(FragmentState {
shader: UI_SLICER_SHADER_HANDLE,
shader: self.shader.clone(),
shader_defs,
entry_point: "fragment".into(),
targets: vec![Some(ColorTargetState {