diff --git a/pax-chassis-web/Cargo.toml b/pax-chassis-web/Cargo.toml index 0ae77e3ad..804dc54b9 100644 --- a/pax-chassis-web/Cargo.toml +++ b/pax-chassis-web/Cargo.toml @@ -13,7 +13,7 @@ include = ["/src", "/interface/public"] crate-type = ["cdylib", "rlib"] [features] -default = ["console_error_panic_hook"] +default = ["console_error_panic_hook", "gpu"] designtime = ["dep:pax-designtime", "pax-runtime/designtime"] gpu = [] diff --git a/pax-pixels/src/render_backend/stencil.rs b/pax-pixels/src/render_backend/stencil.rs index 507c5bb78..b8d9c0544 100644 --- a/pax-pixels/src/render_backend/stencil.rs +++ b/pax-pixels/src/render_backend/stencil.rs @@ -18,6 +18,8 @@ pub struct StencilRenderer { stencil_layer: u32, width: u32, height: u32, + stencil_bind_group: wgpu::BindGroup, + _stencil_bind_group_layout: wgpu::BindGroupLayout, } #[repr(C)] @@ -27,15 +29,39 @@ pub struct Vertex { } impl StencilRenderer { - pub fn new(device: &Device, width: u32, height: u32, _globals: &wgpu::Buffer) -> Self { + pub fn new(device: &Device, width: u32, height: u32, globals: &wgpu::Buffer) -> Self { let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor { label: Some("Stencil Shader"), source: wgpu::ShaderSource::Wgsl(include_str!("stencil.wgsl").into()), }); + let stencil_bind_group_layout = + device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + entries: &[wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStages::VERTEX_FRAGMENT, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: None, + }, + count: None, + }], + label: Some("stencil_bind_group_layout"), + }); + + let stencil_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { + layout: &stencil_bind_group_layout, + entries: &[wgpu::BindGroupEntry { + binding: 0, + resource: globals.as_entire_binding(), + }], + label: Some("stencil_bind_group"), + }); + let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("Stencil Pipeline Layout"), - bind_group_layouts: &[], + bind_group_layouts: &[&stencil_bind_group_layout], push_constant_ranges: &[], }); @@ -62,7 +88,7 @@ impl StencilRenderer { primitive: wgpu::PrimitiveState { topology: wgpu::PrimitiveTopology::TriangleList, strip_index_format: None, - front_face: wgpu::FrontFace::Cw, + front_face: wgpu::FrontFace::Ccw, cull_mode: None, polygon_mode: wgpu::PolygonMode::Fill, unclipped_depth: false, @@ -150,7 +176,7 @@ impl StencilRenderer { usage: BufferUsages::VERTEX | BufferUsages::COPY_DST, }); - let mut indices: [u16; 1024] = [0; 1024]; + let indices: [u16; 1024] = [0; 1024]; let indices_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { label: Some("Stencil Indices"), contents: bytemuck::cast_slice(&indices), @@ -189,6 +215,8 @@ impl StencilRenderer { width, height, stencil_layer: 0, + stencil_bind_group, + _stencil_bind_group_layout: stencil_bind_group_layout, } } @@ -266,6 +294,7 @@ impl StencilRenderer { render_pass.set_pipeline(&self.stencil_pipeline); render_pass.set_vertex_buffer(0, self.vertices_buffer.slice(..)); + render_pass.set_bind_group(0, &self.stencil_bind_group, &[]); render_pass.set_index_buffer(self.indices_buffer.slice(..), wgpu::IndexFormat::Uint16); render_pass.draw_indexed(0..(geometry.indices.len() as u32), 0, 0..1); } @@ -298,6 +327,7 @@ impl StencilRenderer { // Use the decrement pipeline and fullscreen quad to decrease all stencil values render_pass.set_pipeline(&self.decrement_pipeline); + render_pass.set_bind_group(0, &self.stencil_bind_group, &[]); render_pass.set_vertex_buffer(0, self.fullscreen_vertices_buffer.slice(..)); render_pass.draw(0..3, 0..1); } diff --git a/pax-pixels/src/render_backend/stencil.wgsl b/pax-pixels/src/render_backend/stencil.wgsl index a5f36fa19..081c574ae 100644 --- a/pax-pixels/src/render_backend/stencil.wgsl +++ b/pax-pixels/src/render_backend/stencil.wgsl @@ -5,7 +5,7 @@ struct Globals { }; -// @group(0) @binding(0) var globals: Globals; +@group(0) @binding(0) var globals: Globals; struct VertexOutput { @builtin(position) clip_position: vec4, @@ -16,12 +16,12 @@ fn vs_main( @location(0) position: vec2, ) -> VertexOutput { var out: VertexOutput; - // var pos = position; - // pos /= globals.resolution; - // pos *= 2.0; - // pos -= 1.0; - // pos.y *= -1.0; - out.clip_position = vec4(position, 0.0, 1.0); + var pos = position; + pos /= globals.resolution; + pos *= 2.0; + pos -= 1.0; + pos.y *= -1.0; + out.clip_position = vec4(pos, 0.0, 1.0); return out; } diff --git a/pax-pixels/src/render_context.rs b/pax-pixels/src/render_context.rs index 6a94b7999..7e1646f86 100644 --- a/pax-pixels/src/render_context.rs +++ b/pax-pixels/src/render_context.rs @@ -194,7 +194,7 @@ impl<'w> WgpuRenderer<'w> { } } - pub fn push_transform(&mut self, transform: Transform2D) { + pub fn transform(&mut self, transform: Transform2D) { let new_ind = self.buffers.transforms.len(); self.buffers.transforms.push(GpuTransform { transform: transform.then(&self.current_transform()).to_arrays(), @@ -204,7 +204,24 @@ impl<'w> WgpuRenderer<'w> { self.transform_index_stack.push(new_ind); } - pub fn push_clipping(&mut self, path: Path) { + pub fn clip(&mut self, path: Path) { + // fine to transform on CPU - shouldn't be large meshes + // let path = path.transformed(&self.current_transform()); + if self.buffers.primitives.len() > 0 { + self.render_backend.render_primitives(&mut self.buffers); + let CpuBuffers { + geometry, + primitives, + transforms: _, + colors, + gradients, + } = &mut self.buffers; + geometry.vertices.clear(); + geometry.indices.clear(); + primitives.clear(); + colors.clear(); + gradients.clear(); + } let options = FillOptions::tolerance(self.tolerance); let mut geometry = VertexBuffers::new(); let mut geometry_builder = diff --git a/pax-runtime/src/engine/mod.rs b/pax-runtime/src/engine/mod.rs index d3332d449..5923a693a 100644 --- a/pax-runtime/src/engine/mod.rs +++ b/pax-runtime/src/engine/mod.rs @@ -301,7 +301,6 @@ impl PaxEngine { .unwrap_or(false) { rcs.clear(i); - rcs.clip(i, Rect::new(0.0, 0.0, 0.5, 0.5).into_path(0.01)) // only for testing, REMOVE } } // This is pretty useful during debugging - left it here since I use it often. /Sam diff --git a/pax-runtime/src/engine/pax_pixels_render_context.rs b/pax-runtime/src/engine/pax_pixels_render_context.rs index 75314577c..cd2670ccd 100644 --- a/pax-runtime/src/engine/pax_pixels_render_context.rs +++ b/pax-runtime/src/engine/pax_pixels_render_context.rs @@ -99,12 +99,12 @@ impl RenderContext for PaxPixelsRenderer { self.with_layer_context(layer, |context| { log::debug!("pax_pixels_render_context path {:?}", path); let path = convert_kurbo_to_lyon_path(&path); - context.push_clipping(path); + context.clip(path); }); } fn transform(&mut self, layer: usize, affine: kurbo::Affine) { self.with_layer_context(layer, |context| { - context.push_transform(Transform2D::from_array( + context.transform(Transform2D::from_array( affine.as_coeffs().map(|v| v as f32), )) }); diff --git a/pax-std/src/core/frame.rs b/pax-std/src/core/frame.rs index 64b9c95d7..9c2f074d9 100644 --- a/pax-std/src/core/frame.rs +++ b/pax-std/src/core/frame.rs @@ -98,7 +98,7 @@ impl InstanceNode for FrameInstance { for layer in 0..layers { //our "save point" before clipping — restored to in the post_render rcs.save(layer); - // rcs.clip(layer, transformed_bez_path.clone()); + rcs.clip(layer, transformed_bez_path.clone()); } } diff --git a/pax-std/src/drawing/image.rs b/pax-std/src/drawing/image.rs index 568eff15a..af076e5fd 100644 --- a/pax-std/src/drawing/image.rs +++ b/pax-std/src/drawing/image.rs @@ -220,7 +220,7 @@ impl InstanceNode for ImageInstance { let clip_path = kurbo::Rect::new(0.0, 0.0, container_width, container_height); rc.save(layer_id); rc.transform(layer_id, t_and_b.transform.into()); - // rc.clip(layer_id, clip_path.into_path(0.01)); + rc.clip(layer_id, clip_path.into_path(0.01)); rc.draw_image(layer_id, &path, transformed_bounds); rc.restore(layer_id); self.initial_load diff --git a/pax-std/src/drawing/path.rs b/pax-std/src/drawing/path.rs index 810dbc64e..ca33e0f14 100644 --- a/pax-std/src/drawing/path.rs +++ b/pax-std/src/drawing/path.rs @@ -223,7 +223,7 @@ impl InstanceNode for PathInstance { //our "save point" before clipping — restored to in the post_render rc.save(layer_id); - // rc.clip(layer_id, transformed_clip_path.clone()); + rc.clip(layer_id, transformed_clip_path.clone()); rc.fill(layer_id, transformed_bez_path, &properties.fill.get()); if properties .stroke