Skip to content
Open
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 Apps/Playground/Scripts/validation_native.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
// corrupt later tests (e.g. the glow-layer test).
engine.setStencilBuffer(false);
engine.disableScissor();
engine.useReverseDepthBuffer = false;

// This is necessary because of https://github.com/BabylonJS/Babylon.js/pull/15217 so that each test starts fresh.
engine.releaseEffects();
Expand Down
95 changes: 95 additions & 0 deletions Apps/Playground/Tests/validation_cleanup.test.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
const assert = require("node:assert/strict");
const { readFileSync } = require("node:fs");
const { join } = require("node:path");
const { test } = require("node:test");
const { runInNewContext } = require("node:vm");

const source = readFileSync(join(__dirname, "..", "Scripts", "validation_native.js"), "utf8");

function extractFunctionDeclaration(name) {
const escapedName = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
const match = new RegExp(`\\bfunction\\s+${escapedName}\\s*\\(`).exec(source);
assert.ok(match, `Could not find function ${name}`);
const bodyStart = source.indexOf("{", match.index + match[0].length);
assert.ok(bodyStart >= 0, `Could not find body for function ${name}`);

let depth = 0;
let quote = null;
let escaped = false;
let lineComment = false;
let blockComment = false;
for (let index = bodyStart; index < source.length; ++index) {
const character = source[index];
const next = source[index + 1];
if (lineComment) {
lineComment = character !== "\n";
continue;
}
if (blockComment) {
if (character === "*" && next === "/") {
blockComment = false;
++index;
}
continue;
}
if (quote) {
if (escaped) {
escaped = false;
} else if (character === "\\") {
escaped = true;
} else if (character === quote) {
quote = null;
}
continue;
}
if (character === "/" && next === "/") {
lineComment = true;
++index;
} else if (character === "/" && next === "*") {
blockComment = true;
++index;
} else if (character === "\"" || character === "'" || character === "`") {
quote = character;
} else if (character === "{") {
++depth;
} else if (character === "}" && --depth === 0) {
return source.slice(match.index, index + 1);
}
}
assert.fail(`Could not find end of function ${name}`);
}

test("restores forward depth between scenes on the reused engine", () => {
let disposed = 0;
let released = 0;
const leakedTexture = {};
const leakedTextures = [leakedTexture];
const engine = {
scenes: [],
useReverseDepthBuffer: true,
setHardwareScalingLevel() {},
setStencilBuffer() {},
disableScissor() {},
releaseEffects() { assert.equal(this.useReverseDepthBuffer, false); },
getLoadedTexturesCache() { return leakedTextures; },
_releaseTexture(texture) {
assert.equal(texture, leakedTexture);
++released;
leakedTextures.pop();
},
clearInternalTexturesCache() { leakedTextures.length = 0; },
};
Comment thread
bkaradzic-microsoft marked this conversation as resolved.
const context = {
engine,
currentScene: { dispose() { disposed++; } },
console,
BABYLON: { SceneLoader: { OnPluginActivatedObservable: { clear() {} } } },
};
const cleanupAfterTest = runInNewContext(`(${extractFunctionDeclaration("cleanupAfterTest")})`, context);
cleanupAfterTest();
cleanupAfterTest();
assert.equal(disposed, 1);
assert.equal(released, 1);
assert.equal(context.currentScene, null);
assert.equal(engine.useReverseDepthBuffer, false);
});
8 changes: 6 additions & 2 deletions Documentation/ContinuousIntegration.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ These features are multiplatform and the code can be found here : `Apps\Validati

## The test script

The native runner reuses its engine between scenes. Cleanup restores forward depth
(`engine.useReverseDepthBuffer = false`), stencil, and scissor state before the next scene.
Run the cleanup regression without a native build:
`node --test Apps/Playground/Tests/validation_cleanup.test.cjs`.

It loads the json using XMLHttpRequest, then for each entry in the json, loads the Playground, runs it, make a capture.
The most important part is the image comparison. It works the same way as babylonjs validation test.
The function `compare` is responsible for comparing each pixel. Every pixel for a same coordinate that is too much different between reference and rendering are counted.
Expand Down Expand Up @@ -137,7 +142,6 @@ Then, for the intended plaform, download the .zip:

![BuildPage](Images/CI_DownloadZip.jpg)

Finaly, open the zip file. It will contain all rendered images for the build. If the build fails at build time, no artifact will be produced. If the image comparison fails, an artifact containing the image difference will be published.
Finally, open the zip file. It will contain all rendered images for the build. If the build fails at build time, no artifact will be produced. If the image comparison fails, an artifact containing the image difference will be published.

![BuildPage](Images/CI_ArtifactImage.jpg)

Loading