Skip to content

Commit

Permalink
Fix MSAA hang for Mali-G71 and Mali-G76 GPUs (#3499)
Browse files Browse the repository at this point in the history
  • Loading branch information
markschlosseratbentley authored Apr 8, 2022
1 parent d2ec9cb commit bc0d93c
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 9 deletions.
1 change: 1 addition & 0 deletions common/api/webgl-compatibility.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ export enum DepthType {
// @public
export interface GraphicsDriverBugs {
fragDepthDoesNotDisableEarlyZ?: true;
msaaWillHang?: true;
}

// @public
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@itwin/webgl-compatibility",
"comment": "Do not allow buggy GPUs to render MSAA.",
"type": "none"
}
],
"packageName": "@itwin/webgl-compatibility"
}
26 changes: 17 additions & 9 deletions core/webgl-compatibility/src/Capabilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ const buggyIntelMatchers = [
/ANGLE \(Intel, Intel\(R\) (U)?HD Graphics 6(2|3)0 Direct3D11/,
];

// Regexes to match Mali GPUs known to suffer from GraphicsDriverBugs.msaaWillHang.
const buggyMaliMatchers = [
/Mali-G71/,
/Mali-G76/,
];

// Regexes to match as many Intel integrated GPUs as possible.
// https://en.wikipedia.org/wiki/List_of_Intel_graphics_processing_units
const integratedIntelGpuMatchers = [
Expand Down Expand Up @@ -254,6 +260,16 @@ export class Capabilities {

this._isMobile = ProcessDetector.isMobileBrowser;

const debugInfo = gl.getExtension("WEBGL_debug_renderer_info");
const unmaskedRenderer = debugInfo !== null ? gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL) : undefined;
const unmaskedVendor = debugInfo !== null ? gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL) : undefined;

this._driverBugs = {};
if (unmaskedRenderer && buggyIntelMatchers.some((x) => x.test(unmaskedRenderer)))
this._driverBugs.fragDepthDoesNotDisableEarlyZ = true;
if (unmaskedRenderer && buggyMaliMatchers.some((x) => x.test(unmaskedRenderer)))
this._driverBugs.msaaWillHang = true;

this._maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);
this._supportsCreateImageBitmap = typeof createImageBitmap === "function" && ProcessDetector.isChromium && !ProcessDetector.isIOSBrowser;
this._maxTexSizeAllow = Math.min(this._maxTextureSize, maxTexSizeAllowed);
Expand All @@ -263,7 +279,7 @@ export class Capabilities {
this._maxVertUniformVectors = gl.getParameter(gl.MAX_VERTEX_UNIFORM_VECTORS);
this._maxVaryingVectors = gl.getParameter(gl.MAX_VARYING_VECTORS);
this._maxFragUniformVectors = gl.getParameter(gl.MAX_FRAGMENT_UNIFORM_VECTORS);
this._maxAntialiasSamples = (this._isWebGL2 && undefined !== gl2 ? gl.getParameter(gl2.MAX_SAMPLES) : 1);
this._maxAntialiasSamples = this._driverBugs.msaaWillHang ? 1 : (this._isWebGL2 && undefined !== gl2 ? gl.getParameter(gl2.MAX_SAMPLES) : 1);

const extensions = gl.getSupportedExtensions(); // This just retrieves a list of available extensions (not necessarily enabled).
if (extensions) {
Expand All @@ -289,10 +305,6 @@ export class Capabilities {
this._maxDrawBuffers = dbExt !== undefined ? gl.getParameter(dbExt.MAX_DRAW_BUFFERS_WEBGL) : 1;
}

const debugInfo = gl.getExtension("WEBGL_debug_renderer_info");
const unmaskedRenderer = debugInfo !== null ? gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL) : undefined;
const unmaskedVendor = debugInfo !== null ? gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL) : undefined;

// Determine the maximum color-renderable attachment type.
const allowFloatRender =
(undefined === disabledExtensions || -1 === disabledExtensions.indexOf("OES_texture_float"))
Expand Down Expand Up @@ -323,10 +335,6 @@ export class Capabilities {
const missingRequiredFeatures = this._findMissingFeatures(Capabilities.requiredFeatures);
const missingOptionalFeatures = this._findMissingFeatures(Capabilities.optionalFeatures);

this._driverBugs = {};
if (unmaskedRenderer && buggyIntelMatchers.some((x) => x.test(unmaskedRenderer)))
this._driverBugs.fragDepthDoesNotDisableEarlyZ = true;

return {
status: this._getCompatibilityStatus(missingRequiredFeatures, missingOptionalFeatures),
missingRequiredFeatures,
Expand Down
7 changes: 7 additions & 0 deletions core/webgl-compatibility/src/RenderCompatibility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,13 @@ export interface GraphicsDriverBugs {
* The workaround for this bug has minimal impact on performance and no impact on visual fidelity.
*/
fragDepthDoesNotDisableEarlyZ?: true;
/** If true, the graphics driver will hang when applying MSAA to a viewport.
*
* Known to affect certain mobile Mali chipsets (G71 and G76). May affect more.
*
* The workaround for this bug means MSAA cannot be enabled on those devices.
*/
msaaWillHang?: true;
}

/** Describes the level of compatibility of a client device/browser with the iTwin.js rendering system.
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 @@ -240,4 +240,30 @@ describe("Render Compatibility", () => {
expect(compatibility.usingIntegratedGraphics).to.equal(renderer[1]);
}
});

it("detects MSAA hang bug", () => {
const renderers = [
[ "Mali-G71", true ],
[ "Mali-G76", true ],
[ "ANGLE (Intel HD Graphics 620 Direct3D11 vs_5_0 ps_5_0)", false ],
[ "Mali-G79", 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);

const expected = renderer[1] ? true : undefined;
expect(compatibility.driverBugs.msaaWillHang).to.equal(expected);
}
});
});

0 comments on commit bc0d93c

Please sign in to comment.