diff --git a/Cargo.lock b/Cargo.lock index 8617468d..f845dcf7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -362,20 +362,6 @@ dependencies = [ "objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "cocoa" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "core-foundation 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "core-graphics 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", - "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "color-backtrace" version = "0.3.0" @@ -615,7 +601,7 @@ name = "demo" version = "0.1.0" dependencies = [ "color-backtrace 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "foreign-types 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "gl 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", "jemallocator 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "metal 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1731,9 +1717,9 @@ dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "cocoa 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cocoa 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "foreign-types 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "half 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "metal 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)", "objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2739,7 +2725,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "81fb25b677f8bf1eb325017cb6bb8452f87969db0fedb4f757b297bee78a7c62" "checksum cocoa 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f29f7768b2d1be17b96158e3285951d366b40211320fb30826a76cb7a0da6400" -"checksum cocoa 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0a4736c86d51bd878b474400d9ec888156f4037015f5d09794fab9f26eab1ad4" "checksum color-backtrace 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "65d13f1078cc63c791d0deba0dd43db37c9ec02b311f10bed10b577016f3a957" "checksum color_quant 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0dbbb57365263e881e805dc77d94697c9118fd94d8da011240555aa7b23445bd" "checksum combine 3.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "da3da6baa321ec19e1cc41d31bf599f00c783d0517095cdaf0332e3fe8d20680" diff --git a/canvas/src/lib.rs b/canvas/src/lib.rs index c8f27677..8c2da87e 100644 --- a/canvas/src/lib.rs +++ b/canvas/src/lib.rs @@ -28,6 +28,7 @@ use std::f32::consts::PI; use std::mem; use std::sync::Arc; use text::FontCollection; + #[cfg(feature = "pf-text")] pub use text::TextMetrics; pub use text::CanvasFontContext; diff --git a/color/src/lib.rs b/color/src/lib.rs index 77d91e18..e19e4109 100644 --- a/color/src/lib.rs +++ b/color/src/lib.rs @@ -21,6 +21,11 @@ pub struct ColorU { } impl ColorU { + #[inline] + pub fn new(r: u8, g: u8, b: u8, a: u8) -> ColorU { + ColorU { r, g, b, a } + } + #[inline] pub fn transparent_black() -> ColorU { ColorU::from_u32(0) diff --git a/content/src/gradient.rs b/content/src/gradient.rs index 1c08bf1f..54bc2382 100644 --- a/content/src/gradient.rs +++ b/content/src/gradient.rs @@ -12,7 +12,7 @@ use crate::sorted_vector::SortedVector; use pathfinder_color::ColorU; use pathfinder_geometry::line_segment::LineSegment2F; use pathfinder_simd::default::F32x4; -use std::cmp::{self, Ordering, PartialOrd}; +use std::cmp::{Ordering, PartialOrd}; use std::convert; use std::hash::{Hash, Hasher}; use std::mem; @@ -25,8 +25,8 @@ pub struct Gradient { #[derive(Clone, Copy, PartialEq, PartialOrd, Debug)] pub struct ColorStop { - pub color: ColorU, pub offset: f32, + pub color: ColorU, } impl Eq for Gradient {} @@ -79,10 +79,11 @@ impl Gradient { return ColorU::transparent_black(); } - let lower_index = self.stops.binary_search_by(|stop| { + let last_index = self.stops.len() - 1; + let upper_index = self.stops.binary_search_by(|stop| { stop.offset.partial_cmp(&t).unwrap_or(Ordering::Less) - }).unwrap_or_else(convert::identity); - let upper_index = cmp::min(lower_index + 1, self.stops.len() - 1); + }).unwrap_or_else(convert::identity).min(last_index); + let lower_index = if upper_index > 0 { upper_index - 1 } else { upper_index }; let lower_stop = &self.stops.array[lower_index]; let upper_stop = &self.stops.array[upper_index]; @@ -104,3 +105,10 @@ impl Gradient { } } } + +impl ColorStop { + #[inline] + pub fn new(color: ColorU, offset: f32) -> ColorStop { + ColorStop { color, offset } + } +} diff --git a/demo/native/Cargo.toml b/demo/native/Cargo.toml index 39eac0f9..127de9df 100644 --- a/demo/native/Cargo.toml +++ b/demo/native/Cargo.toml @@ -32,7 +32,7 @@ path = "../../gpu" path = "../../simd" [target.'cfg(target_os = "macos")'.dependencies] -foreign-types = "0.5" +foreign-types = "0.3" metal = "0.17" [target.'cfg(target_os = "macos")'.dependencies.pathfinder_metal] diff --git a/geometry/src/rect.rs b/geometry/src/rect.rs index cbe3eec9..50ff99eb 100644 --- a/geometry/src/rect.rs +++ b/geometry/src/rect.rs @@ -181,6 +181,11 @@ impl RectF { RectF::from_points(self.origin() - amount, self.lower_right() + amount) } + #[inline] + pub fn contract(self, amount: Vector2F) -> RectF { + RectF::from_points(self.origin() + amount, self.lower_right() - amount) + } + #[inline] pub fn to_i32(&self) -> RectI { RectI(self.0.to_i32x4()) @@ -308,6 +313,11 @@ impl RectI { .all_true() } + #[inline] + pub fn contract(self, amount: Vector2I) -> RectI { + RectI::from_points(self.origin() + amount, self.lower_right() - amount) + } + #[inline] pub fn to_f32(&self) -> RectF { RectF(self.0.to_f32x4()) diff --git a/geometry/src/transform2d.rs b/geometry/src/transform2d.rs index 5615fcb0..8e98aa5c 100644 --- a/geometry/src/transform2d.rs +++ b/geometry/src/transform2d.rs @@ -14,8 +14,8 @@ use crate::line_segment::LineSegment2F; use crate::rect::RectF; use crate::transform3d::Transform4F; use crate::unit_vector::UnitVector; -use crate::vector::{Vector2F, Vector2I}; -use pathfinder_simd::default::{F32x4, I32x4}; +use crate::vector::Vector2F; +use pathfinder_simd::default::F32x4; use std::ops::{Mul, MulAssign, Sub}; /// A 2x2 matrix, optimized with SIMD, in column-major order. @@ -74,14 +74,17 @@ impl Matrix2x2F { pub fn m11(&self) -> f32 { self.0[0] } + #[inline] pub fn m21(&self) -> f32 { self.0[1] } + #[inline] pub fn m12(&self) -> f32 { self.0[2] } + #[inline] pub fn m22(&self) -> f32 { self.0[3] @@ -113,29 +116,6 @@ impl Mul for Matrix2x2F { } } -/// A 2x2 integer matrix, optimized with SIMD, in column-major order. -#[derive(Clone, Copy, Debug, PartialEq)] -pub struct Matrix2x2I(pub I32x4); - -impl Matrix2x2I { - #[inline] - pub fn m11(&self) -> i32 { - self.0[0] - } - #[inline] - pub fn m21(&self) -> i32 { - self.0[1] - } - #[inline] - pub fn m12(&self) -> i32 { - self.0[2] - } - #[inline] - pub fn m22(&self) -> i32 { - self.0[3] - } -} - /// An affine transform, optimized with SIMD. #[derive(Clone, Copy, Debug, PartialEq)] pub struct Transform2F { @@ -346,10 +326,3 @@ impl MulAssign for Transform2F { *self = *self * other } } - -/// An affine integer transform, optimized with SIMD. -#[derive(Clone, Copy, Debug, PartialEq)] -pub struct Transform2I { - pub matrix: Matrix2x2I, - pub vector: Vector2I, -} diff --git a/geometry/src/vector.rs b/geometry/src/vector.rs index 88b10faa..a683045e 100644 --- a/geometry/src/vector.rs +++ b/geometry/src/vector.rs @@ -11,7 +11,7 @@ //! A SIMD-optimized point type. use pathfinder_simd::default::{F32x2, F32x4, I32x2}; -use std::ops::{Add, AddAssign, Mul, Neg, Sub}; +use std::ops::{Add, AddAssign, Div, Mul, Neg, Sub}; /// 2D points with 32-bit floating point coordinates. #[derive(Clone, Copy, Debug, Default)] @@ -135,6 +135,15 @@ impl Vector2F { Vector2F(self.0.yx()) } + /// Returns the coefficient when the given vector `a` is projected onto this one. + /// + /// That is, if this vector is `v` and this function returns `c`, then `proj_v a = cv`. In + /// other words, this function computes `(a⋅v) / (v⋅v)`. + #[inline] + pub fn projection_coefficient(self, a: Vector2F) -> f32 { + a.dot(self) / self.square_length() + } + #[inline] pub fn is_zero(self) -> bool { self == Vector2F::default() @@ -182,6 +191,14 @@ impl Mul for Vector2F { } } +impl Div for Vector2F { + type Output = Vector2F; + #[inline] + fn div(self, other: Vector2F) -> Vector2F { + Vector2F(self.0 / other.0) + } +} + impl Neg for Vector2F { type Output = Vector2F; #[inline] diff --git a/metal/Cargo.toml b/metal/Cargo.toml index 694bc9ed..c864ca72 100644 --- a/metal/Cargo.toml +++ b/metal/Cargo.toml @@ -8,9 +8,9 @@ edition = "2018" bitflags = "1.0" byteorder = "1.3" block = "0.1" -cocoa = "0.20" +cocoa = "0.19" core-foundation = "0.7" -foreign-types = "0.5" +foreign-types = "0.3" half = "1.4" metal = "0.17" objc = "0.2" diff --git a/renderer/src/builder.rs b/renderer/src/builder.rs index 4204f516..c37a4dc1 100644 --- a/renderer/src/builder.rs +++ b/renderer/src/builder.rs @@ -11,7 +11,7 @@ //! Packs data onto the GPU. use crate::concurrent::executor::Executor; -use crate::gpu_data::{AlphaTileBatchPrimitive, BuiltObject, FillBatchPrimitive, RenderCommand}; +use crate::gpu_data::{AlphaTile, BuiltObject, FillBatchPrimitive, RenderCommand}; use crate::options::{PreparedBuildOptions, RenderCommandListener}; use crate::paint::{PaintInfo, PaintMetadata}; use crate::scene::Scene; @@ -23,6 +23,7 @@ use pathfinder_geometry::vector::{Vector2F, Vector2I}; use pathfinder_geometry::rect::{RectF, RectI}; use pathfinder_geometry::util; use pathfinder_simd::default::{F32x4, I32x4}; +use std::i16; use std::sync::atomic::{AtomicUsize, Ordering}; use std::time::Instant; use std::u16; @@ -88,7 +89,7 @@ impl<'a> SceneBuilder<'a> { built_options: &PreparedBuildOptions, scene: &Scene, paint_metadata: &[PaintMetadata], - ) -> Vec { + ) -> Vec { let path_object = &scene.paths[path_index]; let outline = scene.apply_render_options(path_object.outline(), built_options); let paint_id = path_object.paint(); @@ -105,26 +106,29 @@ impl<'a> SceneBuilder<'a> { tiler.built_object.alpha_tiles } - fn cull_alpha_tiles(&self, alpha_tiles: &mut Vec) { + fn cull_alpha_tiles(&self, alpha_tiles: &mut Vec) { for alpha_tile in alpha_tiles { - let alpha_tile_coords = alpha_tile.tile_coords(); + let alpha_tile_coords = alpha_tile.upper_left.tile_position(); if self .z_buffer - .test(alpha_tile_coords, alpha_tile.object_index as u32) + .test(alpha_tile_coords, alpha_tile.upper_left.object_index as u32) { continue; } // FIXME(pcwalton): Clean this up. - alpha_tile.tile_x_lo = 0xff; - alpha_tile.tile_y_lo = 0xff; - alpha_tile.tile_hi = 0xff; + alpha_tile.upper_left.tile_x = i16::MIN; + alpha_tile.upper_left.tile_y = i16::MIN; + alpha_tile.upper_right.tile_x = i16::MIN; + alpha_tile.upper_right.tile_y = i16::MIN; + alpha_tile.lower_left.tile_x = i16::MIN; + alpha_tile.lower_left.tile_y = i16::MIN; + alpha_tile.lower_right.tile_x = i16::MIN; + alpha_tile.lower_right.tile_y = i16::MIN; } } - fn pack_alpha_tiles(&mut self, - paint_metadata: &[PaintMetadata], - alpha_tiles: Vec) { + fn pack_alpha_tiles(&mut self, paint_metadata: &[PaintMetadata], alpha_tiles: Vec) { let path_count = self.scene.paths.len() as u32; let solid_tiles = self.z_buffer.build_solid_tiles(&self.scene.paths, paint_metadata, @@ -139,7 +143,7 @@ impl<'a> SceneBuilder<'a> { fn finish_building(&mut self, paint_metadata: &[PaintMetadata], - mut alpha_tiles: Vec) { + mut alpha_tiles: Vec) { self.listener.send(RenderCommand::FlushFills); self.cull_alpha_tiles(&mut alpha_tiles); self.pack_alpha_tiles(paint_metadata, alpha_tiles); diff --git a/renderer/src/gpu/renderer.rs b/renderer/src/gpu/renderer.rs index 59d3b047..50be4b46 100644 --- a/renderer/src/gpu/renderer.rs +++ b/renderer/src/gpu/renderer.rs @@ -10,8 +10,7 @@ use crate::gpu::debug::DebugUIPresenter; use crate::gpu::options::{DestFramebuffer, RendererOptions}; -use crate::gpu_data::{AlphaTileBatchPrimitive, FillBatchPrimitive, PaintData}; -use crate::gpu_data::{RenderCommand, SolidTileBatchPrimitive}; +use crate::gpu_data::{AlphaTile, FillBatchPrimitive, PaintData, RenderCommand, SolidTileVertex}; use crate::post::DefringingKernel; use crate::tiles::{TILE_HEIGHT, TILE_WIDTH}; use pathfinder_color::ColorF; @@ -34,14 +33,17 @@ use std::u32; static QUAD_VERTEX_POSITIONS: [u16; 8] = [0, 0, 1, 0, 1, 1, 0, 1]; static QUAD_VERTEX_INDICES: [u32; 6] = [0, 1, 3, 1, 2, 3]; +pub(crate) const MASK_TILES_ACROSS: u32 = 256; +pub(crate) const MASK_TILES_DOWN: u32 = 256; + // FIXME(pcwalton): Shrink this again! -const MASK_FRAMEBUFFER_WIDTH: i32 = TILE_WIDTH as i32 * 256; -const MASK_FRAMEBUFFER_HEIGHT: i32 = TILE_HEIGHT as i32 * 256; +const MASK_FRAMEBUFFER_WIDTH: i32 = TILE_WIDTH as i32 * MASK_TILES_ACROSS as i32; +const MASK_FRAMEBUFFER_HEIGHT: i32 = TILE_HEIGHT as i32 * MASK_TILES_DOWN as i32; // TODO(pcwalton): Replace with `mem::size_of` calls? const FILL_INSTANCE_SIZE: usize = 8; -const SOLID_TILE_INSTANCE_SIZE: usize = 20; -const MASK_TILE_INSTANCE_SIZE: usize = 20; +const SOLID_TILE_VERTEX_SIZE: usize = 12; +const MASK_TILE_VERTEX_SIZE: usize = 16; const MAX_FILLS_PER_BATCH: usize = 0x4000; @@ -63,6 +65,8 @@ where area_lut_texture: D::Texture, quad_vertex_positions_buffer: D::Buffer, quad_vertex_indices_buffer: D::Buffer, + quads_vertex_indices_buffer: D::Buffer, + quads_vertex_indices_length: usize, fill_vertex_array: FillVertexArray, mask_framebuffer: D::Framebuffer, paint_texture: Option, @@ -132,6 +136,7 @@ where BufferTarget::Index, BufferUploadMode::Static, ); + let quads_vertex_indices_buffer = device.create_buffer(); let fill_vertex_array = FillVertexArray::new( &device, @@ -142,14 +147,12 @@ where let alpha_tile_vertex_array = AlphaTileVertexArray::new( &device, &alpha_tile_program, - &quad_vertex_positions_buffer, - &quad_vertex_indices_buffer, + &quads_vertex_indices_buffer, ); let solid_tile_vertex_array = SolidTileVertexArray::new( &device, &solid_tile_program, - &quad_vertex_positions_buffer, - &quad_vertex_indices_buffer, + &quads_vertex_indices_buffer, ); let postprocess_vertex_array = PostprocessVertexArray::new( &device, @@ -187,6 +190,8 @@ where area_lut_texture, quad_vertex_positions_buffer, quad_vertex_indices_buffer, + quads_vertex_indices_buffer, + quads_vertex_indices_length: 0, fill_vertex_array, mask_framebuffer, paint_texture: None, @@ -237,10 +242,10 @@ where self.draw_buffered_fills(); self.begin_composite_timer_query(); } - RenderCommand::SolidTile(ref solid_tiles) => { - let count = solid_tiles.len(); + RenderCommand::SolidTile(ref solid_tile_vertices) => { + let count = solid_tile_vertices.len() / 4; self.stats.solid_tile_count += count; - self.upload_solid_tiles(solid_tiles); + self.upload_solid_tiles(solid_tile_vertices); self.draw_solid_tiles(count as u32); } RenderCommand::AlphaTile(ref alpha_tiles) => { @@ -370,22 +375,49 @@ where TextureDataRef::U8(paint_texels)); } - fn upload_solid_tiles(&mut self, solid_tiles: &[SolidTileBatchPrimitive]) { + fn upload_solid_tiles(&mut self, solid_tile_vertices: &[SolidTileVertex]) { self.device.allocate_buffer( &self.solid_tile_vertex_array.vertex_buffer, - BufferData::Memory(&solid_tiles), + BufferData::Memory(&solid_tile_vertices), BufferTarget::Vertex, BufferUploadMode::Dynamic, ); + self.ensure_index_buffer(solid_tile_vertices.len() / 4); } - fn upload_alpha_tiles(&mut self, alpha_tiles: &[AlphaTileBatchPrimitive]) { + fn upload_alpha_tiles(&mut self, alpha_tiles: &[AlphaTile]) { self.device.allocate_buffer( &self.alpha_tile_vertex_array.vertex_buffer, BufferData::Memory(&alpha_tiles), BufferTarget::Vertex, BufferUploadMode::Dynamic, ); + self.ensure_index_buffer(alpha_tiles.len()); + } + + fn ensure_index_buffer(&mut self, mut length: usize) { + length = length.next_power_of_two(); + if self.quads_vertex_indices_length >= length { + return; + } + + // TODO(pcwalton): Generate these with SIMD. + let mut indices: Vec = Vec::with_capacity(length * 6); + for index in 0..(length as u32) { + indices.extend_from_slice(&[ + index * 4 + 0, index * 4 + 1, index * 4 + 2, + index * 4 + 1, index * 4 + 3, index * 4 + 2, + ]); + } + + self.device.allocate_buffer( + &self.quads_vertex_indices_buffer, + BufferData::Memory(&indices), + BufferTarget::Index, + BufferUploadMode::Static, + ); + + self.quads_vertex_indices_length = length; } fn add_fills(&mut self, mut fills: &[FillBatchPrimitive]) { @@ -465,7 +497,7 @@ where Transform4F::from_scale(scale).translate(Vector4F::new(-1.0, 1.0, 0.0, 1.0)) } - fn draw_alpha_tiles(&mut self, count: u32) { + fn draw_alpha_tiles(&mut self, tile_count: u32) { let clear_color = self.clear_color_for_draw_operation(); let mut textures = vec![self.device.framebuffer_texture(&self.mask_framebuffer)]; @@ -490,7 +522,7 @@ where .0 .to_f32x2()))); - self.device.draw_elements_instanced(6, count, &RenderState { + self.device.draw_elements(tile_count * 6, &RenderState { target: &self.draw_render_target(), program: &self.alpha_tile_program.program, vertex_array: &self.alpha_tile_vertex_array.vertex_array, @@ -512,7 +544,7 @@ where self.preserve_draw_framebuffer(); } - fn draw_solid_tiles(&mut self, count: u32) { + fn draw_solid_tiles(&mut self, tile_count: u32) { let clear_color = self.clear_color_for_draw_operation(); let mut textures = vec![]; @@ -530,7 +562,7 @@ where uniforms.push((&self.solid_tile_program.paint_texture_size_uniform, UniformData::Vec2(self.device.texture_size(paint_texture).0.to_f32x2()))); - self.device.draw_elements_instanced(6, count, &RenderState { + self.device.draw_elements(6 * tile_count, &RenderState { target: &self.draw_render_target(), program: &self.solid_tile_program.program, vertex_array: &self.solid_tile_vertex_array.vertex_array, @@ -940,87 +972,57 @@ where fn new( device: &D, alpha_tile_program: &AlphaTileProgram, - quad_vertex_positions_buffer: &D::Buffer, - quad_vertex_indices_buffer: &D::Buffer, + quads_vertex_indices_buffer: &D::Buffer, ) -> AlphaTileVertexArray { let (vertex_array, vertex_buffer) = (device.create_vertex_array(), device.create_buffer()); - let tess_coord_attr = device.get_vertex_attr(&alpha_tile_program.program, "TessCoord") - .unwrap(); - let tile_origin_attr = device.get_vertex_attr(&alpha_tile_program.program, "TileOrigin") - .unwrap(); + let tile_position_attr = + device.get_vertex_attr(&alpha_tile_program.program, "TilePosition").unwrap(); + let color_tex_coord_attr = device.get_vertex_attr(&alpha_tile_program.program, + "ColorTexCoord").unwrap(); + let mask_tex_coord_attr = device.get_vertex_attr(&alpha_tile_program.program, + "MaskTexCoord").unwrap(); let backdrop_attr = device.get_vertex_attr(&alpha_tile_program.program, "Backdrop") .unwrap(); - let tile_index_attr = device.get_vertex_attr(&alpha_tile_program.program, "TileIndex") - .unwrap(); - let color_tex_matrix_attr = device.get_vertex_attr(&alpha_tile_program.program, - "ColorTexMatrix").unwrap(); - let color_tex_offset_attr = device.get_vertex_attr(&alpha_tile_program.program, - "ColorTexOffset").unwrap(); - // NB: The object must be of type `I16`, not `U16`, to work around a macOS Radeon - // driver bug. - device.bind_buffer(&vertex_array, quad_vertex_positions_buffer, BufferTarget::Vertex); - device.configure_vertex_attr(&vertex_array, &tess_coord_attr, &VertexAttrDescriptor { + device.bind_buffer(&vertex_array, &vertex_buffer, BufferTarget::Vertex); + device.configure_vertex_attr(&vertex_array, &tile_position_attr, &VertexAttrDescriptor { size: 2, class: VertexAttrClass::Int, - attr_type: VertexAttrType::U16, - stride: 4, + attr_type: VertexAttrType::I16, + stride: MASK_TILE_VERTEX_SIZE, offset: 0, divisor: 0, buffer_index: 0, }); - device.bind_buffer(&vertex_array, &vertex_buffer, BufferTarget::Vertex); - device.configure_vertex_attr(&vertex_array, &tile_origin_attr, &VertexAttrDescriptor { - size: 3, - class: VertexAttrClass::Int, - attr_type: VertexAttrType::U8, - stride: MASK_TILE_INSTANCE_SIZE, - offset: 0, - divisor: 1, - buffer_index: 1, + device.configure_vertex_attr(&vertex_array, &color_tex_coord_attr, &VertexAttrDescriptor { + size: 2, + class: VertexAttrClass::FloatNorm, + attr_type: VertexAttrType::U16, + stride: MASK_TILE_VERTEX_SIZE, + offset: 4, + divisor: 0, + buffer_index: 0, + }); + device.configure_vertex_attr(&vertex_array, &mask_tex_coord_attr, &VertexAttrDescriptor { + size: 2, + class: VertexAttrClass::FloatNorm, + attr_type: VertexAttrType::U16, + stride: MASK_TILE_VERTEX_SIZE, + offset: 8, + divisor: 0, + buffer_index: 0, }); device.configure_vertex_attr(&vertex_array, &backdrop_attr, &VertexAttrDescriptor { - size: 1, - class: VertexAttrClass::Int, - attr_type: VertexAttrType::I8, - stride: MASK_TILE_INSTANCE_SIZE, - offset: 3, - divisor: 1, - buffer_index: 1, - }); - device.configure_vertex_attr(&vertex_array, &tile_index_attr, &VertexAttrDescriptor { size: 1, class: VertexAttrClass::Int, attr_type: VertexAttrType::I16, - stride: MASK_TILE_INSTANCE_SIZE, - offset: 6, - divisor: 1, - buffer_index: 1, + stride: MASK_TILE_VERTEX_SIZE, + offset: 12, + divisor: 0, + buffer_index: 0, }); - device.configure_vertex_attr(&vertex_array, - &color_tex_matrix_attr, - &VertexAttrDescriptor { - size: 4, - class: VertexAttrClass::FloatNorm, - attr_type: VertexAttrType::U16, - stride: MASK_TILE_INSTANCE_SIZE, - offset: 8, - divisor: 1, - buffer_index: 1, - }); - device.configure_vertex_attr(&vertex_array, - &color_tex_offset_attr, - &VertexAttrDescriptor { - size: 2, - class: VertexAttrClass::FloatNorm, - attr_type: VertexAttrType::U16, - stride: MASK_TILE_INSTANCE_SIZE, - offset: 16, - divisor: 1, - buffer_index: 1, - }); - device.bind_buffer(&vertex_array, quad_vertex_indices_buffer, BufferTarget::Index); + device.bind_buffer(&vertex_array, quads_vertex_indices_buffer, BufferTarget::Index); AlphaTileVertexArray { vertex_array, vertex_buffer } } @@ -1041,65 +1043,39 @@ where fn new( device: &D, solid_tile_program: &SolidTileProgram, - quad_vertex_positions_buffer: &D::Buffer, - quad_vertex_indices_buffer: &D::Buffer, + quads_vertex_indices_buffer: &D::Buffer, ) -> SolidTileVertexArray { let (vertex_array, vertex_buffer) = (device.create_vertex_array(), device.create_buffer()); - let tess_coord_attr = device.get_vertex_attr(&solid_tile_program.program, "TessCoord") - .unwrap(); - let tile_origin_attr = device.get_vertex_attr(&solid_tile_program.program, "TileOrigin") - .unwrap(); - let color_tex_matrix_attr = device.get_vertex_attr(&solid_tile_program.program, - "ColorTexMatrix").unwrap(); - let color_tex_offset_attr = device.get_vertex_attr(&solid_tile_program.program, - "ColorTexOffset").unwrap(); + let tile_position_attr = + device.get_vertex_attr(&solid_tile_program.program, "TilePosition").unwrap(); + let color_tex_coord_attr = + device.get_vertex_attr(&solid_tile_program.program, "ColorTexCoord").unwrap(); - // NB: The object must be of type short, not unsigned short, to work around a macOS + // NB: The tile origin must be of type short, not unsigned short, to work around a macOS // Radeon driver bug. - device.bind_buffer(&vertex_array, quad_vertex_positions_buffer, BufferTarget::Vertex); - device.configure_vertex_attr(&vertex_array, &tess_coord_attr, &VertexAttrDescriptor { + device.bind_buffer(&vertex_array, &vertex_buffer, BufferTarget::Vertex); + device.configure_vertex_attr(&vertex_array, &tile_position_attr, &VertexAttrDescriptor { size: 2, class: VertexAttrClass::Int, - attr_type: VertexAttrType::U16, - stride: 4, + attr_type: VertexAttrType::I16, + stride: SOLID_TILE_VERTEX_SIZE, offset: 0, divisor: 0, buffer_index: 0, }); - device.bind_buffer(&vertex_array, &vertex_buffer, BufferTarget::Vertex); - device.configure_vertex_attr(&vertex_array, &tile_origin_attr, &VertexAttrDescriptor { - size: 2, - class: VertexAttrClass::Int, - attr_type: VertexAttrType::I16, - stride: SOLID_TILE_INSTANCE_SIZE, - offset: 0, - divisor: 1, - buffer_index: 1, - }); device.configure_vertex_attr(&vertex_array, - &color_tex_matrix_attr, - &VertexAttrDescriptor { - size: 4, - class: VertexAttrClass::FloatNorm, - attr_type: VertexAttrType::U16, - stride: SOLID_TILE_INSTANCE_SIZE, - offset: 4, - divisor: 1, - buffer_index: 1, - }); - device.configure_vertex_attr(&vertex_array, - &color_tex_offset_attr, + &color_tex_coord_attr, &VertexAttrDescriptor { size: 2, class: VertexAttrClass::FloatNorm, attr_type: VertexAttrType::U16, - stride: SOLID_TILE_INSTANCE_SIZE, - offset: 12, - divisor: 1, - buffer_index: 1, + stride: SOLID_TILE_VERTEX_SIZE, + offset: 4, + divisor: 0, + buffer_index: 0, }); - device.bind_buffer(&vertex_array, quad_vertex_indices_buffer, BufferTarget::Index); + device.bind_buffer(&vertex_array, quads_vertex_indices_buffer, BufferTarget::Index); SolidTileVertexArray { vertex_array, vertex_buffer } } diff --git a/renderer/src/gpu_data.rs b/renderer/src/gpu_data.rs index 15f0f50f..9c87cf99 100644 --- a/renderer/src/gpu_data.rs +++ b/renderer/src/gpu_data.rs @@ -22,7 +22,7 @@ use std::time::Duration; pub(crate) struct BuiltObject { pub bounds: RectF, pub fills: Vec, - pub alpha_tiles: Vec, + pub alpha_tiles: Vec, pub tiles: DenseTileMap, } @@ -31,8 +31,8 @@ pub enum RenderCommand { AddPaintData(PaintData), AddFills(Vec), FlushFills, - AlphaTile(Vec), - SolidTile(Vec), + AlphaTile(Vec), + SolidTile(Vec), Finish { build_time: Duration }, } @@ -69,34 +69,35 @@ pub struct FillBatchPrimitive { #[derive(Clone, Copy, Debug)] #[repr(C)] -pub struct SolidTileBatchPrimitive { +pub struct SolidTileVertex { pub tile_x: i16, pub tile_y: i16, - pub texture_m00: u16, - pub texture_m10: u16, - pub texture_m01: u16, - pub texture_m11: u16, - pub texture_m02: u16, - pub texture_m12: u16, + pub color_u: u16, + pub color_v: u16, pub object_index: u16, pub pad: u16, } #[derive(Clone, Copy, Debug, Default)] #[repr(C)] -pub struct AlphaTileBatchPrimitive { - pub tile_x_lo: u8, - pub tile_y_lo: u8, - pub tile_hi: u8, - pub backdrop: i8, +pub struct AlphaTile { + pub upper_left: AlphaTileVertex, + pub upper_right: AlphaTileVertex, + pub lower_left: AlphaTileVertex, + pub lower_right: AlphaTileVertex, +} + +#[derive(Clone, Copy, Debug, Default)] +#[repr(C)] +pub struct AlphaTileVertex { + pub tile_x: i16, + pub tile_y: i16, + pub color_u: u16, + pub color_v: u16, + pub mask_u: u16, + pub mask_v: u16, + pub backdrop: i16, pub object_index: u16, - pub tile_index: u16, - pub texture_m00: u16, - pub texture_m10: u16, - pub texture_m01: u16, - pub texture_m11: u16, - pub texture_m02: u16, - pub texture_m12: u16, } impl Debug for RenderCommand { diff --git a/renderer/src/paint.rs b/renderer/src/paint.rs index 2633f4b4..80c2a2b4 100644 --- a/renderer/src/paint.rs +++ b/renderer/src/paint.rs @@ -1,6 +1,6 @@ // pathfinder/renderer/src/paint.rs // -// Copyright © 2019 The Pathfinder Project Developers. +// Copyright © 2020 The Pathfinder Project Developers. // // Licensed under the Apache License, Version 2.0 or the MIT license @@ -10,17 +10,25 @@ use crate::allocator::{TextureAllocator, TextureLocation}; use crate::gpu_data::PaintData; +use crate::tiles::{TILE_HEIGHT, TILE_WIDTH}; use hashbrown::HashMap; use pathfinder_color::ColorU; use pathfinder_content::gradient::Gradient; -use pathfinder_geometry::rect::RectI; -use pathfinder_geometry::transform2d::{Matrix2x2I, Transform2I}; -use pathfinder_geometry::vector::Vector2I; -use pathfinder_simd::default::I32x4; +use pathfinder_geometry::rect::{RectF, RectI}; +use pathfinder_geometry::transform2d::{Matrix2x2F, Transform2F}; +use pathfinder_geometry::util; +use pathfinder_geometry::vector::{Vector2F, Vector2I}; +use pathfinder_simd::default::F32x4; use std::fmt::{self, Debug, Formatter}; const PAINT_TEXTURE_LENGTH: u32 = 1024; -const PAINT_TEXTURE_SCALE: u32 = 65536 / PAINT_TEXTURE_LENGTH; +const PAINT_TEXTURE_SCALE: f32 = 1.0 / PAINT_TEXTURE_LENGTH as f32; + +// The size of a gradient tile. +// +// TODO(pcwalton): Choose this size dynamically! +const GRADIENT_TILE_LENGTH: u32 = 256; +const GRADIENT_TILE_SCALE: f32 = GRADIENT_TILE_LENGTH as f32 * PAINT_TEXTURE_SCALE; const SOLID_COLOR_TILE_LENGTH: u32 = 16; const MAX_SOLID_COLORS_PER_TILE: u32 = SOLID_COLOR_TILE_LENGTH * SOLID_COLOR_TILE_LENGTH; @@ -112,10 +120,13 @@ pub struct PaintInfo { pub metadata: Vec, } +// TODO(pcwalton): Add clamp/repeat options. #[derive(Debug)] pub struct PaintMetadata { - /// The transform to apply to the texture coordinates, in 0.16 fixed point. - pub tex_transform: Transform2I, + /// The rectangle within the texture atlas. + pub tex_rect: RectI, + /// The transform to apply to screen coordinates to translate them into UVs. + pub tex_transform: Transform2F, /// True if this paint is fully opaque. pub is_opaque: bool, } @@ -133,29 +144,61 @@ impl Palette { paint_id } - pub fn build_paint_info(&self) -> PaintInfo { + pub fn build_paint_info(&self, view_box_size: Vector2I) -> PaintInfo { let mut allocator = TextureAllocator::new(PAINT_TEXTURE_LENGTH); let area = PAINT_TEXTURE_LENGTH as usize * PAINT_TEXTURE_LENGTH as usize; let (mut texels, mut metadata) = (vec![0; area * 4], vec![]); + let mut solid_color_tile_builder = SolidColorTileBuilder::new(); for paint in &self.paints { - let tex_transform; + let (texture_location, tex_transform); match paint { Paint::Color(color) => { - // TODO(pcwalton): Handle other paint types. - let texture_location = solid_color_tile_builder.allocate(&mut allocator); + texture_location = solid_color_tile_builder.allocate(&mut allocator); + let vector = rect_to_inset_uv(texture_location.rect).origin(); + tex_transform = Transform2F { matrix: Matrix2x2F(F32x4::default()), vector }; put_pixel(&mut texels, texture_location.rect.origin(), *color); - tex_transform = Transform2I { - matrix: Matrix2x2I(I32x4::default()), - vector: texture_location.rect.origin().scale(PAINT_TEXTURE_SCALE as i32) + - Vector2I::splat(PAINT_TEXTURE_SCALE as i32 / 2), - }; } - Paint::Gradient(_) => unimplemented!(), + Paint::Gradient(ref gradient) => { + // TODO(pcwalton): Optimize this: + // 1. Use repeating/clamp on the sides. + // 2. Choose an optimal size for the gradient that minimizes memory usage while + // retaining quality. + texture_location = + allocator.allocate(Vector2I::splat(GRADIENT_TILE_LENGTH as i32)) + .expect("Failed to allocate space for the gradient!"); + + tex_transform = + Transform2F::from_translation(rect_to_uv(texture_location.rect).origin()) * + Transform2F::from_scale(Vector2F::splat(GRADIENT_TILE_SCALE) / + view_box_size.to_f32()); + + let gradient_line = tex_transform * gradient.line(); + + // TODO(pcwalton): Optimize this: + // 1. Calculate ∇t up front and use differencing in the inner loop. + // 2. Go four pixels at a time with SIMD. + for y in 0..(GRADIENT_TILE_LENGTH as i32) { + for x in 0..(GRADIENT_TILE_LENGTH as i32) { + let point = texture_location.rect.origin() + Vector2I::new(x, y); + let vector = point.to_f32().scale(1.0 / PAINT_TEXTURE_LENGTH as f32) - + gradient_line.from(); + + let mut t = gradient_line.vector().projection_coefficient(vector); + t = util::clamp(t, 0.0, 1.0); + + put_pixel(&mut texels, point, gradient.sample(t)); + } + } + } } - metadata.push(PaintMetadata { tex_transform, is_opaque: paint.is_opaque() }); + metadata.push(PaintMetadata { + tex_rect: texture_location.rect, + tex_transform, + is_opaque: paint.is_opaque(), + }); } let size = Vector2I::splat(PAINT_TEXTURE_LENGTH as i32); @@ -169,9 +212,28 @@ impl Palette { texels[index + 2] = color.b; texels[index + 3] = color.a; } + + fn rect_to_uv(rect: RectI) -> RectF { + rect.to_f32().scale(1.0 / PAINT_TEXTURE_LENGTH as f32) + } + + fn rect_to_inset_uv(rect: RectI) -> RectF { + rect_to_uv(rect).contract(Vector2F::splat(0.5 / PAINT_TEXTURE_LENGTH as f32)) + } } } +impl PaintMetadata { + // TODO(pcwalton): Apply clamp/repeat to tile rect. + pub(crate) fn calculate_tex_coords(&self, tile_position: Vector2I) -> Vector2F { + let tile_size = Vector2I::new(TILE_WIDTH as i32, TILE_HEIGHT as i32); + let tex_coords = self.tex_transform * tile_position.scale_xy(tile_size).to_f32(); + tex_coords + } +} + +// Solid color allocation + struct SolidColorTileBuilder(Option); struct SolidColorTileBuilderData { diff --git a/renderer/src/scene.rs b/renderer/src/scene.rs index 9892cfa6..e438309a 100644 --- a/renderer/src/scene.rs +++ b/renderer/src/scene.rs @@ -47,7 +47,7 @@ impl Scene { #[inline] pub fn build_paint_info(&self) -> PaintInfo { - self.palette.build_paint_info() + self.palette.build_paint_info(self.view_box.size().to_i32()) } #[allow(clippy::trivially_copy_pass_by_ref)] diff --git a/renderer/src/tiles.rs b/renderer/src/tiles.rs index 9ff7b6ce..bbe3c1ea 100644 --- a/renderer/src/tiles.rs +++ b/renderer/src/tiles.rs @@ -9,14 +9,14 @@ // except according to those terms. use crate::builder::SceneBuilder; -use crate::gpu_data::{AlphaTileBatchPrimitive, BuiltObject, TileObjectPrimitive}; +use crate::gpu::renderer::MASK_TILES_ACROSS; +use crate::gpu_data::{AlphaTile, AlphaTileVertex, BuiltObject, TileObjectPrimitive}; use crate::paint::PaintMetadata; use pathfinder_content::outline::{Contour, Outline, PointIndex}; use pathfinder_content::segment::Segment; use pathfinder_content::sorted_vector::SortedVector; use pathfinder_geometry::line_segment::LineSegment2F; use pathfinder_geometry::rect::{RectF, RectI}; -use pathfinder_geometry::transform2d::Transform2I; use pathfinder_geometry::vector::{Vector2F, Vector2I}; use std::cmp::Ordering; use std::mem; @@ -126,15 +126,32 @@ impl<'a> Tiler<'a> { } } - let alpha_tile = AlphaTileBatchPrimitive::new( - tile_coords, - tile.backdrop, - self.object_index, - tile.alpha_tile_index as u16, - self.paint_metadata.tex_transform, - ); - - self.built_object.alpha_tiles.push(alpha_tile); + self.built_object.alpha_tiles.push(AlphaTile { + upper_left: AlphaTileVertex::new(tile_coords, + tile.alpha_tile_index as u16, + Vector2I::default(), + self.object_index, + tile.backdrop as i16, + &self.paint_metadata), + upper_right: AlphaTileVertex::new(tile_coords, + tile.alpha_tile_index as u16, + Vector2I::new(1, 0), + self.object_index, + tile.backdrop as i16, + &self.paint_metadata), + lower_left: AlphaTileVertex::new(tile_coords, + tile.alpha_tile_index as u16, + Vector2I::new(0, 1), + self.object_index, + tile.backdrop as i16, + &self.paint_metadata), + lower_right: AlphaTileVertex::new(tile_coords, + tile.alpha_tile_index as u16, + Vector2I::splat(1), + self.object_index, + tile.backdrop as i16, + &self.paint_metadata), + }); } } @@ -526,36 +543,39 @@ impl PartialOrd for ActiveEdge { } } -impl AlphaTileBatchPrimitive { +impl AlphaTileVertex { #[inline] - fn new(tile_coords: Vector2I, - backdrop: i8, - object_index: u16, + fn new(tile_origin: Vector2I, tile_index: u16, - tex_transform: Transform2I) - -> AlphaTileBatchPrimitive { - AlphaTileBatchPrimitive { - tile_x_lo: (tile_coords.x() & 0xff) as u8, - tile_y_lo: (tile_coords.y() & 0xff) as u8, - tile_hi: (((tile_coords.x() >> 8) & 0x0f) | ((tile_coords.y() >> 4) & 0xf0)) as u8, - backdrop, + tile_offset: Vector2I, + object_index: u16, + backdrop: i16, + paint_metadata: &PaintMetadata) + -> AlphaTileVertex { + let tile_position = tile_origin + tile_offset; + let color_uv = paint_metadata.calculate_tex_coords(tile_position).scale(65535.0).to_i32(); + + let mask_u = tile_index as i32 % MASK_TILES_ACROSS as i32; + let mask_v = tile_index as i32 / MASK_TILES_ACROSS as i32; + let mask_scale = 65535.0 / MASK_TILES_ACROSS as f32; + let mask_uv = Vector2I::new(mask_u, mask_v) + tile_offset; + let mask_uv = mask_uv.to_f32().scale(mask_scale).to_i32(); + + AlphaTileVertex { + tile_x: tile_position.x() as i16, + tile_y: tile_position.y() as i16, + color_u: color_uv.x() as u16, + color_v: color_uv.y() as u16, + mask_u: mask_uv.x() as u16, + mask_v: mask_uv.y() as u16, object_index, - tile_index, - texture_m00: tex_transform.matrix.m11() as u16, - texture_m10: tex_transform.matrix.m21() as u16, - texture_m01: tex_transform.matrix.m12() as u16, - texture_m11: tex_transform.matrix.m22() as u16, - texture_m02: tex_transform.vector.x() as u16, - texture_m12: tex_transform.vector.y() as u16, + backdrop, } } #[inline] - pub fn tile_coords(&self) -> Vector2I { - Vector2I::new( - (self.tile_x_lo as i32) | (((self.tile_hi & 0xf) as i32) << 8), - (self.tile_y_lo as i32) | (((self.tile_hi & 0xf0) as i32) << 4), - ) + pub fn tile_position(&self) -> Vector2I { + Vector2I::new(self.tile_x as i32, self.tile_y as i32) } } diff --git a/renderer/src/z_buffer.rs b/renderer/src/z_buffer.rs index 51501dc8..044ecc39 100644 --- a/renderer/src/z_buffer.rs +++ b/renderer/src/z_buffer.rs @@ -10,13 +10,12 @@ //! Software occlusion culling. -use crate::gpu_data::SolidTileBatchPrimitive; +use crate::gpu_data::SolidTileVertex; use crate::paint::PaintMetadata; use crate::scene::PathObject; use crate::tile_map::DenseTileMap; use crate::tiles; use pathfinder_geometry::rect::RectF; -use pathfinder_geometry::transform2d::Transform2I; use pathfinder_geometry::vector::Vector2I; use std::ops::Range; use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrdering}; @@ -61,7 +60,7 @@ impl ZBuffer { paths: &[PathObject], paint_metadata: &[PaintMetadata], object_range: Range) - -> Vec { + -> Vec { let mut solid_tiles = vec![]; for tile_index in 0..self.buffer.data.len() { let depth = self.buffer.data[tile_index].load(AtomicOrdering::Relaxed); @@ -76,30 +75,39 @@ impl ZBuffer { } let paint_id = paths[object_index as usize].paint(); - let tex_transform = paint_metadata[paint_id.0 as usize].tex_transform; + let paint_metadata = &paint_metadata[paint_id.0 as usize]; - solid_tiles.push(SolidTileBatchPrimitive::new(tile_coords + self.buffer.rect.origin(), - object_index as u16, - tex_transform)); + let tile_position = tile_coords + self.buffer.rect.origin(); + let object_index = object_index as u16; + + solid_tiles.extend_from_slice(&[ + SolidTileVertex::new(tile_position, object_index, paint_metadata), + SolidTileVertex::new(tile_position + Vector2I::new(1, 0), + object_index, + paint_metadata), + SolidTileVertex::new(tile_position + Vector2I::new(0, 1), + object_index, + paint_metadata), + SolidTileVertex::new(tile_position + Vector2I::new(1, 1), + object_index, + paint_metadata), + ]); } solid_tiles } } -impl SolidTileBatchPrimitive { - fn new(tile_coords: Vector2I, object_index: u16, tex_transform: Transform2I) - -> SolidTileBatchPrimitive { - SolidTileBatchPrimitive { - tile_x: tile_coords.x() as i16, - tile_y: tile_coords.y() as i16, +impl SolidTileVertex { + fn new(tile_position: Vector2I, object_index: u16, paint_metadata: &PaintMetadata) + -> SolidTileVertex { + let color_uv = paint_metadata.calculate_tex_coords(tile_position).scale(65535.0).to_i32(); + SolidTileVertex { + tile_x: tile_position.x() as i16, + tile_y: tile_position.y() as i16, object_index: object_index, - texture_m00: tex_transform.matrix.m11() as u16, - texture_m10: tex_transform.matrix.m21() as u16, - texture_m01: tex_transform.matrix.m12() as u16, - texture_m11: tex_transform.matrix.m22() as u16, - texture_m02: tex_transform.vector.x() as u16, - texture_m12: tex_transform.vector.y() as u16, + color_u: color_uv.x() as u16, + color_v: color_uv.y() as u16, pad: 0, } } diff --git a/resources/shaders/gl3/tile_alpha.fs.glsl b/resources/shaders/gl3/tile_alpha.fs.glsl index 6f142253..20a5db4e 100644 --- a/resources/shaders/gl3/tile_alpha.fs.glsl +++ b/resources/shaders/gl3/tile_alpha.fs.glsl @@ -18,8 +18,8 @@ uniform sampler2D uStencilTexture; uniform sampler2D uPaintTexture; uniform vec2 uPaintTextureSize; -in vec2 vMaskTexCoord; in vec2 vColorTexCoord; +in vec2 vMaskTexCoord; in float vBackdrop; in vec4 vColor; diff --git a/resources/shaders/gl3/tile_alpha.vs.glsl b/resources/shaders/gl3/tile_alpha.vs.glsl index 1467b8e5..369895c0 100644 --- a/resources/shaders/gl3/tile_alpha.vs.glsl +++ b/resources/shaders/gl3/tile_alpha.vs.glsl @@ -18,32 +18,20 @@ uniform mat4 uTransform; uniform vec2 uTileSize; uniform vec2 uStencilTextureSize; -in uvec2 aTessCoord; -in uvec3 aTileOrigin; -in vec4 aColorTexMatrix; -in vec2 aColorTexOffset; +in ivec2 aTilePosition; +in vec2 aColorTexCoord; +in vec2 aMaskTexCoord; in int aBackdrop; -in int aTileIndex; -out vec2 vMaskTexCoord; out vec2 vColorTexCoord; +out vec2 vMaskTexCoord; out float vBackdrop; -vec2 computeTileOffset(uint tileIndex, float stencilTextureWidth){ - uint tilesPerRow = uint(stencilTextureWidth / uTileSize . x); - uvec2 tileOffset = uvec2(tileIndex % tilesPerRow, tileIndex / tilesPerRow); - return vec2(tileOffset)* uTileSize; -} - void main(){ - vec2 tileOffset = vec2(aTessCoord)* uTileSize; - vec2 origin = vec2(aTileOrigin . xy)+ vec2(aTileOrigin . z & 15u, aTileOrigin . z >> 4u)* 256.0; - vec2 position = origin * uTileSize + tileOffset; - vec2 maskTexCoordOrigin = computeTileOffset(uint(aTileIndex), uStencilTextureSize . x); - vec2 maskTexCoord = maskTexCoordOrigin + tileOffset; + vec2 position = aTilePosition * uTileSize; - vMaskTexCoord = maskTexCoord / uStencilTextureSize; - vColorTexCoord = mat2(aColorTexMatrix)* tileOffset + aColorTexOffset; + vMaskTexCoord = aMaskTexCoord; + vColorTexCoord = aColorTexCoord; vBackdrop = float(aBackdrop); gl_Position = uTransform * vec4(position, 0.0, 1.0); } diff --git a/resources/shaders/gl3/tile_solid.vs.glsl b/resources/shaders/gl3/tile_solid.vs.glsl index cfd8432a..806b6d99 100644 --- a/resources/shaders/gl3/tile_solid.vs.glsl +++ b/resources/shaders/gl3/tile_solid.vs.glsl @@ -17,17 +17,14 @@ precision highp float; uniform mat4 uTransform; uniform vec2 uTileSize; -in uvec2 aTessCoord; -in ivec2 aTileOrigin; -in vec4 aColorTexMatrix; -in vec2 aColorTexOffset; +in ivec2 aTilePosition; +in vec2 aColorTexCoord; out vec2 vColorTexCoord; void main(){ - vec2 tileOffset = vec2(aTessCoord)* uTileSize; - vec2 position = aTileOrigin * uTileSize + tileOffset; - vColorTexCoord = mat2(aColorTexMatrix)* tileOffset + aColorTexOffset; + vec2 position = aTilePosition * uTileSize; + vColorTexCoord = aColorTexCoord; gl_Position = uTransform * vec4(position, 0.0, 1.0); } diff --git a/resources/shaders/metal/tile_alpha.fs.metal b/resources/shaders/metal/tile_alpha.fs.metal index 7dde311b..0d9b7126 100644 --- a/resources/shaders/metal/tile_alpha.fs.metal +++ b/resources/shaders/metal/tile_alpha.fs.metal @@ -19,8 +19,8 @@ struct main0_out struct main0_in { - float2 vMaskTexCoord [[user(locn0)]]; - float2 vColorTexCoord [[user(locn1)]]; + float2 vColorTexCoord [[user(locn0)]]; + float2 vMaskTexCoord [[user(locn1)]]; float vBackdrop [[user(locn2)]]; }; diff --git a/resources/shaders/metal/tile_alpha.vs.metal b/resources/shaders/metal/tile_alpha.vs.metal index 2afd50d5..df55ea91 100644 --- a/resources/shaders/metal/tile_alpha.vs.metal +++ b/resources/shaders/metal/tile_alpha.vs.metal @@ -1,6 +1,4 @@ // Automatically generated from files in pathfinder/shaders/. Do not edit! -#pragma clang diagnostic ignored "-Wmissing-prototypes" - #include #include @@ -9,47 +7,31 @@ using namespace metal; struct spvDescriptorSetBuffer0 { constant float2* uTileSize [[id(0)]]; - constant float2* uStencilTextureSize [[id(1)]]; - constant float4x4* uTransform [[id(2)]]; + constant float4x4* uTransform [[id(1)]]; }; struct main0_out { - float2 vMaskTexCoord [[user(locn0)]]; - float2 vColorTexCoord [[user(locn1)]]; + float2 vColorTexCoord [[user(locn0)]]; + float2 vMaskTexCoord [[user(locn1)]]; float vBackdrop [[user(locn2)]]; float4 gl_Position [[position]]; }; struct main0_in { - uint2 aTessCoord [[attribute(0)]]; - uint3 aTileOrigin [[attribute(1)]]; - float4 aColorTexMatrix [[attribute(2)]]; - float2 aColorTexOffset [[attribute(3)]]; - int aBackdrop [[attribute(4)]]; - int aTileIndex [[attribute(5)]]; + int2 aTilePosition [[attribute(0)]]; + float2 aColorTexCoord [[attribute(1)]]; + float2 aMaskTexCoord [[attribute(2)]]; + int aBackdrop [[attribute(3)]]; }; -float2 computeTileOffset(thread const uint& tileIndex, thread const float& stencilTextureWidth, thread float2 uTileSize) -{ - uint tilesPerRow = uint(stencilTextureWidth / uTileSize.x); - uint2 tileOffset = uint2(tileIndex % tilesPerRow, tileIndex / tilesPerRow); - return float2(tileOffset) * uTileSize; -} - vertex main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]]) { main0_out out = {}; - float2 tileOffset = float2(in.aTessCoord) * (*spvDescriptorSet0.uTileSize); - float2 origin = float2(in.aTileOrigin.xy) + (float2(float(in.aTileOrigin.z & 15u), float(in.aTileOrigin.z >> 4u)) * 256.0); - float2 position = (origin * (*spvDescriptorSet0.uTileSize)) + tileOffset; - uint param = uint(in.aTileIndex); - float param_1 = (*spvDescriptorSet0.uStencilTextureSize).x; - float2 maskTexCoordOrigin = computeTileOffset(param, param_1, (*spvDescriptorSet0.uTileSize)); - float2 maskTexCoord = maskTexCoordOrigin + tileOffset; - out.vMaskTexCoord = maskTexCoord / (*spvDescriptorSet0.uStencilTextureSize); - out.vColorTexCoord = (float2x2(float2(in.aColorTexMatrix.xy), float2(in.aColorTexMatrix.zw)) * tileOffset) + in.aColorTexOffset; + float2 position = float2(in.aTilePosition) * (*spvDescriptorSet0.uTileSize); + out.vMaskTexCoord = in.aMaskTexCoord; + out.vColorTexCoord = in.aColorTexCoord; out.vBackdrop = float(in.aBackdrop); out.gl_Position = (*spvDescriptorSet0.uTransform) * float4(position, 0.0, 1.0); return out; diff --git a/resources/shaders/metal/tile_solid.vs.metal b/resources/shaders/metal/tile_solid.vs.metal index cac3ea04..4b344eef 100644 --- a/resources/shaders/metal/tile_solid.vs.metal +++ b/resources/shaders/metal/tile_solid.vs.metal @@ -18,18 +18,15 @@ struct main0_out struct main0_in { - uint2 aTessCoord [[attribute(0)]]; - int2 aTileOrigin [[attribute(1)]]; - float4 aColorTexMatrix [[attribute(2)]]; - float2 aColorTexOffset [[attribute(3)]]; + int2 aTilePosition [[attribute(0)]]; + float2 aColorTexCoord [[attribute(1)]]; }; vertex main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]]) { main0_out out = {}; - float2 tileOffset = float2(in.aTessCoord) * (*spvDescriptorSet0.uTileSize); - float2 position = (float2(in.aTileOrigin) * (*spvDescriptorSet0.uTileSize)) + tileOffset; - out.vColorTexCoord = (float2x2(float2(in.aColorTexMatrix.xy), float2(in.aColorTexMatrix.zw)) * tileOffset) + in.aColorTexOffset; + float2 position = float2(in.aTilePosition) * (*spvDescriptorSet0.uTileSize); + out.vColorTexCoord = in.aColorTexCoord; out.gl_Position = (*spvDescriptorSet0.uTransform) * float4(position, 0.0, 1.0); return out; } diff --git a/shaders/tile_alpha.fs.glsl b/shaders/tile_alpha.fs.glsl index fc2a3f31..ed6f08b0 100644 --- a/shaders/tile_alpha.fs.glsl +++ b/shaders/tile_alpha.fs.glsl @@ -2,7 +2,7 @@ // pathfinder/shaders/tile_alpha.fs.glsl // -// Copyright © 2018 The Pathfinder Project Developers. +// Copyright © 2020 The Pathfinder Project Developers. // // Licensed under the Apache License, Version 2.0 or the MIT license @@ -16,8 +16,8 @@ uniform sampler2D uStencilTexture; uniform sampler2D uPaintTexture; uniform vec2 uPaintTextureSize; -in vec2 vMaskTexCoord; in vec2 vColorTexCoord; +in vec2 vMaskTexCoord; in float vBackdrop; in vec4 vColor; diff --git a/shaders/tile_alpha.vs.glsl b/shaders/tile_alpha.vs.glsl index e589cc89..79c0e346 100644 --- a/shaders/tile_alpha.vs.glsl +++ b/shaders/tile_alpha.vs.glsl @@ -16,32 +16,20 @@ uniform mat4 uTransform; uniform vec2 uTileSize; uniform vec2 uStencilTextureSize; -in uvec2 aTessCoord; -in uvec3 aTileOrigin; -in vec4 aColorTexMatrix; -in vec2 aColorTexOffset; +in ivec2 aTilePosition; +in vec2 aColorTexCoord; +in vec2 aMaskTexCoord; in int aBackdrop; -in int aTileIndex; -out vec2 vMaskTexCoord; out vec2 vColorTexCoord; +out vec2 vMaskTexCoord; out float vBackdrop; -vec2 computeTileOffset(uint tileIndex, float stencilTextureWidth) { - uint tilesPerRow = uint(stencilTextureWidth / uTileSize.x); - uvec2 tileOffset = uvec2(tileIndex % tilesPerRow, tileIndex / tilesPerRow); - return vec2(tileOffset) * uTileSize; -} - void main() { - vec2 tileOffset = vec2(aTessCoord) * uTileSize; - vec2 origin = vec2(aTileOrigin.xy) + vec2(aTileOrigin.z & 15u, aTileOrigin.z >> 4u) * 256.0; - vec2 position = origin * uTileSize + tileOffset; - vec2 maskTexCoordOrigin = computeTileOffset(uint(aTileIndex), uStencilTextureSize.x); - vec2 maskTexCoord = maskTexCoordOrigin + tileOffset; + vec2 position = aTilePosition * uTileSize; - vMaskTexCoord = maskTexCoord / uStencilTextureSize; - vColorTexCoord = mat2(aColorTexMatrix) * tileOffset + aColorTexOffset; + vMaskTexCoord = aMaskTexCoord; + vColorTexCoord = aColorTexCoord; vBackdrop = float(aBackdrop); gl_Position = uTransform * vec4(position, 0.0, 1.0); } diff --git a/shaders/tile_solid.vs.glsl b/shaders/tile_solid.vs.glsl index 788c76ac..aeb1a41b 100644 --- a/shaders/tile_solid.vs.glsl +++ b/shaders/tile_solid.vs.glsl @@ -2,7 +2,7 @@ // pathfinder/shaders/tile_solid.vs.glsl // -// Copyright © 2019 The Pathfinder Project Developers. +// Copyright © 2020 The Pathfinder Project Developers. // // Licensed under the Apache License, Version 2.0 or the MIT license @@ -15,16 +15,13 @@ precision highp float; uniform mat4 uTransform; uniform vec2 uTileSize; -in uvec2 aTessCoord; -in ivec2 aTileOrigin; -in vec4 aColorTexMatrix; -in vec2 aColorTexOffset; +in ivec2 aTilePosition; +in vec2 aColorTexCoord; out vec2 vColorTexCoord; void main() { - vec2 tileOffset = vec2(aTessCoord) * uTileSize; - vec2 position = aTileOrigin * uTileSize + tileOffset; - vColorTexCoord = mat2(aColorTexMatrix) * tileOffset + aColorTexOffset; + vec2 position = aTilePosition * uTileSize; + vColorTexCoord = aColorTexCoord; gl_Position = uTransform * vec4(position, 0.0, 1.0); } diff --git a/simd/src/arm/mod.rs b/simd/src/arm/mod.rs index 8b2dc01f..28699d57 100644 --- a/simd/src/arm/mod.rs +++ b/simd/src/arm/mod.rs @@ -179,6 +179,14 @@ impl Add for F32x2 { } } +impl Div for F32x2 { + type Output = F32x2; + #[inline] + fn div(self, other: F32x2) -> F32x2 { + unsafe { F32x2(simd_div(self.0, other.0)) } + } +} + impl Mul for F32x2 { type Output = F32x2; #[inline] @@ -380,6 +388,14 @@ impl Add for F32x4 { } } +impl Div for F32x4 { + type Output = F32x4; + #[inline] + fn div(self, other: F32x4) -> F32x4 { + unsafe { F32x4(simd_div(self.0, other.0)) } + } +} + impl Mul for F32x4 { type Output = F32x4; #[inline] @@ -412,6 +428,18 @@ impl I32x2 { I32x2::new(x, x) } + // Accessors + + #[inline] + pub fn x(self) -> i32 { + self[0] + } + + #[inline] + pub fn y(self) -> i32 { + self[1] + } + #[inline] pub fn packed_eq(self, other: I32x2) -> U32x2 { unsafe { U32x2(simd_eq(self.0, other.0)) } @@ -750,6 +778,7 @@ impl Index for U32x4 { extern "platform-intrinsic" { fn simd_add(x: T, y: T) -> T; + fn simd_div(x: T, y: T) -> T; fn simd_mul(x: T, y: T) -> T; fn simd_sub(x: T, y: T) -> T; diff --git a/simd/src/scalar/mod.rs b/simd/src/scalar/mod.rs index 742155bd..5be22330 100644 --- a/simd/src/scalar/mod.rs +++ b/simd/src/scalar/mod.rs @@ -10,7 +10,7 @@ use std::f32; use std::fmt::{self, Debug, Formatter}; -use std::ops::{Add, BitAnd, BitOr, Index, IndexMut, Mul, Shr, Sub}; +use std::ops::{Add, BitAnd, BitOr, Div, Index, IndexMut, Mul, Shr, Sub}; mod swizzle_f32x4; mod swizzle_i32x4; @@ -166,6 +166,14 @@ impl Add for F32x2 { } } +impl Div for F32x2 { + type Output = F32x2; + #[inline] + fn div(self, other: F32x2) -> F32x2 { + F32x2([self[0] / other[0], self[1] / other[1]]) + } +} + impl Mul for F32x2 { type Output = F32x2; #[inline] @@ -403,6 +411,19 @@ impl Add for F32x4 { } } +impl Div for F32x4 { + type Output = F32x4; + #[inline] + fn div(self, other: F32x4) -> F32x4 { + F32x4([ + self[0] / other[0], + self[1] / other[1], + self[2] / other[2], + self[3] / other[3], + ]) + } +} + impl Mul for F32x4 { type Output = F32x4; #[inline] @@ -445,6 +466,18 @@ impl I32x2 { I32x2([x, x]) } + // Accessors + + #[inline] + pub fn x(self) -> i32 { + self[0] + } + + #[inline] + pub fn y(self) -> i32 { + self[1] + } + #[inline] pub fn packed_eq(self, other: I32x2) -> U32x2 { U32x2([ diff --git a/simd/src/x86/mod.rs b/simd/src/x86/mod.rs index 91f9eb20..ea8f31f0 100644 --- a/simd/src/x86/mod.rs +++ b/simd/src/x86/mod.rs @@ -11,7 +11,7 @@ use std::cmp::PartialEq; use std::fmt::{self, Debug, Formatter}; use std::mem; -use std::ops::{Add, BitAnd, BitOr, BitXor, Index, IndexMut, Mul, Not, Shr, Sub}; +use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Index, IndexMut, Mul, Not, Shr, Sub}; #[cfg(target_pointer_width = "32")] use std::arch::x86::{__m128, __m128i}; @@ -191,6 +191,14 @@ impl Add for F32x2 { } } +impl Div for F32x2 { + type Output = F32x2; + #[inline] + fn div(self, other: F32x2) -> F32x2 { + (self.to_f32x4() / other.to_f32x4()).xy() + } +} + impl Mul for F32x2 { type Output = F32x2; #[inline] @@ -423,6 +431,14 @@ impl Add for F32x4 { } } +impl Div for F32x4 { + type Output = F32x4; + #[inline] + fn div(self, other: F32x4) -> F32x4 { + unsafe { F32x4(x86::_mm_div_ps(self.0, other.0)) } + } +} + impl Mul for F32x4 { type Output = F32x4; #[inline] @@ -461,6 +477,18 @@ impl I32x2 { I32x2::new(x, x) } + // Accessors + + #[inline] + pub fn x(self) -> i32 { + self[0] + } + + #[inline] + pub fn y(self) -> i32 { + self[1] + } + // Concatenations #[inline]