GPU compute pipeline for non-rendering workloads (e.g. More...
#include <gpu_compute.hpp>
Classes | |
| struct | WavenetLayerArraySpec |
| One WaveNet layer-array's static shape. More... | |
| struct | ReadbackResult |
| struct | AsyncStats |
| Counters for the async path, incremented where the work actually happens: submits at the queue submit, map_resolves when the GPU map callback fires, expired/failed when a request completes with that status. More... | |
| struct | CapabilityReport |
| Runtime GPU capability/limit report for the compute device. More... | |
| struct | DeviceSharingReport |
| struct | BenchmarkResult |
Public Types | |
| enum class | ReadbackStatus { Success , Expired , Failed } |
| using | ReadbackCallback = std::function<void(const ReadbackResult&)> |
Public Member Functions | |
| virtual | ~GpuCompute ()=default |
| virtual bool | initialize_from_surface (GpuSurface &surface)=0 |
| Initialize from an existing GpuSurface's device (device sharing). | |
| virtual bool | initialize_standalone ()=0 |
| Initialize standalone (creates its own device, no rendering surface). | |
| virtual bool | initialize_from_device (void *wgpu_device)=0 |
| Initialize by adopting an already-created WebGPU device. | |
| bool | is_initialized () const |
| virtual bool | device_lost () const =0 |
| True once the WebGPU device has been lost. | |
| virtual std::uint64_t | device_generation () const |
| Monotonic device generation. | |
| virtual void | notify_device_lost ()=0 |
| Report that an ADOPTED device (initialize_from_device / initialize_from_surface) has been lost. | |
| virtual void | notify_device_lost (std::uint64_t generation) |
| virtual void | post_device_lost (std::uint64_t generation) |
| Publish a loss from a backend callback without touching readback queues or invoking user completions. | |
| virtual bool | compute_magnitude (const float *complex_pairs, float *magnitudes, uint32_t num_bins)=0 |
| Compute magnitude spectrum from interleaved complex float pairs. | |
| virtual bool | complex_multiply (const float *a, const float *b, float *result, uint32_t count)=0 |
| Element-wise complex multiply (frequency-domain convolution step). | |
| virtual bool | batch_magnitude (const float *complex_frames, float *magnitude_frames, uint32_t bins_per_frame, uint32_t num_frames)=0 |
| Batch spectral magnitude: processes multiple FFT frames in one dispatch. | |
| virtual bool | fft_forward (const float *complex_in, float *complex_out, uint32_t n)=0 |
| Forward DFT: X[k] = sum_n x[n] exp(-2*pi*i*k*n/N). | |
| virtual bool | fft_inverse (const float *complex_in, float *complex_out, uint32_t n)=0 |
| Inverse DFT, normalized by 1/N (so ifft(fft(x)) == x within tolerance). | |
| virtual bool | fft_forward_timed (const float *complex_in, float *complex_out, uint32_t n, double *gpu_compute_us)=0 |
| Forward FFT that also reports the TRUE GPU compute time (microseconds) of the transform passes, measured with compute-pass timestamp queries — i.e. | |
| virtual bool | prepare_convolution (uint32_t n, const float *ir_spec)=0 |
| Build the resident convolution plan for size n (power of two) and upload ir_spec — the interleaved-complex spectrum of the zero-padded IR (length 2*n, e.g. | |
| virtual bool | convolve (const float *in_complex, float *out_complex, uint32_t n)=0 |
| Run the fused convolution for a prepared n. | |
| virtual bool | prepare_convolution_batch (uint32_t n, const float *ir_spec, uint32_t batch)=0 |
| Batched fused convolution: batch independent length-n blocks convolved with the same resident IR, in ONE submit with ONE readback — amortizing the dominant round-trip across all blocks. | |
| virtual bool | convolve_batch (const float *in_complex, float *out_complex, uint32_t n, uint32_t batch)=0 |
| virtual bool | prepare_multi_convolution (uint32_t n, const float *ir_specs, uint32_t num_ir)=0 |
| Build the multi-IR plan for size n (power of two) and upload ir_specs — num_ir back-to-back interleaved-complex IR spectra (length 2*n*num_ir). | |
| virtual bool | multi_convolve (const float *in_complex, const float *pan_l, const float *pan_r, float *out_lr, uint32_t n, uint32_t num_ir)=0 |
| Run the multi-IR convolution for a prepared (n, num_ir). | |
| virtual bool | multi_convolve_timed (const float *in_complex, const float *pan_l, const float *pan_r, float *out_lr, uint32_t n, uint32_t num_ir, double *gpu_compute_us)=0 |
| Same as multi_convolve, but also reports the true GPU-busy time of the fused pass sequence (forward FFT → broadcast multiply → batched inverse FFT → pan-combine) in microseconds via gpu_compute_us, measured with a compute-pass timestamp query — excluding the input upload and the blocking readback. | |
| virtual bool | prepare_multi_fdl (uint32_t n, const float *ir_part_specs, uint32_t num_ir, uint32_t num_part)=0 |
| Build the partitioned-FDL plan for n = 2*block. | |
| virtual bool | multi_fdl_convolve (const float *in_block, const float *pan_l, const float *pan_r, float *out_block, uint32_t n, uint32_t num_ir)=0 |
| Run one block of partitioned-FDL convolution for a prepared (n, num_ir). | |
| virtual bool | prepare_spectral_stack (uint32_t n, uint32_t hop, uint32_t num_layers)=0 |
| Build the spectral-stack plan for FFT size n (power of two), STFT hop hop, and num_layers resident layer-spectra. | |
| virtual bool | spectral_stack_set_layer (uint32_t layer, const float *mag, const float *phase, uint32_t n, uint32_t num_layers)=0 |
| Upload one captured layer's magnitude (mag, n reals) and initial phase (phase, n reals) into the resident plan for (n, num_layers), activating it. | |
| virtual bool | spectral_stack_render (const float *layer_weights, uint32_t num_layers, float smear, float jitter, uint32_t rng_seed, float *frame_out, uint32_t n)=0 |
| Advance + smear + weighted-sum all resident layers and inverse-FFT to one real frame. | |
| virtual bool | matmul (const float *a, const float *b, float *c, uint32_t m, uint32_t k, uint32_t n)=0 |
| Dense matrix multiply C[M×N] = A[M×K] · B[K×N], all row-major f32. | |
| virtual bool | additive_synth (const float *partials, float *out, uint32_t num_partials, uint32_t num_samples, float sample_rate, float t0_samples)=0 |
| GPU additive synthesis: out[s] = Σ_p amp_p · sin(2π·freq_p·(t0+s)/sr + phase_p), one thread per output sample summing all partials. | |
| virtual bool | modal_strike (const float *modes, float *out, uint32_t num_modes, uint32_t num_samples, float sample_rate, float t0_samples)=0 |
| GPU struck modal synthesis: out[s] = Σ_m amp_m·exp(-decay_m·t)· sin(2π·freq_m·t + phase_m), t=(t0+s)/sr. | |
| virtual bool | granular_cloud (const float *grains, const float *source, float *out, uint32_t num_grains, uint32_t source_len, uint32_t num_samples)=0 |
| GPU granular synthesis ("grain cloud"): sum many Hann-windowed, pitch-shifted snippets of source into out, one GPU thread per output sample. | |
| virtual bool | dense_tanh (const float *input, const float *weights, const float *bias, float *output, uint32_t in_dim, uint32_t out_dim)=0 |
| GPU dense (fully-connected) layer with tanh activation: out[j] = tanh(Σ_i W[j][i]·x[i] + b[j]), one thread per output neuron. | |
| virtual bool | prepare_conv_stack (uint32_t channels, uint32_t kernel, const uint32_t *dilations, uint32_t num_layers, const float *weights, uint32_t weights_len, uint32_t block_size, float head_scale)=0 |
| Build the conv-stack plan: upload weights, allocate the per-layer device-resident activation buffers for block_size samples, and compile the fused pass pipeline. | |
| virtual bool | conv_stack_forward (const float *in_block, float *out_block, uint32_t block_size)=0 |
| Run the fused forward for one mono block (block_size samples in/out): input projection, the dilated gated conv layers, and the linear head, all in one submit. | |
| virtual bool | prepare_wavenet (const WavenetLayerArraySpec *arrays, uint32_t num_arrays, const float *weights, uint32_t weights_len, uint32_t block_size, float head_scale, uint32_t instance=0)=0 |
| Build the WaveNet plan: upload weights (flat, length weights_len, head_scale is the trailing scalar passed separately here), allocate the per-array/per-layer device-resident activation + head buffers for block_size samples, and compile the fused passes. | |
| virtual bool | wavenet_forward (const float *in_block, float *out_block, uint32_t block_size, uint32_t instance=0)=0 |
| Run the fused WaveNet forward for one mono block (block_size in/out): the per-array rechannel, dilated conv layers (+ condition mixin, activation, residual, head accumulate), head rechannels, and the final head_scale, all in one submit. | |
| virtual bool | prepare_wavenet_group (const WavenetLayerArraySpec *, uint32_t, const float *const *, uint32_t, const float *, uint32_t, uint32_t, uint32_t) |
| Prepare a group of count independent WaveNet instances that share one shape (arrays) and run as one unit: weights[i] / head_scales[i] are instance i's blob and head_scale, laid out exactly as for prepare_wavenet(). | |
| virtual bool | wavenet_forward_group (const float *const *, float *const *, uint32_t, uint32_t, uint32_t, double *gpu_busy_us=nullptr) |
| Run one block for every instance of a prepared group: in_blocks[i] / out_blocks[i] are instance i's block_size samples, and count must equal the prepared count. | |
| virtual bool | wavenet_forward_batch (const float *const *in_blocks, float *const *out_blocks, const uint32_t *instances, uint32_t count, uint32_t block_size, double *gpu_busy_us=nullptr) |
| Run one block for count independent WaveNet instances at once. | |
| virtual uint64_t | compute_magnitude_async (const float *complex_pairs, float *magnitudes, uint32_t num_bins, std::chrono::microseconds deadline, ReadbackCallback on_complete)=0 |
| Non-blocking counterpart of compute_magnitude(). | |
| virtual uint64_t | convolve_batch_async (const float *in_complex, float *out_complex, uint32_t n, uint32_t batch, std::chrono::microseconds deadline, ReadbackCallback on_complete)=0 |
| Non-blocking counterpart of convolve_batch(). | |
| virtual std::size_t | poll_readbacks ()=0 |
| Pump the device event queue once and fire the completions that are ready or past their deadline. | |
| virtual std::size_t | readbacks_in_flight () const =0 |
| Requests submitted whose completion has not fired yet. | |
| virtual void | set_max_readbacks_in_flight (std::size_t max_in_flight)=0 |
| Cap on concurrently in-flight async readbacks (default 4). | |
| virtual AsyncStats | async_stats () const =0 |
| virtual void | set_async_timing_enabled (bool) |
| Opt the ASYNC convolution path into GPU-busy timing (default OFF). | |
| virtual double | last_gpu_busy_ns () const |
| The most recent GPU-busy time of the async convolution shader, in nanoseconds (EMA-smoothed), or 0 when timing is disabled, unsupported, or the device quantized a small dispatch to 0 ns (Metal/Chrome do). | |
| virtual const char * | kernel_source (const char *label) const =0 |
| Built-in WGSL for a named pipeline (e.g. | |
| virtual bool | override_kernel_source (const char *label, const char *wgsl)=0 |
| Replace the WGSL of a named pipeline. | |
| virtual CapabilityReport | capabilities () const =0 |
| Query the compute device's backend, optional features, and limits. | |
| virtual DeviceSharingReport | verify_device_sharing (GpuSurface &surface)=0 |
| Test device sharing between Skia Graphite and compute pipelines. | |
| virtual std::vector< BenchmarkResult > | benchmark_magnitude (const std::vector< uint32_t > &sizes, int iterations=10)=0 |
| Benchmark magnitude computation at various sizes. | |
| virtual std::vector< BenchmarkResult > | benchmark_complex_multiply (const std::vector< uint32_t > &sizes, int iterations=10)=0 |
| Benchmark complex multiply at various sizes. | |
Static Public Member Functions | |
| static std::unique_ptr< GpuCompute > | create () |
Protected Attributes | |
| std::atomic< bool > | initialized_ {false} |
GPU compute pipeline for non-rendering workloads (e.g.
spectral processing).
Experimental API for background GPU compute work. It operates on a Dawn wgpu::Device shared with GpuSurface/SkiaSurface.
Design constraints:
Intended use: offline or background batch processing of audio data (spectral analysis, batch convolution, spectrogram generation).
| using pulp::render::GpuCompute::ReadbackCallback = std::function<void(const ReadbackResult&)> |
|
strong |
|
virtualdefault |
|
pure virtual |
GPU additive synthesis: out[s] = Σ_p amp_p · sin(2π·freq_p·(t0+s)/sr + phase_p), one thread per output sample summing all partials.
partials is num_partials × [freq(Hz), amp, phase(rad)] (3·num_partials floats). Thousands of partials parallelize cleanly — the basis for additive / spectral resynthesis. t0_samples is the absolute start sample (block continuity). Not real-time-safe. Returns false on invalid args.
|
pure virtual |
|
pure virtual |
Batch spectral magnitude: processes multiple FFT frames in one dispatch.
Input: frames of interleaved complex data, packed contiguously Output: frames of magnitude data, packed contiguously
|
pure virtual |
Benchmark complex multiply at various sizes.
|
pure virtual |
Benchmark magnitude computation at various sizes.
Returns results for each size in the vector.
|
pure virtual |
Query the compute device's backend, optional features, and limits.
|
pure virtual |
Element-wise complex multiply (frequency-domain convolution step).
Inputs: a, b — interleaved complex [re, im, re, im, ...] (2 * count floats each) Output: result — interleaved complex product (2 * count floats)
|
pure virtual |
Compute magnitude spectrum from interleaved complex float pairs.
Input: complex_pairs — [re0, im0, re1, im1, ...] (2 * num_bins floats) Output: magnitudes — [mag0, mag1, ...] (num_bins floats, linear scale) Returns false if GPU dispatch fails.
|
pure virtual |
Non-blocking counterpart of compute_magnitude().
Submits the dispatch and returns a request id; magnitudes receives num_bins floats when the completion reports Success. deadline is measured from this call. Returns 0 if the request was rejected (not initialized, invalid args, no callback) — the callback does NOT fire in that case.
|
pure virtual |
Run the fused forward for one mono block (block_size samples in/out): input projection, the dilated gated conv layers, and the linear head, all in one submit.
Carries each layer's dilation history across calls (the activation window slides every block), so streaming blocks are continuous and bit-for-bit match the CPU reference run sample-continuously. Returns false if the plan was not prepared for block_size.
|
pure virtual |
Run the fused convolution for a prepared n.
in/out are interleaved complex, length 2*n. Returns false if prepare_convolution(n) was not called, args are invalid, or dispatch fails.
|
pure virtual |
|
pure virtual |
Non-blocking counterpart of convolve_batch().
Same plan requirement (prepare_convolution_batch(n, ir_spec, batch) first) and same result: out_complex receives batch * n * 2 floats, already scaled by the 1/n inverse-FFT factor, when the completion reports Success. deadline is measured from this call. Returns 0 if the request was rejected (not initialized, no plan for n, batch mismatch, null pointers, no callback, or the in-flight cap is reached) — the callback does NOT fire in that case, and the caller counts a miss.
Multiple blocks may be in flight at once. The plan's compute buffers are SHARED across them, which is safe because the WebGPU queue executes submissions in order: submit N's copy into its readback buffer runs before submit N+1 overwrites the plan's input buffer. Only the mapped readback buffer is per-submit (one per request, from the staging pool) — a shared one is precisely what forces a blocking design.
|
static |
|
pure virtual |
GPU dense (fully-connected) layer with tanh activation: out[j] = tanh(Σ_i W[j][i]·x[i] + b[j]), one thread per output neuron.
W is row-major [out_dim × in_dim], b is [out_dim]. The core building block for GPU neural inference — NAM dense / output layers and LSTM gate evaluations are dense layers (the WaveNet path reuses the conv primitives). Not real-time-safe. Returns false on invalid args.
|
inlinevirtual |
Monotonic device generation.
A generation changes at every initialize attempt, so an owner can tag an adopted-device loss notification and reject a callback from an older device after reinitialization.
|
pure virtual |
True once the WebGPU device has been lost.
Device loss is normal — a browser tab can lose its device at any time — so it is reported as state, not as an initialization failure. On loss every in-flight readback completes as Failed and is_initialized() goes false; the owner is expected to re-acquire a device and re-prepare_*.
|
pure virtual |
Forward DFT: X[k] = sum_n x[n] exp(-2*pi*i*k*n/N).
Unnormalized. Returns false if n is not a power of two, exceeds the buffer limit, either pointer is null, or dispatch fails.
|
pure virtual |
Forward FFT that also reports the TRUE GPU compute time (microseconds) of the transform passes, measured with compute-pass timestamp queries — i.e.
excluding upload and the blocking readback that dominates wall-clock. Sets *gpu_compute_us to -1 when timestamp queries are unavailable (capabilities().timestamp_query == false) or N == 1. Diagnostic/benchmark path. Returns false on the same conditions as fft_forward.
|
pure virtual |
Inverse DFT, normalized by 1/N (so ifft(fft(x)) == x within tolerance).
Returns false if n is not a power of two, exceeds the buffer limit, either pointer is null, or dispatch fails.
|
pure virtual |
GPU granular synthesis ("grain cloud"): sum many Hann-windowed, pitch-shifted snippets of source into out, one GPU thread per output sample.
grains is num_grains × [onset(sample), duration(samples), source_pos(sample), pitch(ratio), amp]. Tens of thousands of grains parallelize across samples. Not real-time-safe. Returns false on bad args.
|
pure virtual |
Initialize by adopting an already-created WebGPU device.
wgpu_device is an opaque WGPUDevice, the same handle style as GpuSurface::dawn_device_handle(). Acquires the device's queue, reads its limits/features, installs the uncaptured-error and device-lost callbacks, and builds the compute pipelines.
This is the browser entry point. WebGPU is exposed on Window and DedicatedWorker only, so the worker's JS awaits navigator.gpu.requestAdapter()/requestDevice(), publishes the result as Module.preinitializedWebGPUDevice, and the C++ side takes it via emscripten_webgpu_get_device(). Every asynchronous step of device acquisition stays in JS: no Asyncify is used or needed.
Returns false on a null handle or pipeline-creation failure.
|
pure virtual |
Initialize from an existing GpuSurface's device (device sharing).
Returns false if compute pipelines cannot be created.
|
pure virtual |
Initialize standalone (creates its own device, no rendering surface).
Useful for benchmarking and headless compute.
Native only. It requests the adapter and device and then pumps the event queue once; in a browser those futures resolve only after control returns to the JS event loop, so there is no correct in-line spelling of it. The browser build fails this call explicitly rather than returning a mysterious false — use initialize_from_device() there.
|
inline |
|
pure virtual |
Built-in WGSL for a named pipeline (e.g.
"conv_bmul", "fft_stockham", "magnitude"). Returns nullptr for an unknown label. Pipeline labels are the ones passed to the internal create_pipeline().
|
inlinevirtual |
The most recent GPU-busy time of the async convolution shader, in nanoseconds (EMA-smoothed), or 0 when timing is disabled, unsupported, or the device quantized a small dispatch to 0 ns (Metal/Chrome do).
0 means "no honest number", never an error — callers must render it as absent, not a stall.
|
pure virtual |
Dense matrix multiply C[M×N] = A[M×K] · B[K×N], all row-major f32.
The foundational GPU primitive for neural inference (dense layers, LSTM gate matmuls) and matrix-heavy DSP. Not real-time-safe (uploads + blocks on readback). Returns false on invalid args / dispatch failure.
|
pure virtual |
GPU struck modal synthesis: out[s] = Σ_m amp_m·exp(-decay_m·t)· sin(2π·freq_m·t + phase_m), t=(t0+s)/sr.
modes is num_modes × [freq(Hz), amp, decay(1/s), phase(rad)] (4·num_modes floats) — a struck/plucked modal object (bell / string / body) as a bank of decaying resonant modes. Thousands of modes parallelize. Not real-time-safe.
|
pure virtual |
Run the multi-IR convolution for a prepared (n, num_ir).
in_complex is one zero-padded interleaved-complex input block (length 2*n). pan_l / pan_r are per-room linear gains (length num_ir) applied in the GPU reduce. out_lr receives the stereo result: out_lr[0..n) = L, out_lr[n..2n) = R (length 2*n). Returns false if prepare_multi_convolution was not called for (n, num_ir), args are invalid, or dispatch fails.
|
pure virtual |
Same as multi_convolve, but also reports the true GPU-busy time of the fused pass sequence (forward FFT → broadcast multiply → batched inverse FFT → pan-combine) in microseconds via gpu_compute_us, measured with a compute-pass timestamp query — excluding the input upload and the blocking readback.
Sets *gpu_compute_us = -1 when timing is unavailable (capabilities().timestamp_query == false). Diagnostic / roofline path: comparing this against the call's wall time separates a GPU-busy (bandwidth/compute-bound) kernel from an upload/readback-bound one. Mirrors fft_forward_timed.
|
pure virtual |
Run one block of partitioned-FDL convolution for a prepared (n, num_ir).
in_block is block (= n/2) real input samples; pan_l/pan_r are per-room linear gains (length num_ir). out_block receives the stereo output block: out_block[0..block) = L, out_block[block..2*block) = R (length 2*block = n). The plan carries the delay line and the previous block across calls. Returns false if prepare_multi_fdl was not called for (n, num_ir), args are invalid, or dispatch fails.
|
pure virtual |
Report that an ADOPTED device (initialize_from_device / initialize_from_surface) has been lost.
A device-lost callback can only be installed on the device descriptor, i.e. at creation, so a device this object did not create cannot observe its own loss — its owner must say so. In the browser that owner is the worker's JS, which awaits device.lost. Idempotent. A device created by initialize_standalone() observes loss on its own and needs no call. The owner must call this on the instance's worker strand. Backend callbacks must call post_device_lost() to publish a transition and never drain readbacks directly.
|
inlinevirtual |
|
pure virtual |
Replace the WGSL of a named pipeline.
MUST be called before the pipelines are built (i.e. before initialize_*), because pipelines are compiled once at initialization. Returns false for an unknown label, null WGSL, or a call made after initialization — a late override is refused rather than silently ignored.
|
pure virtual |
Pump the device event queue once and fire the completions that are ready or past their deadline.
Never blocks. Returns the number of requests whose completion has not fired yet. Re-entrant calls (from inside a completion) are a no-op. Detached late-map cleanup is not included.
|
inlinevirtual |
Publish a loss from a backend callback without touching readback queues or invoking user completions.
The owner strand applies the transition on its next operation. A backend with asynchronous callbacks must override this method with a publish-only implementation. The compatibility default forwards synchronously to notify_device_lost() for existing downstream implementations, so it is only safe on the owner strand; new backends must override it before publishing from a callback thread.
|
pure virtual |
Build the conv-stack plan: upload weights, allocate the per-layer device-resident activation buffers for block_size samples, and compile the fused pass pipeline.
Returns false on invalid args, if the buffers exceed a device limit, or on GPU failure. Call once before conv_stack_forward(block_size).
|
pure virtual |
Build the resident convolution plan for size n (power of two) and upload ir_spec — the interleaved-complex spectrum of the zero-padded IR (length 2*n, e.g.
produced by fft_forward of the padded IR). Call once before convolve(n). Returns false on invalid args / GPU failure.
|
pure virtual |
Batched fused convolution: batch independent length-n blocks convolved with the same resident IR, in ONE submit with ONE readback — amortizing the dominant round-trip across all blocks.
in/out hold batch back-to-back interleaved-complex blocks (length 2*n*batch). Returns false if prepare_convolution_batch(n, _, batch) was not called.
|
pure virtual |
Build the multi-IR plan for size n (power of two) and upload ir_specs — num_ir back-to-back interleaved-complex IR spectra (length 2*n*num_ir).
Call once before multi_convolve(n, num_ir). Returns false on invalid args / GPU failure.
|
pure virtual |
Build the partitioned-FDL plan for n = 2*block.
ir_part_specs holds num_ir * num_part back-to-back interleaved-complex partition spectra (each length 2*n): room r partition p at offset (r*num_part + p)*2n. Each partition spectrum is the forward FFT of that IR block zero-padded to n. Call once before multi_fdl_convolve(n, num_ir). Returns false on invalid args or if the resident IR spectra exceed the storage-buffer limit.
|
pure virtual |
Build the spectral-stack plan for FFT size n (power of two), STFT hop hop, and num_layers resident layer-spectra.
hop fixes the per-bin phase advance (2*pi*k*hop/n) applied each render. Allocates the resident magnitude / phase buffers (zeroed: every layer starts inactive/silent) and the combine + inverse-FFT pipeline. Call once before spectral_stack_render. Returns false on invalid args, if the resident buffers would exceed the device storage-buffer binding limit, or on GPU failure.
|
pure virtual |
Build the WaveNet plan: upload weights (flat, length weights_len, head_scale is the trailing scalar passed separately here), allocate the per-array/per-layer device-resident activation + head buffers for block_size samples, and compile the fused passes.
Returns false on invalid args (channels > 64, condition_size != 1, an array-chaining shape mismatch, a weight-count mismatch, a zero dilation, a layer whose causal reach dilation*(kernel-1) plus block_size exceeds 2^20 samples, or a history buffer larger than the device can bind) or GPU failure. The reach bound is checked before anything is allocated, so an untrusted model cannot stall preparation. Call once before wavenet_forward(block_size).
instance selects an independent plan slot on THIS device: two instances (e.g. stereo channels) prepared with the same block_size get separate device-resident buffers + dilation history but share the device, queue, and compiled pipelines — so a stereo plugin needs one device, not one per channel. Instances are identified by (block_size, instance); the default 0 preserves the single-stream behavior.
|
inlinevirtual |
Prepare a group of count independent WaveNet instances that share one shape (arrays) and run as one unit: weights[i] / head_scales[i] are instance i's blob and head_scale, laid out exactly as for prepare_wavenet().
All instances live in shared device buffers and every pass dispatches the whole group at once, so the per-block GPU command count stays that of ONE instance however many instances run — the shape to use for many plugin instances of the same model architecture. Groups are identified by (block_size, group), separately from prepare_wavenet() plans; re-preparing a group replaces it and resets its history. Returns false on invalid args (the prepare_wavenet() shape rules apply), on a group too large for 32-bit buffer sizes, or on GPU failure. The default implementation reports the capability as unavailable.
|
pure virtual |
Requests submitted whose completion has not fired yet.
A request whose deadline fired before its map resolved is removed from this count after its Expired completion, but its detached map cleanup still consumes the admission cap until the late map callback arrives or bounded cleanup grace expires.
|
inlinevirtual |
Opt the ASYNC convolution path into GPU-busy timing (default OFF).
When on, convolve_batch_async() occasionally brackets its compute passes with a timestamp query and reads the result back through the SAME non-blocking readback machinery (never a blocking map), so the shader's own execution time becomes observable without stalling the audio path. Default-off is a hard guarantee: with timing disabled the async path is byte-for-byte what it was, so the native realtime audio path pays and risks nothing. The browser GPU demo turns it on to show honest GPU-compute-vs-round-trip.
|
pure virtual |
Cap on concurrently in-flight async readbacks (default 4).
Admission control, not a hint: at the cap, an async submit is REJECTED (returns 0) instead of queueing. Without it a stalled or throttled GPU — a backgrounded browser tab is the ordinary case — would grow staging memory by one buffer per audio block forever. A rejected submit is a miss, which the caller already knows how to route (MissPolicy).
|
pure virtual |
Advance + smear + weighted-sum all resident layers and inverse-FFT to one real frame.
layer_weights (length num_layers) scales each layer (drive it from a Morph control). smear (0..1) circular box-blurs each layer's magnitude across frequency; jitter (0..1) adds conjugate-symmetric phase wander seeded by rng_seed. The phase advance is conjugate-symmetric so frame_out (n reals) is real. Returns false if the plan was not prepared for (n, num_layers), args are invalid, or dispatch fails.
|
pure virtual |
Upload one captured layer's magnitude (mag, n reals) and initial phase (phase, n reals) into the resident plan for (n, num_layers), activating it.
The phase then persists and advances on the GPU each render. Returns false if prepare_spectral_stack(n, num_layers) was not called, args are invalid, or dispatch fails.
|
pure virtual |
Test device sharing between Skia Graphite and compute pipelines.
Creates render targets and compute buffers on the same device, submits from both, checks for corruption.
|
pure virtual |
Run the fused WaveNet forward for one mono block (block_size in/out): the per-array rechannel, dilated conv layers (+ condition mixin, activation, residual, head accumulate), head rechannels, and the final head_scale, all in one submit.
Carries each layer's dilation history across calls so streaming blocks match the CPU reference run sample-continuously. Returns false if prepare_wavenet was not called for (block_size, instance). instance selects the plan slot prepared above (default 0).
|
inlinevirtual |
Run one block for count independent WaveNet instances at once.
Each instances[i] must have been prepared with block_size, and an instance may appear at most once. Every instance's passes are encoded into ONE command buffer, submitted once, and the count output blocks come back through ONE readback map — so the fixed submit + map round trip is paid once per block for the whole set instead of once per instance. Each instance's output and dilation history are exactly what count separate wavenet_forward() calls would produce. When gpu_busy_us is non-null it receives the GPU-busy microseconds spanning the batch, or -1 when the device has no timestamp queries. Returns false on an unprepared or repeated instance; the Dawn implementation validates the whole set before encoding, so a rejected batch advances no instance's history. Blocks on the readback like wavenet_forward(): run it on a GPU worker or offline, never on the audio thread. The default implementation calls wavenet_forward() per instance.
|
inlinevirtual |
Run one block for every instance of a prepared group: in_blocks[i] / out_blocks[i] are instance i's block_size samples, and count must equal the prepared count.
One submit, one readback. Each instance's output is bit-identical to running it alone through wavenet_forward(). When gpu_busy_us is non-null it receives the GPU-busy microseconds of the block, or -1 without timestamp queries. Blocks on the readback: GPU worker or offline only.
|
protected |