1
1
import tgpu from 'typegpu' ;
2
2
import * as d from 'typegpu/data' ;
3
3
4
+ const Span = d . struct ( {
5
+ x : d . u32 ,
6
+ y : d . u32 ,
7
+ } ) ;
8
+
9
+ // A description of what data our shader program
10
+ // needs from the outside.
11
+ const layout = tgpu
12
+ . bindGroupLayout ( {
13
+ span : { uniform : Span } ,
14
+ } )
15
+ . $idx ( 0 ) ;
16
+
17
+ const shaderCode = tgpu . resolve ( {
18
+ template : /* wgsl */ `
19
+ struct VertexOutput {
20
+ @builtin(position) pos: vec4f,
21
+ @location(0) uv: vec2f,
22
+ }
23
+
24
+ @vertex
25
+ fn main_vertex(
26
+ @builtin(vertex_index) vertexIndex: u32,
27
+ ) -> VertexOutput {
28
+ var pos = array<vec2f, 4>(
29
+ vec2(1, 1), // top-right
30
+ vec2(-1, 1), // top-left
31
+ vec2(1, -1), // bottom-right
32
+ vec2(-1, -1) // bottom-left
33
+ );
34
+ var out: VertexOutput;
35
+ out.pos = vec4f(pos[vertexIndex], 0.0, 1.0);
36
+ out.uv = (pos[vertexIndex] + 1) * 0.5;
37
+ return out;
38
+ }
39
+
40
+ @fragment
41
+ fn main_fragment(
42
+ @location(0) uv: vec2f,
43
+ ) -> @location(0) vec4f {
44
+ let red = floor(uv.x * f32(_EXT_.span.x)) / f32(_EXT_.span.x);
45
+ let green = floor(uv.y * f32(_EXT_.span.y)) / f32(_EXT_.span.y);
46
+ return vec4(red, green, 0.5, 1.0);
47
+ }
48
+ ` ,
49
+ externals : {
50
+ // Linking the shader template with our layout
51
+ _EXT_ : { span : layout . bound . span } ,
52
+ } ,
53
+ } ) ;
54
+
4
55
const root = await tgpu . init ( ) ;
5
56
const device = root . device ;
6
57
7
58
const canvas = document . querySelector ( 'canvas' ) as HTMLCanvasElement ;
8
59
const context = canvas . getContext ( 'webgpu' ) as GPUCanvasContext ;
9
60
const presentationFormat = navigator . gpu . getPreferredCanvasFormat ( ) ;
10
61
11
- const vertWGSL = /* wgsl */ `
12
-
13
- struct Output {
14
- @builtin(position) pos: vec4f,
15
- @location(0) uv: vec2f,
16
- }
17
-
18
- @vertex
19
- fn main(
20
- @builtin(vertex_index) vertexIndex: u32,
21
- ) -> Output {
22
- var pos = array<vec2f, 4>(
23
- vec2(1, 1), // top-right
24
- vec2(-1, 1), // top-left
25
- vec2(1, -1), // bottom-right
26
- vec2(-1, -1) // bottom-left
27
- );
28
- var uv = array<vec2f, 4>(
29
- vec2(1., 1.), // top-right
30
- vec2(0., 1.), // top-left
31
- vec2(1., 0.), // bottom-right
32
- vec2(0., 0.) // bottom-left
33
- );
34
- var out: Output;
35
- out.pos = vec4f(pos[vertexIndex], 0.0, 1.0);
36
- out.uv = uv[vertexIndex];
37
- return out;
38
- }` ;
39
-
40
- const fragWGSL = /* wgsl */ `
41
-
42
- struct Span {
43
- x: u32,
44
- y: u32,
45
- }
46
-
47
- @group(0) @binding(0) var<uniform> span: Span;
48
-
49
- @fragment
50
- fn main(
51
- @location(0) uv: vec2f,
52
- ) -> @location(0) vec4f {
53
- let red = floor(uv.x * f32(span.x)) / f32(span.x);
54
- let green = floor(uv.y * f32(span.y)) / f32(span.y);
55
- return vec4(red, green, 0.5, 1.0);
56
- }` ;
57
-
58
62
context . configure ( {
59
63
device : device ,
60
64
format : presentationFormat ,
61
65
alphaMode : 'premultiplied' ,
62
66
} ) ;
63
67
64
- const Span = d . struct ( {
65
- x : d . u32 ,
66
- y : d . u32 ,
67
- } ) ;
68
-
69
- const spanBuffer = root . createBuffer ( Span , { x : 10 , y : 10 } ) . $usage ( 'uniform' ) ;
68
+ const shaderModule = device . createShaderModule ( { code : shaderCode } ) ;
70
69
71
70
const pipeline = device . createRenderPipeline ( {
72
- layout : 'auto' ,
71
+ layout : device . createPipelineLayout ( {
72
+ bindGroupLayouts : [ root . unwrap ( layout ) ] ,
73
+ } ) ,
73
74
vertex : {
74
- module : device . createShaderModule ( {
75
- code : vertWGSL ,
76
- } ) ,
75
+ module : shaderModule ,
77
76
} ,
78
77
fragment : {
79
- module : device . createShaderModule ( {
80
- code : fragWGSL ,
81
- } ) ,
78
+ module : shaderModule ,
82
79
targets : [
83
80
{
84
81
format : presentationFormat ,
@@ -90,19 +87,13 @@ const pipeline = device.createRenderPipeline({
90
87
} ,
91
88
} ) ;
92
89
93
- const bindGroup = device . createBindGroup ( {
94
- layout : pipeline . getBindGroupLayout ( 0 ) ,
95
- entries : [
96
- {
97
- binding : 0 ,
98
- resource : {
99
- buffer : spanBuffer . buffer ,
100
- } ,
101
- } ,
102
- ] ,
90
+ const spanBuffer = root . createBuffer ( Span , { x : 10 , y : 10 } ) . $usage ( 'uniform' ) ;
91
+
92
+ const bindGroup = root . createBindGroup ( layout , {
93
+ span : spanBuffer ,
103
94
} ) ;
104
95
105
- const draw = ( spanXValue : number , spanYValue : number ) => {
96
+ function draw ( spanXValue : number , spanYValue : number ) {
106
97
const textureView = context . getCurrentTexture ( ) . createView ( ) ;
107
98
const renderPassDescriptor : GPURenderPassDescriptor = {
108
99
colorAttachments : [
@@ -120,12 +111,12 @@ const draw = (spanXValue: number, spanYValue: number) => {
120
111
const commandEncoder = device . createCommandEncoder ( ) ;
121
112
const passEncoder = commandEncoder . beginRenderPass ( renderPassDescriptor ) ;
122
113
passEncoder . setPipeline ( pipeline ) ;
123
- passEncoder . setBindGroup ( 0 , bindGroup ) ;
114
+ passEncoder . setBindGroup ( 0 , root . unwrap ( bindGroup ) ) ;
124
115
passEncoder . draw ( 4 ) ;
125
116
passEncoder . end ( ) ;
126
117
127
118
device . queue . submit ( [ commandEncoder . finish ( ) ] ) ;
128
- } ;
119
+ }
129
120
130
121
let spanX = 10 ;
131
122
let spanY = 10 ;
0 commit comments