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 ¤tShader = 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