Skip to content

Commit 464c313

Browse files
authored
Add new chipsets, fixes logic to detection change in data shape, and adds build tooling
1 parent 8c81b70 commit 464c313

File tree

10 files changed

+206
-84
lines changed

10 files changed

+206
-84
lines changed

.github/workflows/publish.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
name: Publish package to GitHub Packages
2+
3+
on:
4+
release:
5+
types: [published]
6+
workflow_dispatch:
7+
8+
permissions:
9+
contents: read
10+
packages: write
11+
12+
jobs:
13+
publish:
14+
runs-on: ubuntu-latest
15+
steps:
16+
- name: Checkout code
17+
uses: actions/checkout@v4
18+
19+
- name: Set up Node.js & GitHub Packages registry
20+
uses: actions/setup-node@v4
21+
with:
22+
node-version: '18.x'
23+
registry-url: 'https://npm.pkg.github.com'
24+
25+
- name: Install, build, & test
26+
run: |
27+
npm install --legacy-peer-deps
28+
npm run build
29+
npm test
30+
env:
31+
NPM_TOKEN: ${{secrets.NPM_TOKEN}}
32+
33+
- name: Publish to GitHub Packages
34+
run: npm publish
35+
env:
36+
NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}
37+
NPM_TOKEN: ${{secrets.NPM_TOKEN}}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
name: Publish benchmarks to GitHub Pages
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
workflow_dispatch:
8+
schedule:
9+
- cron: '0 0 */14 * *' # every 14 days at midnight UTC
10+
11+
permissions:
12+
contents: read
13+
pages: write
14+
id-token: write
15+
16+
env:
17+
BENCHMARKS_URL: https://roll20.github.io/detect-gpu
18+
19+
jobs:
20+
build:
21+
runs-on: ubuntu-latest
22+
23+
steps:
24+
- name: Check out code
25+
uses: actions/checkout@v4
26+
27+
- name: Use Node.js
28+
uses: actions/setup-node@v4
29+
with:
30+
node-version: '18.x'
31+
32+
- name: Install & build
33+
run: |
34+
npm install --legacy-peer-deps
35+
npm run build
36+
37+
- name: Update benchmarks
38+
run: npm run update-benchmarks
39+
40+
- name: Validate *local* benchmark JSON shape
41+
run: |
42+
npx jest test/validate-benchmarks-shape.test.ts \
43+
--env=jsdom \
44+
--runTestsByPath
45+
env:
46+
BENCHMARKS_URL: file://${{ github.workspace }}/benchmarks
47+
48+
- name: Upload benchmarks as Pages artifact
49+
uses: actions/upload-pages-artifact@v3
50+
with:
51+
path: benchmarks
52+
53+
deploy:
54+
needs: build
55+
runs-on: ubuntu-latest
56+
environment:
57+
name: github-pages
58+
url: ${{ steps.deployment.outputs.page_url }}
59+
60+
steps:
61+
- name: Deploy to GitHub Pages
62+
id: deployment
63+
uses: actions/deploy-pages@v4

.github/workflows/test.yml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Run actions on Pull Request or Push
1+
name: Run tests and linting on pull requests
22
on:
33
push:
44
branches:
@@ -14,20 +14,26 @@ on:
1414

1515
jobs:
1616
test:
17-
name: Run test & lint
18-
runs-on: Ubuntu-20.04
17+
runs-on: ubuntu-latest
1918
steps:
2019
- uses: actions/checkout@v4
20+
21+
# make sure we don't pick up our repo's .npmrc
22+
- name: Un-configure GitHub Packages
23+
run: rm -f .npmrc
24+
2125
- uses: actions/setup-node@v4
2226
with:
2327
node-version: '18.x'
28+
2429
- uses: actions/cache@v4
2530
id: yarn-cache
2631
with:
2732
path: |
2833
node_modules
2934
*/*/node_modules
3035
key: ${{ runner.os }}-install-${{ hashFiles('**/yarn.lock') }}
36+
3137
- run: yarn install
3238
if: ${{ steps.yarn-cache.outputs.cache-hit != 'true' }}
3339

.github/workflows/update-benchmark.yml

Lines changed: 0 additions & 52 deletions
This file was deleted.

.npmrc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
package-lock=false
1+
@roll20:registry=https://npm.pkg.github.com
2+
//npm.pkg.github.com/:_authToken=${NPM_TOKEN}

