Poking gpu-buffer a bit because I'm apparently afraid of writing a blur shader which I've already written once.

This commit is contained in:
Rezmason
2021-11-11 23:30:37 -08:00
parent d05cb3928d
commit 910d29e175
2 changed files with 24 additions and 26 deletions

View File

@@ -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)]));
},
});