@motion-core/motion-gpu 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/README.md +37 -11
  2. package/dist/advanced.d.ts +3 -11
  3. package/dist/advanced.js +3 -6
  4. package/dist/core/advanced.d.ts +6 -0
  5. package/dist/core/advanced.js +5 -0
  6. package/dist/core/current-value.d.ts +23 -0
  7. package/dist/core/current-value.js +36 -0
  8. package/dist/core/error-diagnostics.d.ts +15 -1
  9. package/dist/core/error-diagnostics.js +41 -1
  10. package/dist/core/error-report.d.ts +37 -0
  11. package/dist/core/error-report.js +62 -3
  12. package/dist/{frame-context.d.ts → core/frame-registry.d.ts} +3 -17
  13. package/dist/{frame-context.js → core/frame-registry.js} +2 -37
  14. package/dist/core/index.d.ts +19 -0
  15. package/dist/core/index.js +12 -0
  16. package/dist/core/material-preprocess.d.ts +1 -1
  17. package/dist/core/material-preprocess.js +1 -1
  18. package/dist/core/material.d.ts +4 -4
  19. package/dist/core/material.js +3 -3
  20. package/dist/core/recompile-policy.d.ts +1 -1
  21. package/dist/core/render-graph.d.ts +1 -1
  22. package/dist/core/render-targets.d.ts +1 -1
  23. package/dist/core/render-targets.js +1 -1
  24. package/dist/core/renderer.d.ts +11 -1
  25. package/dist/core/renderer.js +72 -10
  26. package/dist/core/runtime-loop.d.ts +34 -0
  27. package/dist/core/runtime-loop.js +365 -0
  28. package/dist/{advanced-scheduler.d.ts → core/scheduler-helpers.d.ts} +6 -2
  29. package/dist/core/shader.d.ts +2 -2
  30. package/dist/core/shader.js +1 -1
  31. package/dist/core/texture-loader.d.ts +1 -1
  32. package/dist/core/textures.d.ts +1 -1
  33. package/dist/core/textures.js +1 -1
  34. package/dist/core/types.d.ts +4 -0
  35. package/dist/core/uniforms.d.ts +1 -1
  36. package/dist/index.d.ts +3 -14
  37. package/dist/index.js +3 -8
  38. package/dist/passes/BlitPass.d.ts +6 -27
  39. package/dist/passes/BlitPass.js +10 -121
  40. package/dist/passes/CopyPass.d.ts +1 -1
  41. package/dist/passes/CopyPass.js +1 -1
  42. package/dist/passes/FullscreenPass.d.ts +37 -0
  43. package/dist/passes/FullscreenPass.js +131 -0
  44. package/dist/passes/ShaderPass.d.ts +6 -26
  45. package/dist/passes/ShaderPass.js +10 -121
  46. package/dist/passes/index.d.ts +3 -3
  47. package/dist/passes/index.js +3 -3
  48. package/dist/svelte/FragCanvas.svelte +263 -0
  49. package/dist/{FragCanvas.svelte.d.ts → svelte/FragCanvas.svelte.d.ts} +5 -3
  50. package/dist/{MotionGPUErrorOverlay.svelte → svelte/MotionGPUErrorOverlay.svelte} +11 -20
  51. package/dist/{MotionGPUErrorOverlay.svelte.d.ts → svelte/MotionGPUErrorOverlay.svelte.d.ts} +1 -1
  52. package/dist/svelte/advanced.d.ts +11 -0
  53. package/dist/svelte/advanced.js +6 -0
  54. package/dist/svelte/frame-context.d.ts +14 -0
  55. package/dist/svelte/frame-context.js +32 -0
  56. package/dist/svelte/index.d.ts +15 -0
  57. package/dist/svelte/index.js +9 -0
  58. package/dist/{motiongpu-context.d.ts → svelte/motiongpu-context.d.ts} +5 -7
  59. package/dist/{use-motiongpu-user-context.d.ts → svelte/use-motiongpu-user-context.d.ts} +2 -2
  60. package/dist/{use-motiongpu-user-context.js → svelte/use-motiongpu-user-context.js} +1 -1
  61. package/dist/{use-texture.d.ts → svelte/use-texture.d.ts} +7 -2
  62. package/dist/{use-texture.js → svelte/use-texture.js} +9 -3
  63. package/package.json +25 -5
  64. package/dist/FragCanvas.svelte +0 -511
  65. package/dist/current-writable.d.ts +0 -31
  66. package/dist/current-writable.js +0 -27
  67. /package/dist/{advanced-scheduler.js → core/scheduler-helpers.js} +0 -0
  68. /package/dist/{Portal.svelte → svelte/Portal.svelte} +0 -0
  69. /package/dist/{Portal.svelte.d.ts → svelte/Portal.svelte.d.ts} +0 -0
  70. /package/dist/{motiongpu-context.js → svelte/motiongpu-context.js} +0 -0
