perf(movimento): vitrine e 3D mais leves, WebGL por software lembrado na sessão e suporte ao WebKit
This commit is contained in:
1 parent
9fd1570426
commit
8903f3c57e
28 files changed
+854
-406
No files matched your search
@@ -1,4 +1,5 @@
|
||||
import { act, render } from "@testing-library/react";
|
||||
import { isKnownSoftwareWebGL } from "@/lib/device";
|
||||
import HeroFieldScene from "./HeroFieldScene";
|
||||
|
||||
/*
|
||||
@@ -15,6 +16,8 @@ type RendererOptions = {
|
||||
};
|
||||
const mockRenderers: MockRenderer[] = [];
|
||||
let mockFailToCreate = false;
|
||||
/** O nome do renderizador que o contexto de teste conta (WEBGL_debug_renderer_info); `null` = a extensão não existe. */
|
||||
let mockRendererName: string | null = null;
|
||||
/** Quando o teste quer segurar a compilação do shader: a promessa que `compileAsync` devolve. */
|
||||
let mockCompile: () => Promise<unknown> = () => Promise.resolve();
|
||||
|
||||
@@ -31,6 +34,14 @@ class MockRenderer {
|
||||
this.pixelRatio = value;
|
||||
};
|
||||
getPixelRatio = () => this.pixelRatio;
|
||||
getContext = () => ({
|
||||
getExtension: (name: string) =>
|
||||
name === "WEBGL_debug_renderer_info" && mockRendererName !== null
|
||||
? { UNMASKED_RENDERER_WEBGL: 37446 }
|
||||
: null,
|
||||
getParameter: (parameter: number) =>
|
||||
parameter === 37446 ? mockRendererName : null,
|
||||
});
|
||||
constructor(options: RendererOptions) {
|
||||
if (mockFailToCreate) throw new Error("sem WebGL");
|
||||
this.options = options;
|
||||
@@ -64,6 +75,7 @@ beforeEach(() => {
|
||||
jest.useFakeTimers();
|
||||
mockRenderers.length = 0;
|
||||
mockFailToCreate = false;
|
||||
mockRendererName = null;
|
||||
mockCompile = () => Promise.resolve();
|
||||
setDevicePixelRatio(1);
|
||||
});
|
||||
@@ -406,3 +418,54 @@ describe("HeroFieldScene (ambient 3D)", () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("HeroFieldScene: WebGL por software (o teste é o contexto da própria cena)", () => {
|
||||
beforeEach(() => sessionStorage.clear());
|
||||
afterEach(() => sessionStorage.clear());
|
||||
|
||||
it.each([
|
||||
"ANGLE (Google, Vulkan 1.3.0 (SwiftShader Device (Subzero) (0x0000C0DE)), SwiftShader driver)",
|
||||
"llvmpipe (LLVM 15.0.7, 256 bits)",
|
||||
"ANGLE (Microsoft, Microsoft Basic Render Driver (0x0000008C) Direct3D11 vs_5_0 ps_5_0, D3D11)",
|
||||
])(
|
||||
"draws on the CPU (%s): no canvas, the page is told once, the context is freed and the session remembers it",
|
||||
async (name) => {
|
||||
mockRendererName = name;
|
||||
const scene = props();
|
||||
|
||||
const { container } = await mount(<HeroFieldScene {...scene} />);
|
||||
|
||||
// um só contexto: o do teste é o que a cena abriria para desenhar, sem um segundo
|
||||
expect(mockRenderers).toHaveLength(1);
|
||||
expect(mockRenderers[0].dispose).toHaveBeenCalledTimes(1);
|
||||
expect(mockRenderers[0].forceContextLoss).toHaveBeenCalledTimes(1);
|
||||
expect(mockRenderers[0].compileAsync).not.toHaveBeenCalled();
|
||||
expect(container.querySelector("canvas")).toBeNull();
|
||||
expect(scene.onError).toHaveBeenCalledTimes(1);
|
||||
expect(scene.onReady).not.toHaveBeenCalled();
|
||||
expect(isKnownSoftwareWebGL()).toBe(true);
|
||||
},
|
||||
);
|
||||
|
||||
it("draws on the GPU: the canvas stays and the session is not marked", async () => {
|
||||
mockRendererName =
|
||||
"ANGLE (NVIDIA, NVIDIA GeForce RTX 3070 Direct3D11 vs_5_0 ps_5_0, D3D11)";
|
||||
const scene = props();
|
||||
|
||||
const { container } = await mount(<HeroFieldScene {...scene} />);
|
||||
|
||||
expect(container.querySelector("canvas")).toBe(mockRenderers[0].domElement);
|
||||
expect(scene.onError).not.toHaveBeenCalled();
|
||||
expect(isKnownSoftwareWebGL()).toBe(false);
|
||||
});
|
||||
|
||||
it("does not report an unknown renderer (no debug extension) as software", async () => {
|
||||
mockRendererName = null;
|
||||
const scene = props();
|
||||
|
||||
await mount(<HeroFieldScene {...scene} />);
|
||||
|
||||
expect(scene.onError).not.toHaveBeenCalled();
|
||||
expect(isKnownSoftwareWebGL()).toBe(false);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user