18
18
19
19
#include < emscripten.h>
20
20
#include < emscripten/html5.h>
21
+ #include < emscripten/em_js.h>
22
+
23
+ EM_JS_DEPS (deps, " $keepRuntimeAlive" );
24
+
25
+ // Keeps track of whether async tests are still alive to make sure they finish
26
+ // before exit. This tests that keepalives exist where they should.
27
+ static int sScopeCount = 0 ;
28
+ class ScopedCounter {
29
+ public:
30
+ ScopedCounter (const ScopedCounter&&) { Increment (); }
31
+ ScopedCounter (const ScopedCounter&) { Increment (); }
32
+ ScopedCounter () { Increment (); }
33
+ ~ScopedCounter () { Decrement (); }
34
+ private:
35
+ void Increment () { sScopeCount ++; }
36
+ void Decrement () {
37
+ assert (sScopeCount > 0 );
38
+ sScopeCount --;
39
+ if (sScopeCount == 0 ) {
40
+ // Check we don't reach 0 before the runtime is ready to exit.
41
+ // (Make sure this test has scopes for everything that does keepalive.)
42
+ bool runtime_is_kept_alive = EM_ASM_INT ({ return keepRuntimeAlive (); });
43
+ assert (!runtime_is_kept_alive);
44
+ }
45
+ }
46
+ };
47
+
48
+ void RegisterCheckScopesAtExit () {
49
+ atexit ([](){
50
+ // Check we don't exit before the tests are done.
51
+ // (Make sure there's a keepalive for everything the test has scopes for.)
52
+ assert (sScopeCount == 0 );
53
+ // Overwrite the old return code and exit now that everything is done.
54
+ exit (0 );
55
+ });
56
+ }
21
57
22
58
static const wgpu::Instance instance = wgpuCreateInstance(nullptr );
23
59
@@ -126,7 +162,7 @@ void init() {
126
162
// The depth stencil attachment isn't really needed to draw the triangle
127
163
// and doesn't really affect the render result.
128
164
// But having one should give us a slightly better test coverage for the compile of the depth stencil descriptor.
129
- void render (wgpu::Device device, wgpu:: TextureView view, wgpu::TextureView depthStencilView) {
165
+ void render (wgpu::TextureView view, wgpu::TextureView depthStencilView) {
130
166
wgpu::RenderPassColorAttachment attachment{};
131
167
attachment.view = view;
132
168
attachment.loadOp = wgpu::LoadOp::Clear;
@@ -160,11 +196,10 @@ void render(wgpu::Device device, wgpu::TextureView view, wgpu::TextureView depth
160
196
queue.Submit (1 , &commands);
161
197
}
162
198
163
- void issueContentsCheck (std::string functionName, wgpu::Device device,
164
- wgpu::Buffer readbackBuffer, uint32_t expectData) {
199
+ void issueContentsCheck (ScopedCounter scope, std::string functionName, wgpu::Buffer readbackBuffer, uint32_t expectData) {
165
200
readbackBuffer.MapAsync (
166
201
wgpu::MapMode::Read, 0 , 4 , wgpu::CallbackMode::AllowSpontaneous,
167
- [=](wgpu::MapAsyncStatus status, wgpu::StringView message) {
202
+ [=, scope=scope ](wgpu::MapAsyncStatus status, wgpu::StringView message) {
168
203
if (message.length ) {
169
204
printf (" readbackBuffer.MapAsync: %.*s\n " , int (message.length ), message.data );
170
205
}
@@ -183,7 +218,7 @@ void issueContentsCheck(std::string functionName, wgpu::Device device,
183
218
});
184
219
}
185
220
186
- void doCopyTestMappedAtCreation (bool useRange) {
221
+ void doCopyTestMappedAtCreation (ScopedCounter scope, bool useRange) {
187
222
static constexpr uint32_t kValue = 0x05060708 ;
188
223
size_t size = useRange ? 12 : 4 ;
189
224
wgpu::Buffer src;
@@ -225,10 +260,10 @@ void doCopyTestMappedAtCreation(bool useRange) {
225
260
}
226
261
queue.Submit (1 , &commands);
227
262
228
- issueContentsCheck (__FUNCTION__, device , dst, kValue );
263
+ issueContentsCheck (scope, __FUNCTION__ , dst, kValue );
229
264
}
230
265
231
- void doCopyTestMapAsync (bool useRange) {
266
+ void doCopyTestMapAsync (ScopedCounter scope, bool useRange) {
232
267
static constexpr uint32_t kValue = 0x01020304 ;
233
268
size_t size = useRange ? 12 : 4 ;
234
269
wgpu::Buffer src;
@@ -274,11 +309,11 @@ void doCopyTestMapAsync(bool useRange) {
274
309
}
275
310
queue.Submit (1 , &commands);
276
311
277
- issueContentsCheck (functionName, device , dst, kValue );
312
+ issueContentsCheck (scope, functionName , dst, kValue );
278
313
});
279
314
}
280
315
281
- void doRenderTest () {
316
+ void doRenderTest (ScopedCounter scope ) {
282
317
wgpu::Texture readbackTexture;
283
318
{
284
319
wgpu::TextureDescriptor descriptor{};
@@ -302,7 +337,7 @@ void doRenderTest() {
302
337
descriptor.format = wgpu::TextureFormat::Depth32Float;
303
338
depthTexture = device.CreateTexture (&descriptor);
304
339
}
305
- render (device, readbackTexture.CreateView (), depthTexture.CreateView ());
340
+ render (readbackTexture.CreateView (), depthTexture.CreateView ());
306
341
307
342
{
308
343
// A little texture.GetFormat test
@@ -335,20 +370,22 @@ void doRenderTest() {
335
370
336
371
// Check the color value encoded in the shader makes it out correctly.
337
372
static const uint32_t expectData = 0xff0080ff ;
338
- issueContentsCheck (__FUNCTION__, device , readbackBuffer, expectData);
373
+ issueContentsCheck (scope, __FUNCTION__ , readbackBuffer, expectData);
339
374
}
340
375
341
376
wgpu::Surface surface;
342
377
wgpu::TextureView canvasDepthStencilView;
343
378
const uint32_t kWidth = 300 ;
344
379
const uint32_t kHeight = 150 ;
345
380
346
- void frame () {
381
+ void frame (void * vp_scope) {
382
+ auto scope = std::unique_ptr<ScopedCounter>(reinterpret_cast <ScopedCounter*>(vp_scope));
383
+
347
384
wgpu::SurfaceTexture surfaceTexture;
348
385
surface.GetCurrentTexture (&surfaceTexture);
349
386
350
387
wgpu::TextureView backbuffer = surfaceTexture.texture .CreateView ();
351
- render (device, backbuffer, canvasDepthStencilView);
388
+ render (backbuffer, canvasDepthStencilView);
352
389
353
390
// Test should complete when runtime exists after all async work is done.
354
391
emscripten_cancel_main_loop ();
@@ -357,11 +394,12 @@ void frame() {
357
394
void run () {
358
395
init ();
359
396
360
- doCopyTestMappedAtCreation (false );
361
- doCopyTestMappedAtCreation (true );
362
- doCopyTestMapAsync (false );
363
- doCopyTestMapAsync (true );
364
- doRenderTest ();
397
+ ScopedCounter scope;
398
+ doCopyTestMappedAtCreation (scope, false );
399
+ doCopyTestMappedAtCreation (scope, true );
400
+ doCopyTestMapAsync (scope, false );
401
+ doCopyTestMapAsync (scope, true );
402
+ doRenderTest (scope);
365
403
366
404
{
367
405
wgpu::EmscriptenSurfaceSourceCanvasHTMLSelector canvasDesc{};
@@ -393,14 +431,15 @@ void run() {
393
431
}
394
432
}
395
433
396
- emscripten_set_main_loop (frame, 0 , false );
434
+ emscripten_set_main_loop_arg (frame, new ScopedCounter () , 0 , false );
397
435
}
398
436
399
437
int main () {
400
438
GetDevice (run);
401
439
440
+ RegisterCheckScopesAtExit ();
402
441
// This exit code will be reported when all of the async operations
403
442
// complete and the main loop is cancelled. Until then, keepalive keeps
404
443
// the runtime from exiting.
405
- return 0 ;
444
+ return 99 ;
406
445
}
0 commit comments