16
16
17
17
#include " WebGPUHandles.h"
18
18
19
+ #include " WebGPUConstants.h"
20
+
19
21
#include < backend/DriverEnums.h>
20
22
21
23
#include < utils/BitmaskEnum.h>
24
+ #if FWGPU_ENABLED(FWGPU_DEBUG_DESCRIPTOR_SETS)
25
+ #include < utils/CString.h>
26
+ #include < utils/StaticString.h>
27
+ #endif
22
28
23
29
#include < webgpu/webgpu_cpp.h>
30
+ #if FWGPU_ENABLED(FWGPU_DEBUG_DESCRIPTOR_SETS)
31
+ #include < webgpu/webgpu_cpp_print.h>
32
+ #endif
24
33
25
34
#include < algorithm>
35
+ #if FWGPU_ENABLED(FWGPU_DEBUG_DESCRIPTOR_SETS)
36
+ #include < bitset>
37
+ #include < string_view>
38
+ #include < sstream>
39
+ #endif
26
40
#include < cstdint>
27
41
#include < utility>
28
42
#include < vector>
@@ -157,6 +171,196 @@ wgpu::StringView getUserTextureViewLabel(filament::backend::SamplerType target)
157
171
}
158
172
}
159
173
174
+ #if FWGPU_ENABLED(FWGPU_DEBUG_DESCRIPTOR_SETS)
175
+ std::string_view toString (filament::backend::DescriptorType type) {
176
+ using filament::backend::DescriptorType;
177
+ switch (type) {
178
+ case DescriptorType::UNIFORM_BUFFER:
179
+ return " UNIFORM_BUFFER" ;
180
+ case DescriptorType::SHADER_STORAGE_BUFFER:
181
+ return " SHADER_STORAGE_BUFFER" ;
182
+ case DescriptorType::SAMPLER:
183
+ return " SAMPLER" ;
184
+ case DescriptorType::INPUT_ATTACHMENT:
185
+ return " INPUT_ATTACHMENT" ;
186
+ case DescriptorType::SAMPLER_EXTERNAL:
187
+ return " SAMPLER_EXTERNAL" ;
188
+ }
189
+ }
190
+ #endif
191
+
192
+ #if FWGPU_ENABLED(FWGPU_DEBUG_DESCRIPTOR_SETS)
193
+ std::string_view toString (filament::backend::ShaderStageFlags flags) {
194
+ using filament::backend::ShaderStageFlags;
195
+ switch (flags) {
196
+ case ShaderStageFlags::NONE:
197
+ return " NONE" ;
198
+ case ShaderStageFlags::VERTEX:
199
+ return " VERTEX" ;
200
+ case ShaderStageFlags::FRAGMENT:
201
+ return " FRAGMENT" ;
202
+ case ShaderStageFlags::COMPUTE:
203
+ return " COMPUTE" ;
204
+ case ShaderStageFlags::ALL_SHADER_STAGE_FLAGS:
205
+ return " ALL_SHADER_STAGE_FLAGS" ;
206
+ }
207
+ if (any (flags & ShaderStageFlags::VERTEX)) {
208
+ if (any (flags & ShaderStageFlags::FRAGMENT)) {
209
+ return " VERTEX|FRAGMENT" ;
210
+ }
211
+ if (any (flags & ShaderStageFlags::COMPUTE)) {
212
+ return " VERTEX|COMPUTE" ;
213
+ }
214
+ }
215
+ if (any (flags & ShaderStageFlags::FRAGMENT)) {
216
+ if (any (flags & ShaderStageFlags::COMPUTE)) {
217
+ return " FRAGMENT|COMPUTE" ;
218
+ }
219
+ }
220
+ }
221
+ #endif
222
+
223
+ #if FWGPU_ENABLED(FWGPU_DEBUG_DESCRIPTOR_SETS)
224
+ std::string_view toString (filament::backend::DescriptorFlags flags) {
225
+ using filament::backend::DescriptorFlags;
226
+ switch (flags) {
227
+ case DescriptorFlags::NONE:
228
+ return " NONE" ;
229
+ case DescriptorFlags::DYNAMIC_OFFSET:
230
+ return " DYNAMIC_OFFSET" ;
231
+ }
232
+ }
233
+ #endif
234
+
235
+ #if FWGPU_ENABLED(FWGPU_DEBUG_DESCRIPTOR_SETS)
236
+ void printFilamentDescriptorSetLayout (filament::backend::DescriptorSetLayout const & layout) {
237
+ const char * label;
238
+ if (std::holds_alternative<utils::StaticString>(layout.label )) {
239
+ label = std::get<utils::StaticString>(layout.label ).c_str ();
240
+ } else {
241
+ assert_invariant (std::holds_alternative<utils::CString>(layout.label ));
242
+ label = std::get<utils::CString>(layout.label ).c_str ();
243
+ }
244
+ FWGPU_LOGD << " filament::backend::DescriptorSetLayout \" " << label << " \" :" << utils::io::endl;
245
+ FWGPU_LOGD << " bindings (" << layout.bindings .size () << " ):" << utils::io::endl;
246
+ for (filament::backend::DescriptorSetLayoutBinding const & binding: layout.bindings ) {
247
+ FWGPU_LOGD << " binding " << static_cast <uint32_t >(binding.binding ) << " : type "
248
+ << toString (binding.type ) << " stageFlags " << toString (binding.stageFlags )
249
+ << " flags " << toString (binding.flags ) << " count " << binding.count
250
+ << utils::io::endl;
251
+ }
252
+ }
253
+ #endif
254
+
255
+ #if FWGPU_ENABLED(FWGPU_DEBUG_DESCRIPTOR_SETS)
256
+ void printBindGroupLayout (wgpu::BindGroupLayoutDescriptor const & layout) {
257
+ FWGPU_LOGD << " wgpu::BindGroupLayoutDescriptor label \" " << layout.label
258
+ << " \" :" << utils::io::endl;
259
+ FWGPU_LOGD << " entries (" << layout.entryCount << " ):" << utils::io::endl;
260
+ for (size_t entryIndex = 0 ; entryIndex < layout.entryCount ; entryIndex++) {
261
+ wgpu::BindGroupLayoutEntry const & entry = layout.entries [entryIndex];
262
+ std::stringstream visibilityStream;
263
+ visibilityStream << entry.visibility ;
264
+ FWGPU_LOGD << " binding " << entry.binding << " " << visibilityStream.str ();
265
+ assert_invariant (
266
+ (entry.buffer .type != wgpu::BufferBindingType::BindingNotUsed ||
267
+ entry.sampler .type != wgpu::SamplerBindingType::BindingNotUsed ||
268
+ entry.texture .sampleType != wgpu::TextureSampleType::BindingNotUsed ||
269
+ entry.storageTexture .access !=
270
+ wgpu::StorageTextureAccess::BindingNotUsed) &&
271
+ " None of buffer, sampler, texture, or storageTexture bound in the bind "
272
+ " group layout entry?" );
273
+ if (entry.buffer .type != wgpu::BufferBindingType::BindingNotUsed &&
274
+ entry.buffer .type != wgpu::BufferBindingType::Undefined) {
275
+ assert_invariant (
276
+ entry.sampler .type == wgpu::SamplerBindingType::BindingNotUsed &&
277
+ entry.texture .sampleType == wgpu::TextureSampleType::BindingNotUsed &&
278
+ entry.storageTexture .access == wgpu::StorageTextureAccess::BindingNotUsed &&
279
+ " buffer binding used but also sampler and/or texture and/or storageTexture?" );
280
+ std::stringstream typeStream;
281
+ typeStream << entry.buffer .type ;
282
+ FWGPU_LOGD << " " << typeStream.str () << " hasDynamicOffset "
283
+ << bool (entry.buffer .hasDynamicOffset ) << " minBindingSize "
284
+ << entry.buffer .minBindingSize ;
285
+ }
286
+ if (entry.sampler .type != wgpu::SamplerBindingType::BindingNotUsed &&
287
+ entry.sampler .type != wgpu::SamplerBindingType::Undefined) {
288
+ assert_invariant (
289
+ entry.buffer .type == wgpu::BufferBindingType::BindingNotUsed &&
290
+ entry.texture .sampleType == wgpu::TextureSampleType::BindingNotUsed &&
291
+ entry.storageTexture .access == wgpu::StorageTextureAccess::BindingNotUsed &&
292
+ " sampler binding used but also buffer and/or texture and/or storageTexture?" );
293
+ std::stringstream typeStream;
294
+ typeStream << entry.sampler .type ;
295
+ FWGPU_LOGD << " " << typeStream.str ();
296
+ }
297
+ if (entry.texture .sampleType != wgpu::TextureSampleType::BindingNotUsed &&
298
+ entry.texture .sampleType != wgpu::TextureSampleType::Undefined) {
299
+ assert_invariant (
300
+ entry.buffer .type == wgpu::BufferBindingType::BindingNotUsed &&
301
+ entry.sampler .type == wgpu::SamplerBindingType::BindingNotUsed &&
302
+ entry.storageTexture .access == wgpu::StorageTextureAccess::BindingNotUsed &&
303
+ " texture binding used but also buffer and/or sampler and/or storageTexture?" );
304
+ std::stringstream typeStream;
305
+ typeStream << entry.texture .sampleType ;
306
+ std::stringstream viewDimensionStream;
307
+ viewDimensionStream << entry.texture .viewDimension ;
308
+ FWGPU_LOGD << " " << typeStream.str () << " " << viewDimensionStream.str ()
309
+ << " multisampled " << bool (entry.texture .multisampled );
310
+ }
311
+ if (entry.storageTexture .access != wgpu::StorageTextureAccess::BindingNotUsed &&
312
+ entry.storageTexture .access != wgpu::StorageTextureAccess::Undefined) {
313
+ assert_invariant (
314
+ entry.buffer .type == wgpu::BufferBindingType::BindingNotUsed &&
315
+ entry.sampler .type == wgpu::SamplerBindingType::BindingNotUsed &&
316
+ entry.texture .sampleType == wgpu::TextureSampleType::BindingNotUsed &&
317
+ " storageTexture binding used but also buffer and/or sampler and/or texture?" );
318
+ std::stringstream accessStream;
319
+ accessStream << entry.storageTexture .access ;
320
+ std::stringstream formatStream;
321
+ formatStream << entry.storageTexture .format ;
322
+ std::stringstream viewDimensionStream;
323
+ viewDimensionStream << entry.storageTexture .viewDimension ;
324
+ FWGPU_LOGD << " " << accessStream.str () << " " << formatStream.str () << " "
325
+ << viewDimensionStream.str ();
326
+ }
327
+ FWGPU_LOGD << utils::io::endl;
328
+ }
329
+ }
330
+ #endif
331
+
332
+ #if FWGPU_ENABLED(FWGPU_DEBUG_DESCRIPTOR_SETS)
333
+ template <size_t DESCRIPTOR_COUNT>
334
+ void printBindGroup (wgpu::BindGroupDescriptor const & bindGroup,
335
+ std::bitset<DESCRIPTOR_COUNT> entriesByBindingWithDynamicOffsets,
336
+ std::bitset<DESCRIPTOR_COUNT> entriesByBindingAdded) {
337
+ FWGPU_LOGD << " wgpu::BindGroupDescriptor label \" " << bindGroup.label << " \" :" << utils::io::endl;
338
+ FWGPU_LOGD << " entries (" << bindGroup.entryCount << " ):" << utils::io::endl;
339
+ for (size_t entryIndex = 0 ; entryIndex < bindGroup.entryCount ; entryIndex++) {
340
+ wgpu::BindGroupEntry const & entry = bindGroup.entries [entryIndex];
341
+ FWGPU_LOGD << " binding " << entry.binding ;
342
+ assert_invariant ((entry.buffer || entry.sampler || entry.textureView ) &&
343
+ " none of buffer, sampler, or textureView provided in bind group entry?" );
344
+ if (entry.buffer ) {
345
+ assert_invariant (entry.sampler == nullptr && entry.textureView == nullptr &&
346
+ " bind group entry with buffer also has sampler and/or textureView?" );
347
+ FWGPU_LOGD << " buffer" ;
348
+ }
349
+ if (entry.sampler ) {
350
+ assert_invariant (entry.buffer == nullptr && entry.textureView == nullptr &&
351
+ " bind group entry with sampler also has buffer and/or textureView?" );
352
+ FWGPU_LOGD << " sampler" ;
353
+ }
354
+ if (entry.textureView ) {
355
+ assert_invariant (entry.buffer == nullptr && entry.sampler == nullptr &&
356
+ " bind group entry with textureView also has buffer and/or sampler?" );
357
+ FWGPU_LOGD << " textureView" ;
358
+ }
359
+ FWGPU_LOGD << " offset " << entry.offset << " size " << entry.size << utils::io::endl;
360
+ }
361
+ }
362
+ #endif
363
+
160
364
}// namespace
161
365
162
366
namespace filament ::backend {
@@ -237,6 +441,9 @@ wgpu::ShaderStage WebGPUDescriptorSetLayout::filamentStageToWGPUStage(ShaderStag
237
441
238
442
WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout (DescriptorSetLayout const & layout,
239
443
wgpu::Device const & device) {
444
+ #if FWGPU_ENABLED(FWGPU_DEBUG_DESCRIPTOR_SETS)
445
+ printFilamentDescriptorSetLayout (layout);
446
+ #endif
240
447
assert_invariant (device);
241
448
242
449
std::string baseLabel;
@@ -319,6 +526,10 @@ WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout(DescriptorSetLayout const&
319
526
.entryCount = wEntries.size (),
320
527
.entries = wEntries.data ()
321
528
};
529
+ #if FWGPU_ENABLED(FWGPU_DEBUG_DESCRIPTOR_SETS)
530
+ printBindGroupLayout (layoutDescriptor);
531
+ #endif
532
+ mLabel = utils::CString (label.c_str ());
322
533
mLayout = device.CreateBindGroupLayout (&layoutDescriptor);
323
534
}
324
535
@@ -411,9 +622,11 @@ std::vector<wgpu::BindGroupEntry> WebGPUDescriptorSet::createDummyEntriesSortedB
411
622
return entries;
412
623
}
413
624
414
- WebGPUDescriptorSet::WebGPUDescriptorSet (wgpu::BindGroupLayout const & layout,
625
+ WebGPUDescriptorSet::WebGPUDescriptorSet (wgpu::StringView label,
626
+ wgpu::BindGroupLayout const & layout,
415
627
std::vector<WebGPUDescriptorSetLayout::BindGroupEntryInfo> const & bindGroupEntries)
416
- : mLayout (layout),
628
+ : mLabel (label),
629
+ mLayout (layout),
417
630
mEntriesSortedByBinding(createDummyEntriesSortedByBinding(bindGroupEntries)) {
418
631
// Establish the size of entries based on the layout. This should be reliable and efficient.
419
632
assert_invariant (INVALID_INDEX > mEntryIndexByBinding .size ());
@@ -436,23 +649,24 @@ WebGPUDescriptorSet::WebGPUDescriptorSet(wgpu::BindGroupLayout const& layout,
436
649
437
650
WebGPUDescriptorSet::~WebGPUDescriptorSet () {
438
651
mBindGroup = nullptr ;
439
- mLayout = nullptr ;
440
652
}
441
653
442
654
wgpu::BindGroup WebGPUDescriptorSet::lockAndReturn (const wgpu::Device& device) {
443
655
if (mBindGroup ) {
444
656
return mBindGroup ;
445
657
}
446
- // TODO label? Should we just copy layout label?
447
658
wgpu::BindGroupDescriptor desc{
659
+ .label = mLabel ,
448
660
.layout = mLayout ,
449
661
.entryCount = mEntriesSortedByBinding .size (),
450
662
.entries = mEntriesSortedByBinding .data ()
451
663
};
664
+ #if FWGPU_ENABLED(FWGPU_DEBUG_DESCRIPTOR_SETS)
665
+ printBindGroup (desc, mEntriesByBindingWithDynamicOffsets , mEntriesByBindingAdded );
666
+ #endif
452
667
mBindGroup = device.CreateBindGroup (&desc);
453
668
FILAMENT_CHECK_POSTCONDITION (mBindGroup ) << " Failed to create bind group?" ;
454
669
// once we have created the bind group itself we should no longer need any other state
455
- mLayout = nullptr ;
456
670
mEntriesSortedByBinding .clear ();
457
671
mEntriesSortedByBinding .shrink_to_fit ();
458
672
return mBindGroup ;
0 commit comments