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/tests/gl_tests/ParallelShaderCompileTest.cpp b/src/tests/gl_tests/ParallelShaderCompileTest.cpp
index 21788d2..fd3277e 100644
--- a/src/tests/gl_tests/ParallelShaderCompileTest.cpp
+++ b/src/tests/gl_tests/ParallelShaderCompileTest.cpp
@@ -51,11 +51,39 @@
public:
ClearColorWithDraw(GLubyte color) : mColor(color, color, color, 255) {}
- bool compileAndLink()
+ bool compile()
{
- mProgram =
- CompileProgramParallel(insertRandomString(essl1_shaders::vs::Simple()),
- insertRandomString(essl1_shaders::fs::UniformColor()));
+ mVertexShader =
+ compileShader(GL_VERTEX_SHADER, insertRandomString(essl1_shaders::vs::Simple()));
+ mFragmentShader = compileShader(GL_FRAGMENT_SHADER,
+ insertRandomString(essl1_shaders::fs::UniformColor()));
+ return (mVertexShader != 0 && mFragmentShader != 0);
+ }
+
+ bool isCompileCompleted()
+ {
+ GLint status;
+ glGetShaderiv(mVertexShader, GL_COMPLETION_STATUS_KHR, &status);
+ if (status == GL_TRUE)
+ {
+ glGetShaderiv(mFragmentShader, GL_COMPLETION_STATUS_KHR, &status);
+ return (status == GL_TRUE);
+ }
+ return false;
+ }
+
+ bool link()
+ {
+ mProgram = 0;
+ if (checkShader(mVertexShader) && checkShader(mFragmentShader))
+ {
+ mProgram = glCreateProgram();
+ glAttachShader(mProgram, mVertexShader);
+ glAttachShader(mProgram, mFragmentShader);
+ glLinkProgram(mProgram);
+ }
+ glDeleteShader(mVertexShader);
+ glDeleteShader(mFragmentShader);
return (mProgram != 0);
}
@@ -95,7 +123,47 @@
return ostream.str();
}
+ GLuint compileShader(GLenum type, const std::string &source)
+ {
+ GLuint shader = glCreateShader(type);
+
+ const char *sourceArray[1] = {source.c_str()};
+ glShaderSource(shader, 1, sourceArray, nullptr);
+ glCompileShader(shader);
+ return shader;
+ }
+
+ bool checkShader(GLuint shader)
+ {
+ GLint compileResult;
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
+
+ if (compileResult == 0)
+ {
+ GLint infoLogLength;
+ glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
+
+ // Info log length includes the null terminator, so 1 means that the info log is an
+ // empty string.
+ if (infoLogLength > 1)
+ {
+ std::vector<GLchar> infoLog(infoLogLength);
+ glGetShaderInfoLog(shader, static_cast<GLsizei>(infoLog.size()), nullptr,
+ &infoLog[0]);
+ std::cerr << "shader compilation failed: " << &infoLog[0];
+ }
+ else
+ {
+ std::cerr << "shader compilation failed. <Empty log message>";
+ }
+ std::cerr << std::endl;
+ }
+ return (compileResult == GL_TRUE);
+ }
+
GLColor mColor;
+ GLuint mVertexShader;
+ GLuint mFragmentShader;
GLuint mProgram;
};
};
@@ -118,25 +186,48 @@
{
ANGLE_SKIP_TEST_IF(!ensureParallelShaderCompileExtensionAvailable());
- std::vector<std::unique_ptr<ClearColorWithDraw>> tasks;
+ std::vector<std::unique_ptr<ClearColorWithDraw>> compileTasks;
constexpr int kTaskCount = 32;
for (int i = 0; i < kTaskCount; ++i)
{
std::unique_ptr<ClearColorWithDraw> task(new ClearColorWithDraw(i * 255 / kTaskCount));
- bool isLinking = task->compileAndLink();
- ASSERT_TRUE(isLinking);
- tasks.push_back(std::move(task));
+ bool isCompiling = task->compile();
+ ASSERT_TRUE(isCompiling);
+ compileTasks.push_back(std::move(task));
}
+
constexpr unsigned int kPollInterval = 100;
- while (!tasks.empty())
+
+ std::vector<std::unique_ptr<ClearColorWithDraw>> linkTasks;
+ while (!compileTasks.empty())
{
- for (unsigned int i = 0; i < tasks.size();)
+ for (unsigned int i = 0; i < compileTasks.size();)
{
- auto &task = tasks[i];
+ auto &task = compileTasks[i];
+
+ if (task->isCompileCompleted())
+ {
+ bool isLinking = task->link();
+ ASSERT_TRUE(isLinking);
+ linkTasks.push_back(std::move(task));
+ compileTasks.erase(compileTasks.begin() + i);
+ continue;
+ }
+ ++i;
+ }
+ Sleep(kPollInterval);
+ }
+
+ while (!linkTasks.empty())
+ {
+ for (unsigned int i = 0; i < linkTasks.size();)
+ {
+ auto &task = linkTasks[i];
+
if (task->isLinkCompleted())
{
task->drawAndVerify(this);
- tasks.erase(tasks.begin() + i);
+ linkTasks.erase(linkTasks.begin() + i);
continue;
}
++i;