Try to optimize

This commit is contained in:
Michael Pfaff 2024-06-22 16:58:25 -04:00
parent 5fa9e8f883
commit ca750dda7b
13 changed files with 557 additions and 380 deletions

View File

@ -4,6 +4,9 @@ version = "0.1.0"
authors = ["Patrick Walton <pcwalton@mimiga.net>"]
edition = "2018"
[features]
metal = ["dep:core-foundation", "dep:io-surface", "dep:metal", "dep:pathfinder_metal"]
[lib]
crate-type = ["staticlib", "cdylib"]
name = "pathfinder"
@ -51,10 +54,18 @@ path = "../simd"
[dependencies.pathfinder_svg]
path = "../svg"
[target.'cfg(target_os = "macos")'.dependencies]
core-foundation = "0.6"
io-surface = "0.12"
metal = "0.18"
[target.'cfg(target_os = "macos")'.dependencies.core-foundation]
version = "0.6"
optional = true
[target.'cfg(target_os = "macos")'.dependencies.io-surface]
version = "0.12"
optional = true
[target.'cfg(target_os = "macos")'.dependencies.metal]
version = "0.18"
optional = true
[target.'cfg(target_os = "macos")'.dependencies.pathfinder_metal]
path = "../metal"
optional = true

File diff suppressed because it is too large Load Diff

View File

