Inspect

September 24, 2026 · View on GitHub

Overview . Capture . Record

Introduction

Back to top

The Inspect tool shows you a real-time view of all WebGPU Objects that have been created by the page. As objects are created and destroyed, they are reflected by the Inspect tool.

Starting the Inspect Tool

Back to top

WebGPU Inspector does not interfere with a page by default, so you must start the tool for the information to be reported.

Press the Start button on the Inspect panel. This will reload the page, injecting the inspector script. The inspector will intercept all WebGPU commands and report data back to the inspector panel.

GPU Start

When the WebGPU Inspector is active on the page, a small status display is drawn in the upper-left corner of the page. It shows the frame number and a live frame-health HUD:

  • the frame rate and the average frame time, with the fastest and slowest of the last 60 frames in parentheses,
  • the number of dropped frames (missed display refreshes), in red, once there are any,
  • paused while the page is paused from the Capture panel (Pause and Step),
  • a small sparkline of the last 60 frame times, with the display refresh interval dashed, so a hitch shows up as a spike.

The numbers update a few times a second, so they're readable and add almost nothing to the page's own frame cost.

Inspector Status

Inspecting Web Workers

The Inspect Workers checkbox next to the Start button controls whether the inspector also instruments WebGPU calls made inside Web Workers the page creates.

It is on by default, so worker-side WebGPU objects and frames show up in the panel without any extra steps. Injecting into workers requires the inspector to wrap the worker's Worker constructor and rewrite worker URLs, which can interfere with some applications — if a page misbehaves only while being inspected, turn this off and press Start again. When disabled, the page's Worker constructor is left completely untouched.

The setting is remembered between DevTools sessions, and the Capture panel uses it too.

Notes

  • If you press the Start button and the page does not reload, manually refresh the page and press the Start button again. Sometimes the DevTools extension doesn't get injected into the page correctly.

  • If you refresh the page, it will no longer have the injected inspector script. Press the Start button on the Inspector tool to start inspecting again.

  • If you close the DevTools window and open it again, it will have lost the data it collected before. Press the Start button to re-start data collection.

GPU Stats

Back to top

GPU Stats

The inspector will report basic statistics about what's going on with the page.

Frame Time: How long it took the last frame to render. This will be updated every frame.

