mod constructor;
mod execute;
mod prepare;
use crate::ecs::world::World;
use crate::render::wgpu::rendergraph::{PassExecutionContext, PassNode};
use nalgebra_glm::Mat4;
const INITIAL_RECT_CAPACITY: usize = 4096;
const INITIAL_TEXT_VERTEX_CAPACITY: usize = 64000;
const INITIAL_TEXT_INDEX_CAPACITY: usize = 96000;
const INITIAL_TEXT_INSTANCE_CAPACITY: usize = 1024;
const INITIAL_CHARACTER_COLOR_CAPACITY: usize = 10000;
#[repr(C)]
#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
struct UiRectInstance {
position_size: [f32; 4],
color: [f32; 4],
border_color: [f32; 4],
clip_rect: [f32; 4],
params: [f32; 4],
}
#[repr(C)]
#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
struct TextInstanceData {
color: [f32; 4],
outline_color: [f32; 4],
clip_rect: [f32; 4],
params: [f32; 4],
}
#[repr(C)]
#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
struct UiPassVertex {
position: [f32; 2],
}
#[repr(C)]
#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
struct UiTextVertex {
position: [f32; 3],
tex_coords: [f32; 2],
character_index: u32,
text_instance_index: u32,
_padding: u32,
}
#[repr(C)]
#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
struct GlobalUniforms {
projection: Mat4,
}
struct TextDrawCall {
font_index: usize,
index_start: u32,
index_count: u32,
layer: super::UiLayer,
}
struct LayerDrawGroup {
rect_start: u32,
rect_count: u32,
text_draw_start: usize,
text_draw_count: usize,
}
struct TextBuildEntry {
font_index: usize,
index_offset: u32,
index_count: u32,
layer: super::UiLayer,
}
pub struct UiPass {
rect_pipeline: wgpu::RenderPipeline,
text_pipeline: wgpu::RenderPipeline,
text_pipeline_subpixel: wgpu::RenderPipeline,
use_subpixel: bool,
global_uniform_buffer: wgpu::Buffer,
global_uniform_bind_group: wgpu::BindGroup,
rect_quad_vertex_buffer: wgpu::Buffer,
rect_quad_index_buffer: wgpu::Buffer,
rect_instance_buffer: wgpu::Buffer,
rect_instance_bind_group_layout: wgpu::BindGroupLayout,
rect_instance_bind_group: wgpu::BindGroup,
rect_instance_capacity: usize,
rect_count: u32,
text_vertex_buffer: wgpu::Buffer,
text_index_buffer: wgpu::Buffer,
text_instance_buffer: wgpu::Buffer,
character_color_buffer: wgpu::Buffer,
character_bg_color_buffer: wgpu::Buffer,
text_data_bind_group_layout: wgpu::BindGroupLayout,
text_data_bind_group: wgpu::BindGroup,
text_font_bind_group_layout: wgpu::BindGroupLayout,
text_font_bind_groups: Vec<wgpu::BindGroup>,
_text_global_bind_group_layout: wgpu::BindGroupLayout,
text_global_bind_group: wgpu::BindGroup,
text_vertex_capacity: usize,
text_index_capacity: usize,
text_instance_capacity: usize,
character_color_capacity: usize,
character_bg_color_capacity: usize,
text_draw_calls: Vec<TextDrawCall>,
layer_draw_groups: Vec<LayerDrawGroup>,
cached_font_texture_views: Vec<wgpu::TextureView>,
screen_width: f32,
screen_height: f32,
}
impl PassNode<World> for UiPass {
fn name(&self) -> &'static str {
"ui_pass"
}
fn reads(&self) -> Vec<&str> {
vec![]
}
fn writes(&self) -> Vec<&str> {
vec![]
}
fn reads_writes(&self) -> Vec<&str> {
vec!["color", "depth"]
}
fn prepare(&mut self, device: &wgpu::Device, queue: &wgpu::Queue, world: &World) {
self.prepare_pass(device, queue, world);
}
fn execute<'r, 'e>(
&mut self,
context: PassExecutionContext<'r, 'e, World>,
) -> Result<
Vec<crate::render::wgpu::rendergraph::SubGraphRunCommand<'r>>,
crate::render::wgpu::rendergraph::RenderGraphError,
> {
self.execute_pass(context)
}
}