Edit

kc3-lang/angle/src/libANGLE/Shader.h

Branch :

  • Show log

    Commit

  • Author : Shahbaz Youssefi
    Date : 2023-08-17 15:29:24
    Hash : f3c1de36
    Message : Make shader recompile while parallel linking safe Prior to this change, Program* objects held references to Shader* objects. This poses a problem where a shader recompile can race with a program link, if the program link is done in parallel. As a result, a good chunk of the link job is done serially and under the share group lock. After this change, that is no longer a problem, and most of the link can be made lockless/parallelized. This change separates out the "compiled state" from the rest of the shader state. This was already done for the front-end state (for the sake of caching), but is also now done for the backends that need it. The compiled state in turn is placed in a shared_ptr, and is shared with the program. When a shader is compiled, its own shared_ptr is replaced with a new object, leaving all programs currently compiling unaffected and using the previous compilation results. Once a program is linked, its references to compiled shader states is updated. Bug: angleproject:8297 Change-Id: Iff7094a37088fbad99c6241f1c48b0bd4c820eb2 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4791065 Reviewed-by: Geoff Lang <geofflang@chromium.org> Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: Charlie Lao <cclao@google.com>

  • src/libANGLE/Shader.h
  • //
    // Copyright 2002 The ANGLE Project Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    //
    
    // Shader.h: Defines the abstract gl::Shader class and its concrete derived
    // classes VertexShader and FragmentShader. Implements GL shader objects and
    // related functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section
    // 3.8 page 84.
    
    #ifndef LIBANGLE_SHADER_H_
    #define LIBANGLE_SHADER_H_
    
    #include <list>
    #include <memory>
    #include <string>
    #include <vector>
    
    #include <GLSLANG/ShaderLang.h>
    #include "angle_gl.h"
    
    #include "common/BinaryStream.h"
    #include "common/CompiledShaderState.h"
    #include "common/MemoryBuffer.h"
    #include "common/Optional.h"
    #include "common/angleutils.h"
    #include "libANGLE/BlobCache.h"
    #include "libANGLE/Caps.h"
    #include "libANGLE/Compiler.h"
    #include "libANGLE/Debug.h"
    #include "libANGLE/angletypes.h"
    
    namespace rx
    {
    class GLImplFactory;
    class ShaderImpl;
    class ShaderSh;
    class WaitableCompileEvent;
    }  // namespace rx
    
    namespace angle
    {
    class WaitableEvent;
    class WorkerThreadPool;
    }  // namespace angle
    
    namespace gl
    {
    class CompileTask;
    class Context;
    class ShaderProgramManager;
    class State;
    class BinaryInputStream;
    class BinaryOutputStream;
    
    // We defer the compile until link time, or until properties are queried.
    enum class CompileStatus
    {
        // Compilation never done, or has failed.
        NOT_COMPILED,
        // Compile is in progress.
        COMPILE_REQUESTED,
        // Compilation job is done, but is being resolved.  This enum value is there to allow access to
        // compiled state during resolve without triggering threading-related assertions (which ensure
        // no compile job is in progress).
        IS_RESOLVING,
        // Compilation was successful.
        COMPILED,
    };
    
    class ShaderState final : angle::NonCopyable
    {
      public:
        ShaderState(ShaderType shaderType);
        ~ShaderState();
    
        const std::string &getLabel() const { return mLabel; }
    
        const std::string &getSource() const { return mSource; }
        bool compilePending() const { return mCompileStatus == CompileStatus::COMPILE_REQUESTED; }
        CompileStatus getCompileStatus() const { return mCompileStatus; }
    
        ShaderType getShaderType() const { return mCompiledState->shaderType; }
    
        const SharedCompiledShaderState &getCompiledState() const
        {
            ASSERT(!compilePending());
            return mCompiledState;
        }
    
      private:
        friend class Shader;
    
        std::string mLabel;
        std::string mSource;
        size_t mSourceHash = 0;
    
        SharedCompiledShaderState mCompiledState;
    
        // Indicates if this shader has been successfully compiled
        CompileStatus mCompileStatus = CompileStatus::NOT_COMPILED;
    };
    
    class Shader final : angle::NonCopyable, public LabeledObject
    {
      public:
        Shader(ShaderProgramManager *manager,
               rx::GLImplFactory *implFactory,
               const gl::Limitations &rendererLimitations,
               ShaderType type,
               ShaderProgramID handle);
    
        void onDestroy(const Context *context);
    
        angle::Result setLabel(const Context *context, const std::string &label) override;
        const std::string &getLabel() const override;
    
        ShaderType getType() const { return mState.getShaderType(); }
        ShaderProgramID getHandle() const;
    
        rx::ShaderImpl *getImplementation() const { return mImplementation.get(); }
    
        void setSource(const Context *context,
                       GLsizei count,
                       const char *const *string,
                       const GLint *length);
        int getInfoLogLength(const Context *context);
        void getInfoLog(const Context *context, GLsizei bufSize, GLsizei *length, char *infoLog);
        std::string getInfoLogString() const { return mInfoLog; }
        int getSourceLength() const;
        const std::string &getSourceString() const { return mState.getSource(); }
        void getSource(GLsizei bufSize, GLsizei *length, char *buffer) const;
        int getTranslatedSourceLength(const Context *context);
        int getTranslatedSourceWithDebugInfoLength(const Context *context);
        const std::string &getTranslatedSource(const Context *context);
        void getTranslatedSource(const Context *context,
                                 GLsizei bufSize,
                                 GLsizei *length,
                                 char *buffer);
        void getTranslatedSourceWithDebugInfo(const Context *context,
                                              GLsizei bufSize,
                                              GLsizei *length,
                                              char *buffer);
    
        size_t getSourceHash() const;
    
        void compile(const Context *context);
        bool isCompiled(const Context *context);
        bool isCompleted();
    
        // Return the compiled shader state for the program.  The program holds a reference to this
        // state, so the shader is free to recompile, get deleted, etc.
        const SharedCompiledShaderState &getCompiledState() const { return mState.getCompiledState(); }
    
        void addRef();
        void release(const Context *context);
        unsigned int getRefCount() const;
        bool isFlaggedForDeletion() const;
        void flagForDeletion();
    
        const ShaderState &getState() const { return mState; }
    
        GLuint getCurrentMaxComputeWorkGroupInvocations() const
        {
            return mCurrentMaxComputeWorkGroupInvocations;
        }
    
        unsigned int getMaxComputeSharedMemory() const { return mMaxComputeSharedMemory; }
        bool hasBeenDeleted() const { return mDeleteStatus; }
    
        // Block until compiling is finished and resolve it.
        void resolveCompile(const Context *context);
    
        // Writes a shader's binary to the output memory buffer.
        angle::Result serialize(const Context *context, angle::MemoryBuffer *binaryOut) const;
        angle::Result deserialize(BinaryInputStream &stream);
    
        // Load a binary from shader cache.
        angle::Result loadBinary(const Context *context, const void *binary, GLsizei length);
        // Load a binary from a glShaderBinary call.
        angle::Result loadShaderBinary(const Context *context, const void *binary, GLsizei length);
    
        void writeShaderKey(BinaryOutputStream *streamOut) const
        {
            ASSERT(streamOut && !mShaderHash.empty());
            streamOut->writeBytes(mShaderHash.data(), egl::BlobCache::kKeyLength);
            return;
        }
    
      private:
        struct CompilingState;
    
        ~Shader() override;
        static std::string joinShaderSources(GLsizei count,
                                             const char *const *string,
                                             const GLint *length);
        static void GetSourceImpl(const std::string &source,
                                  GLsizei bufSize,
                                  GLsizei *length,
                                  char *buffer);
        angle::Result loadBinaryImpl(const Context *context,
                                     const void *binary,
                                     GLsizei length,
                                     bool generatedWithOfflineCompiler);
    
        // Compute a key to uniquely identify the shader object in memory caches.
        void setShaderKey(const Context *context,
                          const ShCompileOptions &compileOptions,
                          const ShShaderOutput &outputType,
                          const ShBuiltInResources &resources);
    
        ShaderState mState;
        std::unique_ptr<rx::ShaderImpl> mImplementation;
        const gl::Limitations mRendererLimitations;
        const ShaderProgramID mHandle;
        unsigned int mRefCount;  // Number of program objects this shader is attached to
        bool mDeleteStatus;  // Flag to indicate that the shader can be deleted when no longer in use
        std::string mInfoLog;
    
        // We keep a reference to the translator in order to defer compiles while preserving settings.
        BindingPointer<Compiler> mBoundCompiler;
        std::unique_ptr<CompilingState> mCompilingState;
        egl::BlobCache::Key mShaderHash;
    
        ShaderProgramManager *mResourceManager;
    
        GLuint mCurrentMaxComputeWorkGroupInvocations;
        unsigned int mMaxComputeSharedMemory;
    };
    
    const char *GetShaderTypeString(ShaderType type);
    std::string GetShaderDumpFileDirectory();
    std::string GetShaderDumpFileName(size_t shaderHash);
    
    }  // namespace gl
    
    #endif  // LIBANGLE_SHADER_H_