Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
gpu_host_select.hpp
Go to the documentation of this file.
1#pragma once
2
7
8#include <cstdlib>
9#include <cstring>
10
11// Shared GPU PluginViewHost auto-selection for every plugin format adapter
12// (AU v2 / VST3 / CLAP / iOS AUv3). The renderer, JS runtime, Yoga layout,
13// and surface management are identical across formats — only the per-format
14// shell/lifecycle glue differs — so the *decision* of whether to request the
15// GPU host belongs in one place.
16//
17// A developer building a Skia/Dawn/scripted editor gets the GPU host
18// automatically; they never hand-set a flag. Hardcoding `use_gpu=false` is
19// exactly the trap that made the ChainerSynth AU fall back to AutoUi/CPU.
20
21namespace pulp::format {
22
27 const char* v = std::getenv("PULP_DISABLE_PLUGIN_GPU");
28 return v != nullptr && v[0] != '\0' && std::strcmp(v, "0") != 0;
29}
30
32 bool use_gpu = false;
33 const char* mode = "autoui";
34 bool wants_gpu = false;
35 bool create_view_null = false;
36};
37
48 const view::View* v = bridge.view();
49 d.create_view_null = (v == nullptr);
50
51 const bool scripted = bridge.uses_script_ui();
52 const bool view_wants = (v != nullptr) && v->requires_gpu_host();
53 d.wants_gpu = scripted || view_wants;
54
55 if (scripted) {
56 d.mode = "scripted";
57 } else if (view_wants) {
58 d.mode = "custom";
59 } else {
60 d.mode = "autoui";
61 }
62
63 const bool env_off = plugin_gpu_disabled_by_env();
64 d.use_gpu = d.wants_gpu && !env_off;
65
66 // Build-type flag (#perf): a Debug / unoptimized build makes the editor
67 // (and DSP) feel sluggish in a DAW regardless of the GPU/JS path — the most
68 // common "why is this slow?" cause. Surface it in the same log line so it's
69 // obvious in Console/log stream which build a host loaded, and warn loudly
70 // once on Debug. `pulp build` defaults to Release; raw cmake without
71 // -DCMAKE_BUILD_TYPE does not, so this catches both.
72#ifdef NDEBUG
73 constexpr const char* kBuildType = "release";
74#else
75 constexpr const char* kBuildType = "debug";
76#endif
78 "[plugin-gpu-host] adapter mode={} use_gpu={} wants_gpu={} "
79 "env_disabled={} scripted={} requires_gpu_host={} create_view_null={} build={}",
80 d.mode, d.use_gpu, d.wants_gpu, env_off, scripted, view_wants,
81 d.create_view_null, kBuildType);
82#ifndef NDEBUG
83 static bool warned_debug = false;
84 if (!warned_debug) {
85 warned_debug = true;
87 "[plugin-gpu-host] DEBUG build — the plugin UI/DSP will be noticeably "
88 "slower than a Release build. Build Release (the `pulp build` default; "
89 "with raw cmake pass -DCMAKE_BUILD_TYPE=Release) before judging perf.");
90 }
91#endif
92
93 return d;
94}
95
105 const ViewBridge& bridge, const GpuHostDecision& gpu,
108 opts.size = size;
109 opts.use_gpu = gpu.use_gpu;
111 return opts;
112}
113
128 const view::PluginViewHost* host) {
129#ifdef PULP_HAS_SKIA
130 if (!d.use_gpu || host == nullptr) return;
132 return;
134 "[plugin-gpu-host] gpu-init-failed falling_back=cpu mode={} "
135 "use_gpu=true host=cpu — a GPU/scripted editor view silently "
136 "fell back to CPU rendering. Check Dawn/Metal availability in the "
137 "host process (or set PULP_DISABLE_PLUGIN_GPU=1 intentionally).",
138 d.mode);
139#else
140 (void) d;
141 (void) host;
142#endif
143}
144
163 const GpuHostDecision& decision, const char* format_tag) {
165 const bool expected_gpu = decision.use_gpu;
166 const char* mode = decision.mode;
167 return host.observe_gpu_surface(
168 [session, expected_gpu, mode,
169 format_tag](const view::PluginViewHost::GpuSurfaceStatus& status) {
170 // Route navigator.gpu / canvas.getContext('webgpu') through the
171 // host's live GpuSurface — and, just as importantly, DETACH on the
172 // way down so the session never holds a dangling surface.
173 if (session) session->attach_gpu_surface(status.surface);
174
175 switch (status.state) {
176 case State::ready:
178 "[plugin-gpu-host] GpuSurface attached to WidgetBridge "
179 "via ScriptedUiSession ({})",
180 format_tag);
181 break;
182 case State::unavailable:
183 if (expected_gpu) {
185 "[plugin-gpu-host] gpu-init-failed falling_back=cpu "
186 "mode={} use_gpu=true host=cpu ({}) — a "
187 "GPU/scripted editor view has no GPU surface. Check "
188 "Dawn availability in the host process (or set "
189 "PULP_DISABLE_PLUGIN_GPU=1 intentionally).",
190 mode, format_tag);
191 }
192 break;
193 case State::pending:
194 // Not yet created. Nothing to say and nothing to warn
195 // about — this is the normal Windows pre-attach state.
196 break;
197 }
198 });
199}
200
201} // namespace pulp::format
Definition view_bridge.hpp:76
std::uint32_t editor_background_rgb() const
The editor's background as 0xRRGGBB, resolved when open() builds the view: Processor::editor_backgrou...
Definition view_bridge.hpp:333
bool uses_script_ui() const
Definition view_bridge.hpp:272
view::View * view()
Definition view_bridge.hpp:269
Definition plugin_view_host.hpp:348
Definition plugin_view_host.hpp:64
GpuSurfaceState
Definition plugin_view_host.hpp:330
@ unavailable
Definition plugin_view_host.hpp:330
The part of a scripted editor session that editor hosts drive: the frame pump, the content-first open...
Definition scripted_editor_session.hpp:19
virtual void attach_gpu_surface(render::GpuSurface *gpu_surface)=0
See ScriptedUiSession::attach_gpu_surface().
Definition view.hpp:73
What the product grants a device: the quota table indexed by capability tier and live thermal state.
Definition aax_editor.hpp:31
void warn_if_unexpected_cpu_fallback(const GpuHostDecision &d, const view::PluginViewHost *host)
Scream-guard (runtime): after the host's surface state is DECIDED, verify the GPU path actually took.
Definition gpu_host_select.hpp:127
bool plugin_gpu_disabled_by_env()
Runtime opt-out: PULP_DISABLE_PLUGIN_GPU=1 forces the CoreGraphics CPU path.
Definition gpu_host_select.hpp:26
GpuHostDecision decide_gpu_host(const ViewBridge &bridge)
Decide whether the GPU host should be requested for bridge, and emit the [plugin-gpu-host] debug-pari...
Definition gpu_host_select.hpp:46
view::PluginViewHost::Options editor_host_options(const ViewBridge &bridge, const GpuHostDecision &gpu, view::PluginViewHost::Size size)
The editor-host options every format adapter builds its PluginViewHost from: the size the adapter neg...
Definition gpu_host_select.hpp:104
view::PluginViewHost::GpuSurfaceSubscription bind_gpu_surface(view::PluginViewHost &host, view::ScriptedEditorSession *session, const GpuHostDecision &decision, const char *format_tag)
Wire a host's GPU-surface lifecycle to a scripted UI session, for every format.
Definition gpu_host_select.hpp:162
Bounded event contracts shared by host ingress and graph-authored nodes.
Definition anticipation_eligibility.hpp:9
void log_warn(std::format_string< Args... > fmt, Args &&... args)
Definition log.hpp:190
void log_error(std::format_string< Args... > fmt, Args &&... args)
Definition log.hpp:195
void log_info(std::format_string< Args... > fmt, Args &&... args)
Definition log.hpp:185
Definition gpu_host_select.hpp:31
bool create_view_null
bridge has no view (open failed)
Definition gpu_host_select.hpp:35
bool use_gpu
final request passed to PluginViewHost::Options
Definition gpu_host_select.hpp:32
const char * mode
"scripted" | "custom" | "autoui"
Definition gpu_host_select.hpp:33
bool wants_gpu
capability signal, before env opt-out
Definition gpu_host_select.hpp:34
Definition plugin_view_host.hpp:333
render::GpuSurface * surface
non-null iff state==ready
Definition plugin_view_host.hpp:334
GpuSurfaceState state
Definition plugin_view_host.hpp:335
Definition plugin_view_host.hpp:100
bool use_gpu
Use GPU rendering (Dawn/Skia Graphite) instead of CoreGraphics.
Definition plugin_view_host.hpp:102
std::uint32_t background_rgb
The editor's own background, 0xRRGGBB.
Definition plugin_view_host.hpp:126
Size size
Definition plugin_view_host.hpp:101
Definition plugin_view_host.hpp:66