1 // 2 // Copyright 2017 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 // ProgramPipeline.h: Defines the gl::ProgramPipeline class. 8 // Implements GL program pipeline objects and related functionality. 9 // [OpenGL ES 3.1] section 7.4 page 105. 10 11 #ifndef LIBANGLE_PROGRAMPIPELINE_H_ 12 #define LIBANGLE_PROGRAMPIPELINE_H_ 13 14 #include <memory> 15 16 #include "common/angleutils.h" 17 #include "libANGLE/Debug.h" 18 #include "libANGLE/Program.h" 19 #include "libANGLE/ProgramExecutable.h" 20 #include "libANGLE/RefCountObject.h" 21 22 namespace rx 23 { 24 class GLImplFactory; 25 class ProgramPipelineImpl; 26 } // namespace rx 27 28 namespace gl 29 { 30 class Context; 31 class ProgramPipeline; 32 33 class ProgramPipelineState final : angle::NonCopyable 34 { 35 public: 36 ProgramPipelineState(rx::GLImplFactory *factory); 37 ~ProgramPipelineState(); 38 39 const std::string &getLabel() const; 40 getExecutable()41 ProgramExecutable &getExecutable() const 42 { 43 ASSERT(mExecutable); 44 return *mExecutable; 45 } 46 getSharedExecutable()47 const SharedProgramExecutable &getSharedExecutable() const 48 { 49 ASSERT(mExecutable); 50 return mExecutable; 51 } 52 53 void activeShaderProgram(Program *shaderProgram); 54 void useProgramStages(const Context *context, 55 const gl::ShaderBitSet &shaderTypes, 56 Program *shaderProgram, 57 std::vector<angle::ObserverBinding> *programObserverBindings, 58 std::vector<angle::ObserverBinding> *programExecutableObserverBindings); 59 getActiveShaderProgram()60 Program *getActiveShaderProgram() { return mActiveShaderProgram; } 61 isValid()62 GLboolean isValid() const { return mValid; } 63 getShaderProgram(ShaderType shaderType)64 const Program *getShaderProgram(ShaderType shaderType) const { return mPrograms[shaderType]; } getShaderProgramExecutable(ShaderType shaderType)65 const SharedProgramExecutable &getShaderProgramExecutable(ShaderType shaderType) const 66 { 67 return mExecutable->mPPOProgramExecutables[shaderType]; 68 } 69 70 bool usesShaderProgram(ShaderProgramID program) const; 71 72 void updateExecutableTextures(); 73 74 void updateExecutableSpecConstUsageBits(); 75 76 private: 77 SharedProgramExecutable makeNewExecutable( 78 rx::GLImplFactory *factory, 79 ShaderMap<SharedProgramExecutable> &&ppoProgramExecutables); 80 void useProgramStage(const Context *context, 81 ShaderType shaderType, 82 Program *shaderProgram, 83 angle::ObserverBinding *programObserverBinding, 84 angle::ObserverBinding *programExecutableObserverBinding); 85 void destroyDiscardedExecutables(const Context *context); 86 87 friend class ProgramPipeline; 88 89 std::string mLabel; 90 91 // The active shader program 92 Program *mActiveShaderProgram; 93 // The shader programs for each stage. 94 ShaderMap<Program *> mPrograms; 95 96 // Mapping from program's UBOs into the program executable's UBOs. 97 ShaderMap<ProgramUniformBlockArray<GLuint>> mUniformBlockMap; 98 99 // A list of executables to be garbage collected. This is populated as the pipeline is 100 // notified about program relinks, but cannot immediately destroy the old executables due to 101 // lack of access to context. 102 std::vector<SharedProgramExecutable> mProgramExecutablesToDiscard; 103 104 GLboolean mValid; 105 106 InfoLog mInfoLog; 107 108 SharedProgramExecutable mExecutable; 109 110 bool mIsLinked; 111 }; 112 113 class ProgramPipeline final : public RefCountObject<ProgramPipelineID>, 114 public LabeledObject, 115 public angle::ObserverInterface, 116 public angle::Subject 117 { 118 public: 119 ProgramPipeline(rx::GLImplFactory *factory, ProgramPipelineID handle); 120 ~ProgramPipeline() override; 121 122 void onDestroy(const Context *context) override; 123 124 angle::Result setLabel(const Context *context, const std::string &label) override; 125 const std::string &getLabel() const override; 126 getState()127 const ProgramPipelineState &getState() const { return mState; } getState()128 ProgramPipelineState &getState() { return mState; } 129 getExecutable()130 ProgramExecutable &getExecutable() const { return mState.getExecutable(); } getSharedExecutable()131 const SharedProgramExecutable &getSharedExecutable() const 132 { 133 return mState.getSharedExecutable(); 134 } 135 136 rx::ProgramPipelineImpl *getImplementation() const; 137 getActiveShaderProgram()138 Program *getActiveShaderProgram() { return mState.getActiveShaderProgram(); } 139 void activeShaderProgram(Program *shaderProgram); getLinkedActiveShaderProgram(const Context * context)140 Program *getLinkedActiveShaderProgram(const Context *context) 141 { 142 Program *program = mState.getActiveShaderProgram(); 143 if (program) 144 { 145 program->resolveLink(context); 146 } 147 return program; 148 } 149 150 angle::Result useProgramStages(const Context *context, 151 GLbitfield stages, 152 Program *shaderProgram); 153 getShaderProgram(ShaderType shaderType)154 const Program *getShaderProgram(ShaderType shaderType) const 155 { 156 return mState.getShaderProgram(shaderType); 157 } getShaderProgramExecutable(ShaderType shaderType)158 const SharedProgramExecutable &getShaderProgramExecutable(ShaderType shaderType) const 159 { 160 return mState.getShaderProgramExecutable(shaderType); 161 } 162 resetIsLinked()163 void resetIsLinked() { mState.mIsLinked = false; } 164 angle::Result link(const gl::Context *context); 165 getInfoLog()166 InfoLog &getInfoLog() { return mState.mInfoLog; } 167 int getInfoLogLength() const; 168 void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const; 169 170 // Ensure program pipeline is linked. Inlined to make sure its overhead is as low as possible. resolveLink(const Context * context)171 void resolveLink(const Context *context) 172 { 173 if (mState.mIsLinked) 174 { 175 // Already linked, nothing to do. 176 return; 177 } 178 179 resolveAttachedPrograms(context); 180 angle::Result linkResult = link(context); 181 if (linkResult != angle::Result::Continue) 182 { 183 // If the link failed then log a warning, swallow the error and move on. 184 WARN() << "ProgramPipeline link failed" << std::endl; 185 } 186 return; 187 } 188 void resolveAttachedPrograms(const Context *context); 189 190 void validate(const gl::Context *context); isValid()191 GLboolean isValid() const { return mState.isValid(); } isLinked()192 bool isLinked() const { return mState.mIsLinked; } 193 194 // ObserverInterface implementation. 195 void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override; 196 197 private: 198 bool linkVaryings(); 199 void updateLinkedShaderStages(); 200 void updateExecutableAttributes(); 201 void updateTransformFeedbackMembers(); 202 void updateShaderStorageBlocks(); 203 void updateImageBindings(); 204 void updateExecutableGeometryProperties(); 205 void updateExecutableTessellationProperties(); 206 void updateFragmentInoutRangeAndEnablesPerSampleShading(); 207 void updateLinkedVaryings(); 208 void updateExecutable(); 209 210 std::unique_ptr<rx::ProgramPipelineImpl> mProgramPipelineImpl; 211 212 ProgramPipelineState mState; 213 214 std::vector<angle::ObserverBinding> mProgramObserverBindings; 215 std::vector<angle::ObserverBinding> mProgramExecutableObserverBindings; 216 }; 217 } // namespace gl 218 219 #endif // LIBANGLE_PROGRAMPIPELINE_H_ 220