Add back unicode for texture diagrams (#4074)
Example:
```
0 1 2 3
╔═══╤═══╦═══╤═══╗
0 ║ a │ ║ │ ║
╟───┼───╫───┼───╢
1 ║ │ ║ │ ║
╠═══╪═══╬═══╪═══╣
2 ║ │ ║ │ ║
╟───┼───╫───┼───╢
3 ║ │ ║ │ b ║
╚═══╧═══╩═══╧═══╝
```
diff --git a/src/webgpu/shader/execution/expression/call/builtin/texture_utils.ts b/src/webgpu/shader/execution/expression/call/builtin/texture_utils.ts
index ba8a58a..b901328 100644
--- a/src/webgpu/shader/execution/expression/call/builtin/texture_utils.ts
+++ b/src/webgpu/shader/execution/expression/call/builtin/texture_utils.ts
@@ -3430,25 +3430,72 @@
// example when blockWidth = 2, blockHeight = 2
//
// 0 1 2 3
- // +===+===+===+===+
- // 0 # a | # | #
- // +---+---+---+---+
- // 1 # | # | #
- // +===+===+===+===+
- // 2 # | # | #
- // +---+---+---+---+
- // 3 # | # | b #
- // +===+===+===+===+
+ // ╔═══╤═══╦═══╤═══╗
+ // 0 ║ a │ ║ │ ║
+ // ╟───┼───╫───┼───╢
+ // 1 ║ │ ║ │ ║
+ // ╠═══╪═══╬═══╪═══╣
+ // 2 ║ │ ║ │ ║
+ // ╟───┼───╫───┼───╢
+ // 3 ║ │ ║ │ b ║
+ // ╚═══╧═══╩═══╧═══╝
+
+ /* prettier-ignore */
+ const blockParts = {
+ top: { left: '╔', fill: '═══', right: '╗', block: '╦', texel: '╤' },
+ mid: { left: '╠', fill: '═══', right: '╣', block: '╬', texel: '╪' },
+ bot: { left: '╚', fill: '═══', right: '╝', block: '╩', texel: '╧' },
+ texelMid: { left: '╟', fill: '───', right: '╢', block: '╫', texel: '┼' },
+ value: { left: '║', fill: ' ', right: '║', block: '║', texel: '│' },
+ } as const;
+ /* prettier-ignore */
+ const nonBlockParts = {
+ top: { left: '┌', fill: '───', right: '┐', block: '┬', texel: '┬' },
+ mid: { left: '├', fill: '───', right: '┤', block: '┼', texel: '┼' },
+ bot: { left: '└', fill: '───', right: '┘', block: '┴', texel: '┴' },
+ texelMid: { left: '├', fill: '───', right: '┤', block: '┼', texel: '┼' },
+ value: { left: '│', fill: ' ', right: '│', block: '│', texel: '│' },
+ } as const;
const lines: string[] = [];
const letter = (idx: number) => String.fromCodePoint(idx < 30 ? 97 + idx : idx + 9600 - 30); // 97: 'a'
let idCount = 0;
const { blockWidth, blockHeight } = kTextureFormatInfo[texture.descriptor.format];
- const [blockHChar, blockVChar] = Math.max(blockWidth, blockHeight) > 1 ? ['=', '#'] : ['-', '|'];
- const blockHCell = '+'.padStart(4, blockHChar); // generates ---+ or ===+
// range + concatenate results.
const rangeCat = <T>(num: number, fn: (i: number) => T) => range(num, fn).join('');
+ const joinFn = (arr: string[], fn: (i: number) => string) => {
+ const joins = range(arr.length - 1, fn);
+ return arr.map((s, i) => `${s}${joins[i] ?? ''}`).join('');
+ };
+ const parts = Math.max(blockWidth, blockHeight) > 1 ? blockParts : nonBlockParts;
+ /**
+ * Makes a row that's [left, fill, texel, fill, block, fill, texel, fill, right]
+ * except if `contents` is supplied then it would be
+ * [left, contents[0], texel, contents[1], block, contents[2], texel, contents[3], right]
+ */
+ const makeRow = (
+ blockPaddedWidth: number,
+ width: number,
+ {
+ left,
+ fill,
+ right,
+ block,
+ texel,
+ }: {
+ left: string;
+ fill: string;
+ right: string;
+ block: string;
+ texel: string;
+ },
+ contents?: string[]
+ ) => {
+ return `${left}${joinFn(contents ?? range(blockPaddedWidth, x => fill), x => {
+ return (x + 1) % blockWidth === 0 ? block : texel;
+ })}${right}`;
+ };
for (let mipLevel = 0; mipLevel < mipLevelCount; ++mipLevel) {
const level = levels[mipLevel];
@@ -3478,31 +3525,39 @@
continue;
}
+ const blockPaddedHeight = align(height, blockHeight);
+ const blockPaddedWidth = align(width, blockWidth);
lines.push(` ${rangeCat(width, x => ` ${x.toString().padEnd(2)}`)}`);
- lines.push(` +${rangeCat(width, () => blockHCell)}`);
- for (let y = 0; y < height; y++) {
- {
- let line = `${y.toString().padStart(2)} ${blockVChar}`;
- for (let x = 0; x < width; x++) {
- const colChar = (x + 1) % blockWidth === 0 ? blockVChar : '|';
- const texelIdx = x + y * texelsPerRow;
- const weight = layerEntries.get(texelIdx);
- if (weight !== undefined) {
- line += ` ${letter(idCount + orderedTexelIndices.length)} ${colChar}`;
- orderedTexelIndices.push(texelIdx);
- } else {
- line += ` ${colChar}`;
- }
- }
- lines.push(line);
- }
- if (y < height - 1) {
- lines.push(
- ` +${rangeCat(width, () => ((y + 1) % blockHeight === 0 ? blockHCell : '---+'))}`
- );
- }
+ lines.push(` ${makeRow(blockPaddedWidth, width, parts.top)}`);
+ for (let y = 0; y < blockPaddedHeight; y++) {
+ lines.push(
+ `${y.toString().padStart(2)} ${makeRow(
+ blockPaddedWidth,
+ width,
+ parts.value,
+ range(blockPaddedWidth, x => {
+ const texelIdx = x + y * texelsPerRow;
+ const weight = layerEntries.get(texelIdx);
+ const outside = y >= height || x >= width;
+ if (outside || weight === undefined) {
+ return outside ? '░░░' : ' ';
+ } else {
+ const id = letter(idCount + orderedTexelIndices.length);
+ orderedTexelIndices.push(texelIdx);
+ return ` ${id} `;
+ }
+ })
+ )}`
+ );
+ // It's either a block row, a texel row, or the last row.
+ const end = y < blockPaddedHeight - 1;
+ const lineParts = end
+ ? (y + 1) % blockHeight === 0
+ ? parts.mid
+ : parts.texelMid
+ : parts.bot;
+ lines.push(` ${makeRow(blockPaddedWidth, width, lineParts)}`);
}
- lines.push(` +${range(width, () => blockHCell).join('')}`);
const pad2 = (n: number) => n.toString().padStart(2);
const pad3 = (n: number) => n.toString().padStart(3);