Dynamically Alter GPU.js Kernel Output Dimensions
In GPU.js, you can dynamically alter the output dimensions of an
already compiled kernel without redefining the original kernel function.
By utilizing the built-in setOutput() method on the kernel
instance, developers can adjust 1D, 2D, or 3D execution bounds on the
fly. This article explains how dynamic resizing works in GPU.js, how to
implement it in code, and the performance trade-offs to keep in
mind.
Changing Output
Dimensions with setOutput()
When you create a kernel in GPU.js, you typically define the initial
output size using the .setOutput() method during
instantiation. However, this configuration is not permanently locked.
You can call kernel.setOutput() at any point before
executing the kernel with new arguments.
const { GPU } = require('gpu.js');
const gpu = new GPU();
// 1. Create and compile the kernel with initial dimensions
const computeGrid = gpu.createKernel(function() {
return this.thread.x + this.thread.y;
}).setOutput([512, 512]);
// Run with original dimensions (512x512)
let resultA = computeGrid();
// 2. Dynamically change the output dimensions to 1024x1024
computeGrid.setOutput([1024, 1024]);
// Run with updated dimensions
let resultB = computeGrid();How It Works Under the Hood
When you modify the output dimensions, GPU.js handles several updates internally:
- Internal Constants Update: The thread boundaries
accessible inside the kernel via
this.output.x,this.output.y, andthis.output.zupdate automatically to match the new array lengths. - WebGL Viewport and Framebuffer Adjustment: Because GPU.js relies on WebGL textures to hold output data, resizing forces the underlying rendering context to update its viewport dimensions and reallocate appropriately sized texture buffers.
- No Full Kernel Recompilation: The underlying GLSL
shader source code does not need to be fully parsed or re-transpiled
from JavaScript. This makes resizing an existing kernel significantly
faster than destroying it and creating a new one with
gpu.createKernel().
Performance Considerations
While modifying output sizes on an existing kernel is more efficient than instantiating a new one, it is not completely free of overhead:
- Buffer Reallocation: Changing dimensions forces WebGL to dispose of previous output textures and allocate new memory on the GPU. Repeatedly changing dimensions on every frame will introduce garbage collection pressure and GPU memory stalls.
- Input-Output Alignment: If your kernel reads from an input texture whose size matches the old dimensions, you must ensure that your input arrays are updated to prevent out-of-bounds reads or logic errors inside the shader.
- Padding and Fixed Maximums: For real-time applications such as video processing or physics simulations with frequent size changes, it is often more performant to allocate a kernel with the maximum expected dimension and use conditional logic or discard unused fragments, rather than constantly resizing the kernel buffer.