playcanvas
Version:
Open-source WebGL/WebGPU 3D engine for the web
112 lines (111 loc) • 4.6 kB
JavaScript
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
import { Debug } from "../../../core/debug.js";
import { DebugGraphics } from "../debug-graphics.js";
const MAX_DUPLICATES = 5;
const _WebgpuDebug = class _WebgpuDebug {
/**
* Start a validation error scope.
*
* @param {WebgpuGraphicsDevice} device - The graphics device.
*/
static validate(device) {
device.wgpu.pushErrorScope("validation");
_WebgpuDebug._scopes.push("validation");
_WebgpuDebug._markers.push(DebugGraphics.toString());
}
/**
* Start an out-of-memory error scope.
*
* @param {WebgpuGraphicsDevice} device - The graphics device.
*/
static memory(device) {
device.wgpu.pushErrorScope("out-of-memory");
_WebgpuDebug._scopes.push("out-of-memory");
_WebgpuDebug._markers.push(DebugGraphics.toString());
}
/**
* Start an internal error scope.
*
* @param {WebgpuGraphicsDevice} device - The graphics device.
*/
static internal(device) {
device.wgpu.pushErrorScope("internal");
_WebgpuDebug._scopes.push("internal");
_WebgpuDebug._markers.push(DebugGraphics.toString());
}
/**
* End the previous error scope, and print errors if any.
*
* @param {WebgpuGraphicsDevice} device - The graphics device.
* @param {string} label - The label for the error scope.
* @param {...any} args - Additional parameters that form the error message.
*/
static async end(device, label, ...args) {
const header = _WebgpuDebug._scopes.pop();
const marker = _WebgpuDebug._markers.pop();
Debug.assert(header, "Non matching end.");
const error = await device.wgpu.popErrorScope();
if (error) {
const count = _WebgpuDebug._loggedMessages.get(error.message) ?? 0;
if (count < MAX_DUPLICATES) {
const tooMany = count === MAX_DUPLICATES - 1 ? " (Too many errors, ignoring this one from now)" : "";
_WebgpuDebug._loggedMessages.set(error.message, count + 1);
console.error(`WebGPU ${label} ${header} error: ${error.message}`, tooMany, "while rendering", marker, ...args);
}
}
}
/**
* Ends the shader validation scope by retrieving and logging any compilation errors
* or warnings from the shader module. Also handles WebGPU validation errors, while
* avoiding duplicate error messages.
*
* @param {WebgpuGraphicsDevice} device - The WebGPU graphics device.
* @param {GPUShaderModule} shaderModule - The compiled WebGPU shader module.
* @param {string} source - The original shader source code.
* @param {number} [contextLines] - The number of lines before and after the error to log.
* @param {...any} args - Additional parameters providing context about the shader.
*/
static async endShader(device, shaderModule, source, contextLines = 2, ...args) {
const header = _WebgpuDebug._scopes.pop();
const marker = _WebgpuDebug._markers.pop();
Debug.assert(header, "Non-matching error scope end.");
const error = await device.wgpu.popErrorScope();
let errorMessage = "";
if (error) {
errorMessage += `WebGPU ShaderModule creation ${header} error: ${error.message}`;
errorMessage += ` - While rendering ${marker}
`;
}
const compilationInfo = await shaderModule.getCompilationInfo();
if (compilationInfo.messages.length > 0) {
const sourceLines = source.split("\n");
compilationInfo.messages.forEach((message, index) => {
const { type, lineNum, linePos, message: msg } = message;
const lineIndex = lineNum - 1;
errorMessage += `
----- ${type.toUpperCase()} ${index + 1} context: :${lineNum}:${linePos} ${type}: ${msg}
`;
const startLine = Math.max(0, lineIndex - contextLines);
const endLine = Math.min(sourceLines.length, lineIndex + contextLines + 1);
for (let i = startLine; i < endLine; i++) {
const linePrefix = i === lineIndex ? "> " : " ";
errorMessage += `${linePrefix}${i + 1}: ${sourceLines[i]}
`;
}
});
}
if (errorMessage) {
console.error(errorMessage, ...args);
}
}
};
__publicField(_WebgpuDebug, "_scopes", []);
__publicField(_WebgpuDebug, "_markers", []);
/** @type {Map<string,number>} */
__publicField(_WebgpuDebug, "_loggedMessages", /* @__PURE__ */ new Map());
let WebgpuDebug = _WebgpuDebug;
export {
WebgpuDebug
};