mirror of
https://github.com/Rezmason/matrix.git
synced 2026-04-17 13:59:30 -07:00
Refactoring the pass and pipeline, so that inputs and size are handed to and returned from the build function (formerly setSize). This is now the earliest place to build bind groups, which makes sense, because it's also the earliest place to create textures that are proportional to the size of the canvas.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { structs } from "/lib/gpu-buffer.js";
|
||||
import { makeComputeTarget, makePyramidView, loadShader, makeUniformBuffer, makeBindGroup, makePass } from "./utils.js";
|
||||
|
||||
export default (context, getInputs) => {
|
||||
export default (context) => {
|
||||
const { config, device } = context;
|
||||
|
||||
const pyramidHeight = 4;
|
||||
@@ -14,8 +14,7 @@ export default (context, getInputs) => {
|
||||
// If there's no bloom to apply, return a no-op pass with an empty bloom texture
|
||||
if (!enabled) {
|
||||
const emptyTexture = makeComputeTarget(device, 1, 1);
|
||||
const getOutputs = () => ({ ...getInputs(), bloom: emptyTexture });
|
||||
return makePass(getOutputs);
|
||||
return makePass(null, (size, inputs) => ({ ...inputs, bloom: emptyTexture }));
|
||||
}
|
||||
|
||||
const assets = [loadShader(device, "shaders/wgsl/bloomBlur.wgsl"), loadShader(device, "shaders/wgsl/bloomCombine.wgsl")];
|
||||
@@ -26,21 +25,19 @@ export default (context, getInputs) => {
|
||||
});
|
||||
|
||||
let blurPipeline;
|
||||
let combinePipeline;
|
||||
let hBlurPyramid;
|
||||
let vBlurPyramid;
|
||||
let hBlurBuffer;
|
||||
let vBlurBuffer;
|
||||
let hBlurBindGroups;
|
||||
let vBlurBindGroups;
|
||||
let combinePipeline;
|
||||
let combineBuffer;
|
||||
let combineBindGroup;
|
||||
let output;
|
||||
let scaledScreenSize;
|
||||
|
||||
const getOutputs = () => ({
|
||||
primary: getInputs().primary,
|
||||
bloom: output,
|
||||
});
|
||||
|
||||
const ready = (async () => {
|
||||
const loaded = (async () => {
|
||||
const [blurShader, combineShader] = await Promise.all(assets);
|
||||
|
||||
blurPipeline = device.createComputePipeline({
|
||||
@@ -65,47 +62,58 @@ export default (context, getInputs) => {
|
||||
combineBuffer = makeUniformBuffer(device, combineUniforms, { bloomStrength, pyramidHeight });
|
||||
})();
|
||||
|
||||
const setSize = (width, height) => {
|
||||
const build = (screenSize, inputs) => {
|
||||
scaledScreenSize = screenSize.map((x) => Math.floor(x * bloomSize));
|
||||
|
||||
hBlurPyramid?.destroy();
|
||||
hBlurPyramid = makeComputeTarget(device, Math.floor(width * bloomSize), Math.floor(height * bloomSize), pyramidHeight);
|
||||
hBlurPyramid = makeComputeTarget(device, scaledScreenSize, pyramidHeight);
|
||||
|
||||
vBlurPyramid?.destroy();
|
||||
vBlurPyramid = makeComputeTarget(device, Math.floor(width * bloomSize), Math.floor(height * bloomSize), pyramidHeight);
|
||||
vBlurPyramid = makeComputeTarget(device, scaledScreenSize, pyramidHeight);
|
||||
|
||||
output?.destroy();
|
||||
output = makeComputeTarget(device, Math.floor(width * bloomSize), Math.floor(height * bloomSize));
|
||||
scaledScreenSize = [Math.floor(width * bloomSize), Math.floor(height * bloomSize)];
|
||||
output = makeComputeTarget(device, scaledScreenSize);
|
||||
|
||||
const hBlurPyramidViews = [];
|
||||
const vBlurPyramidViews = [];
|
||||
hBlurBindGroups = [];
|
||||
vBlurBindGroups = [];
|
||||
|
||||
for (let i = 0; i < pyramidHeight; i++) {
|
||||
hBlurPyramidViews[i] = makePyramidView(hBlurPyramid, i);
|
||||
vBlurPyramidViews[i] = makePyramidView(vBlurPyramid, i);
|
||||
const srcView = i === 0 ? inputs.highPass.createView() : hBlurPyramidViews[i - 1];
|
||||
hBlurBindGroups[i] = makeBindGroup(device, blurPipeline, 0, [hBlurBuffer, linearSampler, srcView, hBlurPyramidViews[i]]);
|
||||
vBlurBindGroups[i] = makeBindGroup(device, blurPipeline, 0, [vBlurBuffer, linearSampler, hBlurPyramidViews[i], vBlurPyramidViews[i]]);
|
||||
}
|
||||
|
||||
combineBindGroup = makeBindGroup(device, combinePipeline, 0, [combineBuffer, linearSampler, vBlurPyramid.createView(), output.createView()]);
|
||||
|
||||
return {
|
||||
...inputs,
|
||||
bloom: output,
|
||||
};
|
||||
};
|
||||
|
||||
const execute = (encoder) => {
|
||||
const inputs = getInputs();
|
||||
const tex = inputs.primary;
|
||||
|
||||
const run = (encoder) => {
|
||||
const computePass = encoder.beginComputePass();
|
||||
|
||||
computePass.setPipeline(blurPipeline);
|
||||
const hBlurPyramidViews = Array(pyramidHeight)
|
||||
.fill()
|
||||
.map((_, level) => makePyramidView(hBlurPyramid, level));
|
||||
const vBlurPyramidViews = Array(pyramidHeight)
|
||||
.fill()
|
||||
.map((_, level) => makePyramidView(vBlurPyramid, level));
|
||||
for (let i = 0; i < pyramidHeight; i++) {
|
||||
const downsample = 2 ** -i;
|
||||
const size = [Math.ceil(Math.floor(scaledScreenSize[0] * downsample) / 32), Math.floor(Math.floor(scaledScreenSize[1] * downsample)), 1];
|
||||
const srcView = i === 0 ? tex.createView() : hBlurPyramidViews[i - 1];
|
||||
computePass.setBindGroup(0, makeBindGroup(device, blurPipeline, 0, [hBlurBuffer, linearSampler, srcView, hBlurPyramidViews[i]]));
|
||||
computePass.dispatch(...size);
|
||||
computePass.setBindGroup(0, makeBindGroup(device, blurPipeline, 0, [vBlurBuffer, linearSampler, hBlurPyramidViews[i], vBlurPyramidViews[i]]));
|
||||
computePass.dispatch(...size);
|
||||
const dispatchSize = [Math.ceil(Math.floor(scaledScreenSize[0] * downsample) / 32), Math.floor(Math.floor(scaledScreenSize[1] * downsample)), 1];
|
||||
computePass.setBindGroup(0, hBlurBindGroups[i]);
|
||||
computePass.dispatch(...dispatchSize);
|
||||
computePass.setBindGroup(0, vBlurBindGroups[i]);
|
||||
computePass.dispatch(...dispatchSize);
|
||||
}
|
||||
|
||||
computePass.setPipeline(combinePipeline);
|
||||
computePass.setBindGroup(0, makeBindGroup(device, combinePipeline, 0, [combineBuffer, linearSampler, vBlurPyramid.createView(), output.createView()]));
|
||||
computePass.setBindGroup(0, combineBindGroup);
|
||||
computePass.dispatch(Math.ceil(scaledScreenSize[0] / 32), scaledScreenSize[1], 1);
|
||||
|
||||
computePass.endPass();
|
||||
};
|
||||
|
||||
return makePass(getOutputs, ready, setSize, execute);
|
||||
return makePass(loaded, build, run);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user