package/dist/index.js CHANGED
@@ -1,11 +1,6 @@
1
1
  /**
2
- * Public MotionGPU package entrypoint.
2
+ * Root package entrypoint.
3
3
  *
4
- * Exposes the production-ready core API for fullscreen WGSL rendering workflows.
4
+ * Framework-agnostic core entrypoint.
5
5
  */
6
- export { default as FragCanvas } from './FragCanvas.svelte';
7
- export { defineMaterial } from './core/material';
8
- export { BlitPass, CopyPass, ShaderPass } from './passes';
9
- export { useMotionGPU } from './motiongpu-context';
10
- export { useFrame } from './frame-context';
11
- export { useTexture } from './use-texture';
6
+ export * from './core/index.js';
@@ -1,32 +1,11 @@
1
- import type { RenderPass, RenderPassContext, RenderPassFlags, RenderPassInputSlot, RenderPassOutputSlot } from '../core/types';
2
- export interface BlitPassOptions extends RenderPassFlags {
3
- enabled?: boolean;
4
- needsSwap?: boolean;
5
- input?: RenderPassInputSlot;
6
- output?: RenderPassOutputSlot;
7
- filter?: GPUFilterMode;
8
- }
1
+ import { FullscreenPass, type FullscreenPassOptions } from './FullscreenPass.js';
2
+ export type BlitPassOptions = FullscreenPassOptions;
9
3
  /**
10
4
  * Fullscreen texture blit pass.
11
5
  */
