Skip to content

Commit 86d19e5

Browse files
authored
gl: Cleanup code flow in ShaderCompilerService (#9014)
1 parent 70d4166 commit 86d19e5

File tree

2 files changed

+54
-48
lines changed

2 files changed

+54
-48
lines changed

filament/backend/src/opengl/ShaderCompilerService.cpp

Lines changed: 50 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ struct ShaderCompilerService::OpenGLProgramToken : ProgramToken {
142142
// From this state, the token can transition to either LOADING or CANCELED.
143143
WAITING,
144144
// 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.
146146
LOADING,
147147
// This state indicates that shader compilation for the token has finished.
148148
// No state transitions can occur from this state.
@@ -389,59 +389,27 @@ GLuint ShaderCompilerService::getProgram(program_token_t& token) {
389389

390390
if (token->compiler.mMode == Mode::THREAD_POOL) {
391391
// 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.
394394
OpenGLProgramToken::State tokenState = OpenGLProgramToken::State::WAITING;
395395
if (!token->state.compare_exchange_strong(tokenState, OpenGLProgramToken::State::CANCELED,
396396
std::memory_order_relaxed)) {
397397
assert_invariant(tokenState == OpenGLProgramToken::State::LOADING ||
398398
tokenState == OpenGLProgramToken::State::COMPLETED);
399399
token->compiler.mCanceledTokens.push_back(token);
400400
}
401+
} else {
402+
token->compiler.cancelTickOp(token);
401403
}
402404

403-
// Cleanup the token.
404-
token->compiler.cancelTickOp(token);
405405
token = nullptr; // This will try submitting a callback handle to the callback manager.
406406
}
407407

408408
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();
412411
} 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();
445413
}
446414
}
447415

@@ -478,18 +446,17 @@ GLuint ShaderCompilerService::initialize(program_token_t& token) {
478446
FILAMENT_CHECK_POSTCONDITION(linked)
479447
<< "OpenGL program " << token->name.c_str_safe() << " failed to link or compile";
480448

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+
483451
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.
484454
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);
485458
}
486459

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);
493460
token = nullptr;
494461

495462
return program;
@@ -544,6 +511,41 @@ void ShaderCompilerService::ensureTokenIsReady(program_token_t const& token) {
544511

545512
// ------------------------------------------------------------------------------------------------
546513

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+
547549
void ShaderCompilerService::runAtNextTick(CompilerPriorityQueue priority,
548550
program_token_t const& token, Job job) noexcept {
549551
// insert items in order of priority and at the end of the range

filament/backend/src/opengl/ShaderCompilerService.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,10 @@ class ShaderCompilerService {
140140
GLuint initialize(program_token_t& token);
141141
void ensureTokenIsReady(program_token_t const& token);
142142

143+
// Methods for THREAD_POOL mode.
144+
void handleCanceledTokensForThreadPool();
145+
146+
// Methods for SYNCHRONOUS and ASYNCHRONOUS modes.
143147
void runAtNextTick(CompilerPriorityQueue priority, program_token_t const& token,
144148
Job job) noexcept;
145149
void executeTickOps() noexcept;

0 commit comments

Comments
 (0)