Advance M8-M11 parity workflows
This commit is contained in:
90
web/protocol/nanovdb-render-golden.ts
Normal file
90
web/protocol/nanovdb-render-golden.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
import type { ErrorCode } from "./error";
|
||||
|
||||
export const NANOVDB_RENDER_GOLDEN_SCHEMA_VERSION = 1 as const;
|
||||
export const NANOVDB_GOLDEN_MISMATCH_CODE = "NANOVDB_GOLDEN_MISMATCH" as const satisfies ErrorCode;
|
||||
|
||||
export interface NanoVDBRenderGoldenThresholdsIR {
|
||||
maxChannelError: number;
|
||||
meanAbsoluteError: number;
|
||||
rmsError: number;
|
||||
alphaCoverageDeltaRatio: number;
|
||||
}
|
||||
|
||||
export interface NanoVDBRenderGoldenComparisonIR {
|
||||
schemaVersion: typeof NANOVDB_RENDER_GOLDEN_SCHEMA_VERSION;
|
||||
status: "READY" | "BLOCKED";
|
||||
pixelCount: number;
|
||||
comparedChannels: number;
|
||||
maxChannelError: number;
|
||||
meanAbsoluteError: number;
|
||||
rmsError: number;
|
||||
referenceAlphaPixels: number;
|
||||
actualAlphaPixels: number;
|
||||
alphaCoverageDeltaRatio: number;
|
||||
thresholds: NanoVDBRenderGoldenThresholdsIR;
|
||||
errorCode: typeof NANOVDB_GOLDEN_MISMATCH_CODE | null;
|
||||
}
|
||||
|
||||
function validateThresholds(value: NanoVDBRenderGoldenThresholdsIR): NanoVDBRenderGoldenThresholdsIR {
|
||||
if (
|
||||
!Number.isInteger(value.maxChannelError) || value.maxChannelError < 0 || value.maxChannelError > 255 ||
|
||||
!Number.isFinite(value.meanAbsoluteError) || value.meanAbsoluteError < 0 || value.meanAbsoluteError > 255 ||
|
||||
!Number.isFinite(value.rmsError) || value.rmsError < 0 || value.rmsError > 255 ||
|
||||
!Number.isFinite(value.alphaCoverageDeltaRatio) || value.alphaCoverageDeltaRatio < 0 || value.alphaCoverageDeltaRatio > 1
|
||||
) {
|
||||
throw new Error("NANOVDB_INVALID_ARGUMENT: render golden thresholds are invalid");
|
||||
}
|
||||
return { ...value };
|
||||
}
|
||||
|
||||
export function compareNanoVDBRenderGolden(
|
||||
reference: Uint8Array,
|
||||
actual: Uint8Array,
|
||||
thresholdsValue: NanoVDBRenderGoldenThresholdsIR,
|
||||
): NanoVDBRenderGoldenComparisonIR {
|
||||
if (
|
||||
!(reference instanceof Uint8Array) || !(actual instanceof Uint8Array) ||
|
||||
reference.byteLength === 0 || reference.byteLength !== actual.byteLength ||
|
||||
reference.byteLength % 4 !== 0
|
||||
) {
|
||||
throw new Error("NANOVDB_INVALID_ARGUMENT: render golden images must be equal non-empty RGBA8 buffers");
|
||||
}
|
||||
const thresholds = validateThresholds(thresholdsValue);
|
||||
let maximum = 0;
|
||||
let absoluteTotal = 0;
|
||||
let squaredTotal = 0;
|
||||
let referenceAlphaPixels = 0;
|
||||
let actualAlphaPixels = 0;
|
||||
for (let index = 0; index < reference.byteLength; index++) {
|
||||
const difference = Math.abs(reference[index] - actual[index]);
|
||||
maximum = Math.max(maximum, difference);
|
||||
absoluteTotal += difference;
|
||||
squaredTotal += difference * difference;
|
||||
if ((index & 3) === 3) {
|
||||
if (reference[index] > 0) referenceAlphaPixels++;
|
||||
if (actual[index] > 0) actualAlphaPixels++;
|
||||
}
|
||||
}
|
||||
const pixelCount = reference.byteLength / 4;
|
||||
const meanAbsoluteError = absoluteTotal / reference.byteLength;
|
||||
const rmsError = Math.sqrt(squaredTotal / reference.byteLength);
|
||||
const alphaCoverageDeltaRatio = Math.abs(referenceAlphaPixels - actualAlphaPixels) / pixelCount;
|
||||
const matches = maximum <= thresholds.maxChannelError &&
|
||||
meanAbsoluteError <= thresholds.meanAbsoluteError &&
|
||||
rmsError <= thresholds.rmsError &&
|
||||
alphaCoverageDeltaRatio <= thresholds.alphaCoverageDeltaRatio;
|
||||
return {
|
||||
schemaVersion: NANOVDB_RENDER_GOLDEN_SCHEMA_VERSION,
|
||||
status: matches ? "READY" : "BLOCKED",
|
||||
pixelCount,
|
||||
comparedChannels: reference.byteLength,
|
||||
maxChannelError: maximum,
|
||||
meanAbsoluteError,
|
||||
rmsError,
|
||||
referenceAlphaPixels,
|
||||
actualAlphaPixels,
|
||||
alphaCoverageDeltaRatio,
|
||||
thresholds,
|
||||
errorCode: matches ? null : NANOVDB_GOLDEN_MISMATCH_CODE,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user