UNPKG

playcanvas

Version:

PlayCanvas WebGL game engine

150 lines (147 loc) 6.72 kB
import { Debug } from '../../../core/debug.js'; import { DebugGraphics } from '../debug-graphics.js'; function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } function _async_to_generator(fn) { return function() { var self = this, args = arguments; return new Promise(function(resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } /** * @import { WebgpuGraphicsDevice } from './webgpu-graphics-device.js' */ // Maximum number of times a duplicate error message is logged. var MAX_DUPLICATES = 5; /** * Internal WebGPU debug system. Note that the functions only execute in the debug build, and are * stripped out in other builds. */ 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 end(device, label) { for(var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++){ args[_key - 2] = arguments[_key]; } return _async_to_generator(function*() { var header = WebgpuDebug._scopes.pop(); var marker = WebgpuDebug._markers.pop(); Debug.assert(header, 'Non matching end.'); var error = yield device.wgpu.popErrorScope(); if (error) { var _WebgpuDebug__loggedMessages_get; var count = (_WebgpuDebug__loggedMessages_get = WebgpuDebug._loggedMessages.get(error.message)) != null ? _WebgpuDebug__loggedMessages_get : 0; if (count < MAX_DUPLICATES) { var 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 endShader(device, shaderModule, source, contextLines) { if (contextLines === void 0) contextLines = 2; for(var _len = arguments.length, args = new Array(_len > 4 ? _len - 4 : 0), _key = 4; _key < _len; _key++){ args[_key - 4] = arguments[_key]; } return _async_to_generator(function*() { var header = WebgpuDebug._scopes.pop(); var marker = WebgpuDebug._markers.pop(); Debug.assert(header, 'Non-matching error scope end.'); // Capture popErrorScope error (if any) var error = yield device.wgpu.popErrorScope(); var errorMessage = ''; if (error) { errorMessage += "WebGPU ShaderModule creation " + header + " error: " + error.message; errorMessage += " - While rendering " + marker + "\n"; } // Get shader compilation errors var compilationInfo = yield shaderModule.getCompilationInfo(); if (compilationInfo.messages.length > 0) { // split source into lines var sourceLines = source.split('\n'); compilationInfo.messages.forEach((message, index)=>{ var { type, lineNum, linePos, message: msg } = message; var lineIndex = lineNum - 1; // Convert to zero-based index errorMessage += "\n----- " + type.toUpperCase() + " " + (index + 1) + " context: :" + lineNum + ":" + linePos + " " + type + ": " + msg + "\n"; // Extract surrounding lines for context var startLine = Math.max(0, lineIndex - contextLines); var endLine = Math.min(sourceLines.length, lineIndex + contextLines + 1); for(var i = startLine; i < endLine; i++){ var linePrefix = i === lineIndex ? '> ' : ' '; errorMessage += "" + linePrefix + (i + 1) + ": " + sourceLines[i] + "\n"; } }); } // only log if there are errors or messages if (errorMessage) { console.error(errorMessage, ...args); } })(); } } WebgpuDebug._scopes = []; WebgpuDebug._markers = []; /** @type {Map<string,number>} */ WebgpuDebug._loggedMessages = new Map(); export { WebgpuDebug };