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