Upgrade wgpu to 0.15.1 (#250)

* Apply changes for wgpu 0.15

* Add msaa detection

* Enable msaa by default

* Add simplified diagram

* Resolve some unwraps
This commit is contained in:
Max Ammann 2023-04-08 22:54:40 -04:00 committed by GitHub
parent 28573ce470
commit bca19c8ace
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 125 additions and 41 deletions

View File

@ -10,6 +10,10 @@ A simplified version is shown below:
![](./figures/render-stack.drawio.svg)
A further simplified version:
![](./figures/simplified-render-stack.drawio.svg)
Notes:
* wgpu is able to create an interface through which we can reach any device with a GPU.

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -20,8 +20,8 @@ winit = { version = "0.27.2", default-features = false, features = ["x11", "wayl
[target.'cfg(target_arch = "wasm32")'.dependencies]
web-sys = { version = "0.3.58", features = ["Window"] }
wasm-bindgen = "0.2.81"
wasm-bindgen-futures = "0.4.31"
wasm-bindgen = "0.2"
wasm-bindgen-futures = "0.4"
[dependencies]
maplibre = { path = "../maplibre", version = "0.1.0" }

View File

@ -55,7 +55,8 @@ geozero = { version = "0.9.7", default-features = false, features = ["with-mvt",
tile-grid = "0.3.0"
# Rendering
wgpu = "0.14.0"
wgpu = "0.15.0"
# wgpu = { git = "https://github.com/gfx-rs/wgpu" }
lyon = { version = "1.0.0", features = [] }
raw-window-handle = "0.5.0"

View File

@ -46,7 +46,7 @@ pub fn resource_system(
false,
false,
false,
true,
surface.is_multisampling_supported(settings.msaa),
true,
)
.describe_render_pipeline()

View File

@ -6,6 +6,8 @@ use crate::render::graph::RenderGraphError;
pub enum RenderError {
#[error("error in surface")]
Surface(#[from] wgpu::SurfaceError),
#[error("error during surface creation")]
CreateSurfaceError(#[from] wgpu::CreateSurfaceError),
#[error("error in render graph")]
Graph(#[from] RenderGraphError),
#[error("error while requesting device")]

View File

@ -124,11 +124,15 @@ impl RenderResources {
}
}
pub fn recreate_surface<MW>(&mut self, window: &MW, instance: &wgpu::Instance)
pub fn recreate_surface<MW>(
&mut self,
window: &MW,
instance: &wgpu::Instance,
) -> Result<(), RenderError>
where
MW: MapWindow + HeadedMapWindow,
{
self.surface.recreate::<MW>(window, instance);
self.surface.recreate::<MW>(window, instance)
}
pub fn surface(&self) -> &Surface {
@ -160,9 +164,12 @@ impl Renderer {
where
MW: MapWindow + HeadedMapWindow,
{
let instance = wgpu::Instance::new(wgpu_settings.backends.unwrap_or(wgpu::Backends::all()));
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
backends: wgpu_settings.backends.unwrap_or(wgpu::Backends::all()),
dx12_shader_compiler: Default::default(),
});
let surface: wgpu::Surface = unsafe { instance.create_surface(window.raw()) };
let surface: wgpu::Surface = unsafe { instance.create_surface(window.raw())? };
let (adapter, device, queue) = Self::request_device(
&instance,
@ -202,7 +209,10 @@ impl Renderer {
where
MW: MapWindow,
{
let instance = wgpu::Instance::new(wgpu_settings.backends.unwrap_or(wgpu::Backends::all()));
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
backends: wgpu_settings.backends.unwrap_or(wgpu::Backends::all()),
dx12_shader_compiler: Default::default(),
});
let (adapter, device, queue) = Self::request_device(
&instance,
@ -300,6 +310,9 @@ impl Renderer {
max_bind_groups: limits
.max_bind_groups
.min(constrained_limits.max_bind_groups),
max_bindings_per_bind_group: limits
.max_bindings_per_bind_group
.min(constrained_limits.max_bindings_per_bind_group),
max_dynamic_uniform_buffers_per_pipeline_layout: limits
.max_dynamic_uniform_buffers_per_pipeline_layout
.min(constrained_limits.max_dynamic_uniform_buffers_per_pipeline_layout),
@ -448,7 +461,10 @@ mod tests {
let graph = RenderGraph::default();
let backends = wgpu::util::backend_bits_from_env().unwrap_or(wgpu::Backends::all());
let instance = wgpu::Instance::new(backends);
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
backends,
dx12_shader_compiler: Default::default(),
});
let adapter = wgpu::util::initialize_adapter_from_env_or_default(&instance, backends, None)
.await
.expect("Unable to initialize adapter");
@ -468,13 +484,14 @@ mod tests {
let render_state = RenderResources::new(Surface::from_image(
&device,
&HeadlessMapWindow {
size: WindowSize::new(100, 100).unwrap(),
size: WindowSize::new(100, 100).expect("invalid headless map size"),
},
&RendererSettings::default(),
));
let world = World::default();
RenderGraphRunner::run(&graph, &device, &queue, &render_state, &world).unwrap();
RenderGraphRunner::run(&graph, &device, &queue, &render_state, &world)
.expect("failed to run graph runner");
}
}
@ -534,7 +551,7 @@ impl<E: Environment> Plugin<E> for RenderPlugin {
// Edges
draw_graph
.add_node_edge(input_node_id, draw_graph::node::MAIN_PASS)
.unwrap();
.expect("main pass or draw node does not exist");
graph.add_sub_graph(draw_graph::NAME, draw_graph);
graph.add_node(main_graph::node::MAIN_PASS_DEPENDENCIES, EmptyNode);
@ -544,7 +561,7 @@ impl<E: Environment> Plugin<E> for RenderPlugin {
main_graph::node::MAIN_PASS_DEPENDENCIES,
main_graph::node::MAIN_PASS_DRIVER,
)
.unwrap();
.expect("main pass driver or dependencies do not exist");
// render graph dependency
resources.init::<RenderPhase<LayerItem>>();

View File

@ -3,10 +3,15 @@
use std::{mem::size_of, num::NonZeroU32, sync::Arc};
use log::debug;
use wgpu::TextureFormatFeatures;
use crate::{
render::{eventually::HasChanged, resource::texture::TextureView, settings::RendererSettings},
render::{
error::RenderError,
eventually::HasChanged,
resource::texture::TextureView,
settings::{Msaa, RendererSettings},
},
window::{HeadedMapWindow, MapWindow, WindowSize},
};
@ -38,8 +43,10 @@ impl BufferDimensions {
pub struct WindowHead {
surface: wgpu::Surface,
size: WindowSize,
format: wgpu::TextureFormat,
texture_format: wgpu::TextureFormat,
present_mode: wgpu::PresentMode,
texture_format_features: TextureFormatFeatures,
}
impl WindowHead {
@ -52,20 +59,26 @@ impl WindowHead {
let surface_config = wgpu::SurfaceConfiguration {
alpha_mode: wgpu::CompositeAlphaMode::Auto,
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: self.format,
format: self.texture_format,
width: self.size.width(),
height: self.size.height(),
present_mode: self.present_mode,
view_formats: vec![self.texture_format],
};
self.surface.configure(device, &surface_config);
}
pub fn recreate_surface<MW>(&mut self, window: &MW, instance: &wgpu::Instance)
pub fn recreate_surface<MW>(
&mut self,
window: &MW,
instance: &wgpu::Instance,
) -> Result<(), RenderError>
where
MW: MapWindow + HeadedMapWindow,
{
self.surface = unsafe { instance.create_surface(window.raw()) };
self.surface = unsafe { instance.create_surface(window.raw())? };
Ok(())
}
pub fn surface(&self) -> &wgpu::Surface {
@ -170,22 +183,25 @@ impl Surface {
{
let size = window.size();
debug!(
"supported formats by adapter: {:?}",
surface.get_supported_formats(adapter)
);
let capabilities = surface.get_capabilities(adapter);
log::info!("adapter capabilities on surface: {:?}", capabilities);
let format = settings
let texture_format = settings
.texture_format
.or_else(|| surface.get_supported_formats(adapter).first().cloned())
.or_else(|| capabilities.formats.first().cloned())
.unwrap_or(wgpu::TextureFormat::Rgba8Unorm);
log::info!("format description: {:?}", texture_format.describe());
let texture_format_features = adapter.get_texture_format_features(texture_format);
log::info!("format features: {:?}", texture_format_features);
Self {
size,
head: Head::Headed(WindowHead {
surface,
size,
format,
texture_format,
texture_format_features,
present_mode: settings.present_mode,
}),
}
@ -229,6 +245,7 @@ impl Surface {
dimension: wgpu::TextureDimension::D2,
format,
usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::COPY_SRC,
view_formats: &[format],
};
let texture = device.create_texture(&texture_descriptor);
@ -245,7 +262,7 @@ impl Surface {
pub fn surface_format(&self) -> wgpu::TextureFormat {
match &self.head {
Head::Headed(headed) => headed.format,
Head::Headed(headed) => headed.texture_format,
Head::Headless(headless) => headless.texture_format,
}
}
@ -294,18 +311,23 @@ impl Surface {
}
}
pub fn recreate<MW>(&mut self, window: &MW, instance: &wgpu::Instance)
pub fn recreate<MW>(
&mut self,
window: &MW,
instance: &wgpu::Instance,
) -> Result<(), RenderError>
where
MW: MapWindow + HeadedMapWindow,
{
match &mut self.head {
Head::Headed(window_head) => {
if window_head.has_changed(&(self.size.width(), self.size.height())) {
window_head.recreate_surface(window, instance);
window_head.recreate_surface(window, instance)?;
}
}
Head::Headless(_) => {}
}
Ok(())
}
pub fn head(&self) -> &Head {
@ -315,6 +337,31 @@ impl Surface {
pub fn head_mut(&mut self) -> &mut Head {
&mut self.head
}
pub fn is_multisampling_supported(&self, msaa: Msaa) -> bool {
match &self.head {
Head::Headed(headed) => {
let max_sample_count = {
let flags = headed.texture_format_features.flags;
if flags.contains(wgpu::TextureFormatFeatureFlags::MULTISAMPLE_X8) {
8
} else if flags.contains(wgpu::TextureFormatFeatureFlags::MULTISAMPLE_X4) {
4
} else if flags.contains(wgpu::TextureFormatFeatureFlags::MULTISAMPLE_X2) {
2
} else {
1
}
};
let is_supported = msaa.samples <= max_sample_count;
if !is_supported {
log::debug!("Multisampling is not supported on surface");
}
is_supported
}
Head::Headless(_) => false, // TODO: support multisampling on headless
}
}
}
impl HasChanged for WindowHead {

View File

@ -94,6 +94,7 @@ impl Texture {
dimension: wgpu::TextureDimension::D2,
format,
usage,
view_formats: &[format],
});
let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
Self {

View File

@ -16,7 +16,7 @@ pub struct TilePipeline {
/// Force a write and ignore stencil
debug_stencil: bool,
wireframe: bool,
multisampling: bool,
msaa: bool,
raster: bool,
settings: RendererSettings,
@ -43,7 +43,7 @@ impl TilePipeline {
update_stencil,
debug_stencil,
wireframe,
multisampling,
msaa: multisampling,
raster,
settings,
vertex_state,
@ -132,7 +132,7 @@ impl RenderPipeline for TilePipeline {
})
},
multisample: wgpu::MultisampleState {
count: if self.multisampling {
count: if self.msaa {
self.settings.msaa.samples
} else {
1

View File

@ -89,13 +89,14 @@ pub struct Msaa {
}
impl Msaa {
pub fn is_active(&self) -> bool {
pub fn is_multisampling(&self) -> bool {
self.samples > 1
}
}
impl Default for Msaa {
fn default() -> Self {
// By default we are trying to multisample
Self { samples: 4 }
}
}

View File

@ -7,6 +7,7 @@ use crate::{
render::{
eventually::Eventually,
resource::{BackingBufferDescriptor, RenderPipeline, Texture, TilePipeline},
settings::Msaa,
shaders,
shaders::{Shader, ShaderTileMetadata},
tile_view_pattern::{TileViewPattern, WgpuTileViewPattern, DEFAULT_TILE_VIEW_PATTERN_SIZE},
@ -63,7 +64,11 @@ impl System for ResourceSystem {
settings.depth_texture_format,
size.width(),
size.height(),
settings.msaa,
if surface.is_multisampling_supported(settings.msaa) {
settings.msaa
} else {
Msaa { samples: 1 }
},
wgpu::TextureUsages::RENDER_ATTACHMENT,
)
},
@ -72,7 +77,9 @@ impl System for ResourceSystem {
state.multisampling_texture.reinitialize(
|| {
if settings.msaa.is_active() {
if settings.msaa.is_multisampling()
&& surface.is_multisampling_supported(settings.msaa)
{
Some(Texture::new(
Some("multisampling texture"),
device,
@ -120,7 +127,7 @@ impl System for ResourceSystem {
true,
false,
false,
true,
surface.is_multisampling_supported(settings.msaa),
false,
)
.describe_render_pipeline()

View File

@ -48,7 +48,7 @@ pub fn resource_system(
false,
false,
false,
true,
surface.is_multisampling_supported(settings.msaa),
false,
)
.describe_render_pipeline()

View File

@ -41,8 +41,8 @@ web-sys = { version = "0.3.58", features = [
"ErrorEvent"
] }
js-sys = "0.3.58"
wasm-bindgen = "0.2.81"
wasm-bindgen-futures = "0.4.31"
wasm-bindgen = "0.2"
wasm-bindgen-futures = "0.4"
console_log = { version = "0.2.0", features = ["color"] }
tracing-wasm = { version = "0.2.1", optional = true } # TODO: Low quality dependency (remove in a separate PR!)
# For passing Inputs in AsyncProcedureCalls
@ -55,4 +55,4 @@ image = "*" # FIXME: Remove image, use browser capabilities
flatc-rust = "0.2.0"
[dev-dependencies]
wasm-bindgen-test = "0.3.31"
wasm-bindgen-test = "0.3"