forked from shader-slang/slang-playground
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcompute.js
112 lines (93 loc) · 3.19 KB
/
compute.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
class ComputePipeline
{
pipeline;
pipelineLayout;
// TODO: We should make this field optional, and only when user select a "Debug" mode will this option be available,
// and we will output this buffer to the output area.
outputBuffer;
outputBufferRead;
outputTexture;
device;
bindGroup;
// thread group size (array of 3 integers)
threadGroupSize;
// resource name (string) -> binding descriptor
resourceBindings;
constructor(device)
{
this.device = device;
}
setThreadGroupSize(size)
{
this.threadGroupSize = size;
}
createPipelineLayout(resourceDescriptors)
{
this.resourceBindings = resourceDescriptors;
const entries = [];
for (const [name, binding] of this.resourceBindings)
{
entries.push(binding);
}
const bindGroupLayoutDescriptor = {
label: 'compute pipeline bind group layout',
entries: entries,
};
const bindGroupLayout = device.createBindGroupLayout(bindGroupLayoutDescriptor);
const layout = device.createPipelineLayout({bindGroupLayouts: [bindGroupLayout]});
this.pipelineLayout = layout;
}
createPipeline(shaderModule, resources)
{
const pipeline = device.createComputePipeline({
label: 'compute pipeline',
layout: this.pipelineLayout,
compute: {module: shaderModule},
});
this.pipeline = pipeline;
// If resources are provided, create the bind group right away
if (resources)
this.createBindGroup(resources);
}
createBindGroup(allocatedResources)
{
const entries = [];
for (const [name, resource] of allocatedResources)
{
const bindInfo = this.resourceBindings.get(name);
if (bindInfo)
{
if (bindInfo.buffer)
{
entries.push({binding: bindInfo.binding, resource: {buffer: resource}});
}
else if (bindInfo.storageTexture)
{
entries.push({binding: bindInfo.binding, resource: resource.createView()});
}
else if (bindInfo.texture)
{
entries.push({binding: bindInfo.binding, resource: resource.createView()});
}
}
}
// Check that all resources are bound
if (entries.length != this.resourceBindings.size)
{
// print out the names of the resources that aren't bound
for (const [name, resource] of this.resourceBindings)
{
var missingEntries = []
if (!entries.find(entry => entry.binding == resource.binding))
{
missingEntries.push(name);
}
}
throw new Error("Cannot create bind-group. The following resources are not bound: " + missingEntries.join(", "));
}
this.bindGroup = device.createBindGroup({
layout: this.pipeline.getBindGroupLayout(0),
entries: entries,
});
}
}