Skip to content

Commit 96be4ec

Browse files
committed
Add an "Initializing Renderer…" overlay when Vello shader compilation is slow on web
1 parent 62287d7 commit 96be4ec

2 files changed

Lines changed: 49 additions & 1 deletion

File tree

frontend/src/components/panels/Document.svelte

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import Graph from "/src/components/views/Graph.svelte";
88
import RulerInput from "/src/components/widgets/inputs/RulerInput.svelte";
99
import ScrollbarInput from "/src/components/widgets/inputs/ScrollbarInput.svelte";
10+
import TextLabel from "/src/components/widgets/labels/TextLabel.svelte";
1011
import WidgetLayout from "/src/components/widgets/WidgetLayout.svelte";
1112
import type { AppWindowStore } from "/src/stores/app-window";
1213
import type { DocumentStore } from "/src/stores/document";
@@ -16,7 +17,7 @@
1617
import { pasteFile } from "/src/utility-functions/files";
1718
import { textInputCleanup } from "/src/utility-functions/keyboard-entry";
1819
import { rasterizeSVGCanvas } from "/src/utility-functions/rasterization";
19-
import { setupViewportResizeObserver } from "/src/utility-functions/viewports";
20+
import { setupViewportResizeObserver, hasFirstArtworkBeenReceived, markFirstArtworkReceived } from "/src/utility-functions/viewports";
2021
import type { EditorWrapper, MenuDirection, MouseCursorIcon, SRGBA8 } from "/wrapper/pkg/graphite_wasm_wrapper";
2122
2223
let rulerHorizontal: RulerInput | undefined;
@@ -53,6 +54,10 @@
5354
// Rendered SVG viewport data
5455
let artworkSvg = "";
5556
57+
// Web-only "Initializing Renderer…" overlay shown until the first Vello-rendered artwork arrives
58+
const isWeb = import.meta.env.MODE !== "native";
59+
let firstArtworkReceived = hasFirstArtworkBeenReceived();
60+
5661
// Rasterized SVG viewport data, or none if it's not up-to-date
5762
let rasterizedCanvas: HTMLCanvasElement | undefined = undefined;
5863
let rasterizedContext: CanvasRenderingContext2D | undefined = undefined;
@@ -470,6 +475,11 @@
470475
subscriptions.subscribeFrontendMessage("UpdateDocumentArtwork", async (data) => {
471476
await tick();
472477
478+
if (!firstArtworkReceived) {
479+
firstArtworkReceived = true;
480+
markFirstArtworkReceived();
481+
}
482+
473483
updateDocumentArtwork(data.svg);
474484
});
475485
subscriptions.subscribeFrontendMessage("UpdateEyedropperSamplingState", async (data) => {
@@ -708,6 +718,9 @@
708718
>
709719
</canvas>
710720
{/if}
721+
{#if isWeb}
722+
<TextLabel class="shader-compiling-overlay" italic={true} classes={{ show: !firstArtworkReceived }}>Initializing Renderer…</TextLabel>
723+
{/if}
711724
</div>
712725

713726
<div class="graph-view" class:open={$document.graphViewOverlayOpen} style:--fade-artwork={`${$document.fadeArtwork}%`} data-graph>
@@ -944,6 +957,31 @@
944957
unicode-bidi: plaintext;
945958
}
946959
960+
.shader-compiling-overlay {
961+
position: absolute;
962+
inset: 0;
963+
display: flex;
964+
align-items: center;
965+
justify-content: center;
966+
pointer-events: none;
967+
opacity: 0;
968+
transition: opacity 0.5s ease;
969+
970+
&.show {
971+
opacity: 1;
972+
animation: shader-compiling-overlay-fade-in 0.5s ease 0.5s both;
973+
}
974+
975+
@keyframes shader-compiling-overlay-fade-in {
976+
from {
977+
opacity: 0;
978+
}
979+
to {
980+
opacity: 1;
981+
}
982+
}
983+
}
984+
947985
.text-input div {
948986
cursor: text;
949987
background: none;

frontend/src/utility-functions/viewports.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
import type { EditorWrapper } from "/wrapper/pkg/graphite_wasm_wrapper";
22

3+
// Tracks whether any document has produced its first frame of rendered artwork yet during this app session.
4+
// Used to show the one-time "Initializing Renderer…" overlay only on the very first document open.
5+
let firstArtworkEverReceived = false;
6+
export function hasFirstArtworkBeenReceived(): boolean {
7+
return firstArtworkEverReceived;
8+
}
9+
export function markFirstArtworkReceived(): void {
10+
firstArtworkEverReceived = true;
11+
}
12+
313
export function setupViewportResizeObserver(editor: EditorWrapper): () => void {
414
const viewports = Array.from(window.document.querySelectorAll("[data-viewport-container]"));
515
if (viewports.length <= 0) return () => {};

0 commit comments

Comments
 (0)