From 74e9aa37a10c393e0a15a482ed321a0bbd110641 Mon Sep 17 00:00:00 2001 From: grovesNL Date: Mon, 13 Feb 2023 22:35:04 -0330 Subject: [PATCH] Set renderer multisample and depth-stencil state --- examples/hello-world.rs | 9 ++-- src/text_atlas.rs | 94 ++++++++++++++++++++++++++--------------- src/text_render.rs | 20 ++++++--- 3 files changed, 80 insertions(+), 43 deletions(-) diff --git a/examples/hello-world.rs b/examples/hello-world.rs index cc7f3c5..cea61c0 100644 --- a/examples/hello-world.rs +++ b/examples/hello-world.rs @@ -4,9 +4,9 @@ use glyphon::{ }; use wgpu::{ Backends, CommandEncoderDescriptor, CompositeAlphaMode, DeviceDescriptor, Features, Instance, - Limits, LoadOp, Operations, PresentMode, RenderPassColorAttachment, RenderPassDescriptor, - RequestAdapterOptions, SurfaceConfiguration, TextureFormat, TextureUsages, - TextureViewDescriptor, + Limits, LoadOp, MultisampleState, Operations, PresentMode, RenderPassColorAttachment, + RenderPassDescriptor, RequestAdapterOptions, SurfaceConfiguration, TextureFormat, + TextureUsages, TextureViewDescriptor, }; use winit::{ dpi::LogicalSize, @@ -64,12 +64,13 @@ async fn run() { surface.configure(&device, &config); // Set up text renderer - let mut text_renderer = TextRenderer::new(&device, &queue); unsafe { FONT_SYSTEM = Some(FontSystem::new()); } let mut cache = SwashCache::new(unsafe { FONT_SYSTEM.as_ref().unwrap() }); let mut atlas = TextAtlas::new(&device, &queue, swapchain_format); + let mut text_renderer = + TextRenderer::new(&mut atlas, &device, MultisampleState::default(), None); let mut buffer = Buffer::new( unsafe { FONT_SYSTEM.as_ref().unwrap() }, Metrics::new(30, 42), diff --git a/src/text_atlas.rs b/src/text_atlas.rs index 46f6a4a..ea18a3f 100644 --- a/src/text_atlas.rs +++ b/src/text_atlas.rs @@ -5,11 +5,12 @@ use std::{borrow::Cow, mem::size_of, num::NonZeroU64, sync::Arc}; use wgpu::{ BindGroup, BindGroupDescriptor, BindGroupEntry, BindGroupLayoutEntry, BindingResource, BindingType, BlendState, Buffer, BufferBindingType, BufferDescriptor, BufferUsages, - ColorTargetState, ColorWrites, Device, Extent3d, FilterMode, FragmentState, MultisampleState, - PipelineLayoutDescriptor, PrimitiveState, Queue, RenderPipeline, RenderPipelineDescriptor, - SamplerBindingType, SamplerDescriptor, ShaderModuleDescriptor, ShaderSource, ShaderStages, - Texture, TextureDescriptor, TextureDimension, TextureFormat, TextureSampleType, TextureUsages, - TextureView, TextureViewDescriptor, TextureViewDimension, VertexFormat, VertexState, + ColorTargetState, ColorWrites, DepthStencilState, Device, Extent3d, FilterMode, FragmentState, + MultisampleState, PipelineLayout, PipelineLayoutDescriptor, PrimitiveState, Queue, + RenderPipeline, RenderPipelineDescriptor, SamplerBindingType, SamplerDescriptor, ShaderModule, + ShaderModuleDescriptor, ShaderSource, ShaderStages, Texture, TextureDescriptor, + TextureDimension, TextureFormat, TextureSampleType, TextureUsages, TextureView, + TextureViewDescriptor, TextureViewDimension, VertexFormat, VertexState, }; pub(crate) struct InnerAtlas { @@ -88,10 +89,18 @@ impl InnerAtlas { pub struct TextAtlas { pub(crate) params: Params, pub(crate) params_buffer: Buffer, - pub(crate) pipeline: Arc, + pub(crate) cached_pipelines: Vec<( + MultisampleState, + Option, + Arc, + )>, pub(crate) bind_group: Arc, pub(crate) color_atlas: InnerAtlas, pub(crate) mask_atlas: InnerAtlas, + pub(crate) pipeline_layout: PipelineLayout, + pub(crate) shader: ShaderModule, + pub(crate) vertex_buffers: [wgpu::VertexBufferLayout<'static>; 1], + pub(crate) format: TextureFormat, } impl TextAtlas { @@ -234,40 +243,17 @@ impl TextAtlas { push_constant_ranges: &[], }); - let pipeline = Arc::new(device.create_render_pipeline(&RenderPipelineDescriptor { - label: Some("glyphon pipeline"), - layout: Some(&pipeline_layout), - vertex: VertexState { - module: &shader, - entry_point: "vs_main", - buffers: &vertex_buffers, - }, - fragment: Some(FragmentState { - module: &shader, - entry_point: "fs_main", - targets: &[Some(ColorTargetState { - format, - blend: Some(BlendState::ALPHA_BLENDING), - write_mask: ColorWrites::default(), - })], - }), - primitive: PrimitiveState::default(), - depth_stencil: None, - multisample: MultisampleState { - count: 1, - mask: !0, - alpha_to_coverage_enabled: false, - }, - multiview: None, - })); - Self { params, params_buffer, - pipeline, + cached_pipelines: Vec::new(), bind_group, color_atlas, mask_atlas, + pipeline_layout, + shader, + vertex_buffers, + format, } } @@ -295,4 +281,44 @@ impl TextAtlas { ContentType::Mask => &mut self.mask_atlas, } } + + pub(crate) fn get_or_create_pipeline( + &mut self, + device: &Device, + multisample: MultisampleState, + depth_stencil: Option, + ) -> Arc { + self.cached_pipelines + .iter() + .find(|(ms, ds, _)| ms == &multisample && ds == &depth_stencil) + .map(|(_, _, p)| Arc::clone(p)) + .unwrap_or_else(|| { + let pipeline = Arc::new(device.create_render_pipeline(&RenderPipelineDescriptor { + label: Some("glyphon pipeline"), + layout: Some(&self.pipeline_layout), + vertex: VertexState { + module: &self.shader, + entry_point: "vs_main", + buffers: &self.vertex_buffers, + }, + fragment: Some(FragmentState { + module: &self.shader, + entry_point: "fs_main", + targets: &[Some(ColorTargetState { + format: self.format, + blend: Some(BlendState::ALPHA_BLENDING), + write_mask: ColorWrites::default(), + })], + }), + primitive: PrimitiveState::default(), + depth_stencil: depth_stencil.clone(), + multisample, + multiview: None, + })); + + self.cached_pipelines + .push((multisample, depth_stencil, pipeline.clone())); + pipeline + }) + } } diff --git a/src/text_render.rs b/src/text_render.rs index 2de59d6..c8ba554 100644 --- a/src/text_render.rs +++ b/src/text_render.rs @@ -2,10 +2,11 @@ use crate::{ CacheKey, Color, GlyphDetails, GlyphToRender, GpuCacheStatus, Params, PrepareError, RenderError, Resolution, SwashCache, SwashContent, TextArea, TextAtlas, }; -use std::{collections::HashSet, iter, mem::size_of, num::NonZeroU32, slice}; +use std::{collections::HashSet, iter, mem::size_of, num::NonZeroU32, slice, sync::Arc}; use wgpu::{ - Buffer, BufferDescriptor, BufferUsages, Device, Extent3d, ImageCopyTexture, ImageDataLayout, - IndexFormat, Origin3d, Queue, RenderPass, TextureAspect, COPY_BUFFER_ALIGNMENT, + Buffer, BufferDescriptor, BufferUsages, DepthStencilState, Device, Extent3d, ImageCopyTexture, + ImageDataLayout, IndexFormat, MultisampleState, Origin3d, Queue, RenderPass, RenderPipeline, + TextureAspect, COPY_BUFFER_ALIGNMENT, }; /// A text renderer that uses cached glyphs to render text into an existing render pass. @@ -17,11 +18,17 @@ pub struct TextRenderer { vertices_to_render: u32, glyphs_in_use: HashSet, screen_resolution: Resolution, + pipeline: Arc, } impl TextRenderer { /// Creates a new `TextRenderer`. - pub fn new(device: &Device, _queue: &Queue) -> Self { + pub fn new( + atlas: &mut TextAtlas, + device: &Device, + multisample: MultisampleState, + depth_stencil: Option, + ) -> Self { let vertex_buffer_size = next_copy_buffer_size(4096); let vertex_buffer = device.create_buffer(&BufferDescriptor { label: Some("glyphon vertices"), @@ -38,6 +45,8 @@ impl TextRenderer { mapped_at_creation: false, }); + let pipeline = atlas.get_or_create_pipeline(device, multisample, depth_stencil); + Self { vertex_buffer, vertex_buffer_size, @@ -49,6 +58,7 @@ impl TextRenderer { width: 0, height: 0, }, + pipeline, } } @@ -420,7 +430,7 @@ impl TextRenderer { } } - pass.set_pipeline(&atlas.pipeline); + pass.set_pipeline(&self.pipeline); pass.set_bind_group(0, &atlas.bind_group, &[]); pass.set_vertex_buffer(0, self.vertex_buffer.slice(..)); pass.set_index_buffer(self.index_buffer.slice(..), IndexFormat::Uint32);