@ -78,10 +78,8 @@ pub struct Canvas {
impl Canvas {
#[inline]
pub fn new(size: Vector2F) -> Canvas {
let mut scene = Scene::new();
scene.set_view_box(RectF::new(Vector2F::zero(), size));
Canvas::from_scene(scene)
pub fn new() -> Canvas {
Canvas::from_scene(Scene::new())
}
#[inline]
@ -130,10 +128,10 @@ impl Canvas {
self.scene.view_box().size().ceil().to_i32()
}
pub fn set_size(&mut self, new_size: Vector2I) {
let new_view_box = RectI::new(Vector2I::default(), new_size).to_f32();
self.scene.set_bounds(new_view_box);
self.scene.set_view_box(new_view_box);
/// This resets the canvas' bounds. Do not call this mid-draw.
pub fn set_size(&mut self, new_size: Vector2F) {
self.scene.set_bounds(RectF::default());
self.scene.set_view_box(RectF::new(Vector2F::zero(), new_size));
}
}

View File

@ -10,7 +10,7 @@
use crate::{CanvasRenderingContext2D, State, TextAlign, TextBaseline};
use font_kit::canvas::RasterizationOptions;
use font_kit::error::{FontLoadingError, SelectionError};
use font_kit::error::{GlyphLoadingError, FontLoadingError, SelectionError};
use font_kit::family_name::FamilyName;
use font_kit::handle::Handle;
use font_kit::hinting::HintingOptions;
@ -36,10 +36,10 @@ impl CanvasRenderingContext2D {
/// fill the text that you passed into `measure_text()` with the layout-related style
/// properties set at the time you called that function. This allows Pathfinder to skip having
/// to lay out the text again.
pub fn fill_text<T>(&mut self, text: &T, position: Vector2F) where T: ToTextLayout + ?Sized {
pub fn fill_text<T>(&mut self, text: &T, position: Vector2F) -> Result<(), GlyphLoadingError> where T: ToTextLayout + ?Sized {
let paint = self.current_state.resolve_paint(&self.current_state.fill_paint);
let paint_id = self.canvas.scene.push_paint(&paint);
self.fill_or_stroke_text(text, position, paint_id, TextRenderMode::Fill);
self.fill_or_stroke_text(text, position, paint_id, TextRenderMode::Fill)
}
/// Strokes the given text using the current style.
@ -48,11 +48,11 @@ impl CanvasRenderingContext2D {
/// stroke the text that you passed into `measure_text()` with the layout-related style
/// properties set at the time you called that function. This allows Pathfinder to skip having
/// to lay out the text again.
pub fn stroke_text<T>(&mut self, text: &T, position: Vector2F) where T: ToTextLayout + ?Sized {
pub fn stroke_text<T>(&mut self, text: &T, position: Vector2F) -> Result<(), GlyphLoadingError> where T: ToTextLayout + ?Sized {
let paint = self.current_state.resolve_paint(&self.current_state.stroke_paint);
let paint_id = self.canvas.scene.push_paint(&paint);
let render_mode = TextRenderMode::Stroke(self.current_state.resolve_stroke_style());
self.fill_or_stroke_text(text, position, paint_id, render_mode);
self.fill_or_stroke_text(text, position, paint_id, render_mode)
}
/// Returns metrics of the given text using the current style.
@ -68,7 +68,7 @@ impl CanvasRenderingContext2D {
text: &T,
mut position: Vector2F,
paint_id: PaintId,
render_mode: TextRenderMode)
render_mode: TextRenderMode) -> Result<(), GlyphLoadingError>
where T: ToTextLayout + ?Sized {
let layout = text.layout(CanvasState(&self.current_state));
@ -78,8 +78,7 @@ impl CanvasRenderingContext2D {
position += layout.text_origin();
let transform = self.current_state.transform * Transform2F::from_translation(position);
// TODO(pcwalton): Report errors.
drop(self.canvas_font_context
self.canvas_font_context
.0
.borrow_mut()
.font_context
@ -93,7 +92,9 @@ impl CanvasRenderingContext2D {
clip_path,
blend_mode,
paint_id,
}));
})?;
Ok(())
}
// Text styles

View File

@ -12,7 +12,7 @@ egl = "0.2"
log = "0.4"
smallvec = "1.2"
glutin = { version = "0.23", optional = true }
crossbeam-channel = "0.4"
flume = { version = "0.11", default-features = false, features = ["eventual-fairness"] }
[lib]
crate-type = ["cdylib"]

View File

@ -66,8 +66,8 @@ mod magicleap;
mod mocked_c_api;
struct ImmersiveApp {
sender: crossbeam_channel::Sender<Event>,
receiver: crossbeam_channel::Receiver<Event>,
sender: flume::Sender<Event>,
receiver: flume::Receiver<Event>,
demo: DemoApp<MagicLeapWindow>,
}
@ -96,7 +96,7 @@ pub extern "C" fn magicleap_pathfinder_demo_init(egl_display: EGLDisplay, egl_co
let demo = DemoApp::new(window, window_size, options);
info!("Initialized app");
let (sender, receiver) = crossbeam_channel::unbounded();
let (sender, receiver) = flume::unbounded();
Box::into_raw(Box::new(ImmersiveApp { sender, receiver, demo })) as *mut c_void
}

View File

@ -785,7 +785,7 @@ impl Device for GLDevice {
}
fn end_commands(&self) {
unsafe { gl::Flush(); }
//unsafe { gl::Flush(); }
}
fn draw_arrays(&self, index_count: u32, render_state: &RenderState<Self>) {

View File

@ -12,7 +12,7 @@ homepage = "https://github.com/servo/pathfinder"
bitflags = "1.0"
byte-slice-cast = "0.3"
byteorder = "1.2"
crossbeam-channel = "0.4"
flume = { version = "0.11", default-features = false, features = ["eventual-fairness"] }
fxhash = "0.2"
half = "1.5"
hashbrown = "0.7"

View File

@ -25,7 +25,7 @@ use crate::gpu::renderer::Renderer;
use crate::gpu_data::RenderCommand;
use crate::options::{BuildOptions, RenderCommandListener};
use crate::scene::{Scene, SceneSink};
use crossbeam_channel::{self, Receiver, Sender};
use flume::{self, Receiver, Sender};
use pathfinder_geometry::rect::RectF;
use pathfinder_gpu::Device;
use std::thread;
@ -60,9 +60,9 @@ impl SceneProxy {
-> SceneProxy
where E: Executor + Send + 'static {
let (main_to_worker_sender, main_to_worker_receiver) =
crossbeam_channel::bounded(MAX_MESSAGES_IN_FLIGHT);
flume::bounded(MAX_MESSAGES_IN_FLIGHT);
let (worker_to_main_sender, worker_to_main_receiver) =
crossbeam_channel::bounded(MAX_MESSAGES_IN_FLIGHT);
flume::bounded(MAX_MESSAGES_IN_FLIGHT);
let listener = RenderCommandListener::new(Box::new(move |command| {
drop(worker_to_main_sender.send(command))
}));
@ -122,7 +122,7 @@ impl SceneProxy {
/// Returns a copy of the wrapped scene.
#[inline]
pub fn copy_scene(&self) -> Scene {
let (sender, receiver) = crossbeam_channel::bounded(MAX_MESSAGES_IN_FLIGHT);
let (sender, receiver) = flume::bounded(MAX_MESSAGES_IN_FLIGHT);
self.sender.send(MainToWorkerMsg::CopyScene(sender)).unwrap();
receiver.recv().unwrap()
}

View File

@ -646,7 +646,7 @@ impl<D> Renderer<D> where D: Device {
location: TextureLocation { page: TexturePageId(!0), rect: RectI::default() },
});
}
let mut render_target =
let render_target =
&mut self.core.render_targets[render_target_id.render_target as usize];
debug_assert_eq!(render_target.location.page, TexturePageId(!0));
render_target.location = location;

View File

@ -49,7 +49,8 @@ impl<'a> RenderCommandListener<'a> {
}
/// Options that influence scene building.
#[derive(Clone, Default)]
#[derive(Clone, Copy, Default)]
#[repr(C)]
pub struct BuildOptions {
/// A global transform to be applied to the scene.
pub transform: RenderTransform,
@ -71,7 +72,7 @@ impl BuildOptions {
}
/// A global transform to apply to the scene.
#[derive(Clone)]
#[derive(Clone, Copy)]
pub enum RenderTransform {
/// A 2D transform.
Transform2D(Transform2F),

View File

@ -587,7 +587,7 @@ impl Palette {
texture_manager: &mut PaintTextureManager,
render_transform: Transform2F) {
for (paint, metadata) in self.paints.iter().zip(paint_metadata.iter_mut()) {
let mut color_texture_metadata = match metadata.color_texture_metadata {
let color_texture_metadata = match metadata.color_texture_metadata {
None => continue,
Some(ref mut color_texture_metadata) => color_texture_metadata,
};
@ -843,7 +843,7 @@ impl GradientTileBuilder {
})
}
let mut data = self.tiles.last_mut().unwrap();
let data = self.tiles.last_mut().unwrap();
let location = TextureLocation {
page: data.page,
rect: RectI::new(vec2i(0, data.next_index as i32),

View File

@ -34,6 +34,8 @@ use std::u64;
static NEXT_SCENE_ID: AtomicUsize = AtomicUsize::new(0);
const MAX_MESSAGES_IN_FLIGHT: usize = 1024;
/// The vector scene to be rendered.
#[derive(Clone)]
pub struct Scene {
@ -370,11 +372,29 @@ impl Scene {
renderer: &mut Renderer<D>,
build_options: BuildOptions,
executor: E)
where D: Device, E: Executor {
let commands = self.build_into_vector(renderer, build_options, executor);
where D: Device, E: Executor + Send {
std::thread::scope(move |scope| {
let (tx, rx) = flume::bounded(MAX_MESSAGES_IN_FLIGHT);
let level = renderer.mode().level;
// TODO: avoid this auxiliary thread
scope.spawn(move || {
let listener = RenderCommandListener::new(Box::new(move |command| {
tx.send(command).unwrap()
}));
let mut sink = SceneSink::new(listener, level);
self.build(build_options, &mut sink, &executor);
});
renderer.begin_scene();
commands.into_iter().for_each(|command| renderer.render_command(&command));
for command in rx {
renderer.render_command(&command);
}
renderer.end_scene();
});
}
}