ParallelCompile: Parallelize shader translation
This changes to construct a new ShHandle of compiler for each Shader,
and use it to translate the shader source in a background thread.
Bug: chromium:849576
Change-Id: Ib49952c7292321ee6aa1c5996f8f7927f40d8f04
Reviewed-on: https://chromium-review.googlesource.com/1177195
Commit-Queue: Jie A Chen <jie.a.chen@intel.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/Shader.cpp b/src/libANGLE/Shader.cpp
index a2697da..3ebcab2 100644
--- a/src/libANGLE/Shader.cpp
+++ b/src/libANGLE/Shader.cpp
@@ -10,6 +10,7 @@
#include "libANGLE/Shader.h"
+#include <functional>
#include <sstream>
#include "GLSLANG/ShaderLang.h"
@@ -19,6 +20,7 @@
#include "libANGLE/Constants.h"
#include "libANGLE/Context.h"
#include "libANGLE/ResourceManager.h"
+#include "libANGLE/WorkerThread.h"
#include "libANGLE/renderer/GLImplFactory.h"
#include "libANGLE/renderer/ShaderImpl.h"
@@ -96,6 +98,50 @@
}
}
+class ScopedExit final : angle::NonCopyable
+{
+ public:
+ ScopedExit(std::function<void()> exit) : mExit(exit) {}
+ ~ScopedExit() { mExit(); }
+
+ private:
+ std::function<void()> mExit;
+};
+
+class CompileTask : public angle::Closure
+{
+ public:
+ CompileTask(ShHandle handle,
+ std::string &&sourcePath,
+ std::string &&source,
+ ShCompileOptions options)
+ : mHandle(handle),
+ mSourcePath(sourcePath),
+ mSource(source),
+ mOptions(options),
+ mResult(false)
+ {
+ }
+ void operator()() override
+ {
+ std::vector<const char *> srcStrings;
+ if (!mSourcePath.empty())
+ {
+ srcStrings.push_back(mSourcePath.c_str());
+ }
+ srcStrings.push_back(mSource.c_str());
+ mResult = sh::Compile(mHandle, &srcStrings[0], srcStrings.size(), mOptions);
+ }
+ bool getResult() { return mResult; }
+
+ private:
+ ShHandle mHandle;
+ std::string mSourcePath;
+ std::string mSource;
+ ShCompileOptions mOptions;
+ bool mResult;
+};
+
ShaderState::ShaderState(ShaderType shaderType)
: mLabel(),
mShaderType(shaderType),
@@ -131,6 +177,7 @@
void Shader::onDestroy(const gl::Context *context)
{
+ resolveCompile();
mImplementation->destroy();
mBoundCompiler.set(context, nullptr);
mImplementation.reset(nullptr);
@@ -284,6 +331,8 @@
void Shader::compile(const Context *context)
{
+ resolveCompile();
+
mState.mTranslatedSource.clear();
mInfoLog.clear();
mState.mShaderVersion = 100;
@@ -307,19 +356,19 @@
// can change before the link call or another call that resolves the compile.
std::stringstream sourceStream;
-
- mLastCompileOptions = mImplementation->prepareSourceAndReturnOptions(context, &sourceStream,
- &mLastCompiledSourcePath);
- mLastCompileOptions |= (SH_OBJECT_CODE | SH_VARIABLES);
- mLastCompiledSource = sourceStream.str();
+ std::string sourcePath;
+ ShCompileOptions options =
+ mImplementation->prepareSourceAndReturnOptions(context, &sourceStream, &sourcePath);
+ options |= (SH_OBJECT_CODE | SH_VARIABLES);
+ auto source = sourceStream.str();
// Add default options to WebGL shaders to prevent unexpected behavior during compilation.
if (context->getExtensions().webglCompatibility)
{
- mLastCompileOptions |= SH_INIT_GL_POSITION;
- mLastCompileOptions |= SH_LIMIT_CALL_STACK_DEPTH;
- mLastCompileOptions |= SH_LIMIT_EXPRESSION_COMPLEXITY;
- mLastCompileOptions |= SH_ENFORCE_PACKING_RESTRICTIONS;
+ options |= SH_INIT_GL_POSITION;
+ options |= SH_LIMIT_CALL_STACK_DEPTH;
+ options |= SH_LIMIT_EXPRESSION_COMPLEXITY;
+ options |= SH_ENFORCE_PACKING_RESTRICTIONS;
}
// Some targets (eg D3D11 Feature Level 9_3 and below) do not support non-constant loop indexes
@@ -327,10 +376,21 @@
// instruct the compiler to pre-validate.
if (mRendererLimitations.shadersRequireIndexedLoopValidation)
{
- mLastCompileOptions |= SH_VALIDATE_LOOP_INDEXING;
+ options |= SH_VALIDATE_LOOP_INDEXING;
}
mCurrentMaxComputeWorkGroupInvocations = context->getCaps().maxComputeWorkGroupInvocations;
+
+ ASSERT(mBoundCompiler.get());
+ mShCompilerInstance = mBoundCompiler->getInstance(mState.mShaderType);
+ ShHandle compilerHandle = mShCompilerInstance.getHandle();
+ ASSERT(compilerHandle);
+ mCompilerResourcesString = mShCompilerInstance.getBuiltinResourcesString();
+
+ mCompileTask = std::make_shared<CompileTask>(compilerHandle, std::move(sourcePath),
+ std::move(source), options);
+ mWorkerPool = context->getWorkerThreadPool();
+ mCompileEvent = mWorkerPool->postWorkerTask(mCompileTask);
}
void Shader::resolveCompile()
@@ -340,19 +400,21 @@
return;
}
- ASSERT(mBoundCompiler.get());
- ShHandle compilerHandle = mBoundCompiler->getCompilerHandle(mState.mShaderType);
+ ASSERT(mCompileEvent.get());
+ ASSERT(mCompileTask.get());
- std::vector<const char *> srcStrings;
+ mCompileEvent->wait();
- if (!mLastCompiledSourcePath.empty())
- {
- srcStrings.push_back(mLastCompiledSourcePath.c_str());
- }
+ mCompileEvent.reset();
+ mWorkerPool.reset();
- srcStrings.push_back(mLastCompiledSource.c_str());
+ bool compiled = mCompileTask->getResult();
+ mCompileTask.reset();
- if (!sh::Compile(compilerHandle, &srcStrings[0], srcStrings.size(), mLastCompileOptions))
+ ScopedExit exit([this]() { mBoundCompiler->putInstance(std::move(mShCompilerInstance)); });
+
+ ShHandle compilerHandle = mShCompilerInstance.getHandle();
+ if (!compiled)
{
mInfoLog = sh::GetInfoLog(compilerHandle);
WARN() << std::endl << mInfoLog;
@@ -469,7 +531,7 @@
ASSERT(!mState.mTranslatedSource.empty());
- bool success = mImplementation->postTranslateCompile(mBoundCompiler.get(), &mInfoLog);
+ bool success = mImplementation->postTranslateCompile(&mShCompilerInstance, &mInfoLog);
mState.mCompileStatus = success ? CompileStatus::COMPILED : CompileStatus::NOT_COMPILED;
}
@@ -509,6 +571,11 @@
return mState.mCompileStatus == CompileStatus::COMPILED;
}
+bool Shader::isCompleted()
+{
+ return (!mState.compilePending() || mCompileEvent->isReady());
+}
+
int Shader::getShaderVersion()
{
resolveCompile();
@@ -640,8 +707,7 @@
const std::string &Shader::getCompilerResourcesString() const
{
- ASSERT(mBoundCompiler.get());
- return mBoundCompiler->getBuiltinResourcesString(mState.mShaderType);
+ return mCompilerResourcesString;
}
} // namespace gl