mirror of
https://github.com/Rezmason/matrix.git
synced 2026-04-14 12:29:30 -07:00
Renamed gpu-uniforms to gpu-buffer, and messed around with its API.
I believe all the align, size, stride and byteOffset values are now in the proper units, ie. bytes.
This commit is contained in:
22
TODO.txt
22
TODO.txt
@@ -1,24 +1,18 @@
|
||||
TODO:
|
||||
|
||||
gpu-buffer, working title
|
||||
Try and use it for the palette color buffer
|
||||
Test it
|
||||
Demo it to others
|
||||
Make improvements
|
||||
Capture expected requirements down the road, make roadmap
|
||||
License it and put it somewhere else
|
||||
|
||||
WebGPU
|
||||
blur pass
|
||||
|
||||
Update links in issues
|
||||
|
||||
Try to change post processing to compute shaders once they're easier to support
|
||||
|
||||
gpu-uniforms, working title
|
||||
Is this an adequate name for it? Can't it be useful for non-uniform-related things?
|
||||
gpu-buffer maybe?
|
||||
Get all the units to be the same
|
||||
Try and use it for the palette color buffer
|
||||
Test it
|
||||
Demo it to others
|
||||
Make improvements
|
||||
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
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import uniforms from "/lib/gpu-uniforms.js";
|
||||
import { loadTexture, loadShader, makeUniformBuffer, makeBindGroup, makePassFBO, makePass } from "./utils.js";
|
||||
import { loadTexture, loadShader, makeBindGroup, makePassFBO, makePass } from "./utils.js";
|
||||
|
||||
// Multiplies the rendered rain and bloom by a loaded in image
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import uniforms from "/lib/gpu-uniforms.js";
|
||||
import { structs } from "/lib/gpu-buffer.js";
|
||||
import { getCanvasSize, makeUniformBuffer, makePipeline } from "./utils.js";
|
||||
|
||||
import makeRain from "./rainPass.js";
|
||||
@@ -38,7 +38,7 @@ export default async (canvas, config) => {
|
||||
GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_DST,
|
||||
};
|
||||
|
||||
const timeUniforms = uniforms.read(`[[block]] struct Time { seconds : f32; frames : i32; };`).Time;
|
||||
const timeUniforms = structs.from(`[[block]] struct Time { seconds : f32; frames : i32; };`).Time;
|
||||
const timeBuffer = makeUniformBuffer(device, timeUniforms);
|
||||
|
||||
const context = {
|
||||
@@ -68,7 +68,7 @@ export default async (canvas, config) => {
|
||||
pipeline.forEach((step) => step.setSize(...canvasSize));
|
||||
}
|
||||
|
||||
device.queue.writeBuffer(timeBuffer, 0, timeUniforms.write({ seconds: (now - start) / 1000, frames }));
|
||||
device.queue.writeBuffer(timeBuffer, 0, timeUniforms.toBuffer({ seconds: (now - start) / 1000, frames }));
|
||||
frames++;
|
||||
|
||||
const encoder = device.createCommandEncoder();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import uniforms from "/lib/gpu-uniforms.js";
|
||||
import { structs } from "/lib/gpu-buffer.js";
|
||||
import { loadShader, makeUniformBuffer, makeBindGroup, makePassFBO, makePass } from "./utils.js";
|
||||
|
||||
// Maps the brightness of the rendered rain and bloom to colors
|
||||
@@ -123,7 +123,7 @@ export default (context, getInputs) => {
|
||||
},
|
||||
});
|
||||
|
||||
const paletteShaderUniforms = uniforms.read(paletteShader.code);
|
||||
const paletteShaderUniforms = structs.from(paletteShader.code);
|
||||
const configUniforms = paletteShaderUniforms.Config;
|
||||
configBuffer = makeUniformBuffer(device, configUniforms, { ditherMagnitude: 0.05, backgroundColor: config.backgroundColor });
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import uniforms from "/lib/gpu-uniforms.js";
|
||||
import { structs, byteSizeOf } from "/lib/gpu-buffer.js";
|
||||
import { makePassFBO, loadTexture, loadShader, makeUniformBuffer, makeBindGroup, makePass } from "./utils.js";
|
||||
|
||||
const { mat4, vec3 } = glMatrix;
|
||||
@@ -47,7 +47,7 @@ export default (context, getInputs) => {
|
||||
const numQuads = config.volumetric ? numCells : 1;
|
||||
|
||||
const cellsBuffer = device.createBuffer({
|
||||
size: numCells * uniforms.byteSizeOf("vec4<f32>"),
|
||||
size: numCells * byteSizeOf("vec4<f32>"),
|
||||
usage: GPUBufferUsage.STORAGE,
|
||||
});
|
||||
|
||||
@@ -91,7 +91,7 @@ export default (context, getInputs) => {
|
||||
const ready = (async () => {
|
||||
const [msdfTexture, rainShader] = await Promise.all(assets);
|
||||
|
||||
const rainShaderUniforms = uniforms.read(rainShader.code);
|
||||
const rainShaderUniforms = structs.from(rainShader.code);
|
||||
configBuffer = makeConfigBuffer(device, rainShaderUniforms.Config, config, density, gridSize);
|
||||
|
||||
sceneUniforms = rainShaderUniforms.Scene;
|
||||
@@ -147,7 +147,7 @@ export default (context, getInputs) => {
|
||||
mat4.perspectiveZO(camera, (Math.PI / 180) * 90, aspectRatio, 0.0001, 1000);
|
||||
}
|
||||
const screenSize = aspectRatio > 1 ? [1, aspectRatio] : [1 / aspectRatio, 1];
|
||||
device.queue.writeBuffer(sceneBuffer, 0, sceneUniforms.write({ screenSize, camera, transform }));
|
||||
device.queue.writeBuffer(sceneBuffer, 0, sceneUniforms.toBuffer({ screenSize, camera, transform }));
|
||||
|
||||
// Update
|
||||
output?.destroy();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import uniforms from "/lib/gpu-uniforms.js";
|
||||
import { structs } from "/lib/gpu-buffer.js";
|
||||
import { loadShader, makeUniformBuffer, makePassFBO, makePass } from "./utils.js";
|
||||
|
||||
// Matrix Resurrections isn't in theaters yet,
|
||||
@@ -56,7 +56,7 @@ export default (context, getInputs) => {
|
||||
},
|
||||
});
|
||||
|
||||
const configUniforms = uniforms.read(resurrectionShader.code).Config;
|
||||
const configUniforms = structs.from(resurrectionShader.code).Config;
|
||||
configBuffer = makeUniformBuffer(device, configUniforms, { ditherMagnitude: 0.05, backgroundColor: config.backgroundColor });
|
||||
})();
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import uniforms from "/lib/gpu-uniforms.js";
|
||||
import { structs } from "/lib/gpu-buffer.js";
|
||||
import { loadShader, make1DTexture, makeUniformBuffer, makeBindGroup, makePassFBO, makePass } from "./utils.js";
|
||||
|
||||
// Multiplies the rendered rain and bloom by a 1D gradient texture
|
||||
@@ -91,7 +91,7 @@ export default (context, getInputs) => {
|
||||
},
|
||||
});
|
||||
|
||||
const configUniforms = uniforms.read(stripeShader.code).Config;
|
||||
const configUniforms = structs.from(stripeShader.code).Config;
|
||||
configBuffer = makeUniformBuffer(device, configUniforms, { ditherMagnitude: 0.05, backgroundColor: config.backgroundColor });
|
||||
})();
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ const makeUniformBuffer = (device, uniforms, data = null) => {
|
||||
mappedAtCreation: data != null,
|
||||
});
|
||||
if (data != null) {
|
||||
uniforms.write(data, buffer.getMappedRange());
|
||||
uniforms.toBuffer(data, buffer.getMappedRange());
|
||||
buffer.unmap();
|
||||
}
|
||||
return buffer;
|
||||
|
||||
@@ -12,50 +12,49 @@
|
||||
*
|
||||
**/
|
||||
|
||||
const BYTES_PER_ELEMENT = 4;
|
||||
const zero = () => 0;
|
||||
const array = (n) => () => Array(n).fill(0);
|
||||
|
||||
const simpleTypes = {
|
||||
["i32"]: [1, 1, "i32", zero],
|
||||
["u32"]: [1, 1, "u32", zero],
|
||||
["f32"]: [1, 1, "f32", zero],
|
||||
["i32"]: [4, 4, "i32", zero],
|
||||
["u32"]: [4, 4, "u32", zero],
|
||||
["f32"]: [4, 4, "f32", zero],
|
||||
|
||||
["atomic<i32>"]: [1, 1, "i32", zero],
|
||||
["atomic<u32>"]: [1, 1, "u32", zero],
|
||||
["atomic<f32>"]: [1, 1, "f32", zero],
|
||||
["atomic<i32>"]: [4, 4, "i32", zero],
|
||||
["atomic<u32>"]: [4, 4, "u32", zero],
|
||||
["atomic<f32>"]: [4, 4, "f32", zero],
|
||||
|
||||
["vec2<i32>"]: [2, 2, "i32", array(2)],
|
||||
["vec2<u32>"]: [2, 2, "u32", array(2)],
|
||||
["vec2<f32>"]: [2, 2, "f32", array(2)],
|
||||
["vec2<i32>"]: [8, 8, "i32", array(2)],
|
||||
["vec2<u32>"]: [8, 8, "u32", array(2)],
|
||||
["vec2<f32>"]: [8, 8, "f32", array(2)],
|
||||
|
||||
["vec3<i32>"]: [4, 3, "i32", array(3)],
|
||||
["vec3<u32>"]: [4, 3, "u32", array(3)],
|
||||
["vec3<f32>"]: [4, 3, "f32", array(3)],
|
||||
["vec3<i32>"]: [16, 12, "i32", array(3)],
|
||||
["vec3<u32>"]: [16, 12, "u32", array(3)],
|
||||
["vec3<f32>"]: [16, 12, "f32", array(3)],
|
||||
|
||||
["vec4<i32>"]: [4, 4, "i32", array(4)],
|
||||
["vec4<u32>"]: [4, 4, "u32", array(4)],
|
||||
["vec4<f32>"]: [4, 4, "f32", array(4)],
|
||||
["vec4<i32>"]: [16, 16, "i32", array(4)],
|
||||
["vec4<u32>"]: [16, 16, "u32", array(4)],
|
||||
["vec4<f32>"]: [16, 16, "f32", array(4)],
|
||||
|
||||
["mat2x2<f32>"]: [2, 4, "f32", array(2 * 2)],
|
||||
["mat3x2<f32>"]: [2, 6, "f32", array(3 * 2)],
|
||||
["mat4x2<f32>"]: [2, 8, "f32", array(4 * 2)],
|
||||
["mat2x3<f32>"]: [4, 8, "f32", array(2 * 3)],
|
||||
["mat3x3<f32>"]: [4, 12, "f32", array(3 * 3)],
|
||||
["mat4x3<f32>"]: [4, 16, "f32", array(4 * 3)],
|
||||
["mat2x4<f32>"]: [4, 8, "f32", array(2 * 4)],
|
||||
["mat3x4<f32>"]: [4, 12, "f32", array(3 * 4)],
|
||||
["mat4x4<f32>"]: [4, 16, "f32", array(4 * 4)],
|
||||
["mat2x2<f32>"]: [8, 16, "f32", array(2 * 2)],
|
||||
["mat3x2<f32>"]: [8, 24, "f32", array(3 * 2)],
|
||||
["mat4x2<f32>"]: [8, 32, "f32", array(4 * 2)],
|
||||
["mat2x3<f32>"]: [16, 32, "f32", array(2 * 3)],
|
||||
["mat3x3<f32>"]: [16, 48, "f32", array(3 * 3)],
|
||||
["mat4x3<f32>"]: [16, 64, "f32", array(4 * 3)],
|
||||
["mat2x4<f32>"]: [16, 32, "f32", array(2 * 4)],
|
||||
["mat3x4<f32>"]: [16, 48, "f32", array(3 * 4)],
|
||||
["mat4x4<f32>"]: [16, 64, "f32", array(4 * 4)],
|
||||
};
|
||||
|
||||
const getTypeData = (type, attributes, otherStructLayouts) => {
|
||||
if (simpleTypes[type] != null) {
|
||||
let [align, size, baseType, defaultValue] = simpleTypes[type];
|
||||
if (attributes.align != null) {
|
||||
align = parseInt(attributes.align) / 4;
|
||||
align = parseInt(attributes.align);
|
||||
}
|
||||
if (attributes.size != null) {
|
||||
size = parseInt(attributes.size) / 4;
|
||||
size = parseInt(attributes.size);
|
||||
}
|
||||
return {
|
||||
baseType,
|
||||
@@ -67,10 +66,10 @@ const getTypeData = (type, attributes, otherStructLayouts) => {
|
||||
const innerLayout = otherStructLayouts[type];
|
||||
let { align, size } = innerLayout;
|
||||
if (attributes.align != null) {
|
||||
align = parseInt(attributes.align) / 4;
|
||||
align = parseInt(attributes.align);
|
||||
}
|
||||
if (attributes.size != null) {
|
||||
size = parseInt(attributes.size) / 4;
|
||||
size = parseInt(attributes.size);
|
||||
}
|
||||
return {
|
||||
isStruct: true,
|
||||
@@ -153,7 +152,7 @@ const parseStruct = (str, structLayouts) => {
|
||||
byteOffset += typeData.size;
|
||||
}
|
||||
|
||||
const minSizeInBytes = byteOffset * BYTES_PER_ELEMENT;
|
||||
const minSizeInBytes = byteOffset;
|
||||
const align = Math.max(...fields.map((field) => field.align));
|
||||
const size = Math.ceil(minSizeInBytes / align) * align;
|
||||
return { name, fields, size, align };
|
||||
@@ -199,7 +198,7 @@ const writeField = (allLayouts, field, value, views, byteOffset, warnMissingFiel
|
||||
} else {
|
||||
const view = views[field.baseType];
|
||||
const array = value[Symbol.iterator] == null ? [Number(value)] : value;
|
||||
view.set(array, byteOffset + field.byteOffset);
|
||||
view.set(array, (byteOffset + field.byteOffset) / 4);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -208,7 +207,7 @@ const makeGenerator = (layout, structLayouts) => {
|
||||
return Object.freeze({
|
||||
minSize,
|
||||
create: () => makeDataForLayout(structLayouts, layout),
|
||||
write: (object, destination, warnMissingFields = false) => {
|
||||
toBuffer: (object, destination, warnMissingFields = false) => {
|
||||
if (destination == null) {
|
||||
let size = layout.size;
|
||||
const lastField = layout.fields[layout.fields.length - 1];
|
||||
@@ -233,15 +232,16 @@ const makeGenerator = (layout, structLayouts) => {
|
||||
});
|
||||
};
|
||||
|
||||
const api = Object.freeze({
|
||||
read: (wgsl) => {
|
||||
const byteSizeOf = (simpleType) => simpleTypes[simpleType]?.[1];
|
||||
|
||||
const structs = Object.freeze({
|
||||
from: (wgsl) => {
|
||||
if (typeof wgsl !== "string") {
|
||||
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)]));
|
||||
},
|
||||
byteSizeOf: (simpleType) => simpleTypes[simpleType][1] * BYTES_PER_ELEMENT,
|
||||
});
|
||||
|
||||
export default api;
|
||||
export { structs, byteSizeOf };
|
||||
Reference in New Issue
Block a user