Next to the frame time is a bound badge — a live estimate of whether the frame is CPU-bound (the main thread's per-frame work fills most of the frame budget), or GPU/vsync (the main thread has headroom, so the bottleneck is the GPU or the display refresh cap). GPU time is only measured during a Profile Passes capture, so the live badge can flag CPU-bound but defers to a capture to tell GPU-bound apart from vsync-bound.

A dropped-frame counter (⚠ N dropped) appears once the page misses vsync intervals. The display refresh rate is estimated from the frame deltas, and dropped frames are counted across the page and its workers, so the count reflects the whole page (workers usually do the real rendering).

Texture Memory: How much memory is currently being used for textures on the GPU.

Buffer Memory: How much memory is currently being used for buffers on the GPU.

Meters

Frame Time: Plots the frame duration over time. This lets you identify spikes in your renders. A common source of spikes is garbage collection.

The plot overlays three lines on a shared scale: the frame interval (grey), the CPU submit time spent on the main thread each frame (green), and the last-captured GPU frame time (blue, held between captures — GPU time is only measured during a Profile Passes capture). A dashed horizontal line marks the estimated display refresh interval (the frame budget); frame-time spikes rise above it, so anything touching or crossing that line is a dropped frame. Whichever line rides up against the budget tells you where the frame time is going — if CPU is near the budget you're CPU-bound; if it has headroom the GPU or vsync is the limit. The scale is clamped to a few times the refresh interval so a single long stall doesn't flatten the rest of the plot.

GPU Objects: Plots the number of GPU Objects that are allocated over time. You can select a specific GPU object type to plot from the option box. The GPU Objects option tracks all GPU objects.

The option box also offers memory over time: GPU Memory (textures and buffers together), Texture Memory and Buffer Memory, plotted in MB. Hover the plot for the current value in bytes. The figures are estimates from the sizes of the textures and buffers the page has created and not yet destroyed or garbage collected; drivers may pad allocations or add metadata. A memory plot that keeps climbing points at a leak, and a saw-tooth at resources being reallocated every few frames.

A plot that has a saw-tooth pattern indicates you are allocating GPU objects and garbage collection is destroying them. Some GPU objects are more expensive than others, such as buffers and textures. Others are light-weight, such as texture views. But with any garbage collected language, minimizing garbage collection is ideal.

GPU Objects

Back to top

WebGPU is an object based API, and has different object types.

Selecting an object will display information about the object in the Inspect tab. The categories include Adapters, Devices, Render/Compute Pipelines, Shader Modules, Buffers, Textures, Texture Views, Samplers, Bind Groups, Bind Group Layouts, Pipeline Layouts, Render Bundles, pending async pipelines, and Validation Errors. Inspecting an Adapter shows its full set of features and limits.

Each object category displays how many objects of that type are allocated.

Objects that have an associated error are highlighted in red in the lists, and inspecting an object includes an Errors section listing any errors reported for it (see Validation Errors).

Inspection History

Back to top

The header of the GPU Objects list has < (Back) and > (Forward) buttons that step through the objects you have inspected, like browser history navigation. This makes it easy to return to a previously inspected object after following references — for example, jumping from a bind group to one of its textures and back. The buttons are disabled when there is nothing to navigate to.

Filters

Back to top

Large applications can allocate hundreds or thousands of GPU objects, making it difficult to find the one you care about. The Filter panel at the top of the GPU Objects list lets you narrow the lists down by name, by type-specific properties, or to just the objects referenced by the most recent frame capture.

When a filter is active, each object category's header shows the number of visible objects over the total (for example, Textures 12/184). Clearing all filter fields restores the full lists.

A free-text Search field at the top of the Filter panel matches against every object's label, id, and class name. The match is case-insensitive and applies across all object categories simultaneously.

Only objects used in last capture

The Only objects used in last capture checkbox hides every object that was not referenced by the most recent frame capture. This makes it easy to focus on the resources that participated in a specific frame after running a capture from the Capture panel. The list updates automatically when a new capture is taken or cleared.

Textures / Views

  • Format: substring match against the texture's format (for example, rgba8unorm, depth).
  • Width, Height, Depth: numeric comparisons. Each field accepts a plain number for equality, or one of the operators >, >=, <, <=, = followed by a number (for example, >=256, <1024, >1 for array layers).

The texture filters apply to both the Textures list and the Texture Views list (a view inherits its texture's dimensions and format).

Buffers

  • Size: numeric comparison against the buffer's size in bytes (for example, >=1024).
  • Usage: checkboxes for Index, Vertex, Uniform, Storage, Indirect, and QueryResolve. A buffer matches if it has any of the selected usages.

Shader Modules

The Type checkboxes (Vertex, Fragment, Compute) keep only shader modules that define an entry point of the selected stage. A module with multiple entry stages matches if any selected stage is present.

Bind Groups

The Contains field matches a bind group if any of its bound resources (buffers, texture views, or the textures underlying those views) match the given name or id substring. This is useful for finding every bind group that uses a particular texture or buffer.

Object Stacktrace

Back to top

The stacktrace for each object is recorded, identifying where in the code the object was created.

Allocations

Back to top

The Allocations tab, next to Inspect on the right side of the panel, is for finding leaks. A leak in a WebGPU page is usually one line of code that creates a buffer or bind group every frame and never releases it, so this tab groups the live GPU objects by the code that created them. Each row shows the object type, the creation site, how many of those objects are alive, and their buffer and texture memory. Click a row to list its objects, and click an object to inspect it.

  • The creation site is the first frame of the object's creation stack trace. Turn on Object Stacktraces (see Starting the Inspect Tool) to get one. Without stack traces, objects are grouped by label.
  • Type limits the list to one kind of object.
  • Mark Baseline remembers the objects alive now. With Since baseline checked, only objects created after the mark that are still alive are listed. Mark a baseline, let the page run for a while (or repeat an action, such as loading a level twice), and whatever is still growing is the leak.
  • Garbage collected without destroy() lists the buffers, textures and devices the page dropped without calling destroy(), grouped the same way, with a count, memory and when the last one was collected. Their GPU memory is only freed when the garbage collector gets to them, which can be much later.

The tab refreshes every two seconds while it is visible; Refresh updates it immediately.

Validation Errors

Back to top

The inspector listens for WebGPU validation errors and collects them in a Validation Errors category at the bottom of the GPU Objects list. Selecting an error shows its message (and stacktrace when available) along with a button that jumps to the GPU object that caused it. The object that an error refers to is highlighted in red in the object lists.

The inspector also reports some common mistakes as validation errors:

  • Memory leaks — a buffer, texture, or device that is garbage collected without being explicitly destroyed. These objects should be explicitly destroyed to avoid GPU memory leaks.
  • Expired canvas texture use — using a canvas texture (or a bind group containing one) after it has expired, for example as a render pass attachment in a later frame.

Textures

Back to top

When you inspect a texture, a Load button pulls the texture image from the page for visualizing.

Mousing over the texture image will show the pixel color values, if the Inspector can decode the texture format.

The layer title bar will include the min and max pixel color values from the texture.

Left-click on the texture will show the pixel value on the texture layer title bar.

Mip Level: select the mip level to inspect.

Auto Range: when enabled, the min and max pixel values from the texture are used to normalize the texture display.

Exposure: adjusts the brightness of the texture's display.

Channel: lets you inspect specific color channels of the image.

Zoom: scale the display of the texture. You can also control the texture display zoom using control+mouse-wheel.

NaN/Inf, < 0, > 1: draw special values in solid colors so they stand out. NaN/Inf is on by default: NaN is magenta, +Inf is orange and -Inf is cyan. < 0 draws values below 0 in blue, and > 1 draws values above 1 in red, which helps spot out-of-range data in textures that should be normalized. A texel is highlighted when any of its channels has the value.

Histogram: shows a per-channel histogram of the displayed mip level of layer 0, over each channel's own range of finite values (square-root scale). Below it are each channel's range and the counts of NaN, +Inf, -Inf, and values below 0 and above 1.

The copy button in each layer's title bar copies the displayed image to the clipboard as a PNG.

Depth textures are always normalized for display. This means the min and max values of the texture are found, then all values in the depth texture are normalized to that range. This makes it easier to visualize depth textures, even if their values are in a compressed range. Other texture types can be displayed normalized using the Auto Range setting.

Note: if the page is using WebGPU compatibility mode, depth textures can't be viewed as compatibility mode lacks the feature needed to read depth textures.

Shaders

Back to top

When you inspect a shader, it provides an editor for the shader's code.

Reflection Info

WebGPU Inspector will parse the shader's WGSL code and provide reflection information about the shader. This includes the entry functions, inputs and outputs, and resource binding information.

Editing Shaders

You can make changes to the shader code and press the Compile button. The modified shader will be sent to the page and replace the original version of the shader, letting you immediately see shader changes live on the page.

Note

There are limitations to the types of changes you can make to the shader. The page already has a pipeline and bind groups for the original version of the shader, so making any changes to the bindings used by the modified version of the shader will likely result in WebGPU errors.

Compile & Replay

Compile & Replay tries the edit against a captured frame without changing the page. It uses the Capture tab's frame when that frame uses the shader, otherwise the most recent capture that does. The captured frame is replayed on the DevTools GPU device twice: once as captured and once with the edited shader. The inspector then compares every render target the edit could affect. The results open as a Shader Edit tab in the Capture panel. Each changed target gets a card with the target as captured (Before), with the edit (After), the changed texels highlighted, and how many texels changed. Targets that didn't change are listed below the cards. If the edited shader doesn't compile, the error is shown next to the button.

Both runs start from the same captured state, so any differences come from the edit. The edit's effects carry through the rest of the frame, so a change to a G-buffer shader also shows up in the lighting and post-processing targets. The replay has some limits:

  • Render bundles are not replayed.
  • Depth, multisampled and compressed textures start empty rather than with their captured contents, which matters only when the frame reads them before writing them.
  • Only mip 0 and layer 0 of each target are compared. Depth targets show only which texels changed.

Profiling Tips

Back to top

For per-pass GPU timing, the Capture panel has a Profile Passes option that injects timestamp queries around render and compute passes and presents the results as a timeline, showing what percentage of the frame each pass takes. The Inspect panel's stats can also reveal some opportunities for optimization:

  • The bound badge and the CPU line on the Frame Time meter tell you where to look first: a CPU-bound frame calls for fewer/cheaper draw submissions on the main thread (batching, render bundles, fewer state changes), while a GPU/vsync frame calls for a capture to measure per-pass GPU time.
  • A rising dropped-frame count means the page is regularly missing vsync — cross-reference the frame-time spikes above the dashed refresh line to see when.
  • Periodic spikes in the frame time graph indicate your page is probably doing garbage collection during those frames. Try to minimize JavaScript's garbage collection by caching and re-using GPU objects as much as possible.
  • Object numbers rising and falling over time indicate the page is allocating and destroying objects frequently. If the objects accumulate quickly and go down gradually, it indicates you are creating objects and relying on garbage collection to destroy them.
    • Buffer and texture objects in particular are expensive to create and destroy, so you should try to cache buffers and textures in particular as much as possible. Other types of objects, like Texture Views, may be inexpensive but can still cause garbage collection stalls.