package.json

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,27 @@
11
{
2-
"name": "detect-gpu",
3-
"version": "5.0.70",
2+
"name": "@roll20/detect-gpu",
3+
"version": "5.0.74",
44
"description": "Classify GPU's based on their benchmark score in order to provide an adaptive experience.",
55
"author": "Tim van Scherpenzeel",
66
"license": "MIT",
77
"main": "dist/detect-gpu.umd.js",
88
"module": "dist/detect-gpu.esm.js",
99
"types": "dist/src/index.d.ts",
10-
"homepage": "https://github.com/pmndrs/detect-gpu#readme",
10+
"homepage": "https://github.com/Roll20/detect-gpu#readme",
1111
"bugs": {
12-
"url": "https://github.com/pmndrs/detect-gpu/issues"
12+
"url": "https://github.com/Roll20/detect-gpu/issues"
1313
},
1414
"repository": {
1515
"type": "git",
16-
"url": "https://github.com/pmndrs/detect-gpu.git"
16+
"url": "https://github.com/Roll20/detect-gpu.git"
1717
},
1818
"files": [
1919
"dist"
2020
],
21-
"keywords": [
22-
"gpu",
23-
"detect",
24-
"webgl",
25-
"webgl2",
26-
"three.js",
27-
"babylonjs",
28-
"three",
29-
"babylon",
30-
"3d",
31-
"typescript",
32-
"javascript"
33-
],
21+
"publishConfig": {
22+
"@roll20:registry": "https://npm.pkg.github.com"
23+
},
24+
"keywords": [],
3425
"scripts": {
3526
"start": "rollup -c rollup/config.lib.ts -w --configPlugin rollup-plugin-typescript2",
3627
"lint": "eslint \"src/**/*.ts\" \"test/**/*.ts\" \"test/**/*.test.ts\" \"rollup/**/*.ts\" \"scripts/**/*.ts\" \"scripts/**/*.js\" --fix --cache --cache-location ~/.eslintcache/eslintcache",
@@ -42,7 +33,8 @@
4233
"build": "rollup -c rollup/config.lib.ts --configPlugin rollup-plugin-typescript2",
4334
"example": "rollup -w -c rollup/config.dev.ts --configPlugin rollup-plugin-typescript2",
4435
"parse-analytics": "node ./scripts/analytics_parser.js",
45-
"update-benchmarks": "rimraf benchmarks && mkdir -p benchmarks && mkdir -p benchmarks-min && ts-node -O '{\"module\":\"commonjs\"}' ./scripts/update_benchmarks.ts && tar -czvf benchmarks.tar.gz benchmarks-min/*.json && rm -rf benchmarks-min"
36+
"update-benchmarks": "rimraf benchmarks && mkdir -p benchmarks && mkdir -p benchmarks-min && ts-node -O '{\"module\":\"commonjs\"}' ./scripts/update_benchmarks.ts && tar -czvf benchmarks.tar.gz benchmarks-min/*.json && rm -rf benchmarks-min",
37+
"prepare": "npm run build"
4638
},
4739
"dependencies": {
4840
"webgl-constants": "^1.1.1"
@@ -53,6 +45,7 @@
5345
"@types/jest": "^29.5.3",
5446
"@typescript-eslint/eslint-plugin": "^6.4.0",
5547
"@typescript-eslint/parser": "^6.4.0",
48+
"cross-fetch": "^4.1.0",
5649
"csvtojson": "^2.0.10",
5750
"eslint": "^8.4.1",
5851
"eslint-config-prettier": "^9.0.0",

scripts/update_benchmarks.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,13 @@ type Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>;
184184
});
185185

