xref: /aosp_15_r20/external/angle/src/libANGLE/ProgramPipeline.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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.cpp: Implements 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 #include "libANGLE/ProgramPipeline.h"
12*8975f5c5SAndroid Build Coastguard Worker 
13*8975f5c5SAndroid Build Coastguard Worker #include <algorithm>
14*8975f5c5SAndroid Build Coastguard Worker 
15*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Context.h"
16*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Program.h"
17*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/angletypes.h"
18*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/ContextImpl.h"
19*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/ProgramPipelineImpl.h"
20*8975f5c5SAndroid Build Coastguard Worker 
21*8975f5c5SAndroid Build Coastguard Worker namespace gl
22*8975f5c5SAndroid Build Coastguard Worker {
23*8975f5c5SAndroid Build Coastguard Worker 
ProgramPipelineState(rx::GLImplFactory * factory)24*8975f5c5SAndroid Build Coastguard Worker ProgramPipelineState::ProgramPipelineState(rx::GLImplFactory *factory)
25*8975f5c5SAndroid Build Coastguard Worker     : mLabel(),
26*8975f5c5SAndroid Build Coastguard Worker       mActiveShaderProgram(nullptr),
27*8975f5c5SAndroid Build Coastguard Worker       mValid(false),
28*8975f5c5SAndroid Build Coastguard Worker       mExecutable(makeNewExecutable(factory, {})),
29*8975f5c5SAndroid Build Coastguard Worker       mIsLinked(false)
30*8975f5c5SAndroid Build Coastguard Worker {
31*8975f5c5SAndroid Build Coastguard Worker     for (const ShaderType shaderType : AllShaderTypes())
32*8975f5c5SAndroid Build Coastguard Worker     {
33*8975f5c5SAndroid Build Coastguard Worker         mPrograms[shaderType] = nullptr;
34*8975f5c5SAndroid Build Coastguard Worker     }
35*8975f5c5SAndroid Build Coastguard Worker }
36*8975f5c5SAndroid Build Coastguard Worker 
~ProgramPipelineState()37*8975f5c5SAndroid Build Coastguard Worker ProgramPipelineState::~ProgramPipelineState() {}
38*8975f5c5SAndroid Build Coastguard Worker 
getLabel() const39*8975f5c5SAndroid Build Coastguard Worker const std::string &ProgramPipelineState::getLabel() const
40*8975f5c5SAndroid Build Coastguard Worker {
41*8975f5c5SAndroid Build Coastguard Worker     return mLabel;
42*8975f5c5SAndroid Build Coastguard Worker }
43*8975f5c5SAndroid Build Coastguard Worker 
activeShaderProgram(Program * shaderProgram)44*8975f5c5SAndroid Build Coastguard Worker void ProgramPipelineState::activeShaderProgram(Program *shaderProgram)
45*8975f5c5SAndroid Build Coastguard Worker {
46*8975f5c5SAndroid Build Coastguard Worker     mActiveShaderProgram = shaderProgram;
47*8975f5c5SAndroid Build Coastguard Worker }
48*8975f5c5SAndroid Build Coastguard Worker 
makeNewExecutable(rx::GLImplFactory * factory,ShaderMap<SharedProgramExecutable> && ppoProgramExecutables)49*8975f5c5SAndroid Build Coastguard Worker SharedProgramExecutable ProgramPipelineState::makeNewExecutable(
50*8975f5c5SAndroid Build Coastguard Worker     rx::GLImplFactory *factory,
51*8975f5c5SAndroid Build Coastguard Worker     ShaderMap<SharedProgramExecutable> &&ppoProgramExecutables)
52*8975f5c5SAndroid Build Coastguard Worker {
53*8975f5c5SAndroid Build Coastguard Worker     SharedProgramExecutable newExecutable = std::make_shared<ProgramExecutable>(factory, &mInfoLog);
54*8975f5c5SAndroid Build Coastguard Worker     newExecutable->mIsPPO                 = true;
55*8975f5c5SAndroid Build Coastguard Worker     newExecutable->mPPOProgramExecutables = std::move(ppoProgramExecutables);
56*8975f5c5SAndroid Build Coastguard Worker     return newExecutable;
57*8975f5c5SAndroid Build Coastguard Worker }
58*8975f5c5SAndroid Build Coastguard Worker 
useProgramStage(const Context * context,const ShaderType shaderType,Program * shaderProgram,angle::ObserverBinding * programObserverBinding,angle::ObserverBinding * programExecutableObserverBinding)59*8975f5c5SAndroid Build Coastguard Worker void ProgramPipelineState::useProgramStage(const Context *context,
60*8975f5c5SAndroid Build Coastguard Worker                                            const ShaderType shaderType,
61*8975f5c5SAndroid Build Coastguard Worker                                            Program *shaderProgram,
62*8975f5c5SAndroid Build Coastguard Worker                                            angle::ObserverBinding *programObserverBinding,
63*8975f5c5SAndroid Build Coastguard Worker                                            angle::ObserverBinding *programExecutableObserverBinding)
64*8975f5c5SAndroid Build Coastguard Worker {
65*8975f5c5SAndroid Build Coastguard Worker     Program *oldProgram = mPrograms[shaderType];
66*8975f5c5SAndroid Build Coastguard Worker     if (oldProgram)
67*8975f5c5SAndroid Build Coastguard Worker     {
68*8975f5c5SAndroid Build Coastguard Worker         oldProgram->release(context);
69*8975f5c5SAndroid Build Coastguard Worker     }
70*8975f5c5SAndroid Build Coastguard Worker 
71*8975f5c5SAndroid Build Coastguard Worker     // If program refers to a program object with a valid shader attached for the indicated shader
72*8975f5c5SAndroid Build Coastguard Worker     // stage, glUseProgramStages installs the executable code for that stage in the indicated
73*8975f5c5SAndroid Build Coastguard Worker     // program pipeline object pipeline.
74*8975f5c5SAndroid Build Coastguard Worker     if (shaderProgram && (shaderProgram->id().value != 0) &&
75*8975f5c5SAndroid Build Coastguard Worker         shaderProgram->getExecutable().hasLinkedShaderStage(shaderType))
76*8975f5c5SAndroid Build Coastguard Worker     {
77*8975f5c5SAndroid Build Coastguard Worker         mPrograms[shaderType] = shaderProgram;
78*8975f5c5SAndroid Build Coastguard Worker         // Install the program executable, if not already
79*8975f5c5SAndroid Build Coastguard Worker         if (shaderProgram->getSharedExecutable().get() !=
80*8975f5c5SAndroid Build Coastguard Worker             mExecutable->mPPOProgramExecutables[shaderType].get())
81*8975f5c5SAndroid Build Coastguard Worker         {
82*8975f5c5SAndroid Build Coastguard Worker             InstallExecutable(context, shaderProgram->getSharedExecutable(),
83*8975f5c5SAndroid Build Coastguard Worker                               &mExecutable->mPPOProgramExecutables[shaderType]);
84*8975f5c5SAndroid Build Coastguard Worker         }
85*8975f5c5SAndroid Build Coastguard Worker         shaderProgram->addRef();
86*8975f5c5SAndroid Build Coastguard Worker     }
87*8975f5c5SAndroid Build Coastguard Worker     else
88*8975f5c5SAndroid Build Coastguard Worker     {
89*8975f5c5SAndroid Build Coastguard Worker         // If program is zero, or refers to a program object with no valid shader executable for the
90*8975f5c5SAndroid Build Coastguard Worker         // given stage, it is as if the pipeline object has no programmable stage configured for the
91*8975f5c5SAndroid Build Coastguard Worker         // indicated shader stage.
92*8975f5c5SAndroid Build Coastguard Worker         mPrograms[shaderType] = nullptr;
93*8975f5c5SAndroid Build Coastguard Worker         UninstallExecutable(context, &mExecutable->mPPOProgramExecutables[shaderType]);
94*8975f5c5SAndroid Build Coastguard Worker     }
95*8975f5c5SAndroid Build Coastguard Worker 
96*8975f5c5SAndroid Build Coastguard Worker     programObserverBinding->bind(mPrograms[shaderType]);
97*8975f5c5SAndroid Build Coastguard Worker     programExecutableObserverBinding->bind(mExecutable->mPPOProgramExecutables[shaderType].get());
98*8975f5c5SAndroid Build Coastguard Worker }
99*8975f5c5SAndroid Build Coastguard Worker 
useProgramStages(const Context * context,const ShaderBitSet & shaderTypes,Program * shaderProgram,std::vector<angle::ObserverBinding> * programObserverBindings,std::vector<angle::ObserverBinding> * programExecutableObserverBindings)100*8975f5c5SAndroid Build Coastguard Worker void ProgramPipelineState::useProgramStages(
101*8975f5c5SAndroid Build Coastguard Worker     const Context *context,
102*8975f5c5SAndroid Build Coastguard Worker     const ShaderBitSet &shaderTypes,
103*8975f5c5SAndroid Build Coastguard Worker     Program *shaderProgram,
104*8975f5c5SAndroid Build Coastguard Worker     std::vector<angle::ObserverBinding> *programObserverBindings,
105*8975f5c5SAndroid Build Coastguard Worker     std::vector<angle::ObserverBinding> *programExecutableObserverBindings)
106*8975f5c5SAndroid Build Coastguard Worker {
107*8975f5c5SAndroid Build Coastguard Worker     for (ShaderType shaderType : shaderTypes)
108*8975f5c5SAndroid Build Coastguard Worker     {
109*8975f5c5SAndroid Build Coastguard Worker         useProgramStage(context, shaderType, shaderProgram,
110*8975f5c5SAndroid Build Coastguard Worker                         &programObserverBindings->at(static_cast<size_t>(shaderType)),
111*8975f5c5SAndroid Build Coastguard Worker                         &programExecutableObserverBindings->at(static_cast<size_t>(shaderType)));
112*8975f5c5SAndroid Build Coastguard Worker     }
113*8975f5c5SAndroid Build Coastguard Worker }
114*8975f5c5SAndroid Build Coastguard Worker 
usesShaderProgram(ShaderProgramID programId) const115*8975f5c5SAndroid Build Coastguard Worker bool ProgramPipelineState::usesShaderProgram(ShaderProgramID programId) const
116*8975f5c5SAndroid Build Coastguard Worker {
117*8975f5c5SAndroid Build Coastguard Worker     for (const Program *program : mPrograms)
118*8975f5c5SAndroid Build Coastguard Worker     {
119*8975f5c5SAndroid Build Coastguard Worker         if (program && (program->id() == programId))
120*8975f5c5SAndroid Build Coastguard Worker         {
121*8975f5c5SAndroid Build Coastguard Worker             return true;
122*8975f5c5SAndroid Build Coastguard Worker         }
123*8975f5c5SAndroid Build Coastguard Worker     }
124*8975f5c5SAndroid Build Coastguard Worker 
125*8975f5c5SAndroid Build Coastguard Worker     return false;
126*8975f5c5SAndroid Build Coastguard Worker }
127*8975f5c5SAndroid Build Coastguard Worker 
updateExecutableTextures()128*8975f5c5SAndroid Build Coastguard Worker void ProgramPipelineState::updateExecutableTextures()
129*8975f5c5SAndroid Build Coastguard Worker {
130*8975f5c5SAndroid Build Coastguard Worker     for (const ShaderType shaderType : mExecutable->getLinkedShaderStages())
131*8975f5c5SAndroid Build Coastguard Worker     {
132*8975f5c5SAndroid Build Coastguard Worker         const SharedProgramExecutable &programExecutable = getShaderProgramExecutable(shaderType);
133*8975f5c5SAndroid Build Coastguard Worker         ASSERT(programExecutable);
134*8975f5c5SAndroid Build Coastguard Worker         mExecutable->setActiveTextureMask(mExecutable->getActiveSamplersMask() |
135*8975f5c5SAndroid Build Coastguard Worker                                           programExecutable->getActiveSamplersMask());
136*8975f5c5SAndroid Build Coastguard Worker         mExecutable->setActiveImagesMask(mExecutable->getActiveImagesMask() |
137*8975f5c5SAndroid Build Coastguard Worker                                          programExecutable->getActiveImagesMask());
138*8975f5c5SAndroid Build Coastguard Worker         // Updates mActiveSamplerRefCounts, mActiveSamplerTypes, and mActiveSamplerFormats
139*8975f5c5SAndroid Build Coastguard Worker         mExecutable->updateActiveSamplers(*programExecutable);
140*8975f5c5SAndroid Build Coastguard Worker     }
141*8975f5c5SAndroid Build Coastguard Worker }
142*8975f5c5SAndroid Build Coastguard Worker 
updateExecutableSpecConstUsageBits()143*8975f5c5SAndroid Build Coastguard Worker void ProgramPipelineState::updateExecutableSpecConstUsageBits()
144*8975f5c5SAndroid Build Coastguard Worker {
145*8975f5c5SAndroid Build Coastguard Worker     rx::SpecConstUsageBits specConstUsageBits;
146*8975f5c5SAndroid Build Coastguard Worker     for (const ShaderType shaderType : mExecutable->getLinkedShaderStages())
147*8975f5c5SAndroid Build Coastguard Worker     {
148*8975f5c5SAndroid Build Coastguard Worker         const SharedProgramExecutable &programExecutable = getShaderProgramExecutable(shaderType);
149*8975f5c5SAndroid Build Coastguard Worker         ASSERT(programExecutable);
150*8975f5c5SAndroid Build Coastguard Worker         specConstUsageBits |= programExecutable->getSpecConstUsageBits();
151*8975f5c5SAndroid Build Coastguard Worker     }
152*8975f5c5SAndroid Build Coastguard Worker     mExecutable->mPod.specConstUsageBits = specConstUsageBits;
153*8975f5c5SAndroid Build Coastguard Worker }
154*8975f5c5SAndroid Build Coastguard Worker 
ProgramPipeline(rx::GLImplFactory * factory,ProgramPipelineID handle)155*8975f5c5SAndroid Build Coastguard Worker ProgramPipeline::ProgramPipeline(rx::GLImplFactory *factory, ProgramPipelineID handle)
156*8975f5c5SAndroid Build Coastguard Worker     : RefCountObject(factory->generateSerial(), handle),
157*8975f5c5SAndroid Build Coastguard Worker       mProgramPipelineImpl(factory->createProgramPipeline(mState)),
158*8975f5c5SAndroid Build Coastguard Worker       mState(factory)
159*8975f5c5SAndroid Build Coastguard Worker {
160*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mProgramPipelineImpl);
161*8975f5c5SAndroid Build Coastguard Worker 
162*8975f5c5SAndroid Build Coastguard Worker     for (const ShaderType shaderType : AllShaderTypes())
163*8975f5c5SAndroid Build Coastguard Worker     {
164*8975f5c5SAndroid Build Coastguard Worker         mProgramObserverBindings.emplace_back(this, static_cast<angle::SubjectIndex>(shaderType));
165*8975f5c5SAndroid Build Coastguard Worker         mProgramExecutableObserverBindings.emplace_back(
166*8975f5c5SAndroid Build Coastguard Worker             this, static_cast<angle::SubjectIndex>(shaderType));
167*8975f5c5SAndroid Build Coastguard Worker     }
168*8975f5c5SAndroid Build Coastguard Worker }
169*8975f5c5SAndroid Build Coastguard Worker 
~ProgramPipeline()170*8975f5c5SAndroid Build Coastguard Worker ProgramPipeline::~ProgramPipeline()
171*8975f5c5SAndroid Build Coastguard Worker {
172*8975f5c5SAndroid Build Coastguard Worker     mProgramPipelineImpl.reset(nullptr);
173*8975f5c5SAndroid Build Coastguard Worker }
174*8975f5c5SAndroid Build Coastguard Worker 
onDestroy(const Context * context)175*8975f5c5SAndroid Build Coastguard Worker void ProgramPipeline::onDestroy(const Context *context)
176*8975f5c5SAndroid Build Coastguard Worker {
177*8975f5c5SAndroid Build Coastguard Worker     for (Program *program : mState.mPrograms)
178*8975f5c5SAndroid Build Coastguard Worker     {
179*8975f5c5SAndroid Build Coastguard Worker         if (program)
180*8975f5c5SAndroid Build Coastguard Worker         {
181*8975f5c5SAndroid Build Coastguard Worker             ASSERT(program->getRefCount());
182*8975f5c5SAndroid Build Coastguard Worker             program->release(context);
183*8975f5c5SAndroid Build Coastguard Worker         }
184*8975f5c5SAndroid Build Coastguard Worker     }
185*8975f5c5SAndroid Build Coastguard Worker 
186*8975f5c5SAndroid Build Coastguard Worker     getImplementation()->destroy(context);
187*8975f5c5SAndroid Build Coastguard Worker     UninstallExecutable(context, &mState.mExecutable);
188*8975f5c5SAndroid Build Coastguard Worker 
189*8975f5c5SAndroid Build Coastguard Worker     mState.destroyDiscardedExecutables(context);
190*8975f5c5SAndroid Build Coastguard Worker }
191*8975f5c5SAndroid Build Coastguard Worker 
destroyDiscardedExecutables(const Context * context)192*8975f5c5SAndroid Build Coastguard Worker void ProgramPipelineState::destroyDiscardedExecutables(const Context *context)
193*8975f5c5SAndroid Build Coastguard Worker {
194*8975f5c5SAndroid Build Coastguard Worker     for (SharedProgramExecutable &executable : mProgramExecutablesToDiscard)
195*8975f5c5SAndroid Build Coastguard Worker     {
196*8975f5c5SAndroid Build Coastguard Worker         UninstallExecutable(context, &executable);
197*8975f5c5SAndroid Build Coastguard Worker     }
198*8975f5c5SAndroid Build Coastguard Worker     mProgramExecutablesToDiscard.clear();
199*8975f5c5SAndroid Build Coastguard Worker }
200*8975f5c5SAndroid Build Coastguard Worker 
setLabel(const Context * context,const std::string & label)201*8975f5c5SAndroid Build Coastguard Worker angle::Result ProgramPipeline::setLabel(const Context *context, const std::string &label)
202*8975f5c5SAndroid Build Coastguard Worker {
203*8975f5c5SAndroid Build Coastguard Worker     mState.mLabel = label;
204*8975f5c5SAndroid Build Coastguard Worker 
205*8975f5c5SAndroid Build Coastguard Worker     if (mProgramPipelineImpl)
206*8975f5c5SAndroid Build Coastguard Worker     {
207*8975f5c5SAndroid Build Coastguard Worker         return mProgramPipelineImpl->onLabelUpdate(context);
208*8975f5c5SAndroid Build Coastguard Worker     }
209*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
210*8975f5c5SAndroid Build Coastguard Worker }
211*8975f5c5SAndroid Build Coastguard Worker 
getLabel() const212*8975f5c5SAndroid Build Coastguard Worker const std::string &ProgramPipeline::getLabel() const
213*8975f5c5SAndroid Build Coastguard Worker {
214*8975f5c5SAndroid Build Coastguard Worker     return mState.mLabel;
215*8975f5c5SAndroid Build Coastguard Worker }
216*8975f5c5SAndroid Build Coastguard Worker 
getImplementation() const217*8975f5c5SAndroid Build Coastguard Worker rx::ProgramPipelineImpl *ProgramPipeline::getImplementation() const
218*8975f5c5SAndroid Build Coastguard Worker {
219*8975f5c5SAndroid Build Coastguard Worker     return mProgramPipelineImpl.get();
220*8975f5c5SAndroid Build Coastguard Worker }
221*8975f5c5SAndroid Build Coastguard Worker 
activeShaderProgram(Program * shaderProgram)222*8975f5c5SAndroid Build Coastguard Worker void ProgramPipeline::activeShaderProgram(Program *shaderProgram)
223*8975f5c5SAndroid Build Coastguard Worker {
224*8975f5c5SAndroid Build Coastguard Worker     mState.activeShaderProgram(shaderProgram);
225*8975f5c5SAndroid Build Coastguard Worker }
226*8975f5c5SAndroid Build Coastguard Worker 
useProgramStages(const Context * context,GLbitfield stages,Program * shaderProgram)227*8975f5c5SAndroid Build Coastguard Worker angle::Result ProgramPipeline::useProgramStages(const Context *context,
228*8975f5c5SAndroid Build Coastguard Worker                                                 GLbitfield stages,
229*8975f5c5SAndroid Build Coastguard Worker                                                 Program *shaderProgram)
230*8975f5c5SAndroid Build Coastguard Worker {
231*8975f5c5SAndroid Build Coastguard Worker     ShaderBitSet shaderTypes;
232*8975f5c5SAndroid Build Coastguard Worker     if (stages != GL_ALL_SHADER_BITS)
233*8975f5c5SAndroid Build Coastguard Worker     {
234*8975f5c5SAndroid Build Coastguard Worker         ASSERT(stages < 256u);
235*8975f5c5SAndroid Build Coastguard Worker         for (size_t singleShaderBit : angle::BitSet<8>(stages))
236*8975f5c5SAndroid Build Coastguard Worker         {
237*8975f5c5SAndroid Build Coastguard Worker             // Cast back to a bit after the iterator returns an index.
238*8975f5c5SAndroid Build Coastguard Worker             ShaderType shaderType = GetShaderTypeFromBitfield(angle::Bit<size_t>(singleShaderBit));
239*8975f5c5SAndroid Build Coastguard Worker             ASSERT(shaderType != ShaderType::InvalidEnum);
240*8975f5c5SAndroid Build Coastguard Worker             shaderTypes.set(shaderType);
241*8975f5c5SAndroid Build Coastguard Worker         }
242*8975f5c5SAndroid Build Coastguard Worker     }
243*8975f5c5SAndroid Build Coastguard Worker     else
244*8975f5c5SAndroid Build Coastguard Worker     {
245*8975f5c5SAndroid Build Coastguard Worker         shaderTypes.set();
246*8975f5c5SAndroid Build Coastguard Worker     }
247*8975f5c5SAndroid Build Coastguard Worker     ASSERT(shaderTypes.any());
248*8975f5c5SAndroid Build Coastguard Worker 
249*8975f5c5SAndroid Build Coastguard Worker     bool needToUpdatePipelineState = false;
250*8975f5c5SAndroid Build Coastguard Worker     for (ShaderType shaderType : shaderTypes)
251*8975f5c5SAndroid Build Coastguard Worker     {
252*8975f5c5SAndroid Build Coastguard Worker         if (mState.getShaderProgram(shaderType) != shaderProgram ||
253*8975f5c5SAndroid Build Coastguard Worker             (shaderProgram &&
254*8975f5c5SAndroid Build Coastguard Worker              getShaderProgramExecutable(shaderType) != shaderProgram->getSharedExecutable()))
255*8975f5c5SAndroid Build Coastguard Worker         {
256*8975f5c5SAndroid Build Coastguard Worker             needToUpdatePipelineState = true;
257*8975f5c5SAndroid Build Coastguard Worker             break;
258*8975f5c5SAndroid Build Coastguard Worker         }
259*8975f5c5SAndroid Build Coastguard Worker     }
260*8975f5c5SAndroid Build Coastguard Worker 
261*8975f5c5SAndroid Build Coastguard Worker     if (!needToUpdatePipelineState)
262*8975f5c5SAndroid Build Coastguard Worker     {
263*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
264*8975f5c5SAndroid Build Coastguard Worker     }
265*8975f5c5SAndroid Build Coastguard Worker 
266*8975f5c5SAndroid Build Coastguard Worker     mState.useProgramStages(context, shaderTypes, shaderProgram, &mProgramObserverBindings,
267*8975f5c5SAndroid Build Coastguard Worker                             &mProgramExecutableObserverBindings);
268*8975f5c5SAndroid Build Coastguard Worker 
269*8975f5c5SAndroid Build Coastguard Worker     mState.mIsLinked = false;
270*8975f5c5SAndroid Build Coastguard Worker     onStateChange(angle::SubjectMessage::ProgramUnlinked);
271*8975f5c5SAndroid Build Coastguard Worker 
272*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
273*8975f5c5SAndroid Build Coastguard Worker }
274*8975f5c5SAndroid Build Coastguard Worker 
updateLinkedShaderStages()275*8975f5c5SAndroid Build Coastguard Worker void ProgramPipeline::updateLinkedShaderStages()
276*8975f5c5SAndroid Build Coastguard Worker {
277*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->resetLinkedShaderStages();
278*8975f5c5SAndroid Build Coastguard Worker 
279*8975f5c5SAndroid Build Coastguard Worker     for (const ShaderType shaderType : AllShaderTypes())
280*8975f5c5SAndroid Build Coastguard Worker     {
281*8975f5c5SAndroid Build Coastguard Worker         if (getShaderProgramExecutable(shaderType))
282*8975f5c5SAndroid Build Coastguard Worker         {
283*8975f5c5SAndroid Build Coastguard Worker             mState.mExecutable->setLinkedShaderStages(shaderType);
284*8975f5c5SAndroid Build Coastguard Worker         }
285*8975f5c5SAndroid Build Coastguard Worker     }
286*8975f5c5SAndroid Build Coastguard Worker 
287*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->updateCanDrawWith();
288*8975f5c5SAndroid Build Coastguard Worker }
289*8975f5c5SAndroid Build Coastguard Worker 
updateExecutableAttributes()290*8975f5c5SAndroid Build Coastguard Worker void ProgramPipeline::updateExecutableAttributes()
291*8975f5c5SAndroid Build Coastguard Worker {
292*8975f5c5SAndroid Build Coastguard Worker     const SharedProgramExecutable &vertexExecutable =
293*8975f5c5SAndroid Build Coastguard Worker         getShaderProgramExecutable(ShaderType::Vertex);
294*8975f5c5SAndroid Build Coastguard Worker 
295*8975f5c5SAndroid Build Coastguard Worker     if (!vertexExecutable)
296*8975f5c5SAndroid Build Coastguard Worker     {
297*8975f5c5SAndroid Build Coastguard Worker         return;
298*8975f5c5SAndroid Build Coastguard Worker     }
299*8975f5c5SAndroid Build Coastguard Worker 
300*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->mPod.activeAttribLocationsMask =
301*8975f5c5SAndroid Build Coastguard Worker         vertexExecutable->mPod.activeAttribLocationsMask;
302*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->mPod.maxActiveAttribLocation =
303*8975f5c5SAndroid Build Coastguard Worker         vertexExecutable->mPod.maxActiveAttribLocation;
304*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->mPod.attributesTypeMask = vertexExecutable->mPod.attributesTypeMask;
305*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->mPod.attributesMask     = vertexExecutable->mPod.attributesMask;
306*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->mProgramInputs          = vertexExecutable->mProgramInputs;
307*8975f5c5SAndroid Build Coastguard Worker 
308*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->mPod.numViews             = vertexExecutable->mPod.numViews;
309*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->mPod.drawIDLocation       = vertexExecutable->mPod.drawIDLocation;
310*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->mPod.baseVertexLocation   = vertexExecutable->mPod.baseVertexLocation;
311*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->mPod.baseInstanceLocation = vertexExecutable->mPod.baseInstanceLocation;
312*8975f5c5SAndroid Build Coastguard Worker }
313*8975f5c5SAndroid Build Coastguard Worker 
updateTransformFeedbackMembers()314*8975f5c5SAndroid Build Coastguard Worker void ProgramPipeline::updateTransformFeedbackMembers()
315*8975f5c5SAndroid Build Coastguard Worker {
316*8975f5c5SAndroid Build Coastguard Worker     ShaderType lastVertexProcessingStage =
317*8975f5c5SAndroid Build Coastguard Worker         GetLastPreFragmentStage(getExecutable().getLinkedShaderStages());
318*8975f5c5SAndroid Build Coastguard Worker     if (lastVertexProcessingStage == ShaderType::InvalidEnum)
319*8975f5c5SAndroid Build Coastguard Worker     {
320*8975f5c5SAndroid Build Coastguard Worker         return;
321*8975f5c5SAndroid Build Coastguard Worker     }
322*8975f5c5SAndroid Build Coastguard Worker 
323*8975f5c5SAndroid Build Coastguard Worker     const SharedProgramExecutable &lastPreFragmentExecutable =
324*8975f5c5SAndroid Build Coastguard Worker         getShaderProgramExecutable(lastVertexProcessingStage);
325*8975f5c5SAndroid Build Coastguard Worker     ASSERT(lastPreFragmentExecutable);
326*8975f5c5SAndroid Build Coastguard Worker 
327*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->mTransformFeedbackStrides =
328*8975f5c5SAndroid Build Coastguard Worker         lastPreFragmentExecutable->mTransformFeedbackStrides;
329*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->mLinkedTransformFeedbackVaryings =
330*8975f5c5SAndroid Build Coastguard Worker         lastPreFragmentExecutable->mLinkedTransformFeedbackVaryings;
331*8975f5c5SAndroid Build Coastguard Worker }
332*8975f5c5SAndroid Build Coastguard Worker 
updateShaderStorageBlocks()333*8975f5c5SAndroid Build Coastguard Worker void ProgramPipeline::updateShaderStorageBlocks()
334*8975f5c5SAndroid Build Coastguard Worker {
335*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->mShaderStorageBlocks.clear();
336*8975f5c5SAndroid Build Coastguard Worker 
337*8975f5c5SAndroid Build Coastguard Worker     // Only copy the storage blocks from each Program in the PPO once, since each Program could
338*8975f5c5SAndroid Build Coastguard Worker     // contain multiple shader stages.
339*8975f5c5SAndroid Build Coastguard Worker     ShaderBitSet handledStages;
340*8975f5c5SAndroid Build Coastguard Worker 
341*8975f5c5SAndroid Build Coastguard Worker     for (const ShaderType shaderType : AllShaderTypes())
342*8975f5c5SAndroid Build Coastguard Worker     {
343*8975f5c5SAndroid Build Coastguard Worker         const SharedProgramExecutable &programExecutable = getShaderProgramExecutable(shaderType);
344*8975f5c5SAndroid Build Coastguard Worker         if (programExecutable && !handledStages.test(shaderType))
345*8975f5c5SAndroid Build Coastguard Worker         {
346*8975f5c5SAndroid Build Coastguard Worker             // Only add each Program's blocks once.
347*8975f5c5SAndroid Build Coastguard Worker             handledStages |= programExecutable->getLinkedShaderStages();
348*8975f5c5SAndroid Build Coastguard Worker 
349*8975f5c5SAndroid Build Coastguard Worker             for (const InterfaceBlock &block : programExecutable->getShaderStorageBlocks())
350*8975f5c5SAndroid Build Coastguard Worker             {
351*8975f5c5SAndroid Build Coastguard Worker                 mState.mExecutable->mShaderStorageBlocks.emplace_back(block);
352*8975f5c5SAndroid Build Coastguard Worker             }
353*8975f5c5SAndroid Build Coastguard Worker         }
354*8975f5c5SAndroid Build Coastguard Worker     }
355*8975f5c5SAndroid Build Coastguard Worker }
356*8975f5c5SAndroid Build Coastguard Worker 
updateImageBindings()357*8975f5c5SAndroid Build Coastguard Worker void ProgramPipeline::updateImageBindings()
358*8975f5c5SAndroid Build Coastguard Worker {
359*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->mImageBindings.clear();
360*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->mActiveImageShaderBits.fill({});
361*8975f5c5SAndroid Build Coastguard Worker 
362*8975f5c5SAndroid Build Coastguard Worker     // Only copy the storage blocks from each Program in the PPO once, since each Program could
363*8975f5c5SAndroid Build Coastguard Worker     // contain multiple shader stages.
364*8975f5c5SAndroid Build Coastguard Worker     ShaderBitSet handledStages;
365*8975f5c5SAndroid Build Coastguard Worker 
366*8975f5c5SAndroid Build Coastguard Worker     for (const ShaderType shaderType : AllShaderTypes())
367*8975f5c5SAndroid Build Coastguard Worker     {
368*8975f5c5SAndroid Build Coastguard Worker         const SharedProgramExecutable &programExecutable = getShaderProgramExecutable(shaderType);
369*8975f5c5SAndroid Build Coastguard Worker         if (programExecutable && !handledStages.test(shaderType))
370*8975f5c5SAndroid Build Coastguard Worker         {
371*8975f5c5SAndroid Build Coastguard Worker             // Only add each Program's blocks once.
372*8975f5c5SAndroid Build Coastguard Worker             handledStages |= programExecutable->getLinkedShaderStages();
373*8975f5c5SAndroid Build Coastguard Worker 
374*8975f5c5SAndroid Build Coastguard Worker             for (const ImageBinding &imageBinding : *programExecutable->getImageBindings())
375*8975f5c5SAndroid Build Coastguard Worker             {
376*8975f5c5SAndroid Build Coastguard Worker                 mState.mExecutable->mImageBindings.emplace_back(imageBinding);
377*8975f5c5SAndroid Build Coastguard Worker             }
378*8975f5c5SAndroid Build Coastguard Worker 
379*8975f5c5SAndroid Build Coastguard Worker             mState.mExecutable->updateActiveImages(*programExecutable);
380*8975f5c5SAndroid Build Coastguard Worker         }
381*8975f5c5SAndroid Build Coastguard Worker     }
382*8975f5c5SAndroid Build Coastguard Worker }
383*8975f5c5SAndroid Build Coastguard Worker 
updateExecutableGeometryProperties()384*8975f5c5SAndroid Build Coastguard Worker void ProgramPipeline::updateExecutableGeometryProperties()
385*8975f5c5SAndroid Build Coastguard Worker {
386*8975f5c5SAndroid Build Coastguard Worker     const SharedProgramExecutable &geometryExecutable =
387*8975f5c5SAndroid Build Coastguard Worker         getShaderProgramExecutable(ShaderType::Geometry);
388*8975f5c5SAndroid Build Coastguard Worker 
389*8975f5c5SAndroid Build Coastguard Worker     if (!geometryExecutable)
390*8975f5c5SAndroid Build Coastguard Worker     {
391*8975f5c5SAndroid Build Coastguard Worker         return;
392*8975f5c5SAndroid Build Coastguard Worker     }
393*8975f5c5SAndroid Build Coastguard Worker 
394*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->mPod.geometryShaderInputPrimitiveType =
395*8975f5c5SAndroid Build Coastguard Worker         geometryExecutable->mPod.geometryShaderInputPrimitiveType;
396*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->mPod.geometryShaderOutputPrimitiveType =
397*8975f5c5SAndroid Build Coastguard Worker         geometryExecutable->mPod.geometryShaderOutputPrimitiveType;
398*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->mPod.geometryShaderInvocations =
399*8975f5c5SAndroid Build Coastguard Worker         geometryExecutable->mPod.geometryShaderInvocations;
400*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->mPod.geometryShaderMaxVertices =
401*8975f5c5SAndroid Build Coastguard Worker         geometryExecutable->mPod.geometryShaderMaxVertices;
402*8975f5c5SAndroid Build Coastguard Worker }
403*8975f5c5SAndroid Build Coastguard Worker 
updateExecutableTessellationProperties()404*8975f5c5SAndroid Build Coastguard Worker void ProgramPipeline::updateExecutableTessellationProperties()
405*8975f5c5SAndroid Build Coastguard Worker {
406*8975f5c5SAndroid Build Coastguard Worker     const SharedProgramExecutable &tessControlExecutable =
407*8975f5c5SAndroid Build Coastguard Worker         getShaderProgramExecutable(ShaderType::TessControl);
408*8975f5c5SAndroid Build Coastguard Worker     const SharedProgramExecutable &tessEvalExecutable =
409*8975f5c5SAndroid Build Coastguard Worker         getShaderProgramExecutable(ShaderType::TessEvaluation);
410*8975f5c5SAndroid Build Coastguard Worker 
411*8975f5c5SAndroid Build Coastguard Worker     if (tessControlExecutable)
412*8975f5c5SAndroid Build Coastguard Worker     {
413*8975f5c5SAndroid Build Coastguard Worker         mState.mExecutable->mPod.tessControlShaderVertices =
414*8975f5c5SAndroid Build Coastguard Worker             tessControlExecutable->mPod.tessControlShaderVertices;
415*8975f5c5SAndroid Build Coastguard Worker     }
416*8975f5c5SAndroid Build Coastguard Worker 
417*8975f5c5SAndroid Build Coastguard Worker     if (tessEvalExecutable)
418*8975f5c5SAndroid Build Coastguard Worker     {
419*8975f5c5SAndroid Build Coastguard Worker         mState.mExecutable->mPod.tessGenMode        = tessEvalExecutable->mPod.tessGenMode;
420*8975f5c5SAndroid Build Coastguard Worker         mState.mExecutable->mPod.tessGenSpacing     = tessEvalExecutable->mPod.tessGenSpacing;
421*8975f5c5SAndroid Build Coastguard Worker         mState.mExecutable->mPod.tessGenVertexOrder = tessEvalExecutable->mPod.tessGenVertexOrder;
422*8975f5c5SAndroid Build Coastguard Worker         mState.mExecutable->mPod.tessGenPointMode   = tessEvalExecutable->mPod.tessGenPointMode;
423*8975f5c5SAndroid Build Coastguard Worker     }
424*8975f5c5SAndroid Build Coastguard Worker }
425*8975f5c5SAndroid Build Coastguard Worker 
updateFragmentInoutRangeAndEnablesPerSampleShading()426*8975f5c5SAndroid Build Coastguard Worker void ProgramPipeline::updateFragmentInoutRangeAndEnablesPerSampleShading()
427*8975f5c5SAndroid Build Coastguard Worker {
428*8975f5c5SAndroid Build Coastguard Worker     const SharedProgramExecutable &fragmentExecutable =
429*8975f5c5SAndroid Build Coastguard Worker         getShaderProgramExecutable(ShaderType::Fragment);
430*8975f5c5SAndroid Build Coastguard Worker 
431*8975f5c5SAndroid Build Coastguard Worker     if (!fragmentExecutable)
432*8975f5c5SAndroid Build Coastguard Worker     {
433*8975f5c5SAndroid Build Coastguard Worker         return;
434*8975f5c5SAndroid Build Coastguard Worker     }
435*8975f5c5SAndroid Build Coastguard Worker 
436*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->mPod.fragmentInoutIndices = fragmentExecutable->mPod.fragmentInoutIndices;
437*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->mPod.hasDiscard           = fragmentExecutable->mPod.hasDiscard;
438*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->mPod.enablesPerSampleShading =
439*8975f5c5SAndroid Build Coastguard Worker         fragmentExecutable->mPod.enablesPerSampleShading;
440*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->mPod.hasDepthInputAttachment =
441*8975f5c5SAndroid Build Coastguard Worker         fragmentExecutable->mPod.hasDepthInputAttachment;
442*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->mPod.hasStencilInputAttachment =
443*8975f5c5SAndroid Build Coastguard Worker         fragmentExecutable->mPod.hasStencilInputAttachment;
444*8975f5c5SAndroid Build Coastguard Worker }
445*8975f5c5SAndroid Build Coastguard Worker 
updateLinkedVaryings()446*8975f5c5SAndroid Build Coastguard Worker void ProgramPipeline::updateLinkedVaryings()
447*8975f5c5SAndroid Build Coastguard Worker {
448*8975f5c5SAndroid Build Coastguard Worker     // Need to check all of the shader stages, not just linked, so we handle Compute correctly.
449*8975f5c5SAndroid Build Coastguard Worker     for (const ShaderType shaderType : kAllGraphicsShaderTypes)
450*8975f5c5SAndroid Build Coastguard Worker     {
451*8975f5c5SAndroid Build Coastguard Worker         const SharedProgramExecutable &programExecutable = getShaderProgramExecutable(shaderType);
452*8975f5c5SAndroid Build Coastguard Worker         if (programExecutable)
453*8975f5c5SAndroid Build Coastguard Worker         {
454*8975f5c5SAndroid Build Coastguard Worker             mState.mExecutable->mLinkedOutputVaryings[shaderType] =
455*8975f5c5SAndroid Build Coastguard Worker                 programExecutable->getLinkedOutputVaryings(shaderType);
456*8975f5c5SAndroid Build Coastguard Worker             mState.mExecutable->mLinkedInputVaryings[shaderType] =
457*8975f5c5SAndroid Build Coastguard Worker                 programExecutable->getLinkedInputVaryings(shaderType);
458*8975f5c5SAndroid Build Coastguard Worker         }
459*8975f5c5SAndroid Build Coastguard Worker     }
460*8975f5c5SAndroid Build Coastguard Worker 
461*8975f5c5SAndroid Build Coastguard Worker     const SharedProgramExecutable &computeExecutable =
462*8975f5c5SAndroid Build Coastguard Worker         getShaderProgramExecutable(ShaderType::Compute);
463*8975f5c5SAndroid Build Coastguard Worker     if (computeExecutable)
464*8975f5c5SAndroid Build Coastguard Worker     {
465*8975f5c5SAndroid Build Coastguard Worker         mState.mExecutable->mLinkedOutputVaryings[ShaderType::Compute] =
466*8975f5c5SAndroid Build Coastguard Worker             computeExecutable->getLinkedOutputVaryings(ShaderType::Compute);
467*8975f5c5SAndroid Build Coastguard Worker         mState.mExecutable->mLinkedInputVaryings[ShaderType::Compute] =
468*8975f5c5SAndroid Build Coastguard Worker             computeExecutable->getLinkedInputVaryings(ShaderType::Compute);
469*8975f5c5SAndroid Build Coastguard Worker     }
470*8975f5c5SAndroid Build Coastguard Worker }
471*8975f5c5SAndroid Build Coastguard Worker 
updateExecutable()472*8975f5c5SAndroid Build Coastguard Worker void ProgramPipeline::updateExecutable()
473*8975f5c5SAndroid Build Coastguard Worker {
474*8975f5c5SAndroid Build Coastguard Worker     // Vertex Shader ProgramExecutable properties
475*8975f5c5SAndroid Build Coastguard Worker     updateExecutableAttributes();
476*8975f5c5SAndroid Build Coastguard Worker     updateTransformFeedbackMembers();
477*8975f5c5SAndroid Build Coastguard Worker     updateShaderStorageBlocks();
478*8975f5c5SAndroid Build Coastguard Worker     updateImageBindings();
479*8975f5c5SAndroid Build Coastguard Worker 
480*8975f5c5SAndroid Build Coastguard Worker     // Geometry Shader ProgramExecutable properties
481*8975f5c5SAndroid Build Coastguard Worker     updateExecutableGeometryProperties();
482*8975f5c5SAndroid Build Coastguard Worker 
483*8975f5c5SAndroid Build Coastguard Worker     // Tessellation Shaders ProgramExecutable properties
484*8975f5c5SAndroid Build Coastguard Worker     updateExecutableTessellationProperties();
485*8975f5c5SAndroid Build Coastguard Worker 
486*8975f5c5SAndroid Build Coastguard Worker     // Fragment Shader ProgramExecutable properties
487*8975f5c5SAndroid Build Coastguard Worker     updateFragmentInoutRangeAndEnablesPerSampleShading();
488*8975f5c5SAndroid Build Coastguard Worker 
489*8975f5c5SAndroid Build Coastguard Worker     // All Shader ProgramExecutable properties
490*8975f5c5SAndroid Build Coastguard Worker     mState.updateExecutableTextures();
491*8975f5c5SAndroid Build Coastguard Worker     mState.updateExecutableSpecConstUsageBits();
492*8975f5c5SAndroid Build Coastguard Worker     updateLinkedVaryings();
493*8975f5c5SAndroid Build Coastguard Worker }
494*8975f5c5SAndroid Build Coastguard Worker 
resolveAttachedPrograms(const Context * context)495*8975f5c5SAndroid Build Coastguard Worker void ProgramPipeline::resolveAttachedPrograms(const Context *context)
496*8975f5c5SAndroid Build Coastguard Worker {
497*8975f5c5SAndroid Build Coastguard Worker     // Wait for attached programs to finish linking
498*8975f5c5SAndroid Build Coastguard Worker     for (Program *program : mState.mPrograms)
499*8975f5c5SAndroid Build Coastguard Worker     {
500*8975f5c5SAndroid Build Coastguard Worker         if (program != nullptr)
501*8975f5c5SAndroid Build Coastguard Worker         {
502*8975f5c5SAndroid Build Coastguard Worker             program->resolveLink(context);
503*8975f5c5SAndroid Build Coastguard Worker         }
504*8975f5c5SAndroid Build Coastguard Worker     }
505*8975f5c5SAndroid Build Coastguard Worker }
506*8975f5c5SAndroid Build Coastguard Worker 
507*8975f5c5SAndroid Build Coastguard Worker // The attached shaders are checked for linking errors by matching up their variables.
508*8975f5c5SAndroid Build Coastguard Worker // Uniform, input and output variables get collected.
509*8975f5c5SAndroid Build Coastguard Worker // The code gets compiled into binaries.
link(const Context * context)510*8975f5c5SAndroid Build Coastguard Worker angle::Result ProgramPipeline::link(const Context *context)
511*8975f5c5SAndroid Build Coastguard Worker {
512*8975f5c5SAndroid Build Coastguard Worker     mState.destroyDiscardedExecutables(context);
513*8975f5c5SAndroid Build Coastguard Worker 
514*8975f5c5SAndroid Build Coastguard Worker     // Make a new executable to hold the result of the link.
515*8975f5c5SAndroid Build Coastguard Worker     SharedProgramExecutable newExecutable = mState.makeNewExecutable(
516*8975f5c5SAndroid Build Coastguard Worker         context->getImplementation(), std::move(mState.mExecutable->mPPOProgramExecutables));
517*8975f5c5SAndroid Build Coastguard Worker 
518*8975f5c5SAndroid Build Coastguard Worker     InstallExecutable(context, newExecutable, &mState.mExecutable);
519*8975f5c5SAndroid Build Coastguard Worker     onStateChange(angle::SubjectMessage::ProgramUnlinked);
520*8975f5c5SAndroid Build Coastguard Worker 
521*8975f5c5SAndroid Build Coastguard Worker     updateLinkedShaderStages();
522*8975f5c5SAndroid Build Coastguard Worker 
523*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mState.mIsLinked);
524*8975f5c5SAndroid Build Coastguard Worker 
525*8975f5c5SAndroid Build Coastguard Worker     ProgramMergedVaryings mergedVaryings;
526*8975f5c5SAndroid Build Coastguard Worker     ProgramVaryingPacking varyingPacking;
527*8975f5c5SAndroid Build Coastguard Worker     LinkingVariables linkingVariables;
528*8975f5c5SAndroid Build Coastguard Worker 
529*8975f5c5SAndroid Build Coastguard Worker     mState.mInfoLog.reset();
530*8975f5c5SAndroid Build Coastguard Worker 
531*8975f5c5SAndroid Build Coastguard Worker     linkingVariables.initForProgramPipeline(mState);
532*8975f5c5SAndroid Build Coastguard Worker 
533*8975f5c5SAndroid Build Coastguard Worker     const Caps &caps               = context->getCaps();
534*8975f5c5SAndroid Build Coastguard Worker     const Limitations &limitations = context->getLimitations();
535*8975f5c5SAndroid Build Coastguard Worker     const Version &clientVersion   = context->getClientVersion();
536*8975f5c5SAndroid Build Coastguard Worker     const bool isWebGL             = context->isWebGL();
537*8975f5c5SAndroid Build Coastguard Worker 
538*8975f5c5SAndroid Build Coastguard Worker     if (mState.mExecutable->hasLinkedShaderStage(gl::ShaderType::TessControl) !=
539*8975f5c5SAndroid Build Coastguard Worker         mState.mExecutable->hasLinkedShaderStage(gl::ShaderType::TessEvaluation))
540*8975f5c5SAndroid Build Coastguard Worker     {
541*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Stop;
542*8975f5c5SAndroid Build Coastguard Worker     }
543*8975f5c5SAndroid Build Coastguard Worker 
544*8975f5c5SAndroid Build Coastguard Worker     if (mState.mExecutable->hasLinkedShaderStage(ShaderType::Vertex))
545*8975f5c5SAndroid Build Coastguard Worker     {
546*8975f5c5SAndroid Build Coastguard Worker         if (!linkVaryings())
547*8975f5c5SAndroid Build Coastguard Worker         {
548*8975f5c5SAndroid Build Coastguard Worker             return angle::Result::Stop;
549*8975f5c5SAndroid Build Coastguard Worker         }
550*8975f5c5SAndroid Build Coastguard Worker 
551*8975f5c5SAndroid Build Coastguard Worker         if (!LinkValidateProgramGlobalNames(mState.mInfoLog, getExecutable(), linkingVariables))
552*8975f5c5SAndroid Build Coastguard Worker         {
553*8975f5c5SAndroid Build Coastguard Worker             return angle::Result::Stop;
554*8975f5c5SAndroid Build Coastguard Worker         }
555*8975f5c5SAndroid Build Coastguard Worker 
556*8975f5c5SAndroid Build Coastguard Worker         const SharedProgramExecutable &fragmentExecutable =
557*8975f5c5SAndroid Build Coastguard Worker             getShaderProgramExecutable(ShaderType::Fragment);
558*8975f5c5SAndroid Build Coastguard Worker         if (fragmentExecutable)
559*8975f5c5SAndroid Build Coastguard Worker         {
560*8975f5c5SAndroid Build Coastguard Worker             // We should also be validating SSBO and image uniform counts.
561*8975f5c5SAndroid Build Coastguard Worker             const GLuint combinedImageUniforms       = 0;
562*8975f5c5SAndroid Build Coastguard Worker             const GLuint combinedShaderStorageBlocks = 0;
563*8975f5c5SAndroid Build Coastguard Worker             ASSERT(mState.mExecutable->mOutputVariables.empty());
564*8975f5c5SAndroid Build Coastguard Worker             mState.mExecutable->mOutputVariables = fragmentExecutable->getOutputVariables();
565*8975f5c5SAndroid Build Coastguard Worker             if (!mState.mExecutable->linkValidateOutputVariables(
566*8975f5c5SAndroid Build Coastguard Worker                     caps, clientVersion, combinedImageUniforms, combinedShaderStorageBlocks,
567*8975f5c5SAndroid Build Coastguard Worker                     fragmentExecutable->getLinkedShaderVersion(ShaderType::Fragment),
568*8975f5c5SAndroid Build Coastguard Worker                     ProgramAliasedBindings(), ProgramAliasedBindings()))
569*8975f5c5SAndroid Build Coastguard Worker             {
570*8975f5c5SAndroid Build Coastguard Worker                 return angle::Result::Continue;
571*8975f5c5SAndroid Build Coastguard Worker             }
572*8975f5c5SAndroid Build Coastguard Worker         }
573*8975f5c5SAndroid Build Coastguard Worker         mergedVaryings = GetMergedVaryingsFromLinkingVariables(linkingVariables);
574*8975f5c5SAndroid Build Coastguard Worker         // If separable program objects are in use, the set of attributes captured is taken
575*8975f5c5SAndroid Build Coastguard Worker         // from the program object active on the last vertex processing stage.
576*8975f5c5SAndroid Build Coastguard Worker         ShaderType lastVertexProcessingStage =
577*8975f5c5SAndroid Build Coastguard Worker             GetLastPreFragmentStage(getExecutable().getLinkedShaderStages());
578*8975f5c5SAndroid Build Coastguard Worker         if (lastVertexProcessingStage == ShaderType::InvalidEnum)
579*8975f5c5SAndroid Build Coastguard Worker         {
580*8975f5c5SAndroid Build Coastguard Worker             //  If there is no active program for the vertex or fragment shader stages, the results
581*8975f5c5SAndroid Build Coastguard Worker             //  of vertex and fragment shader execution will respectively be undefined. However,
582*8975f5c5SAndroid Build Coastguard Worker             //  this is not an error.
583*8975f5c5SAndroid Build Coastguard Worker             return angle::Result::Continue;
584*8975f5c5SAndroid Build Coastguard Worker         }
585*8975f5c5SAndroid Build Coastguard Worker 
586*8975f5c5SAndroid Build Coastguard Worker         const SharedProgramExecutable *tfExecutable =
587*8975f5c5SAndroid Build Coastguard Worker             &getShaderProgramExecutable(lastVertexProcessingStage);
588*8975f5c5SAndroid Build Coastguard Worker         ASSERT(*tfExecutable);
589*8975f5c5SAndroid Build Coastguard Worker 
590*8975f5c5SAndroid Build Coastguard Worker         if (!*tfExecutable)
591*8975f5c5SAndroid Build Coastguard Worker         {
592*8975f5c5SAndroid Build Coastguard Worker             tfExecutable = &getShaderProgramExecutable(ShaderType::Vertex);
593*8975f5c5SAndroid Build Coastguard Worker         }
594*8975f5c5SAndroid Build Coastguard Worker 
595*8975f5c5SAndroid Build Coastguard Worker         mState.mExecutable->mTransformFeedbackVaryingNames =
596*8975f5c5SAndroid Build Coastguard Worker             (*tfExecutable)->mTransformFeedbackVaryingNames;
597*8975f5c5SAndroid Build Coastguard Worker 
598*8975f5c5SAndroid Build Coastguard Worker         if (!mState.mExecutable->linkMergedVaryings(caps, limitations, clientVersion, isWebGL,
599*8975f5c5SAndroid Build Coastguard Worker                                                     mergedVaryings, linkingVariables,
600*8975f5c5SAndroid Build Coastguard Worker                                                     &varyingPacking))
601*8975f5c5SAndroid Build Coastguard Worker         {
602*8975f5c5SAndroid Build Coastguard Worker             return angle::Result::Stop;
603*8975f5c5SAndroid Build Coastguard Worker         }
604*8975f5c5SAndroid Build Coastguard Worker     }
605*8975f5c5SAndroid Build Coastguard Worker 
606*8975f5c5SAndroid Build Coastguard Worker     // Merge uniforms.
607*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->copyUniformsFromProgramMap(mState.mExecutable->mPPOProgramExecutables);
608*8975f5c5SAndroid Build Coastguard Worker 
609*8975f5c5SAndroid Build Coastguard Worker     if (mState.mExecutable->hasLinkedShaderStage(ShaderType::Vertex))
610*8975f5c5SAndroid Build Coastguard Worker     {
611*8975f5c5SAndroid Build Coastguard Worker         const SharedProgramExecutable &executable = getShaderProgramExecutable(ShaderType::Vertex);
612*8975f5c5SAndroid Build Coastguard Worker         mState.mExecutable->copyInputsFromProgram(*executable);
613*8975f5c5SAndroid Build Coastguard Worker     }
614*8975f5c5SAndroid Build Coastguard Worker 
615*8975f5c5SAndroid Build Coastguard Worker     // Merge shader buffers (UBOs, SSBOs, and atomic counter buffers) into the executable.
616*8975f5c5SAndroid Build Coastguard Worker     // Also copy over image and sampler bindings.
617*8975f5c5SAndroid Build Coastguard Worker     for (ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
618*8975f5c5SAndroid Build Coastguard Worker     {
619*8975f5c5SAndroid Build Coastguard Worker         const SharedProgramExecutable &executable = getShaderProgramExecutable(shaderType);
620*8975f5c5SAndroid Build Coastguard Worker         mState.mExecutable->copyUniformBuffersFromProgram(*executable, shaderType,
621*8975f5c5SAndroid Build Coastguard Worker                                                           &mState.mUniformBlockMap[shaderType]);
622*8975f5c5SAndroid Build Coastguard Worker         mState.mExecutable->copyStorageBuffersFromProgram(*executable, shaderType);
623*8975f5c5SAndroid Build Coastguard Worker         mState.mExecutable->copySamplerBindingsFromProgram(*executable);
624*8975f5c5SAndroid Build Coastguard Worker         mState.mExecutable->copyImageBindingsFromProgram(*executable);
625*8975f5c5SAndroid Build Coastguard Worker     }
626*8975f5c5SAndroid Build Coastguard Worker 
627*8975f5c5SAndroid Build Coastguard Worker     if (mState.mExecutable->hasLinkedShaderStage(ShaderType::Fragment))
628*8975f5c5SAndroid Build Coastguard Worker     {
629*8975f5c5SAndroid Build Coastguard Worker         const SharedProgramExecutable &executable =
630*8975f5c5SAndroid Build Coastguard Worker             getShaderProgramExecutable(ShaderType::Fragment);
631*8975f5c5SAndroid Build Coastguard Worker         mState.mExecutable->copyOutputsFromProgram(*executable);
632*8975f5c5SAndroid Build Coastguard Worker     }
633*8975f5c5SAndroid Build Coastguard Worker 
634*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->mActiveSamplerRefCounts.fill(0);
635*8975f5c5SAndroid Build Coastguard Worker     updateExecutable();
636*8975f5c5SAndroid Build Coastguard Worker 
637*8975f5c5SAndroid Build Coastguard Worker     if (mState.mExecutable->hasLinkedShaderStage(ShaderType::Vertex) ||
638*8975f5c5SAndroid Build Coastguard Worker         mState.mExecutable->hasLinkedShaderStage(ShaderType::Compute))
639*8975f5c5SAndroid Build Coastguard Worker     {
640*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(getImplementation()->link(context, mergedVaryings, varyingPacking));
641*8975f5c5SAndroid Build Coastguard Worker     }
642*8975f5c5SAndroid Build Coastguard Worker 
643*8975f5c5SAndroid Build Coastguard Worker     mState.mIsLinked = true;
644*8975f5c5SAndroid Build Coastguard Worker     onStateChange(angle::SubjectMessage::ProgramRelinked);
645*8975f5c5SAndroid Build Coastguard Worker 
646*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
647*8975f5c5SAndroid Build Coastguard Worker }
648*8975f5c5SAndroid Build Coastguard Worker 
getInfoLogLength() const649*8975f5c5SAndroid Build Coastguard Worker int ProgramPipeline::getInfoLogLength() const
650*8975f5c5SAndroid Build Coastguard Worker {
651*8975f5c5SAndroid Build Coastguard Worker     return static_cast<int>(mState.mInfoLog.getLength());
652*8975f5c5SAndroid Build Coastguard Worker }
653*8975f5c5SAndroid Build Coastguard Worker 
getInfoLog(GLsizei bufSize,GLsizei * length,char * infoLog) const654*8975f5c5SAndroid Build Coastguard Worker void ProgramPipeline::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
655*8975f5c5SAndroid Build Coastguard Worker {
656*8975f5c5SAndroid Build Coastguard Worker     return mState.mInfoLog.getLog(bufSize, length, infoLog);
657*8975f5c5SAndroid Build Coastguard Worker }
658*8975f5c5SAndroid Build Coastguard Worker 
linkVaryings()659*8975f5c5SAndroid Build Coastguard Worker bool ProgramPipeline::linkVaryings()
660*8975f5c5SAndroid Build Coastguard Worker {
661*8975f5c5SAndroid Build Coastguard Worker     ShaderType previousShaderType = ShaderType::InvalidEnum;
662*8975f5c5SAndroid Build Coastguard Worker     for (ShaderType shaderType : kAllGraphicsShaderTypes)
663*8975f5c5SAndroid Build Coastguard Worker     {
664*8975f5c5SAndroid Build Coastguard Worker         const SharedProgramExecutable &programExecutable = getShaderProgramExecutable(shaderType);
665*8975f5c5SAndroid Build Coastguard Worker         if (!programExecutable)
666*8975f5c5SAndroid Build Coastguard Worker         {
667*8975f5c5SAndroid Build Coastguard Worker             continue;
668*8975f5c5SAndroid Build Coastguard Worker         }
669*8975f5c5SAndroid Build Coastguard Worker 
670*8975f5c5SAndroid Build Coastguard Worker         if (previousShaderType != ShaderType::InvalidEnum)
671*8975f5c5SAndroid Build Coastguard Worker         {
672*8975f5c5SAndroid Build Coastguard Worker             const SharedProgramExecutable &previousExecutable =
673*8975f5c5SAndroid Build Coastguard Worker                 getShaderProgramExecutable(previousShaderType);
674*8975f5c5SAndroid Build Coastguard Worker             ASSERT(previousExecutable);
675*8975f5c5SAndroid Build Coastguard Worker 
676*8975f5c5SAndroid Build Coastguard Worker             if (!LinkValidateShaderInterfaceMatching(
677*8975f5c5SAndroid Build Coastguard Worker                     previousExecutable->getLinkedOutputVaryings(previousShaderType),
678*8975f5c5SAndroid Build Coastguard Worker                     programExecutable->getLinkedInputVaryings(shaderType), previousShaderType,
679*8975f5c5SAndroid Build Coastguard Worker                     shaderType, previousExecutable->getLinkedShaderVersion(previousShaderType),
680*8975f5c5SAndroid Build Coastguard Worker                     programExecutable->getLinkedShaderVersion(shaderType), true, mState.mInfoLog))
681*8975f5c5SAndroid Build Coastguard Worker             {
682*8975f5c5SAndroid Build Coastguard Worker                 return false;
683*8975f5c5SAndroid Build Coastguard Worker             }
684*8975f5c5SAndroid Build Coastguard Worker         }
685*8975f5c5SAndroid Build Coastguard Worker         previousShaderType = shaderType;
686*8975f5c5SAndroid Build Coastguard Worker     }
687*8975f5c5SAndroid Build Coastguard Worker 
688*8975f5c5SAndroid Build Coastguard Worker     // TODO: http://anglebug.com/42262233 and http://anglebug.com/42262234
689*8975f5c5SAndroid Build Coastguard Worker     // Need to move logic of validating builtin varyings inside the for-loop above.
690*8975f5c5SAndroid Build Coastguard Worker     // This is because the built-in symbols `gl_ClipDistance` and `gl_CullDistance`
691*8975f5c5SAndroid Build Coastguard Worker     // can be redeclared in Geometry or Tessellation shaders as well.
692*8975f5c5SAndroid Build Coastguard Worker     const SharedProgramExecutable &vertexExecutable =
693*8975f5c5SAndroid Build Coastguard Worker         getShaderProgramExecutable(ShaderType::Vertex);
694*8975f5c5SAndroid Build Coastguard Worker     const SharedProgramExecutable &fragmentExecutable =
695*8975f5c5SAndroid Build Coastguard Worker         getShaderProgramExecutable(ShaderType::Fragment);
696*8975f5c5SAndroid Build Coastguard Worker     if (!vertexExecutable || !fragmentExecutable)
697*8975f5c5SAndroid Build Coastguard Worker     {
698*8975f5c5SAndroid Build Coastguard Worker         return true;
699*8975f5c5SAndroid Build Coastguard Worker     }
700*8975f5c5SAndroid Build Coastguard Worker     return LinkValidateBuiltInVaryings(
701*8975f5c5SAndroid Build Coastguard Worker         vertexExecutable->getLinkedOutputVaryings(ShaderType::Vertex),
702*8975f5c5SAndroid Build Coastguard Worker         fragmentExecutable->getLinkedInputVaryings(ShaderType::Fragment), ShaderType::Vertex,
703*8975f5c5SAndroid Build Coastguard Worker         ShaderType::Fragment, vertexExecutable->getLinkedShaderVersion(ShaderType::Vertex),
704*8975f5c5SAndroid Build Coastguard Worker         fragmentExecutable->getLinkedShaderVersion(ShaderType::Fragment), mState.mInfoLog);
705*8975f5c5SAndroid Build Coastguard Worker }
706*8975f5c5SAndroid Build Coastguard Worker 
validate(const Context * context)707*8975f5c5SAndroid Build Coastguard Worker void ProgramPipeline::validate(const Context *context)
708*8975f5c5SAndroid Build Coastguard Worker {
709*8975f5c5SAndroid Build Coastguard Worker     updateLinkedShaderStages();
710*8975f5c5SAndroid Build Coastguard Worker 
711*8975f5c5SAndroid Build Coastguard Worker     const Caps &caps = context->getCaps();
712*8975f5c5SAndroid Build Coastguard Worker     mState.mValid    = true;
713*8975f5c5SAndroid Build Coastguard Worker     mState.mInfoLog.reset();
714*8975f5c5SAndroid Build Coastguard Worker 
715*8975f5c5SAndroid Build Coastguard Worker     if (mState.mExecutable->hasLinkedShaderStage(gl::ShaderType::TessControl) !=
716*8975f5c5SAndroid Build Coastguard Worker         mState.mExecutable->hasLinkedShaderStage(gl::ShaderType::TessEvaluation))
717*8975f5c5SAndroid Build Coastguard Worker     {
718*8975f5c5SAndroid Build Coastguard Worker         mState.mValid = false;
719*8975f5c5SAndroid Build Coastguard Worker         mState.mInfoLog << "Program pipeline must have both a Tessellation Control and Evaluation "
720*8975f5c5SAndroid Build Coastguard Worker                            "shader or neither\n";
721*8975f5c5SAndroid Build Coastguard Worker         return;
722*8975f5c5SAndroid Build Coastguard Worker     }
723*8975f5c5SAndroid Build Coastguard Worker 
724*8975f5c5SAndroid Build Coastguard Worker     for (const ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
725*8975f5c5SAndroid Build Coastguard Worker     {
726*8975f5c5SAndroid Build Coastguard Worker         Program *shaderProgram = mState.mPrograms[shaderType];
727*8975f5c5SAndroid Build Coastguard Worker         if (shaderProgram)
728*8975f5c5SAndroid Build Coastguard Worker         {
729*8975f5c5SAndroid Build Coastguard Worker             shaderProgram->resolveLink(context);
730*8975f5c5SAndroid Build Coastguard Worker             shaderProgram->validate(caps);
731*8975f5c5SAndroid Build Coastguard Worker             std::string shaderInfoString = shaderProgram->getExecutable().getInfoLogString();
732*8975f5c5SAndroid Build Coastguard Worker             if (shaderInfoString.length())
733*8975f5c5SAndroid Build Coastguard Worker             {
734*8975f5c5SAndroid Build Coastguard Worker                 mState.mValid = false;
735*8975f5c5SAndroid Build Coastguard Worker                 mState.mInfoLog << shaderInfoString << "\n";
736*8975f5c5SAndroid Build Coastguard Worker                 return;
737*8975f5c5SAndroid Build Coastguard Worker             }
738*8975f5c5SAndroid Build Coastguard Worker             if (!shaderProgram->isSeparable())
739*8975f5c5SAndroid Build Coastguard Worker             {
740*8975f5c5SAndroid Build Coastguard Worker                 mState.mValid = false;
741*8975f5c5SAndroid Build Coastguard Worker                 mState.mInfoLog << GetShaderTypeString(shaderType) << " is not marked separable."
742*8975f5c5SAndroid Build Coastguard Worker                                 << "\n";
743*8975f5c5SAndroid Build Coastguard Worker                 return;
744*8975f5c5SAndroid Build Coastguard Worker             }
745*8975f5c5SAndroid Build Coastguard Worker         }
746*8975f5c5SAndroid Build Coastguard Worker     }
747*8975f5c5SAndroid Build Coastguard Worker 
748*8975f5c5SAndroid Build Coastguard Worker     intptr_t programPipelineError = context->getStateCache().getProgramPipelineError(context);
749*8975f5c5SAndroid Build Coastguard Worker     if (programPipelineError)
750*8975f5c5SAndroid Build Coastguard Worker     {
751*8975f5c5SAndroid Build Coastguard Worker         mState.mValid            = false;
752*8975f5c5SAndroid Build Coastguard Worker         const char *errorMessage = reinterpret_cast<const char *>(programPipelineError);
753*8975f5c5SAndroid Build Coastguard Worker         mState.mInfoLog << errorMessage << "\n";
754*8975f5c5SAndroid Build Coastguard Worker         return;
755*8975f5c5SAndroid Build Coastguard Worker     }
756*8975f5c5SAndroid Build Coastguard Worker 
757*8975f5c5SAndroid Build Coastguard Worker     if (!linkVaryings())
758*8975f5c5SAndroid Build Coastguard Worker     {
759*8975f5c5SAndroid Build Coastguard Worker         mState.mValid = false;
760*8975f5c5SAndroid Build Coastguard Worker 
761*8975f5c5SAndroid Build Coastguard Worker         for (const ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
762*8975f5c5SAndroid Build Coastguard Worker         {
763*8975f5c5SAndroid Build Coastguard Worker             Program *shaderProgram = mState.mPrograms[shaderType];
764*8975f5c5SAndroid Build Coastguard Worker             ASSERT(shaderProgram);
765*8975f5c5SAndroid Build Coastguard Worker             shaderProgram->validate(caps);
766*8975f5c5SAndroid Build Coastguard Worker             std::string shaderInfoString = shaderProgram->getExecutable().getInfoLogString();
767*8975f5c5SAndroid Build Coastguard Worker             if (shaderInfoString.length())
768*8975f5c5SAndroid Build Coastguard Worker             {
769*8975f5c5SAndroid Build Coastguard Worker                 mState.mInfoLog << shaderInfoString << "\n";
770*8975f5c5SAndroid Build Coastguard Worker             }
771*8975f5c5SAndroid Build Coastguard Worker         }
772*8975f5c5SAndroid Build Coastguard Worker     }
773*8975f5c5SAndroid Build Coastguard Worker }
774*8975f5c5SAndroid Build Coastguard Worker 
onSubjectStateChange(angle::SubjectIndex index,angle::SubjectMessage message)775*8975f5c5SAndroid Build Coastguard Worker void ProgramPipeline::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
776*8975f5c5SAndroid Build Coastguard Worker {
777*8975f5c5SAndroid Build Coastguard Worker     switch (message)
778*8975f5c5SAndroid Build Coastguard Worker     {
779*8975f5c5SAndroid Build Coastguard Worker         case angle::SubjectMessage::ProgramTextureOrImageBindingChanged:
780*8975f5c5SAndroid Build Coastguard Worker             mState.mExecutable->mActiveSamplerRefCounts.fill(0);
781*8975f5c5SAndroid Build Coastguard Worker             mState.updateExecutableTextures();
782*8975f5c5SAndroid Build Coastguard Worker             break;
783*8975f5c5SAndroid Build Coastguard Worker 
784*8975f5c5SAndroid Build Coastguard Worker         case angle::SubjectMessage::ProgramUnlinked:
785*8975f5c5SAndroid Build Coastguard Worker             // A used program is being relinked.  Ensure next usage of the PPO resolve the program
786*8975f5c5SAndroid Build Coastguard Worker             // link and relinks the PPO.
787*8975f5c5SAndroid Build Coastguard Worker             mState.mIsLinked = false;
788*8975f5c5SAndroid Build Coastguard Worker             onStateChange(angle::SubjectMessage::ProgramUnlinked);
789*8975f5c5SAndroid Build Coastguard Worker             break;
790*8975f5c5SAndroid Build Coastguard Worker 
791*8975f5c5SAndroid Build Coastguard Worker         case angle::SubjectMessage::ProgramRelinked:
792*8975f5c5SAndroid Build Coastguard Worker         {
793*8975f5c5SAndroid Build Coastguard Worker             ShaderType shaderType = static_cast<ShaderType>(index);
794*8975f5c5SAndroid Build Coastguard Worker             ASSERT(mState.mPrograms[shaderType] != nullptr);
795*8975f5c5SAndroid Build Coastguard Worker             ASSERT(mState.mExecutable->mPPOProgramExecutables[shaderType]);
796*8975f5c5SAndroid Build Coastguard Worker 
797*8975f5c5SAndroid Build Coastguard Worker             mState.mIsLinked = false;
798*8975f5c5SAndroid Build Coastguard Worker             mState.mProgramExecutablesToDiscard.emplace_back(
799*8975f5c5SAndroid Build Coastguard Worker                 std::move(mState.mExecutable->mPPOProgramExecutables[shaderType]));
800*8975f5c5SAndroid Build Coastguard Worker             mState.mExecutable->mPPOProgramExecutables[shaderType] =
801*8975f5c5SAndroid Build Coastguard Worker                 mState.mPrograms[shaderType]->getSharedExecutable();
802*8975f5c5SAndroid Build Coastguard Worker 
803*8975f5c5SAndroid Build Coastguard Worker             break;
804*8975f5c5SAndroid Build Coastguard Worker         }
805*8975f5c5SAndroid Build Coastguard Worker         case angle::SubjectMessage::SamplerUniformsUpdated:
806*8975f5c5SAndroid Build Coastguard Worker             mState.mExecutable->clearSamplerBindings();
807*8975f5c5SAndroid Build Coastguard Worker             for (ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
808*8975f5c5SAndroid Build Coastguard Worker             {
809*8975f5c5SAndroid Build Coastguard Worker                 const SharedProgramExecutable &executable = getShaderProgramExecutable(shaderType);
810*8975f5c5SAndroid Build Coastguard Worker                 mState.mExecutable->copySamplerBindingsFromProgram(*executable);
811*8975f5c5SAndroid Build Coastguard Worker             }
812*8975f5c5SAndroid Build Coastguard Worker             mState.mExecutable->mActiveSamplerRefCounts.fill(0);
813*8975f5c5SAndroid Build Coastguard Worker             mState.updateExecutableTextures();
814*8975f5c5SAndroid Build Coastguard Worker             break;
815*8975f5c5SAndroid Build Coastguard Worker         default:
816*8975f5c5SAndroid Build Coastguard Worker             if (angle::IsProgramUniformBlockBindingUpdatedMessage(message))
817*8975f5c5SAndroid Build Coastguard Worker             {
818*8975f5c5SAndroid Build Coastguard Worker                 if (mState.mIsLinked)
819*8975f5c5SAndroid Build Coastguard Worker                 {
820*8975f5c5SAndroid Build Coastguard Worker                     ShaderType shaderType = static_cast<ShaderType>(index);
821*8975f5c5SAndroid Build Coastguard Worker                     const SharedProgramExecutable &executable =
822*8975f5c5SAndroid Build Coastguard Worker                         getShaderProgramExecutable(shaderType);
823*8975f5c5SAndroid Build Coastguard Worker                     const GLuint blockIndex =
824*8975f5c5SAndroid Build Coastguard Worker                         angle::ProgramUniformBlockBindingUpdatedMessageToIndex(message);
825*8975f5c5SAndroid Build Coastguard Worker                     if (executable->getUniformBlocks()[blockIndex].isActive(shaderType))
826*8975f5c5SAndroid Build Coastguard Worker                     {
827*8975f5c5SAndroid Build Coastguard Worker                         const uint32_t blockIndexInPPO =
828*8975f5c5SAndroid Build Coastguard Worker                             mState.mUniformBlockMap[shaderType][blockIndex];
829*8975f5c5SAndroid Build Coastguard Worker                         ASSERT(blockIndexInPPO < mState.mExecutable->mUniformBlocks.size());
830*8975f5c5SAndroid Build Coastguard Worker 
831*8975f5c5SAndroid Build Coastguard Worker                         // Set the block buffer binding in the PPO to the same binding as the
832*8975f5c5SAndroid Build Coastguard Worker                         // program's.
833*8975f5c5SAndroid Build Coastguard Worker                         mState.mExecutable->remapUniformBlockBinding(
834*8975f5c5SAndroid Build Coastguard Worker                             {blockIndexInPPO}, executable->getUniformBlockBinding(blockIndex));
835*8975f5c5SAndroid Build Coastguard Worker 
836*8975f5c5SAndroid Build Coastguard Worker                         // Notify the contexts that the block binding has changed.
837*8975f5c5SAndroid Build Coastguard Worker                         onStateChange(angle::ProgramUniformBlockBindingUpdatedMessageFromIndex(
838*8975f5c5SAndroid Build Coastguard Worker                             blockIndexInPPO));
839*8975f5c5SAndroid Build Coastguard Worker                     }
840*8975f5c5SAndroid Build Coastguard Worker                 }
841*8975f5c5SAndroid Build Coastguard Worker                 break;
842*8975f5c5SAndroid Build Coastguard Worker             }
843*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
844*8975f5c5SAndroid Build Coastguard Worker             break;
845*8975f5c5SAndroid Build Coastguard Worker     }
846*8975f5c5SAndroid Build Coastguard Worker }
847*8975f5c5SAndroid Build Coastguard Worker }  // namespace gl
848