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