Write shapes directly to wasm memory

This commit is contained in:
Belén Albeza 2024-10-25 15:00:57 +02:00 committed by Andrey Antukh
parent 29e0964ebc
commit 4623f36042
9 changed files with 186 additions and 139 deletions

View file

@ -72,7 +72,7 @@
(cr/update! :x2 + (:x delta))
(cr/update! :y2 + (:y delta)))
selrect (if ^boolean space?
(-> selrect
(-> (cr/clone selrect)
(cr/update! :x1 + (:x delta))
(cr/update! :y1 + (:y delta)))
selrect)]

View file

@ -134,13 +134,13 @@
hover-top-frame-id (mf/use-state nil)
frame-hover (mf/use-state nil)
active-frames (mf/use-state #{})
canvas-init? (mf/use-state false)
;; REFS
[viewport-ref
on-viewport-ref] (create-viewport-ref)
canvas-ref (mf/use-ref nil)
canvas-init (mf/use-ref false)
;; VARS
disable-paste (mf/use-var false)
@ -277,19 +277,22 @@
(when ^boolean render.wasm/enabled?
(mf/with-effect []
(time (when-let [canvas (mf/ref-val canvas-ref)]
(->> render.wasm/module
(p/fmap (fn [ready?]
(when ready?
(mf/set-ref-val! canvas-init true)
(render.wasm/assign-canvas canvas)))))
(fn []
(render.wasm/clear-canvas)))))
(->> render.wasm/module
(p/fmap (fn [ready?]
(when ready?
(reset! canvas-init? true)
(render.wasm/assign-canvas canvas)))))
(fn []
(render.wasm/clear-canvas)))))
(mf/with-effect [vbox objects-modified]
(let [sem (when (mf/ref-val canvas-init)
(render.wasm/draw-objects objects-modified zoom vbox))]
(partial render.wasm/cancel-draw sem)))
)
(mf/with-effect [objects-modified canvas-init?]
(when @canvas-init?
(render.wasm/set-objects objects-modified)
(render.wasm/draw-objects zoom vbox)))
(mf/with-effect [vbox canvas-init?]
(let [frame-id (when @canvas-init? (do
(render.wasm/draw-objects zoom vbox)))]
(partial render.wasm/cancel-draw frame-id))))
(hooks/setup-dom-events zoom disable-paste in-viewport? read-only? drawing-tool drawing-path?)
(hooks/setup-viewport-size vport viewport-ref)

View file

@ -8,6 +8,7 @@
"A WASM based render API"
(:require
[app.common.data.macros :as dm]
[app.common.files.helpers :as cfh]
[app.config :as cf]
[promesa.core :as p]))
@ -17,41 +18,31 @@
(defonce ^:dynamic internal-module #js {})
(defonce ^:dynamic internal-gpu-state #js {})
(defn draw-objects
[objects zoom vbox]
(let [draw-rect (unchecked-get internal-module "_draw_rect")
translate (unchecked-get internal-module "_translate")
reset-canvas (unchecked-get internal-module "_reset_canvas")
scale (unchecked-get internal-module "_scale")
flush (unchecked-get internal-module "_flush")
gpu-state internal-gpu-state]
(defn set-objects [objects]
(let [shapes-buffer (unchecked-get internal-module "_shapes_buffer")
heap (unchecked-get internal-module "HEAPF32")
;; size *in bytes* for each shapes::Shape
rect-size 16
;; TODO: remove the `take` once we have the dynamic data structure in Rust
supported-shapes (take 2048 (filter #(not (cfh/root? %)) (vals objects)))
mem (js/Float32Array. (.-buffer heap) (shapes-buffer) (* rect-size (count supported-shapes)))]
(run! (fn [[shape index]]
(.set mem (.-buffer shape) (* index rect-size)))
(zipmap supported-shapes (range)))))
(defn draw-objects
[zoom vbox]
(let [draw-all-shapes (unchecked-get internal-module "_draw_all_shapes")]
(js/requestAnimationFrame
(fn []
(reset-canvas gpu-state)
(scale gpu-state zoom zoom)
(let [x (dm/get-prop vbox :x)
y (dm/get-prop vbox :y)]
(translate gpu-state (- x) (- y)))
(run! (fn [shape]
;; (js/console.log "render-shape" (.-buffer shape))
(let [selrect (dm/get-prop shape :selrect)
x1 (dm/get-prop selrect :x1)
y1 (dm/get-prop selrect :y1)
x2 (dm/get-prop selrect :x2)
y2 (dm/get-prop selrect :y2)]
;; (prn (:id shape) selrect)
(draw-rect gpu-state x1 y1 x2 y2)))
(vals objects))
(flush gpu-state)))))
(let [pan-x (- (dm/get-prop vbox :x))
pan-y (- (dm/get-prop vbox :y))]
(draw-all-shapes internal-gpu-state zoom pan-x pan-y))))))
(defn cancel-draw
[sem]
(when (some? sem)
(js/cancelAnimationFrame sem)))
[frame-id]
(when (some? frame-id)
(js/cancelAnimationFrame frame-id)))
(def ^:private canvas-options
#js {:antialias true