@luma.gl/core 9.0.0-alpha.50 → 9.0.0-alpha.51

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,12 +5,18 @@ import { CompilerMessage } from '../../lib/compiler-log/compiler-message';
5
5
  * Properties for a Shader
6
6
  */
7
7
  export type ShaderProps = ResourceProps & {
8
+ /** Shader language (defaults to auto) */
9
+ language?: 'glsl' | 'wgsl' | 'auto';
10
+ /** Which stage are we compiling? Required by WebGL and GLSL transpiler */
8
11
  stage: 'vertex' | 'fragment' | 'compute';
12
+ /** Shader source code */
9
13
  source: string;
14
+ /** Optional shader source map (WebGPU only) */
10
15
  sourceMap?: string | null;
11
- language?: 'glsl' | 'wgsl' | 'auto';
12
- /** @deprecated use props.stage */
13
- shaderType?: 0x8b30 | 0x8b31 | 0;
16
+ /** Optional shader entry point (WebGPU only) */
17
+ entryPoint?: string;
18
+ /** Show shader source in browser? */
19
+ debug?: 'never' | 'errors' | 'warnings' | 'always';
14
20
  };
15
21
  /**
16
22
  * Immutable Shader object
@@ -19,9 +25,21 @@ export type ShaderProps = ResourceProps & {
19
25
  export declare abstract class Shader extends Resource<ShaderProps> {
20
26
  static defaultProps: Required<ShaderProps>;
21
27
  get [Symbol.toStringTag](): string;
28
+ /** The stage of this shader */
22
29
  readonly stage: 'vertex' | 'fragment' | 'compute';
30
+ /** The source code of this shader */
23
31
  readonly source: string;
32
+ /** The compilation status of this shader. May be 'pending' if compilation is done asynchronously */
33
+ compilationStatus: 'success' | 'error' | 'pending';
34
+ /** Create a new Shader instance */
24
35
  constructor(device: Device, props: ShaderProps);
25
- abstract compilationInfo(): Promise<readonly CompilerMessage[]>;
36
+ /** Get compiler log asynchronously */
37
+ abstract getCompilationInfo(): Promise<readonly CompilerMessage[]>;
38
+ /** Get compiler log synchronously (WebGL only) */
39
+ getCompilationInfoSync(): (readonly CompilerMessage[]) | null;
40
+ /** In browser logging of errors */
41
+ debugShader(): Promise<void>;
42
+ /** In-browser UI logging of errors */
43
+ protected _displayShaderLog(messages: readonly CompilerMessage[]): void;
26
44
  }
27
45
  //# sourceMappingURL=shader.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"shader.d.ts","sourceRoot":"","sources":["../../../src/adapter/resources/shader.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,WAAW,CAAC;AACtC,OAAO,EAAC,QAAQ,EAAE,aAAa,EAAC,MAAM,YAAY,CAAC;AACnD,OAAO,EAAC,eAAe,EAAC,MAAM,yCAAyC,CAAC;AAExE;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,aAAa,GAAG;IACxC,KAAK,EAAE,QAAQ,GAAG,UAAU,GAAG,SAAS,CAAC;IAEzC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IAIpC,kCAAkC;IAClC,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,CAAC,CAAC;CAClC,CAAC;AAEF;;;GAGG;AACH,8BAAsB,MAAO,SAAQ,QAAQ,CAAC,WAAW,CAAC;IACxD,OAAgB,YAAY,EAAE,QAAQ,CAAC,WAAW,CAAC,CAOjD;IAEF,IAAa,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,MAAM,CAAqB;IAEhE,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,UAAU,GAAG,SAAS,CAAC;IAClD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW;IAM9C,QAAQ,CAAC,eAAe,IAAI,OAAO,CAAC,SAAS,eAAe,EAAE,CAAC;CAChE"}
