From ec0a980cb49a72eab6ebb523f5f61ff052bd6069 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Wed, 3 May 2023 11:59:48 +0200 Subject: [PATCH] yet another workaround for https://github.com/gfx-rs/naga/issues/1743 --- crates/re_renderer/shader/point_cloud.wgsl | 14 +++++++++++++ .../re_renderer/shader/utils/sphere_quad.wgsl | 11 ---------- .../re_renderer/src/renderer/point_cloud.rs | 21 +++++++++++++------ .../src/wgpu_resources/shader_module_pool.rs | 10 ++++++++- crates/re_web_viewer_server/build.rs | 1 + 5 files changed, 39 insertions(+), 18 deletions(-) diff --git a/crates/re_renderer/shader/point_cloud.wgsl b/crates/re_renderer/shader/point_cloud.wgsl index 881b6dd05a57..3fff3e6e61b9 100644 --- a/crates/re_renderer/shader/point_cloud.wgsl +++ b/crates/re_renderer/shader/point_cloud.wgsl @@ -111,6 +111,20 @@ fn vs_main(@builtin(vertex_index) vertex_idx: u32) -> VertexOut { return out; } +// TODO(andreas): move this to sphere_quad.wgsl once https://github.com/gfx-rs/naga/issues/1743 is resolved +// point_cloud.rs has a specific workaround in place so we don't need to split vertex/fragment shader here +// +/// Computes coverage of a 2D sphere placed at `circle_center` in the fragment shader using the currently set camera. +/// +/// 2D primitives are always facing the camera - the difference to sphere_quad_coverage is that +/// perspective projection is not taken into account. +fn circle_quad_coverage(world_position: Vec3, radius: f32, circle_center: Vec3) -> f32 { + let to_center = circle_center - world_position; + let distance = length(to_center); + let distance_pixel_difference = fwidth(distance); + return smoothstep(radius + distance_pixel_difference, radius - distance_pixel_difference, distance); +} + fn coverage(world_position: Vec3, radius: f32, point_center: Vec3) -> f32 { if is_camera_orthographic() || has_any_flag(batch.flags, DRAW_AS_CIRCLES) { return circle_quad_coverage(world_position, radius, point_center); diff --git a/crates/re_renderer/shader/utils/sphere_quad.wgsl b/crates/re_renderer/shader/utils/sphere_quad.wgsl index 6416c40aec31..83fc190496f8 100644 --- a/crates/re_renderer/shader/utils/sphere_quad.wgsl +++ b/crates/re_renderer/shader/utils/sphere_quad.wgsl @@ -111,14 +111,3 @@ fn sphere_quad_coverage(world_position: Vec3, radius: f32, sphere_center: Vec3) // Note that we have signed distances to the sphere surface. return saturate(0.5 - distance_to_surface_in_pixels); } - -/// Computes coverage of a 2D sphere placed at `circle_center` in the fragment shader using the currently set camera. -/// -/// 2D primitives are always facing the camera - the difference to sphere_quad_coverage is that -/// perspective projection is not taken into account. -fn circle_quad_coverage(world_position: Vec3, radius: f32, circle_center: Vec3) -> f32 { - let to_center = circle_center - world_position; - let distance = length(to_center); - let distance_pixel_difference = fwidth(distance); - return smoothstep(radius + distance_pixel_difference, radius - distance_pixel_difference, distance); -} diff --git a/crates/re_renderer/src/renderer/point_cloud.rs b/crates/re_renderer/src/renderer/point_cloud.rs index efe9006df69e..81e1a4c198e1 100644 --- a/crates/re_renderer/src/renderer/point_cloud.rs +++ b/crates/re_renderer/src/renderer/point_cloud.rs @@ -624,17 +624,26 @@ impl Renderer for PointCloudRenderer { &pools.bind_group_layouts, ); - let shader_module = pools.shader_modules.get_or_create( - device, - resolver, - &include_shader_module!("../../shader/point_cloud.wgsl"), - ); + let shader_module_desc = include_shader_module!("../../shader/point_cloud.wgsl"); + let shader_module = + pools + .shader_modules + .get_or_create(device, resolver, &shader_module_desc); + + // HACK/WORKAROUND for https://github.com/gfx-rs/naga/issues/1743 + let mut shader_module_desc_vertex = shader_module_desc.clone(); + shader_module_desc_vertex.extra_workaround_replacements = + vec![("fwidth(".to_owned(), "f32(".to_owned())]; + let shader_module_vertex = + pools + .shader_modules + .get_or_create(device, resolver, &shader_module_desc_vertex); let render_pipeline_desc_color = RenderPipelineDesc { label: "PointCloudRenderer::render_pipeline_color".into(), pipeline_layout, vertex_entrypoint: "vs_main".into(), - vertex_handle: shader_module, + vertex_handle: shader_module_vertex, fragment_entrypoint: "fs_main".into(), fragment_handle: shader_module, vertex_buffers: smallvec![], diff --git a/crates/re_renderer/src/wgpu_resources/shader_module_pool.rs b/crates/re_renderer/src/wgpu_resources/shader_module_pool.rs index 9b42f87d1788..df0f4de5c715 100644 --- a/crates/re_renderer/src/wgpu_resources/shader_module_pool.rs +++ b/crates/re_renderer/src/wgpu_resources/shader_module_pool.rs @@ -21,6 +21,7 @@ macro_rules! include_shader_module { $crate::wgpu_resources::ShaderModuleDesc { label: $crate::DebugLabel::from(stringify!($path).strip_prefix("../../shader/")), source: $crate::include_file!($path), + extra_workaround_replacements: Vec::new(), } }}; } @@ -33,6 +34,9 @@ pub struct ShaderModuleDesc { /// Path to the source code of this shader module. pub source: PathBuf, + + /// Additional text replacement workarounds that may be added on top of globally known workarounds. + pub extra_workaround_replacements: Vec<(String, String)>, } impl PartialEq for ShaderModuleDesc { @@ -46,6 +50,7 @@ impl Hash for ShaderModuleDesc { // NOTE: for a shader, the only thing that should matter is the source // code since we can have many entrypoints referring to the same file! self.source.hash(state); + self.extra_workaround_replacements.hash(state); } } @@ -62,7 +67,10 @@ impl ShaderModuleDesc { .map_err(|err| re_log::error!(err=%re_error::format(err))) .unwrap_or_default(); - for (from, to) in shader_text_workaround_replacements { + for (from, to) in shader_text_workaround_replacements + .iter() + .chain(self.extra_workaround_replacements.iter()) + { source_interpolated.contents = source_interpolated.contents.replace(from, to); } diff --git a/crates/re_web_viewer_server/build.rs b/crates/re_web_viewer_server/build.rs index 3837410ac6a2..945cab819778 100644 --- a/crates/re_web_viewer_server/build.rs +++ b/crates/re_web_viewer_server/build.rs @@ -57,6 +57,7 @@ impl<'a> Packages<'a> { // account for locally patched dependencies. rerun_if_changed(path.join("Cargo.toml").as_ref()); rerun_if_changed(path.join("**/*.rs").as_ref()); + rerun_if_changed(path.join("**/*.wgsl").as_ref()); } // Track all direct and indirect dependencies of that root package