Skip to content

Commit ffb124d

Browse files
committed
stronger test that keepalives work correctly
1 parent 595792c commit ffb124d

File tree

1 file changed

+59
-20
lines changed

1 file changed

+59
-20
lines changed

test/webgpu_basic_rendering.cpp

Lines changed: 59 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,42 @@
1818

1919
#include <emscripten.h>
2020
#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+
}
2157

2258
static const wgpu::Instance instance = wgpuCreateInstance(nullptr);
2359

@@ -126,7 +162,7 @@ void init() {
126162
// The depth stencil attachment isn't really needed to draw the triangle
127163
// and doesn't really affect the render result.
128164
// 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) {
130166
wgpu::RenderPassColorAttachment attachment{};
131167
attachment.view = view;
132168
attachment.loadOp = wgpu::LoadOp::Clear;
@@ -160,11 +196,10 @@ void render(wgpu::Device device, wgpu::TextureView view, wgpu::TextureView depth
160196
queue.Submit(1, &commands);
161197
}
162198

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) {
165200
readbackBuffer.MapAsync(
166201
wgpu::MapMode::Read, 0, 4, wgpu::CallbackMode::AllowSpontaneous,
167-
[=](wgpu::MapAsyncStatus status, wgpu::StringView message) {
202+
[=, scope=scope](wgpu::MapAsyncStatus status, wgpu::StringView message) {
168203
if (message.length) {
169204
printf("readbackBuffer.MapAsync: %.*s\n", int(message.length), message.data);
170205
}
@@ -183,7 +218,7 @@ void issueContentsCheck(std::string functionName, wgpu::Device device,
183218
});
184219
}
185220

186-
void doCopyTestMappedAtCreation(bool useRange) {
221+
void doCopyTestMappedAtCreation(ScopedCounter scope, bool useRange) {
187222
static constexpr uint32_t kValue = 0x05060708;
188223
size_t size = useRange ? 12 : 4;
189224
wgpu::Buffer src;
@@ -225,10 +260,10 @@ void doCopyTestMappedAtCreation(bool useRange) {
225260
}
226261
queue.Submit(1, &commands);
227262

228-
issueContentsCheck(__FUNCTION__, device, dst, kValue);
263+
issueContentsCheck(scope, __FUNCTION__, dst, kValue);
229264
}
230265

231-
void doCopyTestMapAsync(bool useRange) {
266+
void doCopyTestMapAsync(ScopedCounter scope, bool useRange) {
232267
static constexpr uint32_t kValue = 0x01020304;
233268
size_t size = useRange ? 12 : 4;
234269
wgpu::Buffer src;
@@ -274,11 +309,11 @@ void doCopyTestMapAsync(bool useRange) {
274309
}
275310
queue.Submit(1, &commands);
276311

277-
issueContentsCheck(functionName, device, dst, kValue);
312+
issueContentsCheck(scope, functionName, dst, kValue);
278313
});
279314
}
280315

281-
void doRenderTest() {
316+
void doRenderTest(ScopedCounter scope) {
282317
wgpu::Texture readbackTexture;
283318
{
284319
wgpu::TextureDescriptor descriptor{};
@@ -302,7 +337,7 @@ void doRenderTest() {
302337
descriptor.format = wgpu::TextureFormat::Depth32Float;
303338
depthTexture = device.CreateTexture(&descriptor);
304339
}
305-
render(device, readbackTexture.CreateView(), depthTexture.CreateView());
340+
render(readbackTexture.CreateView(), depthTexture.CreateView());
306341

307342
{
308343
// A little texture.GetFormat test
@@ -335,20 +370,22 @@ void doRenderTest() {
335370

336371
// Check the color value encoded in the shader makes it out correctly.
337372
static const uint32_t expectData = 0xff0080ff;
338-
issueContentsCheck(__FUNCTION__, device, readbackBuffer, expectData);
373+
issueContentsCheck(scope, __FUNCTION__, readbackBuffer, expectData);
339374
}
340375

341376
wgpu::Surface surface;
342377
wgpu::TextureView canvasDepthStencilView;
343378
const uint32_t kWidth = 300;
344379
const uint32_t kHeight = 150;
345380

346-
void frame() {
381+
void frame(void* vp_scope) {
382+
auto scope = std::unique_ptr<ScopedCounter>(reinterpret_cast<ScopedCounter*>(vp_scope));
383+
347384
wgpu::SurfaceTexture surfaceTexture;
348385
surface.GetCurrentTexture(&surfaceTexture);
349386

350387
wgpu::TextureView backbuffer = surfaceTexture.texture.CreateView();
351-
render(device, backbuffer, canvasDepthStencilView);
388+
render(backbuffer, canvasDepthStencilView);
352389

353390
// Test should complete when runtime exists after all async work is done.
354391
emscripten_cancel_main_loop();
@@ -357,11 +394,12 @@ void frame() {
357394
void run() {
358395
init();
359396

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);
365403

366404
{
367405
wgpu::EmscriptenSurfaceSourceCanvasHTMLSelector canvasDesc{};
@@ -393,14 +431,15 @@ void run() {
393431
}
394432
}
395433

396-
emscripten_set_main_loop(frame, 0, false);
434+
emscripten_set_main_loop_arg(frame, new ScopedCounter(), 0, false);
397435
}
398436

399437
int main() {
400438
GetDevice(run);
401439

440+
RegisterCheckScopesAtExit();
402441
// This exit code will be reported when all of the async operations
403442
// complete and the main loop is cancelled. Until then, keepalive keeps
404443
// the runtime from exiting.
405-
return 0;
444+
return 99;
406445
}

0 commit comments

Comments
 (0)