Commit a155bacf by jchen10 Committed by Commit Bot

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: 's avatarJamie Madill <jmadill@chromium.org>
parent 4d45e7dc
...@@ -19,9 +19,8 @@ namespace gl ...@@ -19,9 +19,8 @@ namespace gl
namespace namespace
{ {
// Global count of active shader compiler handles. Needed to know when to call sh::Initialize and // To know when to call sh::Initialize and sh::Finalize.
// sh::Finalize. size_t gActiveCompilers = 0;
size_t activeCompilerHandles = 0;
ShShaderSpec SelectShaderSpec(GLint majorVersion, GLint minorVersion, bool isWebGL) ShShaderSpec SelectShaderSpec(GLint majorVersion, GLint minorVersion, bool isWebGL)
{ {
...@@ -54,8 +53,7 @@ Compiler::Compiler(rx::GLImplFactory *implFactory, const ContextState &state) ...@@ -54,8 +53,7 @@ Compiler::Compiler(rx::GLImplFactory *implFactory, const ContextState &state)
state.getClientMinorVersion(), state.getClientMinorVersion(),
state.getExtensions().webglCompatibility)), state.getExtensions().webglCompatibility)),
mOutputType(mImplementation->getTranslatorOutputType()), mOutputType(mImplementation->getTranslatorOutputType()),
mResources(), mResources()
mShaderCompilers({})
{ {
ASSERT(state.getClientMajorVersion() == 1 || state.getClientMajorVersion() == 2 || ASSERT(state.getClientMajorVersion() == 1 || state.getClientMajorVersion() == 2 ||
state.getClientMajorVersion() == 3); state.getClientMajorVersion() == 3);
...@@ -63,6 +61,12 @@ Compiler::Compiler(rx::GLImplFactory *implFactory, const ContextState &state) ...@@ -63,6 +61,12 @@ Compiler::Compiler(rx::GLImplFactory *implFactory, const ContextState &state)
const gl::Caps &caps = state.getCaps(); const gl::Caps &caps = state.getCaps();
const gl::Extensions &extensions = state.getExtensions(); const gl::Extensions &extensions = state.getExtensions();
if (gActiveCompilers == 0)
{
sh::Initialize();
}
++gActiveCompilers;
sh::InitBuiltInResources(&mResources); sh::InitBuiltInResources(&mResources);
mResources.MaxVertexAttribs = caps.maxVertexAttributes; mResources.MaxVertexAttribs = caps.maxVertexAttributes;
mResources.MaxVertexUniformVectors = caps.maxVertexUniformVectors; mResources.MaxVertexUniformVectors = caps.maxVertexUniformVectors;
...@@ -161,50 +165,111 @@ Compiler::Compiler(rx::GLImplFactory *implFactory, const ContextState &state) ...@@ -161,50 +165,111 @@ Compiler::Compiler(rx::GLImplFactory *implFactory, const ContextState &state)
Compiler::~Compiler() Compiler::~Compiler()
{ {
for (ShaderType shaderType : AllShaderTypes()) for (auto &pool : mPools)
{ {
ShHandle compilerHandle = mShaderCompilers[shaderType]; for (ShCompilerInstance &instance : pool)
if (compilerHandle)
{ {
sh::Destruct(compilerHandle); instance.destroy();
mShaderCompilers[shaderType] = nullptr;
ASSERT(activeCompilerHandles > 0);
activeCompilerHandles--;
} }
} }
--gActiveCompilers;
if (activeCompilerHandles == 0) if (gActiveCompilers == 0)
{ {
sh::Finalize(); sh::Finalize();
} }
ANGLE_SWALLOW_ERR(mImplementation->release()); ANGLE_SWALLOW_ERR(mImplementation->release());
} }
ShHandle Compiler::getCompilerHandle(ShaderType type) ShCompilerInstance Compiler::getInstance(ShaderType type)
{ {
ASSERT(type != ShaderType::InvalidEnum); ASSERT(type != ShaderType::InvalidEnum);
ShHandle *compiler = &mShaderCompilers[type]; auto &pool = mPools[type];
if (pool.empty())
{
ShHandle handle = sh::ConstructCompiler(ToGLenum(type), mSpec, mOutputType, &mResources);
ASSERT(handle);
return ShCompilerInstance(handle, mOutputType, type);
}
else
{
ShCompilerInstance instance = std::move(pool.back());
pool.pop_back();
return instance;
}
}
if (!(*compiler)) void Compiler::putInstance(ShCompilerInstance &&instance)
{
static constexpr size_t kMaxPoolSize = 32;
auto &pool = mPools[instance.getShaderType()];
if (pool.size() < kMaxPoolSize)
{ {
if (activeCompilerHandles == 0) pool.push_back(std::move(instance));
{ }
sh::Initialize(); else
} {
instance.destroy();
}
}
*compiler = sh::ConstructCompiler(ToGLenum(type), mSpec, mOutputType, &mResources); ShCompilerInstance::ShCompilerInstance() : mHandle(nullptr)
ASSERT(*compiler); {
activeCompilerHandles++; }
ShCompilerInstance::ShCompilerInstance(ShHandle handle,
ShShaderOutput outputType,
ShaderType shaderType)
: mHandle(handle), mOutputType(outputType), mShaderType(shaderType)
{
}
ShCompilerInstance::~ShCompilerInstance()
{
ASSERT(mHandle == nullptr);
}
void ShCompilerInstance::destroy()
{
if (mHandle != nullptr)
{
sh::Destruct(mHandle);
mHandle = nullptr;
} }
}
ShCompilerInstance::ShCompilerInstance(ShCompilerInstance &&other)
: mHandle(other.mHandle), mOutputType(other.mOutputType), mShaderType(other.mShaderType)
{
other.mHandle = nullptr;
}
return *compiler; ShCompilerInstance &ShCompilerInstance::operator=(ShCompilerInstance &&other)
{
mHandle = other.mHandle;
mOutputType = other.mOutputType;
mShaderType = other.mShaderType;
other.mHandle = nullptr;
return *this;
}
ShHandle ShCompilerInstance::getHandle()
{
return mHandle;
}
ShaderType ShCompilerInstance::getShaderType() const
{
return mShaderType;
}
const std::string &ShCompilerInstance::getBuiltinResourcesString()
{
return sh::GetBuiltInResourcesString(mHandle);
} }
const std::string &Compiler::getBuiltinResourcesString(ShaderType type) ShShaderOutput ShCompilerInstance::getShaderOutputType() const
{ {
return sh::GetBuiltInResourcesString(getCompilerHandle(type)); return mOutputType;
} }
} // namespace gl } // namespace gl
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
#ifndef LIBANGLE_COMPILER_H_ #ifndef LIBANGLE_COMPILER_H_
#define LIBANGLE_COMPILER_H_ #define LIBANGLE_COMPILER_H_
#include <vector>
#include "GLSLANG/ShaderLang.h" #include "GLSLANG/ShaderLang.h"
#include "common/PackedEnums.h" #include "common/PackedEnums.h"
#include "libANGLE/Error.h" #include "libANGLE/Error.h"
...@@ -24,15 +26,16 @@ class GLImplFactory; ...@@ -24,15 +26,16 @@ class GLImplFactory;
namespace gl namespace gl
{ {
class ContextState; class ContextState;
class ShCompilerInstance;
class Compiler final : public RefCountObjectNoID class Compiler final : public RefCountObjectNoID
{ {
public: public:
Compiler(rx::GLImplFactory *implFactory, const ContextState &data); Compiler(rx::GLImplFactory *implFactory, const ContextState &data);
ShHandle getCompilerHandle(ShaderType shaderType); ShCompilerInstance getInstance(ShaderType shaderType);
void putInstance(ShCompilerInstance &&instance);
ShShaderOutput getShaderOutputType() const { return mOutputType; } ShShaderOutput getShaderOutputType() const { return mOutputType; }
const std::string &getBuiltinResourcesString(ShaderType type);
private: private:
~Compiler() override; ~Compiler() override;
...@@ -40,8 +43,29 @@ class Compiler final : public RefCountObjectNoID ...@@ -40,8 +43,29 @@ class Compiler final : public RefCountObjectNoID
ShShaderSpec mSpec; ShShaderSpec mSpec;
ShShaderOutput mOutputType; ShShaderOutput mOutputType;
ShBuiltInResources mResources; ShBuiltInResources mResources;
ShaderMap<std::vector<ShCompilerInstance>> mPools;
};
class ShCompilerInstance final : public angle::NonCopyable
{
public:
ShCompilerInstance();
ShCompilerInstance(ShHandle handle, ShShaderOutput outputType, ShaderType shaderType);
~ShCompilerInstance();
void destroy();
ShaderMap<ShHandle> mShaderCompilers; ShCompilerInstance(ShCompilerInstance &&other);
ShCompilerInstance &operator=(ShCompilerInstance &&other);
ShHandle getHandle();
ShaderType getShaderType() const;
const std::string &getBuiltinResourcesString();
ShShaderOutput getShaderOutputType() const;
private:
ShHandle mHandle;
ShShaderOutput mOutputType;
ShaderType mShaderType;
}; };
} // namespace gl } // namespace gl
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "libANGLE/Shader.h" #include "libANGLE/Shader.h"
#include <functional>
#include <sstream> #include <sstream>
#include "GLSLANG/ShaderLang.h" #include "GLSLANG/ShaderLang.h"
...@@ -19,6 +20,7 @@ ...@@ -19,6 +20,7 @@
#include "libANGLE/Constants.h" #include "libANGLE/Constants.h"
#include "libANGLE/Context.h" #include "libANGLE/Context.h"
#include "libANGLE/ResourceManager.h" #include "libANGLE/ResourceManager.h"
#include "libANGLE/WorkerThread.h"
#include "libANGLE/renderer/GLImplFactory.h" #include "libANGLE/renderer/GLImplFactory.h"
#include "libANGLE/renderer/ShaderImpl.h" #include "libANGLE/renderer/ShaderImpl.h"
...@@ -96,6 +98,50 @@ const char *GetShaderTypeString(ShaderType type) ...@@ -96,6 +98,50 @@ const char *GetShaderTypeString(ShaderType type)
} }
} }
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) ShaderState::ShaderState(ShaderType shaderType)
: mLabel(), : mLabel(),
mShaderType(shaderType), mShaderType(shaderType),
...@@ -131,6 +177,7 @@ Shader::Shader(ShaderProgramManager *manager, ...@@ -131,6 +177,7 @@ Shader::Shader(ShaderProgramManager *manager,
void Shader::onDestroy(const gl::Context *context) void Shader::onDestroy(const gl::Context *context)
{ {
resolveCompile();
mImplementation->destroy(); mImplementation->destroy();
mBoundCompiler.set(context, nullptr); mBoundCompiler.set(context, nullptr);
mImplementation.reset(nullptr); mImplementation.reset(nullptr);
...@@ -284,6 +331,8 @@ void Shader::getTranslatedSourceWithDebugInfo(GLsizei bufSize, GLsizei *length, ...@@ -284,6 +331,8 @@ void Shader::getTranslatedSourceWithDebugInfo(GLsizei bufSize, GLsizei *length,
void Shader::compile(const Context *context) void Shader::compile(const Context *context)
{ {
resolveCompile();
mState.mTranslatedSource.clear(); mState.mTranslatedSource.clear();
mInfoLog.clear(); mInfoLog.clear();
mState.mShaderVersion = 100; mState.mShaderVersion = 100;
...@@ -307,19 +356,19 @@ void Shader::compile(const Context *context) ...@@ -307,19 +356,19 @@ void Shader::compile(const Context *context)
// can change before the link call or another call that resolves the compile. // can change before the link call or another call that resolves the compile.
std::stringstream sourceStream; std::stringstream sourceStream;
std::string sourcePath;
mLastCompileOptions = mImplementation->prepareSourceAndReturnOptions(context, &sourceStream, ShCompileOptions options =
&mLastCompiledSourcePath); mImplementation->prepareSourceAndReturnOptions(context, &sourceStream, &sourcePath);
mLastCompileOptions |= (SH_OBJECT_CODE | SH_VARIABLES); options |= (SH_OBJECT_CODE | SH_VARIABLES);
mLastCompiledSource = sourceStream.str(); auto source = sourceStream.str();
// Add default options to WebGL shaders to prevent unexpected behavior during compilation. // Add default options to WebGL shaders to prevent unexpected behavior during compilation.
if (context->getExtensions().webglCompatibility) if (context->getExtensions().webglCompatibility)
{ {
mLastCompileOptions |= SH_INIT_GL_POSITION; options |= SH_INIT_GL_POSITION;
mLastCompileOptions |= SH_LIMIT_CALL_STACK_DEPTH; options |= SH_LIMIT_CALL_STACK_DEPTH;
mLastCompileOptions |= SH_LIMIT_EXPRESSION_COMPLEXITY; options |= SH_LIMIT_EXPRESSION_COMPLEXITY;
mLastCompileOptions |= SH_ENFORCE_PACKING_RESTRICTIONS; options |= SH_ENFORCE_PACKING_RESTRICTIONS;
} }
// Some targets (eg D3D11 Feature Level 9_3 and below) do not support non-constant loop indexes // Some targets (eg D3D11 Feature Level 9_3 and below) do not support non-constant loop indexes
...@@ -327,10 +376,21 @@ void Shader::compile(const Context *context) ...@@ -327,10 +376,21 @@ void Shader::compile(const Context *context)
// instruct the compiler to pre-validate. // instruct the compiler to pre-validate.
if (mRendererLimitations.shadersRequireIndexedLoopValidation) if (mRendererLimitations.shadersRequireIndexedLoopValidation)
{ {
mLastCompileOptions |= SH_VALIDATE_LOOP_INDEXING; options |= SH_VALIDATE_LOOP_INDEXING;
} }
mCurrentMaxComputeWorkGroupInvocations = context->getCaps().maxComputeWorkGroupInvocations; 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() void Shader::resolveCompile()
...@@ -340,19 +400,21 @@ void Shader::resolveCompile() ...@@ -340,19 +400,21 @@ void Shader::resolveCompile()
return; return;
} }
ASSERT(mBoundCompiler.get()); ASSERT(mCompileEvent.get());
ShHandle compilerHandle = mBoundCompiler->getCompilerHandle(mState.mShaderType); ASSERT(mCompileTask.get());
std::vector<const char *> srcStrings; mCompileEvent->wait();
if (!mLastCompiledSourcePath.empty()) mCompileEvent.reset();
{ mWorkerPool.reset();
srcStrings.push_back(mLastCompiledSourcePath.c_str());
} bool compiled = mCompileTask->getResult();
mCompileTask.reset();
srcStrings.push_back(mLastCompiledSource.c_str()); ScopedExit exit([this]() { mBoundCompiler->putInstance(std::move(mShCompilerInstance)); });
if (!sh::Compile(compilerHandle, &srcStrings[0], srcStrings.size(), mLastCompileOptions)) ShHandle compilerHandle = mShCompilerInstance.getHandle();
if (!compiled)
{ {
mInfoLog = sh::GetInfoLog(compilerHandle); mInfoLog = sh::GetInfoLog(compilerHandle);
WARN() << std::endl << mInfoLog; WARN() << std::endl << mInfoLog;
...@@ -469,7 +531,7 @@ void Shader::resolveCompile() ...@@ -469,7 +531,7 @@ void Shader::resolveCompile()
ASSERT(!mState.mTranslatedSource.empty()); 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; mState.mCompileStatus = success ? CompileStatus::COMPILED : CompileStatus::NOT_COMPILED;
} }
...@@ -509,6 +571,11 @@ bool Shader::isCompiled() ...@@ -509,6 +571,11 @@ bool Shader::isCompiled()
return mState.mCompileStatus == CompileStatus::COMPILED; return mState.mCompileStatus == CompileStatus::COMPILED;
} }
bool Shader::isCompleted()
{
return (!mState.compilePending() || mCompileEvent->isReady());
}
int Shader::getShaderVersion() int Shader::getShaderVersion()
{ {
resolveCompile(); resolveCompile();
...@@ -640,8 +707,7 @@ Optional<GLint> Shader::getGeometryShaderMaxVertices() ...@@ -640,8 +707,7 @@ Optional<GLint> Shader::getGeometryShaderMaxVertices()
const std::string &Shader::getCompilerResourcesString() const const std::string &Shader::getCompilerResourcesString() const
{ {
ASSERT(mBoundCompiler.get()); return mCompilerResourcesString;
return mBoundCompiler->getBuiltinResourcesString(mState.mShaderType);
} }
} // namespace gl } // namespace gl
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "common/Optional.h" #include "common/Optional.h"
#include "common/angleutils.h" #include "common/angleutils.h"
#include "libANGLE/Compiler.h"
#include "libANGLE/Debug.h" #include "libANGLE/Debug.h"
#include "libANGLE/angletypes.h" #include "libANGLE/angletypes.h"
...@@ -32,13 +33,19 @@ class ShaderImpl; ...@@ -32,13 +33,19 @@ class ShaderImpl;
class ShaderSh; class ShaderSh;
} }
namespace angle
{
class WaitableEvent;
class WorkerThreadPool;
} // namespace angle
namespace gl namespace gl
{ {
class Compiler;
class ContextState; class ContextState;
struct Limitations; struct Limitations;
class ShaderProgramManager; class ShaderProgramManager;
class Context; class Context;
class CompileTask;
// We defer the compile until link time, or until properties are queried. // We defer the compile until link time, or until properties are queried.
enum class CompileStatus enum class CompileStatus
...@@ -146,6 +153,7 @@ class Shader final : angle::NonCopyable, public LabeledObject ...@@ -146,6 +153,7 @@ class Shader final : angle::NonCopyable, public LabeledObject
void compile(const Context *context); void compile(const Context *context);
bool isCompiled(); bool isCompiled();
bool isCompleted();
void addRef(); void addRef();
void release(const Context *context); void release(const Context *context);
...@@ -190,9 +198,6 @@ class Shader final : angle::NonCopyable, public LabeledObject ...@@ -190,9 +198,6 @@ class Shader final : angle::NonCopyable, public LabeledObject
void resolveCompile(); void resolveCompile();
ShaderState mState; ShaderState mState;
std::string mLastCompiledSource;
std::string mLastCompiledSourcePath;
ShCompileOptions mLastCompileOptions;
std::unique_ptr<rx::ShaderImpl> mImplementation; std::unique_ptr<rx::ShaderImpl> mImplementation;
const gl::Limitations &mRendererLimitations; const gl::Limitations &mRendererLimitations;
const GLuint mHandle; const GLuint mHandle;
...@@ -203,6 +208,11 @@ class Shader final : angle::NonCopyable, public LabeledObject ...@@ -203,6 +208,11 @@ class Shader final : angle::NonCopyable, public LabeledObject
// We keep a reference to the translator in order to defer compiles while preserving settings. // We keep a reference to the translator in order to defer compiles while preserving settings.
BindingPointer<Compiler> mBoundCompiler; BindingPointer<Compiler> mBoundCompiler;
ShCompilerInstance mShCompilerInstance;
std::shared_ptr<CompileTask> mCompileTask;
std::shared_ptr<angle::WorkerThreadPool> mWorkerPool;
std::shared_ptr<angle::WaitableEvent> mCompileEvent;
std::string mCompilerResourcesString;
ShaderProgramManager *mResourceManager; ShaderProgramManager *mResourceManager;
......
...@@ -1167,9 +1167,7 @@ void QueryShaderiv(Shader *shader, GLenum pname, GLint *params) ...@@ -1167,9 +1167,7 @@ void QueryShaderiv(Shader *shader, GLenum pname, GLint *params)
*params = shader->isCompiled() ? GL_TRUE : GL_FALSE; *params = shader->isCompiled() ? GL_TRUE : GL_FALSE;
return; return;
case GL_COMPLETION_STATUS_KHR: case GL_COMPLETION_STATUS_KHR:
// TODO(jie.a.chen@intel.com): Parallelize shader compilation. *params = shader->isCompleted() ? GL_TRUE : GL_FALSE;
// http://crbug.com/849576
*params = shader->isCompiled() ? GL_TRUE : GL_FALSE;
return; return;
case GL_INFO_LOG_LENGTH: case GL_INFO_LOG_LENGTH:
*params = shader->getInfoLogLength(); *params = shader->getInfoLogLength();
......
...@@ -28,7 +28,7 @@ class ShaderImpl : angle::NonCopyable ...@@ -28,7 +28,7 @@ class ShaderImpl : angle::NonCopyable
std::stringstream *sourceStream, std::stringstream *sourceStream,
std::string *sourcePath) = 0; std::string *sourcePath) = 0;
// Returns success for compiling on the driver. Returns success. // Returns success for compiling on the driver. Returns success.
virtual bool postTranslateCompile(gl::Compiler *compiler, std::string *infoLog) = 0; virtual bool postTranslateCompile(gl::ShCompilerInstance *compiler, std::string *infoLog) = 0;
virtual std::string getDebugInfo() const = 0; virtual std::string getDebugInfo() const = 0;
......
...@@ -174,7 +174,7 @@ const std::map<std::string, unsigned int> &GetUniformRegisterMap( ...@@ -174,7 +174,7 @@ const std::map<std::string, unsigned int> &GetUniformRegisterMap(
return *uniformRegisterMap; return *uniformRegisterMap;
} }
bool ShaderD3D::postTranslateCompile(gl::Compiler *compiler, std::string *infoLog) bool ShaderD3D::postTranslateCompile(gl::ShCompilerInstance *compiler, std::string *infoLog)
{ {
// TODO(jmadill): We shouldn't need to cache this. // TODO(jmadill): We shouldn't need to cache this.
mCompilerOutputType = compiler->getShaderOutputType(); mCompilerOutputType = compiler->getShaderOutputType();
...@@ -199,7 +199,7 @@ bool ShaderD3D::postTranslateCompile(gl::Compiler *compiler, std::string *infoLo ...@@ -199,7 +199,7 @@ bool ShaderD3D::postTranslateCompile(gl::Compiler *compiler, std::string *infoLo
mRequiresIEEEStrictCompiling = mRequiresIEEEStrictCompiling =
translatedSource.find("ANGLE_REQUIRES_IEEE_STRICT_COMPILING") != std::string::npos; translatedSource.find("ANGLE_REQUIRES_IEEE_STRICT_COMPILING") != std::string::npos;
ShHandle compilerHandle = compiler->getCompilerHandle(mData.getShaderType()); ShHandle compilerHandle = compiler->getHandle();
mUniformRegisterMap = GetUniformRegisterMap(sh::GetUniformRegisterMap(compilerHandle)); mUniformRegisterMap = GetUniformRegisterMap(sh::GetUniformRegisterMap(compilerHandle));
......
...@@ -42,7 +42,7 @@ class ShaderD3D : public ShaderImpl ...@@ -42,7 +42,7 @@ class ShaderD3D : public ShaderImpl
ShCompileOptions prepareSourceAndReturnOptions(const gl::Context *context, ShCompileOptions prepareSourceAndReturnOptions(const gl::Context *context,
std::stringstream *sourceStream, std::stringstream *sourceStream,
std::string *sourcePath) override; std::string *sourcePath) override;
bool postTranslateCompile(gl::Compiler *compiler, std::string *infoLog) override; bool postTranslateCompile(gl::ShCompilerInstance *compiler, std::string *infoLog) override;
std::string getDebugInfo() const override; std::string getDebugInfo() const override;
// D3D-specific methods // D3D-specific methods
......
...@@ -142,7 +142,7 @@ ShCompileOptions ShaderGL::prepareSourceAndReturnOptions(const gl::Context *cont ...@@ -142,7 +142,7 @@ ShCompileOptions ShaderGL::prepareSourceAndReturnOptions(const gl::Context *cont
return options; return options;
} }
bool ShaderGL::postTranslateCompile(gl::Compiler *compiler, std::string *infoLog) bool ShaderGL::postTranslateCompile(gl::ShCompilerInstance *compiler, std::string *infoLog)
{ {
// Translate the ESSL into GLSL // Translate the ESSL into GLSL
const char *translatedSourceCString = mData.getTranslatedSource().c_str(); const char *translatedSourceCString = mData.getTranslatedSource().c_str();
......
...@@ -32,7 +32,7 @@ class ShaderGL : public ShaderImpl ...@@ -32,7 +32,7 @@ class ShaderGL : public ShaderImpl
ShCompileOptions prepareSourceAndReturnOptions(const gl::Context *context, ShCompileOptions prepareSourceAndReturnOptions(const gl::Context *context,
std::stringstream *sourceStream, std::stringstream *sourceStream,
std::string *sourcePath) override; std::string *sourcePath) override;
bool postTranslateCompile(gl::Compiler *compiler, std::string *infoLog) override; bool postTranslateCompile(gl::ShCompilerInstance *compiler, std::string *infoLog) override;
std::string getDebugInfo() const override; std::string getDebugInfo() const override;
GLuint getShaderID() const; GLuint getShaderID() const;
......
...@@ -30,7 +30,7 @@ ShCompileOptions ShaderNULL::prepareSourceAndReturnOptions(const gl::Context *co ...@@ -30,7 +30,7 @@ ShCompileOptions ShaderNULL::prepareSourceAndReturnOptions(const gl::Context *co
return 0; return 0;
} }
bool ShaderNULL::postTranslateCompile(gl::Compiler *compiler, std::string *infoLog) bool ShaderNULL::postTranslateCompile(gl::ShCompilerInstance *compiler, std::string *infoLog)
{ {
return true; return true;
} }
......
...@@ -26,7 +26,7 @@ class ShaderNULL : public ShaderImpl ...@@ -26,7 +26,7 @@ class ShaderNULL : public ShaderImpl
std::stringstream *sourceStream, std::stringstream *sourceStream,
std::string *sourcePath) override; std::string *sourcePath) override;
// Returns success for compiling on the driver. Returns success. // Returns success for compiling on the driver. Returns success.
bool postTranslateCompile(gl::Compiler *compiler, std::string *infoLog) override; bool postTranslateCompile(gl::ShCompilerInstance *compiler, std::string *infoLog) override;
std::string getDebugInfo() const override; std::string getDebugInfo() const override;
}; };
......
...@@ -30,7 +30,7 @@ ShCompileOptions ShaderVk::prepareSourceAndReturnOptions(const gl::Context *cont ...@@ -30,7 +30,7 @@ ShCompileOptions ShaderVk::prepareSourceAndReturnOptions(const gl::Context *cont
return SH_INITIALIZE_UNINITIALIZED_LOCALS; return SH_INITIALIZE_UNINITIALIZED_LOCALS;
} }
bool ShaderVk::postTranslateCompile(gl::Compiler *compiler, std::string *infoLog) bool ShaderVk::postTranslateCompile(gl::ShCompilerInstance *compiler, std::string *infoLog)
{ {
// No work to do here. // No work to do here.
return true; return true;
......
...@@ -26,7 +26,7 @@ class ShaderVk : public ShaderImpl ...@@ -26,7 +26,7 @@ class ShaderVk : public ShaderImpl
std::stringstream *sourceStream, std::stringstream *sourceStream,
std::string *sourcePath) override; std::string *sourcePath) override;
// Returns success for compiling on the driver. Returns success. // Returns success for compiling on the driver. Returns success.
bool postTranslateCompile(gl::Compiler *compiler, std::string *infoLog) override; bool postTranslateCompile(gl::ShCompilerInstance *compiler, std::string *infoLog) override;
std::string getDebugInfo() const override; std::string getDebugInfo() const override;
}; };
......
...@@ -51,11 +51,39 @@ class ParallelShaderCompileTest : public ANGLETest ...@@ -51,11 +51,39 @@ class ParallelShaderCompileTest : public ANGLETest
public: public:
ClearColorWithDraw(GLubyte color) : mColor(color, color, color, 255) {} ClearColorWithDraw(GLubyte color) : mColor(color, color, color, 255) {}
bool compileAndLink() bool compile()
{ {
mProgram = mVertexShader =
CompileProgramParallel(insertRandomString(essl1_shaders::vs::Simple()), compileShader(GL_VERTEX_SHADER, insertRandomString(essl1_shaders::vs::Simple()));
insertRandomString(essl1_shaders::fs::UniformColor())); 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); return (mProgram != 0);
} }
...@@ -95,7 +123,47 @@ class ParallelShaderCompileTest : public ANGLETest ...@@ -95,7 +123,47 @@ class ParallelShaderCompileTest : public ANGLETest
return ostream.str(); 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; GLColor mColor;
GLuint mVertexShader;
GLuint mFragmentShader;
GLuint mProgram; GLuint mProgram;
}; };
}; };
...@@ -118,25 +186,48 @@ TEST_P(ParallelShaderCompileTest, LinkAndDrawManyPrograms) ...@@ -118,25 +186,48 @@ TEST_P(ParallelShaderCompileTest, LinkAndDrawManyPrograms)
{ {
ANGLE_SKIP_TEST_IF(!ensureParallelShaderCompileExtensionAvailable()); ANGLE_SKIP_TEST_IF(!ensureParallelShaderCompileExtensionAvailable());
std::vector<std::unique_ptr<ClearColorWithDraw>> tasks; std::vector<std::unique_ptr<ClearColorWithDraw>> compileTasks;
constexpr int kTaskCount = 32; constexpr int kTaskCount = 32;
for (int i = 0; i < kTaskCount; ++i) for (int i = 0; i < kTaskCount; ++i)
{ {
std::unique_ptr<ClearColorWithDraw> task(new ClearColorWithDraw(i * 255 / kTaskCount)); std::unique_ptr<ClearColorWithDraw> task(new ClearColorWithDraw(i * 255 / kTaskCount));
bool isLinking = task->compileAndLink(); bool isCompiling = task->compile();
ASSERT_TRUE(isLinking); ASSERT_TRUE(isCompiling);
tasks.push_back(std::move(task)); compileTasks.push_back(std::move(task));
} }
constexpr unsigned int kPollInterval = 100; constexpr unsigned int kPollInterval = 100;
while (!tasks.empty())
std::vector<std::unique_ptr<ClearColorWithDraw>> linkTasks;
while (!compileTasks.empty())
{
for (unsigned int i = 0; i < compileTasks.size();)
{
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 < tasks.size();) for (unsigned int i = 0; i < linkTasks.size();)
{ {
auto &task = tasks[i]; auto &task = linkTasks[i];
if (task->isLinkCompleted()) if (task->isLinkCompleted())
{ {
task->drawAndVerify(this); task->drawAndVerify(this);
tasks.erase(tasks.begin() + i); linkTasks.erase(linkTasks.begin() + i);
continue; continue;
} }
++i; ++i;
......
...@@ -205,12 +205,6 @@ GLuint CompileProgram(const std::string &vsSource, const std::string &fsSource) ...@@ -205,12 +205,6 @@ GLuint CompileProgram(const std::string &vsSource, const std::string &fsSource)
return CompileProgramWithGS(vsSource, "", fsSource); return CompileProgramWithGS(vsSource, "", fsSource);
} }
GLuint CompileProgramParallel(const std::string &vsSource, const std::string &fsSource)
{
std::vector<std::string> emptyVector;
return CompileAndLinkProgram(vsSource, "", fsSource, emptyVector, GL_NONE);
}
GLuint CompileProgramWithGS(const std::string &vsSource, GLuint CompileProgramWithGS(const std::string &vsSource,
const std::string &gsSource, const std::string &gsSource,
const std::string &fsSource) const std::string &fsSource)
......
...@@ -34,8 +34,6 @@ CompileProgramWithGSAndTransformFeedback(const std::string &vsSource, ...@@ -34,8 +34,6 @@ CompileProgramWithGSAndTransformFeedback(const std::string &vsSource,
const std::vector<std::string> &transformFeedbackVaryings, const std::vector<std::string> &transformFeedbackVaryings,
GLenum bufferMode); GLenum bufferMode);
ANGLE_EXPORT GLuint CompileProgram(const std::string &vsSource, const std::string &fsSource); ANGLE_EXPORT GLuint CompileProgram(const std::string &vsSource, const std::string &fsSource);
ANGLE_EXPORT GLuint CompileProgramParallel(const std::string &vsSource,
const std::string &fsSource);
ANGLE_EXPORT GLuint CompileProgramWithGS(const std::string &vsSource, ANGLE_EXPORT GLuint CompileProgramWithGS(const std::string &vsSource,
const std::string &gsSource, const std::string &gsSource,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment