Skip to content

Commit 75206f0

Browse files
authored
feat: byegl.getWgslSource() hook (#7)
1 parent 29dea6f commit 75206f0

File tree

4 files changed

+67
-8
lines changed

4 files changed

+67
-8
lines changed

apps/docs/src/content/getting-started.mdx

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const gl = canvas.getContext('webgl');
1919
Enabling byegl will intercept calls to `.getContext('webgl' | 'webgl2' | 'experimental-webgl')` on all canvases and return
2020
a virtualized WebGL context.
2121

22-
## Basic usage
22+
## Importing WebGPU resources
2323

2424
Once your WebGL app is running on byegl, you can can hook into the underlying WebGPU API directly.
2525

@@ -33,15 +33,41 @@ const wgpuVertexBuffer = device.createBuffer({
3333
// Create a two-way binding between both resources, allowing
3434
// you to populate the buffer using a WGSL compute shader, and
3535
// use it in a WebGL pipeline 🪄
36-
const vertexBuffer = byegl.importWebGPUBuffer(wgpuVertexBuffer);
36+
const vertexBuffer = byegl.importWebGPUBuffer(gl, wgpuVertexBuffer);
3737
// ^? WebGLBuffer
3838
```
3939

4040
The [Hooks: Water Surface](/byegl/examples#hooks/water-surface) example demonstrates this functionality in practice.
4141

42+
## Retrieving WebGPU resources
43+
44+
If you need to access the underlying WebGPU resources, you can use the `byegl.getWebGPUBuffer()` function.
45+
46+
```ts
47+
const wgpuVertexBuffer = byegl.getWebGPUBuffer(gl, vertexBuffer);
48+
// ^? GPUBuffer
49+
```
50+
51+
Note that byegl may need to reallocate the buffer (in case the size of the data changes), so make sure to
52+
call `.getWebGPUBuffer()` each time you need to access the buffer, don't store it off into a variable.
53+
54+
## Retriving generated WGSL code
55+
56+
If you need to access the generated WGSL code, you can use the `byegl.getWGSLSource()` function, passing
57+
the WebGL program. Note that since in WebGPU, both the vertex and fragment shaders are colocated.
58+
59+
```ts
60+
const program = gl.createProgram();
61+
62+
// ...
63+
64+
const wgsl = byegl.getWGSLSource(gl, program);
65+
// ^? string | undefined
66+
```
67+
4268
## Disabling byegl
4369

44-
If you want more granular control over when `byegl` intercepts contexts, `byegl.enable()` returns a disabling function.
70+
If you want more granular control over when `byegl` intercepts contexts, `byegl.enable()` returns a function to disable it.
4571

4672
```ts
4773
const disable = await byegl.enable();
@@ -51,3 +77,4 @@ const disable = await byegl.enable();
5177
//
5278

5379
disable(); // Bye byegl 👋
80+
```

apps/docs/src/examples/glcompat/white-triangle/index.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,30 @@ export default function whiteTriangle({ canvas }: ExampleContext) {
2626
gl.shaderSource(vertexShader, vertexShaderSource);
2727
gl.compileShader(vertexShader);
2828

29+
if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
30+
console.error('Failed to compile vertex shader');
31+
console.error(gl.getShaderInfoLog(vertexShader));
32+
}
33+
2934
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER) as WebGLShader;
3035
gl.shaderSource(fragmentShader, fragmentShaderSource);
3136
gl.compileShader(fragmentShader);
3237

38+
if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
39+
console.error('Failed to compile fragment shader');
40+
console.error(gl.getShaderInfoLog(fragmentShader));
41+
}
42+
3343
const program = gl.createProgram();
3444
gl.attachShader(program, vertexShader);
3545
gl.attachShader(program, fragmentShader);
3646
gl.linkProgram(program);
3747

48+
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
49+
console.error('Failed to link program');
50+
console.error(gl.getProgramInfoLog(program));
51+
}
52+
3853
const positionLocation = gl.getAttribLocation(program, 'a_position');
3954
const positionBuffer = gl.createBuffer();
4055
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);

packages/byegl/src/index.ts

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import tgpu from 'typegpu';
22
import { ByeGLBuffer } from './buffer.ts';
33
import { ByeGLContext } from './byegl-context.ts';
44
import { $internal } from './types.ts';
5-
import { MockWGSLGenerator } from './wgsl/mock-wgsl-generator.ts';
65
import { ShaderkitWGSLGenerator } from './wgsl/shaderkit-wgsl-generator.ts';
6+
import { ByeGLProgram } from './program.ts';
77

88
export async function enable() {
99
const originalGetContext = HTMLCanvasElement.prototype.getContext as any;
@@ -22,7 +22,6 @@ export async function enable() {
2222
contextId === 'experimental-webgl'
2323
) {
2424
const wgslGen = new ShaderkitWGSLGenerator();
25-
// const wgslGen = new MockWGSLGenerator();
2625
return new ByeGLContext(
2726
contextId === 'webgl2' ? 2 : 1,
2827
root,
@@ -43,7 +42,7 @@ export function getDevice(
4342
gl: WebGLRenderingContext | WebGL2RenderingContext,
4443
): GPUDevice {
4544
if (!(gl instanceof ByeGLContext)) {
46-
throw new Error('Cannot use ByeGL hooks on a vanilla WebGPU context');
45+
throw new Error('Cannot use byegl hooks on a vanilla WebGPU context');
4746
}
4847

4948
return gl[$internal].device;
@@ -62,6 +61,15 @@ export function importWebGPUBuffer(
6261
return glBuffer;
6362
}
6463

64+
/**
65+
* Returns the WebGPU buffer associated with the given WebGL buffer.
66+
* Since byegl might reallocate the buffer if the size of the data changes,
67+
* call this function each time you need access. Don't store it off in a variable.
68+
*
69+
* @param gl The WebGL (actually byegl) context.
70+
* @param glBuffer
71+
* @returns The WebGPU buffer associated with `glBuffer`.
72+
*/
6573
export function getWebGPUBuffer(
6674
gl: WebGLRenderingContext | WebGL2RenderingContext,
6775
glBuffer: WebGLBuffer,
@@ -72,3 +80,14 @@ export function getWebGPUBuffer(
7280

7381
return (glBuffer as ByeGLBuffer)[$internal].gpuBuffer;
7482
}
83+
84+
export function getWGSLSource(
85+
gl: WebGLRenderingContext | WebGL2RenderingContext,
86+
glProgram: WebGLProgram,
87+
): string | undefined {
88+
if (!(gl instanceof ByeGLContext)) {
89+
throw new Error('Cannot use byegl hooks on a vanilla WebGL context');
90+
}
91+
92+
return (glProgram as ByeGLProgram)[$internal].compiled?.wgsl;
93+
}

packages/byegl/src/wgsl/shaderkit-wgsl-generator.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,8 +1082,6 @@ ${[...state.varyings.values()].map((varying) => ` ${varying.id} = input.${varyi
10821082
]),
10831083
});
10841084

1085-
console.log('Generated:\n', resolvedWgsl);
1086-
10871085
return {
10881086
wgsl: resolvedWgsl,
10891087
attributes: [...state.attributes.values()],

0 commit comments

Comments
 (0)