autokap 1.3.14 → 1.3.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/browser.js +46 -17
  2. package/package.json +1 -1
package/dist/browser.js CHANGED
@@ -825,27 +825,26 @@ export class Browser {
825
825
  // Pin GPU backend to each platform's native graphics API:
826
826
  // - macOS: Metal (compositor 4→32 fps boost at 2880×1800 vs OpenGL).
827
827
  // - Windows: D3D11.
828
- // - Cloud Run Linux: direct EGL via NVIDIA libEGL_nvidia.so (mounted at
829
- // /usr/local/nvidia/lib64). Two paths failed before: `--use-angle=vulkan`
830
- // fell back to llvmpipe because Cloud Run does not bind-mount the
831
- // NVIDIA Vulkan ICD; `--use-angle=gl` is not a valid ANGLE backend
832
- // on Linux (ANGLE Linux only ships `vulkan` and `swiftshader`), so
833
- // Chromium silently fell back to swiftshader. `--use-gl=egl` skips
834
- // ANGLE entirely and binds to NVIDIA's EGL implementation directly.
828
+ // - Cloud Run Linux: ANGLE/Vulkan binding NVIDIA L4. The Dockerfile
829
+ // ships /usr/share/vulkan/icd.d/nvidia_icd.json (Cloud Run does NOT
830
+ // bind-mount it) so Vulkan loader resolves to libGLX_nvidia.so.0
831
+ // instead of llvmpipe. Verified flag set comes from Musixmatch's
832
+ // production K8s recipe and davesnider's Playwright benchmark.
835
833
  const angleArg = process.platform === 'darwin' ? '--use-angle=metal'
836
834
  : process.platform === 'win32' ? '--use-angle=d3d11'
837
- : null;
838
- // Cloud Run NVIDIA L4: direct EGL + GPU rasterization + zero-copy upload.
839
- // `--ignore-gpu-blocklist` bypasses Chromium's hardcoded driver blocklist
840
- // (it doesn't know about Cloud Run's mounted NVIDIA driver). These flags
841
- // target the throughput wins for backdrop-filter, blur, and full-viewport
842
- // repaints the modal-open scenario that defeated software rasterization
843
- // at ~1 fps. `--enable-features=Vulkan` deliberately omitted: there is no
844
- // NVIDIA Vulkan ICD in the container, and forcing Vulkan reroutes back to
845
- // llvmpipe (software).
835
+ : isLinuxWithGpu ? '--use-angle=vulkan'
836
+ : null;
837
+ // Cloud Run NVIDIA L4: ANGLE/Vulkan + GPU rasterization + zero-copy upload.
838
+ // `--ignore-gpu-blocklist` bypasses Chromium's hardcoded blocklist (it has
839
+ // no entry for Cloud Run's mounted NVIDIA driver). `--enable-features=Vulkan`
840
+ // is required so Chromium uses the Vulkan compositor instead of falling
841
+ // back through HARDWARE_GL → SWIFTSHADER. These flags target the throughput
842
+ // wins for backdrop-filter, blur, and full-viewport repaints the modal
843
+ // scenario that pinned software rasterization at ~1 fps.
846
844
  const cloudGpuArgs = isLinuxWithGpu
847
845
  ? [
848
- '--use-gl=egl',
846
+ '--use-gl=angle',
847
+ '--enable-features=Vulkan',
849
848
  '--ignore-gpu-blocklist',
850
849
  '--enable-gpu-rasterization',
851
850
  '--enable-zero-copy',
@@ -897,6 +896,36 @@ export class Browser {
897
896
  }
898
897
  }, { styleId: CAPTURE_HIDE_STYLE_ID, css: getCaptureHideCSS() });
899
898
  instance.page = await instance.context.newPage();
899
+ // Cloud Run only: query the WebGL UNMASKED_RENDERER_WEBGL string once
900
+ // per browser launch and log it. This is the source of truth for which
901
+ // GPU backend Chromium picked — flag combinations alone are not enough,
902
+ // because Chromium silently steps down the fallback chain
903
+ // (HARDWARE_VULKAN → HARDWARE_GL → SWIFTSHADER → DISPLAY_COMPOSITOR)
904
+ // when a backend fails to initialize. A renderer string containing
905
+ // "NVIDIA" confirms hardware; "SwiftShader" or "llvmpipe" means
906
+ // software fallback. Cheap (~50ms) and only runs in cloud mode.
907
+ if (isCloudRunner) {
908
+ try {
909
+ const gpuInfo = await instance.page.evaluate(() => {
910
+ const canvas = document.createElement('canvas');
911
+ const gl = (canvas.getContext('webgl2') || canvas.getContext('webgl'));
912
+ if (!gl)
913
+ return { error: 'no webgl context' };
914
+ const ext = gl.getExtension('WEBGL_debug_renderer_info');
915
+ if (!ext)
916
+ return { error: 'no debug_renderer_info extension' };
917
+ return {
918
+ vendor: gl.getParameter(ext.UNMASKED_VENDOR_WEBGL),
919
+ renderer: gl.getParameter(ext.UNMASKED_RENDERER_WEBGL),
920
+ version: gl.getParameter(gl.VERSION),
921
+ };
922
+ });
923
+ console.info('[gpu-check] WebGL renderer:', JSON.stringify(gpuInfo));
924
+ }
925
+ catch (err) {
926
+ console.warn('[gpu-check] WebGL query failed:', err.message);
927
+ }
928
+ }
900
929
  return instance;
901
930
  }
902
931
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "autokap",
3
- "version": "1.3.14",
3
+ "version": "1.3.15",
4
4
  "description": "AI-powered CLI tool for capturing clean screenshots of websites",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",