use ahash::{HashMap, HashMapExt};
use lyon::tessellation::FillTessellator;
use std::num::NonZeroUsize;
use std::sync::{Arc, RwLock};
use std::time::Duration;
use tracing::warn;
use wgpu::{BindGroup, BufferUsages, CompositeAlphaMode, SurfaceTarget};
#[cfg(feature = "render_metrics")]
use self::metrics::RenderLoopMetricsTracker;
use self::types::{DrawCommand, RendererScratch};
use crate::effect::{
self, compile_composite_pipeline, compile_effect_pipeline, create_params_bind_group,
EffectError, EffectInstance, LoadedEffect, OffscreenTexturePool,
};
use crate::pipeline::{
compute_padded_bytes_per_row, create_and_depth_texture, create_argb_swizzle_bind_group,
create_argb_swizzle_pipeline, create_msaa_color_texture, create_offscreen_color_texture,
create_pipeline, create_readback_buffer, create_storage_input_buffer,
create_storage_output_buffer, encode_copy_texture_to_buffer, render_buffer_range_to_texture,
ArgbParams, PipelineType, Uniforms,
};
use crate::shape::{CachedShapeDrawData, DrawShapeCommand, Shape};
use crate::texture_manager::TextureManager;
use crate::util::{to_logical, PoolManager};
use crate::vertex::{InstanceColor, InstanceMetadata, InstanceTransform};
use crate::CachedShapeHandle;
pub use construction::RendererCreationError;
mod construction;
mod draw_queue;
mod effects;
#[cfg(feature = "render_metrics")]
pub mod metrics;
mod passes;
mod preparation;
mod readback;
mod rect_utils;
mod rendering;
mod surface;
mod traversal;
pub(crate) mod types;
pub type MathRect = lyon::math::Box2D;
const MAX_CACHED_SHAPES: usize = 1024;
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub enum TextureLayer {
Background,
Foreground,
}
impl From<TextureLayer> for usize {
fn from(value: TextureLayer) -> Self {
match value {
TextureLayer::Background => 0,
TextureLayer::Foreground => 1,
}
}
}
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Hash)]
pub enum ShapeOverflow {
#[default]
Hidden,
Visible,
}
#[derive(Clone)]
pub struct RendererContext {
pub(crate) inner: Arc<RendererContextInner>,
}
pub(crate) struct RendererContextInner {
pub(crate) instance: Arc<wgpu::Instance>,
pub(crate) adapter: Arc<wgpu::Adapter>,
pub(crate) device: Arc<wgpu::Device>,
pub(crate) queue: Arc<wgpu::Queue>,
pub(crate) texture_manager: TextureManager,
pub(crate) shape_cache: RwLock<HashMap<u64, CachedShapeHandle>>,
}
pub struct Renderer<'a> {
pub(crate) physical_size: (u32, u32),
scale_factor: f64,
fringe_width: f32,
context: RendererContext,
instance: Arc<wgpu::Instance>,
surface: Option<wgpu::Surface<'a>>,
device: Arc<wgpu::Device>,
queue: Arc<wgpu::Queue>,
config: wgpu::SurfaceConfiguration,
tessellator: FillTessellator,
buffers_pool_manager: PoolManager,
texture_manager: TextureManager,
draw_tree: easy_tree::Tree<DrawCommand>,
metadata_to_clips: HashMap<usize, usize>,
and_uniforms: Uniforms,
and_uniform_buffer: wgpu::Buffer,
and_bind_group: BindGroup,
and_pipeline: Arc<wgpu::RenderPipeline>,
shape_texture_bind_group_layout_background: Arc<wgpu::BindGroupLayout>,
shape_texture_bind_group_layout_foreground: Arc<wgpu::BindGroupLayout>,
backdrop_texture_bind_group_layout: Arc<wgpu::BindGroupLayout>,
shape_texture_layout_epoch: u64,
default_shape_texture_bind_groups: [Arc<wgpu::BindGroup>; 2], default_backdrop_texture_bind_group: Arc<wgpu::BindGroup>,
decrementing_pipeline: Arc<wgpu::RenderPipeline>,
decrementing_uniforms: Uniforms,
decrementing_uniform_buffer: wgpu::Buffer,
decrementing_bind_group: BindGroup,
temp_vertices: Vec<crate::vertex::CustomVertex>,
temp_indices: Vec<u16>,
geometry_dedup_map: HashMap<u64, (usize, usize)>,
temp_instance_transforms: Vec<InstanceTransform>,
temp_instance_colors: Vec<InstanceColor>,
temp_instance_metadata: Vec<InstanceMetadata>,
aggregated_vertex_buffer: Option<wgpu::Buffer>,
aggregated_index_buffer: Option<wgpu::Buffer>,
aggregated_instance_transform_buffer: Option<wgpu::Buffer>,
aggregated_instance_color_buffer: Option<wgpu::Buffer>,
aggregated_instance_metadata_buffer: Option<wgpu::Buffer>,
identity_instance_transform_buffer: Option<wgpu::Buffer>,
identity_instance_color_buffer: Option<wgpu::Buffer>,
identity_instance_metadata_buffer: Option<wgpu::Buffer>,
argb_cs_bgl: Option<wgpu::BindGroupLayout>,
argb_cs_pipeline: Option<wgpu::ComputePipeline>,
argb_swizzle_bind_group: Option<wgpu::BindGroup>,
argb_params_buffer: Option<wgpu::Buffer>,
argb_input_buffer: Option<wgpu::Buffer>,
argb_output_storage_buffer: Option<wgpu::Buffer>,
argb_readback_buffer: Option<wgpu::Buffer>,
argb_input_buffer_size: u64,
argb_output_buffer_size: u64,
argb_cached_width: u32,
argb_cached_height: u32,
argb_offscreen_texture: Option<wgpu::Texture>,
rtb_offscreen_texture: Option<wgpu::Texture>,
rtb_readback_buffer: Option<wgpu::Buffer>,
rtb_cached_width: u32,
rtb_cached_height: u32,
msaa_sample_count: u32,
msaa_color_texture: Option<wgpu::Texture>,
msaa_color_texture_view: Option<wgpu::TextureView>,
depth_stencil_texture: Option<wgpu::Texture>,
depth_stencil_view: Option<wgpu::TextureView>,
loaded_effects: HashMap<u64, LoadedEffect>,
group_effects: HashMap<usize, EffectInstance>,
backdrop_effects: HashMap<usize, EffectInstance>,
offscreen_texture_pool: OffscreenTexturePool,
composite_pipeline: Option<wgpu::RenderPipeline>,
composite_bgl: Option<wgpu::BindGroupLayout>,
effect_sampler: Option<wgpu::Sampler>,
texture_blit_pipeline: Option<wgpu::RenderPipeline>,
stencil_only_pipeline: Option<wgpu::RenderPipeline>,
backdrop_color_pipeline: Option<wgpu::RenderPipeline>,
backdrop_color_gradient_pipeline: Option<wgpu::RenderPipeline>,
leaf_draw_pipeline: Arc<wgpu::RenderPipeline>,
leaf_draw_gradient_pipeline: Arc<wgpu::RenderPipeline>,
and_gradient_pipeline: Arc<wgpu::RenderPipeline>,
gradient_bind_group_layout: wgpu::BindGroupLayout,
backdrop_gradient_bind_group_layout: wgpu::BindGroupLayout,
gradient_bind_group_layout_epoch: u64,
gradient_ramp_sampler: wgpu::Sampler,
#[cfg(feature = "render_metrics")]
render_loop_metrics_tracker: RenderLoopMetricsTracker,
#[cfg(feature = "render_metrics")]
last_phase_timings: self::metrics::PhaseTimings,
#[cfg(feature = "render_metrics")]
last_pipeline_switch_counts: self::metrics::PipelineSwitchCounts,
last_render_to_texture_view_cpu_time: Duration,
scratch: RendererScratch,
}
const DEFAULT_FRINGE_WIDTH: f32 = 0.75;
impl<'a> Renderer<'a> {
const DEFAULT_FRINGE_WIDTH: f32 = DEFAULT_FRINGE_WIDTH;
pub(super) fn begin_frame_scratch(&mut self) {
self.scratch.begin_frame();
}
pub(super) fn trim_scratch_on_resize_or_policy(&mut self) {
self.buffers_pool_manager.trim();
self.scratch.trim_to_policy();
}
pub fn last_render_to_texture_view_cpu_time(&self) -> Duration {
self.last_render_to_texture_view_cpu_time
}
}