From bd3d0c76d2f3b31c951ff2a407bcf25b3baaea89 Mon Sep 17 00:00:00 2001 From: Rezmason Date: Sun, 7 Nov 2021 00:40:50 -0700 Subject: [PATCH] Fixing the names of shaders in the passes. The loadShader utility function now returns the code and the module, since I'm hoping to parse uniform buffer layouts from the code. --- TODO.txt | 9 ++++++--- js/webgpu/imagePass.js | 10 +++++----- js/webgpu/palettePass.js | 10 +++++----- js/webgpu/rainPass.js | 10 +++++----- js/webgpu/resurrectionPass.js | 10 +++++----- js/webgpu/stripePass.js | 10 +++++----- js/webgpu/utils.js | 9 ++++++--- webgpu_notes.txt | 3 ++- 8 files changed, 39 insertions(+), 32 deletions(-) diff --git a/TODO.txt b/TODO.txt index ce244c2..600441d 100644 --- a/TODO.txt +++ b/TODO.txt @@ -3,13 +3,16 @@ TODO: WebGPU blur pass + Cleanup + Maybe buffer layouts and buffers can be consolidated somehow + Update links in issues Try to change post processing to compute shaders once they're easier to support - std140 - Expand it to add array support - Contemplate adding struct support + buffer-stuffer (was "std140") + Resolve the memory positions of the fields in the parse layouts + Resolve each layout into a Proxy around an ArrayBuffer Document and share it diff --git a/js/webgpu/imagePass.js b/js/webgpu/imagePass.js index a507a68..64c0484 100644 --- a/js/webgpu/imagePass.js +++ b/js/webgpu/imagePass.js @@ -1,5 +1,5 @@ import std140 from "./std140.js"; -import { loadTexture, loadShaderModule, makeUniformBuffer, makePassFBO, makePass } from "./utils.js"; +import { loadTexture, loadShader, makeUniformBuffer, makePassFBO, makePass } from "./utils.js"; // Multiplies the rendered rain and bloom by a loaded in image @@ -35,20 +35,20 @@ export default (context, getInputs) => { let backgroundTex; const bgURL = "bgURL" in config ? config.bgURL : defaultBGURL; - const assets = [loadTexture(device, bgURL), loadShaderModule(device, "shaders/wgsl/imagePass.wgsl")]; + const assets = [loadTexture(device, bgURL), loadShader(device, "shaders/wgsl/imagePass.wgsl")]; const ready = (async () => { - const [bgTex, rainShader] = await Promise.all(assets); + const [bgTex, imageShader] = await Promise.all(assets); backgroundTex = bgTex; renderPipeline = device.createRenderPipeline({ vertex: { - module: rainShader, + module: imageShader.module, entryPoint: "vertMain", }, fragment: { - module: rainShader, + module: imageShader.module, entryPoint: "fragMain", targets: [ { diff --git a/js/webgpu/palettePass.js b/js/webgpu/palettePass.js index b39a539..64f67f0 100644 --- a/js/webgpu/palettePass.js +++ b/js/webgpu/palettePass.js @@ -1,5 +1,5 @@ import std140 from "./std140.js"; -import { loadShaderModule, makeUniformBuffer, makePassFBO, makePass } from "./utils.js"; +import { loadShader, makeUniformBuffer, makePassFBO, makePass } from "./utils.js"; // Maps the brightness of the rendered rain and bloom to colors // in a linear gradient buffer generated from the passed-in color sequence @@ -106,18 +106,18 @@ export default (context, getInputs) => { let renderPipeline; let output; - const assets = [loadShaderModule(device, "shaders/wgsl/palettePass.wgsl")]; + const assets = [loadShader(device, "shaders/wgsl/palettePass.wgsl")]; const ready = (async () => { - const [rainShader] = await Promise.all(assets); + const [paletteShader] = await Promise.all(assets); renderPipeline = device.createRenderPipeline({ vertex: { - module: rainShader, + module: paletteShader.module, entryPoint: "vertMain", }, fragment: { - module: rainShader, + module: paletteShader.module, entryPoint: "fragMain", targets: [ { diff --git a/js/webgpu/rainPass.js b/js/webgpu/rainPass.js index 9dd720d..ac325d6 100644 --- a/js/webgpu/rainPass.js +++ b/js/webgpu/rainPass.js @@ -1,5 +1,5 @@ import std140 from "./std140.js"; -import { makePassFBO, loadTexture, loadShaderModule, makeUniformBuffer, makePass } from "./utils.js"; +import { makePassFBO, loadTexture, loadShader, makeUniformBuffer, makePass } from "./utils.js"; const { mat4, vec3 } = glMatrix; @@ -72,7 +72,7 @@ const makeConfigBuffer = (device, config, density, gridSize) => { export default (context, getInputs) => { const { config, adapter, device, canvasContext, timeBuffer } = context; - const assets = [loadTexture(device, config.glyphTexURL), loadShaderModule(device, "shaders/wgsl/rainPass.wgsl")]; + const assets = [loadTexture(device, config.glyphTexURL), loadShader(device, "shaders/wgsl/rainPass.wgsl")]; // The volumetric mode multiplies the number of columns // to reach the desired density, and then overlaps them @@ -126,7 +126,7 @@ export default (context, getInputs) => { computePipeline = device.createComputePipeline({ compute: { - module: rainShader, + module: rainShader.module, entryPoint: "computeMain", }, }); @@ -139,11 +139,11 @@ export default (context, getInputs) => { renderPipeline = device.createRenderPipeline({ vertex: { - module: rainShader, + module: rainShader.module, entryPoint: "vertMain", }, fragment: { - module: rainShader, + module: rainShader.module, entryPoint: "fragMain", targets: [ { diff --git a/js/webgpu/resurrectionPass.js b/js/webgpu/resurrectionPass.js index 2e7dfec..a5a6136 100644 --- a/js/webgpu/resurrectionPass.js +++ b/js/webgpu/resurrectionPass.js @@ -1,5 +1,5 @@ import std140 from "./std140.js"; -import { loadShaderModule, makeUniformBuffer, makePassFBO, makePass } from "./utils.js"; +import { loadShader, makeUniformBuffer, makePassFBO, makePass } from "./utils.js"; // Matrix Resurrections isn't in theaters yet, // and this version of the effect is still a WIP. @@ -38,18 +38,18 @@ export default (context, getInputs) => { let renderPipeline; let output; - const assets = [loadShaderModule(device, "shaders/wgsl/resurrectionPass.wgsl")]; + const assets = [loadShader(device, "shaders/wgsl/resurrectionPass.wgsl")]; const ready = (async () => { - const [rainShader] = await Promise.all(assets); + const [resurrectionShader] = await Promise.all(assets); renderPipeline = device.createRenderPipeline({ vertex: { - module: rainShader, + module: resurrectionShader.module, entryPoint: "vertMain", }, fragment: { - module: rainShader, + module: resurrectionShader.module, entryPoint: "fragMain", targets: [ { diff --git a/js/webgpu/stripePass.js b/js/webgpu/stripePass.js index bb7c23d..5bfabbe 100644 --- a/js/webgpu/stripePass.js +++ b/js/webgpu/stripePass.js @@ -1,5 +1,5 @@ import std140 from "./std140.js"; -import { loadShaderModule, make1DTexture, makeUniformBuffer, makePassFBO, makePass } from "./utils.js"; +import { loadShader, make1DTexture, makeUniformBuffer, makePassFBO, makePass } from "./utils.js"; // Multiplies the rendered rain and bloom by a 1D gradient texture // generated from the passed-in color sequence @@ -73,18 +73,18 @@ export default (context, getInputs) => { let renderPipeline; let output; - const assets = [loadShaderModule(device, "shaders/wgsl/stripePass.wgsl")]; + const assets = [loadShader(device, "shaders/wgsl/stripePass.wgsl")]; const ready = (async () => { - const [rainShader] = await Promise.all(assets); + const [stripeShader] = await Promise.all(assets); renderPipeline = device.createRenderPipeline({ vertex: { - module: rainShader, + module: stripeShader.module, entryPoint: "vertMain", }, fragment: { - module: rainShader, + module: stripeShader.module, entryPoint: "fragMain", targets: [ { diff --git a/js/webgpu/utils.js b/js/webgpu/utils.js index 9c3d8be..54dd281 100644 --- a/js/webgpu/utils.js +++ b/js/webgpu/utils.js @@ -35,10 +35,13 @@ const makePassFBO = (device, width, height, format = "rgba8unorm") => // TODO: whittle these down }); -const loadShaderModule = async (device, url) => { +const loadShader = async (device, url) => { const response = await fetch(url); const code = await response.text(); - return device.createShaderModule({ code }); + return { + code, + module: device.createShaderModule({ code }), + }; }; const makeUniformBuffer = (device, structLayout, values = null) => { @@ -77,4 +80,4 @@ const makePass = (ready, setSize, getOutputs, execute) => ({ const makePipeline = (context, steps) => steps.filter((f) => f != null).reduce((pipeline, f, i) => [...pipeline, f(context, i == 0 ? null : pipeline[i - 1].getOutputs)], []); -export { getCanvasSize, makePassFBO, make1DTexture, loadTexture, loadShaderModule, makeUniformBuffer, makePass, makePipeline }; +export { getCanvasSize, makePassFBO, make1DTexture, loadTexture, loadShader, makeUniformBuffer, makePass, makePipeline }; diff --git a/webgpu_notes.txt b/webgpu_notes.txt index 797b9fc..bcf8751 100644 --- a/webgpu_notes.txt +++ b/webgpu_notes.txt @@ -42,7 +42,8 @@ Bind groups let you bind a bunch of resources at once Render bundles let you reissue commands You can only use up to FOUR bind groups on your laptop's device! -Here's an annoying gotcha: uniform buffers are like classic UBOs, and have esoteric ("std140") layout requirements! +Here's an annoying gotcha: uniform buffers have layout requirements listed in the WGSL spec + https://gpuweb.github.io/gpuweb/wgsl/#structure-layout-rules Texture lookup in vertex shader You can only sample textures in fragment stages