Set renderer multisample and depth-stencil state

This commit is contained in:
grovesNL 2023-02-13 22:35:04 -03:30 committed by Josh Groves
parent da4bb4af5c
commit 74e9aa37a1
3 changed files with 80 additions and 43 deletions

View file

@ -4,9 +4,9 @@ use glyphon::{
}; };
use wgpu::{ use wgpu::{
Backends, CommandEncoderDescriptor, CompositeAlphaMode, DeviceDescriptor, Features, Instance, Backends, CommandEncoderDescriptor, CompositeAlphaMode, DeviceDescriptor, Features, Instance,
Limits, LoadOp, Operations, PresentMode, RenderPassColorAttachment, RenderPassDescriptor, Limits, LoadOp, MultisampleState, Operations, PresentMode, RenderPassColorAttachment,
RequestAdapterOptions, SurfaceConfiguration, TextureFormat, TextureUsages, RenderPassDescriptor, RequestAdapterOptions, SurfaceConfiguration, TextureFormat,
TextureViewDescriptor, TextureUsages, TextureViewDescriptor,
}; };
use winit::{ use winit::{
dpi::LogicalSize, dpi::LogicalSize,
@ -64,12 +64,13 @@ async fn run() {
surface.configure(&device, &config); surface.configure(&device, &config);
// Set up text renderer // Set up text renderer
let mut text_renderer = TextRenderer::new(&device, &queue);
unsafe { unsafe {
FONT_SYSTEM = Some(FontSystem::new()); FONT_SYSTEM = Some(FontSystem::new());
} }
let mut cache = SwashCache::new(unsafe { FONT_SYSTEM.as_ref().unwrap() }); let mut cache = SwashCache::new(unsafe { FONT_SYSTEM.as_ref().unwrap() });
let mut atlas = TextAtlas::new(&device, &queue, swapchain_format); 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( let mut buffer = Buffer::new(
unsafe { FONT_SYSTEM.as_ref().unwrap() }, unsafe { FONT_SYSTEM.as_ref().unwrap() },
Metrics::new(30, 42), Metrics::new(30, 42),

View file

@ -5,11 +5,12 @@ use std::{borrow::Cow, mem::size_of, num::NonZeroU64, sync::Arc};
use wgpu::{ use wgpu::{
BindGroup, BindGroupDescriptor, BindGroupEntry, BindGroupLayoutEntry, BindingResource, BindGroup, BindGroupDescriptor, BindGroupEntry, BindGroupLayoutEntry, BindingResource,
BindingType, BlendState, Buffer, BufferBindingType, BufferDescriptor, BufferUsages, BindingType, BlendState, Buffer, BufferBindingType, BufferDescriptor, BufferUsages,
ColorTargetState, ColorWrites, Device, Extent3d, FilterMode, FragmentState, MultisampleState, ColorTargetState, ColorWrites, DepthStencilState, Device, Extent3d, FilterMode, FragmentState,
PipelineLayoutDescriptor, PrimitiveState, Queue, RenderPipeline, RenderPipelineDescriptor, MultisampleState, PipelineLayout, PipelineLayoutDescriptor, PrimitiveState, Queue,
SamplerBindingType, SamplerDescriptor, ShaderModuleDescriptor, ShaderSource, ShaderStages, RenderPipeline, RenderPipelineDescriptor, SamplerBindingType, SamplerDescriptor, ShaderModule,
Texture, TextureDescriptor, TextureDimension, TextureFormat, TextureSampleType, TextureUsages, ShaderModuleDescriptor, ShaderSource, ShaderStages, Texture, TextureDescriptor,
TextureView, TextureViewDescriptor, TextureViewDimension, VertexFormat, VertexState, TextureDimension, TextureFormat, TextureSampleType, TextureUsages, TextureView,
TextureViewDescriptor, TextureViewDimension, VertexFormat, VertexState,
}; };
pub(crate) struct InnerAtlas { pub(crate) struct InnerAtlas {
@ -88,10 +89,18 @@ impl InnerAtlas {
pub struct TextAtlas { pub struct TextAtlas {
pub(crate) params: Params, pub(crate) params: Params,
pub(crate) params_buffer: Buffer, pub(crate) params_buffer: Buffer,
pub(crate) pipeline: Arc<RenderPipeline>, pub(crate) cached_pipelines: Vec<(
MultisampleState,
Option<DepthStencilState>,
Arc<RenderPipeline>,
)>,
pub(crate) bind_group: Arc<BindGroup>, pub(crate) bind_group: Arc<BindGroup>,
pub(crate) color_atlas: InnerAtlas, pub(crate) color_atlas: InnerAtlas,
pub(crate) mask_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 { impl TextAtlas {
@ -234,40 +243,17 @@ impl TextAtlas {
push_constant_ranges: &[], 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 { Self {
params, params,
params_buffer, params_buffer,
pipeline, cached_pipelines: Vec::new(),
bind_group, bind_group,
color_atlas, color_atlas,
mask_atlas, mask_atlas,
pipeline_layout,
shader,
vertex_buffers,
format,
} }
} }
@ -295,4 +281,44 @@ impl TextAtlas {
ContentType::Mask => &mut self.mask_atlas, ContentType::Mask => &mut self.mask_atlas,
} }
} }
pub(crate) fn get_or_create_pipeline(
&mut self,
device: &Device,
multisample: MultisampleState,
depth_stencil: Option<DepthStencilState>,
) -> Arc<RenderPipeline> {
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
})
}
} }

View file

@ -2,10 +2,11 @@ use crate::{
CacheKey, Color, GlyphDetails, GlyphToRender, GpuCacheStatus, Params, PrepareError, CacheKey, Color, GlyphDetails, GlyphToRender, GpuCacheStatus, Params, PrepareError,
RenderError, Resolution, SwashCache, SwashContent, TextArea, TextAtlas, 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::{ use wgpu::{
Buffer, BufferDescriptor, BufferUsages, Device, Extent3d, ImageCopyTexture, ImageDataLayout, Buffer, BufferDescriptor, BufferUsages, DepthStencilState, Device, Extent3d, ImageCopyTexture,
IndexFormat, Origin3d, Queue, RenderPass, TextureAspect, COPY_BUFFER_ALIGNMENT, 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. /// 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, vertices_to_render: u32,
glyphs_in_use: HashSet<CacheKey>, glyphs_in_use: HashSet<CacheKey>,
screen_resolution: Resolution, screen_resolution: Resolution,
pipeline: Arc<RenderPipeline>,
} }
impl TextRenderer { impl TextRenderer {
/// Creates a new `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<DepthStencilState>,
) -> Self {
let vertex_buffer_size = next_copy_buffer_size(4096); let vertex_buffer_size = next_copy_buffer_size(4096);
let vertex_buffer = device.create_buffer(&BufferDescriptor { let vertex_buffer = device.create_buffer(&BufferDescriptor {
label: Some("glyphon vertices"), label: Some("glyphon vertices"),
@ -38,6 +45,8 @@ impl TextRenderer {
mapped_at_creation: false, mapped_at_creation: false,
}); });
let pipeline = atlas.get_or_create_pipeline(device, multisample, depth_stencil);
Self { Self {
vertex_buffer, vertex_buffer,
vertex_buffer_size, vertex_buffer_size,
@ -49,6 +58,7 @@ impl TextRenderer {
width: 0, width: 0,
height: 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_bind_group(0, &atlas.bind_group, &[]);
pass.set_vertex_buffer(0, self.vertex_buffer.slice(..)); pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
pass.set_index_buffer(self.index_buffer.slice(..), IndexFormat::Uint32); pass.set_index_buffer(self.index_buffer.slice(..), IndexFormat::Uint32);