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::{
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),

View file

@ -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<RenderPipeline>,
pub(crate) cached_pipelines: Vec<(
MultisampleState,
Option<DepthStencilState>,
Arc<RenderPipeline>,
)>,
pub(crate) bind_group: Arc<BindGroup>,
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<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,
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<CacheKey>,
screen_resolution: Resolution,
pipeline: Arc<RenderPipeline>,
}
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<DepthStencilState>,
) -> 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);