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

@@ -5,6 +5,14 @@ WebGPU
Update links in issues Update links in issues
Get rid of end pass once it's possible to copy a bgra8unorm to a canvas texture 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 gpu-buffer, working title
Try and use it for the palette color buffer Try and use it for the palette color buffer
Test it Test it
@@ -13,14 +21,6 @@ gpu-buffer, working title
Capture expected requirements down the road, make roadmap Capture expected requirements down the road, make roadmap
License it and put it somewhere else 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 Resurrection
Modified glyph order? Modified glyph order?
New glyphs? New glyphs?

View File

@@ -117,14 +117,13 @@ const parseAttributes = (str) => {
const attributes = {}; const attributes = {};
for (const attr of str.split(",").filter((attr) => attr.length > 0)) { for (const attr of str.split(",").filter((attr) => attr.length > 0)) {
const match = attr.match(/(\w+)(\((.*)\))?/); // foo(bar) const match = attr.match(/(\w+)(\((.*)\))?/); // foo(bar)
const [_, name, __, value] = match; const [_, identifier, __, value] = match;
attributes[name] = value; attributes[identifier] = value;
} }
return attributes; return attributes;
}; };
const parseStruct = (str, structLayouts) => { const parseStructLayout = (identifier, body, isBlock, structLayouts) => {
const [_, block, name, body] = str;
const fields = []; const fields = [];
let byteOffset = 0; let byteOffset = 0;
const lines = body const lines = body
@@ -132,12 +131,12 @@ const parseStruct = (str, structLayouts) => {
.split(";") .split(";")
.filter((s) => s.length > 0); .filter((s) => s.length > 0);
for (const line of lines) { 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 [_, __, leftAttributes, identifier, ___, rightAttributes, type] = fieldMatch;
const typeData = getTypeData(type, parseAttributes(rightAttributes ?? ""), structLayouts); const typeData = getTypeData(type, parseAttributes(rightAttributes ?? ""), structLayouts);
if (typeData == null) { if (typeData == null) {
console.warn(`Skipping layout for struct ${name}.`); console.warn(`gSkipping struct ${identifier}.`);
return null; return null;
} }
@@ -155,23 +154,22 @@ const parseStruct = (str, structLayouts) => {
const minSizeInBytes = byteOffset; const minSizeInBytes = byteOffset;
const align = Math.max(...fields.map((field) => field.align)); const align = Math.max(...fields.map((field) => field.align));
const size = Math.ceil(minSizeInBytes / align) * align; const size = Math.ceil(minSizeInBytes / align) * align;
return { name, fields, size, align }; return { identifier, isBlock, fields, size, align };
}; };
const parseStructLayoutsFromShader = (wgsl) => { const parseStructLayoutsFromShader = (wgsl) => {
wgsl = wgsl wgsl = wgsl
.replace(/\/\*(.|\n)*?\*\//gm, "") // remove multi-line comments
.replace(/\s*\/\/.*$/gm, "") // remove end-of-line comments .replace(/\s*\/\/.*$/gm, "") // remove end-of-line comments
.replace(/\n/gm, "") // remove newlines .replace(/\/\*.*?\*\//gms, "") // remove multi-line comments
.replace(/:/g, ": ") // add space after colons .replace(/\s+/gm, " "); // convert all contiguous whitespace to single space characters
.replace(/\s+/g, " "); // convert all whitespace to single space character
const structLayouts = {}; const structLayouts = {};
const structMatches = Array.from(wgsl.matchAll(/(\[\[block\]\])? ?struct (\w+) \{(.*?)\};/g)); // [[block]] struct Foo {...} const structMatches = Array.from(wgsl.matchAll(/(\[\[block\]\])? ?struct (\w+) ?\{(.*?)\};/g)); // [[block]] struct Foo {...}
for (const struct of structMatches) { for (const structMatch of structMatches) {
const layout = parseStruct(struct, structLayouts); const [_, block, identifier, body] = structMatch;
const layout = parseStructLayout(identifier, body, block != null, structLayouts);
if (layout != null) { if (layout != null) {
structLayouts[layout.name] = layout; structLayouts[layout.identifier] = layout;
} }
} }
return structLayouts; return structLayouts;
@@ -211,8 +209,8 @@ const makeGenerator = (layout, structLayouts) => {
if (destination == null) { if (destination == null) {
let size = layout.size; let size = layout.size;
const lastField = layout.fields[layout.fields.length - 1]; const lastField = layout.fields[layout.fields.length - 1];
if (lastField.isArray && lastField.name in object) { if (lastField.isArray && lastField.identifier in object) {
size += lastField.stride * object[lastField.name].length; size += lastField.stride * object[lastField.identifier].length;
} }
destination = new ArrayBuffer(size); destination = new ArrayBuffer(size);
} }
@@ -240,7 +238,7 @@ const structs = Object.freeze({
throw new Error("Input is not a string."); throw new Error("Input is not a string.");
} }
const structLayouts = parseStructLayoutsFromShader(wgsl); 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)]));
}, },
}); });