From 7a47bdce627fa15aee8bb1dc60f77b7ff484a7ae Mon Sep 17 00:00:00 2001 From: Simon Date: Thu, 3 Oct 2024 12:01:32 +0200 Subject: [PATCH 01/20] Low hanging fruit for a bit better precompile (#4438) * low hanging fruit for a bit better precompile * need to rely on latest Bonito to not hang while precompiling * fix hangs for 1.10 * fix single plot update --- WGLMakie/Project.toml | 2 +- WGLMakie/src/display.jl | 2 +- WGLMakie/src/precompiles.jl | 14 ++++++++++++++ WGLMakie/src/serialization.jl | 2 +- src/scenes.jl | 2 +- 5 files changed, 18 insertions(+), 4 deletions(-) diff --git a/WGLMakie/Project.toml b/WGLMakie/Project.toml index e7b384f7586..02e8b8238c5 100644 --- a/WGLMakie/Project.toml +++ b/WGLMakie/Project.toml @@ -20,7 +20,7 @@ ShaderAbstractions = "65257c39-d410-5151-9873-9b3e5be5013e" StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" [compat] -Bonito = "3.2.0" +Bonito = "3.2.1" Colors = "0.11, 0.12" FileIO = "1.1" FreeTypeAbstraction = "0.10" diff --git a/WGLMakie/src/display.jl b/WGLMakie/src/display.jl index 4fe03a5c7f5..a6070ebeb4b 100644 --- a/WGLMakie/src/display.jl +++ b/WGLMakie/src/display.jl @@ -333,7 +333,7 @@ function insert_scene!(session::Session, screen::Screen, scene::Scene) end function insert_plot!(session::Session, scene::Scene, @nospecialize(plot::Plot)) - plot_data = serialize_plots(scene, [plot]) + plot_data = serialize_plots(scene, Plot[plot]) plot_sub = Session(session) Bonito.init_session(plot_sub) plot.__wgl_session = plot_sub diff --git a/WGLMakie/src/precompiles.jl b/WGLMakie/src/precompiles.jl index b6be76a9107..a4837686cf6 100644 --- a/WGLMakie/src/precompiles.jl +++ b/WGLMakie/src/precompiles.jl @@ -14,6 +14,10 @@ macro compile(block) Bonito.jsrender(session, figlike) s = serialize_scene(scene) Bonito.SerializedMessage(session, Dict(:data => s)) + session = Session() + app = App(()-> DOM.div(figlike)) + dom = Bonito.session_dom(session, app) + show(IOBuffer(), Bonito.Hyperscript.Pretty(dom)) close(session) return nothing end @@ -30,6 +34,16 @@ let Makie.CURRENT_FIGURE[] = nothing Observables.clear(TEXTURE_ATLAS) TEXTURE_ATLAS[] = Float32[] + # This should happen in atexit in Bonito, but on Julia versions below v1.11 + # atexit isn't called + for (task, (task, close_ref)) in Bonito.SERVER_CLEANUP_TASKS + close_ref[] = false + end + Bonito.CURRENT_SESSION[] = nothing + if !isnothing(Bonito.GLOBAL_SERVER[]) + close(Bonito.GLOBAL_SERVER[]) + end + Bonito.GLOBAL_SERVER[] = nothing nothing end end diff --git a/WGLMakie/src/serialization.jl b/WGLMakie/src/serialization.jl index 32e87bea64a..e2c62b012f6 100644 --- a/WGLMakie/src/serialization.jl +++ b/WGLMakie/src/serialization.jl @@ -314,7 +314,7 @@ function serialize_scene(scene::Scene) return serialized end -function serialize_plots(scene::Scene, @nospecialize(plots::Vector{T}), result=[]) where {T<:AbstractPlot} +function serialize_plots(scene::Scene, plots::Vector{Plot}, result=[]) for plot in plots # if no plots inserted, this truely is an atomic if isempty(plot.plots) diff --git a/src/scenes.jl b/src/scenes.jl index 4a9359f7681..00e21cd500f 100644 --- a/src/scenes.jl +++ b/src/scenes.jl @@ -72,7 +72,7 @@ mutable struct Scene <: AbstractScene float32convert::Union{Nothing, Float32Convert} "The plots contained in the Scene." - plots::Vector{AbstractPlot} + plots::Vector{Plot} theme::Attributes From 7737b97edee4afa03a25061bd78c3d1ce0bbc55d Mon Sep 17 00:00:00 2001 From: Frederic Freyer Date: Thu, 3 Oct 2024 15:29:56 +0200 Subject: [PATCH 02/20] Fix local serve in ReferenceUpdater (#4444) * fix serve from dir * use / for output path --- ReferenceUpdater/src/local_server.jl | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ReferenceUpdater/src/local_server.jl b/ReferenceUpdater/src/local_server.jl index fdac5c9dffd..44fb0dbaf3d 100644 --- a/ReferenceUpdater/src/local_server.jl +++ b/ReferenceUpdater/src/local_server.jl @@ -12,6 +12,7 @@ function serve_update_page_from_dir(folder) folder = realpath(folder) @assert isdir(folder) "$folder is not a valid directory." + split_scores(folder) router = HTTP.Router() @@ -145,7 +146,6 @@ function serve_update_page(; commit = nothing, pr = nothing) tmpdir = mktempdir() unzip(filepath, tmpdir) rm(filepath) - split_scores(tmpdir) URL_CACHE[download_url] = tmpdir else tmpdir = URL_CACHE[download_url] @@ -186,13 +186,15 @@ end function split_scores(path) + isfile(joinpath(path, "scores_table.tsv")) && return + # Load all refimg scores into a Dict # `filename => (score_glmakie, score_cairomakie, score_wglmakie)` data = Dict{String, Vector{Float64}}() open(joinpath(path, "scores.tsv"), "r") do file for line in eachline(file) score, filepath = split(line, '\t') - pieces = split(filepath, '/') + pieces = splitpath(filepath) backend = pieces[1] filename = join(pieces[2:end], '/') @@ -227,4 +229,5 @@ function split_scores(path) end end + return end From 2bb4de061c68bad4db02d4ddd264d3c8d83f8cf8 Mon Sep 17 00:00:00 2001 From: Simon Date: Thu, 3 Oct 2024 16:22:17 +0200 Subject: [PATCH 03/20] Accessing created Blocks/Plots for SpecApi objects (#4354) * fix user attributes for specapi + updating * add changelog * fix makie tests * make specapi work with interactions * more correctly apply hen function * re-use blocks * remove double visible * fix inspecotr for Resampler * use better score * fix tests * properly free on(visible) * correctly forward visible * add more tests and bugfixes * some optimizations * performance improvements * text update optimizations * update for more efficient update * optimizations for text updates * fix WGLMakie * fix wglmakie for real * revert for now, until we flatten GlyphCollections * fix tests * add docs --- CHANGELOG.md | 1 + WGLMakie/src/particles.jl | 37 ++- docs/src/explanations/specapi.md | 45 +++ precompile/shared-precompile.jl | 1 - src/basic_recipes/text.jl | 3 + src/interfaces.jl | 2 +- src/layouting/text_layouting.jl | 36 +-- src/makielayout/blocks.jl | 29 +- src/makielayout/blocks/legend.jl | 2 +- src/makielayout/types.jl | 3 +- src/scenes.jl | 27 +- src/specapi.jl | 517 +++++++++++++++++++------------ src/types.jl | 37 ++- test/specapi.jl | 41 +++ test/text.jl | 14 +- 15 files changed, 543 insertions(+), 252 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 89d2640f509..33c4f39a06d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## [Unreleased] +- Optimize SpecApi, re-use Blocks better and add API to access the created block objects [#4354](https://github.com/MakieOrg/Makie.jl/pull/4354). - Fix `merge(attr1, attr2)` modifying nested attributes in `attr1` [#4416](https://github.com/MakieOrg/Makie.jl/pull/4416) - Fixed issue with CairoMakie rendering scene backgrounds at the wrong position [#4425](https://github.com/MakieOrg/Makie.jl/pull/4425) - Fix incorrect inverse transformation in `position_on_plot` for lines, causing incorrect tooltip placement in DataInspector [#4402](https://github.com/MakieOrg/Makie.jl/pull/4402) diff --git a/WGLMakie/src/particles.jl b/WGLMakie/src/particles.jl index 25d309fb8b4..34d97fd7964 100644 --- a/WGLMakie/src/particles.jl +++ b/WGLMakie/src/particles.jl @@ -179,7 +179,7 @@ function scatter_shader(scene::Scene, attributes, plot) end per_instance = filter(attributes) do (k, v) - return k in per_instance_keys && !(isscalar(v[])) + return k in per_instance_keys && !(isscalar(to_value(v))) end for (k, v) in per_instance @@ -218,7 +218,6 @@ function scatter_shader(scene::Scene, attributes, plot) handle_color!(plot, uniform_dict, per_instance, :color) handle_color_getter!(uniform_dict, per_instance) - if haskey(uniform_dict, :color) && haskey(per_instance, :color) to_value(uniform_dict[:color]) isa Bool && delete!(uniform_dict, :color) to_value(per_instance[:color]) isa Bool && delete!(per_instance, :color) @@ -238,14 +237,23 @@ function scatter_shader(scene::Scene, attributes, plot) get!(uniform_dict, :strokecolor, RGBAf(0, 0, 0, 0)) get!(uniform_dict, :glowwidth, 0f0) get!(uniform_dict, :glowcolor, RGBAf(0, 0, 0, 0)) - + _, arr = first(per_instance) + if any(v-> length(arr) != length(v), values(per_instance)) + lens = [k => length(v) for (k, v) in per_instance] + error("Not all have the same length: $(lens)") + end return InstancedProgram(WebGL(), lasset("sprites.vert"), lasset("sprites.frag"), instance, VertexArray(; per_instance...), uniform_dict) end function create_shader(scene::Scene, plot::Scatter) # Potentially per instance attributes - attributes = copy(plot.attributes.attributes) + # create new dict so we don't automatically convert to observables + # Which is the case for Dict{Symbol, Observable} + attributes = Dict{Symbol, Any}() + for (k, v) in plot.attributes.attributes + attributes[k] = v + end space = get(attributes, :space, :data) attributes[:preprojection] = Mat4f(I) # calculate this in JS f32c, model = Makie.patch_model(plot) @@ -272,7 +280,6 @@ function create_shader(scene::Scene, plot::Makie.Text{<:Tuple{<:Union{<:Makie.Gl glyphcollection = plot[1] f32c, model = Makie.patch_model(plot) pos = apply_transform_and_f32_conversion(plot, f32c, plot.position) - space = plot.space offset = plot.offset atlas = wgl_texture_atlas() @@ -282,24 +289,23 @@ function create_shader(scene::Scene, plot::Makie.Text{<:Tuple{<:Union{<:Makie.Gl # unpack values from the one signal: positions, char_offset, quad_offset, uv_offset_width, scale = map((1, 2, 3, 4, 5)) do i - return lift(getindex, plot, glyph_data, i) + return lift(getindex, plot, glyph_data, i; ignore_equal_values=true) end - uniform_color = lift(plot, glyphcollection) do gc + uniform_color = lift(plot, glyphcollection; ignore_equal_values=true) do gc if gc isa AbstractArray - reduce(vcat, (Makie.collect_vector(g.colors, length(g.glyphs)) for g in gc), - init = RGBAf[]) + reduce(vcat, (Makie.collect_vector(g.colors, length(g.glyphs)) for g in gc); + init=RGBAf[]) else - Makie.collect_vector(gc.colors, length(gc.glyphs)) + gc.colors.sv end end - - uniform_rotation = lift(plot, glyphcollection) do gc + uniform_rotation = lift(plot, glyphcollection; ignore_equal_values=true) do gc if gc isa AbstractArray - reduce(vcat, (Makie.collect_vector(g.rotations, length(g.glyphs)) for g in gc), - init = Quaternionf[]) + reduce(vcat, (Makie.collect_vector(g.rotations, length(g.glyphs)) for g in gc); + init=Quaternionf[]) else - Makie.collect_vector(gc.rotations, length(gc.glyphs)) + gc.rotations.sv end end @@ -321,6 +327,5 @@ function create_shader(scene::Scene, plot::Makie.Text{<:Tuple{<:Union{<:Makie.Gl :glowwidth => plot.glowwidth, :glowcolor => plot.glowcolor, ) - return scatter_shader(scene, uniforms, plot_attributes) end diff --git a/docs/src/explanations/specapi.md b/docs/src/explanations/specapi.md index 3870aaf6555..11c8d8ba232 100644 --- a/docs/src/explanations/specapi.md +++ b/docs/src/explanations/specapi.md @@ -310,3 +310,48 @@ nothing # hide ```@raw html