mirror of
https://github.com/Rezmason/matrix.git
synced 2026-04-14 12:29:30 -07:00
Fixed a WebGPU sequencing issue when skipIntro=true&once=false, caused by updating the cells and intro cells in the same compute pass. The WebGPU and REGL projects are now also slightly more alike.
This commit is contained in:
25
TODO.txt
25
TODO.txt
@@ -1,5 +1,19 @@
|
|||||||
TODO:
|
TODO:
|
||||||
|
|
||||||
|
Bloom comparison: WebGPU vs REGL
|
||||||
|
Why are they different?
|
||||||
|
Create a project that tests them side-by-side
|
||||||
|
That's right, two canvases, one regl and one webgpu
|
||||||
|
program them both to do the same basic ops in a floating point texture
|
||||||
|
display that texture
|
||||||
|
Retrieve the texture from the GPU and spit it out
|
||||||
|
Possible causes of difference
|
||||||
|
Color space
|
||||||
|
Intermediate texture formats around high pass filter
|
||||||
|
Floating point math
|
||||||
|
Texture interpolation
|
||||||
|
Blur implementation
|
||||||
|
|
||||||
Audio system
|
Audio system
|
||||||
Toggle (or number representing frequency)
|
Toggle (or number representing frequency)
|
||||||
Load the sound effect
|
Load the sound effect
|
||||||
@@ -25,17 +39,6 @@ Support Resurrections SDF bevel and "lights"
|
|||||||
Anomaly mode toggles between this and anomaly streaks
|
Anomaly mode toggles between this and anomaly streaks
|
||||||
|
|
||||||
WebGPU
|
WebGPU
|
||||||
Why is it brighter than the regl version?
|
|
||||||
Create a project that tests them side-by-side
|
|
||||||
That's right, two canvases, one regl and one webgpu
|
|
||||||
program them both to do the same basic ops in a floating point texture
|
|
||||||
display that texture
|
|
||||||
Retrieve the texture from the GPU and spit it out
|
|
||||||
Possible causes of difference
|
|
||||||
Color space
|
|
||||||
Floating point math
|
|
||||||
Texture interpolation
|
|
||||||
Blur implementation
|
|
||||||
Try https://github.com/brendan-duncan/wgsl_reflect
|
Try https://github.com/brendan-duncan/wgsl_reflect
|
||||||
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
|
||||||
Switch to rgba32float somehow?
|
Switch to rgba32float somehow?
|
||||||
|
|||||||
@@ -83,8 +83,10 @@ export default ({ config, device, timeBuffer }) => {
|
|||||||
let configBuffer;
|
let configBuffer;
|
||||||
let sceneUniforms;
|
let sceneUniforms;
|
||||||
let sceneBuffer;
|
let sceneBuffer;
|
||||||
|
let introPipeline;
|
||||||
let computePipeline;
|
let computePipeline;
|
||||||
let renderPipeline;
|
let renderPipeline;
|
||||||
|
let introBindGroup;
|
||||||
let computeBindGroup;
|
let computeBindGroup;
|
||||||
let renderBindGroup;
|
let renderBindGroup;
|
||||||
let output;
|
let output;
|
||||||
@@ -115,7 +117,15 @@ export default ({ config, device, timeBuffer }) => {
|
|||||||
dstFactor: "one",
|
dstFactor: "one",
|
||||||
};
|
};
|
||||||
|
|
||||||
[computePipeline, renderPipeline] = await Promise.all([
|
[introPipeline, computePipeline, renderPipeline] = await Promise.all([
|
||||||
|
device.createComputePipelineAsync({
|
||||||
|
layout: "auto",
|
||||||
|
compute: {
|
||||||
|
module: rainShader.module,
|
||||||
|
entryPoint: "computeIntro",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
device.createComputePipelineAsync({
|
device.createComputePipelineAsync({
|
||||||
layout: "auto",
|
layout: "auto",
|
||||||
compute: {
|
compute: {
|
||||||
@@ -153,6 +163,7 @@ export default ({ config, device, timeBuffer }) => {
|
|||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
introBindGroup = makeBindGroup(device, introPipeline, 0, [configBuffer, timeBuffer, introCellsBuffer]);
|
||||||
computeBindGroup = makeBindGroup(device, computePipeline, 0, [configBuffer, timeBuffer, cellsBuffer, introCellsBuffer]);
|
computeBindGroup = makeBindGroup(device, computePipeline, 0, [configBuffer, timeBuffer, cellsBuffer, introCellsBuffer]);
|
||||||
renderBindGroup = makeBindGroup(device, renderPipeline, 0, [
|
renderBindGroup = makeBindGroup(device, renderPipeline, 0, [
|
||||||
configBuffer,
|
configBuffer,
|
||||||
@@ -198,6 +209,12 @@ export default ({ config, device, timeBuffer }) => {
|
|||||||
const run = (encoder) => {
|
const run = (encoder) => {
|
||||||
// We render the code into an Target using MSDFs: https://github.com/Chlumsky/msdfgen
|
// We render the code into an Target using MSDFs: https://github.com/Chlumsky/msdfgen
|
||||||
|
|
||||||
|
const introPass = encoder.beginComputePass();
|
||||||
|
introPass.setPipeline(introPipeline);
|
||||||
|
introPass.setBindGroup(0, introBindGroup);
|
||||||
|
introPass.dispatchWorkgroups(Math.ceil(gridSize[0] / 32), 1, 1);
|
||||||
|
introPass.end();
|
||||||
|
|
||||||
const computePass = encoder.beginComputePass();
|
const computePass = encoder.beginComputePass();
|
||||||
computePass.setPipeline(computePipeline);
|
computePass.setPipeline(computePipeline);
|
||||||
computePass.setBindGroup(0, computeBindGroup);
|
computePass.setBindGroup(0, computeBindGroup);
|
||||||
|
|||||||
@@ -84,9 +84,12 @@ struct IntroCellData {
|
|||||||
@group(0) @binding(0) var<uniform> config : Config;
|
@group(0) @binding(0) var<uniform> config : Config;
|
||||||
@group(0) @binding(1) var<uniform> time : Time;
|
@group(0) @binding(1) var<uniform> time : Time;
|
||||||
|
|
||||||
|
// Intro-specific bindings
|
||||||
|
@group(0) @binding(2) var<storage, read_write> introCells_RW : IntroCellData;
|
||||||
|
|
||||||
// Compute-specific bindings
|
// Compute-specific bindings
|
||||||
@group(0) @binding(2) var<storage, read_write> cells_RW : CellData;
|
@group(0) @binding(2) var<storage, read_write> cells_RW : CellData;
|
||||||
@group(0) @binding(3) var<storage, read_write> introCells_RW : IntroCellData;
|
@group(0) @binding(3) var<storage, read_write> introCells_RO : IntroCellData;
|
||||||
|
|
||||||
// Render-specific bindings
|
// Render-specific bindings
|
||||||
@group(0) @binding(2) var<uniform> scene : Scene;
|
@group(0) @binding(2) var<uniform> scene : Scene;
|
||||||
@@ -216,7 +219,7 @@ fn getRipple(simTime : f32, screenPos : vec2<f32>) -> f32 {
|
|||||||
|
|
||||||
// Compute shader main functions
|
// Compute shader main functions
|
||||||
|
|
||||||
fn computeIntro (simTime : f32, isFirstFrame : bool, glyphPos : vec2<f32>, screenPos : vec2<f32>, previous : vec4<f32>) -> vec4<f32> {
|
fn computeIntroProgress (simTime : f32, isFirstFrame : bool, glyphPos : vec2<f32>, screenPos : vec2<f32>, previous : vec4<f32>) -> vec4<f32> {
|
||||||
if (bool(config.skipIntro)) {
|
if (bool(config.skipIntro)) {
|
||||||
return vec4<f32>(2.0, 0.0, 0.0, 0.0);
|
return vec4<f32>(2.0, 0.0, 0.0, 0.0);
|
||||||
}
|
}
|
||||||
@@ -298,6 +301,27 @@ fn computeEffect (simTime : f32, isFirstFrame : bool, glyphPos : vec2<f32>, scre
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@compute @workgroup_size(32, 1, 1) fn computeIntro(input : ComputeInput) {
|
||||||
|
|
||||||
|
// Resolve the invocation ID to an intro cell coordinate
|
||||||
|
var column = i32(input.id.x);
|
||||||
|
|
||||||
|
if (column >= i32(config.gridSize.x)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var simTime = time.seconds * config.animationSpeed;
|
||||||
|
var isFirstFrame = time.frames == 0;
|
||||||
|
|
||||||
|
// Update the cell
|
||||||
|
var glyphPos = vec2<f32>(f32(column), 0.0);
|
||||||
|
var screenPos = glyphPos / config.gridSize;
|
||||||
|
|
||||||
|
var introCell = introCells_RW.cells[column];
|
||||||
|
introCell.progress = computeIntroProgress(simTime, isFirstFrame, glyphPos, screenPos, introCell.progress);
|
||||||
|
introCells_RW.cells[column] = introCell;
|
||||||
|
}
|
||||||
|
|
||||||
@compute @workgroup_size(32, 1, 1) fn computeMain(input : ComputeInput) {
|
@compute @workgroup_size(32, 1, 1) fn computeMain(input : ComputeInput) {
|
||||||
|
|
||||||
// Resolve the invocation ID to a cell coordinate
|
// Resolve the invocation ID to a cell coordinate
|
||||||
@@ -317,14 +341,8 @@ fn computeEffect (simTime : f32, isFirstFrame : bool, glyphPos : vec2<f32>, scre
|
|||||||
var glyphPos = vec2<f32>(f32(column), f32(row));
|
var glyphPos = vec2<f32>(f32(column), f32(row));
|
||||||
var screenPos = glyphPos / config.gridSize;
|
var screenPos = glyphPos / config.gridSize;
|
||||||
|
|
||||||
var introCell = introCells_RW.cells[column];
|
|
||||||
|
|
||||||
if (row == i32(config.gridSize.y - 1)) {
|
|
||||||
introCell.progress = computeIntro(simTime, isFirstFrame, glyphPos, screenPos, introCell.progress);
|
|
||||||
introCells_RW.cells[column] = introCell;
|
|
||||||
}
|
|
||||||
|
|
||||||
var cell = cells_RW.cells[i];
|
var cell = cells_RW.cells[i];
|
||||||
|
var introCell = introCells_RO.cells[column];
|
||||||
cell.raindrop = computeRaindrop(simTime, isFirstFrame, glyphPos, screenPos, cell.raindrop, introCell.progress);
|
cell.raindrop = computeRaindrop(simTime, isFirstFrame, glyphPos, screenPos, cell.raindrop, introCell.progress);
|
||||||
cell.symbol = computeSymbol(simTime, isFirstFrame, glyphPos, screenPos, cell.symbol, cell.raindrop);
|
cell.symbol = computeSymbol(simTime, isFirstFrame, glyphPos, screenPos, cell.symbol, cell.raindrop);
|
||||||
cell.effect = computeEffect(simTime, isFirstFrame, glyphPos, screenPos, cell.effect, cell.raindrop);
|
cell.effect = computeEffect(simTime, isFirstFrame, glyphPos, screenPos, cell.effect, cell.raindrop);
|
||||||
|
|||||||
Reference in New Issue
Block a user