use bevy_ecs::prelude::*;
use bevy_render::{
render_resource::{
binding_types::{sampler, texture_2d, uniform_buffer},
*,
},
renderer::RenderDevice,
texture::BevyDefault,
view::{ViewTarget, ViewUniform},
};
#[derive(Resource)]
pub struct UiPipeline {
pub view_layout: BindGroupLayout,
pub image_layout: BindGroupLayout,
}
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,
}
}
}
#[derive(Clone, Copy, Hash, PartialEq, Eq)]
pub struct UiPipelineKey {
pub hdr: 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![
VertexFormat::Float32x3,
VertexFormat::Float32x2,
VertexFormat::Float32x4,
VertexFormat::Uint32,
],
);
let shader_defs = Vec::new();
RenderPipelineDescriptor {
vertex: VertexState {
shader: super::UI_SHADER_HANDLE,
entry_point: "vertex".into(),
shader_defs: shader_defs.clone(),
buffers: vec![vertex_layout],
},
fragment: Some(FragmentState {
shader: super::UI_SHADER_HANDLE,
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()),
}
}
}