2026-08-17 · Dev · 19 min read
Chrome Is Slow on WebGL Sites? Check GPU Acceleration First
A real laptop case where WebGL stuttered in Chrome and ran smoothly in Edge. Here is the five-minute diagnostic path before blaming the scene.
A few days ago, pages built with Three.js started running terribly on my girlfriend's laptop. Not slightly worse than expected. They stuttered enough to make orbit controls feel broken and animation look as if the page were doing far more work than it really was.
The obvious conclusion was that the laptop could not handle the scene.
Then I opened the same page in Edge. It ran smoothly.
That changed the question. The scene had not become simpler. The laptop had not gained a faster graphics card between clicks. Both browsers were based on Chromium, yet one was struggling and the other was not. The useful clue was not that Edge was somehow a better Three.js browser. It was that the machine had already proved it could render the page properly.
The problem was inside Chrome's graphics path.
This is easy to miss because Chrome can still display a WebGL page when the expected GPU path is unavailable. It may fall back to another path, including software rendering in some situations. The result is not always a clean error or a blank canvas. Sometimes the site simply feels inexplicably slow.
Before reducing texture sizes, deleting lights or rewriting a perfectly reasonable scene, check what the browser is actually doing. On a Windows laptop, the first useful answer is often five minutes away.
The five-minute version
If you only want the checklist, use this order:
- Open the same URL in Chrome and Edge under the same conditions.
- In a new Chrome tab, type
chrome://gpuinto the address bar. - Check
WebGLandCompositingunder Graphics Feature Status. - Open
chrome://settings/systemand make sure graphics acceleration is enabled, then relaunch Chrome. - Test the page in an Incognito window, followed by a clean profile if necessary.
- Compare Chrome's report with
edge://gpu. - Update Chrome and the GPU driver.
- On a dual-GPU laptop, test Chrome with Windows set to the high-performance GPU.
Only after those steps would I touch Chrome's experimental GPU flags. They are useful for diagnosis, but they are not harmless magic switches.
Why two Chromium browsers can behave differently
Chrome and Edge share a great deal of Chromium code. That does not make two installations identical.
They can be on different Chromium versions. They have different user profiles, extensions, policies and local settings. An operating system can assign different graphics preferences to each executable. One browser may also have encountered a GPU process crash and recovered differently. Driver workarounds and blocklist decisions can change between releases.
This is why "it works in Edge" is valuable evidence, but not a diagnosis by itself.
It tells you three useful things:
- the page is capable of running well on that hardware;
- the display driver is at least capable of serving one Chromium-based browser;
- a browser-specific setting, profile, version or graphics path deserves attention.
It does not prove that Chrome is rendering everything on the CPU. It also does not prove that Edge always handles GPUs better. You need the browser's own report for that.
What hardware acceleration means here
A Three.js application sends rendering work through WebGL. In current Three.js releases, WebGLRenderer uses WebGL 2.[1] Chrome handles GPU work in a separate GPU process, and on Windows it commonly uses ANGLE to translate WebGL's OpenGL ES style calls into a native graphics API such as Direct3D.[2][3]
A simplified path looks like this:
Three.js scene
|
v
WebGL commands in the renderer process
|
v
Chrome GPU process
|
v
ANGLE and the graphics driver
|
v
Integrated or dedicated GPU
That path contains more moving parts than "the website uses the graphics card." Chrome can disable particular accelerated features when it detects a driver or hardware combination with known problems. A setting, policy, failed GPU process, stale driver or unusual backend can alter the path before the scene reaches the GPU.[2][4]
Software rendering is useful as a compatibility fallback. It is not what I want for a demanding interactive Three.js scene.
1. Reproduce the comparison fairly
The Edge test only helps if both browsers are doing roughly the same job.
Use the same URL, window size and display. Let the page finish loading. Plug the laptop into power, or at least keep the same Windows power mode for both tests. Close unrelated heavy tabs. If the page has a quality selector, use the same setting.
Also check the browser versions. Type these into their respective address bars:
chrome://version
edge://version
If one browser is several releases behind, update it before drawing conclusions.
You do not need a laboratory benchmark. The goal is to avoid comparing a cold first load in one browser with a cached second load in another, or a maximized 4K canvas with a small window.
If the page exposes an FPS counter, note the number. Otherwise, record what you can observe: delayed pointer input, uneven animation, long freezes during first interaction or consistently low frame rate. These are different symptoms and can point to different causes.
2. Open chrome://gpu
Type this into Chrome's address bar:
chrome://gpu
Chrome does not reliably treat internal chrome:// addresses as ordinary links from a website, so copying or typing the address is more dependable than clicking it here.
Start with Graphics Feature Status. The most relevant entries are:
WebGLCompositingRasterization
For the case described in this article, I want WebGL and Compositing to report Hardware accelerated. Some Chrome versions list WebGL 2 separately and some do not, so do not assume a missing standalone WebGL2 row is itself a fault.
Then scroll farther down and look at:
- Problems Detected
- Driver Information
- the active GPU on machines with more than one adapter
- the ANGLE renderer or backend
- GPU process crash or reset messages, if present
The wording matters. Save the whole report if Chrome offers Copy Report to Clipboard, or take screenshots of the feature status, problems and driver sections. A screenshot of one green WebGL line can hide the clue two sections below it.
Here is a practical way to interpret common results:
| What you see | What it suggests | What to do next |
| --- | --- | --- |
| WebGL: Hardware accelerated | Chrome has an accelerated WebGL path | Keep checking the profile, active GPU and the scene itself |
| Software only or hardware acceleration unavailable | Chrome is not using the expected accelerated path | Check the graphics setting, policies, driver and detected problems |
| A feature is Disabled | A setting, flag, policy or compatibility decision may be involved | Relaunch after checking settings, then inspect Problems Detected |
| Repeated GPU process resets or context loss | The driver or selected backend may be unstable | Update first, then test another backend only as a controlled experiment |
| The integrated GPU is active | Not automatically an error | Compare performance, then test the Windows high-performance preference |
An integrated GPU is not proof of a problem. Plenty of Three.js pages run well on modern integrated graphics. Treat the active adapter as evidence, not a verdict.
3. Compare it with edge://gpu
Now open this in Edge:
edge://gpu
Compare the same sections. Do not stop at the green status lines. Look at the active GPU, ANGLE backend, driver version and detected problems.
This comparison is often more useful than arguing about which browser is faster. If Edge reports accelerated WebGL and Chrome reports software rendering, the difference is concrete. If both report hardware acceleration but use different adapters or backends, you have another lead. If both reports look nearly identical, the Chrome profile and extensions become more interesting.
Keep both reports. They turn "Chrome feels bad" into something another developer can investigate.
4. Confirm Chrome's graphics acceleration setting
Open:
chrome://settings/system
Enable Use graphics acceleration when available. Depending on the Chrome version and language, the label may still say Use hardware acceleration when available.
Then use Chrome's Relaunch button. Closing one tab is not enough. The GPU process and browser need a proper restart before you check again.
After relaunching:
- return to
chrome://gpu; - confirm that the status changed as expected;
- load the same Three.js page again;
- compare the behavior with Edge.
There is an awkward detail here. Disabling acceleration is common advice for browser crashes, corrupted video and graphical artifacts. That can be a sensible stability workaround when the GPU path itself is broken. It is not a performance fix for a WebGL application. For this problem, I first want acceleration enabled and the underlying driver issue addressed.
5. Use Incognito as an isolation test
Open an Incognito window and load the same page.
Most extensions are not allowed to run there unless the user explicitly enabled them for Incognito. If the page becomes smooth, something tied to the normal profile is probably involved.[5]
Probably is the important word.
Incognito also changes cookies, storage and session state. Third-party cookies are blocked by default. A site may therefore load a slightly different experience. "It works in Incognito" is a strong clue, not proof that one particular extension is guilty.
Confirm it in the normal profile:
- open
chrome://extensions; - disable extensions temporarily;
- restart the test after each small group;
- enable them again one at a time until the slowdown returns.
Extensions that inject scripts, restyle every page, add overlays, inspect requests or modify canvas behavior deserve attention. I would not start by publicly blaming a specific ad blocker or privacy extension. A clean Chrome profile is an even better control because it removes years of accumulated profile state without deleting the original profile.
Chrome's own Task Manager can also help. Press Shift + Esc and look for an extension or tab consuming unusual CPU time. It will not explain every GPU problem, but it can expose a completely different bottleneck in a minute.
6. Update Chrome and the graphics driver
If Chrome has disabled a GPU feature because of a known driver problem, forcing the feature back on is treating the warning rather than the cause.
Update Chrome first. Then update the graphics driver from the laptop manufacturer or the GPU vendor. On dual-GPU laptops, check both the integrated and dedicated graphics drivers. The integrated adapter may still participate in display output even when the dedicated GPU does the rendering.
Restart Windows after the driver update. Then compare fresh chrome://gpu and edge://gpu reports.
Windows Update may provide a functional driver without providing the newest vendor fix. On the other hand, some laptop manufacturers customize drivers for their switching graphics setup. There is no universal rule that the newest generic package is always best. I would start with the laptop manufacturer's current supported driver, then use the GPU vendor package if the machine and support guidance allow it.
7. Check which GPU Windows assigns to Chrome
This matters most on laptops with an integrated GPU and a dedicated NVIDIA, AMD or Intel adapter.
In Windows 11, go to:
Settings > System > Display > Graphics
Add or select Chrome, open Options, choose High performance, save the setting and fully restart Chrome. Microsoft documents this per-application graphics preference for systems with more than one GPU.[6]
If Chrome is not listed, add chrome.exe as a desktop application. Its location depends on how Chrome was installed. One reliable way to find the right executable is to open Windows Task Manager while Chrome is running, right-click the Chrome process and use Open file location.
This is a test, not a promise. The operating system and driver still make parts of the final decision, and a site can remain slow on a dedicated GPU if its bottleneck is JavaScript or draw-call overhead. A high-performance GPU also consumes more power and can make a laptop hotter.
If this fixes the problem, compare chrome://gpu before and after. The change in the active adapter is more useful than the checkbox alone.
8. Temporarily override the software rendering list
This is where many short tutorials begin. I think it belongs near the end.
Chrome maintains GPU compatibility rules because some driver and hardware combinations cause crashes, corrupted output or security problems. The experimental flag below tells Chrome to ignore those decisions for affected features:
chrome://flags/#ignore-gpu-blocklist
The visible name is commonly Override software rendering list.
Use it as a controlled diagnostic:
- save the current
chrome://gpureport; - change only this one flag to Enabled;
- relaunch Chrome;
- save the new report;
- test the same page;
- return the flag to Default after the test.
If performance suddenly improves and WebGL becomes hardware accelerated, you have learned something useful: Chrome's compatibility decision was involved. That is a reason to investigate the driver, Chrome version and reported blocklist entry. It is not a reason to leave the override enabled forever.
Chromium explicitly warns that experimental flags and switches can change, disappear or break without notice.[7] If forcing the GPU path produces flashing, black frames, tab crashes or WebGL context loss, reset the flag immediately.
9. Test a different ANGLE backend, one at a time
On Windows, Chrome normally uses ANGLE between WebGL and the native graphics stack. ANGLE supports several backends, including Direct3D 11, Vulkan and desktop OpenGL, although the options available in Chrome depend on the build and platform.[3]
The relevant experiment is usually exposed at:
chrome://flags/#use-angle
Its label is commonly Choose ANGLE graphics backend.
Write down the current value and check the active renderer in chrome://gpu. Then test one alternative, relaunch, record the new report and repeat the same page test. On Windows, D3D11 is a sensible comparison if it is available. Vulkan or OpenGL may be useful when investigating a specific driver/backend issue, but neither is a universal speed button.
Change one thing at a time. If you enable the blocklist override, switch ANGLE and change the Windows GPU preference together, a smooth result tells you almost nothing about which change mattered.
Return the backend to Default after testing unless you have a stable, understood workaround. Never follow random advice to disable Chrome's GPU sandbox or watchdog to make a demo faster.
What I would not treat as a GPU fix
Chrome's Memory Saver is worth knowing about, but it is not my first suspect for steady low frame rate in an active tab. It mainly deactivates eligible background tabs. Disable it temporarily if the page is being discarded, reloaded or repeatedly warming up after you return to it. Do not expect it to turn software WebGL into hardware WebGL.
The same applies to clearing the entire browser cache. It may change first-load behavior, shader caches or downloaded assets, but it does not explain a persistent difference in the reported graphics path.
I would also avoid extensions marketed as GPU optimizers. A browser extension cannot repair a broken display driver, and adding more page-injecting code makes the comparison less clean.
If Chrome reports hardware acceleration and still lags
At this point the browser has passed the first check. That does not prove the demo is efficient. Hardware acceleration makes the GPU available; it does not make every scene cheap.
Now I would profile the application.
Check the drawing resolution
High-density displays can quietly multiply the number of pixels rendered every frame. A canvas that looks 1,920 by 1,080 CSS pixels at a device pixel ratio of 2 can require roughly four times as many physical pixels as the same canvas at a ratio of 1.
Three.js lets you cap the renderer's pixel ratio:
```js
const maxPixelRatio = 2;
renderer.setPixelRatio(
Math.min(window.devicePixelRatio, maxPixelRatio)
);
```
Two is not sacred. A heavy full-screen scene may need 1.5 or even 1 on weaker hardware. Choose a cap by measuring the visual and performance tradeoff. Three.js documents that drawing-buffer dimensions are multiplied by the selected pixel ratio.[1]
Inspect draw calls and scene size
renderer.info exposes basic counters that are useful before opening a deeper profiler:
function logRendererStats(renderer) {
console.table({
calls: renderer.info.render.calls,
triangles: renderer.info.render.triangles,
lines: renderer.info.render.lines,
points: renderer.info.render.points,
geometries: renderer.info.memory.geometries,
textures: renderer.info.memory.textures,
programs: renderer.info.programs?.length ?? 0,
});
}
A high triangle count is not automatically worse than a high draw-call count. Hundreds of tiny meshes with separate materials can keep the CPU and driver busy even when the total geometry looks modest. Repeated geometry is a good candidate for InstancedMesh. Static objects may be merged where that makes sense.
Look for the expensive features
Common costs include:
- large dynamic shadow maps;
- several post-processing passes at full resolution;
- too many transparent objects;
- large textures being decoded and uploaded during interaction;
- shader compilation during the first visible frame;
- per-frame allocations and work on the JavaScript main thread;
- render loops that continue at full speed when nothing changes.
Three.js provides compileAsync() to prepare shaders with the parallel shader compilation extension where available, and initTexture() can move texture initialization before the moment it would otherwise cause a visible stall.[1] Those are remedies for specific first-use pauses, not general performance charms.
Use Chrome DevTools Performance recording to separate long JavaScript tasks from rendering work. If the main thread is blocked for 80 milliseconds every frame, changing the GPU backend will not fix the code producing those tasks.
A small diagnostic snippet for your own Three.js app
When I control the code, I like to expose a tiny report that can be copied into a bug ticket:
```js
function getThreeDiagnostics(renderer) {
const gl = renderer.getContext();
const debugInfo = gl.getExtension('WEBGLdebugrenderer_info');
return {
userAgent: navigator.userAgent,
devicePixelRatio: window.devicePixelRatio,
drawingBuffer: ${gl.drawingBufferWidth}x${gl.drawingBufferHeight},
renderer: debugInfo
? gl.getParameter(debugInfo.UNMASKEDRENDERERWEBGL)
: 'not exposed',
vendor: debugInfo
? gl.getParameter(debugInfo.UNMASKEDVENDORWEBGL)
: 'not exposed',
calls: renderer.info.render.calls,
triangles: renderer.info.render.triangles,
textures: renderer.info.memory.textures,
geometries: renderer.info.memory.geometries,
};
}
console.table(getThreeDiagnostics(renderer));
```
The unmasked renderer extension may be unavailable or deliberately restricted, so the code must tolerate that. Do not use this information for browser fingerprinting. Its legitimate purpose here is local diagnosis with the user's knowledge.
This report complements chrome://gpu; it does not replace it. The internal page knows about Chrome's full graphics configuration and detected problems. The application knows its drawing buffer and workload.
What to include in a useful bug report
"Three.js is slow in Chrome" leaves too many possibilities. A useful report contains:
- the exact page URL and steps needed to reproduce the slowdown;
- Chrome and Edge versions;
- Windows version and laptop model;
- GPU models and driver versions;
- whether the laptop was plugged in and its power mode;
- the Chrome
chrome://gpureport; - the Edge
edge://gpureport; - normal profile, Incognito and clean-profile results;
- extension isolation results;
- any change caused by Windows GPU preference;
- a short DevTools Performance trace if acceleration is already healthy.
Remove identifiers or unrelated system details before publishing a full GPU report. For a private issue with a developer, the unedited report is usually more useful.
A note about phones
A similar symptom can occur on Android, but the desktop checklist does not transfer cleanly. Mobile browsers run through device-specific drivers, thermal limits and power management. Chrome and Edge on Android may also share more of the same system components than their desktop installations suggest.
The fair comparison still applies: same page, same device, same temperature and the same power state. The Windows graphics preference and desktop ANGLE flag advice does not.
The order matters
The most useful lesson from my girlfriend's laptop was not a particular flag. It was the order of investigation.
The page looked like a badly optimized Three.js demo. Edge showed that it was not that simple. chrome://gpu gave us a way to inspect the browser before changing the application.
So my order is now:
- prove the symptom in the same conditions;
- inspect
chrome://gpu; - compare
edge://gpu; - enable graphics acceleration and relaunch;
- isolate extensions and the Chrome profile;
- update the browser and drivers;
- test the Windows GPU preference;
- use blocklist and ANGLE flags only as temporary diagnostics;
- profile the Three.js scene if the accelerated path is healthy.
The first thing I check is no longer the polygon count. It is whether Chrome is using the graphics path I thought it was using.
If you have seen the same Chrome-versus-Edge split, I would be interested in what changed it on your machine: the acceleration setting, an extension, the selected GPU, a driver update or a particular ANGLE backend.
Sources and further reading
- Three.js documentation: WebGLRenderer
- Chromium: GPU Accelerated Compositing in Chrome
- ANGLE project documentation and source repository
- Google Chrome Enterprise: Chrome browser policy settings, including hardware acceleration
- Google Chrome Help: Install and manage extensions, including Incognito access
- Microsoft Support: per-application graphics preference in Windows 11
- Chromium: Run Chromium with flags