186186
async function fetchBenchmarks() {
187-
const browser = await puppeteer.launch({ headless: true });
187+
const browser = await puppeteer.launch({
188+
headless: true,
189+
args: [
190+
'--no-sandbox',
191+
'--disable-setuid-sandbox',
192+
],
193+
});
188194
const page = await browser.newPage();
189195

190196
await page.goto(BENCHMARK_URL, { waitUntil: 'networkidle2' });

src/index.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -216,20 +216,23 @@ export const getGPUTier = async ({
216216
}
217217

218218
const tokenizedRenderer = tokenizeForLevenshteinDistance(renderer);
219-
// eslint-disable-next-line prefer-const
220-
let [gpu, , , , fpsesByPixelCount] =
219+
220+
// pick the best matching row
221+
const bestMatch =
221222
matchCount > 1
222223
? matched
223-
.map(
224-
(match) =>
225-
[
226-
match,
227-
getLevenshteinDistance(tokenizedRenderer, match[2]),
228-
] as const
224+
.map((match) =>
225+
[match, getLevenshteinDistance(tokenizedRenderer, match[2])] as const
229226
)
230227
.sort(([, a], [, b]) => a - b)[0][0]
231228
: matched[0];
232229

230+
// gpu name is always at index 0
231+
const gpu = bestMatch[0];
232+
233+
// fpses array is always the last element
234+
const fpsesByPixelCount = bestMatch[bestMatch.length - 1] as ModelEntryScreen[];
235+
233236
debug?.(
234237
`${renderer} matched closest to ${gpu} with the following screen sizes`,
235238
JSON.stringify(fpsesByPixelCount)

src/internal/deobfuscateAppleGPU.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ export function deobfuscateAppleGPU(
5656
['a15', codeA, 15], // ipad mini 6th gen / ipad 10th gen
5757
['m1', codeA, 15], // ipad pro 11 5nd gen / ipad pro 12.9 5th gen / ipad air 5th gen
5858
['m2', codeA, 15], // ipad pro 11 6nd gen / ipad pro 12.9 6th gen
59+
['m4', codeA, 15], // ipad pro 11 7nd gen / ipad pro 13 7th gen
5960
]
6061
: [
6162
// ['a4', 7], // 4 / ipod touch 4th gen
@@ -72,6 +73,7 @@ export function deobfuscateAppleGPU(
7273
['a15', codeA, 15], // 13 / 13 mini / 13 pro / 13 pro max / se 3rd gen / 14 / 14 plus
7374
['a16', codeA, 15], // 14 pro / 14 pro max / 15 / 15 plus
7475
['a17', codeA, 15], // 15 pro / 15 pro max
76+
['a18', codeA, 15], // 16 / 16 plus / 16 pro / 16 pro max
7577
];
7678
let chipsets: typeof possibleChipsets;
7779

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/**
2+
* @jest-environment node
3+
*
4+
*/
5+
6+
import fetch from 'cross-fetch';
7+
(global as any).fetch = fetch;
8+
import fs from 'fs/promises';
9+
10+
const BENCHMARKS_URL = process.env.BENCHMARKS_URL || 'https://roll20.github.io/detect-gpu';
11+
const TEST_FILE = 'd-apple.json';
12+
13+
interface ScreenEntry extends Array<number> {
14+
0: number;
15+
1: number;
16+
2: number;
17+
}
18+
19+
describe('Live benchmark data shape', () => {
20+
let data: unknown;
21+
22+
beforeAll(async () => {
23+
const base = BENCHMARKS_URL.replace(/\/$/, '');
24+
if (base.startsWith('file://')) {
25+
const dirPath = base.replace(/^file:\/\//, '');
26+
const raw = await fs.readFile(`${dirPath}/${TEST_FILE}`, 'utf8');
27+
data = JSON.parse(raw);
28+
} else {
29+
const res = await fetch(`${base}/${TEST_FILE}`);
30+
expect(res.ok).toBe(true);
31+
data = await res.json();
32+
}
33+
});
34+
35+
it('is an array with a version string at index 0', () => {
36+
expect(Array.isArray(data)).toBe(true);
37+
expect(typeof (data as any)[0]).toBe('string');
38+
});
39+
40+
it('each entry has the correct tuple shape', () => {
41+
const entries = (data as any).slice(1);
42+
expect(entries.length).toBeGreaterThan(0);
43+
44+
for (const entry of entries) {
45+
expect(Array.isArray(entry)).toBe(true);
46+
expect([4, 5]).toContain(entry.length);
47+
48+
const screens = entry[entry.length - 1];
49+
expect(Array.isArray(screens)).toBe(true);
50+
expect(screens.length).toBeGreaterThan(0);
51+
52+
for (const screen of screens) {
53+
expect(Array.isArray(screen)).toBe(true);
54+
expect((screen as ScreenEntry).length).toBe(3);
55+
56+
const [w, h, fps] = screen as ScreenEntry;
57+
expect(typeof w).toBe('number');
58+
expect(typeof h).toBe('number');
59+
expect(typeof fps).toBe('number');
60+
}
61+
}
62+
});
63+
});

0 commit comments

Comments
 (0)