Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide API to detect integrated graphics #3324

Merged
merged 14 commits into from
Mar 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions common/api/webgl-compatibility.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ export interface WebGLRenderCompatibilityInfo {
unmaskedRenderer?: string;
unmaskedVendor?: string;
userAgent: string;
usingIntegratedGraphics?: boolean;
}

// @public
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@itwin/webgl-compatibility",
"comment": "A `usingIntegratedGraphics` property has been added to WebGLRenderCompatibilityInfo. If true, there is a likelihood that integrated graphics are being used.",
"type": "none"
}
],
"packageName": "@itwin/webgl-compatibility"
}
18 changes: 18 additions & 0 deletions core/webgl-compatibility/src/Capabilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,23 @@ const buggyIntelMatchers = [
/ANGLE \(Intel, Intel\(R\) (U)?HD Graphics 6(2|3)0 Direct3D11/,
];

// Regexes to match as many Intel integrated GPUs as possible.
// https://en.wikipedia.org/wiki/List_of_Intel_graphics_processing_units
const integratedIntelGpuMatchers = [
/(U)?HD Graphics/,
/Iris/,
];

function isIntegratedGraphics(args: {unmaskedVendor?: string, unmaskedRenderer?: string}): boolean {
if (args.unmaskedRenderer && args.unmaskedRenderer.includes("Intel") && integratedIntelGpuMatchers.some((x) => x.test(args.unmaskedRenderer!)))
return true;

// NB: For now, we do not attempt to detect AMD integrated graphics.
// It appears that AMD integrated graphics are not usually paired with a graphics card so detecting integrated usage there is less important than Intel.

return false;
}

/** Describes the rendering capabilities of the host system.
* @internal
*/
Expand Down Expand Up @@ -316,6 +333,7 @@ export class Capabilities {
missingOptionalFeatures,
unmaskedRenderer,
unmaskedVendor,
usingIntegratedGraphics: isIntegratedGraphics({unmaskedVendor, unmaskedRenderer}),
driverBugs: { ...this._driverBugs },
userAgent: navigator.userAgent,
createdContext: gl,
Expand Down
4 changes: 4 additions & 0 deletions core/webgl-compatibility/src/RenderCompatibility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ export interface WebGLRenderCompatibilityInfo {
unmaskedRenderer?: string;
/** The vendor string reported by this client's graphics driver. */
unmaskedVendor?: string;
/** If true, there is a likelihood that integrated graphics are being used. This can be used to warn users on systems with both integrated graphics and dedicated graphics that they should try to switch to their dedicated graphics for better performance.
* @note This property has the possibility of providing false positives and negatives. A user should use this property mainly as a hint and manually verify what graphics chip is being used.
*/
usingIntegratedGraphics?: boolean;
/** If WebGL context creation failed, an error message supplied by the browser. */
contextErrorMessage?: string;
/** The WebGL context created by the browser and used to generate the compatibility report. */
Expand Down
26 changes: 26 additions & 0 deletions core/webgl-compatibility/src/test/Compatibility.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,4 +214,30 @@ describe("Render Compatibility", () => {
expect(caps.driverBugs.fragDepthDoesNotDisableEarlyZ).to.equal(expected);
}
});

it("detects integrated and dedicated graphics", () => {
const renderers = [
[ "ANGLE (Intel(R) HD Graphics 630 Direct3D11 vs_5_0 ps_5_0)", true ],
[ "ANGLE (Intel(R) UHD Graphics 630 Direct3D11 vs_5_0 ps_5_0)", true ],
[ "ANGLE (Intel HD Graphics 620 Direct3D11 vs_5_0 ps_5_0)", true ],
[ "Intel(R) Iris(TM) Graphics 6100", true ],
[ "ANGLE (NVIDIA GeForce GTX 970 Direct3D11 vs_5_0 ps_5_0)", false ],
];

for (const renderer of renderers) {
overriddenFunctions.overrideCreateContext((ctx: WebGLContext, pname: number) => {
const ext = ctx.getExtension("WEBGL_debug_renderer_info");
if (ext && pname === ext.UNMASKED_RENDERER_WEBGL)
return renderer[0];

return undefined;
});

const context = makeTestContext(true);
const caps = new Capabilities();
const compatibility = caps.init(context);

expect(compatibility.usingIntegratedGraphics).to.equal(renderer[1]);
}
});
});
16 changes: 15 additions & 1 deletion docs/changehistory/NextVersion.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
---
publish: false
---
# NextVersion
# NextVersion

## @itwin/webgl-compatibility changes

### Detecting integrated graphics

Many computers - especially laptops - contain two graphics processing units: a low-powered "integrated" GPU such as those manufactured by Intel, and a more powerful "discrete" GPU typically manufactured by NVidia or AMD. Operating systems and web browsers often default to using the integrated GPU to reduce power consumption, but this can produce poor performance in graphics-heavy applications like those built with iTwin.js. We recommend that users adjust their settings to use the discrete GPU if one is available.

iTwin.js applications can now check [WebGLRenderCompatibilityInfo.usingIntegratedGraphics]($webgl-compatibility) to see if the user might experience degraded performance due to the use of integrated graphics. Because WebGL does not provide access to information about specific graphics hardware, this property is only a heuristic. But it will accurately identify integrated Intel chips manufactured within the past 10 years or so, and allow the application to suggest that the user verify whether a discrete GPU is available to use instead. As a simple example:

```ts
const compatibility = IModelApp.queryRenderCompatibility();
if (compatibility.usingIntegratedGraphics)
alert("Integrated graphics are in use. If a discrete GPU is available, consider switching your device or browser to use it.");
```