@plasius/gpu-renderer 0.2.5 → 0.2.6

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.
@@ -0,0 +1,167 @@
1
+ export function createGpuParallelismCounters() {
2
+ return {
3
+ directDispatches: 0,
4
+ directWorkgroups: 0,
5
+ directShaderInvocations: 0,
6
+ multiWorkgroupDispatches: 0,
7
+ largestDirectWorkgroupsPerDispatch: 0,
8
+ indirectDispatches: 0,
9
+ estimatedIndirectWorkgroupsUpperBound: 0,
10
+ estimatedIndirectShaderInvocationsUpperBound: 0,
11
+ indirectDispatchesWithMultiWorkgroupCapacity: 0,
12
+ largestEstimatedIndirectWorkgroupsPerDispatch: 0,
13
+ }
14
+ }
15
+
16
+ function countDispatchWorkgroups(groups) {
17
+ return groups.reduce((product, value) => {
18
+ const numeric = Number(value ?? 1)
19
+ const count = Number.isFinite(numeric) ? Math.max(1, Math.trunc(numeric)) : 1
20
+ return product * count
21
+ }, 1)
22
+ }
23
+
24
+ export function recordDirectDispatch(
25
+ parallelism,
26
+ groups,
27
+ invocationsPerWorkgroup = 1
28
+ ) {
29
+ const workgroups = countDispatchWorkgroups(groups)
30
+ parallelism.directDispatches += 1
31
+ parallelism.directWorkgroups += workgroups
32
+ parallelism.directShaderInvocations += workgroups * invocationsPerWorkgroup
33
+ parallelism.largestDirectWorkgroupsPerDispatch = Math.max(
34
+ parallelism.largestDirectWorkgroupsPerDispatch,
35
+ workgroups
36
+ )
37
+ if (workgroups > 1) {
38
+ parallelism.multiWorkgroupDispatches += 1
39
+ }
40
+ }
41
+
42
+ export function recordIndirectDispatch(
43
+ parallelism,
44
+ estimatedWorkgroupsUpperBound,
45
+ invocationsPerWorkgroup = 1
46
+ ) {
47
+ const workgroups = Math.max(1, Math.trunc(Number(estimatedWorkgroupsUpperBound) || 1))
48
+ parallelism.indirectDispatches += 1
49
+ parallelism.estimatedIndirectWorkgroupsUpperBound += workgroups
50
+ parallelism.estimatedIndirectShaderInvocationsUpperBound +=
51
+ workgroups * invocationsPerWorkgroup
52
+ parallelism.largestEstimatedIndirectWorkgroupsPerDispatch = Math.max(
53
+ parallelism.largestEstimatedIndirectWorkgroupsPerDispatch,
54
+ workgroups
55
+ )
56
+ if (workgroups > 1) {
57
+ parallelism.indirectDispatchesWithMultiWorkgroupCapacity += 1
58
+ }
59
+ }
60
+
61
+ export function createGpuParallelismDiagnostics(adapterDiagnostics, counters) {
62
+ const totalEstimatedWorkgroupsUpperBound =
63
+ counters.directWorkgroups + counters.estimatedIndirectWorkgroupsUpperBound
64
+ const totalEstimatedShaderInvocationsUpperBound =
65
+ counters.directShaderInvocations +
66
+ counters.estimatedIndirectShaderInvocationsUpperBound
67
+ const exposesMultiWorkgroupParallelism =
68
+ counters.multiWorkgroupDispatches > 0 ||
69
+ counters.indirectDispatchesWithMultiWorkgroupCapacity > 0
70
+ return Object.freeze({
71
+ ...adapterDiagnostics,
72
+ directDispatches: counters.directDispatches,
73
+ directWorkgroups: counters.directWorkgroups,
74
+ directShaderInvocations: counters.directShaderInvocations,
75
+ multiWorkgroupDispatches: counters.multiWorkgroupDispatches,
76
+ largestDirectWorkgroupsPerDispatch: counters.largestDirectWorkgroupsPerDispatch,
77
+ indirectDispatches: counters.indirectDispatches,
78
+ estimatedIndirectWorkgroupsUpperBound: counters.estimatedIndirectWorkgroupsUpperBound,
79
+ estimatedIndirectShaderInvocationsUpperBound:
80
+ counters.estimatedIndirectShaderInvocationsUpperBound,
81
+ indirectDispatchesWithMultiWorkgroupCapacity:
82
+ counters.indirectDispatchesWithMultiWorkgroupCapacity,
83
+ largestEstimatedIndirectWorkgroupsPerDispatch:
84
+ counters.largestEstimatedIndirectWorkgroupsPerDispatch,
85
+ totalEstimatedWorkgroupsUpperBound,
86
+ totalEstimatedShaderInvocationsUpperBound,
87
+ exposesMultiWorkgroupParallelism,
88
+ likelyUsesMoreThanOnePhysicalGpuCore: null,
89
+ coreUtilizationStatus: "not-exposed-by-webgpu",
90
+ })
91
+ }
92
+
93
+ export function createGpuWorkerJobDiagnostics(
94
+ parallelism,
95
+ commandSubmissions,
96
+ frameTimeMs,
97
+ awaitedGpuCompletion
98
+ ) {
99
+ const directDispatchesCompleted = Math.max(0, Number(parallelism?.directDispatches ?? 0))
100
+ const indirectDispatchesCompleted = Math.max(
101
+ 0,
102
+ Number(parallelism?.indirectDispatches ?? 0)
103
+ )
104
+ const completedPerFrame = directDispatchesCompleted + indirectDispatchesCompleted
105
+ const completedPerSubmission =
106
+ commandSubmissions > 0 ? completedPerFrame / commandSubmissions : completedPerFrame
107
+ const completedPerSecond =
108
+ awaitedGpuCompletion && frameTimeMs > 0 ? (completedPerFrame * 1000) / frameTimeMs : null
109
+ return Object.freeze({
110
+ completedPerFrame,
111
+ completedPerSecond,
112
+ completedPerSubmission,
113
+ directDispatchesCompleted,
114
+ indirectDispatchesCompleted,
115
+ frameTimeMs,
116
+ awaitedGpuCompletion,
117
+ })
118
+ }
119
+
120
+ export function createGpuSubmissionBatcher({
121
+ device,
122
+ frameIndex,
123
+ maxFramePassesPerSubmission,
124
+ startingSubmissionCount = 0,
125
+ labelPrefix = "plasius.wavefront.frame",
126
+ }) {
127
+ let encodedFramePasses = 0
128
+ let submissionCount = 0
129
+ let encoder = createCommandEncoder()
130
+
131
+ function createCommandEncoder() {
132
+ return device.createCommandEncoder({
133
+ label: `${labelPrefix}.${frameIndex}.batched.${startingSubmissionCount + submissionCount + 1}`,
134
+ })
135
+ }
136
+
137
+ function submitCurrentEncoder() {
138
+ if (encodedFramePasses <= 0) {
139
+ return false
140
+ }
141
+ device.queue.submit([encoder.finish()])
142
+ submissionCount += 1
143
+ encodedFramePasses = 0
144
+ encoder = createCommandEncoder()
145
+ return true
146
+ }
147
+
148
+ return Object.freeze({
149
+ reserve(passCount = 1) {
150
+ if (
151
+ encodedFramePasses > 0 &&
152
+ encodedFramePasses + passCount > maxFramePassesPerSubmission
153
+ ) {
154
+ submitCurrentEncoder()
155
+ }
156
+ encodedFramePasses += passCount
157
+ return encoder
158
+ },
159
+ flush() {
160
+ submitCurrentEncoder()
161
+ return submissionCount
162
+ },
163
+ getSubmissionCount() {
164
+ return submissionCount
165
+ },
166
+ })
167
+ }