xref: /aosp_15_r20/external/angle/src/libANGLE/Program.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2002 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 // Program.cpp: Implements the gl::Program class. Implements GL program objects
8*8975f5c5SAndroid Build Coastguard Worker // and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
9*8975f5c5SAndroid Build Coastguard Worker 
10*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Program.h"
11*8975f5c5SAndroid Build Coastguard Worker 
12*8975f5c5SAndroid Build Coastguard Worker #include <algorithm>
13*8975f5c5SAndroid Build Coastguard Worker #include <utility>
14*8975f5c5SAndroid Build Coastguard Worker 
15*8975f5c5SAndroid Build Coastguard Worker #include "common/angle_version_info.h"
16*8975f5c5SAndroid Build Coastguard Worker #include "common/bitset_utils.h"
17*8975f5c5SAndroid Build Coastguard Worker #include "common/debug.h"
18*8975f5c5SAndroid Build Coastguard Worker #include "common/platform.h"
19*8975f5c5SAndroid Build Coastguard Worker #include "common/platform_helpers.h"
20*8975f5c5SAndroid Build Coastguard Worker #include "common/string_utils.h"
21*8975f5c5SAndroid Build Coastguard Worker #include "common/utilities.h"
22*8975f5c5SAndroid Build Coastguard Worker #include "compiler/translator/blocklayout.h"
23*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Context.h"
24*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/ErrorStrings.h"
25*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/MemoryProgramCache.h"
26*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/ProgramLinkedResources.h"
27*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/ResourceManager.h"
28*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Uniform.h"
29*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/VaryingPacking.h"
30*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Version.h"
31*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/capture/FrameCapture.h"
32*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/features.h"
33*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/histogram_macros.h"
34*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/queryconversions.h"
35*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/ContextImpl.h"
36*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/GLImplFactory.h"
37*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/ProgramImpl.h"
38*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/trace.h"
39*8975f5c5SAndroid Build Coastguard Worker #include "platform/PlatformMethods.h"
40*8975f5c5SAndroid Build Coastguard Worker #include "platform/autogen/FrontendFeatures_autogen.h"
41*8975f5c5SAndroid Build Coastguard Worker 
42*8975f5c5SAndroid Build Coastguard Worker namespace gl
43*8975f5c5SAndroid Build Coastguard Worker {
44*8975f5c5SAndroid Build Coastguard Worker 
45*8975f5c5SAndroid Build Coastguard Worker namespace
46*8975f5c5SAndroid Build Coastguard Worker {
InitUniformBlockLinker(const ProgramState & state,UniformBlockLinker * blockLinker)47*8975f5c5SAndroid Build Coastguard Worker void InitUniformBlockLinker(const ProgramState &state, UniformBlockLinker *blockLinker)
48*8975f5c5SAndroid Build Coastguard Worker {
49*8975f5c5SAndroid Build Coastguard Worker     for (ShaderType shaderType : AllShaderTypes())
50*8975f5c5SAndroid Build Coastguard Worker     {
51*8975f5c5SAndroid Build Coastguard Worker         const SharedCompiledShaderState &shader = state.getAttachedShader(shaderType);
52*8975f5c5SAndroid Build Coastguard Worker         if (shader)
53*8975f5c5SAndroid Build Coastguard Worker         {
54*8975f5c5SAndroid Build Coastguard Worker             blockLinker->addShaderBlocks(shaderType, &shader->uniformBlocks);
55*8975f5c5SAndroid Build Coastguard Worker         }
56*8975f5c5SAndroid Build Coastguard Worker     }
57*8975f5c5SAndroid Build Coastguard Worker }
58*8975f5c5SAndroid Build Coastguard Worker 
InitShaderStorageBlockLinker(const ProgramState & state,ShaderStorageBlockLinker * blockLinker)59*8975f5c5SAndroid Build Coastguard Worker void InitShaderStorageBlockLinker(const ProgramState &state, ShaderStorageBlockLinker *blockLinker)
60*8975f5c5SAndroid Build Coastguard Worker {
61*8975f5c5SAndroid Build Coastguard Worker     for (ShaderType shaderType : AllShaderTypes())
62*8975f5c5SAndroid Build Coastguard Worker     {
63*8975f5c5SAndroid Build Coastguard Worker         const SharedCompiledShaderState &shader = state.getAttachedShader(shaderType);
64*8975f5c5SAndroid Build Coastguard Worker         if (shader)
65*8975f5c5SAndroid Build Coastguard Worker         {
66*8975f5c5SAndroid Build Coastguard Worker             blockLinker->addShaderBlocks(shaderType, &shader->shaderStorageBlocks);
67*8975f5c5SAndroid Build Coastguard Worker         }
68*8975f5c5SAndroid Build Coastguard Worker     }
69*8975f5c5SAndroid Build Coastguard Worker }
70*8975f5c5SAndroid Build Coastguard Worker 
71*8975f5c5SAndroid Build Coastguard Worker // Provides a mechanism to access the result of asynchronous linking.
72*8975f5c5SAndroid Build Coastguard Worker class LinkEvent : angle::NonCopyable
73*8975f5c5SAndroid Build Coastguard Worker {
74*8975f5c5SAndroid Build Coastguard Worker   public:
~LinkEvent()75*8975f5c5SAndroid Build Coastguard Worker     virtual ~LinkEvent() {}
76*8975f5c5SAndroid Build Coastguard Worker 
77*8975f5c5SAndroid Build Coastguard Worker     // Please be aware that these methods may be called under a gl::Context other
78*8975f5c5SAndroid Build Coastguard Worker     // than the one where the LinkEvent was created.
79*8975f5c5SAndroid Build Coastguard Worker     //
80*8975f5c5SAndroid Build Coastguard Worker     // Waits until the linking is actually done. Returns true if the linking
81*8975f5c5SAndroid Build Coastguard Worker     // succeeded, false otherwise.
82*8975f5c5SAndroid Build Coastguard Worker     virtual angle::Result wait(const Context *context) = 0;
83*8975f5c5SAndroid Build Coastguard Worker     // Peeks whether the linking is still ongoing.
84*8975f5c5SAndroid Build Coastguard Worker     virtual bool isLinking() = 0;
85*8975f5c5SAndroid Build Coastguard Worker };
86*8975f5c5SAndroid Build Coastguard Worker 
87*8975f5c5SAndroid Build Coastguard Worker // Wraps an already done linking.
88*8975f5c5SAndroid Build Coastguard Worker class LinkEventDone final : public LinkEvent
89*8975f5c5SAndroid Build Coastguard Worker {
90*8975f5c5SAndroid Build Coastguard Worker   public:
LinkEventDone(angle::Result result)91*8975f5c5SAndroid Build Coastguard Worker     LinkEventDone(angle::Result result) : mResult(result) {}
wait(const Context * context)92*8975f5c5SAndroid Build Coastguard Worker     angle::Result wait(const Context *context) override { return mResult; }
isLinking()93*8975f5c5SAndroid Build Coastguard Worker     bool isLinking() override { return false; }
94*8975f5c5SAndroid Build Coastguard Worker 
95*8975f5c5SAndroid Build Coastguard Worker   private:
96*8975f5c5SAndroid Build Coastguard Worker     angle::Result mResult;
97*8975f5c5SAndroid Build Coastguard Worker };
98*8975f5c5SAndroid Build Coastguard Worker 
ScheduleSubTasks(const std::shared_ptr<angle::WorkerThreadPool> & workerThreadPool,std::vector<std::shared_ptr<rx::LinkSubTask>> & tasks,std::vector<std::shared_ptr<angle::WaitableEvent>> * eventsOut)99*8975f5c5SAndroid Build Coastguard Worker void ScheduleSubTasks(const std::shared_ptr<angle::WorkerThreadPool> &workerThreadPool,
100*8975f5c5SAndroid Build Coastguard Worker                       std::vector<std::shared_ptr<rx::LinkSubTask>> &tasks,
101*8975f5c5SAndroid Build Coastguard Worker                       std::vector<std::shared_ptr<angle::WaitableEvent>> *eventsOut)
102*8975f5c5SAndroid Build Coastguard Worker {
103*8975f5c5SAndroid Build Coastguard Worker     eventsOut->reserve(tasks.size());
104*8975f5c5SAndroid Build Coastguard Worker     for (const std::shared_ptr<rx::LinkSubTask> &subTask : tasks)
105*8975f5c5SAndroid Build Coastguard Worker     {
106*8975f5c5SAndroid Build Coastguard Worker         eventsOut->push_back(workerThreadPool->postWorkerTask(subTask));
107*8975f5c5SAndroid Build Coastguard Worker     }
108*8975f5c5SAndroid Build Coastguard Worker }
109*8975f5c5SAndroid Build Coastguard Worker }  // anonymous namespace
110*8975f5c5SAndroid Build Coastguard Worker 
GetLinkMismatchErrorString(LinkMismatchError linkError)111*8975f5c5SAndroid Build Coastguard Worker const char *GetLinkMismatchErrorString(LinkMismatchError linkError)
112*8975f5c5SAndroid Build Coastguard Worker {
113*8975f5c5SAndroid Build Coastguard Worker     switch (linkError)
114*8975f5c5SAndroid Build Coastguard Worker     {
115*8975f5c5SAndroid Build Coastguard Worker         case LinkMismatchError::TYPE_MISMATCH:
116*8975f5c5SAndroid Build Coastguard Worker             return "Type";
117*8975f5c5SAndroid Build Coastguard Worker         case LinkMismatchError::ARRAYNESS_MISMATCH:
118*8975f5c5SAndroid Build Coastguard Worker             return "Array-ness";
119*8975f5c5SAndroid Build Coastguard Worker         case LinkMismatchError::ARRAY_SIZE_MISMATCH:
120*8975f5c5SAndroid Build Coastguard Worker             return "Array size";
121*8975f5c5SAndroid Build Coastguard Worker         case LinkMismatchError::PRECISION_MISMATCH:
122*8975f5c5SAndroid Build Coastguard Worker             return "Precision";
123*8975f5c5SAndroid Build Coastguard Worker         case LinkMismatchError::STRUCT_NAME_MISMATCH:
124*8975f5c5SAndroid Build Coastguard Worker             return "Structure name";
125*8975f5c5SAndroid Build Coastguard Worker         case LinkMismatchError::FIELD_NUMBER_MISMATCH:
126*8975f5c5SAndroid Build Coastguard Worker             return "Field number";
127*8975f5c5SAndroid Build Coastguard Worker         case LinkMismatchError::FIELD_NAME_MISMATCH:
128*8975f5c5SAndroid Build Coastguard Worker             return "Field name";
129*8975f5c5SAndroid Build Coastguard Worker 
130*8975f5c5SAndroid Build Coastguard Worker         case LinkMismatchError::INTERPOLATION_TYPE_MISMATCH:
131*8975f5c5SAndroid Build Coastguard Worker             return "Interpolation type";
132*8975f5c5SAndroid Build Coastguard Worker         case LinkMismatchError::INVARIANCE_MISMATCH:
133*8975f5c5SAndroid Build Coastguard Worker             return "Invariance";
134*8975f5c5SAndroid Build Coastguard Worker 
135*8975f5c5SAndroid Build Coastguard Worker         case LinkMismatchError::BINDING_MISMATCH:
136*8975f5c5SAndroid Build Coastguard Worker             return "Binding layout qualifier";
137*8975f5c5SAndroid Build Coastguard Worker         case LinkMismatchError::LOCATION_MISMATCH:
138*8975f5c5SAndroid Build Coastguard Worker             return "Location layout qualifier";
139*8975f5c5SAndroid Build Coastguard Worker         case LinkMismatchError::OFFSET_MISMATCH:
140*8975f5c5SAndroid Build Coastguard Worker             return "Offset layout qualifier";
141*8975f5c5SAndroid Build Coastguard Worker         case LinkMismatchError::INSTANCE_NAME_MISMATCH:
142*8975f5c5SAndroid Build Coastguard Worker             return "Instance name qualifier";
143*8975f5c5SAndroid Build Coastguard Worker         case LinkMismatchError::FORMAT_MISMATCH:
144*8975f5c5SAndroid Build Coastguard Worker             return "Format qualifier";
145*8975f5c5SAndroid Build Coastguard Worker 
146*8975f5c5SAndroid Build Coastguard Worker         case LinkMismatchError::LAYOUT_QUALIFIER_MISMATCH:
147*8975f5c5SAndroid Build Coastguard Worker             return "Layout qualifier";
148*8975f5c5SAndroid Build Coastguard Worker         case LinkMismatchError::MATRIX_PACKING_MISMATCH:
149*8975f5c5SAndroid Build Coastguard Worker             return "Matrix Packing";
150*8975f5c5SAndroid Build Coastguard Worker 
151*8975f5c5SAndroid Build Coastguard Worker         case LinkMismatchError::FIELD_LOCATION_MISMATCH:
152*8975f5c5SAndroid Build Coastguard Worker             return "Field location";
153*8975f5c5SAndroid Build Coastguard Worker         case LinkMismatchError::FIELD_STRUCT_NAME_MISMATCH:
154*8975f5c5SAndroid Build Coastguard Worker             return "Field structure name";
155*8975f5c5SAndroid Build Coastguard Worker         default:
156*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
157*8975f5c5SAndroid Build Coastguard Worker             return "";
158*8975f5c5SAndroid Build Coastguard Worker     }
159*8975f5c5SAndroid Build Coastguard Worker }
160*8975f5c5SAndroid Build Coastguard Worker 
161*8975f5c5SAndroid Build Coastguard Worker template <typename T>
UpdateInterfaceVariable(std::vector<T> * block,const sh::ShaderVariable & var)162*8975f5c5SAndroid Build Coastguard Worker void UpdateInterfaceVariable(std::vector<T> *block, const sh::ShaderVariable &var)
163*8975f5c5SAndroid Build Coastguard Worker {
164*8975f5c5SAndroid Build Coastguard Worker     if (!var.isStruct())
165*8975f5c5SAndroid Build Coastguard Worker     {
166*8975f5c5SAndroid Build Coastguard Worker         block->emplace_back(var);
167*8975f5c5SAndroid Build Coastguard Worker         block->back().resetEffectiveLocation();
168*8975f5c5SAndroid Build Coastguard Worker     }
169*8975f5c5SAndroid Build Coastguard Worker 
170*8975f5c5SAndroid Build Coastguard Worker     for (const sh::ShaderVariable &field : var.fields)
171*8975f5c5SAndroid Build Coastguard Worker     {
172*8975f5c5SAndroid Build Coastguard Worker         ASSERT(!var.name.empty() || var.isShaderIOBlock);
173*8975f5c5SAndroid Build Coastguard Worker 
174*8975f5c5SAndroid Build Coastguard Worker         // Shader I/O block naming is similar to UBOs and SSBOs:
175*8975f5c5SAndroid Build Coastguard Worker         //
176*8975f5c5SAndroid Build Coastguard Worker         //     in Block
177*8975f5c5SAndroid Build Coastguard Worker         //     {
178*8975f5c5SAndroid Build Coastguard Worker         //         type field;  // produces "field"
179*8975f5c5SAndroid Build Coastguard Worker         //     };
180*8975f5c5SAndroid Build Coastguard Worker         //
181*8975f5c5SAndroid Build Coastguard Worker         //     in Block2
182*8975f5c5SAndroid Build Coastguard Worker         //     {
183*8975f5c5SAndroid Build Coastguard Worker         //         type field;  // produces "Block2.field"
184*8975f5c5SAndroid Build Coastguard Worker         //     } block2;
185*8975f5c5SAndroid Build Coastguard Worker         //
186*8975f5c5SAndroid Build Coastguard Worker         const std::string &baseName = var.isShaderIOBlock ? var.structOrBlockName : var.name;
187*8975f5c5SAndroid Build Coastguard Worker         const std::string prefix    = var.name.empty() ? "" : baseName + ".";
188*8975f5c5SAndroid Build Coastguard Worker 
189*8975f5c5SAndroid Build Coastguard Worker         if (!field.isStruct())
190*8975f5c5SAndroid Build Coastguard Worker         {
191*8975f5c5SAndroid Build Coastguard Worker             sh::ShaderVariable fieldCopy = field;
192*8975f5c5SAndroid Build Coastguard Worker             fieldCopy.updateEffectiveLocation(var);
193*8975f5c5SAndroid Build Coastguard Worker             fieldCopy.name = prefix + field.name;
194*8975f5c5SAndroid Build Coastguard Worker             block->emplace_back(fieldCopy);
195*8975f5c5SAndroid Build Coastguard Worker         }
196*8975f5c5SAndroid Build Coastguard Worker 
197*8975f5c5SAndroid Build Coastguard Worker         for (const sh::ShaderVariable &nested : field.fields)
198*8975f5c5SAndroid Build Coastguard Worker         {
199*8975f5c5SAndroid Build Coastguard Worker             sh::ShaderVariable nestedCopy = nested;
200*8975f5c5SAndroid Build Coastguard Worker             nestedCopy.updateEffectiveLocation(field);
201*8975f5c5SAndroid Build Coastguard Worker             nestedCopy.name = prefix + field.name + "." + nested.name;
202*8975f5c5SAndroid Build Coastguard Worker             block->emplace_back(nestedCopy);
203*8975f5c5SAndroid Build Coastguard Worker         }
204*8975f5c5SAndroid Build Coastguard Worker     }
205*8975f5c5SAndroid Build Coastguard Worker }
206*8975f5c5SAndroid Build Coastguard Worker 
207*8975f5c5SAndroid Build Coastguard Worker // Saves the linking context for later use in resolveLink().
208*8975f5c5SAndroid Build Coastguard Worker struct Program::LinkingState
209*8975f5c5SAndroid Build Coastguard Worker {
210*8975f5c5SAndroid Build Coastguard Worker     LinkingVariables linkingVariables;
211*8975f5c5SAndroid Build Coastguard Worker     ProgramLinkedResources resources;
212*8975f5c5SAndroid Build Coastguard Worker     std::unique_ptr<LinkEvent> linkEvent;
213*8975f5c5SAndroid Build Coastguard Worker     bool linkingFromBinary;
214*8975f5c5SAndroid Build Coastguard Worker };
215*8975f5c5SAndroid Build Coastguard Worker 
216*8975f5c5SAndroid Build Coastguard Worker const char *const g_fakepath = "C:\\fakepath";
217*8975f5c5SAndroid Build Coastguard Worker 
218*8975f5c5SAndroid Build Coastguard Worker // InfoLog implementation.
InfoLog()219*8975f5c5SAndroid Build Coastguard Worker InfoLog::InfoLog() : mLazyStream(nullptr) {}
220*8975f5c5SAndroid Build Coastguard Worker 
~InfoLog()221*8975f5c5SAndroid Build Coastguard Worker InfoLog::~InfoLog() {}
222*8975f5c5SAndroid Build Coastguard Worker 
getLength() const223*8975f5c5SAndroid Build Coastguard Worker size_t InfoLog::getLength() const
224*8975f5c5SAndroid Build Coastguard Worker {
225*8975f5c5SAndroid Build Coastguard Worker     if (!mLazyStream)
226*8975f5c5SAndroid Build Coastguard Worker     {
227*8975f5c5SAndroid Build Coastguard Worker         return 0;
228*8975f5c5SAndroid Build Coastguard Worker     }
229*8975f5c5SAndroid Build Coastguard Worker 
230*8975f5c5SAndroid Build Coastguard Worker     const std::string &logString = mLazyStream->str();
231*8975f5c5SAndroid Build Coastguard Worker     return logString.empty() ? 0 : logString.length() + 1;
232*8975f5c5SAndroid Build Coastguard Worker }
233*8975f5c5SAndroid Build Coastguard Worker 
getLog(GLsizei bufSize,GLsizei * length,char * infoLog) const234*8975f5c5SAndroid Build Coastguard Worker void InfoLog::getLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
235*8975f5c5SAndroid Build Coastguard Worker {
236*8975f5c5SAndroid Build Coastguard Worker     size_t index = 0;
237*8975f5c5SAndroid Build Coastguard Worker 
238*8975f5c5SAndroid Build Coastguard Worker     if (bufSize > 0)
239*8975f5c5SAndroid Build Coastguard Worker     {
240*8975f5c5SAndroid Build Coastguard Worker         const std::string logString(str());
241*8975f5c5SAndroid Build Coastguard Worker 
242*8975f5c5SAndroid Build Coastguard Worker         if (!logString.empty())
243*8975f5c5SAndroid Build Coastguard Worker         {
244*8975f5c5SAndroid Build Coastguard Worker             index = std::min(static_cast<size_t>(bufSize) - 1, logString.length());
245*8975f5c5SAndroid Build Coastguard Worker             memcpy(infoLog, logString.c_str(), index);
246*8975f5c5SAndroid Build Coastguard Worker         }
247*8975f5c5SAndroid Build Coastguard Worker 
248*8975f5c5SAndroid Build Coastguard Worker         infoLog[index] = '\0';
249*8975f5c5SAndroid Build Coastguard Worker     }
250*8975f5c5SAndroid Build Coastguard Worker 
251*8975f5c5SAndroid Build Coastguard Worker     if (length)
252*8975f5c5SAndroid Build Coastguard Worker     {
253*8975f5c5SAndroid Build Coastguard Worker         *length = static_cast<GLsizei>(index);
254*8975f5c5SAndroid Build Coastguard Worker     }
255*8975f5c5SAndroid Build Coastguard Worker }
256*8975f5c5SAndroid Build Coastguard Worker 
257*8975f5c5SAndroid Build Coastguard Worker // append a sanitized message to the program info log.
258*8975f5c5SAndroid Build Coastguard Worker // The D3D compiler includes a fake file path in some of the warning or error
259*8975f5c5SAndroid Build Coastguard Worker // messages, so lets remove all occurrences of this fake file path from the log.
appendSanitized(const char * message)260*8975f5c5SAndroid Build Coastguard Worker void InfoLog::appendSanitized(const char *message)
261*8975f5c5SAndroid Build Coastguard Worker {
262*8975f5c5SAndroid Build Coastguard Worker     ensureInitialized();
263*8975f5c5SAndroid Build Coastguard Worker 
264*8975f5c5SAndroid Build Coastguard Worker     std::string msg(message);
265*8975f5c5SAndroid Build Coastguard Worker 
266*8975f5c5SAndroid Build Coastguard Worker     size_t found;
267*8975f5c5SAndroid Build Coastguard Worker     do
268*8975f5c5SAndroid Build Coastguard Worker     {
269*8975f5c5SAndroid Build Coastguard Worker         found = msg.find(g_fakepath);
270*8975f5c5SAndroid Build Coastguard Worker         if (found != std::string::npos)
271*8975f5c5SAndroid Build Coastguard Worker         {
272*8975f5c5SAndroid Build Coastguard Worker             msg.erase(found, strlen(g_fakepath));
273*8975f5c5SAndroid Build Coastguard Worker         }
274*8975f5c5SAndroid Build Coastguard Worker     } while (found != std::string::npos);
275*8975f5c5SAndroid Build Coastguard Worker 
276*8975f5c5SAndroid Build Coastguard Worker     if (!msg.empty())
277*8975f5c5SAndroid Build Coastguard Worker     {
278*8975f5c5SAndroid Build Coastguard Worker         *mLazyStream << message << std::endl;
279*8975f5c5SAndroid Build Coastguard Worker     }
280*8975f5c5SAndroid Build Coastguard Worker }
281*8975f5c5SAndroid Build Coastguard Worker 
reset()282*8975f5c5SAndroid Build Coastguard Worker void InfoLog::reset()
283*8975f5c5SAndroid Build Coastguard Worker {
284*8975f5c5SAndroid Build Coastguard Worker     if (mLazyStream)
285*8975f5c5SAndroid Build Coastguard Worker     {
286*8975f5c5SAndroid Build Coastguard Worker         mLazyStream.reset(nullptr);
287*8975f5c5SAndroid Build Coastguard Worker     }
288*8975f5c5SAndroid Build Coastguard Worker }
289*8975f5c5SAndroid Build Coastguard Worker 
empty() const290*8975f5c5SAndroid Build Coastguard Worker bool InfoLog::empty() const
291*8975f5c5SAndroid Build Coastguard Worker {
292*8975f5c5SAndroid Build Coastguard Worker     if (!mLazyStream)
293*8975f5c5SAndroid Build Coastguard Worker     {
294*8975f5c5SAndroid Build Coastguard Worker         return true;
295*8975f5c5SAndroid Build Coastguard Worker     }
296*8975f5c5SAndroid Build Coastguard Worker 
297*8975f5c5SAndroid Build Coastguard Worker     return mLazyStream->rdbuf()->in_avail() == 0;
298*8975f5c5SAndroid Build Coastguard Worker }
299*8975f5c5SAndroid Build Coastguard Worker 
LogLinkMismatch(InfoLog & infoLog,const std::string & variableName,const char * variableType,LinkMismatchError linkError,const std::string & mismatchedStructOrBlockFieldName,ShaderType shaderType1,ShaderType shaderType2)300*8975f5c5SAndroid Build Coastguard Worker void LogLinkMismatch(InfoLog &infoLog,
301*8975f5c5SAndroid Build Coastguard Worker                      const std::string &variableName,
302*8975f5c5SAndroid Build Coastguard Worker                      const char *variableType,
303*8975f5c5SAndroid Build Coastguard Worker                      LinkMismatchError linkError,
304*8975f5c5SAndroid Build Coastguard Worker                      const std::string &mismatchedStructOrBlockFieldName,
305*8975f5c5SAndroid Build Coastguard Worker                      ShaderType shaderType1,
306*8975f5c5SAndroid Build Coastguard Worker                      ShaderType shaderType2)
307*8975f5c5SAndroid Build Coastguard Worker {
308*8975f5c5SAndroid Build Coastguard Worker     std::ostringstream stream;
309*8975f5c5SAndroid Build Coastguard Worker     stream << GetLinkMismatchErrorString(linkError) << "s of " << variableType << " '"
310*8975f5c5SAndroid Build Coastguard Worker            << variableName;
311*8975f5c5SAndroid Build Coastguard Worker 
312*8975f5c5SAndroid Build Coastguard Worker     if (!mismatchedStructOrBlockFieldName.empty())
313*8975f5c5SAndroid Build Coastguard Worker     {
314*8975f5c5SAndroid Build Coastguard Worker         stream << "' member '" << variableName << "." << mismatchedStructOrBlockFieldName;
315*8975f5c5SAndroid Build Coastguard Worker     }
316*8975f5c5SAndroid Build Coastguard Worker 
317*8975f5c5SAndroid Build Coastguard Worker     stream << "' differ between " << GetShaderTypeString(shaderType1) << " and "
318*8975f5c5SAndroid Build Coastguard Worker            << GetShaderTypeString(shaderType2) << " shaders.";
319*8975f5c5SAndroid Build Coastguard Worker 
320*8975f5c5SAndroid Build Coastguard Worker     infoLog << stream.str();
321*8975f5c5SAndroid Build Coastguard Worker }
322*8975f5c5SAndroid Build Coastguard Worker 
IsActiveInterfaceBlock(const sh::InterfaceBlock & interfaceBlock)323*8975f5c5SAndroid Build Coastguard Worker bool IsActiveInterfaceBlock(const sh::InterfaceBlock &interfaceBlock)
324*8975f5c5SAndroid Build Coastguard Worker {
325*8975f5c5SAndroid Build Coastguard Worker     // Only 'packed' blocks are allowed to be considered inactive.
326*8975f5c5SAndroid Build Coastguard Worker     return interfaceBlock.active || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED;
327*8975f5c5SAndroid Build Coastguard Worker }
328*8975f5c5SAndroid Build Coastguard Worker 
329*8975f5c5SAndroid Build Coastguard Worker // VariableLocation implementation.
VariableLocation()330*8975f5c5SAndroid Build Coastguard Worker VariableLocation::VariableLocation() : index(kUnused), arrayIndex(0), ignored(false) {}
331*8975f5c5SAndroid Build Coastguard Worker 
VariableLocation(unsigned int arrayIndexIn,unsigned int index)332*8975f5c5SAndroid Build Coastguard Worker VariableLocation::VariableLocation(unsigned int arrayIndexIn, unsigned int index)
333*8975f5c5SAndroid Build Coastguard Worker     : index(index), ignored(false)
334*8975f5c5SAndroid Build Coastguard Worker {
335*8975f5c5SAndroid Build Coastguard Worker     ASSERT(arrayIndex != GL_INVALID_INDEX);
336*8975f5c5SAndroid Build Coastguard Worker     SetBitField(arrayIndex, arrayIndexIn);
337*8975f5c5SAndroid Build Coastguard Worker }
338*8975f5c5SAndroid Build Coastguard Worker 
339*8975f5c5SAndroid Build Coastguard Worker // ProgramBindings implementation.
ProgramBindings()340*8975f5c5SAndroid Build Coastguard Worker ProgramBindings::ProgramBindings() {}
341*8975f5c5SAndroid Build Coastguard Worker 
~ProgramBindings()342*8975f5c5SAndroid Build Coastguard Worker ProgramBindings::~ProgramBindings() {}
343*8975f5c5SAndroid Build Coastguard Worker 
bindLocation(GLuint index,const std::string & name)344*8975f5c5SAndroid Build Coastguard Worker void ProgramBindings::bindLocation(GLuint index, const std::string &name)
345*8975f5c5SAndroid Build Coastguard Worker {
346*8975f5c5SAndroid Build Coastguard Worker     mBindings[name] = index;
347*8975f5c5SAndroid Build Coastguard Worker }
348*8975f5c5SAndroid Build Coastguard Worker 
getBindingByName(const std::string & name) const349*8975f5c5SAndroid Build Coastguard Worker int ProgramBindings::getBindingByName(const std::string &name) const
350*8975f5c5SAndroid Build Coastguard Worker {
351*8975f5c5SAndroid Build Coastguard Worker     auto iter = mBindings.find(name);
352*8975f5c5SAndroid Build Coastguard Worker     return (iter != mBindings.end()) ? iter->second : -1;
353*8975f5c5SAndroid Build Coastguard Worker }
354*8975f5c5SAndroid Build Coastguard Worker 
355*8975f5c5SAndroid Build Coastguard Worker template <typename T>
getBinding(const T & variable) const356*8975f5c5SAndroid Build Coastguard Worker int ProgramBindings::getBinding(const T &variable) const
357*8975f5c5SAndroid Build Coastguard Worker {
358*8975f5c5SAndroid Build Coastguard Worker     return getBindingByName(variable.name);
359*8975f5c5SAndroid Build Coastguard Worker }
360*8975f5c5SAndroid Build Coastguard Worker 
begin() const361*8975f5c5SAndroid Build Coastguard Worker ProgramBindings::const_iterator ProgramBindings::begin() const
362*8975f5c5SAndroid Build Coastguard Worker {
363*8975f5c5SAndroid Build Coastguard Worker     return mBindings.begin();
364*8975f5c5SAndroid Build Coastguard Worker }
365*8975f5c5SAndroid Build Coastguard Worker 
end() const366*8975f5c5SAndroid Build Coastguard Worker ProgramBindings::const_iterator ProgramBindings::end() const
367*8975f5c5SAndroid Build Coastguard Worker {
368*8975f5c5SAndroid Build Coastguard Worker     return mBindings.end();
369*8975f5c5SAndroid Build Coastguard Worker }
370*8975f5c5SAndroid Build Coastguard Worker 
getStableIterationMap() const371*8975f5c5SAndroid Build Coastguard Worker std::map<std::string, GLuint> ProgramBindings::getStableIterationMap() const
372*8975f5c5SAndroid Build Coastguard Worker {
373*8975f5c5SAndroid Build Coastguard Worker     return std::map<std::string, GLuint>(mBindings.begin(), mBindings.end());
374*8975f5c5SAndroid Build Coastguard Worker }
375*8975f5c5SAndroid Build Coastguard Worker 
376*8975f5c5SAndroid Build Coastguard Worker // ProgramAliasedBindings implementation.
ProgramAliasedBindings()377*8975f5c5SAndroid Build Coastguard Worker ProgramAliasedBindings::ProgramAliasedBindings() {}
378*8975f5c5SAndroid Build Coastguard Worker 
~ProgramAliasedBindings()379*8975f5c5SAndroid Build Coastguard Worker ProgramAliasedBindings::~ProgramAliasedBindings() {}
380*8975f5c5SAndroid Build Coastguard Worker 
bindLocation(GLuint index,const std::string & name)381*8975f5c5SAndroid Build Coastguard Worker void ProgramAliasedBindings::bindLocation(GLuint index, const std::string &name)
382*8975f5c5SAndroid Build Coastguard Worker {
383*8975f5c5SAndroid Build Coastguard Worker     mBindings[name] = ProgramBinding(index);
384*8975f5c5SAndroid Build Coastguard Worker 
385*8975f5c5SAndroid Build Coastguard Worker     // EXT_blend_func_extended spec: "If it specifies the base name of an array,
386*8975f5c5SAndroid Build Coastguard Worker     // it identifies the resources associated with the first element of the array."
387*8975f5c5SAndroid Build Coastguard Worker     //
388*8975f5c5SAndroid Build Coastguard Worker     // Normalize array bindings so that "name" and "name[0]" map to the same entry.
389*8975f5c5SAndroid Build Coastguard Worker     // If this binding is of the form "name[0]", then mark the "name" binding as
390*8975f5c5SAndroid Build Coastguard Worker     // aliased but do not update it yet in case "name" is not actually an array.
391*8975f5c5SAndroid Build Coastguard Worker     size_t nameLengthWithoutArrayIndex;
392*8975f5c5SAndroid Build Coastguard Worker     unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
393*8975f5c5SAndroid Build Coastguard Worker     if (arrayIndex == 0)
394*8975f5c5SAndroid Build Coastguard Worker     {
395*8975f5c5SAndroid Build Coastguard Worker         std::string baseName = name.substr(0u, nameLengthWithoutArrayIndex);
396*8975f5c5SAndroid Build Coastguard Worker         auto iter            = mBindings.find(baseName);
397*8975f5c5SAndroid Build Coastguard Worker         if (iter != mBindings.end())
398*8975f5c5SAndroid Build Coastguard Worker         {
399*8975f5c5SAndroid Build Coastguard Worker             iter->second.aliased = true;
400*8975f5c5SAndroid Build Coastguard Worker         }
401*8975f5c5SAndroid Build Coastguard Worker     }
402*8975f5c5SAndroid Build Coastguard Worker }
403*8975f5c5SAndroid Build Coastguard Worker 
getBindingByName(const std::string & name) const404*8975f5c5SAndroid Build Coastguard Worker int ProgramAliasedBindings::getBindingByName(const std::string &name) const
405*8975f5c5SAndroid Build Coastguard Worker {
406*8975f5c5SAndroid Build Coastguard Worker     auto iter = mBindings.find(name);
407*8975f5c5SAndroid Build Coastguard Worker     return (iter != mBindings.end()) ? iter->second.location : -1;
408*8975f5c5SAndroid Build Coastguard Worker }
409*8975f5c5SAndroid Build Coastguard Worker 
getBindingByLocation(GLuint location) const410*8975f5c5SAndroid Build Coastguard Worker int ProgramAliasedBindings::getBindingByLocation(GLuint location) const
411*8975f5c5SAndroid Build Coastguard Worker {
412*8975f5c5SAndroid Build Coastguard Worker     for (const auto &iter : mBindings)
413*8975f5c5SAndroid Build Coastguard Worker     {
414*8975f5c5SAndroid Build Coastguard Worker         if (iter.second.location == location)
415*8975f5c5SAndroid Build Coastguard Worker         {
416*8975f5c5SAndroid Build Coastguard Worker             return iter.second.location;
417*8975f5c5SAndroid Build Coastguard Worker         }
418*8975f5c5SAndroid Build Coastguard Worker     }
419*8975f5c5SAndroid Build Coastguard Worker     return -1;
420*8975f5c5SAndroid Build Coastguard Worker }
421*8975f5c5SAndroid Build Coastguard Worker 
422*8975f5c5SAndroid Build Coastguard Worker template <typename T>
getBinding(const T & variable) const423*8975f5c5SAndroid Build Coastguard Worker int ProgramAliasedBindings::getBinding(const T &variable) const
424*8975f5c5SAndroid Build Coastguard Worker {
425*8975f5c5SAndroid Build Coastguard Worker     const std::string &name = variable.name;
426*8975f5c5SAndroid Build Coastguard Worker 
427*8975f5c5SAndroid Build Coastguard Worker     // Check with the normalized array name if applicable.
428*8975f5c5SAndroid Build Coastguard Worker     if (variable.isArray())
429*8975f5c5SAndroid Build Coastguard Worker     {
430*8975f5c5SAndroid Build Coastguard Worker         size_t nameLengthWithoutArrayIndex;
431*8975f5c5SAndroid Build Coastguard Worker         unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
432*8975f5c5SAndroid Build Coastguard Worker         if (arrayIndex == 0)
433*8975f5c5SAndroid Build Coastguard Worker         {
434*8975f5c5SAndroid Build Coastguard Worker             std::string baseName = name.substr(0u, nameLengthWithoutArrayIndex);
435*8975f5c5SAndroid Build Coastguard Worker             auto iter            = mBindings.find(baseName);
436*8975f5c5SAndroid Build Coastguard Worker             // If "name" exists and is not aliased, that means it was modified more
437*8975f5c5SAndroid Build Coastguard Worker             // recently than its "name[0]" form and should be used instead of that.
438*8975f5c5SAndroid Build Coastguard Worker             if (iter != mBindings.end() && !iter->second.aliased)
439*8975f5c5SAndroid Build Coastguard Worker             {
440*8975f5c5SAndroid Build Coastguard Worker                 return iter->second.location;
441*8975f5c5SAndroid Build Coastguard Worker             }
442*8975f5c5SAndroid Build Coastguard Worker         }
443*8975f5c5SAndroid Build Coastguard Worker         else if (arrayIndex == GL_INVALID_INDEX)
444*8975f5c5SAndroid Build Coastguard Worker         {
445*8975f5c5SAndroid Build Coastguard Worker             auto iter = mBindings.find(variable.name);
446*8975f5c5SAndroid Build Coastguard Worker             // If "name" exists and is not aliased, that means it was modified more
447*8975f5c5SAndroid Build Coastguard Worker             // recently than its "name[0]" form and should be used instead of that.
448*8975f5c5SAndroid Build Coastguard Worker             if (iter != mBindings.end() && !iter->second.aliased)
449*8975f5c5SAndroid Build Coastguard Worker             {
450*8975f5c5SAndroid Build Coastguard Worker                 return iter->second.location;
451*8975f5c5SAndroid Build Coastguard Worker             }
452*8975f5c5SAndroid Build Coastguard Worker             // The base name was aliased, so use the name with the array notation.
453*8975f5c5SAndroid Build Coastguard Worker             return getBindingByName(name + "[0]");
454*8975f5c5SAndroid Build Coastguard Worker         }
455*8975f5c5SAndroid Build Coastguard Worker     }
456*8975f5c5SAndroid Build Coastguard Worker 
457*8975f5c5SAndroid Build Coastguard Worker     return getBindingByName(name);
458*8975f5c5SAndroid Build Coastguard Worker }
459*8975f5c5SAndroid Build Coastguard Worker template int ProgramAliasedBindings::getBinding<UsedUniform>(const UsedUniform &variable) const;
460*8975f5c5SAndroid Build Coastguard Worker template int ProgramAliasedBindings::getBinding<ProgramOutput>(const ProgramOutput &variable) const;
461*8975f5c5SAndroid Build Coastguard Worker template int ProgramAliasedBindings::getBinding<sh::ShaderVariable>(
462*8975f5c5SAndroid Build Coastguard Worker     const sh::ShaderVariable &variable) const;
463*8975f5c5SAndroid Build Coastguard Worker 
begin() const464*8975f5c5SAndroid Build Coastguard Worker ProgramAliasedBindings::const_iterator ProgramAliasedBindings::begin() const
465*8975f5c5SAndroid Build Coastguard Worker {
466*8975f5c5SAndroid Build Coastguard Worker     return mBindings.begin();
467*8975f5c5SAndroid Build Coastguard Worker }
468*8975f5c5SAndroid Build Coastguard Worker 
end() const469*8975f5c5SAndroid Build Coastguard Worker ProgramAliasedBindings::const_iterator ProgramAliasedBindings::end() const
470*8975f5c5SAndroid Build Coastguard Worker {
471*8975f5c5SAndroid Build Coastguard Worker     return mBindings.end();
472*8975f5c5SAndroid Build Coastguard Worker }
473*8975f5c5SAndroid Build Coastguard Worker 
getStableIterationMap() const474*8975f5c5SAndroid Build Coastguard Worker std::map<std::string, ProgramBinding> ProgramAliasedBindings::getStableIterationMap() const
475*8975f5c5SAndroid Build Coastguard Worker {
476*8975f5c5SAndroid Build Coastguard Worker     return std::map<std::string, ProgramBinding>(mBindings.begin(), mBindings.end());
477*8975f5c5SAndroid Build Coastguard Worker }
478*8975f5c5SAndroid Build Coastguard Worker 
479*8975f5c5SAndroid Build Coastguard Worker // ProgramState implementation.
ProgramState(rx::GLImplFactory * factory)480*8975f5c5SAndroid Build Coastguard Worker ProgramState::ProgramState(rx::GLImplFactory *factory)
481*8975f5c5SAndroid Build Coastguard Worker     : mLabel(),
482*8975f5c5SAndroid Build Coastguard Worker       mAttachedShaders{},
483*8975f5c5SAndroid Build Coastguard Worker       mTransformFeedbackBufferMode(GL_INTERLEAVED_ATTRIBS),
484*8975f5c5SAndroid Build Coastguard Worker       mBinaryRetrieveableHint(false),
485*8975f5c5SAndroid Build Coastguard Worker       mSeparable(false),
486*8975f5c5SAndroid Build Coastguard Worker       mExecutable(new ProgramExecutable(factory, &mInfoLog))
487*8975f5c5SAndroid Build Coastguard Worker {}
488*8975f5c5SAndroid Build Coastguard Worker 
~ProgramState()489*8975f5c5SAndroid Build Coastguard Worker ProgramState::~ProgramState()
490*8975f5c5SAndroid Build Coastguard Worker {
491*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!hasAnyAttachedShader());
492*8975f5c5SAndroid Build Coastguard Worker }
493*8975f5c5SAndroid Build Coastguard Worker 
getLabel()494*8975f5c5SAndroid Build Coastguard Worker const std::string &ProgramState::getLabel()
495*8975f5c5SAndroid Build Coastguard Worker {
496*8975f5c5SAndroid Build Coastguard Worker     return mLabel;
497*8975f5c5SAndroid Build Coastguard Worker }
498*8975f5c5SAndroid Build Coastguard Worker 
getAttachedShader(ShaderType shaderType) const499*8975f5c5SAndroid Build Coastguard Worker SharedCompiledShaderState ProgramState::getAttachedShader(ShaderType shaderType) const
500*8975f5c5SAndroid Build Coastguard Worker {
501*8975f5c5SAndroid Build Coastguard Worker     ASSERT(shaderType != ShaderType::InvalidEnum);
502*8975f5c5SAndroid Build Coastguard Worker     return mAttachedShaders[shaderType];
503*8975f5c5SAndroid Build Coastguard Worker }
504*8975f5c5SAndroid Build Coastguard Worker 
hasAnyAttachedShader() const505*8975f5c5SAndroid Build Coastguard Worker bool ProgramState::hasAnyAttachedShader() const
506*8975f5c5SAndroid Build Coastguard Worker {
507*8975f5c5SAndroid Build Coastguard Worker     for (const SharedCompiledShaderState &shader : mAttachedShaders)
508*8975f5c5SAndroid Build Coastguard Worker     {
509*8975f5c5SAndroid Build Coastguard Worker         if (shader)
510*8975f5c5SAndroid Build Coastguard Worker         {
511*8975f5c5SAndroid Build Coastguard Worker             return true;
512*8975f5c5SAndroid Build Coastguard Worker         }
513*8975f5c5SAndroid Build Coastguard Worker     }
514*8975f5c5SAndroid Build Coastguard Worker     return false;
515*8975f5c5SAndroid Build Coastguard Worker }
516*8975f5c5SAndroid Build Coastguard Worker 
getAttachedTransformFeedbackStage() const517*8975f5c5SAndroid Build Coastguard Worker ShaderType ProgramState::getAttachedTransformFeedbackStage() const
518*8975f5c5SAndroid Build Coastguard Worker {
519*8975f5c5SAndroid Build Coastguard Worker     if (mAttachedShaders[ShaderType::Geometry])
520*8975f5c5SAndroid Build Coastguard Worker     {
521*8975f5c5SAndroid Build Coastguard Worker         return ShaderType::Geometry;
522*8975f5c5SAndroid Build Coastguard Worker     }
523*8975f5c5SAndroid Build Coastguard Worker     if (mAttachedShaders[ShaderType::TessEvaluation])
524*8975f5c5SAndroid Build Coastguard Worker     {
525*8975f5c5SAndroid Build Coastguard Worker         return ShaderType::TessEvaluation;
526*8975f5c5SAndroid Build Coastguard Worker     }
527*8975f5c5SAndroid Build Coastguard Worker     return ShaderType::Vertex;
528*8975f5c5SAndroid Build Coastguard Worker }
529*8975f5c5SAndroid Build Coastguard Worker 
530*8975f5c5SAndroid Build Coastguard Worker // The common portion of parallel link and load jobs
531*8975f5c5SAndroid Build Coastguard Worker class Program::MainLinkLoadTask : public angle::Closure
532*8975f5c5SAndroid Build Coastguard Worker {
533*8975f5c5SAndroid Build Coastguard Worker   public:
MainLinkLoadTask(const std::shared_ptr<angle::WorkerThreadPool> & subTaskWorkerPool,ProgramState * state,std::shared_ptr<rx::LinkTask> && linkTask)534*8975f5c5SAndroid Build Coastguard Worker     MainLinkLoadTask(const std::shared_ptr<angle::WorkerThreadPool> &subTaskWorkerPool,
535*8975f5c5SAndroid Build Coastguard Worker                      ProgramState *state,
536*8975f5c5SAndroid Build Coastguard Worker                      std::shared_ptr<rx::LinkTask> &&linkTask)
537*8975f5c5SAndroid Build Coastguard Worker         : mSubTaskWorkerPool(subTaskWorkerPool), mState(*state), mLinkTask(std::move(linkTask))
538*8975f5c5SAndroid Build Coastguard Worker     {
539*8975f5c5SAndroid Build Coastguard Worker         ASSERT(subTaskWorkerPool.get());
540*8975f5c5SAndroid Build Coastguard Worker     }
541*8975f5c5SAndroid Build Coastguard Worker     ~MainLinkLoadTask() override = default;
542*8975f5c5SAndroid Build Coastguard Worker 
getResult(const Context * context)543*8975f5c5SAndroid Build Coastguard Worker     angle::Result getResult(const Context *context)
544*8975f5c5SAndroid Build Coastguard Worker     {
545*8975f5c5SAndroid Build Coastguard Worker         InfoLog &infoLog = mState.getExecutable().getInfoLog();
546*8975f5c5SAndroid Build Coastguard Worker 
547*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(mResult);
548*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(mLinkTask->getResult(context, infoLog));
549*8975f5c5SAndroid Build Coastguard Worker 
550*8975f5c5SAndroid Build Coastguard Worker         for (const std::shared_ptr<rx::LinkSubTask> &task : mSubTasks)
551*8975f5c5SAndroid Build Coastguard Worker         {
552*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(task->getResult(context, infoLog));
553*8975f5c5SAndroid Build Coastguard Worker         }
554*8975f5c5SAndroid Build Coastguard Worker 
555*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
556*8975f5c5SAndroid Build Coastguard Worker     }
557*8975f5c5SAndroid Build Coastguard Worker 
waitSubTasks()558*8975f5c5SAndroid Build Coastguard Worker     void waitSubTasks() { angle::WaitableEvent::WaitMany(&mSubTaskWaitableEvents); }
559*8975f5c5SAndroid Build Coastguard Worker 
areSubTasksLinking()560*8975f5c5SAndroid Build Coastguard Worker     bool areSubTasksLinking()
561*8975f5c5SAndroid Build Coastguard Worker     {
562*8975f5c5SAndroid Build Coastguard Worker         if (mLinkTask->isLinkingInternally())
563*8975f5c5SAndroid Build Coastguard Worker         {
564*8975f5c5SAndroid Build Coastguard Worker             return true;
565*8975f5c5SAndroid Build Coastguard Worker         }
566*8975f5c5SAndroid Build Coastguard Worker         return !angle::WaitableEvent::AllReady(&mSubTaskWaitableEvents);
567*8975f5c5SAndroid Build Coastguard Worker     }
568*8975f5c5SAndroid Build Coastguard Worker 
569*8975f5c5SAndroid Build Coastguard Worker   protected:
scheduleSubTasks(std::vector<std::shared_ptr<rx::LinkSubTask>> && linkSubTasks,std::vector<std::shared_ptr<rx::LinkSubTask>> && postLinkSubTasks)570*8975f5c5SAndroid Build Coastguard Worker     void scheduleSubTasks(std::vector<std::shared_ptr<rx::LinkSubTask>> &&linkSubTasks,
571*8975f5c5SAndroid Build Coastguard Worker                           std::vector<std::shared_ptr<rx::LinkSubTask>> &&postLinkSubTasks)
572*8975f5c5SAndroid Build Coastguard Worker     {
573*8975f5c5SAndroid Build Coastguard Worker         // Only one of linkSubTasks or postLinkSubTasks should have tasks.  This is because
574*8975f5c5SAndroid Build Coastguard Worker         // currently, there is no support for ordering them.
575*8975f5c5SAndroid Build Coastguard Worker         ASSERT(linkSubTasks.empty() || postLinkSubTasks.empty());
576*8975f5c5SAndroid Build Coastguard Worker 
577*8975f5c5SAndroid Build Coastguard Worker         // Schedule link subtasks
578*8975f5c5SAndroid Build Coastguard Worker         mSubTasks = std::move(linkSubTasks);
579*8975f5c5SAndroid Build Coastguard Worker         ScheduleSubTasks(mSubTaskWorkerPool, mSubTasks, &mSubTaskWaitableEvents);
580*8975f5c5SAndroid Build Coastguard Worker 
581*8975f5c5SAndroid Build Coastguard Worker         // Schedule post-link subtasks
582*8975f5c5SAndroid Build Coastguard Worker         mState.mExecutable->mPostLinkSubTasks = std::move(postLinkSubTasks);
583*8975f5c5SAndroid Build Coastguard Worker         ScheduleSubTasks(mSubTaskWorkerPool, mState.mExecutable->mPostLinkSubTasks,
584*8975f5c5SAndroid Build Coastguard Worker                          &mState.mExecutable->mPostLinkSubTaskWaitableEvents);
585*8975f5c5SAndroid Build Coastguard Worker 
586*8975f5c5SAndroid Build Coastguard Worker         // No further use for worker pool.  Release it earlier than the destructor (to avoid
587*8975f5c5SAndroid Build Coastguard Worker         // situations such as http://anglebug.com/42267099)
588*8975f5c5SAndroid Build Coastguard Worker         mSubTaskWorkerPool.reset();
589*8975f5c5SAndroid Build Coastguard Worker     }
590*8975f5c5SAndroid Build Coastguard Worker 
591*8975f5c5SAndroid Build Coastguard Worker     std::shared_ptr<angle::WorkerThreadPool> mSubTaskWorkerPool;
592*8975f5c5SAndroid Build Coastguard Worker     ProgramState &mState;
593*8975f5c5SAndroid Build Coastguard Worker     std::shared_ptr<rx::LinkTask> mLinkTask;
594*8975f5c5SAndroid Build Coastguard Worker 
595*8975f5c5SAndroid Build Coastguard Worker     // Subtask and wait events
596*8975f5c5SAndroid Build Coastguard Worker     std::vector<std::shared_ptr<rx::LinkSubTask>> mSubTasks;
597*8975f5c5SAndroid Build Coastguard Worker     std::vector<std::shared_ptr<angle::WaitableEvent>> mSubTaskWaitableEvents;
598*8975f5c5SAndroid Build Coastguard Worker 
599*8975f5c5SAndroid Build Coastguard Worker     // The result of the front-end portion of the link.  The backend's result is retrieved via
600*8975f5c5SAndroid Build Coastguard Worker     // mLinkTask->getResult().  The subtask results are retrieved via mSubTasks similarly.
601*8975f5c5SAndroid Build Coastguard Worker     angle::Result mResult;
602*8975f5c5SAndroid Build Coastguard Worker };
603*8975f5c5SAndroid Build Coastguard Worker 
604*8975f5c5SAndroid Build Coastguard Worker class Program::MainLinkTask final : public Program::MainLinkLoadTask
605*8975f5c5SAndroid Build Coastguard Worker {
606*8975f5c5SAndroid Build Coastguard Worker   public:
MainLinkTask(const std::shared_ptr<angle::WorkerThreadPool> & subTaskWorkerPool,const Caps & caps,const Limitations & limitations,const Version & clientVersion,bool isWebGL,Program * program,ProgramState * state,LinkingVariables * linkingVariables,ProgramLinkedResources * resources,std::shared_ptr<rx::LinkTask> && linkTask)607*8975f5c5SAndroid Build Coastguard Worker     MainLinkTask(const std::shared_ptr<angle::WorkerThreadPool> &subTaskWorkerPool,
608*8975f5c5SAndroid Build Coastguard Worker                  const Caps &caps,
609*8975f5c5SAndroid Build Coastguard Worker                  const Limitations &limitations,
610*8975f5c5SAndroid Build Coastguard Worker                  const Version &clientVersion,
611*8975f5c5SAndroid Build Coastguard Worker                  bool isWebGL,
612*8975f5c5SAndroid Build Coastguard Worker                  Program *program,
613*8975f5c5SAndroid Build Coastguard Worker                  ProgramState *state,
614*8975f5c5SAndroid Build Coastguard Worker                  LinkingVariables *linkingVariables,
615*8975f5c5SAndroid Build Coastguard Worker                  ProgramLinkedResources *resources,
616*8975f5c5SAndroid Build Coastguard Worker                  std::shared_ptr<rx::LinkTask> &&linkTask)
617*8975f5c5SAndroid Build Coastguard Worker         : MainLinkLoadTask(subTaskWorkerPool, state, std::move(linkTask)),
618*8975f5c5SAndroid Build Coastguard Worker           mCaps(caps),
619*8975f5c5SAndroid Build Coastguard Worker           mLimitations(limitations),
620*8975f5c5SAndroid Build Coastguard Worker           mClientVersion(clientVersion),
621*8975f5c5SAndroid Build Coastguard Worker           mIsWebGL(isWebGL),
622*8975f5c5SAndroid Build Coastguard Worker           mProgram(program),
623*8975f5c5SAndroid Build Coastguard Worker           mLinkingVariables(linkingVariables),
624*8975f5c5SAndroid Build Coastguard Worker           mResources(resources)
625*8975f5c5SAndroid Build Coastguard Worker     {}
626*8975f5c5SAndroid Build Coastguard Worker     ~MainLinkTask() override = default;
627*8975f5c5SAndroid Build Coastguard Worker 
operator ()()628*8975f5c5SAndroid Build Coastguard Worker     void operator()() override { mResult = linkImpl(); }
629*8975f5c5SAndroid Build Coastguard Worker 
630*8975f5c5SAndroid Build Coastguard Worker   private:
631*8975f5c5SAndroid Build Coastguard Worker     angle::Result linkImpl();
632*8975f5c5SAndroid Build Coastguard Worker 
633*8975f5c5SAndroid Build Coastguard Worker     // State needed for link
634*8975f5c5SAndroid Build Coastguard Worker     const Caps &mCaps;
635*8975f5c5SAndroid Build Coastguard Worker     const Limitations &mLimitations;
636*8975f5c5SAndroid Build Coastguard Worker     const Version mClientVersion;
637*8975f5c5SAndroid Build Coastguard Worker     const bool mIsWebGL;
638*8975f5c5SAndroid Build Coastguard Worker     Program *mProgram;
639*8975f5c5SAndroid Build Coastguard Worker     LinkingVariables *mLinkingVariables;
640*8975f5c5SAndroid Build Coastguard Worker     ProgramLinkedResources *mResources;
641*8975f5c5SAndroid Build Coastguard Worker };
642*8975f5c5SAndroid Build Coastguard Worker 
643*8975f5c5SAndroid Build Coastguard Worker class Program::MainLoadTask final : public Program::MainLinkLoadTask
644*8975f5c5SAndroid Build Coastguard Worker {
645*8975f5c5SAndroid Build Coastguard Worker   public:
MainLoadTask(const std::shared_ptr<angle::WorkerThreadPool> & subTaskWorkerPool,Program * program,ProgramState * state,std::shared_ptr<rx::LinkTask> && loadTask)646*8975f5c5SAndroid Build Coastguard Worker     MainLoadTask(const std::shared_ptr<angle::WorkerThreadPool> &subTaskWorkerPool,
647*8975f5c5SAndroid Build Coastguard Worker                  Program *program,
648*8975f5c5SAndroid Build Coastguard Worker                  ProgramState *state,
649*8975f5c5SAndroid Build Coastguard Worker                  std::shared_ptr<rx::LinkTask> &&loadTask)
650*8975f5c5SAndroid Build Coastguard Worker         : MainLinkLoadTask(subTaskWorkerPool, state, std::move(loadTask))
651*8975f5c5SAndroid Build Coastguard Worker     {}
652*8975f5c5SAndroid Build Coastguard Worker     ~MainLoadTask() override = default;
653*8975f5c5SAndroid Build Coastguard Worker 
operator ()()654*8975f5c5SAndroid Build Coastguard Worker     void operator()() override { mResult = loadImpl(); }
655*8975f5c5SAndroid Build Coastguard Worker 
656*8975f5c5SAndroid Build Coastguard Worker   private:
657*8975f5c5SAndroid Build Coastguard Worker     angle::Result loadImpl();
658*8975f5c5SAndroid Build Coastguard Worker };
659*8975f5c5SAndroid Build Coastguard Worker 
660*8975f5c5SAndroid Build Coastguard Worker class Program::MainLinkLoadEvent final : public LinkEvent
661*8975f5c5SAndroid Build Coastguard Worker {
662*8975f5c5SAndroid Build Coastguard Worker   public:
MainLinkLoadEvent(const std::shared_ptr<MainLinkLoadTask> & linkTask,const std::shared_ptr<angle::WaitableEvent> & waitEvent)663*8975f5c5SAndroid Build Coastguard Worker     MainLinkLoadEvent(const std::shared_ptr<MainLinkLoadTask> &linkTask,
664*8975f5c5SAndroid Build Coastguard Worker                       const std::shared_ptr<angle::WaitableEvent> &waitEvent)
665*8975f5c5SAndroid Build Coastguard Worker         : mLinkTask(linkTask), mWaitableEvent(waitEvent)
666*8975f5c5SAndroid Build Coastguard Worker     {}
~MainLinkLoadEvent()667*8975f5c5SAndroid Build Coastguard Worker     ~MainLinkLoadEvent() override {}
668*8975f5c5SAndroid Build Coastguard Worker 
wait(const Context * context)669*8975f5c5SAndroid Build Coastguard Worker     angle::Result wait(const Context *context) override
670*8975f5c5SAndroid Build Coastguard Worker     {
671*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRACE_EVENT0("gpu.angle", "Program::MainLinkLoadEvent::wait");
672*8975f5c5SAndroid Build Coastguard Worker 
673*8975f5c5SAndroid Build Coastguard Worker         mWaitableEvent->wait();
674*8975f5c5SAndroid Build Coastguard Worker         mLinkTask->waitSubTasks();
675*8975f5c5SAndroid Build Coastguard Worker 
676*8975f5c5SAndroid Build Coastguard Worker         return mLinkTask->getResult(context);
677*8975f5c5SAndroid Build Coastguard Worker     }
isLinking()678*8975f5c5SAndroid Build Coastguard Worker     bool isLinking() override
679*8975f5c5SAndroid Build Coastguard Worker     {
680*8975f5c5SAndroid Build Coastguard Worker         return !mWaitableEvent->isReady() || mLinkTask->areSubTasksLinking();
681*8975f5c5SAndroid Build Coastguard Worker     }
682*8975f5c5SAndroid Build Coastguard Worker 
683*8975f5c5SAndroid Build Coastguard Worker   private:
684*8975f5c5SAndroid Build Coastguard Worker     std::shared_ptr<MainLinkLoadTask> mLinkTask;
685*8975f5c5SAndroid Build Coastguard Worker     std::shared_ptr<angle::WaitableEvent> mWaitableEvent;
686*8975f5c5SAndroid Build Coastguard Worker };
687*8975f5c5SAndroid Build Coastguard Worker 
linkImpl()688*8975f5c5SAndroid Build Coastguard Worker angle::Result Program::MainLinkTask::linkImpl()
689*8975f5c5SAndroid Build Coastguard Worker {
690*8975f5c5SAndroid Build Coastguard Worker     ProgramMergedVaryings mergedVaryings;
691*8975f5c5SAndroid Build Coastguard Worker 
692*8975f5c5SAndroid Build Coastguard Worker     // Do the front-end portion of the link.
693*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mProgram->linkJobImpl(mCaps, mLimitations, mClientVersion, mIsWebGL,
694*8975f5c5SAndroid Build Coastguard Worker                                     mLinkingVariables, mResources, &mergedVaryings));
695*8975f5c5SAndroid Build Coastguard Worker 
696*8975f5c5SAndroid Build Coastguard Worker     // Next, do the backend portion of the link.  If there are any subtasks to be scheduled, they
697*8975f5c5SAndroid Build Coastguard Worker     // are collected now.
698*8975f5c5SAndroid Build Coastguard Worker     std::vector<std::shared_ptr<rx::LinkSubTask>> linkSubTasks;
699*8975f5c5SAndroid Build Coastguard Worker     std::vector<std::shared_ptr<rx::LinkSubTask>> postLinkSubTasks;
700*8975f5c5SAndroid Build Coastguard Worker     mLinkTask->link(*mResources, mergedVaryings, &linkSubTasks, &postLinkSubTasks);
701*8975f5c5SAndroid Build Coastguard Worker 
702*8975f5c5SAndroid Build Coastguard Worker     // Must be after backend's link to avoid misleading the linker about input/output variables.
703*8975f5c5SAndroid Build Coastguard Worker     mState.updateProgramInterfaceInputs();
704*8975f5c5SAndroid Build Coastguard Worker     mState.updateProgramInterfaceOutputs();
705*8975f5c5SAndroid Build Coastguard Worker 
706*8975f5c5SAndroid Build Coastguard Worker     // Schedule the subtasks
707*8975f5c5SAndroid Build Coastguard Worker     scheduleSubTasks(std::move(linkSubTasks), std::move(postLinkSubTasks));
708*8975f5c5SAndroid Build Coastguard Worker 
709*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
710*8975f5c5SAndroid Build Coastguard Worker }
711*8975f5c5SAndroid Build Coastguard Worker 
loadImpl()712*8975f5c5SAndroid Build Coastguard Worker angle::Result Program::MainLoadTask::loadImpl()
713*8975f5c5SAndroid Build Coastguard Worker {
714*8975f5c5SAndroid Build Coastguard Worker     std::vector<std::shared_ptr<rx::LinkSubTask>> linkSubTasks;
715*8975f5c5SAndroid Build Coastguard Worker     std::vector<std::shared_ptr<rx::LinkSubTask>> postLinkSubTasks;
716*8975f5c5SAndroid Build Coastguard Worker     mLinkTask->load(&linkSubTasks, &postLinkSubTasks);
717*8975f5c5SAndroid Build Coastguard Worker 
718*8975f5c5SAndroid Build Coastguard Worker     // Schedule the subtasks
719*8975f5c5SAndroid Build Coastguard Worker     scheduleSubTasks(std::move(linkSubTasks), std::move(postLinkSubTasks));
720*8975f5c5SAndroid Build Coastguard Worker 
721*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
722*8975f5c5SAndroid Build Coastguard Worker }
723*8975f5c5SAndroid Build Coastguard Worker 
Program(rx::GLImplFactory * factory,ShaderProgramManager * manager,ShaderProgramID handle)724*8975f5c5SAndroid Build Coastguard Worker Program::Program(rx::GLImplFactory *factory, ShaderProgramManager *manager, ShaderProgramID handle)
725*8975f5c5SAndroid Build Coastguard Worker     : mSerial(factory->generateSerial()),
726*8975f5c5SAndroid Build Coastguard Worker       mState(factory),
727*8975f5c5SAndroid Build Coastguard Worker       mProgram(factory->createProgram(mState)),
728*8975f5c5SAndroid Build Coastguard Worker       mValidated(false),
729*8975f5c5SAndroid Build Coastguard Worker       mDeleteStatus(false),
730*8975f5c5SAndroid Build Coastguard Worker       mIsBinaryCached(true),
731*8975f5c5SAndroid Build Coastguard Worker       mLinked(false),
732*8975f5c5SAndroid Build Coastguard Worker       mProgramHash{0},
733*8975f5c5SAndroid Build Coastguard Worker       mRefCount(0),
734*8975f5c5SAndroid Build Coastguard Worker       mResourceManager(manager),
735*8975f5c5SAndroid Build Coastguard Worker       mHandle(handle),
736*8975f5c5SAndroid Build Coastguard Worker       mAttachedShaders{}
737*8975f5c5SAndroid Build Coastguard Worker {
738*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mProgram);
739*8975f5c5SAndroid Build Coastguard Worker 
740*8975f5c5SAndroid Build Coastguard Worker     unlink();
741*8975f5c5SAndroid Build Coastguard Worker }
742*8975f5c5SAndroid Build Coastguard Worker 
~Program()743*8975f5c5SAndroid Build Coastguard Worker Program::~Program()
744*8975f5c5SAndroid Build Coastguard Worker {
745*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mProgram);
746*8975f5c5SAndroid Build Coastguard Worker }
747*8975f5c5SAndroid Build Coastguard Worker 
onDestroy(const Context * context)748*8975f5c5SAndroid Build Coastguard Worker void Program::onDestroy(const Context *context)
749*8975f5c5SAndroid Build Coastguard Worker {
750*8975f5c5SAndroid Build Coastguard Worker     resolveLink(context);
751*8975f5c5SAndroid Build Coastguard Worker     waitForPostLinkTasks(context);
752*8975f5c5SAndroid Build Coastguard Worker 
753*8975f5c5SAndroid Build Coastguard Worker     for (ShaderType shaderType : AllShaderTypes())
754*8975f5c5SAndroid Build Coastguard Worker     {
755*8975f5c5SAndroid Build Coastguard Worker         Shader *shader = getAttachedShader(shaderType);
756*8975f5c5SAndroid Build Coastguard Worker         if (shader != nullptr)
757*8975f5c5SAndroid Build Coastguard Worker         {
758*8975f5c5SAndroid Build Coastguard Worker             shader->release(context);
759*8975f5c5SAndroid Build Coastguard Worker         }
760*8975f5c5SAndroid Build Coastguard Worker         mState.mShaderCompileJobs[shaderType].reset();
761*8975f5c5SAndroid Build Coastguard Worker         mState.mAttachedShaders[shaderType].reset();
762*8975f5c5SAndroid Build Coastguard Worker         mAttachedShaders[shaderType] = nullptr;
763*8975f5c5SAndroid Build Coastguard Worker     }
764*8975f5c5SAndroid Build Coastguard Worker 
765*8975f5c5SAndroid Build Coastguard Worker     mProgram->destroy(context);
766*8975f5c5SAndroid Build Coastguard Worker     UninstallExecutable(context, &mState.mExecutable);
767*8975f5c5SAndroid Build Coastguard Worker 
768*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mState.hasAnyAttachedShader());
769*8975f5c5SAndroid Build Coastguard Worker     SafeDelete(mProgram);
770*8975f5c5SAndroid Build Coastguard Worker 
771*8975f5c5SAndroid Build Coastguard Worker     mBinary.clear();
772*8975f5c5SAndroid Build Coastguard Worker 
773*8975f5c5SAndroid Build Coastguard Worker     delete this;
774*8975f5c5SAndroid Build Coastguard Worker }
775*8975f5c5SAndroid Build Coastguard Worker 
id() const776*8975f5c5SAndroid Build Coastguard Worker ShaderProgramID Program::id() const
777*8975f5c5SAndroid Build Coastguard Worker {
778*8975f5c5SAndroid Build Coastguard Worker     return mHandle;
779*8975f5c5SAndroid Build Coastguard Worker }
780*8975f5c5SAndroid Build Coastguard Worker 
setLabel(const Context * context,const std::string & label)781*8975f5c5SAndroid Build Coastguard Worker angle::Result Program::setLabel(const Context *context, const std::string &label)
782*8975f5c5SAndroid Build Coastguard Worker {
783*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mLinkingState);
784*8975f5c5SAndroid Build Coastguard Worker     mState.mLabel = label;
785*8975f5c5SAndroid Build Coastguard Worker 
786*8975f5c5SAndroid Build Coastguard Worker     if (mProgram)
787*8975f5c5SAndroid Build Coastguard Worker     {
788*8975f5c5SAndroid Build Coastguard Worker         return mProgram->onLabelUpdate(context);
789*8975f5c5SAndroid Build Coastguard Worker     }
790*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
791*8975f5c5SAndroid Build Coastguard Worker }
792*8975f5c5SAndroid Build Coastguard Worker 
getLabel() const793*8975f5c5SAndroid Build Coastguard Worker const std::string &Program::getLabel() const
794*8975f5c5SAndroid Build Coastguard Worker {
795*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mLinkingState);
796*8975f5c5SAndroid Build Coastguard Worker     return mState.mLabel;
797*8975f5c5SAndroid Build Coastguard Worker }
798*8975f5c5SAndroid Build Coastguard Worker 
attachShader(const Context * context,Shader * shader)799*8975f5c5SAndroid Build Coastguard Worker void Program::attachShader(const Context *context, Shader *shader)
800*8975f5c5SAndroid Build Coastguard Worker {
801*8975f5c5SAndroid Build Coastguard Worker     resolveLink(context);
802*8975f5c5SAndroid Build Coastguard Worker 
803*8975f5c5SAndroid Build Coastguard Worker     ShaderType shaderType = shader->getType();
804*8975f5c5SAndroid Build Coastguard Worker     ASSERT(shaderType != ShaderType::InvalidEnum);
805*8975f5c5SAndroid Build Coastguard Worker 
806*8975f5c5SAndroid Build Coastguard Worker     shader->addRef();
807*8975f5c5SAndroid Build Coastguard Worker     mAttachedShaders[shaderType] = shader;
808*8975f5c5SAndroid Build Coastguard Worker }
809*8975f5c5SAndroid Build Coastguard Worker 
detachShader(const Context * context,Shader * shader)810*8975f5c5SAndroid Build Coastguard Worker void Program::detachShader(const Context *context, Shader *shader)
811*8975f5c5SAndroid Build Coastguard Worker {
812*8975f5c5SAndroid Build Coastguard Worker     resolveLink(context);
813*8975f5c5SAndroid Build Coastguard Worker 
814*8975f5c5SAndroid Build Coastguard Worker     ShaderType shaderType = shader->getType();
815*8975f5c5SAndroid Build Coastguard Worker     ASSERT(shaderType != ShaderType::InvalidEnum);
816*8975f5c5SAndroid Build Coastguard Worker 
817*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mAttachedShaders[shaderType] == shader);
818*8975f5c5SAndroid Build Coastguard Worker     shader->release(context);
819*8975f5c5SAndroid Build Coastguard Worker     mAttachedShaders[shaderType] = nullptr;
820*8975f5c5SAndroid Build Coastguard Worker     mState.mShaderCompileJobs[shaderType].reset();
821*8975f5c5SAndroid Build Coastguard Worker     mState.mAttachedShaders[shaderType].reset();
822*8975f5c5SAndroid Build Coastguard Worker }
823*8975f5c5SAndroid Build Coastguard Worker 
getAttachedShadersCount() const824*8975f5c5SAndroid Build Coastguard Worker int Program::getAttachedShadersCount() const
825*8975f5c5SAndroid Build Coastguard Worker {
826*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mLinkingState);
827*8975f5c5SAndroid Build Coastguard Worker     int numAttachedShaders = 0;
828*8975f5c5SAndroid Build Coastguard Worker     for (const Shader *shader : mAttachedShaders)
829*8975f5c5SAndroid Build Coastguard Worker     {
830*8975f5c5SAndroid Build Coastguard Worker         if (shader != nullptr)
831*8975f5c5SAndroid Build Coastguard Worker         {
832*8975f5c5SAndroid Build Coastguard Worker             ++numAttachedShaders;
833*8975f5c5SAndroid Build Coastguard Worker         }
834*8975f5c5SAndroid Build Coastguard Worker     }
835*8975f5c5SAndroid Build Coastguard Worker 
836*8975f5c5SAndroid Build Coastguard Worker     return numAttachedShaders;
837*8975f5c5SAndroid Build Coastguard Worker }
838*8975f5c5SAndroid Build Coastguard Worker 
getAttachedShader(ShaderType shaderType) const839*8975f5c5SAndroid Build Coastguard Worker Shader *Program::getAttachedShader(ShaderType shaderType) const
840*8975f5c5SAndroid Build Coastguard Worker {
841*8975f5c5SAndroid Build Coastguard Worker     return mAttachedShaders[shaderType];
842*8975f5c5SAndroid Build Coastguard Worker }
843*8975f5c5SAndroid Build Coastguard Worker 
bindAttributeLocation(const Context * context,GLuint index,const char * name)844*8975f5c5SAndroid Build Coastguard Worker void Program::bindAttributeLocation(const Context *context, GLuint index, const char *name)
845*8975f5c5SAndroid Build Coastguard Worker {
846*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mLinkingState);
847*8975f5c5SAndroid Build Coastguard Worker     mState.mAttributeBindings.bindLocation(index, name);
848*8975f5c5SAndroid Build Coastguard Worker }
849*8975f5c5SAndroid Build Coastguard Worker 
bindUniformLocation(const Context * context,UniformLocation location,const char * name)850*8975f5c5SAndroid Build Coastguard Worker void Program::bindUniformLocation(const Context *context,
851*8975f5c5SAndroid Build Coastguard Worker                                   UniformLocation location,
852*8975f5c5SAndroid Build Coastguard Worker                                   const char *name)
853*8975f5c5SAndroid Build Coastguard Worker {
854*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mLinkingState);
855*8975f5c5SAndroid Build Coastguard Worker     mState.mUniformLocationBindings.bindLocation(location.value, name);
856*8975f5c5SAndroid Build Coastguard Worker }
857*8975f5c5SAndroid Build Coastguard Worker 
bindFragmentOutputLocation(const Context * context,GLuint index,const char * name)858*8975f5c5SAndroid Build Coastguard Worker void Program::bindFragmentOutputLocation(const Context *context, GLuint index, const char *name)
859*8975f5c5SAndroid Build Coastguard Worker {
860*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mLinkingState);
861*8975f5c5SAndroid Build Coastguard Worker     mState.mFragmentOutputLocations.bindLocation(index, name);
862*8975f5c5SAndroid Build Coastguard Worker }
863*8975f5c5SAndroid Build Coastguard Worker 
bindFragmentOutputIndex(const Context * context,GLuint index,const char * name)864*8975f5c5SAndroid Build Coastguard Worker void Program::bindFragmentOutputIndex(const Context *context, GLuint index, const char *name)
865*8975f5c5SAndroid Build Coastguard Worker {
866*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mLinkingState);
867*8975f5c5SAndroid Build Coastguard Worker     mState.mFragmentOutputIndexes.bindLocation(index, name);
868*8975f5c5SAndroid Build Coastguard Worker }
869*8975f5c5SAndroid Build Coastguard Worker 
makeNewExecutable(const Context * context)870*8975f5c5SAndroid Build Coastguard Worker void Program::makeNewExecutable(const Context *context)
871*8975f5c5SAndroid Build Coastguard Worker {
872*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mLinkingState);
873*8975f5c5SAndroid Build Coastguard Worker     waitForPostLinkTasks(context);
874*8975f5c5SAndroid Build Coastguard Worker 
875*8975f5c5SAndroid Build Coastguard Worker     // Unlink the program, but do not clear the validation-related caching yet, since we can still
876*8975f5c5SAndroid Build Coastguard Worker     // use the previously linked program if linking the shaders fails.
877*8975f5c5SAndroid Build Coastguard Worker     mLinked = false;
878*8975f5c5SAndroid Build Coastguard Worker 
879*8975f5c5SAndroid Build Coastguard Worker     mLinkingState = std::make_unique<LinkingState>();
880*8975f5c5SAndroid Build Coastguard Worker 
881*8975f5c5SAndroid Build Coastguard Worker     // By default, set the link event as failing.  If link succeeds, it will be replaced by the
882*8975f5c5SAndroid Build Coastguard Worker     // appropriate event.
883*8975f5c5SAndroid Build Coastguard Worker     mLinkingState->linkEvent = std::make_unique<LinkEventDone>(angle::Result::Stop);
884*8975f5c5SAndroid Build Coastguard Worker 
885*8975f5c5SAndroid Build Coastguard Worker     InstallExecutable(
886*8975f5c5SAndroid Build Coastguard Worker         context,
887*8975f5c5SAndroid Build Coastguard Worker         std::make_shared<ProgramExecutable>(context->getImplementation(), &mState.mInfoLog),
888*8975f5c5SAndroid Build Coastguard Worker         &mState.mExecutable);
889*8975f5c5SAndroid Build Coastguard Worker     onStateChange(angle::SubjectMessage::ProgramUnlinked);
890*8975f5c5SAndroid Build Coastguard Worker 
891*8975f5c5SAndroid Build Coastguard Worker     // If caching is disabled, consider it cached!
892*8975f5c5SAndroid Build Coastguard Worker     mIsBinaryCached = context->getFrontendFeatures().disableProgramCaching.enabled;
893*8975f5c5SAndroid Build Coastguard Worker 
894*8975f5c5SAndroid Build Coastguard Worker     // Start with a clean slate every time a new executable is installed.  Note that the executable
895*8975f5c5SAndroid Build Coastguard Worker     // binary is not mutable; once linked it remains constant.  When the program changes, a new
896*8975f5c5SAndroid Build Coastguard Worker     // executable is installed in this function.
897*8975f5c5SAndroid Build Coastguard Worker     mBinary.clear();
898*8975f5c5SAndroid Build Coastguard Worker }
899*8975f5c5SAndroid Build Coastguard Worker 
setupExecutableForLink(const Context * context)900*8975f5c5SAndroid Build Coastguard Worker void Program::setupExecutableForLink(const Context *context)
901*8975f5c5SAndroid Build Coastguard Worker {
902*8975f5c5SAndroid Build Coastguard Worker     // Create a new executable to hold the result of the link.  The previous executable may still be
903*8975f5c5SAndroid Build Coastguard Worker     // referenced by the contexts the program is current on, and any program pipelines it may be
904*8975f5c5SAndroid Build Coastguard Worker     // used in.  Once link succeeds, the users of the program are notified to update their
905*8975f5c5SAndroid Build Coastguard Worker     // executables.
906*8975f5c5SAndroid Build Coastguard Worker     makeNewExecutable(context);
907*8975f5c5SAndroid Build Coastguard Worker 
908*8975f5c5SAndroid Build Coastguard Worker     // For every attached shader, get the compile job and compiled state.  This is done at link time
909*8975f5c5SAndroid Build Coastguard Worker     // (instead of earlier, such as attachShader time), because the shader could get recompiled
910*8975f5c5SAndroid Build Coastguard Worker     // between attach and link.
911*8975f5c5SAndroid Build Coastguard Worker     //
912*8975f5c5SAndroid Build Coastguard Worker     // Additionally, make sure the backend is also able to cache the compiled state of its own
913*8975f5c5SAndroid Build Coastguard Worker     // ShaderImpl objects.
914*8975f5c5SAndroid Build Coastguard Worker     ShaderMap<rx::ShaderImpl *> shaderImpls = {};
915*8975f5c5SAndroid Build Coastguard Worker     for (ShaderType shaderType : AllShaderTypes())
916*8975f5c5SAndroid Build Coastguard Worker     {
917*8975f5c5SAndroid Build Coastguard Worker         Shader *shader = mAttachedShaders[shaderType];
918*8975f5c5SAndroid Build Coastguard Worker         SharedCompileJob compileJob;
919*8975f5c5SAndroid Build Coastguard Worker         SharedCompiledShaderState shaderCompiledState;
920*8975f5c5SAndroid Build Coastguard Worker         if (shader != nullptr)
921*8975f5c5SAndroid Build Coastguard Worker         {
922*8975f5c5SAndroid Build Coastguard Worker             compileJob              = shader->getCompileJob(&shaderCompiledState);
923*8975f5c5SAndroid Build Coastguard Worker             shaderImpls[shaderType] = shader->getImplementation();
924*8975f5c5SAndroid Build Coastguard Worker         }
925*8975f5c5SAndroid Build Coastguard Worker         mState.mShaderCompileJobs[shaderType] = std::move(compileJob);
926*8975f5c5SAndroid Build Coastguard Worker         mState.mAttachedShaders[shaderType]   = std::move(shaderCompiledState);
927*8975f5c5SAndroid Build Coastguard Worker     }
928*8975f5c5SAndroid Build Coastguard Worker     mProgram->prepareForLink(shaderImpls);
929*8975f5c5SAndroid Build Coastguard Worker 
930*8975f5c5SAndroid Build Coastguard Worker     const angle::FrontendFeatures &frontendFeatures = context->getFrontendFeatures();
931*8975f5c5SAndroid Build Coastguard Worker     if (frontendFeatures.dumpShaderSource.enabled)
932*8975f5c5SAndroid Build Coastguard Worker     {
933*8975f5c5SAndroid Build Coastguard Worker         dumpProgramInfo(context);
934*8975f5c5SAndroid Build Coastguard Worker     }
935*8975f5c5SAndroid Build Coastguard Worker 
936*8975f5c5SAndroid Build Coastguard Worker     // Make sure the executable state is in sync with the program.
937*8975f5c5SAndroid Build Coastguard Worker     //
938*8975f5c5SAndroid Build Coastguard Worker     // The transform feedback buffer mode is duplicated in the executable as it is the only
939*8975f5c5SAndroid Build Coastguard Worker     // link-input that is also needed at draw time.
940*8975f5c5SAndroid Build Coastguard Worker     //
941*8975f5c5SAndroid Build Coastguard Worker     // The transform feedback varying names are duplicated because the program pipeline link is not
942*8975f5c5SAndroid Build Coastguard Worker     // currently able to use the link result of the program directly (and redoes the link, using
943*8975f5c5SAndroid Build Coastguard Worker     // these names).
944*8975f5c5SAndroid Build Coastguard Worker     //
945*8975f5c5SAndroid Build Coastguard Worker     // The isSeparable state is duplicated for convenience; it is used when setting sampler/image
946*8975f5c5SAndroid Build Coastguard Worker     // uniforms.
947*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->mPod.transformFeedbackBufferMode = mState.mTransformFeedbackBufferMode;
948*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->mTransformFeedbackVaryingNames   = mState.mTransformFeedbackVaryingNames;
949*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->mPod.isSeparable                 = mState.mSeparable;
950*8975f5c5SAndroid Build Coastguard Worker 
951*8975f5c5SAndroid Build Coastguard Worker     mState.mInfoLog.reset();
952*8975f5c5SAndroid Build Coastguard Worker }
953*8975f5c5SAndroid Build Coastguard Worker 
link(const Context * context,angle::JobResultExpectancy resultExpectancy)954*8975f5c5SAndroid Build Coastguard Worker angle::Result Program::link(const Context *context, angle::JobResultExpectancy resultExpectancy)
955*8975f5c5SAndroid Build Coastguard Worker {
956*8975f5c5SAndroid Build Coastguard Worker     auto *platform   = ANGLEPlatformCurrent();
957*8975f5c5SAndroid Build Coastguard Worker     double startTime = platform->currentTime(platform);
958*8975f5c5SAndroid Build Coastguard Worker 
959*8975f5c5SAndroid Build Coastguard Worker     setupExecutableForLink(context);
960*8975f5c5SAndroid Build Coastguard Worker 
961*8975f5c5SAndroid Build Coastguard Worker     mProgramHash              = {0};
962*8975f5c5SAndroid Build Coastguard Worker     MemoryProgramCache *cache = (context->getFrontendFeatures().disableProgramCaching.enabled)
963*8975f5c5SAndroid Build Coastguard Worker                                     ? nullptr
964*8975f5c5SAndroid Build Coastguard Worker                                     : context->getMemoryProgramCache();
965*8975f5c5SAndroid Build Coastguard Worker 
966*8975f5c5SAndroid Build Coastguard Worker     // TODO: http://anglebug.com/42263141: Enable program caching for separable programs
967*8975f5c5SAndroid Build Coastguard Worker     if (cache && !isSeparable())
968*8975f5c5SAndroid Build Coastguard Worker     {
969*8975f5c5SAndroid Build Coastguard Worker         std::lock_guard<angle::SimpleMutex> cacheLock(context->getProgramCacheMutex());
970*8975f5c5SAndroid Build Coastguard Worker         egl::CacheGetResult result = egl::CacheGetResult::NotFound;
971*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(cache->getProgram(context, this, &mProgramHash, &result));
972*8975f5c5SAndroid Build Coastguard Worker 
973*8975f5c5SAndroid Build Coastguard Worker         switch (result)
974*8975f5c5SAndroid Build Coastguard Worker         {
975*8975f5c5SAndroid Build Coastguard Worker             case egl::CacheGetResult::Success:
976*8975f5c5SAndroid Build Coastguard Worker             {
977*8975f5c5SAndroid Build Coastguard Worker                 // No need to care about the compile jobs any more.
978*8975f5c5SAndroid Build Coastguard Worker                 mState.mShaderCompileJobs = {};
979*8975f5c5SAndroid Build Coastguard Worker 
980*8975f5c5SAndroid Build Coastguard Worker                 std::scoped_lock lock(mHistogramMutex);
981*8975f5c5SAndroid Build Coastguard Worker                 // Succeeded in loading the binaries in the front-end, back end may still be loading
982*8975f5c5SAndroid Build Coastguard Worker                 // asynchronously
983*8975f5c5SAndroid Build Coastguard Worker                 double delta = platform->currentTime(platform) - startTime;
984*8975f5c5SAndroid Build Coastguard Worker                 int us       = static_cast<int>(delta * 1000'000.0);
985*8975f5c5SAndroid Build Coastguard Worker                 ANGLE_HISTOGRAM_COUNTS("GPU.ANGLE.ProgramCache.ProgramCacheHitTimeUS", us);
986*8975f5c5SAndroid Build Coastguard Worker                 return angle::Result::Continue;
987*8975f5c5SAndroid Build Coastguard Worker             }
988*8975f5c5SAndroid Build Coastguard Worker             case egl::CacheGetResult::Rejected:
989*8975f5c5SAndroid Build Coastguard Worker                 // If the program binary was found but rejected, the program executable may be in an
990*8975f5c5SAndroid Build Coastguard Worker                 // inconsistent half-loaded state.  In that case, start over.
991*8975f5c5SAndroid Build Coastguard Worker                 mLinkingState.reset();
992*8975f5c5SAndroid Build Coastguard Worker                 setupExecutableForLink(context);
993*8975f5c5SAndroid Build Coastguard Worker                 break;
994*8975f5c5SAndroid Build Coastguard Worker             case egl::CacheGetResult::NotFound:
995*8975f5c5SAndroid Build Coastguard Worker             default:
996*8975f5c5SAndroid Build Coastguard Worker                 break;
997*8975f5c5SAndroid Build Coastguard Worker         }
998*8975f5c5SAndroid Build Coastguard Worker     }
999*8975f5c5SAndroid Build Coastguard Worker 
1000*8975f5c5SAndroid Build Coastguard Worker     const Caps &caps               = context->getCaps();
1001*8975f5c5SAndroid Build Coastguard Worker     const Limitations &limitations = context->getLimitations();
1002*8975f5c5SAndroid Build Coastguard Worker     const Version &clientVersion   = context->getClientVersion();
1003*8975f5c5SAndroid Build Coastguard Worker     const bool isWebGL             = context->isWebGL();
1004*8975f5c5SAndroid Build Coastguard Worker 
1005*8975f5c5SAndroid Build Coastguard Worker     // Ask the backend to prepare the link task.
1006*8975f5c5SAndroid Build Coastguard Worker     std::shared_ptr<rx::LinkTask> linkTask;
1007*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mProgram->link(context, &linkTask));
1008*8975f5c5SAndroid Build Coastguard Worker 
1009*8975f5c5SAndroid Build Coastguard Worker     std::unique_ptr<LinkingState> linkingState = std::make_unique<LinkingState>();
1010*8975f5c5SAndroid Build Coastguard Worker 
1011*8975f5c5SAndroid Build Coastguard Worker     // Prepare the main link job
1012*8975f5c5SAndroid Build Coastguard Worker     std::shared_ptr<MainLinkLoadTask> mainLinkTask(new MainLinkTask(
1013*8975f5c5SAndroid Build Coastguard Worker         context->getLinkSubTaskThreadPool(), caps, limitations, clientVersion, isWebGL, this,
1014*8975f5c5SAndroid Build Coastguard Worker         &mState, &linkingState->linkingVariables, &linkingState->resources, std::move(linkTask)));
1015*8975f5c5SAndroid Build Coastguard Worker 
1016*8975f5c5SAndroid Build Coastguard Worker     // While the subtasks are currently always thread-safe, the main task is not safe on all
1017*8975f5c5SAndroid Build Coastguard Worker     // backends.  A front-end feature selects whether the single-threaded pool must be used.
1018*8975f5c5SAndroid Build Coastguard Worker     const angle::JobThreadSafety threadSafety =
1019*8975f5c5SAndroid Build Coastguard Worker         context->getFrontendFeatures().linkJobIsThreadSafe.enabled ? angle::JobThreadSafety::Safe
1020*8975f5c5SAndroid Build Coastguard Worker                                                                    : angle::JobThreadSafety::Unsafe;
1021*8975f5c5SAndroid Build Coastguard Worker     std::shared_ptr<angle::WaitableEvent> mainLinkEvent =
1022*8975f5c5SAndroid Build Coastguard Worker         context->postCompileLinkTask(mainLinkTask, threadSafety, resultExpectancy);
1023*8975f5c5SAndroid Build Coastguard Worker 
1024*8975f5c5SAndroid Build Coastguard Worker     mLinkingState                    = std::move(linkingState);
1025*8975f5c5SAndroid Build Coastguard Worker     mLinkingState->linkingFromBinary = false;
1026*8975f5c5SAndroid Build Coastguard Worker     mLinkingState->linkEvent = std::make_unique<MainLinkLoadEvent>(mainLinkTask, mainLinkEvent);
1027*8975f5c5SAndroid Build Coastguard Worker 
1028*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1029*8975f5c5SAndroid Build Coastguard Worker }
1030*8975f5c5SAndroid Build Coastguard Worker 
linkJobImpl(const Caps & caps,const Limitations & limitations,const Version & clientVersion,bool isWebGL,LinkingVariables * linkingVariables,ProgramLinkedResources * resources,ProgramMergedVaryings * mergedVaryingsOut)1031*8975f5c5SAndroid Build Coastguard Worker angle::Result Program::linkJobImpl(const Caps &caps,
1032*8975f5c5SAndroid Build Coastguard Worker                                    const Limitations &limitations,
1033*8975f5c5SAndroid Build Coastguard Worker                                    const Version &clientVersion,
1034*8975f5c5SAndroid Build Coastguard Worker                                    bool isWebGL,
1035*8975f5c5SAndroid Build Coastguard Worker                                    LinkingVariables *linkingVariables,
1036*8975f5c5SAndroid Build Coastguard Worker                                    ProgramLinkedResources *resources,
1037*8975f5c5SAndroid Build Coastguard Worker                                    ProgramMergedVaryings *mergedVaryingsOut)
1038*8975f5c5SAndroid Build Coastguard Worker {
1039*8975f5c5SAndroid Build Coastguard Worker     // Cache load failed, fall through to normal linking.
1040*8975f5c5SAndroid Build Coastguard Worker     unlink();
1041*8975f5c5SAndroid Build Coastguard Worker 
1042*8975f5c5SAndroid Build Coastguard Worker     // Validate we have properly attached shaders after checking the cache.  Since the input to the
1043*8975f5c5SAndroid Build Coastguard Worker     // shaders is part of the cache key, if there was a cache hit, the shaders would have linked
1044*8975f5c5SAndroid Build Coastguard Worker     // correctly.
1045*8975f5c5SAndroid Build Coastguard Worker     if (!linkValidateShaders())
1046*8975f5c5SAndroid Build Coastguard Worker     {
1047*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Stop;
1048*8975f5c5SAndroid Build Coastguard Worker     }
1049*8975f5c5SAndroid Build Coastguard Worker 
1050*8975f5c5SAndroid Build Coastguard Worker     linkShaders();
1051*8975f5c5SAndroid Build Coastguard Worker 
1052*8975f5c5SAndroid Build Coastguard Worker     linkingVariables->initForProgram(mState);
1053*8975f5c5SAndroid Build Coastguard Worker     resources->init(
1054*8975f5c5SAndroid Build Coastguard Worker         &mState.mExecutable->mUniformBlocks, &mState.mExecutable->mUniforms,
1055*8975f5c5SAndroid Build Coastguard Worker         &mState.mExecutable->mUniformNames, &mState.mExecutable->mUniformMappedNames,
1056*8975f5c5SAndroid Build Coastguard Worker         &mState.mExecutable->mShaderStorageBlocks, &mState.mExecutable->mBufferVariables,
1057*8975f5c5SAndroid Build Coastguard Worker         &mState.mExecutable->mAtomicCounterBuffers, &mState.mExecutable->mPixelLocalStorageFormats);
1058*8975f5c5SAndroid Build Coastguard Worker 
1059*8975f5c5SAndroid Build Coastguard Worker     updateLinkedShaderStages();
1060*8975f5c5SAndroid Build Coastguard Worker 
1061*8975f5c5SAndroid Build Coastguard Worker     InitUniformBlockLinker(mState, &resources->uniformBlockLinker);
1062*8975f5c5SAndroid Build Coastguard Worker     InitShaderStorageBlockLinker(mState, &resources->shaderStorageBlockLinker);
1063*8975f5c5SAndroid Build Coastguard Worker 
1064*8975f5c5SAndroid Build Coastguard Worker     if (mState.mAttachedShaders[ShaderType::Compute])
1065*8975f5c5SAndroid Build Coastguard Worker     {
1066*8975f5c5SAndroid Build Coastguard Worker         GLuint combinedImageUniforms = 0;
1067*8975f5c5SAndroid Build Coastguard Worker         if (!linkUniforms(caps, clientVersion, &resources->unusedUniforms, &combinedImageUniforms))
1068*8975f5c5SAndroid Build Coastguard Worker         {
1069*8975f5c5SAndroid Build Coastguard Worker             return angle::Result::Stop;
1070*8975f5c5SAndroid Build Coastguard Worker         }
1071*8975f5c5SAndroid Build Coastguard Worker 
1072*8975f5c5SAndroid Build Coastguard Worker         GLuint combinedShaderStorageBlocks = 0u;
1073*8975f5c5SAndroid Build Coastguard Worker         if (!LinkValidateProgramInterfaceBlocks(
1074*8975f5c5SAndroid Build Coastguard Worker                 caps, clientVersion, isWebGL, mState.mExecutable->getLinkedShaderStages(),
1075*8975f5c5SAndroid Build Coastguard Worker                 *resources, mState.mInfoLog, &combinedShaderStorageBlocks))
1076*8975f5c5SAndroid Build Coastguard Worker         {
1077*8975f5c5SAndroid Build Coastguard Worker             return angle::Result::Stop;
1078*8975f5c5SAndroid Build Coastguard Worker         }
1079*8975f5c5SAndroid Build Coastguard Worker 
1080*8975f5c5SAndroid Build Coastguard Worker         // [OpenGL ES 3.1] Chapter 8.22 Page 203:
1081*8975f5c5SAndroid Build Coastguard Worker         // A link error will be generated if the sum of the number of active image uniforms used in
1082*8975f5c5SAndroid Build Coastguard Worker         // all shaders, the number of active shader storage blocks, and the number of active
1083*8975f5c5SAndroid Build Coastguard Worker         // fragment shader outputs exceeds the implementation-dependent value of
1084*8975f5c5SAndroid Build Coastguard Worker         // MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
1085*8975f5c5SAndroid Build Coastguard Worker         if (combinedImageUniforms + combinedShaderStorageBlocks >
1086*8975f5c5SAndroid Build Coastguard Worker             static_cast<GLuint>(caps.maxCombinedShaderOutputResources))
1087*8975f5c5SAndroid Build Coastguard Worker         {
1088*8975f5c5SAndroid Build Coastguard Worker             mState.mInfoLog
1089*8975f5c5SAndroid Build Coastguard Worker                 << "The sum of the number of active image uniforms, active shader storage blocks "
1090*8975f5c5SAndroid Build Coastguard Worker                    "and active fragment shader outputs exceeds "
1091*8975f5c5SAndroid Build Coastguard Worker                    "MAX_COMBINED_SHADER_OUTPUT_RESOURCES ("
1092*8975f5c5SAndroid Build Coastguard Worker                 << caps.maxCombinedShaderOutputResources << ")";
1093*8975f5c5SAndroid Build Coastguard Worker             return angle::Result::Stop;
1094*8975f5c5SAndroid Build Coastguard Worker         }
1095*8975f5c5SAndroid Build Coastguard Worker     }
1096*8975f5c5SAndroid Build Coastguard Worker     else
1097*8975f5c5SAndroid Build Coastguard Worker     {
1098*8975f5c5SAndroid Build Coastguard Worker         if (!linkAttributes(caps, limitations, isWebGL))
1099*8975f5c5SAndroid Build Coastguard Worker         {
1100*8975f5c5SAndroid Build Coastguard Worker             return angle::Result::Stop;
1101*8975f5c5SAndroid Build Coastguard Worker         }
1102*8975f5c5SAndroid Build Coastguard Worker 
1103*8975f5c5SAndroid Build Coastguard Worker         if (!linkVaryings())
1104*8975f5c5SAndroid Build Coastguard Worker         {
1105*8975f5c5SAndroid Build Coastguard Worker             return angle::Result::Stop;
1106*8975f5c5SAndroid Build Coastguard Worker         }
1107*8975f5c5SAndroid Build Coastguard Worker 
1108*8975f5c5SAndroid Build Coastguard Worker         GLuint combinedImageUniforms = 0;
1109*8975f5c5SAndroid Build Coastguard Worker         if (!linkUniforms(caps, clientVersion, &resources->unusedUniforms, &combinedImageUniforms))
1110*8975f5c5SAndroid Build Coastguard Worker         {
1111*8975f5c5SAndroid Build Coastguard Worker             return angle::Result::Stop;
1112*8975f5c5SAndroid Build Coastguard Worker         }
1113*8975f5c5SAndroid Build Coastguard Worker 
1114*8975f5c5SAndroid Build Coastguard Worker         GLuint combinedShaderStorageBlocks = 0u;
1115*8975f5c5SAndroid Build Coastguard Worker         if (!LinkValidateProgramInterfaceBlocks(
1116*8975f5c5SAndroid Build Coastguard Worker                 caps, clientVersion, isWebGL, mState.mExecutable->getLinkedShaderStages(),
1117*8975f5c5SAndroid Build Coastguard Worker                 *resources, mState.mInfoLog, &combinedShaderStorageBlocks))
1118*8975f5c5SAndroid Build Coastguard Worker         {
1119*8975f5c5SAndroid Build Coastguard Worker             return angle::Result::Stop;
1120*8975f5c5SAndroid Build Coastguard Worker         }
1121*8975f5c5SAndroid Build Coastguard Worker 
1122*8975f5c5SAndroid Build Coastguard Worker         if (!LinkValidateProgramGlobalNames(mState.mInfoLog, getExecutable(), *linkingVariables))
1123*8975f5c5SAndroid Build Coastguard Worker         {
1124*8975f5c5SAndroid Build Coastguard Worker             return angle::Result::Stop;
1125*8975f5c5SAndroid Build Coastguard Worker         }
1126*8975f5c5SAndroid Build Coastguard Worker 
1127*8975f5c5SAndroid Build Coastguard Worker         const SharedCompiledShaderState &vertexShader = mState.mAttachedShaders[ShaderType::Vertex];
1128*8975f5c5SAndroid Build Coastguard Worker         if (vertexShader)
1129*8975f5c5SAndroid Build Coastguard Worker         {
1130*8975f5c5SAndroid Build Coastguard Worker             mState.mExecutable->mPod.numViews = vertexShader->numViews;
1131*8975f5c5SAndroid Build Coastguard Worker             mState.mExecutable->mPod.hasClipDistance =
1132*8975f5c5SAndroid Build Coastguard Worker                 vertexShader->metadataFlags.test(sh::MetadataFlags::HasClipDistance);
1133*8975f5c5SAndroid Build Coastguard Worker             mState.mExecutable->mPod.specConstUsageBits |= vertexShader->specConstUsageBits;
1134*8975f5c5SAndroid Build Coastguard Worker         }
1135*8975f5c5SAndroid Build Coastguard Worker 
1136*8975f5c5SAndroid Build Coastguard Worker         const SharedCompiledShaderState &fragmentShader =
1137*8975f5c5SAndroid Build Coastguard Worker             mState.mAttachedShaders[ShaderType::Fragment];
1138*8975f5c5SAndroid Build Coastguard Worker         if (fragmentShader)
1139*8975f5c5SAndroid Build Coastguard Worker         {
1140*8975f5c5SAndroid Build Coastguard Worker             ASSERT(mState.mExecutable->mOutputVariables.empty());
1141*8975f5c5SAndroid Build Coastguard Worker             mState.mExecutable->mOutputVariables.reserve(
1142*8975f5c5SAndroid Build Coastguard Worker                 fragmentShader->activeOutputVariables.size());
1143*8975f5c5SAndroid Build Coastguard Worker             for (const sh::ShaderVariable &shaderVariable : fragmentShader->activeOutputVariables)
1144*8975f5c5SAndroid Build Coastguard Worker             {
1145*8975f5c5SAndroid Build Coastguard Worker                 mState.mExecutable->mOutputVariables.emplace_back(shaderVariable);
1146*8975f5c5SAndroid Build Coastguard Worker             }
1147*8975f5c5SAndroid Build Coastguard Worker             if (!mState.mExecutable->linkValidateOutputVariables(
1148*8975f5c5SAndroid Build Coastguard Worker                     caps, clientVersion, combinedImageUniforms, combinedShaderStorageBlocks,
1149*8975f5c5SAndroid Build Coastguard Worker                     fragmentShader->shaderVersion, mState.mFragmentOutputLocations,
1150*8975f5c5SAndroid Build Coastguard Worker                     mState.mFragmentOutputIndexes))
1151*8975f5c5SAndroid Build Coastguard Worker             {
1152*8975f5c5SAndroid Build Coastguard Worker                 return angle::Result::Stop;
1153*8975f5c5SAndroid Build Coastguard Worker             }
1154*8975f5c5SAndroid Build Coastguard Worker 
1155*8975f5c5SAndroid Build Coastguard Worker             mState.mExecutable->mPod.hasDiscard =
1156*8975f5c5SAndroid Build Coastguard Worker                 fragmentShader->metadataFlags.test(sh::MetadataFlags::HasDiscard);
1157*8975f5c5SAndroid Build Coastguard Worker             mState.mExecutable->mPod.enablesPerSampleShading =
1158*8975f5c5SAndroid Build Coastguard Worker                 fragmentShader->metadataFlags.test(sh::MetadataFlags::EnablesPerSampleShading);
1159*8975f5c5SAndroid Build Coastguard Worker             mState.mExecutable->mPod.hasDepthInputAttachment =
1160*8975f5c5SAndroid Build Coastguard Worker                 fragmentShader->metadataFlags.test(sh::MetadataFlags::HasDepthInputAttachment);
1161*8975f5c5SAndroid Build Coastguard Worker             mState.mExecutable->mPod.hasStencilInputAttachment =
1162*8975f5c5SAndroid Build Coastguard Worker                 fragmentShader->metadataFlags.test(sh::MetadataFlags::HasStencilInputAttachment);
1163*8975f5c5SAndroid Build Coastguard Worker             mState.mExecutable->mPod.advancedBlendEquations =
1164*8975f5c5SAndroid Build Coastguard Worker                 fragmentShader->advancedBlendEquations;
1165*8975f5c5SAndroid Build Coastguard Worker             mState.mExecutable->mPod.specConstUsageBits |= fragmentShader->specConstUsageBits;
1166*8975f5c5SAndroid Build Coastguard Worker 
1167*8975f5c5SAndroid Build Coastguard Worker             for (uint32_t index = 0; index < IMPLEMENTATION_MAX_DRAW_BUFFERS; ++index)
1168*8975f5c5SAndroid Build Coastguard Worker             {
1169*8975f5c5SAndroid Build Coastguard Worker                 const sh::MetadataFlags flag = static_cast<sh::MetadataFlags>(
1170*8975f5c5SAndroid Build Coastguard Worker                     static_cast<uint32_t>(sh::MetadataFlags::HasInputAttachment0) + index);
1171*8975f5c5SAndroid Build Coastguard Worker                 if (fragmentShader->metadataFlags.test(flag))
1172*8975f5c5SAndroid Build Coastguard Worker                 {
1173*8975f5c5SAndroid Build Coastguard Worker                     mState.mExecutable->mPod.fragmentInoutIndices.set(index);
1174*8975f5c5SAndroid Build Coastguard Worker                 }
1175*8975f5c5SAndroid Build Coastguard Worker             }
1176*8975f5c5SAndroid Build Coastguard Worker         }
1177*8975f5c5SAndroid Build Coastguard Worker 
1178*8975f5c5SAndroid Build Coastguard Worker         *mergedVaryingsOut = GetMergedVaryingsFromLinkingVariables(*linkingVariables);
1179*8975f5c5SAndroid Build Coastguard Worker         if (!mState.mExecutable->linkMergedVaryings(caps, limitations, clientVersion, isWebGL,
1180*8975f5c5SAndroid Build Coastguard Worker                                                     *mergedVaryingsOut, *linkingVariables,
1181*8975f5c5SAndroid Build Coastguard Worker                                                     &resources->varyingPacking))
1182*8975f5c5SAndroid Build Coastguard Worker         {
1183*8975f5c5SAndroid Build Coastguard Worker             return angle::Result::Stop;
1184*8975f5c5SAndroid Build Coastguard Worker         }
1185*8975f5c5SAndroid Build Coastguard Worker     }
1186*8975f5c5SAndroid Build Coastguard Worker 
1187*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->saveLinkedStateInfo(mState);
1188*8975f5c5SAndroid Build Coastguard Worker 
1189*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1190*8975f5c5SAndroid Build Coastguard Worker }
1191*8975f5c5SAndroid Build Coastguard Worker 
isLinking() const1192*8975f5c5SAndroid Build Coastguard Worker bool Program::isLinking() const
1193*8975f5c5SAndroid Build Coastguard Worker {
1194*8975f5c5SAndroid Build Coastguard Worker     return mLinkingState.get() && mLinkingState->linkEvent && mLinkingState->linkEvent->isLinking();
1195*8975f5c5SAndroid Build Coastguard Worker }
1196*8975f5c5SAndroid Build Coastguard Worker 
isBinaryReady(const Context * context)1197*8975f5c5SAndroid Build Coastguard Worker bool Program::isBinaryReady(const Context *context)
1198*8975f5c5SAndroid Build Coastguard Worker {
1199*8975f5c5SAndroid Build Coastguard Worker     if (mState.mExecutable->mPostLinkSubTasks.empty())
1200*8975f5c5SAndroid Build Coastguard Worker     {
1201*8975f5c5SAndroid Build Coastguard Worker         // Ensure the program binary is cached, even if the backend waits for post-link tasks
1202*8975f5c5SAndroid Build Coastguard Worker         // without the knowledge of the front-end.
1203*8975f5c5SAndroid Build Coastguard Worker         cacheProgramBinaryIfNotAlready(context);
1204*8975f5c5SAndroid Build Coastguard Worker         return true;
1205*8975f5c5SAndroid Build Coastguard Worker     }
1206*8975f5c5SAndroid Build Coastguard Worker 
1207*8975f5c5SAndroid Build Coastguard Worker     const bool allPostLinkTasksComplete =
1208*8975f5c5SAndroid Build Coastguard Worker         angle::WaitableEvent::AllReady(&mState.mExecutable->getPostLinkSubTaskWaitableEvents());
1209*8975f5c5SAndroid Build Coastguard Worker 
1210*8975f5c5SAndroid Build Coastguard Worker     // Once the binary is ready, the |glGetProgramBinary| call will result in
1211*8975f5c5SAndroid Build Coastguard Worker     // |waitForPostLinkTasks| which in turn may internally cache the binary.  However, for the sake
1212*8975f5c5SAndroid Build Coastguard Worker     // of blob cache tests, call |waitForPostLinkTasks| anyway if tasks are already complete.
1213*8975f5c5SAndroid Build Coastguard Worker     if (allPostLinkTasksComplete)
1214*8975f5c5SAndroid Build Coastguard Worker     {
1215*8975f5c5SAndroid Build Coastguard Worker         waitForPostLinkTasks(context);
1216*8975f5c5SAndroid Build Coastguard Worker     }
1217*8975f5c5SAndroid Build Coastguard Worker 
1218*8975f5c5SAndroid Build Coastguard Worker     return allPostLinkTasksComplete;
1219*8975f5c5SAndroid Build Coastguard Worker }
1220*8975f5c5SAndroid Build Coastguard Worker 
resolveLinkImpl(const Context * context)1221*8975f5c5SAndroid Build Coastguard Worker void Program::resolveLinkImpl(const Context *context)
1222*8975f5c5SAndroid Build Coastguard Worker {
1223*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mLinkingState.get());
1224*8975f5c5SAndroid Build Coastguard Worker 
1225*8975f5c5SAndroid Build Coastguard Worker     angle::Result result                       = mLinkingState->linkEvent->wait(context);
1226*8975f5c5SAndroid Build Coastguard Worker     mLinked                                    = result == angle::Result::Continue;
1227*8975f5c5SAndroid Build Coastguard Worker     std::unique_ptr<LinkingState> linkingState = std::move(mLinkingState);
1228*8975f5c5SAndroid Build Coastguard Worker     if (!mLinked)
1229*8975f5c5SAndroid Build Coastguard Worker     {
1230*8975f5c5SAndroid Build Coastguard Worker         // If the link fails, the spec allows program queries to either return empty results (all
1231*8975f5c5SAndroid Build Coastguard Worker         // zeros) or whatever parts of the link happened to have been done before the failure:
1232*8975f5c5SAndroid Build Coastguard Worker         //
1233*8975f5c5SAndroid Build Coastguard Worker         // > Implementations may return information on variables and interface blocks that would
1234*8975f5c5SAndroid Build Coastguard Worker         // > have been active had the program been linked successfully.  In cases where the link
1235*8975f5c5SAndroid Build Coastguard Worker         // > failed because the program required too many resources, these commands may help
1236*8975f5c5SAndroid Build Coastguard Worker         // > applications determine why limits were exceeded. However, the information returned in
1237*8975f5c5SAndroid Build Coastguard Worker         // > this case is implementation-dependent and may be incomplete.
1238*8975f5c5SAndroid Build Coastguard Worker         //
1239*8975f5c5SAndroid Build Coastguard Worker         // The above means that it's ok for ANGLE to reset the executable here, but it *may* be
1240*8975f5c5SAndroid Build Coastguard Worker         // helpful to applications if it doesn't.  We do reset it however, the info log should
1241*8975f5c5SAndroid Build Coastguard Worker         // already have enough debug information for the application.
1242*8975f5c5SAndroid Build Coastguard Worker         mState.mExecutable->reset();
1243*8975f5c5SAndroid Build Coastguard Worker         return;
1244*8975f5c5SAndroid Build Coastguard Worker     }
1245*8975f5c5SAndroid Build Coastguard Worker 
1246*8975f5c5SAndroid Build Coastguard Worker     // According to GLES 3.0/3.1 spec for LinkProgram and UseProgram,
1247*8975f5c5SAndroid Build Coastguard Worker     // Only successfully linked program can replace the executables.
1248*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mLinked);
1249*8975f5c5SAndroid Build Coastguard Worker 
1250*8975f5c5SAndroid Build Coastguard Worker     // In case of a successful link, it is no longer required for the attached shaders to hold on to
1251*8975f5c5SAndroid Build Coastguard Worker     // the memory they have used. Therefore, the shader compilations are resolved to save memory.
1252*8975f5c5SAndroid Build Coastguard Worker     for (Shader *shader : mAttachedShaders)
1253*8975f5c5SAndroid Build Coastguard Worker     {
1254*8975f5c5SAndroid Build Coastguard Worker         if (shader != nullptr)
1255*8975f5c5SAndroid Build Coastguard Worker         {
1256*8975f5c5SAndroid Build Coastguard Worker             shader->resolveCompile(context);
1257*8975f5c5SAndroid Build Coastguard Worker         }
1258*8975f5c5SAndroid Build Coastguard Worker     }
1259*8975f5c5SAndroid Build Coastguard Worker 
1260*8975f5c5SAndroid Build Coastguard Worker     // Mark implementation-specific unreferenced uniforms as ignored.
1261*8975f5c5SAndroid Build Coastguard Worker     std::vector<ImageBinding> *imageBindings = getExecutable().getImageBindings();
1262*8975f5c5SAndroid Build Coastguard Worker     mProgram->markUnusedUniformLocations(&mState.mExecutable->mUniformLocations,
1263*8975f5c5SAndroid Build Coastguard Worker                                          &mState.mExecutable->mSamplerBindings, imageBindings);
1264*8975f5c5SAndroid Build Coastguard Worker 
1265*8975f5c5SAndroid Build Coastguard Worker     // Must be called after markUnusedUniformLocations.
1266*8975f5c5SAndroid Build Coastguard Worker     postResolveLink(context);
1267*8975f5c5SAndroid Build Coastguard Worker 
1268*8975f5c5SAndroid Build Coastguard Worker     // Notify observers that a new linked executable is available.  If this program is current on a
1269*8975f5c5SAndroid Build Coastguard Worker     // context, the executable is reinstalled.  If it is attached to a PPO, it is installed there
1270*8975f5c5SAndroid Build Coastguard Worker     // and the PPO is marked as needing to be linked again.
1271*8975f5c5SAndroid Build Coastguard Worker     onStateChange(angle::SubjectMessage::ProgramRelinked);
1272*8975f5c5SAndroid Build Coastguard Worker 
1273*8975f5c5SAndroid Build Coastguard Worker     // Cache the program if:
1274*8975f5c5SAndroid Build Coastguard Worker     //
1275*8975f5c5SAndroid Build Coastguard Worker     // - Not loading from binary, in which case the program is already in the cache.
1276*8975f5c5SAndroid Build Coastguard Worker     // - There are no post link tasks. If there are any, waitForPostLinkTasks will do this
1277*8975f5c5SAndroid Build Coastguard Worker     //   instead.
1278*8975f5c5SAndroid Build Coastguard Worker     //   * Note that serialize() calls waitForPostLinkTasks, so caching the binary here
1279*8975f5c5SAndroid Build Coastguard Worker     //     effectively forces a wait for the post-link tasks.
1280*8975f5c5SAndroid Build Coastguard Worker     //
1281*8975f5c5SAndroid Build Coastguard Worker     if (!linkingState->linkingFromBinary && mState.mExecutable->mPostLinkSubTasks.empty())
1282*8975f5c5SAndroid Build Coastguard Worker     {
1283*8975f5c5SAndroid Build Coastguard Worker         cacheProgramBinaryIfNotAlready(context);
1284*8975f5c5SAndroid Build Coastguard Worker     }
1285*8975f5c5SAndroid Build Coastguard Worker }
1286*8975f5c5SAndroid Build Coastguard Worker 
waitForPostLinkTasks(const Context * context)1287*8975f5c5SAndroid Build Coastguard Worker void Program::waitForPostLinkTasks(const Context *context)
1288*8975f5c5SAndroid Build Coastguard Worker {
1289*8975f5c5SAndroid Build Coastguard Worker     // No-op if no tasks.
1290*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->waitForPostLinkTasks(context);
1291*8975f5c5SAndroid Build Coastguard Worker 
1292*8975f5c5SAndroid Build Coastguard Worker     // Now that the subtasks are done, cache the binary (this was deferred in resolveLinkImpl).
1293*8975f5c5SAndroid Build Coastguard Worker     cacheProgramBinaryIfNotAlready(context);
1294*8975f5c5SAndroid Build Coastguard Worker }
1295*8975f5c5SAndroid Build Coastguard Worker 
updateLinkedShaderStages()1296*8975f5c5SAndroid Build Coastguard Worker void Program::updateLinkedShaderStages()
1297*8975f5c5SAndroid Build Coastguard Worker {
1298*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->resetLinkedShaderStages();
1299*8975f5c5SAndroid Build Coastguard Worker 
1300*8975f5c5SAndroid Build Coastguard Worker     for (ShaderType shaderType : AllShaderTypes())
1301*8975f5c5SAndroid Build Coastguard Worker     {
1302*8975f5c5SAndroid Build Coastguard Worker         if (mState.mAttachedShaders[shaderType])
1303*8975f5c5SAndroid Build Coastguard Worker         {
1304*8975f5c5SAndroid Build Coastguard Worker             mState.mExecutable->setLinkedShaderStages(shaderType);
1305*8975f5c5SAndroid Build Coastguard Worker         }
1306*8975f5c5SAndroid Build Coastguard Worker     }
1307*8975f5c5SAndroid Build Coastguard Worker }
1308*8975f5c5SAndroid Build Coastguard Worker 
updateActiveSamplers()1309*8975f5c5SAndroid Build Coastguard Worker void ProgramState::updateActiveSamplers()
1310*8975f5c5SAndroid Build Coastguard Worker {
1311*8975f5c5SAndroid Build Coastguard Worker     mExecutable->mActiveSamplerRefCounts.fill(0);
1312*8975f5c5SAndroid Build Coastguard Worker     mExecutable->updateActiveSamplers(*mExecutable);
1313*8975f5c5SAndroid Build Coastguard Worker }
1314*8975f5c5SAndroid Build Coastguard Worker 
updateProgramInterfaceInputs()1315*8975f5c5SAndroid Build Coastguard Worker void ProgramState::updateProgramInterfaceInputs()
1316*8975f5c5SAndroid Build Coastguard Worker {
1317*8975f5c5SAndroid Build Coastguard Worker     const ShaderType firstAttachedShaderType = mExecutable->getFirstLinkedShaderStageType();
1318*8975f5c5SAndroid Build Coastguard Worker 
1319*8975f5c5SAndroid Build Coastguard Worker     if (firstAttachedShaderType == ShaderType::Vertex)
1320*8975f5c5SAndroid Build Coastguard Worker     {
1321*8975f5c5SAndroid Build Coastguard Worker         // Vertex attributes are already what we need, so nothing to do
1322*8975f5c5SAndroid Build Coastguard Worker         return;
1323*8975f5c5SAndroid Build Coastguard Worker     }
1324*8975f5c5SAndroid Build Coastguard Worker 
1325*8975f5c5SAndroid Build Coastguard Worker     const SharedCompiledShaderState &shader = getAttachedShader(firstAttachedShaderType);
1326*8975f5c5SAndroid Build Coastguard Worker     ASSERT(shader);
1327*8975f5c5SAndroid Build Coastguard Worker 
1328*8975f5c5SAndroid Build Coastguard Worker     // Copy over each input varying, since the Shader could go away
1329*8975f5c5SAndroid Build Coastguard Worker     if (shader->shaderType == ShaderType::Compute)
1330*8975f5c5SAndroid Build Coastguard Worker     {
1331*8975f5c5SAndroid Build Coastguard Worker         for (const sh::ShaderVariable &attribute : shader->allAttributes)
1332*8975f5c5SAndroid Build Coastguard Worker         {
1333*8975f5c5SAndroid Build Coastguard Worker             // Compute Shaders have the following built-in input variables.
1334*8975f5c5SAndroid Build Coastguard Worker             //
1335*8975f5c5SAndroid Build Coastguard Worker             // in uvec3 gl_NumWorkGroups;
1336*8975f5c5SAndroid Build Coastguard Worker             // in uvec3 gl_WorkGroupID;
1337*8975f5c5SAndroid Build Coastguard Worker             // in uvec3 gl_LocalInvocationID;
1338*8975f5c5SAndroid Build Coastguard Worker             // in uvec3 gl_GlobalInvocationID;
1339*8975f5c5SAndroid Build Coastguard Worker             // in uint  gl_LocalInvocationIndex;
1340*8975f5c5SAndroid Build Coastguard Worker             // They are all vecs or uints, so no special handling is required.
1341*8975f5c5SAndroid Build Coastguard Worker             mExecutable->mProgramInputs.emplace_back(attribute);
1342*8975f5c5SAndroid Build Coastguard Worker         }
1343*8975f5c5SAndroid Build Coastguard Worker     }
1344*8975f5c5SAndroid Build Coastguard Worker     else
1345*8975f5c5SAndroid Build Coastguard Worker     {
1346*8975f5c5SAndroid Build Coastguard Worker         for (const sh::ShaderVariable &varying : shader->inputVaryings)
1347*8975f5c5SAndroid Build Coastguard Worker         {
1348*8975f5c5SAndroid Build Coastguard Worker             UpdateInterfaceVariable(&mExecutable->mProgramInputs, varying);
1349*8975f5c5SAndroid Build Coastguard Worker         }
1350*8975f5c5SAndroid Build Coastguard Worker     }
1351*8975f5c5SAndroid Build Coastguard Worker }
1352*8975f5c5SAndroid Build Coastguard Worker 
updateProgramInterfaceOutputs()1353*8975f5c5SAndroid Build Coastguard Worker void ProgramState::updateProgramInterfaceOutputs()
1354*8975f5c5SAndroid Build Coastguard Worker {
1355*8975f5c5SAndroid Build Coastguard Worker     const ShaderType lastAttachedShaderType = mExecutable->getLastLinkedShaderStageType();
1356*8975f5c5SAndroid Build Coastguard Worker 
1357*8975f5c5SAndroid Build Coastguard Worker     if (lastAttachedShaderType == ShaderType::Fragment)
1358*8975f5c5SAndroid Build Coastguard Worker     {
1359*8975f5c5SAndroid Build Coastguard Worker         // Fragment outputs are already what we need, so nothing to do
1360*8975f5c5SAndroid Build Coastguard Worker         return;
1361*8975f5c5SAndroid Build Coastguard Worker     }
1362*8975f5c5SAndroid Build Coastguard Worker     if (lastAttachedShaderType == ShaderType::Compute)
1363*8975f5c5SAndroid Build Coastguard Worker     {
1364*8975f5c5SAndroid Build Coastguard Worker         // If the program only contains a Compute Shader, then there are no user-defined outputs.
1365*8975f5c5SAndroid Build Coastguard Worker         return;
1366*8975f5c5SAndroid Build Coastguard Worker     }
1367*8975f5c5SAndroid Build Coastguard Worker 
1368*8975f5c5SAndroid Build Coastguard Worker     const SharedCompiledShaderState &shader = getAttachedShader(lastAttachedShaderType);
1369*8975f5c5SAndroid Build Coastguard Worker     ASSERT(shader);
1370*8975f5c5SAndroid Build Coastguard Worker 
1371*8975f5c5SAndroid Build Coastguard Worker     // Copy over each output varying, since the Shader could go away
1372*8975f5c5SAndroid Build Coastguard Worker     for (const sh::ShaderVariable &varying : shader->outputVaryings)
1373*8975f5c5SAndroid Build Coastguard Worker     {
1374*8975f5c5SAndroid Build Coastguard Worker         UpdateInterfaceVariable(&mExecutable->mOutputVariables, varying);
1375*8975f5c5SAndroid Build Coastguard Worker     }
1376*8975f5c5SAndroid Build Coastguard Worker }
1377*8975f5c5SAndroid Build Coastguard Worker 
1378*8975f5c5SAndroid Build Coastguard Worker // Returns the program object to an unlinked state, before re-linking, or at destruction
unlink()1379*8975f5c5SAndroid Build Coastguard Worker void Program::unlink()
1380*8975f5c5SAndroid Build Coastguard Worker {
1381*8975f5c5SAndroid Build Coastguard Worker     // There is always a new executable created on link, so the executable is already in a clean
1382*8975f5c5SAndroid Build Coastguard Worker     // state.
1383*8975f5c5SAndroid Build Coastguard Worker 
1384*8975f5c5SAndroid Build Coastguard Worker     mValidated = false;
1385*8975f5c5SAndroid Build Coastguard Worker }
1386*8975f5c5SAndroid Build Coastguard Worker 
setBinary(const Context * context,GLenum binaryFormat,const void * binary,GLsizei length)1387*8975f5c5SAndroid Build Coastguard Worker angle::Result Program::setBinary(const Context *context,
1388*8975f5c5SAndroid Build Coastguard Worker                                  GLenum binaryFormat,
1389*8975f5c5SAndroid Build Coastguard Worker                                  const void *binary,
1390*8975f5c5SAndroid Build Coastguard Worker                                  GLsizei length)
1391*8975f5c5SAndroid Build Coastguard Worker {
1392*8975f5c5SAndroid Build Coastguard Worker     ASSERT(binaryFormat == GL_PROGRAM_BINARY_ANGLE);
1393*8975f5c5SAndroid Build Coastguard Worker 
1394*8975f5c5SAndroid Build Coastguard Worker     makeNewExecutable(context);
1395*8975f5c5SAndroid Build Coastguard Worker 
1396*8975f5c5SAndroid Build Coastguard Worker     egl::CacheGetResult result = egl::CacheGetResult::NotFound;
1397*8975f5c5SAndroid Build Coastguard Worker     return loadBinary(context, binary, length, &result);
1398*8975f5c5SAndroid Build Coastguard Worker }
1399*8975f5c5SAndroid Build Coastguard Worker 
loadBinary(const Context * context,const void * binary,GLsizei length,egl::CacheGetResult * resultOut)1400*8975f5c5SAndroid Build Coastguard Worker angle::Result Program::loadBinary(const Context *context,
1401*8975f5c5SAndroid Build Coastguard Worker                                   const void *binary,
1402*8975f5c5SAndroid Build Coastguard Worker                                   GLsizei length,
1403*8975f5c5SAndroid Build Coastguard Worker                                   egl::CacheGetResult *resultOut)
1404*8975f5c5SAndroid Build Coastguard Worker {
1405*8975f5c5SAndroid Build Coastguard Worker     *resultOut = egl::CacheGetResult::Rejected;
1406*8975f5c5SAndroid Build Coastguard Worker 
1407*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mLinkingState);
1408*8975f5c5SAndroid Build Coastguard Worker     unlink();
1409*8975f5c5SAndroid Build Coastguard Worker 
1410*8975f5c5SAndroid Build Coastguard Worker     BinaryInputStream stream(binary, length);
1411*8975f5c5SAndroid Build Coastguard Worker     if (!deserialize(context, stream))
1412*8975f5c5SAndroid Build Coastguard Worker     {
1413*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
1414*8975f5c5SAndroid Build Coastguard Worker     }
1415*8975f5c5SAndroid Build Coastguard Worker     // Currently we require the full shader text to compute the program hash.
1416*8975f5c5SAndroid Build Coastguard Worker     // We could also store the binary in the internal program cache.
1417*8975f5c5SAndroid Build Coastguard Worker 
1418*8975f5c5SAndroid Build Coastguard Worker     // Initialize the uniform block -> buffer index map based on serialized data.
1419*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->initInterfaceBlockBindings();
1420*8975f5c5SAndroid Build Coastguard Worker 
1421*8975f5c5SAndroid Build Coastguard Worker     // If load does not succeed, we know for sure that the binary is not compatible with the
1422*8975f5c5SAndroid Build Coastguard Worker     // backend.  The loaded binary could have been read from the on-disk shader cache and be
1423*8975f5c5SAndroid Build Coastguard Worker     // corrupted or serialized with different revision and subsystem id than the currently loaded
1424*8975f5c5SAndroid Build Coastguard Worker     // backend.  Returning to the caller results in link happening using the original shader
1425*8975f5c5SAndroid Build Coastguard Worker     // sources.
1426*8975f5c5SAndroid Build Coastguard Worker     std::shared_ptr<rx::LinkTask> loadTask;
1427*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mProgram->load(context, &stream, &loadTask, resultOut));
1428*8975f5c5SAndroid Build Coastguard Worker     if (*resultOut == egl::CacheGetResult::Rejected)
1429*8975f5c5SAndroid Build Coastguard Worker     {
1430*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
1431*8975f5c5SAndroid Build Coastguard Worker     }
1432*8975f5c5SAndroid Build Coastguard Worker 
1433*8975f5c5SAndroid Build Coastguard Worker     std::unique_ptr<LinkEvent> loadEvent;
1434*8975f5c5SAndroid Build Coastguard Worker     if (loadTask)
1435*8975f5c5SAndroid Build Coastguard Worker     {
1436*8975f5c5SAndroid Build Coastguard Worker         std::shared_ptr<MainLinkLoadTask> mainLoadTask(new MainLoadTask(
1437*8975f5c5SAndroid Build Coastguard Worker             context->getLinkSubTaskThreadPool(), this, &mState, std::move(loadTask)));
1438*8975f5c5SAndroid Build Coastguard Worker 
1439*8975f5c5SAndroid Build Coastguard Worker         std::shared_ptr<angle::WaitableEvent> mainLoadEvent =
1440*8975f5c5SAndroid Build Coastguard Worker             context->getShaderCompileThreadPool()->postWorkerTask(mainLoadTask);
1441*8975f5c5SAndroid Build Coastguard Worker         loadEvent = std::make_unique<MainLinkLoadEvent>(mainLoadTask, mainLoadEvent);
1442*8975f5c5SAndroid Build Coastguard Worker     }
1443*8975f5c5SAndroid Build Coastguard Worker     else
1444*8975f5c5SAndroid Build Coastguard Worker     {
1445*8975f5c5SAndroid Build Coastguard Worker         loadEvent = std::make_unique<LinkEventDone>(angle::Result::Continue);
1446*8975f5c5SAndroid Build Coastguard Worker     }
1447*8975f5c5SAndroid Build Coastguard Worker 
1448*8975f5c5SAndroid Build Coastguard Worker     mLinkingState->linkingFromBinary = true;
1449*8975f5c5SAndroid Build Coastguard Worker     mLinkingState->linkEvent         = std::move(loadEvent);
1450*8975f5c5SAndroid Build Coastguard Worker 
1451*8975f5c5SAndroid Build Coastguard Worker     // Don't attempt to cache the binary that's just loaded
1452*8975f5c5SAndroid Build Coastguard Worker     mIsBinaryCached = true;
1453*8975f5c5SAndroid Build Coastguard Worker 
1454*8975f5c5SAndroid Build Coastguard Worker     *resultOut = egl::CacheGetResult::Success;
1455*8975f5c5SAndroid Build Coastguard Worker 
1456*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1457*8975f5c5SAndroid Build Coastguard Worker }
1458*8975f5c5SAndroid Build Coastguard Worker 
getBinary(Context * context,GLenum * binaryFormat,void * binary,GLsizei bufSize,GLsizei * length)1459*8975f5c5SAndroid Build Coastguard Worker angle::Result Program::getBinary(Context *context,
1460*8975f5c5SAndroid Build Coastguard Worker                                  GLenum *binaryFormat,
1461*8975f5c5SAndroid Build Coastguard Worker                                  void *binary,
1462*8975f5c5SAndroid Build Coastguard Worker                                  GLsizei bufSize,
1463*8975f5c5SAndroid Build Coastguard Worker                                  GLsizei *length)
1464*8975f5c5SAndroid Build Coastguard Worker {
1465*8975f5c5SAndroid Build Coastguard Worker     if (!mState.mBinaryRetrieveableHint)
1466*8975f5c5SAndroid Build Coastguard Worker     {
1467*8975f5c5SAndroid Build Coastguard Worker         ANGLE_PERF_WARNING(
1468*8975f5c5SAndroid Build Coastguard Worker             context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
1469*8975f5c5SAndroid Build Coastguard Worker             "Saving program binary without GL_PROGRAM_BINARY_RETRIEVABLE_HINT is suboptimal.");
1470*8975f5c5SAndroid Build Coastguard Worker     }
1471*8975f5c5SAndroid Build Coastguard Worker 
1472*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mLinkingState);
1473*8975f5c5SAndroid Build Coastguard Worker     if (binaryFormat)
1474*8975f5c5SAndroid Build Coastguard Worker     {
1475*8975f5c5SAndroid Build Coastguard Worker         *binaryFormat = GL_PROGRAM_BINARY_ANGLE;
1476*8975f5c5SAndroid Build Coastguard Worker     }
1477*8975f5c5SAndroid Build Coastguard Worker 
1478*8975f5c5SAndroid Build Coastguard Worker     // Serialize the program only if not already done.
1479*8975f5c5SAndroid Build Coastguard Worker     if (mBinary.empty())
1480*8975f5c5SAndroid Build Coastguard Worker     {
1481*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(serialize(context));
1482*8975f5c5SAndroid Build Coastguard Worker     }
1483*8975f5c5SAndroid Build Coastguard Worker 
1484*8975f5c5SAndroid Build Coastguard Worker     GLsizei streamLength       = static_cast<GLsizei>(mBinary.size());
1485*8975f5c5SAndroid Build Coastguard Worker     const uint8_t *streamState = mBinary.data();
1486*8975f5c5SAndroid Build Coastguard Worker 
1487*8975f5c5SAndroid Build Coastguard Worker     if (streamLength > bufSize)
1488*8975f5c5SAndroid Build Coastguard Worker     {
1489*8975f5c5SAndroid Build Coastguard Worker         if (length)
1490*8975f5c5SAndroid Build Coastguard Worker         {
1491*8975f5c5SAndroid Build Coastguard Worker             *length = 0;
1492*8975f5c5SAndroid Build Coastguard Worker         }
1493*8975f5c5SAndroid Build Coastguard Worker 
1494*8975f5c5SAndroid Build Coastguard Worker         // TODO: This should be moved to the validation layer but computing the size of the binary
1495*8975f5c5SAndroid Build Coastguard Worker         // before saving it causes the save to happen twice.  It may be possible to write the binary
1496*8975f5c5SAndroid Build Coastguard Worker         // to a separate buffer, validate sizes and then copy it.
1497*8975f5c5SAndroid Build Coastguard Worker         ANGLE_CHECK(context, false, "Insufficient buffer size", GL_INVALID_OPERATION);
1498*8975f5c5SAndroid Build Coastguard Worker     }
1499*8975f5c5SAndroid Build Coastguard Worker 
1500*8975f5c5SAndroid Build Coastguard Worker     if (binary)
1501*8975f5c5SAndroid Build Coastguard Worker     {
1502*8975f5c5SAndroid Build Coastguard Worker         char *ptr = reinterpret_cast<char *>(binary);
1503*8975f5c5SAndroid Build Coastguard Worker 
1504*8975f5c5SAndroid Build Coastguard Worker         memcpy(ptr, streamState, streamLength);
1505*8975f5c5SAndroid Build Coastguard Worker         ptr += streamLength;
1506*8975f5c5SAndroid Build Coastguard Worker 
1507*8975f5c5SAndroid Build Coastguard Worker         ASSERT(ptr - streamLength == binary);
1508*8975f5c5SAndroid Build Coastguard Worker 
1509*8975f5c5SAndroid Build Coastguard Worker         // Once the binary is retrieved, assume the application will never need the binary and
1510*8975f5c5SAndroid Build Coastguard Worker         // release the memory.  Note that implicit caching to blob cache is disabled when the
1511*8975f5c5SAndroid Build Coastguard Worker         // GL_PROGRAM_BINARY_RETRIEVABLE_HINT is set.  If that hint is not set, serialization is
1512*8975f5c5SAndroid Build Coastguard Worker         // done twice, which is what the perf warning above is about!
1513*8975f5c5SAndroid Build Coastguard Worker         mBinary.clear();
1514*8975f5c5SAndroid Build Coastguard Worker     }
1515*8975f5c5SAndroid Build Coastguard Worker 
1516*8975f5c5SAndroid Build Coastguard Worker     if (length)
1517*8975f5c5SAndroid Build Coastguard Worker     {
1518*8975f5c5SAndroid Build Coastguard Worker         *length = streamLength;
1519*8975f5c5SAndroid Build Coastguard Worker     }
1520*8975f5c5SAndroid Build Coastguard Worker 
1521*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1522*8975f5c5SAndroid Build Coastguard Worker }
1523*8975f5c5SAndroid Build Coastguard Worker 
getBinaryLength(Context * context)1524*8975f5c5SAndroid Build Coastguard Worker GLint Program::getBinaryLength(Context *context)
1525*8975f5c5SAndroid Build Coastguard Worker {
1526*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mLinkingState);
1527*8975f5c5SAndroid Build Coastguard Worker     if (!mLinked)
1528*8975f5c5SAndroid Build Coastguard Worker     {
1529*8975f5c5SAndroid Build Coastguard Worker         return 0;
1530*8975f5c5SAndroid Build Coastguard Worker     }
1531*8975f5c5SAndroid Build Coastguard Worker 
1532*8975f5c5SAndroid Build Coastguard Worker     GLint length;
1533*8975f5c5SAndroid Build Coastguard Worker     angle::Result result =
1534*8975f5c5SAndroid Build Coastguard Worker         getBinary(context, nullptr, nullptr, std::numeric_limits<GLint>::max(), &length);
1535*8975f5c5SAndroid Build Coastguard Worker     if (result != angle::Result::Continue)
1536*8975f5c5SAndroid Build Coastguard Worker     {
1537*8975f5c5SAndroid Build Coastguard Worker         return 0;
1538*8975f5c5SAndroid Build Coastguard Worker     }
1539*8975f5c5SAndroid Build Coastguard Worker 
1540*8975f5c5SAndroid Build Coastguard Worker     return length;
1541*8975f5c5SAndroid Build Coastguard Worker }
1542*8975f5c5SAndroid Build Coastguard Worker 
setBinaryRetrievableHint(bool retrievable)1543*8975f5c5SAndroid Build Coastguard Worker void Program::setBinaryRetrievableHint(bool retrievable)
1544*8975f5c5SAndroid Build Coastguard Worker {
1545*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mLinkingState);
1546*8975f5c5SAndroid Build Coastguard Worker     // TODO(jmadill) : replace with dirty bits
1547*8975f5c5SAndroid Build Coastguard Worker     mProgram->setBinaryRetrievableHint(retrievable);
1548*8975f5c5SAndroid Build Coastguard Worker     mState.mBinaryRetrieveableHint = retrievable;
1549*8975f5c5SAndroid Build Coastguard Worker }
1550*8975f5c5SAndroid Build Coastguard Worker 
getBinaryRetrievableHint() const1551*8975f5c5SAndroid Build Coastguard Worker bool Program::getBinaryRetrievableHint() const
1552*8975f5c5SAndroid Build Coastguard Worker {
1553*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mLinkingState);
1554*8975f5c5SAndroid Build Coastguard Worker     return mState.mBinaryRetrieveableHint;
1555*8975f5c5SAndroid Build Coastguard Worker }
1556*8975f5c5SAndroid Build Coastguard Worker 
getInfoLogLength() const1557*8975f5c5SAndroid Build Coastguard Worker int Program::getInfoLogLength() const
1558*8975f5c5SAndroid Build Coastguard Worker {
1559*8975f5c5SAndroid Build Coastguard Worker     return static_cast<int>(mState.mInfoLog.getLength());
1560*8975f5c5SAndroid Build Coastguard Worker }
1561*8975f5c5SAndroid Build Coastguard Worker 
getInfoLog(GLsizei bufSize,GLsizei * length,char * infoLog) const1562*8975f5c5SAndroid Build Coastguard Worker void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
1563*8975f5c5SAndroid Build Coastguard Worker {
1564*8975f5c5SAndroid Build Coastguard Worker     return mState.mInfoLog.getLog(bufSize, length, infoLog);
1565*8975f5c5SAndroid Build Coastguard Worker }
1566*8975f5c5SAndroid Build Coastguard Worker 
setSeparable(const Context * context,bool separable)1567*8975f5c5SAndroid Build Coastguard Worker void Program::setSeparable(const Context *context, bool separable)
1568*8975f5c5SAndroid Build Coastguard Worker {
1569*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mLinkingState);
1570*8975f5c5SAndroid Build Coastguard Worker 
1571*8975f5c5SAndroid Build Coastguard Worker     if (isSeparable() != separable)
1572*8975f5c5SAndroid Build Coastguard Worker     {
1573*8975f5c5SAndroid Build Coastguard Worker         mProgram->setSeparable(separable);
1574*8975f5c5SAndroid Build Coastguard Worker         mState.mSeparable = separable;
1575*8975f5c5SAndroid Build Coastguard Worker     }
1576*8975f5c5SAndroid Build Coastguard Worker }
1577*8975f5c5SAndroid Build Coastguard Worker 
deleteSelf(const Context * context)1578*8975f5c5SAndroid Build Coastguard Worker void Program::deleteSelf(const Context *context)
1579*8975f5c5SAndroid Build Coastguard Worker {
1580*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mRefCount == 0 && mDeleteStatus);
1581*8975f5c5SAndroid Build Coastguard Worker     mResourceManager->deleteProgram(context, mHandle);
1582*8975f5c5SAndroid Build Coastguard Worker }
1583*8975f5c5SAndroid Build Coastguard Worker 
getRefCount() const1584*8975f5c5SAndroid Build Coastguard Worker unsigned int Program::getRefCount() const
1585*8975f5c5SAndroid Build Coastguard Worker {
1586*8975f5c5SAndroid Build Coastguard Worker     return mRefCount;
1587*8975f5c5SAndroid Build Coastguard Worker }
1588*8975f5c5SAndroid Build Coastguard Worker 
getAttachedShaders(GLsizei maxCount,GLsizei * count,ShaderProgramID * shaders) const1589*8975f5c5SAndroid Build Coastguard Worker void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, ShaderProgramID *shaders) const
1590*8975f5c5SAndroid Build Coastguard Worker {
1591*8975f5c5SAndroid Build Coastguard Worker     int total = 0;
1592*8975f5c5SAndroid Build Coastguard Worker 
1593*8975f5c5SAndroid Build Coastguard Worker     for (const Shader *shader : mAttachedShaders)
1594*8975f5c5SAndroid Build Coastguard Worker     {
1595*8975f5c5SAndroid Build Coastguard Worker         if (shader != nullptr && total < maxCount)
1596*8975f5c5SAndroid Build Coastguard Worker         {
1597*8975f5c5SAndroid Build Coastguard Worker             shaders[total] = shader->getHandle();
1598*8975f5c5SAndroid Build Coastguard Worker             ++total;
1599*8975f5c5SAndroid Build Coastguard Worker         }
1600*8975f5c5SAndroid Build Coastguard Worker     }
1601*8975f5c5SAndroid Build Coastguard Worker 
1602*8975f5c5SAndroid Build Coastguard Worker     if (count)
1603*8975f5c5SAndroid Build Coastguard Worker     {
1604*8975f5c5SAndroid Build Coastguard Worker         *count = total;
1605*8975f5c5SAndroid Build Coastguard Worker     }
1606*8975f5c5SAndroid Build Coastguard Worker }
1607*8975f5c5SAndroid Build Coastguard Worker 
flagForDeletion()1608*8975f5c5SAndroid Build Coastguard Worker void Program::flagForDeletion()
1609*8975f5c5SAndroid Build Coastguard Worker {
1610*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mLinkingState);
1611*8975f5c5SAndroid Build Coastguard Worker     mDeleteStatus = true;
1612*8975f5c5SAndroid Build Coastguard Worker }
1613*8975f5c5SAndroid Build Coastguard Worker 
isFlaggedForDeletion() const1614*8975f5c5SAndroid Build Coastguard Worker bool Program::isFlaggedForDeletion() const
1615*8975f5c5SAndroid Build Coastguard Worker {
1616*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mLinkingState);
1617*8975f5c5SAndroid Build Coastguard Worker     return mDeleteStatus;
1618*8975f5c5SAndroid Build Coastguard Worker }
1619*8975f5c5SAndroid Build Coastguard Worker 
validate(const Caps & caps)1620*8975f5c5SAndroid Build Coastguard Worker void Program::validate(const Caps &caps)
1621*8975f5c5SAndroid Build Coastguard Worker {
1622*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mLinkingState);
1623*8975f5c5SAndroid Build Coastguard Worker     mState.mInfoLog.reset();
1624*8975f5c5SAndroid Build Coastguard Worker 
1625*8975f5c5SAndroid Build Coastguard Worker     if (mLinked)
1626*8975f5c5SAndroid Build Coastguard Worker     {
1627*8975f5c5SAndroid Build Coastguard Worker         mValidated = ConvertToBool(mProgram->validate(caps));
1628*8975f5c5SAndroid Build Coastguard Worker     }
1629*8975f5c5SAndroid Build Coastguard Worker     else
1630*8975f5c5SAndroid Build Coastguard Worker     {
1631*8975f5c5SAndroid Build Coastguard Worker         mState.mInfoLog << "Program has not been successfully linked.";
1632*8975f5c5SAndroid Build Coastguard Worker     }
1633*8975f5c5SAndroid Build Coastguard Worker }
1634*8975f5c5SAndroid Build Coastguard Worker 
isValidated() const1635*8975f5c5SAndroid Build Coastguard Worker bool Program::isValidated() const
1636*8975f5c5SAndroid Build Coastguard Worker {
1637*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mLinkingState);
1638*8975f5c5SAndroid Build Coastguard Worker     return mValidated;
1639*8975f5c5SAndroid Build Coastguard Worker }
1640*8975f5c5SAndroid Build Coastguard Worker 
bindUniformBlock(UniformBlockIndex uniformBlockIndex,GLuint uniformBlockBinding)1641*8975f5c5SAndroid Build Coastguard Worker void Program::bindUniformBlock(UniformBlockIndex uniformBlockIndex, GLuint uniformBlockBinding)
1642*8975f5c5SAndroid Build Coastguard Worker {
1643*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mLinkingState);
1644*8975f5c5SAndroid Build Coastguard Worker 
1645*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->remapUniformBlockBinding(uniformBlockIndex, uniformBlockBinding);
1646*8975f5c5SAndroid Build Coastguard Worker 
1647*8975f5c5SAndroid Build Coastguard Worker     mProgram->onUniformBlockBinding(uniformBlockIndex);
1648*8975f5c5SAndroid Build Coastguard Worker 
1649*8975f5c5SAndroid Build Coastguard Worker     onStateChange(
1650*8975f5c5SAndroid Build Coastguard Worker         angle::ProgramUniformBlockBindingUpdatedMessageFromIndex(uniformBlockIndex.value));
1651*8975f5c5SAndroid Build Coastguard Worker }
1652*8975f5c5SAndroid Build Coastguard Worker 
setTransformFeedbackVaryings(const Context * context,GLsizei count,const GLchar * const * varyings,GLenum bufferMode)1653*8975f5c5SAndroid Build Coastguard Worker void Program::setTransformFeedbackVaryings(const Context *context,
1654*8975f5c5SAndroid Build Coastguard Worker                                            GLsizei count,
1655*8975f5c5SAndroid Build Coastguard Worker                                            const GLchar *const *varyings,
1656*8975f5c5SAndroid Build Coastguard Worker                                            GLenum bufferMode)
1657*8975f5c5SAndroid Build Coastguard Worker {
1658*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mLinkingState);
1659*8975f5c5SAndroid Build Coastguard Worker 
1660*8975f5c5SAndroid Build Coastguard Worker     mState.mTransformFeedbackVaryingNames.resize(count);
1661*8975f5c5SAndroid Build Coastguard Worker     for (GLsizei i = 0; i < count; i++)
1662*8975f5c5SAndroid Build Coastguard Worker     {
1663*8975f5c5SAndroid Build Coastguard Worker         mState.mTransformFeedbackVaryingNames[i] = varyings[i];
1664*8975f5c5SAndroid Build Coastguard Worker     }
1665*8975f5c5SAndroid Build Coastguard Worker 
1666*8975f5c5SAndroid Build Coastguard Worker     mState.mTransformFeedbackBufferMode = bufferMode;
1667*8975f5c5SAndroid Build Coastguard Worker }
1668*8975f5c5SAndroid Build Coastguard Worker 
linkValidateShaders()1669*8975f5c5SAndroid Build Coastguard Worker bool Program::linkValidateShaders()
1670*8975f5c5SAndroid Build Coastguard Worker {
1671*8975f5c5SAndroid Build Coastguard Worker     // Wait for attached shaders to finish compilation.  At this point, they need to be checked
1672*8975f5c5SAndroid Build Coastguard Worker     // whether they successfully compiled.  This information is cached so that all compile jobs can
1673*8975f5c5SAndroid Build Coastguard Worker     // be waited on and their corresponding objects released before the actual check.
1674*8975f5c5SAndroid Build Coastguard Worker     //
1675*8975f5c5SAndroid Build Coastguard Worker     // Note that this function is called from the link job, and is therefore not protected by any
1676*8975f5c5SAndroid Build Coastguard Worker     // locks.
1677*8975f5c5SAndroid Build Coastguard Worker     ShaderBitSet successfullyCompiledShaders;
1678*8975f5c5SAndroid Build Coastguard Worker     for (ShaderType shaderType : AllShaderTypes())
1679*8975f5c5SAndroid Build Coastguard Worker     {
1680*8975f5c5SAndroid Build Coastguard Worker         const SharedCompileJob &compileJob = mState.mShaderCompileJobs[shaderType];
1681*8975f5c5SAndroid Build Coastguard Worker         if (compileJob)
1682*8975f5c5SAndroid Build Coastguard Worker         {
1683*8975f5c5SAndroid Build Coastguard Worker             const bool success = WaitCompileJobUnlocked(compileJob);
1684*8975f5c5SAndroid Build Coastguard Worker             successfullyCompiledShaders.set(shaderType, success);
1685*8975f5c5SAndroid Build Coastguard Worker         }
1686*8975f5c5SAndroid Build Coastguard Worker     }
1687*8975f5c5SAndroid Build Coastguard Worker     mState.mShaderCompileJobs = {};
1688*8975f5c5SAndroid Build Coastguard Worker 
1689*8975f5c5SAndroid Build Coastguard Worker     const ShaderMap<SharedCompiledShaderState> &shaders = mState.mAttachedShaders;
1690*8975f5c5SAndroid Build Coastguard Worker 
1691*8975f5c5SAndroid Build Coastguard Worker     bool isComputeShaderAttached  = shaders[ShaderType::Compute].get() != nullptr;
1692*8975f5c5SAndroid Build Coastguard Worker     bool isGraphicsShaderAttached = shaders[ShaderType::Vertex].get() != nullptr ||
1693*8975f5c5SAndroid Build Coastguard Worker                                     shaders[ShaderType::TessControl].get() != nullptr ||
1694*8975f5c5SAndroid Build Coastguard Worker                                     shaders[ShaderType::TessEvaluation].get() != nullptr ||
1695*8975f5c5SAndroid Build Coastguard Worker                                     shaders[ShaderType::Geometry].get() != nullptr ||
1696*8975f5c5SAndroid Build Coastguard Worker                                     shaders[ShaderType::Fragment].get() != nullptr;
1697*8975f5c5SAndroid Build Coastguard Worker     // Check whether we both have a compute and non-compute shaders attached.
1698*8975f5c5SAndroid Build Coastguard Worker     // If there are of both types attached, then linking should fail.
1699*8975f5c5SAndroid Build Coastguard Worker     // OpenGL ES 3.10, 7.3 Program Objects, under LinkProgram
1700*8975f5c5SAndroid Build Coastguard Worker     if (isComputeShaderAttached && isGraphicsShaderAttached)
1701*8975f5c5SAndroid Build Coastguard Worker     {
1702*8975f5c5SAndroid Build Coastguard Worker         mState.mInfoLog << "Both compute and graphics shaders are attached to the same program.";
1703*8975f5c5SAndroid Build Coastguard Worker         return false;
1704*8975f5c5SAndroid Build Coastguard Worker     }
1705*8975f5c5SAndroid Build Coastguard Worker 
1706*8975f5c5SAndroid Build Coastguard Worker     Optional<int> version;
1707*8975f5c5SAndroid Build Coastguard Worker     for (ShaderType shaderType : kAllGraphicsShaderTypes)
1708*8975f5c5SAndroid Build Coastguard Worker     {
1709*8975f5c5SAndroid Build Coastguard Worker         const SharedCompiledShaderState &shader = shaders[shaderType];
1710*8975f5c5SAndroid Build Coastguard Worker         ASSERT(!shader || shader->shaderType == shaderType);
1711*8975f5c5SAndroid Build Coastguard Worker 
1712*8975f5c5SAndroid Build Coastguard Worker         if (!shader)
1713*8975f5c5SAndroid Build Coastguard Worker         {
1714*8975f5c5SAndroid Build Coastguard Worker             continue;
1715*8975f5c5SAndroid Build Coastguard Worker         }
1716*8975f5c5SAndroid Build Coastguard Worker 
1717*8975f5c5SAndroid Build Coastguard Worker         if (!successfullyCompiledShaders.test(shaderType))
1718*8975f5c5SAndroid Build Coastguard Worker         {
1719*8975f5c5SAndroid Build Coastguard Worker             mState.mInfoLog << ShaderTypeToString(shaderType) << " shader is not compiled.";
1720*8975f5c5SAndroid Build Coastguard Worker             return false;
1721*8975f5c5SAndroid Build Coastguard Worker         }
1722*8975f5c5SAndroid Build Coastguard Worker 
1723*8975f5c5SAndroid Build Coastguard Worker         if (!version.valid())
1724*8975f5c5SAndroid Build Coastguard Worker         {
1725*8975f5c5SAndroid Build Coastguard Worker             version = shader->shaderVersion;
1726*8975f5c5SAndroid Build Coastguard Worker         }
1727*8975f5c5SAndroid Build Coastguard Worker         else if (version != shader->shaderVersion)
1728*8975f5c5SAndroid Build Coastguard Worker         {
1729*8975f5c5SAndroid Build Coastguard Worker             mState.mInfoLog << ShaderTypeToString(shaderType)
1730*8975f5c5SAndroid Build Coastguard Worker                             << " shader version does not match other shader versions.";
1731*8975f5c5SAndroid Build Coastguard Worker             return false;
1732*8975f5c5SAndroid Build Coastguard Worker         }
1733*8975f5c5SAndroid Build Coastguard Worker     }
1734*8975f5c5SAndroid Build Coastguard Worker 
1735*8975f5c5SAndroid Build Coastguard Worker     if (isComputeShaderAttached)
1736*8975f5c5SAndroid Build Coastguard Worker     {
1737*8975f5c5SAndroid Build Coastguard Worker         ASSERT(shaders[ShaderType::Compute]->shaderType == ShaderType::Compute);
1738*8975f5c5SAndroid Build Coastguard Worker 
1739*8975f5c5SAndroid Build Coastguard Worker         // GLSL ES 3.10, 4.4.1.1 Compute Shader Inputs
1740*8975f5c5SAndroid Build Coastguard Worker         // If the work group size is not specified, a link time error should occur.
1741*8975f5c5SAndroid Build Coastguard Worker         if (!shaders[ShaderType::Compute]->localSize.isDeclared())
1742*8975f5c5SAndroid Build Coastguard Worker         {
1743*8975f5c5SAndroid Build Coastguard Worker             mState.mInfoLog << "Work group size is not specified.";
1744*8975f5c5SAndroid Build Coastguard Worker             return false;
1745*8975f5c5SAndroid Build Coastguard Worker         }
1746*8975f5c5SAndroid Build Coastguard Worker     }
1747*8975f5c5SAndroid Build Coastguard Worker     else
1748*8975f5c5SAndroid Build Coastguard Worker     {
1749*8975f5c5SAndroid Build Coastguard Worker         if (!isGraphicsShaderAttached)
1750*8975f5c5SAndroid Build Coastguard Worker         {
1751*8975f5c5SAndroid Build Coastguard Worker             mState.mInfoLog << "No compiled shaders.";
1752*8975f5c5SAndroid Build Coastguard Worker             return false;
1753*8975f5c5SAndroid Build Coastguard Worker         }
1754*8975f5c5SAndroid Build Coastguard Worker 
1755*8975f5c5SAndroid Build Coastguard Worker         bool hasVertex   = shaders[ShaderType::Vertex].get() != nullptr;
1756*8975f5c5SAndroid Build Coastguard Worker         bool hasFragment = shaders[ShaderType::Fragment].get() != nullptr;
1757*8975f5c5SAndroid Build Coastguard Worker         if (!isSeparable() && (!hasVertex || !hasFragment))
1758*8975f5c5SAndroid Build Coastguard Worker         {
1759*8975f5c5SAndroid Build Coastguard Worker             mState.mInfoLog
1760*8975f5c5SAndroid Build Coastguard Worker                 << "The program must contain objects to form both a vertex and fragment shader.";
1761*8975f5c5SAndroid Build Coastguard Worker             return false;
1762*8975f5c5SAndroid Build Coastguard Worker         }
1763*8975f5c5SAndroid Build Coastguard Worker 
1764*8975f5c5SAndroid Build Coastguard Worker         bool hasTessControl    = shaders[ShaderType::TessControl].get() != nullptr;
1765*8975f5c5SAndroid Build Coastguard Worker         bool hasTessEvaluation = shaders[ShaderType::TessEvaluation].get() != nullptr;
1766*8975f5c5SAndroid Build Coastguard Worker         if (!isSeparable() && (hasTessControl != hasTessEvaluation))
1767*8975f5c5SAndroid Build Coastguard Worker         {
1768*8975f5c5SAndroid Build Coastguard Worker             mState.mInfoLog
1769*8975f5c5SAndroid Build Coastguard Worker                 << "Tessellation control and evaluation shaders must be specified together.";
1770*8975f5c5SAndroid Build Coastguard Worker             return false;
1771*8975f5c5SAndroid Build Coastguard Worker         }
1772*8975f5c5SAndroid Build Coastguard Worker 
1773*8975f5c5SAndroid Build Coastguard Worker         const SharedCompiledShaderState &geometryShader = shaders[ShaderType::Geometry];
1774*8975f5c5SAndroid Build Coastguard Worker         if (geometryShader)
1775*8975f5c5SAndroid Build Coastguard Worker         {
1776*8975f5c5SAndroid Build Coastguard Worker             // [GL_EXT_geometry_shader] Chapter 7
1777*8975f5c5SAndroid Build Coastguard Worker             // Linking can fail for a variety of reasons as specified in the OpenGL ES Shading
1778*8975f5c5SAndroid Build Coastguard Worker             // Language Specification, as well as any of the following reasons:
1779*8975f5c5SAndroid Build Coastguard Worker             // * One or more of the shader objects attached to <program> are not compiled
1780*8975f5c5SAndroid Build Coastguard Worker             //   successfully.
1781*8975f5c5SAndroid Build Coastguard Worker             // * The shaders do not use the same shader language version.
1782*8975f5c5SAndroid Build Coastguard Worker             // * <program> contains objects to form a geometry shader, and
1783*8975f5c5SAndroid Build Coastguard Worker             //   - <program> is not separable and contains no objects to form a vertex shader; or
1784*8975f5c5SAndroid Build Coastguard Worker             //   - the input primitive type, output primitive type, or maximum output vertex count
1785*8975f5c5SAndroid Build Coastguard Worker             //     is not specified in the compiled geometry shader object.
1786*8975f5c5SAndroid Build Coastguard Worker             if (!geometryShader->hasValidGeometryShaderInputPrimitiveType())
1787*8975f5c5SAndroid Build Coastguard Worker             {
1788*8975f5c5SAndroid Build Coastguard Worker                 mState.mInfoLog << "Input primitive type is not specified in the geometry shader.";
1789*8975f5c5SAndroid Build Coastguard Worker                 return false;
1790*8975f5c5SAndroid Build Coastguard Worker             }
1791*8975f5c5SAndroid Build Coastguard Worker 
1792*8975f5c5SAndroid Build Coastguard Worker             if (!geometryShader->hasValidGeometryShaderOutputPrimitiveType())
1793*8975f5c5SAndroid Build Coastguard Worker             {
1794*8975f5c5SAndroid Build Coastguard Worker                 mState.mInfoLog << "Output primitive type is not specified in the geometry shader.";
1795*8975f5c5SAndroid Build Coastguard Worker                 return false;
1796*8975f5c5SAndroid Build Coastguard Worker             }
1797*8975f5c5SAndroid Build Coastguard Worker 
1798*8975f5c5SAndroid Build Coastguard Worker             if (!geometryShader->hasValidGeometryShaderMaxVertices())
1799*8975f5c5SAndroid Build Coastguard Worker             {
1800*8975f5c5SAndroid Build Coastguard Worker                 mState.mInfoLog << "'max_vertices' is not specified in the geometry shader.";
1801*8975f5c5SAndroid Build Coastguard Worker                 return false;
1802*8975f5c5SAndroid Build Coastguard Worker             }
1803*8975f5c5SAndroid Build Coastguard Worker         }
1804*8975f5c5SAndroid Build Coastguard Worker 
1805*8975f5c5SAndroid Build Coastguard Worker         const SharedCompiledShaderState &tessControlShader = shaders[ShaderType::TessControl];
1806*8975f5c5SAndroid Build Coastguard Worker         if (tessControlShader)
1807*8975f5c5SAndroid Build Coastguard Worker         {
1808*8975f5c5SAndroid Build Coastguard Worker             int tcsShaderVertices = tessControlShader->tessControlShaderVertices;
1809*8975f5c5SAndroid Build Coastguard Worker             if (tcsShaderVertices == 0)
1810*8975f5c5SAndroid Build Coastguard Worker             {
1811*8975f5c5SAndroid Build Coastguard Worker                 // In tessellation control shader, output vertices should be specified at least
1812*8975f5c5SAndroid Build Coastguard Worker                 // once.
1813*8975f5c5SAndroid Build Coastguard Worker                 // > GLSL ES Version 3.20.6 spec:
1814*8975f5c5SAndroid Build Coastguard Worker                 // > 4.4.2. Output Layout Qualifiers
1815*8975f5c5SAndroid Build Coastguard Worker                 // > Tessellation Control Outputs
1816*8975f5c5SAndroid Build Coastguard Worker                 // > ...
1817*8975f5c5SAndroid Build Coastguard Worker                 // > There must be at least one layout qualifier specifying an output patch vertex
1818*8975f5c5SAndroid Build Coastguard Worker                 // > count in any program containing a tessellation control shader.
1819*8975f5c5SAndroid Build Coastguard Worker                 mState.mInfoLog << "In Tessellation Control Shader, at least one layout qualifier "
1820*8975f5c5SAndroid Build Coastguard Worker                                    "specifying an output patch vertex count must exist.";
1821*8975f5c5SAndroid Build Coastguard Worker                 return false;
1822*8975f5c5SAndroid Build Coastguard Worker             }
1823*8975f5c5SAndroid Build Coastguard Worker         }
1824*8975f5c5SAndroid Build Coastguard Worker 
1825*8975f5c5SAndroid Build Coastguard Worker         const SharedCompiledShaderState &tessEvaluationShader = shaders[ShaderType::TessEvaluation];
1826*8975f5c5SAndroid Build Coastguard Worker         if (tessEvaluationShader)
1827*8975f5c5SAndroid Build Coastguard Worker         {
1828*8975f5c5SAndroid Build Coastguard Worker             GLenum tesPrimitiveMode = tessEvaluationShader->tessGenMode;
1829*8975f5c5SAndroid Build Coastguard Worker             if (tesPrimitiveMode == 0)
1830*8975f5c5SAndroid Build Coastguard Worker             {
1831*8975f5c5SAndroid Build Coastguard Worker                 // In tessellation evaluation shader, a primitive mode should be specified at least
1832*8975f5c5SAndroid Build Coastguard Worker                 // once.
1833*8975f5c5SAndroid Build Coastguard Worker                 // > GLSL ES Version 3.20.6 spec:
1834*8975f5c5SAndroid Build Coastguard Worker                 // > 4.4.1. Input Layout Qualifiers
1835*8975f5c5SAndroid Build Coastguard Worker                 // > Tessellation Evaluation Inputs
1836*8975f5c5SAndroid Build Coastguard Worker                 // > ...
1837*8975f5c5SAndroid Build Coastguard Worker                 // > The tessellation evaluation shader object in a program must declare a primitive
1838*8975f5c5SAndroid Build Coastguard Worker                 // > mode in its input layout. Declaring vertex spacing, ordering, or point mode
1839*8975f5c5SAndroid Build Coastguard Worker                 // > identifiers is optional.
1840*8975f5c5SAndroid Build Coastguard Worker                 mState.mInfoLog
1841*8975f5c5SAndroid Build Coastguard Worker                     << "The Tessellation Evaluation Shader object in a program must declare a "
1842*8975f5c5SAndroid Build Coastguard Worker                        "primitive mode in its input layout.";
1843*8975f5c5SAndroid Build Coastguard Worker                 return false;
1844*8975f5c5SAndroid Build Coastguard Worker             }
1845*8975f5c5SAndroid Build Coastguard Worker         }
1846*8975f5c5SAndroid Build Coastguard Worker     }
1847*8975f5c5SAndroid Build Coastguard Worker 
1848*8975f5c5SAndroid Build Coastguard Worker     return true;
1849*8975f5c5SAndroid Build Coastguard Worker }
1850*8975f5c5SAndroid Build Coastguard Worker 
1851*8975f5c5SAndroid Build Coastguard Worker // Assumes linkValidateShaders() has validated the shaders and caches some values from the shaders.
linkShaders()1852*8975f5c5SAndroid Build Coastguard Worker void Program::linkShaders()
1853*8975f5c5SAndroid Build Coastguard Worker {
1854*8975f5c5SAndroid Build Coastguard Worker     const ShaderMap<SharedCompiledShaderState> &shaders = mState.mAttachedShaders;
1855*8975f5c5SAndroid Build Coastguard Worker 
1856*8975f5c5SAndroid Build Coastguard Worker     const bool isComputeShaderAttached = shaders[ShaderType::Compute].get() != nullptr;
1857*8975f5c5SAndroid Build Coastguard Worker 
1858*8975f5c5SAndroid Build Coastguard Worker     if (isComputeShaderAttached)
1859*8975f5c5SAndroid Build Coastguard Worker     {
1860*8975f5c5SAndroid Build Coastguard Worker         mState.mExecutable->mPod.computeShaderLocalSize = shaders[ShaderType::Compute]->localSize;
1861*8975f5c5SAndroid Build Coastguard Worker     }
1862*8975f5c5SAndroid Build Coastguard Worker     else
1863*8975f5c5SAndroid Build Coastguard Worker     {
1864*8975f5c5SAndroid Build Coastguard Worker         const SharedCompiledShaderState &geometryShader = shaders[ShaderType::Geometry];
1865*8975f5c5SAndroid Build Coastguard Worker         if (geometryShader)
1866*8975f5c5SAndroid Build Coastguard Worker         {
1867*8975f5c5SAndroid Build Coastguard Worker             mState.mExecutable->mPod.geometryShaderInputPrimitiveType =
1868*8975f5c5SAndroid Build Coastguard Worker                 geometryShader->geometryShaderInputPrimitiveType;
1869*8975f5c5SAndroid Build Coastguard Worker             mState.mExecutable->mPod.geometryShaderOutputPrimitiveType =
1870*8975f5c5SAndroid Build Coastguard Worker                 geometryShader->geometryShaderOutputPrimitiveType;
1871*8975f5c5SAndroid Build Coastguard Worker             mState.mExecutable->mPod.geometryShaderMaxVertices =
1872*8975f5c5SAndroid Build Coastguard Worker                 geometryShader->geometryShaderMaxVertices;
1873*8975f5c5SAndroid Build Coastguard Worker             mState.mExecutable->mPod.geometryShaderInvocations =
1874*8975f5c5SAndroid Build Coastguard Worker                 geometryShader->geometryShaderInvocations;
1875*8975f5c5SAndroid Build Coastguard Worker         }
1876*8975f5c5SAndroid Build Coastguard Worker 
1877*8975f5c5SAndroid Build Coastguard Worker         const SharedCompiledShaderState &tessControlShader = shaders[ShaderType::TessControl];
1878*8975f5c5SAndroid Build Coastguard Worker         if (tessControlShader)
1879*8975f5c5SAndroid Build Coastguard Worker         {
1880*8975f5c5SAndroid Build Coastguard Worker             int tcsShaderVertices = tessControlShader->tessControlShaderVertices;
1881*8975f5c5SAndroid Build Coastguard Worker             mState.mExecutable->mPod.tessControlShaderVertices = tcsShaderVertices;
1882*8975f5c5SAndroid Build Coastguard Worker         }
1883*8975f5c5SAndroid Build Coastguard Worker 
1884*8975f5c5SAndroid Build Coastguard Worker         const SharedCompiledShaderState &tessEvaluationShader = shaders[ShaderType::TessEvaluation];
1885*8975f5c5SAndroid Build Coastguard Worker         if (tessEvaluationShader)
1886*8975f5c5SAndroid Build Coastguard Worker         {
1887*8975f5c5SAndroid Build Coastguard Worker             GLenum tesPrimitiveMode = tessEvaluationShader->tessGenMode;
1888*8975f5c5SAndroid Build Coastguard Worker 
1889*8975f5c5SAndroid Build Coastguard Worker             mState.mExecutable->mPod.tessGenMode        = tesPrimitiveMode;
1890*8975f5c5SAndroid Build Coastguard Worker             mState.mExecutable->mPod.tessGenSpacing     = tessEvaluationShader->tessGenSpacing;
1891*8975f5c5SAndroid Build Coastguard Worker             mState.mExecutable->mPod.tessGenVertexOrder = tessEvaluationShader->tessGenVertexOrder;
1892*8975f5c5SAndroid Build Coastguard Worker             mState.mExecutable->mPod.tessGenPointMode   = tessEvaluationShader->tessGenPointMode;
1893*8975f5c5SAndroid Build Coastguard Worker         }
1894*8975f5c5SAndroid Build Coastguard Worker     }
1895*8975f5c5SAndroid Build Coastguard Worker }
1896*8975f5c5SAndroid Build Coastguard Worker 
linkVaryings()1897*8975f5c5SAndroid Build Coastguard Worker bool Program::linkVaryings()
1898*8975f5c5SAndroid Build Coastguard Worker {
1899*8975f5c5SAndroid Build Coastguard Worker     ShaderType previousShaderType = ShaderType::InvalidEnum;
1900*8975f5c5SAndroid Build Coastguard Worker     for (ShaderType shaderType : kAllGraphicsShaderTypes)
1901*8975f5c5SAndroid Build Coastguard Worker     {
1902*8975f5c5SAndroid Build Coastguard Worker         const SharedCompiledShaderState &currentShader = mState.mAttachedShaders[shaderType];
1903*8975f5c5SAndroid Build Coastguard Worker         if (!currentShader)
1904*8975f5c5SAndroid Build Coastguard Worker         {
1905*8975f5c5SAndroid Build Coastguard Worker             continue;
1906*8975f5c5SAndroid Build Coastguard Worker         }
1907*8975f5c5SAndroid Build Coastguard Worker 
1908*8975f5c5SAndroid Build Coastguard Worker         if (previousShaderType != ShaderType::InvalidEnum)
1909*8975f5c5SAndroid Build Coastguard Worker         {
1910*8975f5c5SAndroid Build Coastguard Worker             const SharedCompiledShaderState &previousShader =
1911*8975f5c5SAndroid Build Coastguard Worker                 mState.mAttachedShaders[previousShaderType];
1912*8975f5c5SAndroid Build Coastguard Worker             const std::vector<sh::ShaderVariable> &outputVaryings = previousShader->outputVaryings;
1913*8975f5c5SAndroid Build Coastguard Worker 
1914*8975f5c5SAndroid Build Coastguard Worker             if (!LinkValidateShaderInterfaceMatching(
1915*8975f5c5SAndroid Build Coastguard Worker                     outputVaryings, currentShader->inputVaryings, previousShaderType,
1916*8975f5c5SAndroid Build Coastguard Worker                     currentShader->shaderType, previousShader->shaderVersion,
1917*8975f5c5SAndroid Build Coastguard Worker                     currentShader->shaderVersion, isSeparable(), mState.mInfoLog))
1918*8975f5c5SAndroid Build Coastguard Worker             {
1919*8975f5c5SAndroid Build Coastguard Worker                 return false;
1920*8975f5c5SAndroid Build Coastguard Worker             }
1921*8975f5c5SAndroid Build Coastguard Worker         }
1922*8975f5c5SAndroid Build Coastguard Worker         previousShaderType = currentShader->shaderType;
1923*8975f5c5SAndroid Build Coastguard Worker     }
1924*8975f5c5SAndroid Build Coastguard Worker 
1925*8975f5c5SAndroid Build Coastguard Worker     // TODO: http://anglebug.com/42262233 and http://anglebug.com/42262234
1926*8975f5c5SAndroid Build Coastguard Worker     // Need to move logic of validating builtin varyings inside the for-loop above.
1927*8975f5c5SAndroid Build Coastguard Worker     // This is because the built-in symbols `gl_ClipDistance` and `gl_CullDistance`
1928*8975f5c5SAndroid Build Coastguard Worker     // can be redeclared in Geometry or Tessellation shaders as well.
1929*8975f5c5SAndroid Build Coastguard Worker     const SharedCompiledShaderState &vertexShader   = mState.mAttachedShaders[ShaderType::Vertex];
1930*8975f5c5SAndroid Build Coastguard Worker     const SharedCompiledShaderState &fragmentShader = mState.mAttachedShaders[ShaderType::Fragment];
1931*8975f5c5SAndroid Build Coastguard Worker     if (vertexShader && fragmentShader &&
1932*8975f5c5SAndroid Build Coastguard Worker         !LinkValidateBuiltInVaryings(vertexShader->outputVaryings, fragmentShader->inputVaryings,
1933*8975f5c5SAndroid Build Coastguard Worker                                      vertexShader->shaderType, fragmentShader->shaderType,
1934*8975f5c5SAndroid Build Coastguard Worker                                      vertexShader->shaderVersion, fragmentShader->shaderVersion,
1935*8975f5c5SAndroid Build Coastguard Worker                                      mState.mInfoLog))
1936*8975f5c5SAndroid Build Coastguard Worker     {
1937*8975f5c5SAndroid Build Coastguard Worker         return false;
1938*8975f5c5SAndroid Build Coastguard Worker     }
1939*8975f5c5SAndroid Build Coastguard Worker 
1940*8975f5c5SAndroid Build Coastguard Worker     return true;
1941*8975f5c5SAndroid Build Coastguard Worker }
1942*8975f5c5SAndroid Build Coastguard Worker 
linkUniforms(const Caps & caps,const Version & clientVersion,std::vector<UnusedUniform> * unusedUniformsOutOrNull,GLuint * combinedImageUniformsOut)1943*8975f5c5SAndroid Build Coastguard Worker bool Program::linkUniforms(const Caps &caps,
1944*8975f5c5SAndroid Build Coastguard Worker                            const Version &clientVersion,
1945*8975f5c5SAndroid Build Coastguard Worker                            std::vector<UnusedUniform> *unusedUniformsOutOrNull,
1946*8975f5c5SAndroid Build Coastguard Worker                            GLuint *combinedImageUniformsOut)
1947*8975f5c5SAndroid Build Coastguard Worker {
1948*8975f5c5SAndroid Build Coastguard Worker     // Initialize executable shader map.
1949*8975f5c5SAndroid Build Coastguard Worker     ShaderMap<std::vector<sh::ShaderVariable>> shaderUniforms;
1950*8975f5c5SAndroid Build Coastguard Worker     for (const SharedCompiledShaderState &shader : mState.mAttachedShaders)
1951*8975f5c5SAndroid Build Coastguard Worker     {
1952*8975f5c5SAndroid Build Coastguard Worker         if (shader)
1953*8975f5c5SAndroid Build Coastguard Worker         {
1954*8975f5c5SAndroid Build Coastguard Worker             shaderUniforms[shader->shaderType] = shader->uniforms;
1955*8975f5c5SAndroid Build Coastguard Worker         }
1956*8975f5c5SAndroid Build Coastguard Worker     }
1957*8975f5c5SAndroid Build Coastguard Worker 
1958*8975f5c5SAndroid Build Coastguard Worker     if (!mState.mExecutable->linkUniforms(caps, shaderUniforms, mState.mUniformLocationBindings,
1959*8975f5c5SAndroid Build Coastguard Worker                                           combinedImageUniformsOut, unusedUniformsOutOrNull))
1960*8975f5c5SAndroid Build Coastguard Worker     {
1961*8975f5c5SAndroid Build Coastguard Worker         return false;
1962*8975f5c5SAndroid Build Coastguard Worker     }
1963*8975f5c5SAndroid Build Coastguard Worker 
1964*8975f5c5SAndroid Build Coastguard Worker     if (clientVersion >= Version(3, 1))
1965*8975f5c5SAndroid Build Coastguard Worker     {
1966*8975f5c5SAndroid Build Coastguard Worker         GLint locationSize = static_cast<GLint>(mState.mExecutable->getUniformLocations().size());
1967*8975f5c5SAndroid Build Coastguard Worker 
1968*8975f5c5SAndroid Build Coastguard Worker         if (locationSize > caps.maxUniformLocations)
1969*8975f5c5SAndroid Build Coastguard Worker         {
1970*8975f5c5SAndroid Build Coastguard Worker             mState.mInfoLog << "Exceeded maximum uniform location size";
1971*8975f5c5SAndroid Build Coastguard Worker             return false;
1972*8975f5c5SAndroid Build Coastguard Worker         }
1973*8975f5c5SAndroid Build Coastguard Worker     }
1974*8975f5c5SAndroid Build Coastguard Worker 
1975*8975f5c5SAndroid Build Coastguard Worker     return true;
1976*8975f5c5SAndroid Build Coastguard Worker }
1977*8975f5c5SAndroid Build Coastguard Worker 
1978*8975f5c5SAndroid Build Coastguard Worker // Assigns locations to all attributes (except built-ins) from the bindings and program locations.
linkAttributes(const Caps & caps,const Limitations & limitations,bool webglCompatibility)1979*8975f5c5SAndroid Build Coastguard Worker bool Program::linkAttributes(const Caps &caps,
1980*8975f5c5SAndroid Build Coastguard Worker                              const Limitations &limitations,
1981*8975f5c5SAndroid Build Coastguard Worker                              bool webglCompatibility)
1982*8975f5c5SAndroid Build Coastguard Worker {
1983*8975f5c5SAndroid Build Coastguard Worker     int shaderVersion          = -1;
1984*8975f5c5SAndroid Build Coastguard Worker     unsigned int usedLocations = 0;
1985*8975f5c5SAndroid Build Coastguard Worker 
1986*8975f5c5SAndroid Build Coastguard Worker     const SharedCompiledShaderState &vertexShader = mState.getAttachedShader(ShaderType::Vertex);
1987*8975f5c5SAndroid Build Coastguard Worker 
1988*8975f5c5SAndroid Build Coastguard Worker     if (!vertexShader)
1989*8975f5c5SAndroid Build Coastguard Worker     {
1990*8975f5c5SAndroid Build Coastguard Worker         // No vertex shader, so no attributes, so nothing to do
1991*8975f5c5SAndroid Build Coastguard Worker         return true;
1992*8975f5c5SAndroid Build Coastguard Worker     }
1993*8975f5c5SAndroid Build Coastguard Worker 
1994*8975f5c5SAndroid Build Coastguard Worker     // In GLSL ES 3.00.6, aliasing checks should be done with all declared attributes -
1995*8975f5c5SAndroid Build Coastguard Worker     // see GLSL ES 3.00.6 section 12.46. Inactive attributes will be pruned after
1996*8975f5c5SAndroid Build Coastguard Worker     // aliasing checks.
1997*8975f5c5SAndroid Build Coastguard Worker     // In GLSL ES 1.00.17 we only do aliasing checks for active attributes.
1998*8975f5c5SAndroid Build Coastguard Worker     shaderVersion = vertexShader->shaderVersion;
1999*8975f5c5SAndroid Build Coastguard Worker     const std::vector<sh::ShaderVariable> &shaderAttributes =
2000*8975f5c5SAndroid Build Coastguard Worker         shaderVersion >= 300 ? vertexShader->allAttributes : vertexShader->activeAttributes;
2001*8975f5c5SAndroid Build Coastguard Worker 
2002*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mState.mExecutable->mProgramInputs.empty());
2003*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->mProgramInputs.reserve(shaderAttributes.size());
2004*8975f5c5SAndroid Build Coastguard Worker 
2005*8975f5c5SAndroid Build Coastguard Worker     GLuint maxAttribs = static_cast<GLuint>(caps.maxVertexAttributes);
2006*8975f5c5SAndroid Build Coastguard Worker     std::vector<ProgramInput *> usedAttribMap(maxAttribs, nullptr);
2007*8975f5c5SAndroid Build Coastguard Worker 
2008*8975f5c5SAndroid Build Coastguard Worker     for (const sh::ShaderVariable &shaderAttribute : shaderAttributes)
2009*8975f5c5SAndroid Build Coastguard Worker     {
2010*8975f5c5SAndroid Build Coastguard Worker         // GLSL ES 3.10 January 2016 section 4.3.4: Vertex shader inputs can't be arrays or
2011*8975f5c5SAndroid Build Coastguard Worker         // structures, so we don't need to worry about adjusting their names or generating entries
2012*8975f5c5SAndroid Build Coastguard Worker         // for each member/element (unlike uniforms for example).
2013*8975f5c5SAndroid Build Coastguard Worker         ASSERT(!shaderAttribute.isArray() && !shaderAttribute.isStruct());
2014*8975f5c5SAndroid Build Coastguard Worker 
2015*8975f5c5SAndroid Build Coastguard Worker         mState.mExecutable->mProgramInputs.emplace_back(shaderAttribute);
2016*8975f5c5SAndroid Build Coastguard Worker 
2017*8975f5c5SAndroid Build Coastguard Worker         // Assign locations to attributes that have a binding location and check for attribute
2018*8975f5c5SAndroid Build Coastguard Worker         // aliasing.
2019*8975f5c5SAndroid Build Coastguard Worker         ProgramInput &attribute = mState.mExecutable->mProgramInputs.back();
2020*8975f5c5SAndroid Build Coastguard Worker         int bindingLocation     = mState.mAttributeBindings.getBinding(attribute);
2021*8975f5c5SAndroid Build Coastguard Worker         if (attribute.getLocation() == -1 && bindingLocation != -1)
2022*8975f5c5SAndroid Build Coastguard Worker         {
2023*8975f5c5SAndroid Build Coastguard Worker             attribute.setLocation(bindingLocation);
2024*8975f5c5SAndroid Build Coastguard Worker         }
2025*8975f5c5SAndroid Build Coastguard Worker 
2026*8975f5c5SAndroid Build Coastguard Worker         if (attribute.getLocation() != -1)
2027*8975f5c5SAndroid Build Coastguard Worker         {
2028*8975f5c5SAndroid Build Coastguard Worker             // Location is set by glBindAttribLocation or by location layout qualifier
2029*8975f5c5SAndroid Build Coastguard Worker             const int regs = VariableRegisterCount(attribute.getType());
2030*8975f5c5SAndroid Build Coastguard Worker 
2031*8975f5c5SAndroid Build Coastguard Worker             if (static_cast<GLuint>(regs + attribute.getLocation()) > maxAttribs)
2032*8975f5c5SAndroid Build Coastguard Worker             {
2033*8975f5c5SAndroid Build Coastguard Worker                 mState.mInfoLog << "Attribute (" << attribute.name << ") at location "
2034*8975f5c5SAndroid Build Coastguard Worker                                 << attribute.getLocation() << " is too big to fit";
2035*8975f5c5SAndroid Build Coastguard Worker 
2036*8975f5c5SAndroid Build Coastguard Worker                 return false;
2037*8975f5c5SAndroid Build Coastguard Worker             }
2038*8975f5c5SAndroid Build Coastguard Worker 
2039*8975f5c5SAndroid Build Coastguard Worker             for (int reg = 0; reg < regs; reg++)
2040*8975f5c5SAndroid Build Coastguard Worker             {
2041*8975f5c5SAndroid Build Coastguard Worker                 const int regLocation         = attribute.getLocation() + reg;
2042*8975f5c5SAndroid Build Coastguard Worker                 ProgramInput *linkedAttribute = usedAttribMap[regLocation];
2043*8975f5c5SAndroid Build Coastguard Worker 
2044*8975f5c5SAndroid Build Coastguard Worker                 // In GLSL ES 3.00.6 and in WebGL, attribute aliasing produces a link error.
2045*8975f5c5SAndroid Build Coastguard Worker                 // In non-WebGL GLSL ES 1.00.17, attribute aliasing is allowed with some
2046*8975f5c5SAndroid Build Coastguard Worker                 // restrictions - see GLSL ES 1.00.17 section 2.10.4, but ANGLE currently has a bug.
2047*8975f5c5SAndroid Build Coastguard Worker                 // In D3D 9 and 11, aliasing is not supported, so check a limitation.
2048*8975f5c5SAndroid Build Coastguard Worker                 if (linkedAttribute)
2049*8975f5c5SAndroid Build Coastguard Worker                 {
2050*8975f5c5SAndroid Build Coastguard Worker                     if (shaderVersion >= 300 || webglCompatibility ||
2051*8975f5c5SAndroid Build Coastguard Worker                         limitations.noVertexAttributeAliasing)
2052*8975f5c5SAndroid Build Coastguard Worker                     {
2053*8975f5c5SAndroid Build Coastguard Worker                         mState.mInfoLog << "Attribute '" << attribute.name
2054*8975f5c5SAndroid Build Coastguard Worker                                         << "' aliases attribute '" << linkedAttribute->name
2055*8975f5c5SAndroid Build Coastguard Worker                                         << "' at location " << regLocation;
2056*8975f5c5SAndroid Build Coastguard Worker                         return false;
2057*8975f5c5SAndroid Build Coastguard Worker                     }
2058*8975f5c5SAndroid Build Coastguard Worker                 }
2059*8975f5c5SAndroid Build Coastguard Worker                 else
2060*8975f5c5SAndroid Build Coastguard Worker                 {
2061*8975f5c5SAndroid Build Coastguard Worker                     usedAttribMap[regLocation] = &attribute;
2062*8975f5c5SAndroid Build Coastguard Worker                 }
2063*8975f5c5SAndroid Build Coastguard Worker 
2064*8975f5c5SAndroid Build Coastguard Worker                 usedLocations |= 1 << regLocation;
2065*8975f5c5SAndroid Build Coastguard Worker             }
2066*8975f5c5SAndroid Build Coastguard Worker         }
2067*8975f5c5SAndroid Build Coastguard Worker     }
2068*8975f5c5SAndroid Build Coastguard Worker 
2069*8975f5c5SAndroid Build Coastguard Worker     // Assign locations to attributes that don't have a binding location.
2070*8975f5c5SAndroid Build Coastguard Worker     for (ProgramInput &attribute : mState.mExecutable->mProgramInputs)
2071*8975f5c5SAndroid Build Coastguard Worker     {
2072*8975f5c5SAndroid Build Coastguard Worker         // Not set by glBindAttribLocation or by location layout qualifier
2073*8975f5c5SAndroid Build Coastguard Worker         if (attribute.getLocation() == -1)
2074*8975f5c5SAndroid Build Coastguard Worker         {
2075*8975f5c5SAndroid Build Coastguard Worker             int regs           = VariableRegisterCount(attribute.getType());
2076*8975f5c5SAndroid Build Coastguard Worker             int availableIndex = AllocateFirstFreeBits(&usedLocations, regs, maxAttribs);
2077*8975f5c5SAndroid Build Coastguard Worker 
2078*8975f5c5SAndroid Build Coastguard Worker             if (availableIndex == -1 || static_cast<GLuint>(availableIndex + regs) > maxAttribs)
2079*8975f5c5SAndroid Build Coastguard Worker             {
2080*8975f5c5SAndroid Build Coastguard Worker                 mState.mInfoLog << "Too many attributes (" << attribute.name << ")";
2081*8975f5c5SAndroid Build Coastguard Worker                 return false;
2082*8975f5c5SAndroid Build Coastguard Worker             }
2083*8975f5c5SAndroid Build Coastguard Worker 
2084*8975f5c5SAndroid Build Coastguard Worker             attribute.setLocation(availableIndex);
2085*8975f5c5SAndroid Build Coastguard Worker         }
2086*8975f5c5SAndroid Build Coastguard Worker     }
2087*8975f5c5SAndroid Build Coastguard Worker 
2088*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mState.mExecutable->mPod.attributesTypeMask.none());
2089*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mState.mExecutable->mPod.attributesMask.none());
2090*8975f5c5SAndroid Build Coastguard Worker 
2091*8975f5c5SAndroid Build Coastguard Worker     // Prune inactive attributes. This step is only needed on shaderVersion >= 300 since on earlier
2092*8975f5c5SAndroid Build Coastguard Worker     // shader versions we're only processing active attributes to begin with.
2093*8975f5c5SAndroid Build Coastguard Worker     if (shaderVersion >= 300)
2094*8975f5c5SAndroid Build Coastguard Worker     {
2095*8975f5c5SAndroid Build Coastguard Worker         for (auto attributeIter = mState.mExecutable->getProgramInputs().begin();
2096*8975f5c5SAndroid Build Coastguard Worker              attributeIter != mState.mExecutable->getProgramInputs().end();)
2097*8975f5c5SAndroid Build Coastguard Worker         {
2098*8975f5c5SAndroid Build Coastguard Worker             if (attributeIter->isActive())
2099*8975f5c5SAndroid Build Coastguard Worker             {
2100*8975f5c5SAndroid Build Coastguard Worker                 ++attributeIter;
2101*8975f5c5SAndroid Build Coastguard Worker             }
2102*8975f5c5SAndroid Build Coastguard Worker             else
2103*8975f5c5SAndroid Build Coastguard Worker             {
2104*8975f5c5SAndroid Build Coastguard Worker                 attributeIter = mState.mExecutable->mProgramInputs.erase(attributeIter);
2105*8975f5c5SAndroid Build Coastguard Worker             }
2106*8975f5c5SAndroid Build Coastguard Worker         }
2107*8975f5c5SAndroid Build Coastguard Worker     }
2108*8975f5c5SAndroid Build Coastguard Worker 
2109*8975f5c5SAndroid Build Coastguard Worker     for (const ProgramInput &attribute : mState.mExecutable->getProgramInputs())
2110*8975f5c5SAndroid Build Coastguard Worker     {
2111*8975f5c5SAndroid Build Coastguard Worker         ASSERT(attribute.isActive());
2112*8975f5c5SAndroid Build Coastguard Worker         ASSERT(attribute.getLocation() != -1);
2113*8975f5c5SAndroid Build Coastguard Worker         unsigned int regs = static_cast<unsigned int>(VariableRegisterCount(attribute.getType()));
2114*8975f5c5SAndroid Build Coastguard Worker 
2115*8975f5c5SAndroid Build Coastguard Worker         unsigned int location = static_cast<unsigned int>(attribute.getLocation());
2116*8975f5c5SAndroid Build Coastguard Worker         for (unsigned int r = 0; r < regs; r++)
2117*8975f5c5SAndroid Build Coastguard Worker         {
2118*8975f5c5SAndroid Build Coastguard Worker             // Built-in active program inputs don't have a bound attribute.
2119*8975f5c5SAndroid Build Coastguard Worker             if (!attribute.isBuiltIn())
2120*8975f5c5SAndroid Build Coastguard Worker             {
2121*8975f5c5SAndroid Build Coastguard Worker                 mState.mExecutable->mPod.activeAttribLocationsMask.set(location);
2122*8975f5c5SAndroid Build Coastguard Worker                 mState.mExecutable->mPod.maxActiveAttribLocation =
2123*8975f5c5SAndroid Build Coastguard Worker                     std::max(mState.mExecutable->mPod.maxActiveAttribLocation, location + 1);
2124*8975f5c5SAndroid Build Coastguard Worker 
2125*8975f5c5SAndroid Build Coastguard Worker                 ComponentType componentType =
2126*8975f5c5SAndroid Build Coastguard Worker                     GLenumToComponentType(VariableComponentType(attribute.getType()));
2127*8975f5c5SAndroid Build Coastguard Worker 
2128*8975f5c5SAndroid Build Coastguard Worker                 SetComponentTypeMask(componentType, location,
2129*8975f5c5SAndroid Build Coastguard Worker                                      &mState.mExecutable->mPod.attributesTypeMask);
2130*8975f5c5SAndroid Build Coastguard Worker                 mState.mExecutable->mPod.attributesMask.set(location);
2131*8975f5c5SAndroid Build Coastguard Worker 
2132*8975f5c5SAndroid Build Coastguard Worker                 location++;
2133*8975f5c5SAndroid Build Coastguard Worker             }
2134*8975f5c5SAndroid Build Coastguard Worker         }
2135*8975f5c5SAndroid Build Coastguard Worker     }
2136*8975f5c5SAndroid Build Coastguard Worker 
2137*8975f5c5SAndroid Build Coastguard Worker     return true;
2138*8975f5c5SAndroid Build Coastguard Worker }
2139*8975f5c5SAndroid Build Coastguard Worker 
serialize(const Context * context)2140*8975f5c5SAndroid Build Coastguard Worker angle::Result Program::serialize(const Context *context)
2141*8975f5c5SAndroid Build Coastguard Worker {
2142*8975f5c5SAndroid Build Coastguard Worker     // In typical applications, the binary should already be empty here.  However, in unusual
2143*8975f5c5SAndroid Build Coastguard Worker     // situations this may not be true.  In particular, if the application doesn't set
2144*8975f5c5SAndroid Build Coastguard Worker     // GL_PROGRAM_BINARY_RETRIEVABLE_HINT, gets the program length but doesn't get the binary, the
2145*8975f5c5SAndroid Build Coastguard Worker     // cached binary remains until the program is destroyed or the program is bound (both causing
2146*8975f5c5SAndroid Build Coastguard Worker     // |waitForPostLinkTasks()| to cache the program in the blob cache).
2147*8975f5c5SAndroid Build Coastguard Worker     if (!mBinary.empty())
2148*8975f5c5SAndroid Build Coastguard Worker     {
2149*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
2150*8975f5c5SAndroid Build Coastguard Worker     }
2151*8975f5c5SAndroid Build Coastguard Worker 
2152*8975f5c5SAndroid Build Coastguard Worker     BinaryOutputStream stream;
2153*8975f5c5SAndroid Build Coastguard Worker 
2154*8975f5c5SAndroid Build Coastguard Worker     stream.writeBytes(
2155*8975f5c5SAndroid Build Coastguard Worker         reinterpret_cast<const unsigned char *>(angle::GetANGLEShaderProgramVersion()),
2156*8975f5c5SAndroid Build Coastguard Worker         angle::GetANGLEShaderProgramVersionHashSize());
2157*8975f5c5SAndroid Build Coastguard Worker 
2158*8975f5c5SAndroid Build Coastguard Worker     stream.writeBool(angle::Is64Bit());
2159*8975f5c5SAndroid Build Coastguard Worker 
2160*8975f5c5SAndroid Build Coastguard Worker     stream.writeInt(angle::GetANGLESHVersion());
2161*8975f5c5SAndroid Build Coastguard Worker 
2162*8975f5c5SAndroid Build Coastguard Worker     stream.writeString(context->getRendererString());
2163*8975f5c5SAndroid Build Coastguard Worker 
2164*8975f5c5SAndroid Build Coastguard Worker     // nullptr context is supported when computing binary length.
2165*8975f5c5SAndroid Build Coastguard Worker     if (context)
2166*8975f5c5SAndroid Build Coastguard Worker     {
2167*8975f5c5SAndroid Build Coastguard Worker         stream.writeInt(context->getClientVersion().major);
2168*8975f5c5SAndroid Build Coastguard Worker         stream.writeInt(context->getClientVersion().minor);
2169*8975f5c5SAndroid Build Coastguard Worker     }
2170*8975f5c5SAndroid Build Coastguard Worker     else
2171*8975f5c5SAndroid Build Coastguard Worker     {
2172*8975f5c5SAndroid Build Coastguard Worker         stream.writeInt(2);
2173*8975f5c5SAndroid Build Coastguard Worker         stream.writeInt(0);
2174*8975f5c5SAndroid Build Coastguard Worker     }
2175*8975f5c5SAndroid Build Coastguard Worker 
2176*8975f5c5SAndroid Build Coastguard Worker     // mSeparable must be before mExecutable->save(), since it uses the value.
2177*8975f5c5SAndroid Build Coastguard Worker     stream.writeBool(mState.mSeparable);
2178*8975f5c5SAndroid Build Coastguard Worker     stream.writeInt(mState.mTransformFeedbackBufferMode);
2179*8975f5c5SAndroid Build Coastguard Worker 
2180*8975f5c5SAndroid Build Coastguard Worker     stream.writeInt(mState.mTransformFeedbackVaryingNames.size());
2181*8975f5c5SAndroid Build Coastguard Worker     for (const std::string &name : mState.mTransformFeedbackVaryingNames)
2182*8975f5c5SAndroid Build Coastguard Worker     {
2183*8975f5c5SAndroid Build Coastguard Worker         stream.writeString(name);
2184*8975f5c5SAndroid Build Coastguard Worker     }
2185*8975f5c5SAndroid Build Coastguard Worker 
2186*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->save(&stream);
2187*8975f5c5SAndroid Build Coastguard Worker 
2188*8975f5c5SAndroid Build Coastguard Worker     // Warn the app layer if saving a binary with unsupported transform feedback.
2189*8975f5c5SAndroid Build Coastguard Worker     if (!mState.mExecutable->getLinkedTransformFeedbackVaryings().empty() &&
2190*8975f5c5SAndroid Build Coastguard Worker         context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled)
2191*8975f5c5SAndroid Build Coastguard Worker     {
2192*8975f5c5SAndroid Build Coastguard Worker         ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
2193*8975f5c5SAndroid Build Coastguard Worker                            "Saving program binary with transform feedback, which is not supported "
2194*8975f5c5SAndroid Build Coastguard Worker                            "on this driver.");
2195*8975f5c5SAndroid Build Coastguard Worker     }
2196*8975f5c5SAndroid Build Coastguard Worker 
2197*8975f5c5SAndroid Build Coastguard Worker     if (context->getShareGroup()->getFrameCaptureShared()->enabled())
2198*8975f5c5SAndroid Build Coastguard Worker     {
2199*8975f5c5SAndroid Build Coastguard Worker         // Serialize the source for each stage for re-use during capture
2200*8975f5c5SAndroid Build Coastguard Worker         for (ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
2201*8975f5c5SAndroid Build Coastguard Worker         {
2202*8975f5c5SAndroid Build Coastguard Worker             Shader *shader = getAttachedShader(shaderType);
2203*8975f5c5SAndroid Build Coastguard Worker             if (shader)
2204*8975f5c5SAndroid Build Coastguard Worker             {
2205*8975f5c5SAndroid Build Coastguard Worker                 stream.writeString(shader->getSourceString());
2206*8975f5c5SAndroid Build Coastguard Worker             }
2207*8975f5c5SAndroid Build Coastguard Worker             else
2208*8975f5c5SAndroid Build Coastguard Worker             {
2209*8975f5c5SAndroid Build Coastguard Worker                 // If we don't have an attached shader, which would occur if this program was
2210*8975f5c5SAndroid Build Coastguard Worker                 // created via glProgramBinary, pull from our cached copy
2211*8975f5c5SAndroid Build Coastguard Worker                 const angle::ProgramSources &cachedLinkedSources =
2212*8975f5c5SAndroid Build Coastguard Worker                     context->getShareGroup()->getFrameCaptureShared()->getProgramSources(id());
2213*8975f5c5SAndroid Build Coastguard Worker                 const std::string &cachedSourceString = cachedLinkedSources[shaderType];
2214*8975f5c5SAndroid Build Coastguard Worker                 ASSERT(!cachedSourceString.empty());
2215*8975f5c5SAndroid Build Coastguard Worker                 stream.writeString(cachedSourceString.c_str());
2216*8975f5c5SAndroid Build Coastguard Worker             }
2217*8975f5c5SAndroid Build Coastguard Worker         }
2218*8975f5c5SAndroid Build Coastguard Worker     }
2219*8975f5c5SAndroid Build Coastguard Worker 
2220*8975f5c5SAndroid Build Coastguard Worker     mProgram->save(context, &stream);
2221*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mState.mExecutable->mPostLinkSubTasks.empty());
2222*8975f5c5SAndroid Build Coastguard Worker 
2223*8975f5c5SAndroid Build Coastguard Worker     if (!mBinary.resize(stream.length()))
2224*8975f5c5SAndroid Build Coastguard Worker     {
2225*8975f5c5SAndroid Build Coastguard Worker         ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
2226*8975f5c5SAndroid Build Coastguard Worker                            "Failed to allocate enough memory to serialize a program. (%zu bytes)",
2227*8975f5c5SAndroid Build Coastguard Worker                            stream.length());
2228*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Stop;
2229*8975f5c5SAndroid Build Coastguard Worker     }
2230*8975f5c5SAndroid Build Coastguard Worker     memcpy(mBinary.data(), stream.data(), stream.length());
2231*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2232*8975f5c5SAndroid Build Coastguard Worker }
2233*8975f5c5SAndroid Build Coastguard Worker 
deserialize(const Context * context,BinaryInputStream & stream)2234*8975f5c5SAndroid Build Coastguard Worker bool Program::deserialize(const Context *context, BinaryInputStream &stream)
2235*8975f5c5SAndroid Build Coastguard Worker {
2236*8975f5c5SAndroid Build Coastguard Worker     std::vector<uint8_t> angleShaderProgramVersionString(
2237*8975f5c5SAndroid Build Coastguard Worker         angle::GetANGLEShaderProgramVersionHashSize(), 0);
2238*8975f5c5SAndroid Build Coastguard Worker     stream.readBytes(angleShaderProgramVersionString.data(),
2239*8975f5c5SAndroid Build Coastguard Worker                      angleShaderProgramVersionString.size());
2240*8975f5c5SAndroid Build Coastguard Worker     if (memcmp(angleShaderProgramVersionString.data(), angle::GetANGLEShaderProgramVersion(),
2241*8975f5c5SAndroid Build Coastguard Worker                angleShaderProgramVersionString.size()) != 0)
2242*8975f5c5SAndroid Build Coastguard Worker     {
2243*8975f5c5SAndroid Build Coastguard Worker         mState.mInfoLog << "Invalid program binary version.";
2244*8975f5c5SAndroid Build Coastguard Worker         return false;
2245*8975f5c5SAndroid Build Coastguard Worker     }
2246*8975f5c5SAndroid Build Coastguard Worker 
2247*8975f5c5SAndroid Build Coastguard Worker     bool binaryIs64Bit = stream.readBool();
2248*8975f5c5SAndroid Build Coastguard Worker     if (binaryIs64Bit != angle::Is64Bit())
2249*8975f5c5SAndroid Build Coastguard Worker     {
2250*8975f5c5SAndroid Build Coastguard Worker         mState.mInfoLog << "cannot load program binaries across CPU architectures.";
2251*8975f5c5SAndroid Build Coastguard Worker         return false;
2252*8975f5c5SAndroid Build Coastguard Worker     }
2253*8975f5c5SAndroid Build Coastguard Worker 
2254*8975f5c5SAndroid Build Coastguard Worker     int angleSHVersion = stream.readInt<int>();
2255*8975f5c5SAndroid Build Coastguard Worker     if (angleSHVersion != angle::GetANGLESHVersion())
2256*8975f5c5SAndroid Build Coastguard Worker     {
2257*8975f5c5SAndroid Build Coastguard Worker         mState.mInfoLog << "cannot load program binaries across different angle sh version.";
2258*8975f5c5SAndroid Build Coastguard Worker         return false;
2259*8975f5c5SAndroid Build Coastguard Worker     }
2260*8975f5c5SAndroid Build Coastguard Worker 
2261*8975f5c5SAndroid Build Coastguard Worker     std::string rendererString = stream.readString();
2262*8975f5c5SAndroid Build Coastguard Worker     if (rendererString != context->getRendererString())
2263*8975f5c5SAndroid Build Coastguard Worker     {
2264*8975f5c5SAndroid Build Coastguard Worker         mState.mInfoLog << "Cannot load program binary due to changed renderer string.";
2265*8975f5c5SAndroid Build Coastguard Worker         return false;
2266*8975f5c5SAndroid Build Coastguard Worker     }
2267*8975f5c5SAndroid Build Coastguard Worker 
2268*8975f5c5SAndroid Build Coastguard Worker     int majorVersion = stream.readInt<int>();
2269*8975f5c5SAndroid Build Coastguard Worker     int minorVersion = stream.readInt<int>();
2270*8975f5c5SAndroid Build Coastguard Worker     if (majorVersion != context->getClientMajorVersion() ||
2271*8975f5c5SAndroid Build Coastguard Worker         minorVersion != context->getClientMinorVersion())
2272*8975f5c5SAndroid Build Coastguard Worker     {
2273*8975f5c5SAndroid Build Coastguard Worker         mState.mInfoLog << "Cannot load program binaries across different ES context versions.";
2274*8975f5c5SAndroid Build Coastguard Worker         return false;
2275*8975f5c5SAndroid Build Coastguard Worker     }
2276*8975f5c5SAndroid Build Coastguard Worker 
2277*8975f5c5SAndroid Build Coastguard Worker     mState.mSeparable                   = stream.readBool();
2278*8975f5c5SAndroid Build Coastguard Worker     mState.mTransformFeedbackBufferMode = stream.readInt<GLenum>();
2279*8975f5c5SAndroid Build Coastguard Worker 
2280*8975f5c5SAndroid Build Coastguard Worker     mState.mTransformFeedbackVaryingNames.resize(stream.readInt<size_t>());
2281*8975f5c5SAndroid Build Coastguard Worker     for (std::string &name : mState.mTransformFeedbackVaryingNames)
2282*8975f5c5SAndroid Build Coastguard Worker     {
2283*8975f5c5SAndroid Build Coastguard Worker         name = stream.readString();
2284*8975f5c5SAndroid Build Coastguard Worker     }
2285*8975f5c5SAndroid Build Coastguard Worker 
2286*8975f5c5SAndroid Build Coastguard Worker     // mSeparable must be before mExecutable->load(), since it uses the value.  This state is
2287*8975f5c5SAndroid Build Coastguard Worker     // duplicated in the executable for convenience.
2288*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->mPod.isSeparable = mState.mSeparable;
2289*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->load(&stream);
2290*8975f5c5SAndroid Build Coastguard Worker 
2291*8975f5c5SAndroid Build Coastguard Worker     static_assert(static_cast<unsigned long>(ShaderType::EnumCount) <= sizeof(unsigned long) * 8,
2292*8975f5c5SAndroid Build Coastguard Worker                   "Too many shader types");
2293*8975f5c5SAndroid Build Coastguard Worker 
2294*8975f5c5SAndroid Build Coastguard Worker     // Reject programs that use transform feedback varyings if the hardware cannot support them.
2295*8975f5c5SAndroid Build Coastguard Worker     if (mState.mExecutable->getLinkedTransformFeedbackVaryings().size() > 0 &&
2296*8975f5c5SAndroid Build Coastguard Worker         context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled)
2297*8975f5c5SAndroid Build Coastguard Worker     {
2298*8975f5c5SAndroid Build Coastguard Worker         mState.mInfoLog << "Current driver does not support transform feedback in binary programs.";
2299*8975f5c5SAndroid Build Coastguard Worker         return false;
2300*8975f5c5SAndroid Build Coastguard Worker     }
2301*8975f5c5SAndroid Build Coastguard Worker 
2302*8975f5c5SAndroid Build Coastguard Worker     if (!mState.mAttachedShaders[ShaderType::Compute])
2303*8975f5c5SAndroid Build Coastguard Worker     {
2304*8975f5c5SAndroid Build Coastguard Worker         mState.mExecutable->updateTransformFeedbackStrides();
2305*8975f5c5SAndroid Build Coastguard Worker         mState.mExecutable->mTransformFeedbackVaryingNames = mState.mTransformFeedbackVaryingNames;
2306*8975f5c5SAndroid Build Coastguard Worker     }
2307*8975f5c5SAndroid Build Coastguard Worker 
2308*8975f5c5SAndroid Build Coastguard Worker     if (context->getShareGroup()->getFrameCaptureShared()->enabled())
2309*8975f5c5SAndroid Build Coastguard Worker     {
2310*8975f5c5SAndroid Build Coastguard Worker         // Extract the source for each stage from the program binary
2311*8975f5c5SAndroid Build Coastguard Worker         angle::ProgramSources sources;
2312*8975f5c5SAndroid Build Coastguard Worker 
2313*8975f5c5SAndroid Build Coastguard Worker         for (ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
2314*8975f5c5SAndroid Build Coastguard Worker         {
2315*8975f5c5SAndroid Build Coastguard Worker             std::string shaderSource = stream.readString();
2316*8975f5c5SAndroid Build Coastguard Worker             ASSERT(shaderSource.length() > 0);
2317*8975f5c5SAndroid Build Coastguard Worker             sources[shaderType] = std::move(shaderSource);
2318*8975f5c5SAndroid Build Coastguard Worker         }
2319*8975f5c5SAndroid Build Coastguard Worker 
2320*8975f5c5SAndroid Build Coastguard Worker         // Store it for use during mid-execution capture
2321*8975f5c5SAndroid Build Coastguard Worker         context->getShareGroup()->getFrameCaptureShared()->setProgramSources(id(),
2322*8975f5c5SAndroid Build Coastguard Worker                                                                              std::move(sources));
2323*8975f5c5SAndroid Build Coastguard Worker     }
2324*8975f5c5SAndroid Build Coastguard Worker 
2325*8975f5c5SAndroid Build Coastguard Worker     return true;
2326*8975f5c5SAndroid Build Coastguard Worker }
2327*8975f5c5SAndroid Build Coastguard Worker 
postResolveLink(const Context * context)2328*8975f5c5SAndroid Build Coastguard Worker void Program::postResolveLink(const Context *context)
2329*8975f5c5SAndroid Build Coastguard Worker {
2330*8975f5c5SAndroid Build Coastguard Worker     mState.updateActiveSamplers();
2331*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->mActiveImageShaderBits.fill({});
2332*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->updateActiveImages(getExecutable());
2333*8975f5c5SAndroid Build Coastguard Worker 
2334*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->initInterfaceBlockBindings();
2335*8975f5c5SAndroid Build Coastguard Worker     mState.mExecutable->setUniformValuesFromBindingQualifiers();
2336*8975f5c5SAndroid Build Coastguard Worker 
2337*8975f5c5SAndroid Build Coastguard Worker     if (context->getExtensions().multiDrawANGLE)
2338*8975f5c5SAndroid Build Coastguard Worker     {
2339*8975f5c5SAndroid Build Coastguard Worker         mState.mExecutable->mPod.drawIDLocation =
2340*8975f5c5SAndroid Build Coastguard Worker             mState.mExecutable->getUniformLocation("gl_DrawID").value;
2341*8975f5c5SAndroid Build Coastguard Worker     }
2342*8975f5c5SAndroid Build Coastguard Worker 
2343*8975f5c5SAndroid Build Coastguard Worker     if (context->getExtensions().baseVertexBaseInstanceShaderBuiltinANGLE)
2344*8975f5c5SAndroid Build Coastguard Worker     {
2345*8975f5c5SAndroid Build Coastguard Worker         mState.mExecutable->mPod.baseVertexLocation =
2346*8975f5c5SAndroid Build Coastguard Worker             mState.mExecutable->getUniformLocation("gl_BaseVertex").value;
2347*8975f5c5SAndroid Build Coastguard Worker         mState.mExecutable->mPod.baseInstanceLocation =
2348*8975f5c5SAndroid Build Coastguard Worker             mState.mExecutable->getUniformLocation("gl_BaseInstance").value;
2349*8975f5c5SAndroid Build Coastguard Worker     }
2350*8975f5c5SAndroid Build Coastguard Worker }
2351*8975f5c5SAndroid Build Coastguard Worker 
cacheProgramBinaryIfNotAlready(const Context * context)2352*8975f5c5SAndroid Build Coastguard Worker void Program::cacheProgramBinaryIfNotAlready(const Context *context)
2353*8975f5c5SAndroid Build Coastguard Worker {
2354*8975f5c5SAndroid Build Coastguard Worker     // If program caching is disabled, we already consider the binary cached.
2355*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!context->getFrontendFeatures().disableProgramCaching.enabled || mIsBinaryCached);
2356*8975f5c5SAndroid Build Coastguard Worker     if (!mLinked || mIsBinaryCached || mState.mBinaryRetrieveableHint)
2357*8975f5c5SAndroid Build Coastguard Worker     {
2358*8975f5c5SAndroid Build Coastguard Worker         // Program caching is disabled, the program is yet to be linked, it's already cached, or the
2359*8975f5c5SAndroid Build Coastguard Worker         // application has specified that it prefers to cache the program binary itself.
2360*8975f5c5SAndroid Build Coastguard Worker         return;
2361*8975f5c5SAndroid Build Coastguard Worker     }
2362*8975f5c5SAndroid Build Coastguard Worker 
2363*8975f5c5SAndroid Build Coastguard Worker     // No post-link tasks should be pending.
2364*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mState.mExecutable->mPostLinkSubTasks.empty());
2365*8975f5c5SAndroid Build Coastguard Worker 
2366*8975f5c5SAndroid Build Coastguard Worker     // Save to the program cache.
2367*8975f5c5SAndroid Build Coastguard Worker     std::lock_guard<angle::SimpleMutex> cacheLock(context->getProgramCacheMutex());
2368*8975f5c5SAndroid Build Coastguard Worker     MemoryProgramCache *cache = context->getMemoryProgramCache();
2369*8975f5c5SAndroid Build Coastguard Worker     // TODO: http://anglebug.com/42263141: Enable program caching for separable programs
2370*8975f5c5SAndroid Build Coastguard Worker     if (cache && !isSeparable() &&
2371*8975f5c5SAndroid Build Coastguard Worker         (mState.mExecutable->mLinkedTransformFeedbackVaryings.empty() ||
2372*8975f5c5SAndroid Build Coastguard Worker          !context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled))
2373*8975f5c5SAndroid Build Coastguard Worker     {
2374*8975f5c5SAndroid Build Coastguard Worker         if (cache->putProgram(mProgramHash, context, this) == angle::Result::Stop)
2375*8975f5c5SAndroid Build Coastguard Worker         {
2376*8975f5c5SAndroid Build Coastguard Worker             // Don't fail linking if putting the program binary into the cache fails, the program is
2377*8975f5c5SAndroid Build Coastguard Worker             // still usable.
2378*8975f5c5SAndroid Build Coastguard Worker             ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
2379*8975f5c5SAndroid Build Coastguard Worker                                "Failed to save linked program to memory program cache.");
2380*8975f5c5SAndroid Build Coastguard Worker         }
2381*8975f5c5SAndroid Build Coastguard Worker 
2382*8975f5c5SAndroid Build Coastguard Worker         // Drop the binary; the application didn't specify that it wants to retrieve the binary.  If
2383*8975f5c5SAndroid Build Coastguard Worker         // it did, we wouldn't be implicitly caching it.
2384*8975f5c5SAndroid Build Coastguard Worker         mBinary.clear();
2385*8975f5c5SAndroid Build Coastguard Worker     }
2386*8975f5c5SAndroid Build Coastguard Worker 
2387*8975f5c5SAndroid Build Coastguard Worker     mIsBinaryCached = true;
2388*8975f5c5SAndroid Build Coastguard Worker }
2389*8975f5c5SAndroid Build Coastguard Worker 
dumpProgramInfo(const Context * context) const2390*8975f5c5SAndroid Build Coastguard Worker void Program::dumpProgramInfo(const Context *context) const
2391*8975f5c5SAndroid Build Coastguard Worker {
2392*8975f5c5SAndroid Build Coastguard Worker     std::stringstream dumpStream;
2393*8975f5c5SAndroid Build Coastguard Worker     for (ShaderType shaderType : angle::AllEnums<ShaderType>())
2394*8975f5c5SAndroid Build Coastguard Worker     {
2395*8975f5c5SAndroid Build Coastguard Worker         Shader *shader = getAttachedShader(shaderType);
2396*8975f5c5SAndroid Build Coastguard Worker         if (shader)
2397*8975f5c5SAndroid Build Coastguard Worker         {
2398*8975f5c5SAndroid Build Coastguard Worker             dumpStream << shader->getType() << ": "
2399*8975f5c5SAndroid Build Coastguard Worker                        << GetShaderDumpFileName(shader->getSourceHash()) << std::endl;
2400*8975f5c5SAndroid Build Coastguard Worker         }
2401*8975f5c5SAndroid Build Coastguard Worker     }
2402*8975f5c5SAndroid Build Coastguard Worker 
2403*8975f5c5SAndroid Build Coastguard Worker     std::string dump = dumpStream.str();
2404*8975f5c5SAndroid Build Coastguard Worker     size_t dumpHash  = std::hash<std::string>{}(dump);
2405*8975f5c5SAndroid Build Coastguard Worker 
2406*8975f5c5SAndroid Build Coastguard Worker     std::stringstream pathStream;
2407*8975f5c5SAndroid Build Coastguard Worker     std::string shaderDumpDir = GetShaderDumpFileDirectory();
2408*8975f5c5SAndroid Build Coastguard Worker     if (!shaderDumpDir.empty())
2409*8975f5c5SAndroid Build Coastguard Worker     {
2410*8975f5c5SAndroid Build Coastguard Worker         pathStream << shaderDumpDir << "/";
2411*8975f5c5SAndroid Build Coastguard Worker     }
2412*8975f5c5SAndroid Build Coastguard Worker     pathStream << dumpHash << ".program";
2413*8975f5c5SAndroid Build Coastguard Worker     std::string path = pathStream.str();
2414*8975f5c5SAndroid Build Coastguard Worker 
2415*8975f5c5SAndroid Build Coastguard Worker     writeFile(path.c_str(), dump.c_str(), dump.length());
2416*8975f5c5SAndroid Build Coastguard Worker     INFO() << "Dumped program: " << path;
2417*8975f5c5SAndroid Build Coastguard Worker }
2418*8975f5c5SAndroid Build Coastguard Worker }  // namespace gl
2419