@@ -142,7 +142,7 @@ struct ShaderCompilerService::OpenGLProgramToken : ProgramToken {
142
142
// From this state, the token can transition to either LOADING or CANCELED.
143
143
WAITING,
144
144
// This state indicates that shader compilation is currently underway for the token.
145
- // From this state, the token can transition to either COMPLETED or CANCELED .
145
+ // From this state, the token can only transition to COMPLETED.
146
146
LOADING,
147
147
// This state indicates that shader compilation for the token has finished.
148
148
// No state transitions can occur from this state.
@@ -389,59 +389,27 @@ GLuint ShaderCompilerService::getProgram(program_token_t& token) {
389
389
390
390
if (token->compiler .mMode == Mode::THREAD_POOL) {
391
391
// Attempt to cancel the token. If the token's resource loading has already begun, the
392
- // token will be monitored until completion so that it proceeds with resource destruction
393
- // afterward.
392
+ // token will be monitored via the `mCanceledTokens` until completion so that it proceeds
393
+ // with resource destruction afterward.
394
394
OpenGLProgramToken::State tokenState = OpenGLProgramToken::State::WAITING;
395
395
if (!token->state .compare_exchange_strong (tokenState, OpenGLProgramToken::State::CANCELED,
396
396
std::memory_order_relaxed)) {
397
397
assert_invariant (tokenState == OpenGLProgramToken::State::LOADING ||
398
398
tokenState == OpenGLProgramToken::State::COMPLETED);
399
399
token->compiler .mCanceledTokens .push_back (token);
400
400
}
401
+ } else {
402
+ token->compiler .cancelTickOp (token);
401
403
}
402
404
403
- // Cleanup the token.
404
- token->compiler .cancelTickOp (token);
405
405
token = nullptr ; // This will try submitting a callback handle to the callback manager.
406
406
}
407
407
408
408
void ShaderCompilerService::tick () {
409
- // we don't need to run executeTickOps() if we're using the thread-pool
410
- if (UTILS_UNLIKELY (mMode != Mode::THREAD_POOL)) {
411
- executeTickOps ();
409
+ if (mMode == Mode::THREAD_POOL) {
410
+ handleCanceledTokensForThreadPool ();
412
411
} else {
413
- // TODO: refactor (or rename) `executeTickOps` so that it performs properly
414
- // (including below) based on mMode.
415
- for (auto it = mCanceledTokens .begin (); it != mCanceledTokens .end ();) {
416
- auto token = *it;
417
- OpenGLProgramToken::State tokenState = token->state .load (std::memory_order_relaxed);
418
-
419
- if (tokenState != OpenGLProgramToken::State::COMPLETED) {
420
- ++it;
421
- continue ;
422
- }
423
-
424
- mCompilerThreadPool .queue (CompilerPriorityQueue::LOW, token,
425
- [token]() mutable {
426
- assert_invariant (token->state == OpenGLProgramToken::State::COMPLETED);
427
- for (GLuint& shader: token->gl .shaders ) {
428
- if (!shader) {
429
- continue ;
430
- }
431
- if (token->gl .program ) {
432
- glDetachShader (token->gl .program , shader);
433
- }
434
- glDeleteShader (shader);
435
- shader = 0 ;
436
- }
437
- if (token->gl .program ) {
438
- glDeleteProgram (token->gl .program );
439
- token->gl .program = 0 ;
440
- }
441
- });
442
-
443
- it = mCanceledTokens .erase (it);
444
- }
412
+ executeTickOps ();
445
413
}
446
414
}
447
415
@@ -478,18 +446,17 @@ GLuint ShaderCompilerService::initialize(program_token_t& token) {
478
446
FILAMENT_CHECK_POSTCONDITION (linked)
479
447
<< " OpenGL program " << token->name .c_str_safe () << " failed to link or compile" ;
480
448
481
- // The program is successfully created. Try caching the program blob. In the THREAD_POOL mode,
482
- // caching is performed in the pool.
449
+ GLuint const program = token-> gl . program ;
450
+
483
451
if (mMode != Mode::THREAD_POOL) {
452
+ // The program has been successfully created. Try caching the program blob for
453
+ // non-THREAD_POOL modes. In the THREAD_POOL mode, caching is performed in the pool.
484
454
tryCachingProgram (mBlobCache , mDriver .mPlatform , token);
455
+ // The token could be present in the tick op list at this point. Ensure the token is not in
456
+ // the tick op list.(b/394319326)
457
+ token->compiler .cancelTickOp (token);
485
458
}
486
459
487
- // Release the program from the token.
488
- GLuint const program = token->gl .program ;
489
- token->gl .program = 0 ;
490
-
491
- // Cleanup the token.
492
- token->compiler .cancelTickOp (token);
493
460
token = nullptr ;
494
461
495
462
return program;
@@ -544,6 +511,41 @@ void ShaderCompilerService::ensureTokenIsReady(program_token_t const& token) {
544
511
545
512
// ------------------------------------------------------------------------------------------------
546
513
514
+ void ShaderCompilerService::handleCanceledTokensForThreadPool () {
515
+ for (auto it = mCanceledTokens .begin (); it != mCanceledTokens .end ();) {
516
+ auto token = *it;
517
+ OpenGLProgramToken::State tokenState = token->state .load (std::memory_order_relaxed);
518
+
519
+ if (tokenState != OpenGLProgramToken::State::COMPLETED) {
520
+ ++it;
521
+ continue ;
522
+ }
523
+
524
+ mCompilerThreadPool .queue (CompilerPriorityQueue::LOW, token,
525
+ [token]() mutable {
526
+ assert_invariant (token->state == OpenGLProgramToken::State::COMPLETED);
527
+ for (GLuint& shader: token->gl .shaders ) {
528
+ if (!shader) {
529
+ continue ;
530
+ }
531
+ if (token->gl .program ) {
532
+ glDetachShader (token->gl .program , shader);
533
+ }
534
+ glDeleteShader (shader);
535
+ shader = 0 ;
536
+ }
537
+ if (token->gl .program ) {
538
+ glDeleteProgram (token->gl .program );
539
+ token->gl .program = 0 ;
540
+ }
541
+ });
542
+
543
+ it = mCanceledTokens .erase (it);
544
+ }
545
+ }
546
+
547
+ // ------------------------------------------------------------------------------------------------
548
+
547
549
void ShaderCompilerService::runAtNextTick (CompilerPriorityQueue priority,
548
550
program_token_t const & token, Job job) noexcept {
549
551
// insert items in order of priority and at the end of the range
0 commit comments