UNPKG

playcanvas

Version:

Open-source WebGL/WebGPU 3D engine for the web

112 lines (111 loc) 4.6 kB
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 };