{"id":14981524,"url":"https://github.com/figma/webgl-profiler","last_synced_at":"2025-08-02T09:08:57.440Z","repository":{"id":103154781,"uuid":"158478167","full_name":"figma/webgl-profiler","owner":"figma","description":"A GPU-side profiler for WebGL using EXT_disjoint_timer_query","archived":false,"fork":false,"pushed_at":"2023-05-20T20:30:35.000Z","size":14,"stargazers_count":73,"open_issues_count":0,"forks_count":4,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-04-05T09:34:20.848Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/figma.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-11-21T02:17:15.000Z","updated_at":"2025-01-17T14:55:49.000Z","dependencies_parsed_at":null,"dependency_job_id":"180285a4-aaf5-4f99-8000-b66392a44a0b","html_url":"https://github.com/figma/webgl-profiler","commit_stats":{"total_commits":4,"total_committers":2,"mean_commits":2.0,"dds":0.25,"last_synced_commit":"ec7a1482db9b63ad25e4d4523e1109e16f87505c"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/figma/webgl-profiler","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/figma%2Fwebgl-profiler","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/figma%2Fwebgl-profiler/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/figma%2Fwebgl-profiler/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/figma%2Fwebgl-profiler/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/figma","download_url":"https://codeload.github.com/figma/webgl-profiler/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/figma%2Fwebgl-profiler/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268361056,"owners_count":24238368,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-02T02:00:12.353Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-09-24T14:03:45.675Z","updated_at":"2025-08-02T09:08:57.398Z","avatar_url":"https://github.com/figma.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# WebGL Profiler\n\nThis repository contains a small library to enable GPU-side profiling of\nWebGL command queues using the `EXT_disjoint_timer_query` OpenGL extension.\nThe output at the end is a profile that can be dropped into\nhttps://www.speedscope.app/ and viewed as a flamechart.\n\nWe need to do special profiling GPU-side because CPU-side gl calls are not\nsynchronized with the GPU's actual execution of those commands. Instead, to\nmeasure how long things are taking on the GPU, we need to insert special\ncommands into the GPU's command queue telling it when to start a timer and\nwhen to stop the timer.\n\nThis comes with an annoying list of limitations:\n\n- This currently only works in Desktop Chrome \u003e= 70.\n  The extension was completedly removed in Chrome in Chrome 65\n  (https://crbug.com/808744) and Firefox 63 due to a severe security\n  vulnerability (https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-10229).\n  It was re-introduced in Chrome 70 (https://crbug.com/820891). There's\n  an open bug for re-exposing this in Android Chrome (https://crbug.com/870491).\n\n- There's no way to ask for a timestamp. This is what `TIMESTAMP_EXT`\n  was designed for, but it was removed in 2016 (https://crbug.com/595172).\n  This makes it difficult to see how much time has elapsed between queries,\n  so instead we need to have queries always running.\n\n- It seems like the elapsed time for every command other than draw calls is\n  indicated as zero on GPUs I've tested. The total elapsed times still seem\n  ballpark correct when comparing against active GPU time in a Chrome\n  performance profile, however. This could either mean that the GPU times of\n  other commands are negligible, or that the `EXT_disjoint_timer_query` is lying\n  in this cases :|\n\n- Some graphics card/driver combinations seem to have unresolvably buggy\n  behavior. This unfortunately includes the NVIDIA GeForce GT 750M, which was\n  actually the very first card I tested this on, since it's the discrete\n  graphics card on my MacBook Pro! If you try to use the profiler with this\n  card, it will hard crash to avoid providing confusing information. Other\n  cards are probably buggy too. See: https://twitter.com/jlfwong/status/1058475013546770432\n\n## Usage\n\nTo use this library, you can either install it as an npm module, or just\ninclude it as a script tag:\n\n```html\n  \u003cscript src=\"webgl-profiler.js\"\u003e\u003c/script\u003e\n```\n\nIf consuming through npm, you can get access to the `WebGLProfiler` class\nvia `const WebGLProfiler = require('webgl-profiler')`. If you included it\nas a script tag, you can access it as a global `WebGLProfiler` variable.\n\nFrom there, you can construct a profiler for a given `WebGLRenderingContext`,\nlike so:\n\n```javascript\nconst gl = canvas.getContext('webgl');\nconst profiler = new WebGLProfiler(gl)\n```\n\nTo start a profile, run `profiler.start()`. To stop a profile, wait for the GPU\ncommands to flush, then download a file that can be imported into\nhttps://www.speedscope.app/, run `profiler.stopAndDownload()`.\n\nUnlike CPU side operations, there's no concept of a \"call stack\", so we need\nto explicitly annotate the GPU command queue with human-readable information.\nYou can either do this via paired calls to\n`profiler.pushContext(contextName)` and `profiler.popContext(contextName)`, or\nyou can use `profiler.withContext(contextName)`.\n\nHere's the relevant bits of an example usage:\n\n```javascript\nvar profiler = new WebGLProfiler(gl)\nprofiler.start()\n{\n  profiler.pushContext(\"a\")\n  gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n  {\n    profiler.pushContext(\"b\")\n    for (let i = 0; i \u003c 10; i++) {\n      gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4)\n    }\n    profiler.popContext(\"b\")\n\n    profiler.withContext(\"c\", function() {\n      for (let i = 0; i \u003c 10; i++) {\n        gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4)\n      }\n    })\n  }\n  profiler.popContext(\"a\")\n}\nprofiler.stopAndDownload()\n```\n\nThis will produce a profile that looks something like this in speedscope:\n\n![example profile](https://user-images.githubusercontent.com/150329/48817461-75acb780-ecfb-11e8-8468-46ba4edf9c2d.png)\n\n\nYou can see a full working example in [`example.html`](example.html).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffigma%2Fwebgl-profiler","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffigma%2Fwebgl-profiler","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffigma%2Fwebgl-profiler/lists"}