12
- export declare class BlitPass implements RenderPass {
13
- enabled: boolean;
14
- needsSwap: boolean;
15
- input: RenderPassInputSlot;
16
- output: RenderPassOutputSlot;
17
- clear: boolean;
18
- clearColor: [number, number, number, number];
19
- preserve: boolean;
20
- private readonly filter;
21
- private device;
22
- private sampler;
23
- private bindGroupLayout;
24
- private shaderModule;
25
- private readonly pipelineByFormat;
26
- private bindGroupByView;
6
+ export declare class BlitPass extends FullscreenPass {
7
+ protected getProgram(): string;
27
8
  constructor(options?: BlitPassOptions);
28
- private ensureResources;
29
- setSize(width: number, height: number): void;
30
- render(context: RenderPassContext): void;
31
- dispose(): void;
9
+ protected getVertexEntryPoint(): string;
10
+ protected getFragmentEntryPoint(): string;
32
11
  }
@@ -1,3 +1,4 @@
1
+ import { FullscreenPass } from './FullscreenPass.js';
1
2
  const FULLSCREEN_BLIT_SHADER = `
2
3
  struct MotionGPUVertexOut {
3
4
  @builtin(position) position: vec4f,
@@ -30,129 +31,17 @@ fn motiongpuBlitFragment(in: MotionGPUVertexOut) -> @location(0) vec4f {
30
31
  /**
31
32
  * Fullscreen texture blit pass.
32
33
  */
33
- export class BlitPass {
34
- enabled;
35
- needsSwap;
36
- input;
37
- output;
38
- clear;
39
- clearColor;
40
- preserve;
41
- filter;
42
- device = null;
43
- sampler = null;
44
- bindGroupLayout = null;
45
- shaderModule = null;
46
- pipelineByFormat = new Map();
47
- bindGroupByView = new WeakMap();
48
- constructor(options = {}) {
49
- this.enabled = options.enabled ?? true;
50
- this.needsSwap = options.needsSwap ?? true;
51
- this.input = options.input ?? 'source';
52
- this.output = options.output ?? (this.needsSwap ? 'target' : 'source');
53
- this.clear = options.clear ?? false;
54
- this.clearColor = options.clearColor ?? [0, 0, 0, 1];
55
- this.preserve = options.preserve ?? true;
56
- this.filter = options.filter ?? 'linear';
57
- }
58
- ensureResources(device, format) {
59
- if (this.device !== device) {
60
- this.device = device;
61
- this.sampler = null;
62
- this.bindGroupLayout = null;
63
- this.shaderModule = null;
64
- this.pipelineByFormat.clear();
65
- this.bindGroupByView = new WeakMap();
66
- }
67
- if (!this.sampler) {
68
- this.sampler = device.createSampler({
69
- magFilter: this.filter,
70
- minFilter: this.filter,
71
- addressModeU: 'clamp-to-edge',
72
- addressModeV: 'clamp-to-edge'
73
- });
74
- }
75
- if (!this.bindGroupLayout) {
76
- this.bindGroupLayout = device.createBindGroupLayout({
77
- entries: [
78
- {
79
- binding: 0,
80
- visibility: GPUShaderStage.FRAGMENT,
81
- sampler: { type: 'filtering' }
82
- },
83
- {
84
- binding: 1,
85
- visibility: GPUShaderStage.FRAGMENT,
86
- texture: {
87
- sampleType: 'float',
88
- viewDimension: '2d',
89
- multisampled: false
90
- }
91
- }
92
- ]
93
- });
94
- }
95
- if (!this.shaderModule) {
96
- this.shaderModule = device.createShaderModule({
97
- code: FULLSCREEN_BLIT_SHADER
98
- });
99
- }
100
- let pipeline = this.pipelineByFormat.get(format);
101
- if (!pipeline) {
102
- const pipelineLayout = device.createPipelineLayout({
103
- bindGroupLayouts: [this.bindGroupLayout]
104
- });
105
- pipeline = device.createRenderPipeline({
106
- layout: pipelineLayout,
107
- vertex: {
108
- module: this.shaderModule,
109
- entryPoint: 'motiongpuBlitVertex'
110
- },
111
- fragment: {
112
- module: this.shaderModule,
113
- entryPoint: 'motiongpuBlitFragment',
114
- targets: [{ format }]
115
- },
116
- primitive: { topology: 'triangle-list' }
117
- });
118
- this.pipelineByFormat.set(format, pipeline);
119
- }
120
- return {
121
- sampler: this.sampler,
122
- bindGroupLayout: this.bindGroupLayout,
123
- pipeline
124
- };
34
+ export class BlitPass extends FullscreenPass {
35
+ getProgram() {
36
+ return FULLSCREEN_BLIT_SHADER;
125
37
  }
126
- setSize(width, height) {
127
- void width;
128
- void height;
38
+ constructor(options = {}) {
39
+ super(options);
129
40
  }
130
- render(context) {
131
- const { sampler, bindGroupLayout, pipeline } = this.ensureResources(context.device, context.output.format);
132
- const inputView = context.input.view;
133
- let bindGroup = this.bindGroupByView.get(inputView);
134
- if (!bindGroup) {
135
- bindGroup = context.device.createBindGroup({
136
- layout: bindGroupLayout,
137
- entries: [
138
- { binding: 0, resource: sampler },
139
- { binding: 1, resource: inputView }
140
- ]
141
- });
142
- this.bindGroupByView.set(inputView, bindGroup);
143
- }
144
- const pass = context.beginRenderPass();
145
- pass.setPipeline(pipeline);
146
- pass.setBindGroup(0, bindGroup);
147
- pass.draw(3);
148
- pass.end();
41
+ getVertexEntryPoint() {
42
+ return 'motiongpuBlitVertex';
149
43
  }
150
- dispose() {
151
- this.device = null;
152
- this.sampler = null;
153
- this.bindGroupLayout = null;
154
- this.shaderModule = null;
155
- this.pipelineByFormat.clear();
156
- this.bindGroupByView = new WeakMap();
44
+ getFragmentEntryPoint() {
45
+ return 'motiongpuBlitFragment';
157
46
  }
158
47
  }
@@ -1,4 +1,4 @@
1
- import type { RenderPass, RenderPassContext, RenderPassFlags, RenderPassInputSlot, RenderPassOutputSlot } from '../core/types';
1
+ import type { RenderPass, RenderPassContext, RenderPassFlags, RenderPassInputSlot, RenderPassOutputSlot } from '../core/types.js';
2
2
  export interface CopyPassOptions extends RenderPassFlags {
3
3
  enabled?: boolean;
4
4
  needsSwap?: boolean;
@@ -1,4 +1,4 @@
1
- import { BlitPass } from './BlitPass';
1
+ import { BlitPass } from './BlitPass.js';
2
2
  /**
3
3
  * Texture copy pass with fullscreen-blit fallback.
4
4
  */
@@ -0,0 +1,37 @@
1
+ import type { RenderPass, RenderPassContext, RenderPassFlags, RenderPassInputSlot, RenderPassOutputSlot } from '../core/types.js';
2
+ export interface FullscreenPassOptions extends RenderPassFlags {
3
+ enabled?: boolean;
4
+ needsSwap?: boolean;
5
+ input?: RenderPassInputSlot;
6
+ output?: RenderPassOutputSlot;
7
+ filter?: GPUFilterMode;
8
+ }
9
+ /**
10
+ * Shared base for fullscreen texture sampling passes.
11
+ */
12
+ export declare abstract class FullscreenPass implements RenderPass {
13
+ enabled: boolean;
14
+ needsSwap: boolean;
15
+ input: RenderPassInputSlot;
16
+ output: RenderPassOutputSlot;
17
+ clear: boolean;
18
+ clearColor: [number, number, number, number];
19
+ preserve: boolean;
20
+ private readonly filter;
21
+ private device;
22
+ private sampler;
23
+ private bindGroupLayout;
24
+ private shaderModule;
25
+ private readonly pipelineByFormat;
26
+ private bindGroupByView;
27
+ protected constructor(options?: FullscreenPassOptions);
28
+ protected abstract getProgram(): string;
29
+ protected abstract getVertexEntryPoint(): string;
30
+ protected abstract getFragmentEntryPoint(): string;
31
+ protected invalidateFullscreenCache(): void;
32
+ private ensureResources;
33
+ setSize(width: number, height: number): void;
34
+ protected renderFullscreen(context: RenderPassContext): void;
35
+ render(context: RenderPassContext): void;
36
+ dispose(): void;
37
+ }
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Shared base for fullscreen texture sampling passes.
3
+ */
4
+ export class FullscreenPass {
5
+ enabled;
6
+ needsSwap;
7
+ input;
8
+ output;
9
+ clear;
10
+ clearColor;
11
+ preserve;
12
+ filter;
13
+ device = null;
14
+ sampler = null;
15
+ bindGroupLayout = null;
16
+ shaderModule = null;
17
+ pipelineByFormat = new Map();
18
+ bindGroupByView = new WeakMap();
19
+ constructor(options = {}) {
20
+ this.enabled = options.enabled ?? true;
21
+ this.needsSwap = options.needsSwap ?? true;
22
+ this.input = options.input ?? 'source';
23
+ this.output = options.output ?? (this.needsSwap ? 'target' : 'source');
24
+ this.clear = options.clear ?? false;
25
+ this.clearColor = options.clearColor ?? [0, 0, 0, 1];
26
+ this.preserve = options.preserve ?? true;
27
+ this.filter = options.filter ?? 'linear';
28
+ }
29
+ invalidateFullscreenCache() {
30
+ this.shaderModule = null;
31
+ this.pipelineByFormat.clear();
32
+ this.bindGroupByView = new WeakMap();
33
+ }
34
+ ensureResources(device, format) {
35
+ if (this.device !== device) {
36
+ this.device = device;
37
+ this.sampler = null;
38
+ this.bindGroupLayout = null;
39
+ this.invalidateFullscreenCache();
40
+ }
41
+ if (!this.sampler) {
42
+ this.sampler = device.createSampler({
43
+ magFilter: this.filter,
44
+ minFilter: this.filter,
45
+ addressModeU: 'clamp-to-edge',
46
+ addressModeV: 'clamp-to-edge'
47
+ });
48
+ }
49
+ if (!this.bindGroupLayout) {
50
+ this.bindGroupLayout = device.createBindGroupLayout({
51
+ entries: [
52
+ {
53
+ binding: 0,
54
+ visibility: GPUShaderStage.FRAGMENT,
55
+ sampler: { type: 'filtering' }
56
+ },
57
+ {
58
+ binding: 1,
59
+ visibility: GPUShaderStage.FRAGMENT,
60
+ texture: {
61
+ sampleType: 'float',
62
+ viewDimension: '2d',
63
+ multisampled: false
64
+ }
65
+ }
66
+ ]
67
+ });
68
+ }
69
+ if (!this.shaderModule) {
70
+ this.shaderModule = device.createShaderModule({ code: this.getProgram() });
71
+ }
72
+ let pipeline = this.pipelineByFormat.get(format);
73
+ if (!pipeline) {
74
+ const pipelineLayout = device.createPipelineLayout({
75
+ bindGroupLayouts: [this.bindGroupLayout]
76
+ });
77
+ pipeline = device.createRenderPipeline({
78
+ layout: pipelineLayout,
79
+ vertex: {
80
+ module: this.shaderModule,
81
+ entryPoint: this.getVertexEntryPoint()
82
+ },
83
+ fragment: {
84
+ module: this.shaderModule,
85
+ entryPoint: this.getFragmentEntryPoint(),
86
+ targets: [{ format }]
87
+ },
88
+ primitive: { topology: 'triangle-list' }
89
+ });
90
+ this.pipelineByFormat.set(format, pipeline);
91
+ }
92
+ return {
93
+ sampler: this.sampler,
94
+ bindGroupLayout: this.bindGroupLayout,
95
+ pipeline
96
+ };
97
+ }
98
+ setSize(width, height) {
99
+ void width;
100
+ void height;
101
+ }
102
+ renderFullscreen(context) {
103
+ const { sampler, bindGroupLayout, pipeline } = this.ensureResources(context.device, context.output.format);
104
+ const inputView = context.input.view;
105
+ let bindGroup = this.bindGroupByView.get(inputView);
106
+ if (!bindGroup) {
107
+ bindGroup = context.device.createBindGroup({
108
+ layout: bindGroupLayout,
109
+ entries: [
110
+ { binding: 0, resource: sampler },
111
+ { binding: 1, resource: inputView }
112
+ ]
113
+ });
114
+ this.bindGroupByView.set(inputView, bindGroup);
115
+ }
116
+ const pass = context.beginRenderPass();
117
+ pass.setPipeline(pipeline);
118
+ pass.setBindGroup(0, bindGroup);
119
+ pass.draw(3);
120
+ pass.end();
121
+ }
122
+ render(context) {
123
+ this.renderFullscreen(context);
124
+ }
125
+ dispose() {
126
+ this.device = null;
127
+ this.sampler = null;
128
+ this.bindGroupLayout = null;
129
+ this.invalidateFullscreenCache();
130
+ }
131
+ }
@@ -1,40 +1,20 @@
1
- import type { RenderPass, RenderPassContext, RenderPassFlags, RenderPassInputSlot, RenderPassOutputSlot } from '../core/types';
2
- export interface ShaderPassOptions extends RenderPassFlags {
1
+ import { FullscreenPass, type FullscreenPassOptions } from './FullscreenPass.js';
2
+ export interface ShaderPassOptions extends FullscreenPassOptions {
3
3
  fragment: string;
4
- enabled?: boolean;
5
- needsSwap?: boolean;
6
- input?: RenderPassInputSlot;
7
- output?: RenderPassOutputSlot;
8
- filter?: GPUFilterMode;
9
4
  }
10
5
  /**
11
6
  * Fullscreen programmable shader pass.
12
7
  */
13
- export declare class ShaderPass implements RenderPass {
14
- enabled: boolean;
15
- needsSwap: boolean;
16
- input: RenderPassInputSlot;
17
- output: RenderPassOutputSlot;
18
- clear: boolean;
19
- clearColor: [number, number, number, number];
20
- preserve: boolean;
21
- private readonly filter;
8
+ export declare class ShaderPass extends FullscreenPass {
22
9
  private fragment;
23
10
  private program;
24
- private device;
25
- private sampler;
26
- private bindGroupLayout;
27
- private shaderModule;
28
- private readonly pipelineByFormat;
29
- private bindGroupByView;
30
11
  constructor(options: ShaderPassOptions);
31
12
  /**
32
13
  * Replaces current shader fragment and invalidates pipeline cache.
33
14
  */
34
15
  setFragment(fragment: string): void;
35
16
  getFragment(): string;
36
- private ensureResources;
37
- setSize(width: number, height: number): void;
38
- render(context: RenderPassContext): void;
39
- dispose(): void;
17
+ protected getProgram(): string;
18
+ protected getVertexEntryPoint(): string;
19
+ protected getFragmentEntryPoint(): string;
40
20
  }
@@ -1,3 +1,4 @@
1
+ import { FullscreenPass } from './FullscreenPass.js';
1
2
  const SHADER_PASS_CONTRACT = /\bfn\s+shade\s*\(\s*inputColor\s*:\s*vec4f\s*,\s*uv\s*:\s*vec2f\s*\)\s*->\s*vec4f/;
2
3
  function buildShaderPassProgram(fragment) {
3
4
  if (!SHADER_PASS_CONTRACT.test(fragment)) {
@@ -39,32 +40,11 @@ fn motiongpuShaderPassFragment(in: MotionGPUVertexOut) -> @location(0) vec4f {
39
40
  /**
40
41
  * Fullscreen programmable shader pass.
41
42
  */
42
- export class ShaderPass {
43
- enabled;
44
- needsSwap;
45
- input;
46
- output;
47
- clear;
48
- clearColor;
49
- preserve;
50
- filter;
43
+ export class ShaderPass extends FullscreenPass {
51
44
  fragment;
52
45
  program;
53
- device = null;
54
- sampler = null;
55
- bindGroupLayout = null;
56
- shaderModule = null;
57
- pipelineByFormat = new Map();
58
- bindGroupByView = new WeakMap();
59
46
  constructor(options) {
60
- this.enabled = options.enabled ?? true;
61
- this.needsSwap = options.needsSwap ?? true;
62
- this.input = options.input ?? 'source';
63
- this.output = options.output ?? (this.needsSwap ? 'target' : 'source');
64
- this.clear = options.clear ?? false;
65
- this.clearColor = options.clearColor ?? [0, 0, 0, 1];
66
- this.preserve = options.preserve ?? true;
67
- this.filter = options.filter ?? 'linear';
47
+ super(options);
68
48
  this.fragment = options.fragment;
69
49
  this.program = buildShaderPassProgram(options.fragment);
70
50
  }
@@ -74,109 +54,18 @@ export class ShaderPass {
74
54
  setFragment(fragment) {
75
55
  this.fragment = fragment;
76
56
  this.program = buildShaderPassProgram(fragment);
77
- this.shaderModule = null;
78
- this.pipelineByFormat.clear();
79
- this.bindGroupByView = new WeakMap();
57
+ this.invalidateFullscreenCache();
80
58
  }
81
59
  getFragment() {
82
60
  return this.fragment;
83
61
  }
84
- ensureResources(device, format) {
85
- if (this.device !== device) {
86
- this.device = device;
87
- this.sampler = null;
88
- this.bindGroupLayout = null;
89
- this.shaderModule = null;
90
- this.pipelineByFormat.clear();
91
- this.bindGroupByView = new WeakMap();
92
- }
93
- if (!this.sampler) {
94
- this.sampler = device.createSampler({
95
- magFilter: this.filter,
96
- minFilter: this.filter,
97
- addressModeU: 'clamp-to-edge',
98
- addressModeV: 'clamp-to-edge'
99
- });
100
- }
101
- if (!this.bindGroupLayout) {
102
- this.bindGroupLayout = device.createBindGroupLayout({
103
- entries: [
104
- {
105
- binding: 0,
106
- visibility: GPUShaderStage.FRAGMENT,
107
- sampler: { type: 'filtering' }
108
- },
109
- {
110
- binding: 1,
111
- visibility: GPUShaderStage.FRAGMENT,
112
- texture: {
113
- sampleType: 'float',
114
- viewDimension: '2d',
115
- multisampled: false
116
- }
117
- }
118
- ]
119
- });
120
- }
121
- if (!this.shaderModule) {
122
- this.shaderModule = device.createShaderModule({ code: this.program });
123
- }
124
- let pipeline = this.pipelineByFormat.get(format);
125
- if (!pipeline) {
126
- const pipelineLayout = device.createPipelineLayout({
127
- bindGroupLayouts: [this.bindGroupLayout]
128
- });
129
- pipeline = device.createRenderPipeline({
130
- layout: pipelineLayout,
131
- vertex: {
132
- module: this.shaderModule,
133
- entryPoint: 'motiongpuShaderPassVertex'
134
- },
135
- fragment: {
136
- module: this.shaderModule,
137
- entryPoint: 'motiongpuShaderPassFragment',
138
- targets: [{ format }]
139
- },
140
- primitive: { topology: 'triangle-list' }
141
- });
142
- this.pipelineByFormat.set(format, pipeline);
143
- }
144
- return {
145
- sampler: this.sampler,
146
- bindGroupLayout: this.bindGroupLayout,
147
- pipeline
148
- };
62
+ getProgram() {
63
+ return this.program;
149
64
  }
150
- setSize(width, height) {
151
- void width;
152
- void height;
65
+ getVertexEntryPoint() {
66
+ return 'motiongpuShaderPassVertex';
153
67
  }
154
- render(context) {
155
- const { sampler, bindGroupLayout, pipeline } = this.ensureResources(context.device, context.output.format);
156
- const inputView = context.input.view;
157
- let bindGroup = this.bindGroupByView.get(inputView);
158
- if (!bindGroup) {
159
- bindGroup = context.device.createBindGroup({
160
- layout: bindGroupLayout,
161
- entries: [
162
- { binding: 0, resource: sampler },
163
- { binding: 1, resource: inputView }
164
- ]
165
- });
166
- this.bindGroupByView.set(inputView, bindGroup);
167
- }
168
- const pass = context.beginRenderPass();
169
- pass.setPipeline(pipeline);
170
- pass.setBindGroup(0, bindGroup);
171
- pass.draw(3);
172
- pass.end();
173
- }
174
- dispose() {
175
- this.device = null;
176
- this.sampler = null;
177
- this.bindGroupLayout = null;
178
- this.shaderModule = null;
179
- this.pipelineByFormat.clear();
180
- this.bindGroupByView = new WeakMap();
68
+ getFragmentEntryPoint() {
69
+ return 'motiongpuShaderPassFragment';
181
70
  }
182
71
  }
@@ -1,3 +1,3 @@
1
- export { BlitPass, type BlitPassOptions } from './BlitPass';
2
- export { CopyPass, type CopyPassOptions } from './CopyPass';
3
- export { ShaderPass, type ShaderPassOptions } from './ShaderPass';
1
+ export { BlitPass, type BlitPassOptions } from './BlitPass.js';
2
+ export { CopyPass, type CopyPassOptions } from './CopyPass.js';
3
+ export { ShaderPass, type ShaderPassOptions } from './ShaderPass.js';
@@ -1,3 +1,3 @@
1
- export { BlitPass } from './BlitPass';
2
- export { CopyPass } from './CopyPass';
3
- export { ShaderPass } from './ShaderPass';
1
+ export { BlitPass } from './BlitPass.js';
2
+ export { CopyPass } from './CopyPass.js';
3
+ export { ShaderPass } from './ShaderPass.js';