Repository: google/filament
File: filament/backend/src/opengl/ShaderCompilerService.cpp (C++)

Code before:
    // Finally stop the thread pool immediately. Pending jobs will be discarded. We guarantee by
    // construction that nobody is waiting on a token (because waiting is only done on the main
    // backend thread, and if we're here, we're on the backend main thread).
    mCompilerThreadPool.terminate();

    mRunAtNextTickOps.clear();
    mPendingSynchronousPrograms.clear();

    // We could have some pending callbacks here, we need to execute them.
    // This is equivalent to calling cancelTickOp() on all active tokens.
    mCallbackManager.terminate();
}

ShaderCompilerService::program_token_t ShaderCompilerService::createProgram(
        CString const& name, Program&& program) {
    auto& gl = mDriver.getContext();
    CompilerPriorityQueue const priorityQueue = program.getPriorityQueue();

    // Create a token. A callback condition (handle) is internally created upon token creation.
    auto token = std::make_shared<OpenGLProgramToken>(*this, name);
    if (UTILS_UNLIKELY(gl.isES2())) {
        token->attributes = std::move(program.getAttributes());
    }

    if (mMode == Mode::SYNCHRONOUS) {
        if (priorityQueue == CompilerPriorityQueue::IMMEDIATE ||
                shouldCompileSynchronousProgramThisTick()) {
            // We should immediately compile this program this frame.
            compileProgram(token, std::move(program));
        } else {
            // We already exceeded the number of non-IMMEDIATE synchronous programs we're allowed to
            // create this frame. Queue it for a future frame, sorted by priority.
            auto const pos = std::lower_bound(mPendingSynchronousPrograms.begin(),
                    mPendingSynchronousPrograms.end(), priorityQueue,
                    [](PendingSynchronousProgram const& lhs,
                            CompilerPriorityQueue const priorityQueue) {
                        return std::get<1>(lhs).getPriorityQueue() < priorityQueue;
                    });
            mPendingSynchronousPrograms.emplace(pos, token, std::move(program));
        }
    } else {
        // Truly asynchronous platforms can always begin compiling immediately.
        compileProgram(token, std::move(program));
    }

    return token;
}

void ShaderCompilerService::compileProgram(
        program_token_t const& token, Program&& program) noexcept {
    auto& gl = mDriver.getContext();

Review comment (suggestion):
The term `IMMEDIATE` appears to function as intended for SYNCHRONOUS mode, but not for other modes. Can we rename it more universally like CRITICAL, URGENT, HIGHEST, etc? (and make it work immediately for SYNCHRONOUS mode)

Code after:

        mShaderCompilerThreadCount = poolSize;
        mCompilerThreadPool.init(mShaderCompilerThreadCount,
                [&platform = mDriver.mPlatform, priority] {
                    // give the thread a name
                    JobSystem::setThreadName("CompilerThreadPool");
                    // run at a slightly lower priority than other filament threads
                    JobSystem::setThreadPriority(priority);
                    // create a gl context current to this thread
                    platform.createContext(true);
                },
                [&platform = mDriver.mPlatform] {
                    // release context and thread state
                    platform.releaseContext();
                });
    }
}

void ShaderCompilerService::terminate() noexcept {
    // Finally stop the thread pool immediately. Pending jobs will be discarded. We guarantee by
    // construction that nobody is waiting on a token (because waiting is only done on the main
    // backend thread, and if we're here, we're on the backend main thread).
    mCompilerThreadPool.terminate();

    mRunAtNextTickOps.clear();
    mPendingSynchronousPrograms.clear();

    // We could have some pending callbacks here, we need to execute them.
    // This is equivalent to calling cancelTickOp() on all active tokens.
    mCallbackManager.terminate();
}

ShaderCompilerService::program_token_t ShaderCompilerService::createProgram(
        CString const& name, Program&& program) {
    auto& gl = mDriver.getContext();
    CompilerPriorityQueue const priorityQueue = program.getPriorityQueue();

    // Create a token. A callback condition (handle) is internally created upon token creation.
    auto token = std::make_shared<OpenGLProgramToken>(*this, name);
    if (UTILS_UNLIKELY(gl.isES2())) {
        token->attributes = std::move(program.getAttributes());
    }

    if (mMode == Mode::SYNCHRONOUS) {
        if (priorityQueue == CompilerPriorityQueue::CRITICAL ||
                shouldCompileSynchronousProgramThisTick()) {
            // We should immediately compile this program this frame.
            compileProgram(token, std::move(program));
        } else {
            // We already exceeded the number of non-IMMEDIATE synchronous programs we're allowed to
            // create this frame. Queue it for a future frame, sorted by priority.