UNPKG

@motion-core/motion-gpu

Version:

Framework-agnostic WebGPU runtime for fullscreen WGSL shaders with explicit Svelte, React, and Vue adapter entrypoints.

128 lines (127 loc) 3.42 kB
//#region src/lib/passes/FullscreenPass.ts /** * Shared base for fullscreen texture sampling passes. */ var FullscreenPass = class { enabled; needsSwap; input; output; clear; clearColor; preserve; filter; device = null; sampler = null; bindGroupLayout = null; shaderModule = null; pipelineByFormat = /* @__PURE__ */ new Map(); bindGroupByView = /* @__PURE__ */ new WeakMap(); constructor(options = {}) { this.enabled = options.enabled ?? true; this.needsSwap = options.needsSwap ?? true; this.input = options.input ?? "source"; this.output = options.output ?? (this.needsSwap ? "target" : "source"); this.clear = options.clear ?? false; this.clearColor = options.clearColor ?? [ 0, 0, 0, 1 ]; this.preserve = options.preserve ?? true; this.filter = options.filter ?? "linear"; } invalidateFullscreenCache() { this.shaderModule = null; this.pipelineByFormat.clear(); this.bindGroupByView = /* @__PURE__ */ new WeakMap(); } ensureResources(device, format) { if (this.device !== device) { this.device = device; this.sampler = null; this.bindGroupLayout = null; this.invalidateFullscreenCache(); } if (!this.sampler) this.sampler = device.createSampler({ magFilter: this.filter, minFilter: this.filter, addressModeU: "clamp-to-edge", addressModeV: "clamp-to-edge" }); if (!this.bindGroupLayout) this.bindGroupLayout = device.createBindGroupLayout({ entries: [{ binding: 0, visibility: GPUShaderStage.FRAGMENT, sampler: { type: "filtering" } }, { binding: 1, visibility: GPUShaderStage.FRAGMENT, texture: { sampleType: "float", viewDimension: "2d", multisampled: false } }] }); if (!this.shaderModule) this.shaderModule = device.createShaderModule({ code: this.getProgram() }); let pipeline = this.pipelineByFormat.get(format); if (!pipeline) { const pipelineLayout = device.createPipelineLayout({ bindGroupLayouts: [this.bindGroupLayout] }); pipeline = device.createRenderPipeline({ layout: pipelineLayout, vertex: { module: this.shaderModule, entryPoint: this.getVertexEntryPoint() }, fragment: { module: this.shaderModule, entryPoint: this.getFragmentEntryPoint(), targets: [{ format }] }, primitive: { topology: "triangle-list" } }); this.pipelineByFormat.set(format, pipeline); } return { sampler: this.sampler, bindGroupLayout: this.bindGroupLayout, pipeline }; } setSize(width, height) {} renderFullscreen(context) { const { sampler, bindGroupLayout, pipeline } = this.ensureResources(context.device, context.output.format); const inputView = context.input.view; let bindGroup = this.bindGroupByView.get(inputView); if (!bindGroup) { bindGroup = context.device.createBindGroup({ layout: bindGroupLayout, entries: [{ binding: 0, resource: sampler }, { binding: 1, resource: inputView }] }); this.bindGroupByView.set(inputView, bindGroup); } const pass = context.beginRenderPass(); pass.setPipeline(pipeline); pass.setBindGroup(0, bindGroup); pass.draw(3); pass.end(); } render(context) { this.renderFullscreen(context); } dispose() { this.device = null; this.sampler = null; this.bindGroupLayout = null; this.invalidateFullscreenCache(); } }; //#endregion export { FullscreenPass }; //# sourceMappingURL=FullscreenPass.js.map