Commit 2f348d2a by Jamie Madill Committed by Commit Bot

Make gl::Compiler reference-counted.

This is helpful for implementing program binary caching in ANGLE. in order to maintain the current behaviour in Chrome, we will need to defer shader compilation until link time. Since WebGL allows the app layer to enable and disable extensions explicitly, the app can enable or disable an extension between the calls to glCompileShader and glLinkProgram. Then, if we're deferring shader compilation, we will have to preserve the extension settings at the time of the call to compile, not the current settings at the time of link. Making the compiler reference-counted gives us a pretty simple and robust solution. This also changes the Context class to lazily init the shader compiler. Lazy init prevents any unexpected nulls, and also ensures the releaseShaderCompiler does exactly that: just releases the shader compiler, and does not immediately re-initialize it. BUG=angleproject:2044 Change-Id: I0f0eeb4eb94dc4eee238f92482804a0921c77df0 Reviewed-on: https://chromium-review.googlesource.com/522868Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 168d5e80
......@@ -122,12 +122,6 @@ Compiler::Compiler(rx::GLImplFactory *implFactory, const ContextState &state)
Compiler::~Compiler()
{
release();
SafeDelete(mImplementation);
}
Error Compiler::release()
{
if (mFragmentCompiler)
{
sh::Destruct(mFragmentCompiler);
......@@ -161,8 +155,6 @@ Error Compiler::release()
}
mImplementation->release();
return gl::NoError();
}
ShHandle Compiler::getCompilerHandle(GLenum type)
......
......@@ -10,8 +10,9 @@
#ifndef LIBANGLE_COMPILER_H_
#define LIBANGLE_COMPILER_H_
#include "libANGLE/Error.h"
#include "GLSLANG/ShaderLang.h"
#include "libANGLE/Error.h"
#include "libANGLE/RefCountObject.h"
namespace rx
{
......@@ -23,19 +24,17 @@ namespace gl
{
class ContextState;
class Compiler final : angle::NonCopyable
class Compiler final : public RefCountObjectNoID
{
public:
Compiler(rx::GLImplFactory *implFactory, const ContextState &data);
~Compiler();
Error release();
ShHandle getCompilerHandle(GLenum type);
ShShaderOutput getShaderOutputType() const { return mOutputType; }
private:
rx::CompilerImpl *mImplementation;
~Compiler() override;
std::unique_ptr<rx::CompilerImpl> mImplementation;
ShShaderSpec mSpec;
ShShaderOutput mOutputType;
ShBuiltInResources mResources;
......
......@@ -257,7 +257,7 @@ Context::Context(rx::EGLImplFactory *implFactory,
mLimitations,
GetNoError(attribs)),
mImplementation(implFactory->createContext(mState)),
mCompiler(nullptr),
mCompiler(),
mConfig(config),
mClientType(EGL_OPENGL_ES_API),
mHasBeenCurrent(false),
......@@ -361,8 +361,6 @@ Context::Context(rx::EGLImplFactory *implFactory,
bindTransformFeedback(0);
}
mCompiler = new Compiler(mImplementation.get(), mState);
// Initialize dirty bit masks
// TODO(jmadill): additional ES3 state
mTexImageDirtyBits.set(State::DIRTY_BIT_UNPACK_ALIGNMENT);
......@@ -444,8 +442,7 @@ void Context::destroy(egl::Display *display)
SafeDelete(mSurfacelessFramebuffer);
releaseSurface(display);
SafeDelete(mCompiler);
releaseShaderCompiler();
mState.mBuffers->release(this);
mState.mShaderPrograms->release(this);
......@@ -1248,7 +1245,7 @@ Framebuffer *Context::getFramebuffer(GLuint handle) const
return mState.mFramebuffers->getFramebuffer(handle);
}
FenceNV *Context::getFenceNV(unsigned int handle)
FenceNV *Context::getFenceNV(GLuint handle)
{
auto fence = mFenceNVMap.find(handle);
......@@ -1262,7 +1259,7 @@ FenceNV *Context::getFenceNV(unsigned int handle)
}
}
Query *Context::getQuery(unsigned int handle, bool create, GLenum type)
Query *Context::getQuery(GLuint handle, bool create, GLenum type)
{
auto query = mQueryMap.find(handle);
......@@ -1300,7 +1297,11 @@ Texture *Context::getSamplerTexture(unsigned int sampler, GLenum type) const
Compiler *Context::getCompiler() const
{
return mCompiler;
if (mCompiler.get() == nullptr)
{
mCompiler.set(new Compiler(mImplementation.get(), mState));
}
return mCompiler.get();
}
void Context::getBooleanvImpl(GLenum pname, GLboolean *params)
......@@ -2579,9 +2580,8 @@ void Context::requestExtension(const char *name)
updateCaps();
initExtensionStrings();
// Re-create the compiler with the requested extensions enabled.
SafeDelete(mCompiler);
mCompiler = new Compiler(mImplementation.get(), mState);
// Release the shader compiler so it will be re-created with the requested extensions enabled.
releaseShaderCompiler();
// Invalidate all cached completenesses for textures and framebuffer. Some extensions make new
// formats renderable or sampleable.
......@@ -4504,7 +4504,7 @@ void Context::linkProgram(GLuint program)
void Context::releaseShaderCompiler()
{
handleError(mCompiler->release());
mCompiler.set(nullptr);
}
void Context::shaderBinary(GLsizei n,
......
......@@ -818,8 +818,8 @@ class Context final : public ValidationContext
Extensions mExtensions;
Limitations mLimitations;
// Shader compiler
Compiler *mCompiler;
// Shader compiler. Lazily initialized hence the mutable value.
mutable BindingPointer<Compiler> mCompiler;
State mGLState;
......
......@@ -150,6 +150,6 @@ class Shader final : angle::NonCopyable, public LabeledObject
};
bool CompareShaderVar(const sh::ShaderVariable &x, const sh::ShaderVariable &y);
}
} // namespace gl
#endif // LIBANGLE_SHADER_H_
......@@ -711,6 +711,33 @@ TEST_P(GLSLTest, FrontFacingAndVarying)
EXPECT_NE(0u, program);
}
// Test that we can release the shader compiler and still compile things properly.
TEST_P(GLSLTest, ReleaseCompilerThenCompile)
{
const std::string &simpleVS =
"attribute vec4 position; void main() { gl_Position = position; }";
const std::string &simpleFS = "void main() { gl_FragColor = vec4(1, 0, 0, 1); }";
// Draw with the first program.
ANGLE_GL_PROGRAM(program1, simpleVS, simpleFS);
drawQuad(program1, "position", 0.5f);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
// Clear and release shader compiler.
glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
glReleaseShaderCompiler();
ASSERT_GL_NO_ERROR();
// Draw with a second program.
ANGLE_GL_PROGRAM(program2, simpleVS, simpleFS);
drawQuad(program2, "position", 0.5f);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
}
// Verify that linking shaders declaring different shading language versions fails.
TEST_P(GLSLTest_ES3, VersionMismatch)
{
......
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