From 910d29e175f71ef34931bd754ab2293728073696 Mon Sep 17 00:00:00 2001 From: Rezmason Date: Thu, 11 Nov 2021 23:30:37 -0800 Subject: [PATCH] Poking gpu-buffer a bit because I'm apparently afraid of writing a blur shader which I've already written once. --- TODO.txt | 16 ++++++++-------- lib/gpu-buffer.js | 34 ++++++++++++++++------------------ 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/TODO.txt b/TODO.txt index 198b183..cd76198 100644 --- a/TODO.txt +++ b/TODO.txt @@ -5,6 +5,14 @@ WebGPU Update links in issues Get rid of end pass once it's possible to copy a bgra8unorm to a canvas texture +Support looping + +Write an explanation of the rain pass (and include images) + Compute + Volumetric quads + Fullscreen quad and spacial mapping + MSDFs + gpu-buffer, working title Try and use it for the palette color buffer Test it @@ -13,14 +21,6 @@ gpu-buffer, working title Capture expected requirements down the road, make roadmap License it and put it somewhere else -Write an explanation of the rain pass (and include images) - Compute - Volumetric quads - Fullscreen quad and spacial mapping - MSDFs - -Support looping - Resurrection Modified glyph order? New glyphs? diff --git a/lib/gpu-buffer.js b/lib/gpu-buffer.js index 657dc69..280dec1 100644 --- a/lib/gpu-buffer.js +++ b/lib/gpu-buffer.js @@ -117,14 +117,13 @@ const parseAttributes = (str) => { const attributes = {}; for (const attr of str.split(",").filter((attr) => attr.length > 0)) { const match = attr.match(/(\w+)(\((.*)\))?/); // foo(bar) - const [_, name, __, value] = match; - attributes[name] = value; + const [_, identifier, __, value] = match; + attributes[identifier] = value; } return attributes; }; -const parseStruct = (str, structLayouts) => { - const [_, block, name, body] = str; +const parseStructLayout = (identifier, body, isBlock, structLayouts) => { const fields = []; let byteOffset = 0; const lines = body @@ -132,12 +131,12 @@ const parseStruct = (str, structLayouts) => { .split(";") .filter((s) => s.length > 0); for (const line of lines) { - const fieldMatch = line.match(/(\[\[(.*?)\]\])? ?(\w+) ?: (\[\[(.*?)\]\])? ?(.*)/); // [[...]] foo : [[...]] bar; + const fieldMatch = line.match(/(\[\[(.*?)\]\])? ?(\w+) ?: ?(\[\[(.*?)\]\])? ?(.*)/); // [[...]] foo : [[...]] bar; const [_, __, leftAttributes, identifier, ___, rightAttributes, type] = fieldMatch; const typeData = getTypeData(type, parseAttributes(rightAttributes ?? ""), structLayouts); if (typeData == null) { - console.warn(`Skipping layout for struct ${name}.`); + console.warn(`gSkipping struct ${identifier}.`); return null; } @@ -155,23 +154,22 @@ const parseStruct = (str, structLayouts) => { const minSizeInBytes = byteOffset; const align = Math.max(...fields.map((field) => field.align)); const size = Math.ceil(minSizeInBytes / align) * align; - return { name, fields, size, align }; + return { identifier, isBlock, fields, size, align }; }; const parseStructLayoutsFromShader = (wgsl) => { wgsl = wgsl - .replace(/\/\*(.|\n)*?\*\//gm, "") // remove multi-line comments .replace(/\s*\/\/.*$/gm, "") // remove end-of-line comments - .replace(/\n/gm, "") // remove newlines - .replace(/:/g, ": ") // add space after colons - .replace(/\s+/g, " "); // convert all whitespace to single space character + .replace(/\/\*.*?\*\//gms, "") // remove multi-line comments + .replace(/\s+/gm, " "); // convert all contiguous whitespace to single space characters const structLayouts = {}; - const structMatches = Array.from(wgsl.matchAll(/(\[\[block\]\])? ?struct (\w+) \{(.*?)\};/g)); // [[block]] struct Foo {...} - for (const struct of structMatches) { - const layout = parseStruct(struct, structLayouts); + const structMatches = Array.from(wgsl.matchAll(/(\[\[block\]\])? ?struct (\w+) ?\{(.*?)\};/g)); // [[block]] struct Foo {...} + for (const structMatch of structMatches) { + const [_, block, identifier, body] = structMatch; + const layout = parseStructLayout(identifier, body, block != null, structLayouts); if (layout != null) { - structLayouts[layout.name] = layout; + structLayouts[layout.identifier] = layout; } } return structLayouts; @@ -211,8 +209,8 @@ const makeGenerator = (layout, structLayouts) => { if (destination == null) { let size = layout.size; const lastField = layout.fields[layout.fields.length - 1]; - if (lastField.isArray && lastField.name in object) { - size += lastField.stride * object[lastField.name].length; + if (lastField.isArray && lastField.identifier in object) { + size += lastField.stride * object[lastField.identifier].length; } destination = new ArrayBuffer(size); } @@ -240,7 +238,7 @@ const structs = Object.freeze({ throw new Error("Input is not a string."); } const structLayouts = parseStructLayoutsFromShader(wgsl); - return Object.fromEntries(Object.entries(structLayouts).map(([name, layout]) => [name, makeGenerator(layout, structLayouts)])); + return Object.fromEntries(Object.entries(structLayouts).map(([identifier, layout]) => [identifier, makeGenerator(layout, structLayouts)])); }, });