1
+ {"version":3,"file":"shader.d.ts","sourceRoot":"","sources":["../../../src/adapter/resources/shader.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,WAAW,CAAC;AACtC,OAAO,EAAC,QAAQ,EAAE,aAAa,EAAC,MAAM,YAAY,CAAC;AAGnD,OAAO,EAAC,eAAe,EAAC,MAAM,yCAAyC,CAAC;AAIxE;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,aAAa,GAAG;IACxC,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IACpC,0EAA0E;IAC1E,KAAK,EAAE,QAAQ,GAAG,UAAU,GAAG,SAAS,CAAC;IACzC,yBAAyB;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,gDAAgD;IAChD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qCAAqC;IACrC,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,UAAU,GAAG,QAAQ,CAAC;CACpD,CAAC;AAEF;;;GAGG;AACH,8BAAsB,MAAO,SAAQ,QAAQ,CAAC,WAAW,CAAC;IACxD,OAAgB,YAAY,EAAE,QAAQ,CAAC,WAAW,CAAC,CAQjD;IAEF,IAAa,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,MAAM,CAAqB;IAEhE,+BAA+B;IAC/B,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,UAAU,GAAG,SAAS,CAAC;IAClD,qCAAqC;IACrC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,oGAAoG;IACpG,iBAAiB,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,CAAa;IAE/D,mCAAmC;gBACvB,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW;IAM9C,sCAAsC;IACtC,QAAQ,CAAC,kBAAkB,IAAI,OAAO,CAAC,SAAS,eAAe,EAAE,CAAC;IAElE,kDAAkD;IAClD,sBAAsB,IAAI,CAAC,SAAS,eAAe,EAAE,CAAC,GAAG,IAAI;IAM7D,mCAAmC;IAC7B,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAwBlC,sCAAsC;IACtC,SAAS,CAAC,iBAAiB,CAAC,QAAQ,EAAE,SAAS,eAAe,EAAE,GAAG,IAAI;CAoCxE"}
@@ -1,24 +1,87 @@
1
1
  let _Symbol$toStringTag;
2
2
  import { Resource } from "./resource.js";
3
+ import { uid } from "../../lib/utils/utils.js";
4
+ import { formatCompilerLog } from "../../lib/compiler-log/format-compiler-log.js";
5
+ import { getShaderInfo } from "../../lib/compiler-log/get-shader-info.js";
3
6
  _Symbol$toStringTag = Symbol.toStringTag;
4
7
  export class Shader extends Resource {
5
8
  get [_Symbol$toStringTag]() {
6
9
  return 'Shader';
7
10
  }
8
11
  constructor(device, props) {
9
- super(device, props, Shader.defaultProps);
12
+ super(device, {
13
+ id: getShaderIdFromProps(props),
14
+ ...props
15
+ }, Shader.defaultProps);
10
16
  this.stage = void 0;
11
17
  this.source = void 0;
18
+ this.compilationStatus = 'pending';
12
19
  this.stage = this.props.stage;
13
20
  this.source = this.props.source;
14
21
  }
22
+ getCompilationInfoSync() {
23
+ return null;
24
+ }
25
+ async debugShader() {
26
+ switch (this.props.debug) {
27
+ case 'never':
28
+ return;
29
+ case 'errors':
30
+ if (this.compilationStatus === 'success') {
31
+ return;
32
+ }
33
+ break;
34
+ case 'warnings':
35
+ case 'always':
36
+ break;
37
+ }
38
+ const messages = await this.getCompilationInfo();
39
+ if (this.props.debug === 'warnings' && (messages === null || messages === void 0 ? void 0 : messages.length) === 0) {
40
+ return;
41
+ }
42
+ this._displayShaderLog(messages);
43
+ }
44
+ _displayShaderLog(messages) {
45
+ var _document, _document$getElements;
46
+ if (typeof document === 'undefined' || !((_document = document) !== null && _document !== void 0 && _document.createElement)) {
47
+ return;
48
+ }
49
+ const shaderName = getShaderInfo(this.source).name;
50
+ const shaderTitle = `${this.stage} ${shaderName}`;
51
+ const htmlLog = formatCompilerLog(messages, this.source, {
52
+ showSourceCode: 'all',
53
+ html: true
54
+ });
55
+ const button = document.createElement('Button');
56
+ button.innerHTML = `
57
+ <h1>Shader Compilation Error in ${shaderTitle}</h1><br /><br />
58
+ <code style="user-select:text;"><pre>
59
+ ${htmlLog}
60
+ </pre></code>`;
61
+ button.style.top = '10px';
62
+ button.style.left = '10px';
63
+ button.style.position = 'absolute';
64
+ button.style.zIndex = '9999';
65
+ button.style.width = '100%';
66
+ button.style.textAlign = 'left';
67
+ document.body.appendChild(button);
68
+ (_document$getElements = document.getElementsByClassName('luma-compiler-log-error')[0]) === null || _document$getElements === void 0 ? void 0 : _document$getElements.scrollIntoView();
69
+ button.onclick = () => {
70
+ const dataURI = `data:text/plain,${encodeURIComponent(this.source)}`;
71
+ navigator.clipboard.writeText(dataURI);
72
+ };
73
+ }
15
74
  }
16
75
  Shader.defaultProps = {
17
76
  ...Resource.defaultProps,
77
+ language: 'auto',
18
78
  stage: 'vertex',
19
79
  source: '',
20
80
  sourceMap: null,
21
- language: 'auto',
22
- shaderType: 0
81
+ entryPoint: 'main',
82
+ debug: 'errors'
23
83
  };
84
+ function getShaderIdFromProps(props) {
85
+ return getShaderInfo(props.source).name || props.id || uid(`unnamed ${props.stage}-shader`);
86
+ }
24
87
  //# sourceMappingURL=shader.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"shader.js","names":["Resource","_Symbol$toStringTag","Symbol","toStringTag","Shader","constructor","device","props","defaultProps","stage","source","sourceMap","language","shaderType"],"sources":["../../../src/adapter/resources/shader.ts"],"sourcesContent":["// luma.gl, MIT license\nimport type {Device} from '../device';\nimport {Resource, ResourceProps} from './resource';\nimport {CompilerMessage} from '../../lib/compiler-log/compiler-message';\n\n/**\n * Properties for a Shader\n */\nexport type ShaderProps = ResourceProps & {\n stage: 'vertex' | 'fragment' | 'compute'; // Required by WebGL and GLSL transpiler\n // code: string;\n source: string;\n sourceMap?: string | null; // WebGPU only\n language?: 'glsl' | 'wgsl' | 'auto'; // wgsl in WebGPU only\n // entryPoint?: string;\n\n // WEBGL\n /** @deprecated use props.stage */\n shaderType?: 0x8b30 | 0x8b31 | 0; // GL_FRAGMENT_SHADER | GL_VERTEX_SHADER\n};\n\n/**\n * Immutable Shader object\n * In WebGPU the handle can be copied between threads\n */\nexport abstract class Shader extends Resource<ShaderProps> {\n static override defaultProps: Required<ShaderProps> = {\n ...Resource.defaultProps,\n stage: 'vertex',\n source: '',\n sourceMap: null,\n language: 'auto',\n shaderType: 0\n };\n\n override get [Symbol.toStringTag](): string { return 'Shader'; }\n\n readonly stage: 'vertex' | 'fragment' | 'compute';\n readonly source: string;\n\n constructor(device: Device, props: ShaderProps) {\n super(device, props, Shader.defaultProps);\n this.stage = this.props.stage;\n this.source = this.props.source;\n }\n\n abstract compilationInfo(): Promise<readonly CompilerMessage[]>;\n}\n"],"mappings":";SAEQA,QAAQ;AAAAC,mBAAA,GAiCAC,MAAM,CAACC,WAAW;AAVlC,OAAO,MAAeC,MAAM,SAASJ,QAAQ,CAAc;EAUzD,KAAAC,mBAAA,IAA4C;IAAE,OAAO,QAAQ;EAAE;EAK/DI,WAAWA,CAACC,MAAc,EAAEC,KAAkB,EAAE;IAC9C,KAAK,CAACD,MAAM,EAAEC,KAAK,EAAEH,MAAM,CAACI,YAAY,CAAC;IAAC,KAJnCC,KAAK;IAAA,KACLC,MAAM;IAIb,IAAI,CAACD,KAAK,GAAG,IAAI,CAACF,KAAK,CAACE,KAAK;IAC7B,IAAI,CAACC,MAAM,GAAG,IAAI,CAACH,KAAK,CAACG,MAAM;EACjC;AAGF;AAtBsBN,MAAM,CACVI,YAAY,GAA0B;EACpD,GAAGR,QAAQ,CAACQ,YAAY;EACxBC,KAAK,EAAE,QAAQ;EACfC,MAAM,EAAE,EAAE;EACVC,SAAS,EAAE,IAAI;EACfC,QAAQ,EAAE,MAAM;EAChBC,UAAU,EAAE;AACd,CAAC"}
1
+ {"version":3,"file":"shader.js","names":["Resource","uid","formatCompilerLog","getShaderInfo","_Symbol$toStringTag","Symbol","toStringTag","Shader","constructor","device","props","id","getShaderIdFromProps","defaultProps","stage","source","compilationStatus","getCompilationInfoSync","debugShader","debug","messages","getCompilationInfo","length","_displayShaderLog","_document","_document$getElements","document","createElement","shaderName","name","shaderTitle","htmlLog","showSourceCode","html","button","innerHTML","style","top","left","position","zIndex","width","textAlign","body","appendChild","getElementsByClassName","scrollIntoView","onclick","dataURI","encodeURIComponent","navigator","clipboard","writeText","language","sourceMap","entryPoint"],"sources":["../../../src/adapter/resources/shader.ts"],"sourcesContent":["// luma.gl, MIT license\nimport type {Device} from '../device';\nimport {Resource, ResourceProps} from './resource';\n// import { log } from '../../lib/utils/log';\nimport {uid} from '../../lib/utils/utils';\nimport {CompilerMessage} from '../../lib/compiler-log/compiler-message';\nimport {formatCompilerLog} from '../../lib/compiler-log/format-compiler-log';\nimport {getShaderInfo} from '../../lib/compiler-log/get-shader-info';\n\n/**\n * Properties for a Shader\n */\nexport type ShaderProps = ResourceProps & {\n /** Shader language (defaults to auto) */ \n language?: 'glsl' | 'wgsl' | 'auto';\n /** Which stage are we compiling? Required by WebGL and GLSL transpiler */\n stage: 'vertex' | 'fragment' | 'compute';\n /** Shader source code */\n source: string;\n /** Optional shader source map (WebGPU only) */\n sourceMap?: string | null;\n /** Optional shader entry point (WebGPU only) */\n entryPoint?: string;\n /** Show shader source in browser? */\n debug?: 'never' | 'errors' | 'warnings' | 'always';\n};\n\n/**\n * Immutable Shader object\n * In WebGPU the handle can be copied between threads\n */\nexport abstract class Shader extends Resource<ShaderProps> {\n static override defaultProps: Required<ShaderProps> = {\n ...Resource.defaultProps,\n language: 'auto',\n stage: 'vertex',\n source: '',\n sourceMap: null,\n entryPoint: 'main',\n debug: 'errors'\n };\n\n override get [Symbol.toStringTag](): string { return 'Shader'; }\n\n /** The stage of this shader */\n readonly stage: 'vertex' | 'fragment' | 'compute';\n /** The source code of this shader */\n readonly source: string;\n /** The compilation status of this shader. May be 'pending' if compilation is done asynchronously */\n compilationStatus: 'success' | 'error' | 'pending' = 'pending';\n\n /** Create a new Shader instance */\n constructor(device: Device, props: ShaderProps) {\n super(device, {id: getShaderIdFromProps(props), ...props}, Shader.defaultProps);\n this.stage = this.props.stage;\n this.source = this.props.source;\n }\n\n /** Get compiler log asynchronously */\n abstract getCompilationInfo(): Promise<readonly CompilerMessage[]>;\n\n /** Get compiler log synchronously (WebGL only) */\n getCompilationInfoSync(): (readonly CompilerMessage[]) | null {\n return null;\n }\n\n // PORTABLE HELPERS\n\n /** In browser logging of errors */\n async debugShader(): Promise<void> {\n switch (this.props.debug) {\n case 'never':\n return;\n case 'errors':\n // On WebGL - Don't extract the log unless errors\n if (this.compilationStatus === 'success') {\n return;\n }\n break;\n case 'warnings':\n case 'always':\n break;\n }\n\n const messages = await this.getCompilationInfo();\n if (this.props.debug === 'warnings' && messages?.length === 0) {\n return;\n }\n this._displayShaderLog(messages);\n }\n\n // PRIVATE\n\n /** In-browser UI logging of errors */\n protected _displayShaderLog(messages: readonly CompilerMessage[]): void {\n // Return if under Node.js / incomplete `document` polyfills\n if (typeof document === 'undefined' || !document?.createElement) {\n return;\n }\n\n const shaderName: string = getShaderInfo(this.source).name;\n const shaderTitle: string = `${this.stage} ${shaderName}`;\n const htmlLog = formatCompilerLog(messages, this.source, {showSourceCode: 'all', html: true});\n\n // Make it clickable so we can copy to clipboard \n const button = document.createElement('Button');\n button.innerHTML = `\n<h1>Shader Compilation Error in ${shaderTitle}</h1><br /><br />\n<code style=\"user-select:text;\"><pre>\n${htmlLog}\n</pre></code>`;\n button.style.top = '10px';\n button.style.left = '10px';\n button.style.position = 'absolute';\n button.style.zIndex = '9999';\n button.style.width = '100%';\n button.style.textAlign = 'left';\n document.body.appendChild(button);\n\n document.getElementsByClassName('luma-compiler-log-error')[0]?.scrollIntoView();\n\n // TODO - add a small embedded copy button (instead of main button)\n button.onclick = () => {\n // const source = this.source.replaceAll('\\n', '<br />');\n const dataURI = `data:text/plain,${encodeURIComponent(this.source)}`;\n navigator.clipboard.writeText(dataURI);\n };\n\n // TODO - add a small embedded close button\n }\n}\n\n// HELPERS\n\n/** Deduce an id, from shader source, or supplied id, or shader type */\nfunction getShaderIdFromProps(props: ShaderProps): string {\n return getShaderInfo(props.source).name || props.id || uid(`unnamed ${props.stage}-shader`);\n}\n"],"mappings":"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"}
package/dist/dist.dev.js CHANGED
@@ -1455,26 +1455,172 @@ var __exports__ = (() => {
1455
1455
  colorSpace: "srgb"
1456
1456
  });
1457
1457
 
1458
+ // src/lib/compiler-log/format-compiler-log.ts
1459
+ function formatCompilerLog(shaderLog, source, options) {
1460
+ let formattedLog = "";
1461
+ const lines = source.split(/\r?\n/);
1462
+ const log2 = shaderLog.slice().sort((a, b) => a.lineNum - b.lineNum);
1463
+ switch (options?.showSourceCode || "no") {
1464
+ case "all":
1465
+ let currentMessage = 0;
1466
+ for (let lineNum = 1; lineNum <= lines.length; lineNum++) {
1467
+ formattedLog += getNumberedLine(lines[lineNum - 1], lineNum, options);
1468
+ while (log2.length > currentMessage && log2[currentMessage].lineNum === lineNum) {
1469
+ const message = log2[currentMessage++];
1470
+ formattedLog += formatCompilerMessage(message, lines, message.lineNum, {
1471
+ ...options,
1472
+ inlineSource: false
1473
+ });
1474
+ }
1475
+ }
1476
+ return formattedLog;
1477
+ case "issues":
1478
+ case "no":
1479
+ for (const message of shaderLog) {
1480
+ formattedLog += formatCompilerMessage(message, lines, message.lineNum, {
1481
+ inlineSource: options?.showSourceCode !== "no"
1482
+ });
1483
+ }
1484
+ return formattedLog;
1485
+ }
1486
+ }
1487
+ function formatCompilerMessage(message, lines, lineNum, options) {
1488
+ if (options?.inlineSource) {
1489
+ const numberedLines = getNumberedLines(lines, lineNum);
1490
+ const positionIndicator = message.linePos > 0 ? `${" ".repeat(message.linePos + 5)}^^^
1491
+ ` : "";
1492
+ return `
1493
+ ${numberedLines}${positionIndicator}${message.type.toUpperCase()}: ${message.message}
1494
+
1495
+ `;
1496
+ }
1497
+ return options?.html ? `<div class='luma-compiler-log-error' style="color:red;"><b> ${message.type.toUpperCase()}: ${message.message}</b></div>` : `${message.type.toUpperCase()}: ${message.message}`;
1498
+ }
1499
+ function getNumberedLines(lines, lineNum, options) {
1500
+ let numberedLines = "";
1501
+ for (let lineIndex = lineNum - 2; lineIndex <= lineNum; lineIndex++) {
1502
+ const sourceLine = lines[lineIndex - 1];
1503
+ if (sourceLine !== void 0) {
1504
+ numberedLines += getNumberedLine(sourceLine, lineNum, options);
1505
+ }
1506
+ }
1507
+ return numberedLines;
1508
+ }
1509
+ function getNumberedLine(line, lineNum, options) {
1510
+ return `${padLeft(String(lineNum), 4)}: ${line}${options?.html ? "<br/>" : "\n"}`;
1511
+ }
1512
+ function padLeft(string, paddedLength) {
1513
+ let result = "";
1514
+ for (let i = string.length; i < paddedLength; ++i) {
1515
+ result += " ";
1516
+ }
1517
+ return result + string;
1518
+ }
1519
+
1520
+ // src/lib/compiler-log/get-shader-info.ts
1521
+ function getShaderInfo(source, defaultName) {
1522
+ return {
1523
+ name: getShaderName(source, defaultName),
1524
+ language: "glsl",
1525
+ version: getShaderVersion(source)
1526
+ };
1527
+ }
1528
+ function getShaderName(shader, defaultName = "unnamed") {
1529
+ const SHADER_NAME_REGEXP = /#define[\s*]SHADER_NAME[\s*]([A-Za-z0-9_-]+)[\s*]/;
1530
+ const match = SHADER_NAME_REGEXP.exec(shader);
1531
+ return match ? match[1] : defaultName;
1532
+ }
1533
+ function getShaderVersion(source) {
1534
+ let version = 100;
1535
+ const words = source.match(/[^\s]+/g);
1536
+ if (words && words.length >= 2 && words[0] === "#version") {
1537
+ const v = parseInt(words[1], 10);
1538
+ if (Number.isFinite(v)) {
1539
+ version = v;
1540
+ }
1541
+ }
1542
+ return version;
1543
+ }
1544
+
1458
1545
  // src/adapter/resources/shader.ts
1459
1546
  var _Shader = class extends Resource {
1460
1547
  get [Symbol.toStringTag]() {
1461
1548
  return "Shader";
1462
1549
  }
1550
+ compilationStatus = "pending";
1463
1551
  constructor(device, props) {
1464
- super(device, props, _Shader.defaultProps);
1552
+ super(device, {
1553
+ id: getShaderIdFromProps(props),
1554
+ ...props
1555
+ }, _Shader.defaultProps);
1465
1556
  this.stage = this.props.stage;
1466
1557
  this.source = this.props.source;
1467
1558
  }
1559
+ getCompilationInfoSync() {
1560
+ return null;
1561
+ }
1562
+ async debugShader() {
1563
+ switch (this.props.debug) {
1564
+ case "never":
1565
+ return;
1566
+ case "errors":
1567
+ if (this.compilationStatus === "success") {
1568
+ return;
1569
+ }
1570
+ break;
1571
+ case "warnings":
1572
+ case "always":
1573
+ break;
1574
+ }
1575
+ const messages = await this.getCompilationInfo();
1576
+ if (this.props.debug === "warnings" && messages?.length === 0) {
1577
+ return;
1578
+ }
1579
+ this._displayShaderLog(messages);
1580
+ }
1581
+ _displayShaderLog(messages) {
1582
+ if (typeof document === "undefined" || !document?.createElement) {
1583
+ return;
1584
+ }
1585
+ const shaderName = getShaderInfo(this.source).name;
1586
+ const shaderTitle = `${this.stage} ${shaderName}`;
1587
+ const htmlLog = formatCompilerLog(messages, this.source, {
1588
+ showSourceCode: "all",
1589
+ html: true
1590
+ });
1591
+ const button = document.createElement("Button");
1592
+ button.innerHTML = `
1593
+ <h1>Shader Compilation Error in ${shaderTitle}</h1><br /><br />
1594
+ <code style="user-select:text;"><pre>
1595
+ ${htmlLog}
1596
+ </pre></code>`;
1597
+ button.style.top = "10px";
1598
+ button.style.left = "10px";
1599
+ button.style.position = "absolute";
1600
+ button.style.zIndex = "9999";
1601
+ button.style.width = "100%";
1602
+ button.style.textAlign = "left";
1603
+ document.body.appendChild(button);
1604
+ document.getElementsByClassName("luma-compiler-log-error")[0]?.scrollIntoView();
1605
+ button.onclick = () => {
1606
+ const dataURI = `data:text/plain,${encodeURIComponent(this.source)}`;
1607
+ navigator.clipboard.writeText(dataURI);
1608
+ };
1609
+ }
1468
1610
  };
1469
1611
  var Shader = _Shader;
1470
1612
  __publicField(Shader, "defaultProps", {
1471
1613
  ...Resource.defaultProps,
1614
+ language: "auto",
1472
1615
  stage: "vertex",
1473
1616
  source: "",
1474
1617
  sourceMap: null,
1475
- language: "auto",
1476
- shaderType: 0
1618
+ entryPoint: "main",
1619
+ debug: "errors"
1477
1620
  });
1621
+ function getShaderIdFromProps(props) {
1622
+ return getShaderInfo(props.source).name || props.id || uid(`unnamed ${props.stage}-shader`);
1623
+ }
1478
1624
 
1479
1625
  // src/adapter/resources/sampler.ts
1480
1626
  var _Sampler = class extends Resource {
@@ -2559,46 +2705,6 @@ var __exports__ = (() => {
2559
2705
  return `${dataType}x${components}`;
2560
2706
  }
2561
2707
 
2562
- // src/lib/compiler-log/format-compiler-log.ts
2563
- function formatCompilerLog(shaderLog, source, options) {
2564
- const lines = source.split(/\r?\n/);
2565
- let formattedLog = "";
2566
- for (const message of shaderLog) {
2567
- formattedLog += formatCompilerMessage(message, lines, message.lineNum, options);
2568
- }
2569
- return formattedLog;
2570
- }
2571
- function formatCompilerMessage(message, lines, lineNum, options) {
2572
- if (options?.showSourceCode) {
2573
- const positionIndicator = message.linePos > 0 ? `${" ".repeat(message.linePos + 5)}^^^
2574
- ` : "";
2575
- const numberedLines = getNumberedLines(lines, lineNum);
2576
- return `${numberedLines}${positionIndicator}${message.type.toUpperCase()}: ${message.message}
2577
-
2578
- `;
2579
- }
2580
- return `${message.type.toUpperCase()}: ${message.message}
2581
- `;
2582
- }
2583
- function getNumberedLines(lines, lineNum) {
2584
- let numberedLines = "";
2585
- for (let line = lineNum - 2; line <= lineNum; line++) {
2586
- const sourceLine = lines[line];
2587
- if (sourceLine !== void 0) {
2588
- numberedLines += `${padLeft(String(line), 4)}: ${sourceLine}
2589
- `;
2590
- }
2591
- }
2592
- return numberedLines;
2593
- }
2594
- function padLeft(string, paddedLength) {
2595
- let result = "";
2596
- for (let i = string.length; i < paddedLength; ++i) {
2597
- result += " ";
2598
- }
2599
- return result + string;
2600
- }
2601
-
2602
2708
  // src/lib/utils/cast.ts
2603
2709
  function cast(value) {
2604
2710
  return value;
package/dist/index.cjs CHANGED
@@ -887,28 +887,178 @@ __publicField(ExternalTexture, "defaultProps", {
887
887
  colorSpace: "srgb"
888
888
  });
889
889
 
890
+ // src/lib/compiler-log/format-compiler-log.ts
891
+ function formatCompilerLog(shaderLog, source, options) {
892
+ let formattedLog = "";
893
+ const lines = source.split(/\r?\n/);
894
+ const log2 = shaderLog.slice().sort((a, b) => a.lineNum - b.lineNum);
895
+ switch ((options == null ? void 0 : options.showSourceCode) || "no") {
896
+ case "all":
897
+ let currentMessage = 0;
898
+ for (let lineNum = 1; lineNum <= lines.length; lineNum++) {
899
+ formattedLog += getNumberedLine(lines[lineNum - 1], lineNum, options);
900
+ while (log2.length > currentMessage && log2[currentMessage].lineNum === lineNum) {
901
+ const message = log2[currentMessage++];
902
+ formattedLog += formatCompilerMessage(message, lines, message.lineNum, {
903
+ ...options,
904
+ inlineSource: false
905
+ });
906
+ }
907
+ }
908
+ return formattedLog;
909
+ case "issues":
910
+ case "no":
911
+ for (const message of shaderLog) {
912
+ formattedLog += formatCompilerMessage(message, lines, message.lineNum, {
913
+ inlineSource: (options == null ? void 0 : options.showSourceCode) !== "no"
914
+ });
915
+ }
916
+ return formattedLog;
917
+ }
918
+ }
919
+ function formatCompilerMessage(message, lines, lineNum, options) {
920
+ if (options == null ? void 0 : options.inlineSource) {
921
+ const numberedLines = getNumberedLines(lines, lineNum);
922
+ const positionIndicator = message.linePos > 0 ? `${" ".repeat(message.linePos + 5)}^^^
923
+ ` : "";
924
+ return `
925
+ ${numberedLines}${positionIndicator}${message.type.toUpperCase()}: ${message.message}
926
+
927
+ `;
928
+ }
929
+ return (options == null ? void 0 : options.html) ? `<div class='luma-compiler-log-error' style="color:red;"><b> ${message.type.toUpperCase()}: ${message.message}</b></div>` : `${message.type.toUpperCase()}: ${message.message}`;
930
+ }
931
+ function getNumberedLines(lines, lineNum, options) {
932
+ let numberedLines = "";
933
+ for (let lineIndex = lineNum - 2; lineIndex <= lineNum; lineIndex++) {
934
+ const sourceLine = lines[lineIndex - 1];
935
+ if (sourceLine !== void 0) {
936
+ numberedLines += getNumberedLine(sourceLine, lineNum, options);
937
+ }
938
+ }
939
+ return numberedLines;
940
+ }
941
+ function getNumberedLine(line, lineNum, options) {
942
+ return `${padLeft(String(lineNum), 4)}: ${line}${(options == null ? void 0 : options.html) ? "<br/>" : "\n"}`;
943
+ }
944
+ function padLeft(string, paddedLength) {
945
+ let result = "";
946
+ for (let i = string.length; i < paddedLength; ++i) {
947
+ result += " ";
948
+ }
949
+ return result + string;
950
+ }
951
+
952
+ // src/lib/compiler-log/get-shader-info.ts
953
+ function getShaderInfo(source, defaultName) {
954
+ return {
955
+ name: getShaderName(source, defaultName),
956
+ language: "glsl",
957
+ version: getShaderVersion(source)
958
+ };
959
+ }
960
+ function getShaderName(shader, defaultName = "unnamed") {
961
+ const SHADER_NAME_REGEXP = /#define[\s*]SHADER_NAME[\s*]([A-Za-z0-9_-]+)[\s*]/;
962
+ const match = SHADER_NAME_REGEXP.exec(shader);
963
+ return match ? match[1] : defaultName;
964
+ }
965
+ function getShaderVersion(source) {
966
+ let version = 100;
967
+ const words = source.match(/[^\s]+/g);
968
+ if (words && words.length >= 2 && words[0] === "#version") {
969
+ const v = parseInt(words[1], 10);
970
+ if (Number.isFinite(v)) {
971
+ version = v;
972
+ }
973
+ }
974
+ return version;
975
+ }
976
+
890
977
  // src/adapter/resources/shader.ts
891
978
  var _Shader = class extends Resource {
892
979
  get [Symbol.toStringTag]() {
893
980
  return "Shader";
894
981
  }
982
+ /** The stage of this shader */
895
983
  stage;
984
+ /** The source code of this shader */
896
985
  source;
986
+ /** The compilation status of this shader. May be 'pending' if compilation is done asynchronously */
987
+ compilationStatus = "pending";
988
+ /** Create a new Shader instance */
897
989
  constructor(device, props) {
898
- super(device, props, _Shader.defaultProps);
990
+ super(device, { id: getShaderIdFromProps(props), ...props }, _Shader.defaultProps);
899
991
  this.stage = this.props.stage;
900
992
  this.source = this.props.source;
901
993
  }
994
+ /** Get compiler log synchronously (WebGL only) */
995
+ getCompilationInfoSync() {
996
+ return null;
997
+ }
998
+ // PORTABLE HELPERS
999
+ /** In browser logging of errors */
1000
+ async debugShader() {
1001
+ switch (this.props.debug) {
1002
+ case "never":
1003
+ return;
1004
+ case "errors":
1005
+ if (this.compilationStatus === "success") {
1006
+ return;
1007
+ }
1008
+ break;
1009
+ case "warnings":
1010
+ case "always":
1011
+ break;
1012
+ }
1013
+ const messages = await this.getCompilationInfo();
1014
+ if (this.props.debug === "warnings" && (messages == null ? void 0 : messages.length) === 0) {
1015
+ return;
1016
+ }
1017
+ this._displayShaderLog(messages);
1018
+ }
1019
+ // PRIVATE
1020
+ /** In-browser UI logging of errors */
1021
+ _displayShaderLog(messages) {
1022
+ var _a;
1023
+ if (typeof document === "undefined" || !(document == null ? void 0 : document.createElement)) {
1024
+ return;
1025
+ }
1026
+ const shaderName = getShaderInfo(this.source).name;
1027
+ const shaderTitle = `${this.stage} ${shaderName}`;
1028
+ const htmlLog = formatCompilerLog(messages, this.source, { showSourceCode: "all", html: true });
1029
+ const button = document.createElement("Button");
1030
+ button.innerHTML = `
1031
+ <h1>Shader Compilation Error in ${shaderTitle}</h1><br /><br />
1032
+ <code style="user-select:text;"><pre>
1033
+ ${htmlLog}
1034
+ </pre></code>`;
1035
+ button.style.top = "10px";
1036
+ button.style.left = "10px";
1037
+ button.style.position = "absolute";
1038
+ button.style.zIndex = "9999";
1039
+ button.style.width = "100%";
1040
+ button.style.textAlign = "left";
1041
+ document.body.appendChild(button);
1042
+ (_a = document.getElementsByClassName("luma-compiler-log-error")[0]) == null ? void 0 : _a.scrollIntoView();
1043
+ button.onclick = () => {
1044
+ const dataURI = `data:text/plain,${encodeURIComponent(this.source)}`;
1045
+ navigator.clipboard.writeText(dataURI);
1046
+ };
1047
+ }
902
1048
  };
903
1049
  var Shader = _Shader;
904
1050
  __publicField(Shader, "defaultProps", {
905
1051
  ...Resource.defaultProps,
1052
+ language: "auto",
906
1053
  stage: "vertex",
907
1054
  source: "",
908
1055
  sourceMap: null,
909
- language: "auto",
910
- shaderType: 0
1056
+ entryPoint: "main",
1057
+ debug: "errors"
911
1058
  });
1059
+ function getShaderIdFromProps(props) {
1060
+ return getShaderInfo(props.source).name || props.id || uid(`unnamed ${props.stage}-shader`);
1061
+ }
912
1062
 
913
1063
  // src/adapter/resources/sampler.ts
914
1064
  var _Sampler = class extends Resource {
@@ -2066,46 +2216,6 @@ function getVertexFormatFromAttribute(typedArray, size, normalized) {
2066
2216
  return `${dataType}x${components}`;
2067
2217
  }
2068
2218
 
2069
- // src/lib/compiler-log/format-compiler-log.ts
2070
- function formatCompilerLog(shaderLog, source, options) {
2071
- const lines = source.split(/\r?\n/);
2072
- let formattedLog = "";
2073
- for (const message of shaderLog) {
2074
- formattedLog += formatCompilerMessage(message, lines, message.lineNum, options);
2075
- }
2076
- return formattedLog;
2077
- }
2078
- function formatCompilerMessage(message, lines, lineNum, options) {
2079
- if (options == null ? void 0 : options.showSourceCode) {
2080
- const positionIndicator = message.linePos > 0 ? `${" ".repeat(message.linePos + 5)}^^^
2081
- ` : "";
2082
- const numberedLines = getNumberedLines(lines, lineNum);
2083
- return `${numberedLines}${positionIndicator}${message.type.toUpperCase()}: ${message.message}
2084
-
2085
- `;
2086
- }
2087
- return `${message.type.toUpperCase()}: ${message.message}
2088
- `;
2089
- }
2090
- function getNumberedLines(lines, lineNum) {
2091
- let numberedLines = "";
2092
- for (let line = lineNum - 2; line <= lineNum; line++) {
2093
- const sourceLine = lines[line];
2094
- if (sourceLine !== void 0) {
2095
- numberedLines += `${padLeft(String(line), 4)}: ${sourceLine}
2096
- `;
2097
- }
2098
- }
2099
- return numberedLines;
2100
- }
2101
- function padLeft(string, paddedLength) {
2102
- let result = "";
2103
- for (let i = string.length; i < paddedLength; ++i) {
2104
- result += " ";
2105
- }
2106
- return result + string;
2107
- }
2108
-
2109
2219
  // src/lib/utils/cast.ts
2110
2220
  function cast(value) {
2111
2221
  return value;
@@ -1,6 +1,8 @@
1
1
  import type { CompilerMessage } from './compiler-message';
2
2
  /** @returns annotated errors or warnings */
3
3
  export declare function formatCompilerLog(shaderLog: readonly CompilerMessage[], source: string, options?: {
4
- showSourceCode?: boolean;
4
+ /** Include source code in the log. Either just the lines before issues or all source code */
5
+ showSourceCode?: 'no' | 'issues' | 'all';
6
+ html?: boolean;
5
7
  }): string;
6
8
  //# sourceMappingURL=format-compiler-log.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"format-compiler-log.d.ts","sourceRoot":"","sources":["../../../src/lib/compiler-log/format-compiler-log.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,oBAAoB,CAAC;AAExD,4CAA4C;AAC5C,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,SAAS,eAAe,EAAE,EACrC,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;IACR,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,GACA,MAAM,CAQR"}
1
+ {"version":3,"file":"format-compiler-log.d.ts","sourceRoot":"","sources":["../../../src/lib/compiler-log/format-compiler-log.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,oBAAoB,CAAC;AAExD,4CAA4C;AAC5C,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,SAAS,eAAe,EAAE,EACrC,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;IACR,6FAA6F;IAC7F,cAAc,CAAC,EAAE,IAAI,GAAG,QAAQ,GAAG,KAAK,CAAC;IACzC,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,GACA,MAAM,CA+BR"}