
# 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.
131 lines
4.1 KiB
Rust
131 lines
4.1 KiB
Rust
use bevy_asset::{load_embedded_asset, Handle};
|
|
use bevy_ecs::prelude::*;
|
|
use bevy_image::BevyDefault as _;
|
|
use bevy_render::{
|
|
render_resource::{
|
|
binding_types::{sampler, texture_2d, uniform_buffer},
|
|
*,
|
|
},
|
|
renderer::RenderDevice,
|
|
view::{ViewTarget, ViewUniform},
|
|
};
|
|
|
|
#[derive(Resource)]
|
|
pub struct UiPipeline {
|
|
pub view_layout: BindGroupLayout,
|
|
pub image_layout: BindGroupLayout,
|
|
pub shader: Handle<Shader>,
|
|
}
|
|
|
|
impl FromWorld for UiPipeline {
|
|
fn from_world(world: &mut World) -> Self {
|
|
let render_device = world.resource::<RenderDevice>();
|
|
|
|
let view_layout = render_device.create_bind_group_layout(
|
|
"ui_view_layout",
|
|
&BindGroupLayoutEntries::single(
|
|
ShaderStages::VERTEX_FRAGMENT,
|
|
uniform_buffer::<ViewUniform>(true),
|
|
),
|
|
);
|
|
|
|
let image_layout = render_device.create_bind_group_layout(
|
|
"ui_image_layout",
|
|
&BindGroupLayoutEntries::sequential(
|
|
ShaderStages::FRAGMENT,
|
|
(
|
|
texture_2d(TextureSampleType::Float { filterable: true }),
|
|
sampler(SamplerBindingType::Filtering),
|
|
),
|
|
),
|
|
);
|
|
|
|
UiPipeline {
|
|
view_layout,
|
|
image_layout,
|
|
shader: load_embedded_asset!(world, "ui.wgsl"),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Copy, Hash, PartialEq, Eq)]
|
|
pub struct UiPipelineKey {
|
|
pub hdr: bool,
|
|
pub anti_alias: bool,
|
|
}
|
|
|
|
impl SpecializedRenderPipeline for UiPipeline {
|
|
type Key = UiPipelineKey;
|
|
|
|
fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor {
|
|
let vertex_layout = VertexBufferLayout::from_vertex_formats(
|
|
VertexStepMode::Vertex,
|
|
vec![
|
|
// position
|
|
VertexFormat::Float32x3,
|
|
// uv
|
|
VertexFormat::Float32x2,
|
|
// color
|
|
VertexFormat::Float32x4,
|
|
// mode
|
|
VertexFormat::Uint32,
|
|
// border radius
|
|
VertexFormat::Float32x4,
|
|
// border thickness
|
|
VertexFormat::Float32x4,
|
|
// border size
|
|
VertexFormat::Float32x2,
|
|
// position relative to the center
|
|
VertexFormat::Float32x2,
|
|
],
|
|
);
|
|
let shader_defs = if key.anti_alias {
|
|
vec!["ANTI_ALIAS".into()]
|
|
} else {
|
|
Vec::new()
|
|
};
|
|
|
|
RenderPipelineDescriptor {
|
|
vertex: VertexState {
|
|
shader: self.shader.clone(),
|
|
entry_point: "vertex".into(),
|
|
shader_defs: shader_defs.clone(),
|
|
buffers: vec![vertex_layout],
|
|
},
|
|
fragment: Some(FragmentState {
|
|
shader: self.shader.clone(),
|
|
shader_defs,
|
|
entry_point: "fragment".into(),
|
|
targets: vec![Some(ColorTargetState {
|
|
format: if key.hdr {
|
|
ViewTarget::TEXTURE_FORMAT_HDR
|
|
} else {
|
|
TextureFormat::bevy_default()
|
|
},
|
|
blend: Some(BlendState::ALPHA_BLENDING),
|
|
write_mask: ColorWrites::ALL,
|
|
})],
|
|
}),
|
|
layout: vec![self.view_layout.clone(), self.image_layout.clone()],
|
|
push_constant_ranges: Vec::new(),
|
|
primitive: PrimitiveState {
|
|
front_face: FrontFace::Ccw,
|
|
cull_mode: None,
|
|
unclipped_depth: false,
|
|
polygon_mode: PolygonMode::Fill,
|
|
conservative: false,
|
|
topology: PrimitiveTopology::TriangleList,
|
|
strip_index_format: None,
|
|
},
|
|
depth_stencil: None,
|
|
multisample: MultisampleState {
|
|
count: 1,
|
|
mask: !0,
|
|
alpha_to_coverage_enabled: false,
|
|
},
|
|
label: Some("ui_pipeline".into()),
|
|
zero_initialize_workgroup_memory: false,
|
|
}
|
|
}
|
|
}
|