xref: /aosp_15_r20/external/angle/src/libANGLE/ProgramExecutable.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2020 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 // ProgramExecutable.cpp: Collects the interfaces common to both Programs and
7*8975f5c5SAndroid Build Coastguard Worker // ProgramPipelines in order to execute/draw with either.
8*8975f5c5SAndroid Build Coastguard Worker 
9*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/ProgramExecutable.h"
10*8975f5c5SAndroid Build Coastguard Worker 
11*8975f5c5SAndroid Build Coastguard Worker #include "common/string_utils.h"
12*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Context.h"
13*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Program.h"
14*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Shader.h"
15*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/queryconversions.h"
16*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/GLImplFactory.h"
17*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/ProgramExecutableImpl.h"
18*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/ProgramImpl.h"
19*8975f5c5SAndroid Build Coastguard Worker 
20*8975f5c5SAndroid Build Coastguard Worker namespace gl
21*8975f5c5SAndroid Build Coastguard Worker {
22*8975f5c5SAndroid Build Coastguard Worker namespace
23*8975f5c5SAndroid Build Coastguard Worker {
24*8975f5c5SAndroid Build Coastguard Worker ANGLE_ENABLE_STRUCT_PADDING_WARNINGS
25*8975f5c5SAndroid Build Coastguard Worker // A placeholder struct just to ensure sh::BlockMemberInfo is tightly packed since vulkan backend
26*8975f5c5SAndroid Build Coastguard Worker // uses it and memcpy the entire vector which requires it tightly packed to make msan happy.
27*8975f5c5SAndroid Build Coastguard Worker struct BlockMemberInfoPaddingTest
28*8975f5c5SAndroid Build Coastguard Worker {
29*8975f5c5SAndroid Build Coastguard Worker     sh::BlockMemberInfo blockMemberInfo;
30*8975f5c5SAndroid Build Coastguard Worker };
31*8975f5c5SAndroid Build Coastguard Worker ANGLE_DISABLE_STRUCT_PADDING_WARNINGS
32*8975f5c5SAndroid Build Coastguard Worker 
IncludeSameArrayElement(const std::set<std::string> & nameSet,const std::string & name)33*8975f5c5SAndroid Build Coastguard Worker bool IncludeSameArrayElement(const std::set<std::string> &nameSet, const std::string &name)
34*8975f5c5SAndroid Build Coastguard Worker {
35*8975f5c5SAndroid Build Coastguard Worker     std::vector<unsigned int> subscripts;
36*8975f5c5SAndroid Build Coastguard Worker     std::string baseName = ParseResourceName(name, &subscripts);
37*8975f5c5SAndroid Build Coastguard Worker     for (const std::string &nameInSet : nameSet)
38*8975f5c5SAndroid Build Coastguard Worker     {
39*8975f5c5SAndroid Build Coastguard Worker         std::vector<unsigned int> arrayIndices;
40*8975f5c5SAndroid Build Coastguard Worker         std::string arrayName = ParseResourceName(nameInSet, &arrayIndices);
41*8975f5c5SAndroid Build Coastguard Worker         if (baseName == arrayName &&
42*8975f5c5SAndroid Build Coastguard Worker             (subscripts.empty() || arrayIndices.empty() || subscripts == arrayIndices))
43*8975f5c5SAndroid Build Coastguard Worker         {
44*8975f5c5SAndroid Build Coastguard Worker             return true;
45*8975f5c5SAndroid Build Coastguard Worker         }
46*8975f5c5SAndroid Build Coastguard Worker     }
47*8975f5c5SAndroid Build Coastguard Worker     return false;
48*8975f5c5SAndroid Build Coastguard Worker }
49*8975f5c5SAndroid Build Coastguard Worker 
50*8975f5c5SAndroid Build Coastguard Worker // Find the matching varying or field by name.
FindOutputVaryingOrField(const ProgramMergedVaryings & varyings,ShaderType stage,const std::string & name)51*8975f5c5SAndroid Build Coastguard Worker const sh::ShaderVariable *FindOutputVaryingOrField(const ProgramMergedVaryings &varyings,
52*8975f5c5SAndroid Build Coastguard Worker                                                    ShaderType stage,
53*8975f5c5SAndroid Build Coastguard Worker                                                    const std::string &name)
54*8975f5c5SAndroid Build Coastguard Worker {
55*8975f5c5SAndroid Build Coastguard Worker     const sh::ShaderVariable *var = nullptr;
56*8975f5c5SAndroid Build Coastguard Worker     for (const ProgramVaryingRef &ref : varyings)
57*8975f5c5SAndroid Build Coastguard Worker     {
58*8975f5c5SAndroid Build Coastguard Worker         if (ref.frontShaderStage != stage)
59*8975f5c5SAndroid Build Coastguard Worker         {
60*8975f5c5SAndroid Build Coastguard Worker             continue;
61*8975f5c5SAndroid Build Coastguard Worker         }
62*8975f5c5SAndroid Build Coastguard Worker 
63*8975f5c5SAndroid Build Coastguard Worker         const sh::ShaderVariable *varying = ref.get(stage);
64*8975f5c5SAndroid Build Coastguard Worker         if (varying->name == name)
65*8975f5c5SAndroid Build Coastguard Worker         {
66*8975f5c5SAndroid Build Coastguard Worker             var = varying;
67*8975f5c5SAndroid Build Coastguard Worker             break;
68*8975f5c5SAndroid Build Coastguard Worker         }
69*8975f5c5SAndroid Build Coastguard Worker         GLuint fieldIndex = 0;
70*8975f5c5SAndroid Build Coastguard Worker         var               = varying->findField(name, &fieldIndex);
71*8975f5c5SAndroid Build Coastguard Worker         if (var != nullptr)
72*8975f5c5SAndroid Build Coastguard Worker         {
73*8975f5c5SAndroid Build Coastguard Worker             break;
74*8975f5c5SAndroid Build Coastguard Worker         }
75*8975f5c5SAndroid Build Coastguard Worker     }
76*8975f5c5SAndroid Build Coastguard Worker     return var;
77*8975f5c5SAndroid Build Coastguard Worker }
78*8975f5c5SAndroid Build Coastguard Worker 
FindUsedOutputLocation(std::vector<VariableLocation> & outputLocations,unsigned int baseLocation,unsigned int elementCount,const std::vector<VariableLocation> & reservedLocations,unsigned int variableIndex)79*8975f5c5SAndroid Build Coastguard Worker bool FindUsedOutputLocation(std::vector<VariableLocation> &outputLocations,
80*8975f5c5SAndroid Build Coastguard Worker                             unsigned int baseLocation,
81*8975f5c5SAndroid Build Coastguard Worker                             unsigned int elementCount,
82*8975f5c5SAndroid Build Coastguard Worker                             const std::vector<VariableLocation> &reservedLocations,
83*8975f5c5SAndroid Build Coastguard Worker                             unsigned int variableIndex)
84*8975f5c5SAndroid Build Coastguard Worker {
85*8975f5c5SAndroid Build Coastguard Worker     if (baseLocation + elementCount > outputLocations.size())
86*8975f5c5SAndroid Build Coastguard Worker     {
87*8975f5c5SAndroid Build Coastguard Worker         elementCount = baseLocation < outputLocations.size()
88*8975f5c5SAndroid Build Coastguard Worker                            ? static_cast<unsigned int>(outputLocations.size() - baseLocation)
89*8975f5c5SAndroid Build Coastguard Worker                            : 0;
90*8975f5c5SAndroid Build Coastguard Worker     }
91*8975f5c5SAndroid Build Coastguard Worker     for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
92*8975f5c5SAndroid Build Coastguard Worker     {
93*8975f5c5SAndroid Build Coastguard Worker         const unsigned int location = baseLocation + elementIndex;
94*8975f5c5SAndroid Build Coastguard Worker         if (outputLocations[location].used())
95*8975f5c5SAndroid Build Coastguard Worker         {
96*8975f5c5SAndroid Build Coastguard Worker             VariableLocation locationInfo(elementIndex, variableIndex);
97*8975f5c5SAndroid Build Coastguard Worker             if (std::find(reservedLocations.begin(), reservedLocations.end(), locationInfo) ==
98*8975f5c5SAndroid Build Coastguard Worker                 reservedLocations.end())
99*8975f5c5SAndroid Build Coastguard Worker             {
100*8975f5c5SAndroid Build Coastguard Worker                 return true;
101*8975f5c5SAndroid Build Coastguard Worker             }
102*8975f5c5SAndroid Build Coastguard Worker         }
103*8975f5c5SAndroid Build Coastguard Worker     }
104*8975f5c5SAndroid Build Coastguard Worker     return false;
105*8975f5c5SAndroid Build Coastguard Worker }
106*8975f5c5SAndroid Build Coastguard Worker 
AssignOutputLocations(std::vector<VariableLocation> & outputLocations,unsigned int baseLocation,unsigned int elementCount,const std::vector<VariableLocation> & reservedLocations,unsigned int variableIndex,bool locationAssignedByApi,ProgramOutput & outputVariable)107*8975f5c5SAndroid Build Coastguard Worker void AssignOutputLocations(std::vector<VariableLocation> &outputLocations,
108*8975f5c5SAndroid Build Coastguard Worker                            unsigned int baseLocation,
109*8975f5c5SAndroid Build Coastguard Worker                            unsigned int elementCount,
110*8975f5c5SAndroid Build Coastguard Worker                            const std::vector<VariableLocation> &reservedLocations,
111*8975f5c5SAndroid Build Coastguard Worker                            unsigned int variableIndex,
112*8975f5c5SAndroid Build Coastguard Worker                            bool locationAssignedByApi,
113*8975f5c5SAndroid Build Coastguard Worker                            ProgramOutput &outputVariable)
114*8975f5c5SAndroid Build Coastguard Worker {
115*8975f5c5SAndroid Build Coastguard Worker     if (baseLocation + elementCount > outputLocations.size())
116*8975f5c5SAndroid Build Coastguard Worker     {
117*8975f5c5SAndroid Build Coastguard Worker         outputLocations.resize(baseLocation + elementCount);
118*8975f5c5SAndroid Build Coastguard Worker     }
119*8975f5c5SAndroid Build Coastguard Worker     for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
120*8975f5c5SAndroid Build Coastguard Worker     {
121*8975f5c5SAndroid Build Coastguard Worker         VariableLocation locationInfo(elementIndex, variableIndex);
122*8975f5c5SAndroid Build Coastguard Worker         if (std::find(reservedLocations.begin(), reservedLocations.end(), locationInfo) ==
123*8975f5c5SAndroid Build Coastguard Worker             reservedLocations.end())
124*8975f5c5SAndroid Build Coastguard Worker         {
125*8975f5c5SAndroid Build Coastguard Worker             outputVariable.pod.location = baseLocation;
126*8975f5c5SAndroid Build Coastguard Worker             const unsigned int location = baseLocation + elementIndex;
127*8975f5c5SAndroid Build Coastguard Worker             outputLocations[location]   = locationInfo;
128*8975f5c5SAndroid Build Coastguard Worker         }
129*8975f5c5SAndroid Build Coastguard Worker     }
130*8975f5c5SAndroid Build Coastguard Worker     outputVariable.pod.hasApiAssignedLocation = locationAssignedByApi;
131*8975f5c5SAndroid Build Coastguard Worker }
132*8975f5c5SAndroid Build Coastguard Worker 
GetOutputLocationForLink(const ProgramAliasedBindings & fragmentOutputLocations,const ProgramOutput & outputVariable)133*8975f5c5SAndroid Build Coastguard Worker int GetOutputLocationForLink(const ProgramAliasedBindings &fragmentOutputLocations,
134*8975f5c5SAndroid Build Coastguard Worker                              const ProgramOutput &outputVariable)
135*8975f5c5SAndroid Build Coastguard Worker {
136*8975f5c5SAndroid Build Coastguard Worker     if (outputVariable.pod.location != -1)
137*8975f5c5SAndroid Build Coastguard Worker     {
138*8975f5c5SAndroid Build Coastguard Worker         return outputVariable.pod.location;
139*8975f5c5SAndroid Build Coastguard Worker     }
140*8975f5c5SAndroid Build Coastguard Worker     int apiLocation = fragmentOutputLocations.getBinding(outputVariable);
141*8975f5c5SAndroid Build Coastguard Worker     if (apiLocation != -1)
142*8975f5c5SAndroid Build Coastguard Worker     {
143*8975f5c5SAndroid Build Coastguard Worker         return apiLocation;
144*8975f5c5SAndroid Build Coastguard Worker     }
145*8975f5c5SAndroid Build Coastguard Worker     return -1;
146*8975f5c5SAndroid Build Coastguard Worker }
147*8975f5c5SAndroid Build Coastguard Worker 
AssignOutputIndex(const ProgramAliasedBindings & fragmentOutputIndexes,ProgramOutput & outputVariable)148*8975f5c5SAndroid Build Coastguard Worker void AssignOutputIndex(const ProgramAliasedBindings &fragmentOutputIndexes,
149*8975f5c5SAndroid Build Coastguard Worker                        ProgramOutput &outputVariable)
150*8975f5c5SAndroid Build Coastguard Worker {
151*8975f5c5SAndroid Build Coastguard Worker     if (outputVariable.pod.hasShaderAssignedLocation)
152*8975f5c5SAndroid Build Coastguard Worker     {
153*8975f5c5SAndroid Build Coastguard Worker         // Already assigned through a layout qualifier
154*8975f5c5SAndroid Build Coastguard Worker         ASSERT(outputVariable.pod.index == 0 || outputVariable.pod.index == 1);
155*8975f5c5SAndroid Build Coastguard Worker         return;
156*8975f5c5SAndroid Build Coastguard Worker     }
157*8975f5c5SAndroid Build Coastguard Worker 
158*8975f5c5SAndroid Build Coastguard Worker     int apiIndex = fragmentOutputIndexes.getBinding(outputVariable);
159*8975f5c5SAndroid Build Coastguard Worker     if (apiIndex != -1)
160*8975f5c5SAndroid Build Coastguard Worker     {
161*8975f5c5SAndroid Build Coastguard Worker         // Index layout qualifier from the shader takes precedence, so the index from the API is
162*8975f5c5SAndroid Build Coastguard Worker         // checked only if the index was not set in the shader. This is not specified in the EXT
163*8975f5c5SAndroid Build Coastguard Worker         // spec, but is specified in desktop OpenGL specs.
164*8975f5c5SAndroid Build Coastguard Worker         ASSERT(apiIndex == 0 || apiIndex == 1);
165*8975f5c5SAndroid Build Coastguard Worker         outputVariable.pod.index = apiIndex;
166*8975f5c5SAndroid Build Coastguard Worker         return;
167*8975f5c5SAndroid Build Coastguard Worker     }
168*8975f5c5SAndroid Build Coastguard Worker 
169*8975f5c5SAndroid Build Coastguard Worker     // EXT_blend_func_extended: Outputs get index 0 by default.
170*8975f5c5SAndroid Build Coastguard Worker     outputVariable.pod.index = 0;
171*8975f5c5SAndroid Build Coastguard Worker }
172*8975f5c5SAndroid Build Coastguard Worker 
AddUniforms(const ShaderMap<SharedProgramExecutable> & executables,ShaderBitSet activeShaders,std::vector<LinkedUniform> * outputUniforms,std::vector<std::string> * outputUniformNames,std::vector<std::string> * outputUniformMappedNames,const std::function<RangeUI (const ProgramExecutable &)> & getRange)173*8975f5c5SAndroid Build Coastguard Worker RangeUI AddUniforms(const ShaderMap<SharedProgramExecutable> &executables,
174*8975f5c5SAndroid Build Coastguard Worker                     ShaderBitSet activeShaders,
175*8975f5c5SAndroid Build Coastguard Worker                     std::vector<LinkedUniform> *outputUniforms,
176*8975f5c5SAndroid Build Coastguard Worker                     std::vector<std::string> *outputUniformNames,
177*8975f5c5SAndroid Build Coastguard Worker                     std::vector<std::string> *outputUniformMappedNames,
178*8975f5c5SAndroid Build Coastguard Worker                     const std::function<RangeUI(const ProgramExecutable &)> &getRange)
179*8975f5c5SAndroid Build Coastguard Worker {
180*8975f5c5SAndroid Build Coastguard Worker     unsigned int startRange = static_cast<unsigned int>(outputUniforms->size());
181*8975f5c5SAndroid Build Coastguard Worker     for (ShaderType shaderType : activeShaders)
182*8975f5c5SAndroid Build Coastguard Worker     {
183*8975f5c5SAndroid Build Coastguard Worker         const ProgramExecutable &executable = *executables[shaderType];
184*8975f5c5SAndroid Build Coastguard Worker         const RangeUI uniformRange          = getRange(executable);
185*8975f5c5SAndroid Build Coastguard Worker 
186*8975f5c5SAndroid Build Coastguard Worker         const std::vector<LinkedUniform> &programUniforms = executable.getUniforms();
187*8975f5c5SAndroid Build Coastguard Worker         outputUniforms->insert(outputUniforms->end(), programUniforms.begin() + uniformRange.low(),
188*8975f5c5SAndroid Build Coastguard Worker                                programUniforms.begin() + uniformRange.high());
189*8975f5c5SAndroid Build Coastguard Worker 
190*8975f5c5SAndroid Build Coastguard Worker         const std::vector<std::string> &uniformNames = executable.getUniformNames();
191*8975f5c5SAndroid Build Coastguard Worker         outputUniformNames->insert(outputUniformNames->end(),
192*8975f5c5SAndroid Build Coastguard Worker                                    uniformNames.begin() + uniformRange.low(),
193*8975f5c5SAndroid Build Coastguard Worker                                    uniformNames.begin() + uniformRange.high());
194*8975f5c5SAndroid Build Coastguard Worker 
195*8975f5c5SAndroid Build Coastguard Worker         const std::vector<std::string> &uniformMappedNames = executable.getUniformMappedNames();
196*8975f5c5SAndroid Build Coastguard Worker         outputUniformMappedNames->insert(outputUniformMappedNames->end(),
197*8975f5c5SAndroid Build Coastguard Worker                                          uniformMappedNames.begin() + uniformRange.low(),
198*8975f5c5SAndroid Build Coastguard Worker                                          uniformMappedNames.begin() + uniformRange.high());
199*8975f5c5SAndroid Build Coastguard Worker     }
200*8975f5c5SAndroid Build Coastguard Worker     return RangeUI(startRange, static_cast<unsigned int>(outputUniforms->size()));
201*8975f5c5SAndroid Build Coastguard Worker }
202*8975f5c5SAndroid Build Coastguard Worker 
203*8975f5c5SAndroid Build Coastguard Worker template <typename BlockT>
AppendActiveBlocks(ShaderType shaderType,const std::vector<BlockT> & blocksIn,std::vector<BlockT> & blocksOut,ProgramUniformBlockArray<GLuint> * ppoBlockMap)204*8975f5c5SAndroid Build Coastguard Worker void AppendActiveBlocks(ShaderType shaderType,
205*8975f5c5SAndroid Build Coastguard Worker                         const std::vector<BlockT> &blocksIn,
206*8975f5c5SAndroid Build Coastguard Worker                         std::vector<BlockT> &blocksOut,
207*8975f5c5SAndroid Build Coastguard Worker                         ProgramUniformBlockArray<GLuint> *ppoBlockMap)
208*8975f5c5SAndroid Build Coastguard Worker {
209*8975f5c5SAndroid Build Coastguard Worker     for (size_t index = 0; index < blocksIn.size(); ++index)
210*8975f5c5SAndroid Build Coastguard Worker     {
211*8975f5c5SAndroid Build Coastguard Worker         const BlockT &block = blocksIn[index];
212*8975f5c5SAndroid Build Coastguard Worker         if (block.isActive(shaderType))
213*8975f5c5SAndroid Build Coastguard Worker         {
214*8975f5c5SAndroid Build Coastguard Worker             // Have a way for the PPO to know how to map the program's UBO index into its own UBO
215*8975f5c5SAndroid Build Coastguard Worker             // array.  This is used to propagate changes to the program's UBOs to the PPO's UBO
216*8975f5c5SAndroid Build Coastguard Worker             // list.
217*8975f5c5SAndroid Build Coastguard Worker             if (ppoBlockMap != nullptr)
218*8975f5c5SAndroid Build Coastguard Worker             {
219*8975f5c5SAndroid Build Coastguard Worker                 (*ppoBlockMap)[static_cast<uint32_t>(index)] =
220*8975f5c5SAndroid Build Coastguard Worker                     static_cast<uint32_t>(blocksOut.size());
221*8975f5c5SAndroid Build Coastguard Worker             }
222*8975f5c5SAndroid Build Coastguard Worker 
223*8975f5c5SAndroid Build Coastguard Worker             blocksOut.push_back(block);
224*8975f5c5SAndroid Build Coastguard Worker         }
225*8975f5c5SAndroid Build Coastguard Worker     }
226*8975f5c5SAndroid Build Coastguard Worker }
227*8975f5c5SAndroid Build Coastguard Worker 
SaveProgramInputs(BinaryOutputStream * stream,const std::vector<ProgramInput> & programInputs)228*8975f5c5SAndroid Build Coastguard Worker void SaveProgramInputs(BinaryOutputStream *stream, const std::vector<ProgramInput> &programInputs)
229*8975f5c5SAndroid Build Coastguard Worker {
230*8975f5c5SAndroid Build Coastguard Worker     stream->writeInt(programInputs.size());
231*8975f5c5SAndroid Build Coastguard Worker     for (const ProgramInput &attrib : programInputs)
232*8975f5c5SAndroid Build Coastguard Worker     {
233*8975f5c5SAndroid Build Coastguard Worker         stream->writeString(attrib.name);
234*8975f5c5SAndroid Build Coastguard Worker         stream->writeString(attrib.mappedName);
235*8975f5c5SAndroid Build Coastguard Worker         stream->writeStruct(attrib.pod);
236*8975f5c5SAndroid Build Coastguard Worker     }
237*8975f5c5SAndroid Build Coastguard Worker }
LoadProgramInputs(BinaryInputStream * stream,std::vector<ProgramInput> * programInputs)238*8975f5c5SAndroid Build Coastguard Worker void LoadProgramInputs(BinaryInputStream *stream, std::vector<ProgramInput> *programInputs)
239*8975f5c5SAndroid Build Coastguard Worker {
240*8975f5c5SAndroid Build Coastguard Worker     size_t attribCount = stream->readInt<size_t>();
241*8975f5c5SAndroid Build Coastguard Worker     ASSERT(programInputs->empty());
242*8975f5c5SAndroid Build Coastguard Worker     if (attribCount > 0)
243*8975f5c5SAndroid Build Coastguard Worker     {
244*8975f5c5SAndroid Build Coastguard Worker         programInputs->resize(attribCount);
245*8975f5c5SAndroid Build Coastguard Worker         for (size_t attribIndex = 0; attribIndex < attribCount; ++attribIndex)
246*8975f5c5SAndroid Build Coastguard Worker         {
247*8975f5c5SAndroid Build Coastguard Worker             ProgramInput &attrib = (*programInputs)[attribIndex];
248*8975f5c5SAndroid Build Coastguard Worker             stream->readString(&attrib.name);
249*8975f5c5SAndroid Build Coastguard Worker             stream->readString(&attrib.mappedName);
250*8975f5c5SAndroid Build Coastguard Worker             stream->readStruct(&attrib.pod);
251*8975f5c5SAndroid Build Coastguard Worker         }
252*8975f5c5SAndroid Build Coastguard Worker     }
253*8975f5c5SAndroid Build Coastguard Worker }
254*8975f5c5SAndroid Build Coastguard Worker 
SaveUniforms(BinaryOutputStream * stream,const std::vector<LinkedUniform> & uniforms,const std::vector<std::string> & uniformNames,const std::vector<std::string> & uniformMappedNames,const std::vector<VariableLocation> & uniformLocations)255*8975f5c5SAndroid Build Coastguard Worker void SaveUniforms(BinaryOutputStream *stream,
256*8975f5c5SAndroid Build Coastguard Worker                   const std::vector<LinkedUniform> &uniforms,
257*8975f5c5SAndroid Build Coastguard Worker                   const std::vector<std::string> &uniformNames,
258*8975f5c5SAndroid Build Coastguard Worker                   const std::vector<std::string> &uniformMappedNames,
259*8975f5c5SAndroid Build Coastguard Worker                   const std::vector<VariableLocation> &uniformLocations)
260*8975f5c5SAndroid Build Coastguard Worker {
261*8975f5c5SAndroid Build Coastguard Worker     stream->writeVector(uniforms);
262*8975f5c5SAndroid Build Coastguard Worker     ASSERT(uniforms.size() == uniformNames.size());
263*8975f5c5SAndroid Build Coastguard Worker     ASSERT(uniforms.size() == uniformMappedNames.size());
264*8975f5c5SAndroid Build Coastguard Worker     for (const std::string &name : uniformNames)
265*8975f5c5SAndroid Build Coastguard Worker     {
266*8975f5c5SAndroid Build Coastguard Worker         stream->writeString(name);
267*8975f5c5SAndroid Build Coastguard Worker     }
268*8975f5c5SAndroid Build Coastguard Worker     for (const std::string &name : uniformMappedNames)
269*8975f5c5SAndroid Build Coastguard Worker     {
270*8975f5c5SAndroid Build Coastguard Worker         stream->writeString(name);
271*8975f5c5SAndroid Build Coastguard Worker     }
272*8975f5c5SAndroid Build Coastguard Worker     stream->writeVector(uniformLocations);
273*8975f5c5SAndroid Build Coastguard Worker }
LoadUniforms(BinaryInputStream * stream,std::vector<LinkedUniform> * uniforms,std::vector<std::string> * uniformNames,std::vector<std::string> * uniformMappedNames,std::vector<VariableLocation> * uniformLocations)274*8975f5c5SAndroid Build Coastguard Worker void LoadUniforms(BinaryInputStream *stream,
275*8975f5c5SAndroid Build Coastguard Worker                   std::vector<LinkedUniform> *uniforms,
276*8975f5c5SAndroid Build Coastguard Worker                   std::vector<std::string> *uniformNames,
277*8975f5c5SAndroid Build Coastguard Worker                   std::vector<std::string> *uniformMappedNames,
278*8975f5c5SAndroid Build Coastguard Worker                   std::vector<VariableLocation> *uniformLocations)
279*8975f5c5SAndroid Build Coastguard Worker {
280*8975f5c5SAndroid Build Coastguard Worker     stream->readVector(uniforms);
281*8975f5c5SAndroid Build Coastguard Worker     if (!uniforms->empty())
282*8975f5c5SAndroid Build Coastguard Worker     {
283*8975f5c5SAndroid Build Coastguard Worker         uniformNames->resize(uniforms->size());
284*8975f5c5SAndroid Build Coastguard Worker         for (size_t uniformIndex = 0; uniformIndex < uniforms->size(); ++uniformIndex)
285*8975f5c5SAndroid Build Coastguard Worker         {
286*8975f5c5SAndroid Build Coastguard Worker             stream->readString(&(*uniformNames)[uniformIndex]);
287*8975f5c5SAndroid Build Coastguard Worker         }
288*8975f5c5SAndroid Build Coastguard Worker         uniformMappedNames->resize(uniforms->size());
289*8975f5c5SAndroid Build Coastguard Worker         for (size_t uniformIndex = 0; uniformIndex < uniforms->size(); ++uniformIndex)
290*8975f5c5SAndroid Build Coastguard Worker         {
291*8975f5c5SAndroid Build Coastguard Worker             stream->readString(&(*uniformMappedNames)[uniformIndex]);
292*8975f5c5SAndroid Build Coastguard Worker         }
293*8975f5c5SAndroid Build Coastguard Worker     }
294*8975f5c5SAndroid Build Coastguard Worker     stream->readVector(uniformLocations);
295*8975f5c5SAndroid Build Coastguard Worker }
296*8975f5c5SAndroid Build Coastguard Worker 
SaveSamplerBindings(BinaryOutputStream * stream,const std::vector<SamplerBinding> & samplerBindings,const std::vector<GLuint> & samplerBoundTextureUnits)297*8975f5c5SAndroid Build Coastguard Worker void SaveSamplerBindings(BinaryOutputStream *stream,
298*8975f5c5SAndroid Build Coastguard Worker                          const std::vector<SamplerBinding> &samplerBindings,
299*8975f5c5SAndroid Build Coastguard Worker                          const std::vector<GLuint> &samplerBoundTextureUnits)
300*8975f5c5SAndroid Build Coastguard Worker {
301*8975f5c5SAndroid Build Coastguard Worker     stream->writeVector(samplerBindings);
302*8975f5c5SAndroid Build Coastguard Worker     stream->writeInt(samplerBoundTextureUnits.size());
303*8975f5c5SAndroid Build Coastguard Worker }
LoadSamplerBindings(BinaryInputStream * stream,std::vector<SamplerBinding> * samplerBindings,std::vector<GLuint> * samplerBoundTextureUnits)304*8975f5c5SAndroid Build Coastguard Worker void LoadSamplerBindings(BinaryInputStream *stream,
305*8975f5c5SAndroid Build Coastguard Worker                          std::vector<SamplerBinding> *samplerBindings,
306*8975f5c5SAndroid Build Coastguard Worker                          std::vector<GLuint> *samplerBoundTextureUnits)
307*8975f5c5SAndroid Build Coastguard Worker {
308*8975f5c5SAndroid Build Coastguard Worker     stream->readVector(samplerBindings);
309*8975f5c5SAndroid Build Coastguard Worker     ASSERT(samplerBoundTextureUnits->empty());
310*8975f5c5SAndroid Build Coastguard Worker     size_t boundTextureUnitsCount = stream->readInt<size_t>();
311*8975f5c5SAndroid Build Coastguard Worker     samplerBoundTextureUnits->resize(boundTextureUnitsCount, 0);
312*8975f5c5SAndroid Build Coastguard Worker }
313*8975f5c5SAndroid Build Coastguard Worker 
WriteBufferVariable(BinaryOutputStream * stream,const BufferVariable & var)314*8975f5c5SAndroid Build Coastguard Worker void WriteBufferVariable(BinaryOutputStream *stream, const BufferVariable &var)
315*8975f5c5SAndroid Build Coastguard Worker {
316*8975f5c5SAndroid Build Coastguard Worker     stream->writeString(var.name);
317*8975f5c5SAndroid Build Coastguard Worker     stream->writeString(var.mappedName);
318*8975f5c5SAndroid Build Coastguard Worker     stream->writeStruct(var.pod);
319*8975f5c5SAndroid Build Coastguard Worker }
320*8975f5c5SAndroid Build Coastguard Worker 
LoadBufferVariable(BinaryInputStream * stream,BufferVariable * var)321*8975f5c5SAndroid Build Coastguard Worker void LoadBufferVariable(BinaryInputStream *stream, BufferVariable *var)
322*8975f5c5SAndroid Build Coastguard Worker {
323*8975f5c5SAndroid Build Coastguard Worker     var->name       = stream->readString();
324*8975f5c5SAndroid Build Coastguard Worker     var->mappedName = stream->readString();
325*8975f5c5SAndroid Build Coastguard Worker     stream->readStruct(&var->pod);
326*8975f5c5SAndroid Build Coastguard Worker }
327*8975f5c5SAndroid Build Coastguard Worker 
WriteAtomicCounterBuffer(BinaryOutputStream * stream,const AtomicCounterBuffer & var)328*8975f5c5SAndroid Build Coastguard Worker void WriteAtomicCounterBuffer(BinaryOutputStream *stream, const AtomicCounterBuffer &var)
329*8975f5c5SAndroid Build Coastguard Worker {
330*8975f5c5SAndroid Build Coastguard Worker     stream->writeVector(var.memberIndexes);
331*8975f5c5SAndroid Build Coastguard Worker     stream->writeStruct(var.pod);
332*8975f5c5SAndroid Build Coastguard Worker }
333*8975f5c5SAndroid Build Coastguard Worker 
LoadAtomicCounterBuffer(BinaryInputStream * stream,AtomicCounterBuffer * var)334*8975f5c5SAndroid Build Coastguard Worker void LoadAtomicCounterBuffer(BinaryInputStream *stream, AtomicCounterBuffer *var)
335*8975f5c5SAndroid Build Coastguard Worker {
336*8975f5c5SAndroid Build Coastguard Worker     stream->readVector(&var->memberIndexes);
337*8975f5c5SAndroid Build Coastguard Worker     stream->readStruct(&var->pod);
338*8975f5c5SAndroid Build Coastguard Worker }
339*8975f5c5SAndroid Build Coastguard Worker 
WriteInterfaceBlock(BinaryOutputStream * stream,const InterfaceBlock & block)340*8975f5c5SAndroid Build Coastguard Worker void WriteInterfaceBlock(BinaryOutputStream *stream, const InterfaceBlock &block)
341*8975f5c5SAndroid Build Coastguard Worker {
342*8975f5c5SAndroid Build Coastguard Worker     stream->writeString(block.name);
343*8975f5c5SAndroid Build Coastguard Worker     stream->writeString(block.mappedName);
344*8975f5c5SAndroid Build Coastguard Worker     stream->writeVector(block.memberIndexes);
345*8975f5c5SAndroid Build Coastguard Worker     stream->writeStruct(block.pod);
346*8975f5c5SAndroid Build Coastguard Worker }
347*8975f5c5SAndroid Build Coastguard Worker 
LoadInterfaceBlock(BinaryInputStream * stream,InterfaceBlock * block)348*8975f5c5SAndroid Build Coastguard Worker void LoadInterfaceBlock(BinaryInputStream *stream, InterfaceBlock *block)
349*8975f5c5SAndroid Build Coastguard Worker {
350*8975f5c5SAndroid Build Coastguard Worker     block->name       = stream->readString();
351*8975f5c5SAndroid Build Coastguard Worker     block->mappedName = stream->readString();
352*8975f5c5SAndroid Build Coastguard Worker     stream->readVector(&block->memberIndexes);
353*8975f5c5SAndroid Build Coastguard Worker     stream->readStruct(&block->pod);
354*8975f5c5SAndroid Build Coastguard Worker }
355*8975f5c5SAndroid Build Coastguard Worker 
CopyStringToBuffer(GLchar * buffer,const std::string & string,GLsizei bufSize,GLsizei * lengthOut)356*8975f5c5SAndroid Build Coastguard Worker void CopyStringToBuffer(GLchar *buffer,
357*8975f5c5SAndroid Build Coastguard Worker                         const std::string &string,
358*8975f5c5SAndroid Build Coastguard Worker                         GLsizei bufSize,
359*8975f5c5SAndroid Build Coastguard Worker                         GLsizei *lengthOut)
360*8975f5c5SAndroid Build Coastguard Worker {
361*8975f5c5SAndroid Build Coastguard Worker     ASSERT(bufSize > 0);
362*8975f5c5SAndroid Build Coastguard Worker     size_t length = std::min<size_t>(bufSize - 1, string.length());
363*8975f5c5SAndroid Build Coastguard Worker     memcpy(buffer, string.c_str(), length);
364*8975f5c5SAndroid Build Coastguard Worker     buffer[length] = '\0';
365*8975f5c5SAndroid Build Coastguard Worker 
366*8975f5c5SAndroid Build Coastguard Worker     if (lengthOut)
367*8975f5c5SAndroid Build Coastguard Worker     {
368*8975f5c5SAndroid Build Coastguard Worker         *lengthOut = static_cast<GLsizei>(length);
369*8975f5c5SAndroid Build Coastguard Worker     }
370*8975f5c5SAndroid Build Coastguard Worker }
371*8975f5c5SAndroid Build Coastguard Worker 
372*8975f5c5SAndroid Build Coastguard Worker template <typename T>
GetResourceMaxNameSize(const T & resource,GLint max)373*8975f5c5SAndroid Build Coastguard Worker GLuint GetResourceMaxNameSize(const T &resource, GLint max)
374*8975f5c5SAndroid Build Coastguard Worker {
375*8975f5c5SAndroid Build Coastguard Worker     if (resource.isArray())
376*8975f5c5SAndroid Build Coastguard Worker     {
377*8975f5c5SAndroid Build Coastguard Worker         return std::max(max, clampCast<GLint>((resource.name + "[0]").size()));
378*8975f5c5SAndroid Build Coastguard Worker     }
379*8975f5c5SAndroid Build Coastguard Worker     else
380*8975f5c5SAndroid Build Coastguard Worker     {
381*8975f5c5SAndroid Build Coastguard Worker         return std::max(max, clampCast<GLint>((resource.name).size()));
382*8975f5c5SAndroid Build Coastguard Worker     }
383*8975f5c5SAndroid Build Coastguard Worker }
384*8975f5c5SAndroid Build Coastguard Worker 
385*8975f5c5SAndroid Build Coastguard Worker template <typename T>
GetResourceLocation(const GLchar * name,const T & variable,GLint location)386*8975f5c5SAndroid Build Coastguard Worker GLuint GetResourceLocation(const GLchar *name, const T &variable, GLint location)
387*8975f5c5SAndroid Build Coastguard Worker {
388*8975f5c5SAndroid Build Coastguard Worker     if (variable.isBuiltIn())
389*8975f5c5SAndroid Build Coastguard Worker     {
390*8975f5c5SAndroid Build Coastguard Worker         return GL_INVALID_INDEX;
391*8975f5c5SAndroid Build Coastguard Worker     }
392*8975f5c5SAndroid Build Coastguard Worker 
393*8975f5c5SAndroid Build Coastguard Worker     if (variable.isArray())
394*8975f5c5SAndroid Build Coastguard Worker     {
395*8975f5c5SAndroid Build Coastguard Worker         size_t nameLengthWithoutArrayIndexOut;
396*8975f5c5SAndroid Build Coastguard Worker         size_t arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndexOut);
397*8975f5c5SAndroid Build Coastguard Worker         // The 'name' string may not contain the array notation "[0]"
398*8975f5c5SAndroid Build Coastguard Worker         if (arrayIndex != GL_INVALID_INDEX)
399*8975f5c5SAndroid Build Coastguard Worker         {
400*8975f5c5SAndroid Build Coastguard Worker             location += arrayIndex;
401*8975f5c5SAndroid Build Coastguard Worker         }
402*8975f5c5SAndroid Build Coastguard Worker     }
403*8975f5c5SAndroid Build Coastguard Worker 
404*8975f5c5SAndroid Build Coastguard Worker     return location;
405*8975f5c5SAndroid Build Coastguard Worker }
406*8975f5c5SAndroid Build Coastguard Worker 
407*8975f5c5SAndroid Build Coastguard Worker template <typename T>
GetResourceName(const T & resource)408*8975f5c5SAndroid Build Coastguard Worker const std::string GetResourceName(const T &resource)
409*8975f5c5SAndroid Build Coastguard Worker {
410*8975f5c5SAndroid Build Coastguard Worker     std::string resourceName = resource.name;
411*8975f5c5SAndroid Build Coastguard Worker 
412*8975f5c5SAndroid Build Coastguard Worker     if (resource.isArray())
413*8975f5c5SAndroid Build Coastguard Worker     {
414*8975f5c5SAndroid Build Coastguard Worker         resourceName += "[0]";
415*8975f5c5SAndroid Build Coastguard Worker     }
416*8975f5c5SAndroid Build Coastguard Worker 
417*8975f5c5SAndroid Build Coastguard Worker     return resourceName;
418*8975f5c5SAndroid Build Coastguard Worker }
419*8975f5c5SAndroid Build Coastguard Worker 
GetVariableLocation(const std::vector<gl::ProgramOutput> & list,const std::vector<VariableLocation> & locationList,const std::string & name)420*8975f5c5SAndroid Build Coastguard Worker GLint GetVariableLocation(const std::vector<gl::ProgramOutput> &list,
421*8975f5c5SAndroid Build Coastguard Worker                           const std::vector<VariableLocation> &locationList,
422*8975f5c5SAndroid Build Coastguard Worker                           const std::string &name)
423*8975f5c5SAndroid Build Coastguard Worker {
424*8975f5c5SAndroid Build Coastguard Worker     size_t nameLengthWithoutArrayIndex;
425*8975f5c5SAndroid Build Coastguard Worker     unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
426*8975f5c5SAndroid Build Coastguard Worker 
427*8975f5c5SAndroid Build Coastguard Worker     for (size_t location = 0u; location < locationList.size(); ++location)
428*8975f5c5SAndroid Build Coastguard Worker     {
429*8975f5c5SAndroid Build Coastguard Worker         const VariableLocation &variableLocation = locationList[location];
430*8975f5c5SAndroid Build Coastguard Worker         if (!variableLocation.used())
431*8975f5c5SAndroid Build Coastguard Worker         {
432*8975f5c5SAndroid Build Coastguard Worker             continue;
433*8975f5c5SAndroid Build Coastguard Worker         }
434*8975f5c5SAndroid Build Coastguard Worker 
435*8975f5c5SAndroid Build Coastguard Worker         const gl::ProgramOutput &variable = list[variableLocation.index];
436*8975f5c5SAndroid Build Coastguard Worker 
437*8975f5c5SAndroid Build Coastguard Worker         // Array output variables may be bound out of order, so we need to ensure we only pick the
438*8975f5c5SAndroid Build Coastguard Worker         // first element if given the base name.
439*8975f5c5SAndroid Build Coastguard Worker         if ((variable.name == name) && (variableLocation.arrayIndex == 0))
440*8975f5c5SAndroid Build Coastguard Worker         {
441*8975f5c5SAndroid Build Coastguard Worker             return static_cast<GLint>(location);
442*8975f5c5SAndroid Build Coastguard Worker         }
443*8975f5c5SAndroid Build Coastguard Worker         if (variable.isArray() && variableLocation.arrayIndex == arrayIndex &&
444*8975f5c5SAndroid Build Coastguard Worker             angle::BeginsWith(variable.name, name, nameLengthWithoutArrayIndex))
445*8975f5c5SAndroid Build Coastguard Worker         {
446*8975f5c5SAndroid Build Coastguard Worker             return static_cast<GLint>(location);
447*8975f5c5SAndroid Build Coastguard Worker         }
448*8975f5c5SAndroid Build Coastguard Worker     }
449*8975f5c5SAndroid Build Coastguard Worker 
450*8975f5c5SAndroid Build Coastguard Worker     return -1;
451*8975f5c5SAndroid Build Coastguard Worker }
452*8975f5c5SAndroid Build Coastguard Worker 
453*8975f5c5SAndroid Build Coastguard Worker template <typename VarT>
GetResourceIndexFromName(const std::vector<VarT> & list,const std::string & name)454*8975f5c5SAndroid Build Coastguard Worker GLuint GetResourceIndexFromName(const std::vector<VarT> &list, const std::string &name)
455*8975f5c5SAndroid Build Coastguard Worker {
456*8975f5c5SAndroid Build Coastguard Worker     std::string nameAsArrayName = name + "[0]";
457*8975f5c5SAndroid Build Coastguard Worker     for (size_t index = 0; index < list.size(); index++)
458*8975f5c5SAndroid Build Coastguard Worker     {
459*8975f5c5SAndroid Build Coastguard Worker         const VarT &resource = list[index];
460*8975f5c5SAndroid Build Coastguard Worker         if (resource.name == name || (resource.isArray() && resource.name == nameAsArrayName))
461*8975f5c5SAndroid Build Coastguard Worker         {
462*8975f5c5SAndroid Build Coastguard Worker             return static_cast<GLuint>(index);
463*8975f5c5SAndroid Build Coastguard Worker         }
464*8975f5c5SAndroid Build Coastguard Worker     }
465*8975f5c5SAndroid Build Coastguard Worker 
466*8975f5c5SAndroid Build Coastguard Worker     return GL_INVALID_INDEX;
467*8975f5c5SAndroid Build Coastguard Worker }
468*8975f5c5SAndroid Build Coastguard Worker 
GetUniformIndexFromName(const std::vector<LinkedUniform> & uniformList,const std::vector<std::string> & nameList,const std::string & name)469*8975f5c5SAndroid Build Coastguard Worker GLuint GetUniformIndexFromName(const std::vector<LinkedUniform> &uniformList,
470*8975f5c5SAndroid Build Coastguard Worker                                const std::vector<std::string> &nameList,
471*8975f5c5SAndroid Build Coastguard Worker                                const std::string &name)
472*8975f5c5SAndroid Build Coastguard Worker {
473*8975f5c5SAndroid Build Coastguard Worker     std::string nameAsArrayName = name + "[0]";
474*8975f5c5SAndroid Build Coastguard Worker     for (size_t index = 0; index < nameList.size(); index++)
475*8975f5c5SAndroid Build Coastguard Worker     {
476*8975f5c5SAndroid Build Coastguard Worker         const std::string &uniformName = nameList[index];
477*8975f5c5SAndroid Build Coastguard Worker         if (uniformName == name || (uniformList[index].isArray() && uniformName == nameAsArrayName))
478*8975f5c5SAndroid Build Coastguard Worker         {
479*8975f5c5SAndroid Build Coastguard Worker             return static_cast<GLuint>(index);
480*8975f5c5SAndroid Build Coastguard Worker         }
481*8975f5c5SAndroid Build Coastguard Worker     }
482*8975f5c5SAndroid Build Coastguard Worker 
483*8975f5c5SAndroid Build Coastguard Worker     return GL_INVALID_INDEX;
484*8975f5c5SAndroid Build Coastguard Worker }
485*8975f5c5SAndroid Build Coastguard Worker 
GetUniformLocation(const std::vector<LinkedUniform> & uniformList,const std::vector<std::string> & nameList,const std::vector<VariableLocation> & locationList,const std::string & name)486*8975f5c5SAndroid Build Coastguard Worker GLint GetUniformLocation(const std::vector<LinkedUniform> &uniformList,
487*8975f5c5SAndroid Build Coastguard Worker                          const std::vector<std::string> &nameList,
488*8975f5c5SAndroid Build Coastguard Worker                          const std::vector<VariableLocation> &locationList,
489*8975f5c5SAndroid Build Coastguard Worker                          const std::string &name)
490*8975f5c5SAndroid Build Coastguard Worker {
491*8975f5c5SAndroid Build Coastguard Worker     size_t nameLengthWithoutArrayIndex;
492*8975f5c5SAndroid Build Coastguard Worker     unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
493*8975f5c5SAndroid Build Coastguard Worker 
494*8975f5c5SAndroid Build Coastguard Worker     for (size_t location = 0u; location < locationList.size(); ++location)
495*8975f5c5SAndroid Build Coastguard Worker     {
496*8975f5c5SAndroid Build Coastguard Worker         const VariableLocation &variableLocation = locationList[location];
497*8975f5c5SAndroid Build Coastguard Worker         if (!variableLocation.used())
498*8975f5c5SAndroid Build Coastguard Worker         {
499*8975f5c5SAndroid Build Coastguard Worker             continue;
500*8975f5c5SAndroid Build Coastguard Worker         }
501*8975f5c5SAndroid Build Coastguard Worker 
502*8975f5c5SAndroid Build Coastguard Worker         const LinkedUniform &variable  = uniformList[variableLocation.index];
503*8975f5c5SAndroid Build Coastguard Worker         const std::string &uniformName = nameList[variableLocation.index];
504*8975f5c5SAndroid Build Coastguard Worker 
505*8975f5c5SAndroid Build Coastguard Worker         // Array output variables may be bound out of order, so we need to ensure we only pick the
506*8975f5c5SAndroid Build Coastguard Worker         // first element if given the base name. Uniforms don't allow this behavior and some code
507*8975f5c5SAndroid Build Coastguard Worker         // seemingly depends on the opposite behavior, so only enable it for output variables.
508*8975f5c5SAndroid Build Coastguard Worker         if (angle::BeginsWith(uniformName, name) && (variableLocation.arrayIndex == 0))
509*8975f5c5SAndroid Build Coastguard Worker         {
510*8975f5c5SAndroid Build Coastguard Worker             if (name.length() == uniformName.length())
511*8975f5c5SAndroid Build Coastguard Worker             {
512*8975f5c5SAndroid Build Coastguard Worker                 ASSERT(name == uniformName);
513*8975f5c5SAndroid Build Coastguard Worker                 // GLES 3.1 November 2016 page 87.
514*8975f5c5SAndroid Build Coastguard Worker                 // The string exactly matches the name of the active variable.
515*8975f5c5SAndroid Build Coastguard Worker                 return static_cast<GLint>(location);
516*8975f5c5SAndroid Build Coastguard Worker             }
517*8975f5c5SAndroid Build Coastguard Worker             if (name.length() + 3u == uniformName.length() && variable.isArray())
518*8975f5c5SAndroid Build Coastguard Worker             {
519*8975f5c5SAndroid Build Coastguard Worker                 ASSERT(name + "[0]" == uniformName);
520*8975f5c5SAndroid Build Coastguard Worker                 // The string identifies the base name of an active array, where the string would
521*8975f5c5SAndroid Build Coastguard Worker                 // exactly match the name of the variable if the suffix "[0]" were appended to the
522*8975f5c5SAndroid Build Coastguard Worker                 // string.
523*8975f5c5SAndroid Build Coastguard Worker                 return static_cast<GLint>(location);
524*8975f5c5SAndroid Build Coastguard Worker             }
525*8975f5c5SAndroid Build Coastguard Worker         }
526*8975f5c5SAndroid Build Coastguard Worker         if (variable.isArray() && variableLocation.arrayIndex == arrayIndex &&
527*8975f5c5SAndroid Build Coastguard Worker             nameLengthWithoutArrayIndex + 3u == uniformName.length() &&
528*8975f5c5SAndroid Build Coastguard Worker             angle::BeginsWith(uniformName, name, nameLengthWithoutArrayIndex))
529*8975f5c5SAndroid Build Coastguard Worker         {
530*8975f5c5SAndroid Build Coastguard Worker             ASSERT(name.substr(0u, nameLengthWithoutArrayIndex) + "[0]" == uniformName);
531*8975f5c5SAndroid Build Coastguard Worker             // The string identifies an active element of the array, where the string ends with the
532*8975f5c5SAndroid Build Coastguard Worker             // concatenation of the "[" character, an integer (with no "+" sign, extra leading
533*8975f5c5SAndroid Build Coastguard Worker             // zeroes, or whitespace) identifying an array element, and the "]" character, the
534*8975f5c5SAndroid Build Coastguard Worker             // integer is less than the number of active elements of the array variable, and where
535*8975f5c5SAndroid Build Coastguard Worker             // the string would exactly match the enumerated name of the array if the decimal
536*8975f5c5SAndroid Build Coastguard Worker             // integer were replaced with zero.
537*8975f5c5SAndroid Build Coastguard Worker             return static_cast<GLint>(location);
538*8975f5c5SAndroid Build Coastguard Worker         }
539*8975f5c5SAndroid Build Coastguard Worker     }
540*8975f5c5SAndroid Build Coastguard Worker 
541*8975f5c5SAndroid Build Coastguard Worker     return -1;
542*8975f5c5SAndroid Build Coastguard Worker }
543*8975f5c5SAndroid Build Coastguard Worker 
GetInterfaceBlockIndex(const std::vector<InterfaceBlock> & list,const std::string & name)544*8975f5c5SAndroid Build Coastguard Worker GLuint GetInterfaceBlockIndex(const std::vector<InterfaceBlock> &list, const std::string &name)
545*8975f5c5SAndroid Build Coastguard Worker {
546*8975f5c5SAndroid Build Coastguard Worker     std::vector<unsigned int> subscripts;
547*8975f5c5SAndroid Build Coastguard Worker     std::string baseName = ParseResourceName(name, &subscripts);
548*8975f5c5SAndroid Build Coastguard Worker 
549*8975f5c5SAndroid Build Coastguard Worker     unsigned int numBlocks = static_cast<unsigned int>(list.size());
550*8975f5c5SAndroid Build Coastguard Worker     for (unsigned int blockIndex = 0; blockIndex < numBlocks; blockIndex++)
551*8975f5c5SAndroid Build Coastguard Worker     {
552*8975f5c5SAndroid Build Coastguard Worker         const auto &block = list[blockIndex];
553*8975f5c5SAndroid Build Coastguard Worker         if (block.name == baseName)
554*8975f5c5SAndroid Build Coastguard Worker         {
555*8975f5c5SAndroid Build Coastguard Worker             const bool arrayElementZero =
556*8975f5c5SAndroid Build Coastguard Worker                 (subscripts.empty() && (!block.pod.isArray || block.pod.arrayElement == 0));
557*8975f5c5SAndroid Build Coastguard Worker             const bool arrayElementMatches =
558*8975f5c5SAndroid Build Coastguard Worker                 (subscripts.size() == 1 && subscripts[0] == block.pod.arrayElement);
559*8975f5c5SAndroid Build Coastguard Worker             if (arrayElementMatches || arrayElementZero)
560*8975f5c5SAndroid Build Coastguard Worker             {
561*8975f5c5SAndroid Build Coastguard Worker                 return blockIndex;
562*8975f5c5SAndroid Build Coastguard Worker             }
563*8975f5c5SAndroid Build Coastguard Worker         }
564*8975f5c5SAndroid Build Coastguard Worker     }
565*8975f5c5SAndroid Build Coastguard Worker 
566*8975f5c5SAndroid Build Coastguard Worker     return GL_INVALID_INDEX;
567*8975f5c5SAndroid Build Coastguard Worker }
568*8975f5c5SAndroid Build Coastguard Worker 
GetInterfaceBlockName(const UniformBlockIndex index,const std::vector<InterfaceBlock> & list,GLsizei bufSize,GLsizei * length,GLchar * name)569*8975f5c5SAndroid Build Coastguard Worker void GetInterfaceBlockName(const UniformBlockIndex index,
570*8975f5c5SAndroid Build Coastguard Worker                            const std::vector<InterfaceBlock> &list,
571*8975f5c5SAndroid Build Coastguard Worker                            GLsizei bufSize,
572*8975f5c5SAndroid Build Coastguard Worker                            GLsizei *length,
573*8975f5c5SAndroid Build Coastguard Worker                            GLchar *name)
574*8975f5c5SAndroid Build Coastguard Worker {
575*8975f5c5SAndroid Build Coastguard Worker     ASSERT(index.value < list.size());
576*8975f5c5SAndroid Build Coastguard Worker 
577*8975f5c5SAndroid Build Coastguard Worker     const auto &block = list[index.value];
578*8975f5c5SAndroid Build Coastguard Worker 
579*8975f5c5SAndroid Build Coastguard Worker     if (bufSize > 0)
580*8975f5c5SAndroid Build Coastguard Worker     {
581*8975f5c5SAndroid Build Coastguard Worker         std::string blockName = block.name;
582*8975f5c5SAndroid Build Coastguard Worker 
583*8975f5c5SAndroid Build Coastguard Worker         if (block.pod.isArray)
584*8975f5c5SAndroid Build Coastguard Worker         {
585*8975f5c5SAndroid Build Coastguard Worker             blockName += ArrayString(block.pod.arrayElement);
586*8975f5c5SAndroid Build Coastguard Worker         }
587*8975f5c5SAndroid Build Coastguard Worker         CopyStringToBuffer(name, blockName, bufSize, length);
588*8975f5c5SAndroid Build Coastguard Worker     }
589*8975f5c5SAndroid Build Coastguard Worker }
590*8975f5c5SAndroid Build Coastguard Worker 
591*8975f5c5SAndroid Build Coastguard Worker template <typename T>
GetActiveInterfaceBlockMaxNameLength(const std::vector<T> & resources)592*8975f5c5SAndroid Build Coastguard Worker GLint GetActiveInterfaceBlockMaxNameLength(const std::vector<T> &resources)
593*8975f5c5SAndroid Build Coastguard Worker {
594*8975f5c5SAndroid Build Coastguard Worker     int maxLength = 0;
595*8975f5c5SAndroid Build Coastguard Worker 
596*8975f5c5SAndroid Build Coastguard Worker     for (const T &resource : resources)
597*8975f5c5SAndroid Build Coastguard Worker     {
598*8975f5c5SAndroid Build Coastguard Worker         if (!resource.name.empty())
599*8975f5c5SAndroid Build Coastguard Worker         {
600*8975f5c5SAndroid Build Coastguard Worker             int length = static_cast<int>(resource.nameWithArrayIndex().length());
601*8975f5c5SAndroid Build Coastguard Worker             maxLength  = std::max(length + 1, maxLength);
602*8975f5c5SAndroid Build Coastguard Worker         }
603*8975f5c5SAndroid Build Coastguard Worker     }
604*8975f5c5SAndroid Build Coastguard Worker 
605*8975f5c5SAndroid Build Coastguard Worker     return maxLength;
606*8975f5c5SAndroid Build Coastguard Worker }
607*8975f5c5SAndroid Build Coastguard Worker 
608*8975f5c5SAndroid Build Coastguard Worker // This simplified cast function doesn't need to worry about advanced concepts like
609*8975f5c5SAndroid Build Coastguard Worker // depth range values, or casting to bool.
610*8975f5c5SAndroid Build Coastguard Worker template <typename DestT, typename SrcT>
611*8975f5c5SAndroid Build Coastguard Worker DestT UniformStateQueryCast(SrcT value);
612*8975f5c5SAndroid Build Coastguard Worker 
613*8975f5c5SAndroid Build Coastguard Worker // From-Float-To-Integer Casts
614*8975f5c5SAndroid Build Coastguard Worker template <>
UniformStateQueryCast(GLfloat value)615*8975f5c5SAndroid Build Coastguard Worker GLint UniformStateQueryCast(GLfloat value)
616*8975f5c5SAndroid Build Coastguard Worker {
617*8975f5c5SAndroid Build Coastguard Worker     return clampCast<GLint>(roundf(value));
618*8975f5c5SAndroid Build Coastguard Worker }
619*8975f5c5SAndroid Build Coastguard Worker 
620*8975f5c5SAndroid Build Coastguard Worker template <>
UniformStateQueryCast(GLfloat value)621*8975f5c5SAndroid Build Coastguard Worker GLuint UniformStateQueryCast(GLfloat value)
622*8975f5c5SAndroid Build Coastguard Worker {
623*8975f5c5SAndroid Build Coastguard Worker     return clampCast<GLuint>(roundf(value));
624*8975f5c5SAndroid Build Coastguard Worker }
625*8975f5c5SAndroid Build Coastguard Worker 
626*8975f5c5SAndroid Build Coastguard Worker // From-Integer-to-Integer Casts
627*8975f5c5SAndroid Build Coastguard Worker template <>
UniformStateQueryCast(GLuint value)628*8975f5c5SAndroid Build Coastguard Worker GLint UniformStateQueryCast(GLuint value)
629*8975f5c5SAndroid Build Coastguard Worker {
630*8975f5c5SAndroid Build Coastguard Worker     return clampCast<GLint>(value);
631*8975f5c5SAndroid Build Coastguard Worker }
632*8975f5c5SAndroid Build Coastguard Worker 
633*8975f5c5SAndroid Build Coastguard Worker template <>
UniformStateQueryCast(GLint value)634*8975f5c5SAndroid Build Coastguard Worker GLuint UniformStateQueryCast(GLint value)
635*8975f5c5SAndroid Build Coastguard Worker {
636*8975f5c5SAndroid Build Coastguard Worker     return clampCast<GLuint>(value);
637*8975f5c5SAndroid Build Coastguard Worker }
638*8975f5c5SAndroid Build Coastguard Worker 
639*8975f5c5SAndroid Build Coastguard Worker // From-Boolean-to-Anything Casts
640*8975f5c5SAndroid Build Coastguard Worker template <>
UniformStateQueryCast(GLboolean value)641*8975f5c5SAndroid Build Coastguard Worker GLfloat UniformStateQueryCast(GLboolean value)
642*8975f5c5SAndroid Build Coastguard Worker {
643*8975f5c5SAndroid Build Coastguard Worker     return (ConvertToBool(value) ? 1.0f : 0.0f);
644*8975f5c5SAndroid Build Coastguard Worker }
645*8975f5c5SAndroid Build Coastguard Worker 
646*8975f5c5SAndroid Build Coastguard Worker template <>
UniformStateQueryCast(GLboolean value)647*8975f5c5SAndroid Build Coastguard Worker GLint UniformStateQueryCast(GLboolean value)
648*8975f5c5SAndroid Build Coastguard Worker {
649*8975f5c5SAndroid Build Coastguard Worker     return (ConvertToBool(value) ? 1 : 0);
650*8975f5c5SAndroid Build Coastguard Worker }
651*8975f5c5SAndroid Build Coastguard Worker 
652*8975f5c5SAndroid Build Coastguard Worker template <>
UniformStateQueryCast(GLboolean value)653*8975f5c5SAndroid Build Coastguard Worker GLuint UniformStateQueryCast(GLboolean value)
654*8975f5c5SAndroid Build Coastguard Worker {
655*8975f5c5SAndroid Build Coastguard Worker     return (ConvertToBool(value) ? 1u : 0u);
656*8975f5c5SAndroid Build Coastguard Worker }
657*8975f5c5SAndroid Build Coastguard Worker 
658*8975f5c5SAndroid Build Coastguard Worker // Default to static_cast
659*8975f5c5SAndroid Build Coastguard Worker template <typename DestT, typename SrcT>
UniformStateQueryCast(SrcT value)660*8975f5c5SAndroid Build Coastguard Worker DestT UniformStateQueryCast(SrcT value)
661*8975f5c5SAndroid Build Coastguard Worker {
662*8975f5c5SAndroid Build Coastguard Worker     return static_cast<DestT>(value);
663*8975f5c5SAndroid Build Coastguard Worker }
664*8975f5c5SAndroid Build Coastguard Worker 
665*8975f5c5SAndroid Build Coastguard Worker template <typename SrcT, typename DestT>
UniformStateQueryCastLoop(DestT * dataOut,const uint8_t * srcPointer,int components)666*8975f5c5SAndroid Build Coastguard Worker void UniformStateQueryCastLoop(DestT *dataOut, const uint8_t *srcPointer, int components)
667*8975f5c5SAndroid Build Coastguard Worker {
668*8975f5c5SAndroid Build Coastguard Worker     for (int comp = 0; comp < components; ++comp)
669*8975f5c5SAndroid Build Coastguard Worker     {
670*8975f5c5SAndroid Build Coastguard Worker         // We only work with strides of 4 bytes for uniform components. (GLfloat/GLint)
671*8975f5c5SAndroid Build Coastguard Worker         // Don't use SrcT stride directly since GLboolean has a stride of 1 byte.
672*8975f5c5SAndroid Build Coastguard Worker         size_t offset               = comp * 4;
673*8975f5c5SAndroid Build Coastguard Worker         const SrcT *typedSrcPointer = reinterpret_cast<const SrcT *>(&srcPointer[offset]);
674*8975f5c5SAndroid Build Coastguard Worker         dataOut[comp]               = UniformStateQueryCast<DestT>(*typedSrcPointer);
675*8975f5c5SAndroid Build Coastguard Worker     }
676*8975f5c5SAndroid Build Coastguard Worker }
677*8975f5c5SAndroid Build Coastguard Worker }  // anonymous namespace
678*8975f5c5SAndroid Build Coastguard Worker 
679*8975f5c5SAndroid Build Coastguard Worker // ImageBinding implementation.
ImageBinding(GLuint imageUnit,size_t count,TextureType textureTypeIn)680*8975f5c5SAndroid Build Coastguard Worker ImageBinding::ImageBinding(GLuint imageUnit, size_t count, TextureType textureTypeIn)
681*8975f5c5SAndroid Build Coastguard Worker     : textureType(textureTypeIn)
682*8975f5c5SAndroid Build Coastguard Worker {
683*8975f5c5SAndroid Build Coastguard Worker     for (size_t index = 0; index < count; ++index)
684*8975f5c5SAndroid Build Coastguard Worker     {
685*8975f5c5SAndroid Build Coastguard Worker         boundImageUnits.push_back(imageUnit + static_cast<GLuint>(index));
686*8975f5c5SAndroid Build Coastguard Worker     }
687*8975f5c5SAndroid Build Coastguard Worker }
688*8975f5c5SAndroid Build Coastguard Worker 
689*8975f5c5SAndroid Build Coastguard Worker // ProgramInput implementation.
ProgramInput(const sh::ShaderVariable & var)690*8975f5c5SAndroid Build Coastguard Worker ProgramInput::ProgramInput(const sh::ShaderVariable &var)
691*8975f5c5SAndroid Build Coastguard Worker {
692*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!var.isStruct());
693*8975f5c5SAndroid Build Coastguard Worker 
694*8975f5c5SAndroid Build Coastguard Worker     name       = var.name;
695*8975f5c5SAndroid Build Coastguard Worker     mappedName = var.mappedName;
696*8975f5c5SAndroid Build Coastguard Worker 
697*8975f5c5SAndroid Build Coastguard Worker     SetBitField(pod.type, var.type);
698*8975f5c5SAndroid Build Coastguard Worker     pod.location = var.hasImplicitLocation ? -1 : var.location;
699*8975f5c5SAndroid Build Coastguard Worker     SetBitField(pod.interpolation, var.interpolation);
700*8975f5c5SAndroid Build Coastguard Worker     pod.flagBitsAsUByte              = 0;
701*8975f5c5SAndroid Build Coastguard Worker     pod.flagBits.active              = var.active;
702*8975f5c5SAndroid Build Coastguard Worker     pod.flagBits.isPatch             = var.isPatch;
703*8975f5c5SAndroid Build Coastguard Worker     pod.flagBits.hasImplicitLocation = var.hasImplicitLocation;
704*8975f5c5SAndroid Build Coastguard Worker     pod.flagBits.isArray             = var.isArray();
705*8975f5c5SAndroid Build Coastguard Worker     pod.flagBits.isBuiltIn           = IsBuiltInName(var.name);
706*8975f5c5SAndroid Build Coastguard Worker     SetBitField(pod.basicTypeElementCount, var.getBasicTypeElementCount());
707*8975f5c5SAndroid Build Coastguard Worker     pod.id = var.id;
708*8975f5c5SAndroid Build Coastguard Worker     SetBitField(pod.arraySizeProduct, var.getArraySizeProduct());
709*8975f5c5SAndroid Build Coastguard Worker }
710*8975f5c5SAndroid Build Coastguard Worker 
711*8975f5c5SAndroid Build Coastguard Worker // ProgramOutput implementation.
ProgramOutput(const sh::ShaderVariable & var)712*8975f5c5SAndroid Build Coastguard Worker ProgramOutput::ProgramOutput(const sh::ShaderVariable &var)
713*8975f5c5SAndroid Build Coastguard Worker {
714*8975f5c5SAndroid Build Coastguard Worker     name       = var.name;
715*8975f5c5SAndroid Build Coastguard Worker     mappedName = var.mappedName;
716*8975f5c5SAndroid Build Coastguard Worker 
717*8975f5c5SAndroid Build Coastguard Worker     pod.type     = var.type;
718*8975f5c5SAndroid Build Coastguard Worker     pod.location = var.location;
719*8975f5c5SAndroid Build Coastguard Worker     pod.index    = var.index;
720*8975f5c5SAndroid Build Coastguard Worker     pod.id       = var.id;
721*8975f5c5SAndroid Build Coastguard Worker 
722*8975f5c5SAndroid Build Coastguard Worker     SetBitField(pod.outermostArraySize, var.getOutermostArraySize());
723*8975f5c5SAndroid Build Coastguard Worker     SetBitField(pod.basicTypeElementCount, var.getBasicTypeElementCount());
724*8975f5c5SAndroid Build Coastguard Worker 
725*8975f5c5SAndroid Build Coastguard Worker     SetBitField(pod.isPatch, var.isPatch);
726*8975f5c5SAndroid Build Coastguard Worker     SetBitField(pod.yuv, var.yuv);
727*8975f5c5SAndroid Build Coastguard Worker     SetBitField(pod.isBuiltIn, IsBuiltInName(var.name));
728*8975f5c5SAndroid Build Coastguard Worker     SetBitField(pod.isArray, var.isArray());
729*8975f5c5SAndroid Build Coastguard Worker     SetBitField(pod.hasImplicitLocation, var.hasImplicitLocation);
730*8975f5c5SAndroid Build Coastguard Worker     SetBitField(pod.hasShaderAssignedLocation, var.location != -1);
731*8975f5c5SAndroid Build Coastguard Worker     SetBitField(pod.hasApiAssignedLocation, false);
732*8975f5c5SAndroid Build Coastguard Worker     SetBitField(pod.pad, 0);
733*8975f5c5SAndroid Build Coastguard Worker 
734*8975f5c5SAndroid Build Coastguard Worker     if (pod.hasShaderAssignedLocation && pod.index == -1)
735*8975f5c5SAndroid Build Coastguard Worker     {
736*8975f5c5SAndroid Build Coastguard Worker         // Location was assigned but index was not. Equivalent to setting index to 0.
737*8975f5c5SAndroid Build Coastguard Worker         pod.index = 0;
738*8975f5c5SAndroid Build Coastguard Worker     }
739*8975f5c5SAndroid Build Coastguard Worker }
740*8975f5c5SAndroid Build Coastguard Worker 
741*8975f5c5SAndroid Build Coastguard Worker // ProgramExecutable implementation.
ProgramExecutable(rx::GLImplFactory * factory,InfoLog * infoLog)742*8975f5c5SAndroid Build Coastguard Worker ProgramExecutable::ProgramExecutable(rx::GLImplFactory *factory, InfoLog *infoLog)
743*8975f5c5SAndroid Build Coastguard Worker     : mImplementation(factory->createProgramExecutable(this)),
744*8975f5c5SAndroid Build Coastguard Worker       mInfoLog(infoLog),
745*8975f5c5SAndroid Build Coastguard Worker       mCachedBaseVertex(0),
746*8975f5c5SAndroid Build Coastguard Worker       mCachedBaseInstance(0),
747*8975f5c5SAndroid Build Coastguard Worker       mIsPPO(false)
748*8975f5c5SAndroid Build Coastguard Worker {
749*8975f5c5SAndroid Build Coastguard Worker     memset(&mPod, 0, sizeof(mPod));
750*8975f5c5SAndroid Build Coastguard Worker     reset();
751*8975f5c5SAndroid Build Coastguard Worker }
752*8975f5c5SAndroid Build Coastguard Worker 
~ProgramExecutable()753*8975f5c5SAndroid Build Coastguard Worker ProgramExecutable::~ProgramExecutable()
754*8975f5c5SAndroid Build Coastguard Worker {
755*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mPostLinkSubTasks.empty());
756*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mPostLinkSubTaskWaitableEvents.empty());
757*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mImplementation == nullptr);
758*8975f5c5SAndroid Build Coastguard Worker }
759*8975f5c5SAndroid Build Coastguard Worker 
destroy(const Context * context)760*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::destroy(const Context *context)
761*8975f5c5SAndroid Build Coastguard Worker {
762*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mImplementation != nullptr);
763*8975f5c5SAndroid Build Coastguard Worker 
764*8975f5c5SAndroid Build Coastguard Worker     for (SharedProgramExecutable &executable : mPPOProgramExecutables)
765*8975f5c5SAndroid Build Coastguard Worker     {
766*8975f5c5SAndroid Build Coastguard Worker         if (executable)
767*8975f5c5SAndroid Build Coastguard Worker         {
768*8975f5c5SAndroid Build Coastguard Worker             UninstallExecutable(context, &executable);
769*8975f5c5SAndroid Build Coastguard Worker         }
770*8975f5c5SAndroid Build Coastguard Worker     }
771*8975f5c5SAndroid Build Coastguard Worker 
772*8975f5c5SAndroid Build Coastguard Worker     mImplementation->destroy(context);
773*8975f5c5SAndroid Build Coastguard Worker     SafeDelete(mImplementation);
774*8975f5c5SAndroid Build Coastguard Worker }
775*8975f5c5SAndroid Build Coastguard Worker 
reset()776*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::reset()
777*8975f5c5SAndroid Build Coastguard Worker {
778*8975f5c5SAndroid Build Coastguard Worker     mPod.activeAttribLocationsMask.reset();
779*8975f5c5SAndroid Build Coastguard Worker     mPod.attributesTypeMask.reset();
780*8975f5c5SAndroid Build Coastguard Worker     mPod.attributesMask.reset();
781*8975f5c5SAndroid Build Coastguard Worker     mPod.maxActiveAttribLocation = 0;
782*8975f5c5SAndroid Build Coastguard Worker     mPod.activeOutputVariablesMask.reset();
783*8975f5c5SAndroid Build Coastguard Worker     mPod.activeSecondaryOutputVariablesMask.reset();
784*8975f5c5SAndroid Build Coastguard Worker 
785*8975f5c5SAndroid Build Coastguard Worker     mPod.defaultUniformRange       = RangeUI(0, 0);
786*8975f5c5SAndroid Build Coastguard Worker     mPod.samplerUniformRange       = RangeUI(0, 0);
787*8975f5c5SAndroid Build Coastguard Worker     mPod.imageUniformRange         = RangeUI(0, 0);
788*8975f5c5SAndroid Build Coastguard Worker     mPod.atomicCounterUniformRange = RangeUI(0, 0);
789*8975f5c5SAndroid Build Coastguard Worker 
790*8975f5c5SAndroid Build Coastguard Worker     mPod.fragmentInoutIndices.reset();
791*8975f5c5SAndroid Build Coastguard Worker 
792*8975f5c5SAndroid Build Coastguard Worker     mPod.hasClipDistance         = false;
793*8975f5c5SAndroid Build Coastguard Worker     mPod.hasDiscard              = false;
794*8975f5c5SAndroid Build Coastguard Worker     mPod.enablesPerSampleShading = false;
795*8975f5c5SAndroid Build Coastguard Worker     mPod.hasYUVOutput            = false;
796*8975f5c5SAndroid Build Coastguard Worker     mPod.hasDepthInputAttachment   = false;
797*8975f5c5SAndroid Build Coastguard Worker     mPod.hasStencilInputAttachment = false;
798*8975f5c5SAndroid Build Coastguard Worker 
799*8975f5c5SAndroid Build Coastguard Worker     mPod.advancedBlendEquations.reset();
800*8975f5c5SAndroid Build Coastguard Worker 
801*8975f5c5SAndroid Build Coastguard Worker     mPod.geometryShaderInputPrimitiveType  = PrimitiveMode::Triangles;
802*8975f5c5SAndroid Build Coastguard Worker     mPod.geometryShaderOutputPrimitiveType = PrimitiveMode::TriangleStrip;
803*8975f5c5SAndroid Build Coastguard Worker     mPod.geometryShaderInvocations         = 1;
804*8975f5c5SAndroid Build Coastguard Worker     mPod.geometryShaderMaxVertices         = 0;
805*8975f5c5SAndroid Build Coastguard Worker 
806*8975f5c5SAndroid Build Coastguard Worker     mPod.transformFeedbackBufferMode = GL_INTERLEAVED_ATTRIBS;
807*8975f5c5SAndroid Build Coastguard Worker 
808*8975f5c5SAndroid Build Coastguard Worker     mPod.numViews = -1;
809*8975f5c5SAndroid Build Coastguard Worker 
810*8975f5c5SAndroid Build Coastguard Worker     mPod.drawIDLocation = -1;
811*8975f5c5SAndroid Build Coastguard Worker 
812*8975f5c5SAndroid Build Coastguard Worker     mPod.baseVertexLocation   = -1;
813*8975f5c5SAndroid Build Coastguard Worker     mPod.baseInstanceLocation = -1;
814*8975f5c5SAndroid Build Coastguard Worker 
815*8975f5c5SAndroid Build Coastguard Worker     mPod.tessControlShaderVertices = 0;
816*8975f5c5SAndroid Build Coastguard Worker     mPod.tessGenMode               = GL_NONE;
817*8975f5c5SAndroid Build Coastguard Worker     mPod.tessGenSpacing            = GL_NONE;
818*8975f5c5SAndroid Build Coastguard Worker     mPod.tessGenVertexOrder        = GL_NONE;
819*8975f5c5SAndroid Build Coastguard Worker     mPod.tessGenPointMode          = GL_NONE;
820*8975f5c5SAndroid Build Coastguard Worker     mPod.drawBufferTypeMask.reset();
821*8975f5c5SAndroid Build Coastguard Worker     mPod.computeShaderLocalSize.fill(1);
822*8975f5c5SAndroid Build Coastguard Worker 
823*8975f5c5SAndroid Build Coastguard Worker     mPod.specConstUsageBits.reset();
824*8975f5c5SAndroid Build Coastguard Worker 
825*8975f5c5SAndroid Build Coastguard Worker     mActiveSamplersMask.reset();
826*8975f5c5SAndroid Build Coastguard Worker     mActiveSamplerRefCounts = {};
827*8975f5c5SAndroid Build Coastguard Worker     mActiveSamplerTypes.fill(TextureType::InvalidEnum);
828*8975f5c5SAndroid Build Coastguard Worker     mActiveSamplerYUV.reset();
829*8975f5c5SAndroid Build Coastguard Worker     mActiveSamplerFormats.fill(SamplerFormat::InvalidEnum);
830*8975f5c5SAndroid Build Coastguard Worker 
831*8975f5c5SAndroid Build Coastguard Worker     mActiveImagesMask.reset();
832*8975f5c5SAndroid Build Coastguard Worker 
833*8975f5c5SAndroid Build Coastguard Worker     mUniformBlockIndexToBufferBinding = {};
834*8975f5c5SAndroid Build Coastguard Worker 
835*8975f5c5SAndroid Build Coastguard Worker     mProgramInputs.clear();
836*8975f5c5SAndroid Build Coastguard Worker     mLinkedTransformFeedbackVaryings.clear();
837*8975f5c5SAndroid Build Coastguard Worker     mTransformFeedbackStrides.clear();
838*8975f5c5SAndroid Build Coastguard Worker     mUniforms.clear();
839*8975f5c5SAndroid Build Coastguard Worker     mUniformNames.clear();
840*8975f5c5SAndroid Build Coastguard Worker     mUniformMappedNames.clear();
841*8975f5c5SAndroid Build Coastguard Worker     mUniformBlocks.clear();
842*8975f5c5SAndroid Build Coastguard Worker     mUniformLocations.clear();
843*8975f5c5SAndroid Build Coastguard Worker     mShaderStorageBlocks.clear();
844*8975f5c5SAndroid Build Coastguard Worker     mAtomicCounterBuffers.clear();
845*8975f5c5SAndroid Build Coastguard Worker     mBufferVariables.clear();
846*8975f5c5SAndroid Build Coastguard Worker     mOutputVariables.clear();
847*8975f5c5SAndroid Build Coastguard Worker     mOutputLocations.clear();
848*8975f5c5SAndroid Build Coastguard Worker     mSecondaryOutputLocations.clear();
849*8975f5c5SAndroid Build Coastguard Worker     mSamplerBindings.clear();
850*8975f5c5SAndroid Build Coastguard Worker     mSamplerBoundTextureUnits.clear();
851*8975f5c5SAndroid Build Coastguard Worker     mImageBindings.clear();
852*8975f5c5SAndroid Build Coastguard Worker     mPixelLocalStorageFormats.clear();
853*8975f5c5SAndroid Build Coastguard Worker 
854*8975f5c5SAndroid Build Coastguard Worker     mPostLinkSubTasks.clear();
855*8975f5c5SAndroid Build Coastguard Worker     mPostLinkSubTaskWaitableEvents.clear();
856*8975f5c5SAndroid Build Coastguard Worker }
857*8975f5c5SAndroid Build Coastguard Worker 
load(gl::BinaryInputStream * stream)858*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::load(gl::BinaryInputStream *stream)
859*8975f5c5SAndroid Build Coastguard Worker {
860*8975f5c5SAndroid Build Coastguard Worker     static_assert(MAX_VERTEX_ATTRIBS * 2 <= sizeof(uint32_t) * 8,
861*8975f5c5SAndroid Build Coastguard Worker                   "Too many vertex attribs for mask: All bits of mAttributesTypeMask types and "
862*8975f5c5SAndroid Build Coastguard Worker                   "mask fit into 32 bits each");
863*8975f5c5SAndroid Build Coastguard Worker     static_assert(IMPLEMENTATION_MAX_DRAW_BUFFERS * 2 <= 8 * sizeof(uint32_t),
864*8975f5c5SAndroid Build Coastguard Worker                   "All bits of mDrawBufferTypeMask and mActiveOutputVariables types and mask fit "
865*8975f5c5SAndroid Build Coastguard Worker                   "into 32 bits each");
866*8975f5c5SAndroid Build Coastguard Worker 
867*8975f5c5SAndroid Build Coastguard Worker     stream->readStruct(&mPod);
868*8975f5c5SAndroid Build Coastguard Worker 
869*8975f5c5SAndroid Build Coastguard Worker     LoadProgramInputs(stream, &mProgramInputs);
870*8975f5c5SAndroid Build Coastguard Worker     LoadUniforms(stream, &mUniforms, &mUniformNames, &mUniformMappedNames, &mUniformLocations);
871*8975f5c5SAndroid Build Coastguard Worker 
872*8975f5c5SAndroid Build Coastguard Worker     size_t uniformBlockCount = stream->readInt<size_t>();
873*8975f5c5SAndroid Build Coastguard Worker     ASSERT(getUniformBlocks().empty());
874*8975f5c5SAndroid Build Coastguard Worker     mUniformBlocks.resize(uniformBlockCount);
875*8975f5c5SAndroid Build Coastguard Worker     for (size_t uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount; ++uniformBlockIndex)
876*8975f5c5SAndroid Build Coastguard Worker     {
877*8975f5c5SAndroid Build Coastguard Worker         InterfaceBlock &uniformBlock = mUniformBlocks[uniformBlockIndex];
878*8975f5c5SAndroid Build Coastguard Worker         LoadInterfaceBlock(stream, &uniformBlock);
879*8975f5c5SAndroid Build Coastguard Worker     }
880*8975f5c5SAndroid Build Coastguard Worker 
881*8975f5c5SAndroid Build Coastguard Worker     size_t shaderStorageBlockCount = stream->readInt<size_t>();
882*8975f5c5SAndroid Build Coastguard Worker     ASSERT(getShaderStorageBlocks().empty());
883*8975f5c5SAndroid Build Coastguard Worker     mShaderStorageBlocks.resize(shaderStorageBlockCount);
884*8975f5c5SAndroid Build Coastguard Worker     for (size_t shaderStorageBlockIndex = 0; shaderStorageBlockIndex < shaderStorageBlockCount;
885*8975f5c5SAndroid Build Coastguard Worker          ++shaderStorageBlockIndex)
886*8975f5c5SAndroid Build Coastguard Worker     {
887*8975f5c5SAndroid Build Coastguard Worker         InterfaceBlock &shaderStorageBlock = mShaderStorageBlocks[shaderStorageBlockIndex];
888*8975f5c5SAndroid Build Coastguard Worker         LoadInterfaceBlock(stream, &shaderStorageBlock);
889*8975f5c5SAndroid Build Coastguard Worker     }
890*8975f5c5SAndroid Build Coastguard Worker 
891*8975f5c5SAndroid Build Coastguard Worker     size_t atomicCounterBufferCount = stream->readInt<size_t>();
892*8975f5c5SAndroid Build Coastguard Worker     ASSERT(getAtomicCounterBuffers().empty());
893*8975f5c5SAndroid Build Coastguard Worker     mAtomicCounterBuffers.resize(atomicCounterBufferCount);
894*8975f5c5SAndroid Build Coastguard Worker     for (size_t bufferIndex = 0; bufferIndex < atomicCounterBufferCount; ++bufferIndex)
895*8975f5c5SAndroid Build Coastguard Worker     {
896*8975f5c5SAndroid Build Coastguard Worker         AtomicCounterBuffer &atomicCounterBuffer = mAtomicCounterBuffers[bufferIndex];
897*8975f5c5SAndroid Build Coastguard Worker         LoadAtomicCounterBuffer(stream, &atomicCounterBuffer);
898*8975f5c5SAndroid Build Coastguard Worker     }
899*8975f5c5SAndroid Build Coastguard Worker 
900*8975f5c5SAndroid Build Coastguard Worker     size_t bufferVariableCount = stream->readInt<size_t>();
901*8975f5c5SAndroid Build Coastguard Worker     ASSERT(getBufferVariables().empty());
902*8975f5c5SAndroid Build Coastguard Worker     mBufferVariables.resize(bufferVariableCount);
903*8975f5c5SAndroid Build Coastguard Worker     for (size_t bufferVarIndex = 0; bufferVarIndex < bufferVariableCount; ++bufferVarIndex)
904*8975f5c5SAndroid Build Coastguard Worker     {
905*8975f5c5SAndroid Build Coastguard Worker         LoadBufferVariable(stream, &mBufferVariables[bufferVarIndex]);
906*8975f5c5SAndroid Build Coastguard Worker     }
907*8975f5c5SAndroid Build Coastguard Worker 
908*8975f5c5SAndroid Build Coastguard Worker     size_t transformFeedbackVaryingCount = stream->readInt<size_t>();
909*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mLinkedTransformFeedbackVaryings.empty());
910*8975f5c5SAndroid Build Coastguard Worker     mLinkedTransformFeedbackVaryings.resize(transformFeedbackVaryingCount);
911*8975f5c5SAndroid Build Coastguard Worker     for (size_t transformFeedbackVaryingIndex = 0;
912*8975f5c5SAndroid Build Coastguard Worker          transformFeedbackVaryingIndex < transformFeedbackVaryingCount;
913*8975f5c5SAndroid Build Coastguard Worker          ++transformFeedbackVaryingIndex)
914*8975f5c5SAndroid Build Coastguard Worker     {
915*8975f5c5SAndroid Build Coastguard Worker         TransformFeedbackVarying &varying =
916*8975f5c5SAndroid Build Coastguard Worker             mLinkedTransformFeedbackVaryings[transformFeedbackVaryingIndex];
917*8975f5c5SAndroid Build Coastguard Worker         stream->readVector(&varying.arraySizes);
918*8975f5c5SAndroid Build Coastguard Worker         stream->readInt(&varying.type);
919*8975f5c5SAndroid Build Coastguard Worker         stream->readString(&varying.name);
920*8975f5c5SAndroid Build Coastguard Worker         varying.arrayIndex = stream->readInt<GLuint>();
921*8975f5c5SAndroid Build Coastguard Worker     }
922*8975f5c5SAndroid Build Coastguard Worker 
923*8975f5c5SAndroid Build Coastguard Worker     size_t outputCount = stream->readInt<size_t>();
924*8975f5c5SAndroid Build Coastguard Worker     ASSERT(getOutputVariables().empty());
925*8975f5c5SAndroid Build Coastguard Worker     mOutputVariables.resize(outputCount);
926*8975f5c5SAndroid Build Coastguard Worker     for (size_t outputIndex = 0; outputIndex < outputCount; ++outputIndex)
927*8975f5c5SAndroid Build Coastguard Worker     {
928*8975f5c5SAndroid Build Coastguard Worker         ProgramOutput &output = mOutputVariables[outputIndex];
929*8975f5c5SAndroid Build Coastguard Worker         stream->readString(&output.name);
930*8975f5c5SAndroid Build Coastguard Worker         stream->readString(&output.mappedName);
931*8975f5c5SAndroid Build Coastguard Worker         stream->readStruct(&output.pod);
932*8975f5c5SAndroid Build Coastguard Worker     }
933*8975f5c5SAndroid Build Coastguard Worker 
934*8975f5c5SAndroid Build Coastguard Worker     stream->readVector(&mOutputLocations);
935*8975f5c5SAndroid Build Coastguard Worker     stream->readVector(&mSecondaryOutputLocations);
936*8975f5c5SAndroid Build Coastguard Worker     LoadSamplerBindings(stream, &mSamplerBindings, &mSamplerBoundTextureUnits);
937*8975f5c5SAndroid Build Coastguard Worker 
938*8975f5c5SAndroid Build Coastguard Worker     size_t imageBindingCount = stream->readInt<size_t>();
939*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mImageBindings.empty());
940*8975f5c5SAndroid Build Coastguard Worker     mImageBindings.resize(imageBindingCount);
941*8975f5c5SAndroid Build Coastguard Worker     for (size_t imageIndex = 0; imageIndex < imageBindingCount; ++imageIndex)
942*8975f5c5SAndroid Build Coastguard Worker     {
943*8975f5c5SAndroid Build Coastguard Worker         ImageBinding &imageBinding = mImageBindings[imageIndex];
944*8975f5c5SAndroid Build Coastguard Worker         size_t elementCount        = stream->readInt<size_t>();
945*8975f5c5SAndroid Build Coastguard Worker         imageBinding.textureType   = static_cast<TextureType>(stream->readInt<unsigned int>());
946*8975f5c5SAndroid Build Coastguard Worker         imageBinding.boundImageUnits.resize(elementCount);
947*8975f5c5SAndroid Build Coastguard Worker         for (size_t elementIndex = 0; elementIndex < elementCount; ++elementIndex)
948*8975f5c5SAndroid Build Coastguard Worker         {
949*8975f5c5SAndroid Build Coastguard Worker             imageBinding.boundImageUnits[elementIndex] = stream->readInt<unsigned int>();
950*8975f5c5SAndroid Build Coastguard Worker         }
951*8975f5c5SAndroid Build Coastguard Worker     }
952*8975f5c5SAndroid Build Coastguard Worker 
953*8975f5c5SAndroid Build Coastguard Worker     // ANGLE_shader_pixel_local_storage.
954*8975f5c5SAndroid Build Coastguard Worker     size_t plsCount = stream->readInt<size_t>();
955*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mPixelLocalStorageFormats.empty());
956*8975f5c5SAndroid Build Coastguard Worker     mPixelLocalStorageFormats.resize(plsCount);
957*8975f5c5SAndroid Build Coastguard Worker     stream->readBytes(reinterpret_cast<uint8_t *>(mPixelLocalStorageFormats.data()), plsCount);
958*8975f5c5SAndroid Build Coastguard Worker 
959*8975f5c5SAndroid Build Coastguard Worker     // These values are currently only used by PPOs, so only load them when the program is marked
960*8975f5c5SAndroid Build Coastguard Worker     // separable to save memory.
961*8975f5c5SAndroid Build Coastguard Worker     if (mPod.isSeparable)
962*8975f5c5SAndroid Build Coastguard Worker     {
963*8975f5c5SAndroid Build Coastguard Worker         for (ShaderType shaderType : getLinkedShaderStages())
964*8975f5c5SAndroid Build Coastguard Worker         {
965*8975f5c5SAndroid Build Coastguard Worker             mLinkedOutputVaryings[shaderType].resize(stream->readInt<size_t>());
966*8975f5c5SAndroid Build Coastguard Worker             for (sh::ShaderVariable &variable : mLinkedOutputVaryings[shaderType])
967*8975f5c5SAndroid Build Coastguard Worker             {
968*8975f5c5SAndroid Build Coastguard Worker                 LoadShaderVar(stream, &variable);
969*8975f5c5SAndroid Build Coastguard Worker             }
970*8975f5c5SAndroid Build Coastguard Worker             mLinkedInputVaryings[shaderType].resize(stream->readInt<size_t>());
971*8975f5c5SAndroid Build Coastguard Worker             for (sh::ShaderVariable &variable : mLinkedInputVaryings[shaderType])
972*8975f5c5SAndroid Build Coastguard Worker             {
973*8975f5c5SAndroid Build Coastguard Worker                 LoadShaderVar(stream, &variable);
974*8975f5c5SAndroid Build Coastguard Worker             }
975*8975f5c5SAndroid Build Coastguard Worker             mLinkedUniforms[shaderType].resize(stream->readInt<size_t>());
976*8975f5c5SAndroid Build Coastguard Worker             for (sh::ShaderVariable &variable : mLinkedUniforms[shaderType])
977*8975f5c5SAndroid Build Coastguard Worker             {
978*8975f5c5SAndroid Build Coastguard Worker                 LoadShaderVar(stream, &variable);
979*8975f5c5SAndroid Build Coastguard Worker             }
980*8975f5c5SAndroid Build Coastguard Worker             mLinkedUniformBlocks[shaderType].resize(stream->readInt<size_t>());
981*8975f5c5SAndroid Build Coastguard Worker             for (sh::InterfaceBlock &shaderStorageBlock : mLinkedUniformBlocks[shaderType])
982*8975f5c5SAndroid Build Coastguard Worker             {
983*8975f5c5SAndroid Build Coastguard Worker                 LoadShInterfaceBlock(stream, &shaderStorageBlock);
984*8975f5c5SAndroid Build Coastguard Worker             }
985*8975f5c5SAndroid Build Coastguard Worker         }
986*8975f5c5SAndroid Build Coastguard Worker     }
987*8975f5c5SAndroid Build Coastguard Worker }
988*8975f5c5SAndroid Build Coastguard Worker 
save(gl::BinaryOutputStream * stream) const989*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::save(gl::BinaryOutputStream *stream) const
990*8975f5c5SAndroid Build Coastguard Worker {
991*8975f5c5SAndroid Build Coastguard Worker     static_assert(MAX_VERTEX_ATTRIBS * 2 <= sizeof(uint32_t) * 8,
992*8975f5c5SAndroid Build Coastguard Worker                   "All bits of mAttributesTypeMask types and mask fit into 32 bits each");
993*8975f5c5SAndroid Build Coastguard Worker     static_assert(
994*8975f5c5SAndroid Build Coastguard Worker         IMPLEMENTATION_MAX_DRAW_BUFFERS * 2 <= 8 * sizeof(uint32_t),
995*8975f5c5SAndroid Build Coastguard Worker         "All bits of mDrawBufferTypeMask and mActiveOutputVariables can be contained in 32 bits");
996*8975f5c5SAndroid Build Coastguard Worker 
997*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mPod.geometryShaderInvocations >= 1 && mPod.geometryShaderMaxVertices >= 0);
998*8975f5c5SAndroid Build Coastguard Worker     stream->writeStruct(mPod);
999*8975f5c5SAndroid Build Coastguard Worker 
1000*8975f5c5SAndroid Build Coastguard Worker     SaveProgramInputs(stream, mProgramInputs);
1001*8975f5c5SAndroid Build Coastguard Worker     SaveUniforms(stream, mUniforms, mUniformNames, mUniformMappedNames, mUniformLocations);
1002*8975f5c5SAndroid Build Coastguard Worker 
1003*8975f5c5SAndroid Build Coastguard Worker     stream->writeInt(getUniformBlocks().size());
1004*8975f5c5SAndroid Build Coastguard Worker     for (const InterfaceBlock &uniformBlock : getUniformBlocks())
1005*8975f5c5SAndroid Build Coastguard Worker     {
1006*8975f5c5SAndroid Build Coastguard Worker         WriteInterfaceBlock(stream, uniformBlock);
1007*8975f5c5SAndroid Build Coastguard Worker     }
1008*8975f5c5SAndroid Build Coastguard Worker 
1009*8975f5c5SAndroid Build Coastguard Worker     stream->writeInt(getShaderStorageBlocks().size());
1010*8975f5c5SAndroid Build Coastguard Worker     for (const InterfaceBlock &shaderStorageBlock : getShaderStorageBlocks())
1011*8975f5c5SAndroid Build Coastguard Worker     {
1012*8975f5c5SAndroid Build Coastguard Worker         WriteInterfaceBlock(stream, shaderStorageBlock);
1013*8975f5c5SAndroid Build Coastguard Worker     }
1014*8975f5c5SAndroid Build Coastguard Worker 
1015*8975f5c5SAndroid Build Coastguard Worker     stream->writeInt(mAtomicCounterBuffers.size());
1016*8975f5c5SAndroid Build Coastguard Worker     for (const AtomicCounterBuffer &atomicCounterBuffer : getAtomicCounterBuffers())
1017*8975f5c5SAndroid Build Coastguard Worker     {
1018*8975f5c5SAndroid Build Coastguard Worker         WriteAtomicCounterBuffer(stream, atomicCounterBuffer);
1019*8975f5c5SAndroid Build Coastguard Worker     }
1020*8975f5c5SAndroid Build Coastguard Worker 
1021*8975f5c5SAndroid Build Coastguard Worker     stream->writeInt(getBufferVariables().size());
1022*8975f5c5SAndroid Build Coastguard Worker     for (const BufferVariable &bufferVariable : getBufferVariables())
1023*8975f5c5SAndroid Build Coastguard Worker     {
1024*8975f5c5SAndroid Build Coastguard Worker         WriteBufferVariable(stream, bufferVariable);
1025*8975f5c5SAndroid Build Coastguard Worker     }
1026*8975f5c5SAndroid Build Coastguard Worker 
1027*8975f5c5SAndroid Build Coastguard Worker     stream->writeInt(getLinkedTransformFeedbackVaryings().size());
1028*8975f5c5SAndroid Build Coastguard Worker     for (const auto &var : getLinkedTransformFeedbackVaryings())
1029*8975f5c5SAndroid Build Coastguard Worker     {
1030*8975f5c5SAndroid Build Coastguard Worker         stream->writeVector(var.arraySizes);
1031*8975f5c5SAndroid Build Coastguard Worker         stream->writeInt(var.type);
1032*8975f5c5SAndroid Build Coastguard Worker         stream->writeString(var.name);
1033*8975f5c5SAndroid Build Coastguard Worker 
1034*8975f5c5SAndroid Build Coastguard Worker         stream->writeIntOrNegOne(var.arrayIndex);
1035*8975f5c5SAndroid Build Coastguard Worker     }
1036*8975f5c5SAndroid Build Coastguard Worker 
1037*8975f5c5SAndroid Build Coastguard Worker     stream->writeInt(getOutputVariables().size());
1038*8975f5c5SAndroid Build Coastguard Worker     for (const ProgramOutput &output : getOutputVariables())
1039*8975f5c5SAndroid Build Coastguard Worker     {
1040*8975f5c5SAndroid Build Coastguard Worker         stream->writeString(output.name);
1041*8975f5c5SAndroid Build Coastguard Worker         stream->writeString(output.mappedName);
1042*8975f5c5SAndroid Build Coastguard Worker         stream->writeStruct(output.pod);
1043*8975f5c5SAndroid Build Coastguard Worker     }
1044*8975f5c5SAndroid Build Coastguard Worker 
1045*8975f5c5SAndroid Build Coastguard Worker     stream->writeVector(mOutputLocations);
1046*8975f5c5SAndroid Build Coastguard Worker     stream->writeVector(mSecondaryOutputLocations);
1047*8975f5c5SAndroid Build Coastguard Worker     SaveSamplerBindings(stream, mSamplerBindings, mSamplerBoundTextureUnits);
1048*8975f5c5SAndroid Build Coastguard Worker 
1049*8975f5c5SAndroid Build Coastguard Worker     stream->writeInt(getImageBindings().size());
1050*8975f5c5SAndroid Build Coastguard Worker     for (const auto &imageBinding : getImageBindings())
1051*8975f5c5SAndroid Build Coastguard Worker     {
1052*8975f5c5SAndroid Build Coastguard Worker         stream->writeInt(imageBinding.boundImageUnits.size());
1053*8975f5c5SAndroid Build Coastguard Worker         stream->writeInt(static_cast<unsigned int>(imageBinding.textureType));
1054*8975f5c5SAndroid Build Coastguard Worker         for (size_t i = 0; i < imageBinding.boundImageUnits.size(); ++i)
1055*8975f5c5SAndroid Build Coastguard Worker         {
1056*8975f5c5SAndroid Build Coastguard Worker             stream->writeInt(imageBinding.boundImageUnits[i]);
1057*8975f5c5SAndroid Build Coastguard Worker         }
1058*8975f5c5SAndroid Build Coastguard Worker     }
1059*8975f5c5SAndroid Build Coastguard Worker 
1060*8975f5c5SAndroid Build Coastguard Worker     // ANGLE_shader_pixel_local_storage.
1061*8975f5c5SAndroid Build Coastguard Worker     stream->writeInt<size_t>(mPixelLocalStorageFormats.size());
1062*8975f5c5SAndroid Build Coastguard Worker     stream->writeBytes(reinterpret_cast<const uint8_t *>(mPixelLocalStorageFormats.data()),
1063*8975f5c5SAndroid Build Coastguard Worker                        mPixelLocalStorageFormats.size());
1064*8975f5c5SAndroid Build Coastguard Worker 
1065*8975f5c5SAndroid Build Coastguard Worker     // These values are currently only used by PPOs, so only save them when the program is marked
1066*8975f5c5SAndroid Build Coastguard Worker     // separable to save memory.
1067*8975f5c5SAndroid Build Coastguard Worker     if (mPod.isSeparable)
1068*8975f5c5SAndroid Build Coastguard Worker     {
1069*8975f5c5SAndroid Build Coastguard Worker         for (ShaderType shaderType : getLinkedShaderStages())
1070*8975f5c5SAndroid Build Coastguard Worker         {
1071*8975f5c5SAndroid Build Coastguard Worker             stream->writeInt(mLinkedOutputVaryings[shaderType].size());
1072*8975f5c5SAndroid Build Coastguard Worker             for (const sh::ShaderVariable &shaderVariable : mLinkedOutputVaryings[shaderType])
1073*8975f5c5SAndroid Build Coastguard Worker             {
1074*8975f5c5SAndroid Build Coastguard Worker                 WriteShaderVar(stream, shaderVariable);
1075*8975f5c5SAndroid Build Coastguard Worker             }
1076*8975f5c5SAndroid Build Coastguard Worker             stream->writeInt(mLinkedInputVaryings[shaderType].size());
1077*8975f5c5SAndroid Build Coastguard Worker             for (const sh::ShaderVariable &shaderVariable : mLinkedInputVaryings[shaderType])
1078*8975f5c5SAndroid Build Coastguard Worker             {
1079*8975f5c5SAndroid Build Coastguard Worker                 WriteShaderVar(stream, shaderVariable);
1080*8975f5c5SAndroid Build Coastguard Worker             }
1081*8975f5c5SAndroid Build Coastguard Worker             stream->writeInt(mLinkedUniforms[shaderType].size());
1082*8975f5c5SAndroid Build Coastguard Worker             for (const sh::ShaderVariable &shaderVariable : mLinkedUniforms[shaderType])
1083*8975f5c5SAndroid Build Coastguard Worker             {
1084*8975f5c5SAndroid Build Coastguard Worker                 WriteShaderVar(stream, shaderVariable);
1085*8975f5c5SAndroid Build Coastguard Worker             }
1086*8975f5c5SAndroid Build Coastguard Worker             stream->writeInt(mLinkedUniformBlocks[shaderType].size());
1087*8975f5c5SAndroid Build Coastguard Worker             for (const sh::InterfaceBlock &shaderStorageBlock : mLinkedUniformBlocks[shaderType])
1088*8975f5c5SAndroid Build Coastguard Worker             {
1089*8975f5c5SAndroid Build Coastguard Worker                 WriteShInterfaceBlock(stream, shaderStorageBlock);
1090*8975f5c5SAndroid Build Coastguard Worker             }
1091*8975f5c5SAndroid Build Coastguard Worker         }
1092*8975f5c5SAndroid Build Coastguard Worker     }
1093*8975f5c5SAndroid Build Coastguard Worker }
1094*8975f5c5SAndroid Build Coastguard Worker 
getInfoLogString() const1095*8975f5c5SAndroid Build Coastguard Worker std::string ProgramExecutable::getInfoLogString() const
1096*8975f5c5SAndroid Build Coastguard Worker {
1097*8975f5c5SAndroid Build Coastguard Worker     return mInfoLog->str();
1098*8975f5c5SAndroid Build Coastguard Worker }
1099*8975f5c5SAndroid Build Coastguard Worker 
getFirstLinkedShaderStageType() const1100*8975f5c5SAndroid Build Coastguard Worker ShaderType ProgramExecutable::getFirstLinkedShaderStageType() const
1101*8975f5c5SAndroid Build Coastguard Worker {
1102*8975f5c5SAndroid Build Coastguard Worker     const ShaderBitSet linkedStages = mPod.linkedShaderStages;
1103*8975f5c5SAndroid Build Coastguard Worker     if (linkedStages.none())
1104*8975f5c5SAndroid Build Coastguard Worker     {
1105*8975f5c5SAndroid Build Coastguard Worker         return ShaderType::InvalidEnum;
1106*8975f5c5SAndroid Build Coastguard Worker     }
1107*8975f5c5SAndroid Build Coastguard Worker 
1108*8975f5c5SAndroid Build Coastguard Worker     return linkedStages.first();
1109*8975f5c5SAndroid Build Coastguard Worker }
1110*8975f5c5SAndroid Build Coastguard Worker 
getLastLinkedShaderStageType() const1111*8975f5c5SAndroid Build Coastguard Worker ShaderType ProgramExecutable::getLastLinkedShaderStageType() const
1112*8975f5c5SAndroid Build Coastguard Worker {
1113*8975f5c5SAndroid Build Coastguard Worker     const ShaderBitSet linkedStages = mPod.linkedShaderStages;
1114*8975f5c5SAndroid Build Coastguard Worker     if (linkedStages.none())
1115*8975f5c5SAndroid Build Coastguard Worker     {
1116*8975f5c5SAndroid Build Coastguard Worker         return ShaderType::InvalidEnum;
1117*8975f5c5SAndroid Build Coastguard Worker     }
1118*8975f5c5SAndroid Build Coastguard Worker 
1119*8975f5c5SAndroid Build Coastguard Worker     return linkedStages.last();
1120*8975f5c5SAndroid Build Coastguard Worker }
1121*8975f5c5SAndroid Build Coastguard Worker 
setActive(size_t textureUnit,const SamplerBinding & samplerBinding,const gl::LinkedUniform & samplerUniform)1122*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::setActive(size_t textureUnit,
1123*8975f5c5SAndroid Build Coastguard Worker                                   const SamplerBinding &samplerBinding,
1124*8975f5c5SAndroid Build Coastguard Worker                                   const gl::LinkedUniform &samplerUniform)
1125*8975f5c5SAndroid Build Coastguard Worker {
1126*8975f5c5SAndroid Build Coastguard Worker     mActiveSamplersMask.set(textureUnit);
1127*8975f5c5SAndroid Build Coastguard Worker     mActiveSamplerTypes[textureUnit]      = samplerBinding.textureType;
1128*8975f5c5SAndroid Build Coastguard Worker     mActiveSamplerYUV[textureUnit]        = IsSamplerYUVType(samplerBinding.samplerType);
1129*8975f5c5SAndroid Build Coastguard Worker     mActiveSamplerFormats[textureUnit]    = samplerBinding.format;
1130*8975f5c5SAndroid Build Coastguard Worker     mActiveSamplerShaderBits[textureUnit] = samplerUniform.activeShaders();
1131*8975f5c5SAndroid Build Coastguard Worker }
1132*8975f5c5SAndroid Build Coastguard Worker 
setInactive(size_t textureUnit)1133*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::setInactive(size_t textureUnit)
1134*8975f5c5SAndroid Build Coastguard Worker {
1135*8975f5c5SAndroid Build Coastguard Worker     mActiveSamplersMask.reset(textureUnit);
1136*8975f5c5SAndroid Build Coastguard Worker     mActiveSamplerTypes[textureUnit] = TextureType::InvalidEnum;
1137*8975f5c5SAndroid Build Coastguard Worker     mActiveSamplerYUV.reset(textureUnit);
1138*8975f5c5SAndroid Build Coastguard Worker     mActiveSamplerFormats[textureUnit] = SamplerFormat::InvalidEnum;
1139*8975f5c5SAndroid Build Coastguard Worker     mActiveSamplerShaderBits[textureUnit].reset();
1140*8975f5c5SAndroid Build Coastguard Worker }
1141*8975f5c5SAndroid Build Coastguard Worker 
hasSamplerTypeConflict(size_t textureUnit)1142*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::hasSamplerTypeConflict(size_t textureUnit)
1143*8975f5c5SAndroid Build Coastguard Worker {
1144*8975f5c5SAndroid Build Coastguard Worker     // Conflicts are marked with InvalidEnum
1145*8975f5c5SAndroid Build Coastguard Worker     mActiveSamplerYUV.reset(textureUnit);
1146*8975f5c5SAndroid Build Coastguard Worker     mActiveSamplerTypes[textureUnit] = TextureType::InvalidEnum;
1147*8975f5c5SAndroid Build Coastguard Worker }
1148*8975f5c5SAndroid Build Coastguard Worker 
hasSamplerFormatConflict(size_t textureUnit)1149*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::hasSamplerFormatConflict(size_t textureUnit)
1150*8975f5c5SAndroid Build Coastguard Worker {
1151*8975f5c5SAndroid Build Coastguard Worker     // Conflicts are marked with InvalidEnum
1152*8975f5c5SAndroid Build Coastguard Worker     mActiveSamplerFormats[textureUnit] = SamplerFormat::InvalidEnum;
1153*8975f5c5SAndroid Build Coastguard Worker }
1154*8975f5c5SAndroid Build Coastguard Worker 
updateActiveSamplers(const ProgramExecutable & executable)1155*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::updateActiveSamplers(const ProgramExecutable &executable)
1156*8975f5c5SAndroid Build Coastguard Worker {
1157*8975f5c5SAndroid Build Coastguard Worker     const std::vector<SamplerBinding> &samplerBindings = executable.getSamplerBindings();
1158*8975f5c5SAndroid Build Coastguard Worker     const std::vector<GLuint> &boundTextureUnits       = executable.getSamplerBoundTextureUnits();
1159*8975f5c5SAndroid Build Coastguard Worker 
1160*8975f5c5SAndroid Build Coastguard Worker     for (uint32_t samplerIndex = 0; samplerIndex < samplerBindings.size(); ++samplerIndex)
1161*8975f5c5SAndroid Build Coastguard Worker     {
1162*8975f5c5SAndroid Build Coastguard Worker         const SamplerBinding &samplerBinding = samplerBindings[samplerIndex];
1163*8975f5c5SAndroid Build Coastguard Worker 
1164*8975f5c5SAndroid Build Coastguard Worker         for (uint16_t index = 0; index < samplerBinding.textureUnitsCount; index++)
1165*8975f5c5SAndroid Build Coastguard Worker         {
1166*8975f5c5SAndroid Build Coastguard Worker             GLint textureUnit = samplerBinding.getTextureUnit(boundTextureUnits, index);
1167*8975f5c5SAndroid Build Coastguard Worker             if (++mActiveSamplerRefCounts[textureUnit] == 1)
1168*8975f5c5SAndroid Build Coastguard Worker             {
1169*8975f5c5SAndroid Build Coastguard Worker                 uint32_t uniformIndex = executable.getUniformIndexFromSamplerIndex(samplerIndex);
1170*8975f5c5SAndroid Build Coastguard Worker                 setActive(textureUnit, samplerBinding, executable.getUniforms()[uniformIndex]);
1171*8975f5c5SAndroid Build Coastguard Worker             }
1172*8975f5c5SAndroid Build Coastguard Worker             else
1173*8975f5c5SAndroid Build Coastguard Worker             {
1174*8975f5c5SAndroid Build Coastguard Worker                 if (mActiveSamplerTypes[textureUnit] != samplerBinding.textureType ||
1175*8975f5c5SAndroid Build Coastguard Worker                     mActiveSamplerYUV.test(textureUnit) !=
1176*8975f5c5SAndroid Build Coastguard Worker                         IsSamplerYUVType(samplerBinding.samplerType))
1177*8975f5c5SAndroid Build Coastguard Worker                 {
1178*8975f5c5SAndroid Build Coastguard Worker                     hasSamplerTypeConflict(textureUnit);
1179*8975f5c5SAndroid Build Coastguard Worker                 }
1180*8975f5c5SAndroid Build Coastguard Worker 
1181*8975f5c5SAndroid Build Coastguard Worker                 if (mActiveSamplerFormats[textureUnit] != samplerBinding.format)
1182*8975f5c5SAndroid Build Coastguard Worker                 {
1183*8975f5c5SAndroid Build Coastguard Worker                     hasSamplerFormatConflict(textureUnit);
1184*8975f5c5SAndroid Build Coastguard Worker                 }
1185*8975f5c5SAndroid Build Coastguard Worker             }
1186*8975f5c5SAndroid Build Coastguard Worker             mActiveSamplersMask.set(textureUnit);
1187*8975f5c5SAndroid Build Coastguard Worker         }
1188*8975f5c5SAndroid Build Coastguard Worker     }
1189*8975f5c5SAndroid Build Coastguard Worker 
1190*8975f5c5SAndroid Build Coastguard Worker     // Invalidate the validation cache.
1191*8975f5c5SAndroid Build Coastguard Worker     resetCachedValidateSamplersResult();
1192*8975f5c5SAndroid Build Coastguard Worker }
1193*8975f5c5SAndroid Build Coastguard Worker 
updateActiveImages(const ProgramExecutable & executable)1194*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::updateActiveImages(const ProgramExecutable &executable)
1195*8975f5c5SAndroid Build Coastguard Worker {
1196*8975f5c5SAndroid Build Coastguard Worker     const std::vector<ImageBinding> &imageBindings = executable.getImageBindings();
1197*8975f5c5SAndroid Build Coastguard Worker     for (uint32_t imageIndex = 0; imageIndex < imageBindings.size(); ++imageIndex)
1198*8975f5c5SAndroid Build Coastguard Worker     {
1199*8975f5c5SAndroid Build Coastguard Worker         const gl::ImageBinding &imageBinding = imageBindings.at(imageIndex);
1200*8975f5c5SAndroid Build Coastguard Worker 
1201*8975f5c5SAndroid Build Coastguard Worker         uint32_t uniformIndex = executable.getUniformIndexFromImageIndex(imageIndex);
1202*8975f5c5SAndroid Build Coastguard Worker         const gl::LinkedUniform &imageUniform = executable.getUniforms()[uniformIndex];
1203*8975f5c5SAndroid Build Coastguard Worker         const ShaderBitSet shaderBits         = imageUniform.activeShaders();
1204*8975f5c5SAndroid Build Coastguard Worker         for (GLint imageUnit : imageBinding.boundImageUnits)
1205*8975f5c5SAndroid Build Coastguard Worker         {
1206*8975f5c5SAndroid Build Coastguard Worker             mActiveImagesMask.set(imageUnit);
1207*8975f5c5SAndroid Build Coastguard Worker             mActiveImageShaderBits[imageUnit] |= shaderBits;
1208*8975f5c5SAndroid Build Coastguard Worker         }
1209*8975f5c5SAndroid Build Coastguard Worker     }
1210*8975f5c5SAndroid Build Coastguard Worker }
1211*8975f5c5SAndroid Build Coastguard Worker 
setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex)1212*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex)
1213*8975f5c5SAndroid Build Coastguard Worker {
1214*8975f5c5SAndroid Build Coastguard Worker     bool foundBinding         = false;
1215*8975f5c5SAndroid Build Coastguard Worker     TextureType foundType     = TextureType::InvalidEnum;
1216*8975f5c5SAndroid Build Coastguard Worker     bool foundYUV             = false;
1217*8975f5c5SAndroid Build Coastguard Worker     SamplerFormat foundFormat = SamplerFormat::InvalidEnum;
1218*8975f5c5SAndroid Build Coastguard Worker 
1219*8975f5c5SAndroid Build Coastguard Worker     for (uint32_t samplerIndex = 0; samplerIndex < mSamplerBindings.size(); ++samplerIndex)
1220*8975f5c5SAndroid Build Coastguard Worker     {
1221*8975f5c5SAndroid Build Coastguard Worker         const SamplerBinding &binding = mSamplerBindings[samplerIndex];
1222*8975f5c5SAndroid Build Coastguard Worker 
1223*8975f5c5SAndroid Build Coastguard Worker         // A conflict exists if samplers of different types are sourced by the same texture unit.
1224*8975f5c5SAndroid Build Coastguard Worker         // We need to check all bound textures to detect this error case.
1225*8975f5c5SAndroid Build Coastguard Worker         for (uint16_t index = 0; index < binding.textureUnitsCount; index++)
1226*8975f5c5SAndroid Build Coastguard Worker         {
1227*8975f5c5SAndroid Build Coastguard Worker             GLuint textureUnit = binding.getTextureUnit(mSamplerBoundTextureUnits, index);
1228*8975f5c5SAndroid Build Coastguard Worker             if (textureUnit != textureUnitIndex)
1229*8975f5c5SAndroid Build Coastguard Worker             {
1230*8975f5c5SAndroid Build Coastguard Worker                 continue;
1231*8975f5c5SAndroid Build Coastguard Worker             }
1232*8975f5c5SAndroid Build Coastguard Worker 
1233*8975f5c5SAndroid Build Coastguard Worker             if (!foundBinding)
1234*8975f5c5SAndroid Build Coastguard Worker             {
1235*8975f5c5SAndroid Build Coastguard Worker                 foundBinding          = true;
1236*8975f5c5SAndroid Build Coastguard Worker                 foundType             = binding.textureType;
1237*8975f5c5SAndroid Build Coastguard Worker                 foundYUV              = IsSamplerYUVType(binding.samplerType);
1238*8975f5c5SAndroid Build Coastguard Worker                 foundFormat           = binding.format;
1239*8975f5c5SAndroid Build Coastguard Worker                 uint32_t uniformIndex = getUniformIndexFromSamplerIndex(samplerIndex);
1240*8975f5c5SAndroid Build Coastguard Worker                 setActive(textureUnit, binding, mUniforms[uniformIndex]);
1241*8975f5c5SAndroid Build Coastguard Worker             }
1242*8975f5c5SAndroid Build Coastguard Worker             else
1243*8975f5c5SAndroid Build Coastguard Worker             {
1244*8975f5c5SAndroid Build Coastguard Worker                 if (foundType != binding.textureType ||
1245*8975f5c5SAndroid Build Coastguard Worker                     foundYUV != IsSamplerYUVType(binding.samplerType))
1246*8975f5c5SAndroid Build Coastguard Worker                 {
1247*8975f5c5SAndroid Build Coastguard Worker                     hasSamplerTypeConflict(textureUnit);
1248*8975f5c5SAndroid Build Coastguard Worker                 }
1249*8975f5c5SAndroid Build Coastguard Worker 
1250*8975f5c5SAndroid Build Coastguard Worker                 if (foundFormat != binding.format)
1251*8975f5c5SAndroid Build Coastguard Worker                 {
1252*8975f5c5SAndroid Build Coastguard Worker                     hasSamplerFormatConflict(textureUnit);
1253*8975f5c5SAndroid Build Coastguard Worker                 }
1254*8975f5c5SAndroid Build Coastguard Worker             }
1255*8975f5c5SAndroid Build Coastguard Worker         }
1256*8975f5c5SAndroid Build Coastguard Worker     }
1257*8975f5c5SAndroid Build Coastguard Worker }
1258*8975f5c5SAndroid Build Coastguard Worker 
saveLinkedStateInfo(const ProgramState & state)1259*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::saveLinkedStateInfo(const ProgramState &state)
1260*8975f5c5SAndroid Build Coastguard Worker {
1261*8975f5c5SAndroid Build Coastguard Worker     for (ShaderType shaderType : getLinkedShaderStages())
1262*8975f5c5SAndroid Build Coastguard Worker     {
1263*8975f5c5SAndroid Build Coastguard Worker         const SharedCompiledShaderState &shader = state.getAttachedShader(shaderType);
1264*8975f5c5SAndroid Build Coastguard Worker         ASSERT(shader);
1265*8975f5c5SAndroid Build Coastguard Worker         mPod.linkedShaderVersions[shaderType] = shader->shaderVersion;
1266*8975f5c5SAndroid Build Coastguard Worker         mLinkedOutputVaryings[shaderType]     = shader->outputVaryings;
1267*8975f5c5SAndroid Build Coastguard Worker         mLinkedInputVaryings[shaderType]      = shader->inputVaryings;
1268*8975f5c5SAndroid Build Coastguard Worker         mLinkedUniforms[shaderType]           = shader->uniforms;
1269*8975f5c5SAndroid Build Coastguard Worker         mLinkedUniformBlocks[shaderType]      = shader->uniformBlocks;
1270*8975f5c5SAndroid Build Coastguard Worker     }
1271*8975f5c5SAndroid Build Coastguard Worker }
1272*8975f5c5SAndroid Build Coastguard Worker 
linkMergedVaryings(const Caps & caps,const Limitations & limitations,const Version & clientVersion,bool webglCompatibility,const ProgramMergedVaryings & mergedVaryings,const LinkingVariables & linkingVariables,ProgramVaryingPacking * varyingPacking)1273*8975f5c5SAndroid Build Coastguard Worker bool ProgramExecutable::linkMergedVaryings(const Caps &caps,
1274*8975f5c5SAndroid Build Coastguard Worker                                            const Limitations &limitations,
1275*8975f5c5SAndroid Build Coastguard Worker                                            const Version &clientVersion,
1276*8975f5c5SAndroid Build Coastguard Worker                                            bool webglCompatibility,
1277*8975f5c5SAndroid Build Coastguard Worker                                            const ProgramMergedVaryings &mergedVaryings,
1278*8975f5c5SAndroid Build Coastguard Worker                                            const LinkingVariables &linkingVariables,
1279*8975f5c5SAndroid Build Coastguard Worker                                            ProgramVaryingPacking *varyingPacking)
1280*8975f5c5SAndroid Build Coastguard Worker {
1281*8975f5c5SAndroid Build Coastguard Worker     ShaderType tfStage = GetLastPreFragmentStage(linkingVariables.isShaderStageUsedBitset);
1282*8975f5c5SAndroid Build Coastguard Worker 
1283*8975f5c5SAndroid Build Coastguard Worker     if (!linkValidateTransformFeedback(caps, clientVersion, mergedVaryings, tfStage))
1284*8975f5c5SAndroid Build Coastguard Worker     {
1285*8975f5c5SAndroid Build Coastguard Worker         return false;
1286*8975f5c5SAndroid Build Coastguard Worker     }
1287*8975f5c5SAndroid Build Coastguard Worker 
1288*8975f5c5SAndroid Build Coastguard Worker     // Map the varyings to the register file
1289*8975f5c5SAndroid Build Coastguard Worker     // In WebGL, we use a slightly different handling for packing variables.
1290*8975f5c5SAndroid Build Coastguard Worker     gl::PackMode packMode = PackMode::ANGLE_RELAXED;
1291*8975f5c5SAndroid Build Coastguard Worker     if (limitations.noFlexibleVaryingPacking)
1292*8975f5c5SAndroid Build Coastguard Worker     {
1293*8975f5c5SAndroid Build Coastguard Worker         // D3D9 pack mode is strictly more strict than WebGL, so takes priority.
1294*8975f5c5SAndroid Build Coastguard Worker         packMode = PackMode::ANGLE_NON_CONFORMANT_D3D9;
1295*8975f5c5SAndroid Build Coastguard Worker     }
1296*8975f5c5SAndroid Build Coastguard Worker     else if (webglCompatibility)
1297*8975f5c5SAndroid Build Coastguard Worker     {
1298*8975f5c5SAndroid Build Coastguard Worker         packMode = PackMode::WEBGL_STRICT;
1299*8975f5c5SAndroid Build Coastguard Worker     }
1300*8975f5c5SAndroid Build Coastguard Worker 
1301*8975f5c5SAndroid Build Coastguard Worker     // Build active shader stage map.
1302*8975f5c5SAndroid Build Coastguard Worker     ShaderBitSet activeShadersMask;
1303*8975f5c5SAndroid Build Coastguard Worker     for (ShaderType shaderType : kAllGraphicsShaderTypes)
1304*8975f5c5SAndroid Build Coastguard Worker     {
1305*8975f5c5SAndroid Build Coastguard Worker         // - Check for attached shaders to handle the case of a Program linking the currently
1306*8975f5c5SAndroid Build Coastguard Worker         // attached shaders.
1307*8975f5c5SAndroid Build Coastguard Worker         // - Check for linked shaders to handle the case of a PPO linking separable programs before
1308*8975f5c5SAndroid Build Coastguard Worker         // drawing.
1309*8975f5c5SAndroid Build Coastguard Worker         if (linkingVariables.isShaderStageUsedBitset[shaderType] ||
1310*8975f5c5SAndroid Build Coastguard Worker             getLinkedShaderStages().test(shaderType))
1311*8975f5c5SAndroid Build Coastguard Worker         {
1312*8975f5c5SAndroid Build Coastguard Worker             activeShadersMask[shaderType] = true;
1313*8975f5c5SAndroid Build Coastguard Worker         }
1314*8975f5c5SAndroid Build Coastguard Worker     }
1315*8975f5c5SAndroid Build Coastguard Worker 
1316*8975f5c5SAndroid Build Coastguard Worker     if (!varyingPacking->collectAndPackUserVaryings(*mInfoLog, caps, packMode, activeShadersMask,
1317*8975f5c5SAndroid Build Coastguard Worker                                                     mergedVaryings, mTransformFeedbackVaryingNames,
1318*8975f5c5SAndroid Build Coastguard Worker                                                     mPod.isSeparable))
1319*8975f5c5SAndroid Build Coastguard Worker     {
1320*8975f5c5SAndroid Build Coastguard Worker         return false;
1321*8975f5c5SAndroid Build Coastguard Worker     }
1322*8975f5c5SAndroid Build Coastguard Worker 
1323*8975f5c5SAndroid Build Coastguard Worker     gatherTransformFeedbackVaryings(mergedVaryings, tfStage);
1324*8975f5c5SAndroid Build Coastguard Worker     updateTransformFeedbackStrides();
1325*8975f5c5SAndroid Build Coastguard Worker 
1326*8975f5c5SAndroid Build Coastguard Worker     return true;
1327*8975f5c5SAndroid Build Coastguard Worker }
1328*8975f5c5SAndroid Build Coastguard Worker 
linkValidateTransformFeedback(const Caps & caps,const Version & clientVersion,const ProgramMergedVaryings & varyings,ShaderType stage)1329*8975f5c5SAndroid Build Coastguard Worker bool ProgramExecutable::linkValidateTransformFeedback(const Caps &caps,
1330*8975f5c5SAndroid Build Coastguard Worker                                                       const Version &clientVersion,
1331*8975f5c5SAndroid Build Coastguard Worker                                                       const ProgramMergedVaryings &varyings,
1332*8975f5c5SAndroid Build Coastguard Worker                                                       ShaderType stage)
1333*8975f5c5SAndroid Build Coastguard Worker {
1334*8975f5c5SAndroid Build Coastguard Worker     // Validate the tf names regardless of the actual program varyings.
1335*8975f5c5SAndroid Build Coastguard Worker     std::set<std::string> uniqueNames;
1336*8975f5c5SAndroid Build Coastguard Worker     for (const std::string &tfVaryingName : mTransformFeedbackVaryingNames)
1337*8975f5c5SAndroid Build Coastguard Worker     {
1338*8975f5c5SAndroid Build Coastguard Worker         if (clientVersion < Version(3, 1) && tfVaryingName.find('[') != std::string::npos)
1339*8975f5c5SAndroid Build Coastguard Worker         {
1340*8975f5c5SAndroid Build Coastguard Worker             *mInfoLog << "Capture of array elements is undefined and not supported.";
1341*8975f5c5SAndroid Build Coastguard Worker             return false;
1342*8975f5c5SAndroid Build Coastguard Worker         }
1343*8975f5c5SAndroid Build Coastguard Worker         if (clientVersion >= Version(3, 1))
1344*8975f5c5SAndroid Build Coastguard Worker         {
1345*8975f5c5SAndroid Build Coastguard Worker             if (IncludeSameArrayElement(uniqueNames, tfVaryingName))
1346*8975f5c5SAndroid Build Coastguard Worker             {
1347*8975f5c5SAndroid Build Coastguard Worker                 *mInfoLog << "Two transform feedback varyings include the same array element ("
1348*8975f5c5SAndroid Build Coastguard Worker                           << tfVaryingName << ").";
1349*8975f5c5SAndroid Build Coastguard Worker                 return false;
1350*8975f5c5SAndroid Build Coastguard Worker             }
1351*8975f5c5SAndroid Build Coastguard Worker         }
1352*8975f5c5SAndroid Build Coastguard Worker         else
1353*8975f5c5SAndroid Build Coastguard Worker         {
1354*8975f5c5SAndroid Build Coastguard Worker             if (uniqueNames.count(tfVaryingName) > 0)
1355*8975f5c5SAndroid Build Coastguard Worker             {
1356*8975f5c5SAndroid Build Coastguard Worker                 *mInfoLog << "Two transform feedback varyings specify the same output variable ("
1357*8975f5c5SAndroid Build Coastguard Worker                           << tfVaryingName << ").";
1358*8975f5c5SAndroid Build Coastguard Worker                 return false;
1359*8975f5c5SAndroid Build Coastguard Worker             }
1360*8975f5c5SAndroid Build Coastguard Worker         }
1361*8975f5c5SAndroid Build Coastguard Worker         uniqueNames.insert(tfVaryingName);
1362*8975f5c5SAndroid Build Coastguard Worker     }
1363*8975f5c5SAndroid Build Coastguard Worker 
1364*8975f5c5SAndroid Build Coastguard Worker     // From OpneGLES spec. 11.1.2.1: A program will fail to link if:
1365*8975f5c5SAndroid Build Coastguard Worker     // the count specified by TransformFeedbackVaryings is non-zero, but the
1366*8975f5c5SAndroid Build Coastguard Worker     // program object has no vertex, tessellation evaluation, or geometry shader
1367*8975f5c5SAndroid Build Coastguard Worker     if (mTransformFeedbackVaryingNames.size() > 0 &&
1368*8975f5c5SAndroid Build Coastguard Worker         !gl::ShaderTypeSupportsTransformFeedback(getLinkedTransformFeedbackStage()))
1369*8975f5c5SAndroid Build Coastguard Worker     {
1370*8975f5c5SAndroid Build Coastguard Worker         *mInfoLog << "Linked transform feedback stage " << getLinkedTransformFeedbackStage()
1371*8975f5c5SAndroid Build Coastguard Worker                   << " does not support transform feedback varying.";
1372*8975f5c5SAndroid Build Coastguard Worker         return false;
1373*8975f5c5SAndroid Build Coastguard Worker     }
1374*8975f5c5SAndroid Build Coastguard Worker 
1375*8975f5c5SAndroid Build Coastguard Worker     // Validate against program varyings.
1376*8975f5c5SAndroid Build Coastguard Worker     size_t totalComponents = 0;
1377*8975f5c5SAndroid Build Coastguard Worker     for (const std::string &tfVaryingName : mTransformFeedbackVaryingNames)
1378*8975f5c5SAndroid Build Coastguard Worker     {
1379*8975f5c5SAndroid Build Coastguard Worker         std::vector<unsigned int> subscripts;
1380*8975f5c5SAndroid Build Coastguard Worker         std::string baseName = ParseResourceName(tfVaryingName, &subscripts);
1381*8975f5c5SAndroid Build Coastguard Worker 
1382*8975f5c5SAndroid Build Coastguard Worker         const sh::ShaderVariable *var = FindOutputVaryingOrField(varyings, stage, baseName);
1383*8975f5c5SAndroid Build Coastguard Worker         if (var == nullptr)
1384*8975f5c5SAndroid Build Coastguard Worker         {
1385*8975f5c5SAndroid Build Coastguard Worker             *mInfoLog << "Transform feedback varying " << tfVaryingName
1386*8975f5c5SAndroid Build Coastguard Worker                       << " does not exist in the vertex shader.";
1387*8975f5c5SAndroid Build Coastguard Worker             return false;
1388*8975f5c5SAndroid Build Coastguard Worker         }
1389*8975f5c5SAndroid Build Coastguard Worker 
1390*8975f5c5SAndroid Build Coastguard Worker         // Validate the matching variable.
1391*8975f5c5SAndroid Build Coastguard Worker         if (var->isStruct())
1392*8975f5c5SAndroid Build Coastguard Worker         {
1393*8975f5c5SAndroid Build Coastguard Worker             *mInfoLog << "Struct cannot be captured directly (" << baseName << ").";
1394*8975f5c5SAndroid Build Coastguard Worker             return false;
1395*8975f5c5SAndroid Build Coastguard Worker         }
1396*8975f5c5SAndroid Build Coastguard Worker 
1397*8975f5c5SAndroid Build Coastguard Worker         size_t elementCount   = 0;
1398*8975f5c5SAndroid Build Coastguard Worker         size_t componentCount = 0;
1399*8975f5c5SAndroid Build Coastguard Worker 
1400*8975f5c5SAndroid Build Coastguard Worker         if (var->isArray())
1401*8975f5c5SAndroid Build Coastguard Worker         {
1402*8975f5c5SAndroid Build Coastguard Worker             if (clientVersion < Version(3, 1))
1403*8975f5c5SAndroid Build Coastguard Worker             {
1404*8975f5c5SAndroid Build Coastguard Worker                 *mInfoLog << "Capture of arrays is undefined and not supported.";
1405*8975f5c5SAndroid Build Coastguard Worker                 return false;
1406*8975f5c5SAndroid Build Coastguard Worker             }
1407*8975f5c5SAndroid Build Coastguard Worker 
1408*8975f5c5SAndroid Build Coastguard Worker             // GLSL ES 3.10 section 4.3.6: A vertex output can't be an array of arrays.
1409*8975f5c5SAndroid Build Coastguard Worker             ASSERT(!var->isArrayOfArrays());
1410*8975f5c5SAndroid Build Coastguard Worker 
1411*8975f5c5SAndroid Build Coastguard Worker             if (!subscripts.empty() && subscripts[0] >= var->getOutermostArraySize())
1412*8975f5c5SAndroid Build Coastguard Worker             {
1413*8975f5c5SAndroid Build Coastguard Worker                 *mInfoLog << "Cannot capture outbound array element '" << tfVaryingName << "'.";
1414*8975f5c5SAndroid Build Coastguard Worker                 return false;
1415*8975f5c5SAndroid Build Coastguard Worker             }
1416*8975f5c5SAndroid Build Coastguard Worker             elementCount = (subscripts.empty() ? var->getOutermostArraySize() : 1);
1417*8975f5c5SAndroid Build Coastguard Worker         }
1418*8975f5c5SAndroid Build Coastguard Worker         else
1419*8975f5c5SAndroid Build Coastguard Worker         {
1420*8975f5c5SAndroid Build Coastguard Worker             if (!subscripts.empty())
1421*8975f5c5SAndroid Build Coastguard Worker             {
1422*8975f5c5SAndroid Build Coastguard Worker                 *mInfoLog << "Varying '" << baseName
1423*8975f5c5SAndroid Build Coastguard Worker                           << "' is not an array to be captured by element.";
1424*8975f5c5SAndroid Build Coastguard Worker                 return false;
1425*8975f5c5SAndroid Build Coastguard Worker             }
1426*8975f5c5SAndroid Build Coastguard Worker             elementCount = 1;
1427*8975f5c5SAndroid Build Coastguard Worker         }
1428*8975f5c5SAndroid Build Coastguard Worker 
1429*8975f5c5SAndroid Build Coastguard Worker         componentCount = VariableComponentCount(var->type) * elementCount;
1430*8975f5c5SAndroid Build Coastguard Worker         if (mPod.transformFeedbackBufferMode == GL_SEPARATE_ATTRIBS &&
1431*8975f5c5SAndroid Build Coastguard Worker             componentCount > static_cast<GLuint>(caps.maxTransformFeedbackSeparateComponents))
1432*8975f5c5SAndroid Build Coastguard Worker         {
1433*8975f5c5SAndroid Build Coastguard Worker             *mInfoLog << "Transform feedback varying " << tfVaryingName << " components ("
1434*8975f5c5SAndroid Build Coastguard Worker                       << componentCount << ") exceed the maximum separate components ("
1435*8975f5c5SAndroid Build Coastguard Worker                       << caps.maxTransformFeedbackSeparateComponents << ").";
1436*8975f5c5SAndroid Build Coastguard Worker             return false;
1437*8975f5c5SAndroid Build Coastguard Worker         }
1438*8975f5c5SAndroid Build Coastguard Worker 
1439*8975f5c5SAndroid Build Coastguard Worker         totalComponents += componentCount;
1440*8975f5c5SAndroid Build Coastguard Worker         if (mPod.transformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS &&
1441*8975f5c5SAndroid Build Coastguard Worker             totalComponents > static_cast<GLuint>(caps.maxTransformFeedbackInterleavedComponents))
1442*8975f5c5SAndroid Build Coastguard Worker         {
1443*8975f5c5SAndroid Build Coastguard Worker             *mInfoLog << "Transform feedback varying total components (" << totalComponents
1444*8975f5c5SAndroid Build Coastguard Worker                       << ") exceed the maximum interleaved components ("
1445*8975f5c5SAndroid Build Coastguard Worker                       << caps.maxTransformFeedbackInterleavedComponents << ").";
1446*8975f5c5SAndroid Build Coastguard Worker             return false;
1447*8975f5c5SAndroid Build Coastguard Worker         }
1448*8975f5c5SAndroid Build Coastguard Worker     }
1449*8975f5c5SAndroid Build Coastguard Worker     return true;
1450*8975f5c5SAndroid Build Coastguard Worker }
1451*8975f5c5SAndroid Build Coastguard Worker 
gatherTransformFeedbackVaryings(const ProgramMergedVaryings & varyings,ShaderType stage)1452*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::gatherTransformFeedbackVaryings(const ProgramMergedVaryings &varyings,
1453*8975f5c5SAndroid Build Coastguard Worker                                                         ShaderType stage)
1454*8975f5c5SAndroid Build Coastguard Worker {
1455*8975f5c5SAndroid Build Coastguard Worker     // Gather the linked varyings that are used for transform feedback, they should all exist.
1456*8975f5c5SAndroid Build Coastguard Worker     mLinkedTransformFeedbackVaryings.clear();
1457*8975f5c5SAndroid Build Coastguard Worker     for (const std::string &tfVaryingName : mTransformFeedbackVaryingNames)
1458*8975f5c5SAndroid Build Coastguard Worker     {
1459*8975f5c5SAndroid Build Coastguard Worker         std::vector<unsigned int> subscripts;
1460*8975f5c5SAndroid Build Coastguard Worker         std::string baseName = ParseResourceName(tfVaryingName, &subscripts);
1461*8975f5c5SAndroid Build Coastguard Worker         size_t subscript     = GL_INVALID_INDEX;
1462*8975f5c5SAndroid Build Coastguard Worker         if (!subscripts.empty())
1463*8975f5c5SAndroid Build Coastguard Worker         {
1464*8975f5c5SAndroid Build Coastguard Worker             subscript = subscripts.back();
1465*8975f5c5SAndroid Build Coastguard Worker         }
1466*8975f5c5SAndroid Build Coastguard Worker         for (const ProgramVaryingRef &ref : varyings)
1467*8975f5c5SAndroid Build Coastguard Worker         {
1468*8975f5c5SAndroid Build Coastguard Worker             if (ref.frontShaderStage != stage)
1469*8975f5c5SAndroid Build Coastguard Worker             {
1470*8975f5c5SAndroid Build Coastguard Worker                 continue;
1471*8975f5c5SAndroid Build Coastguard Worker             }
1472*8975f5c5SAndroid Build Coastguard Worker 
1473*8975f5c5SAndroid Build Coastguard Worker             const sh::ShaderVariable *varying = ref.get(stage);
1474*8975f5c5SAndroid Build Coastguard Worker             if (baseName == varying->name)
1475*8975f5c5SAndroid Build Coastguard Worker             {
1476*8975f5c5SAndroid Build Coastguard Worker                 mLinkedTransformFeedbackVaryings.emplace_back(*varying,
1477*8975f5c5SAndroid Build Coastguard Worker                                                               static_cast<GLuint>(subscript));
1478*8975f5c5SAndroid Build Coastguard Worker                 break;
1479*8975f5c5SAndroid Build Coastguard Worker             }
1480*8975f5c5SAndroid Build Coastguard Worker             else if (varying->isStruct())
1481*8975f5c5SAndroid Build Coastguard Worker             {
1482*8975f5c5SAndroid Build Coastguard Worker                 GLuint fieldIndex = 0;
1483*8975f5c5SAndroid Build Coastguard Worker                 const auto *field = varying->findField(tfVaryingName, &fieldIndex);
1484*8975f5c5SAndroid Build Coastguard Worker                 if (field != nullptr)
1485*8975f5c5SAndroid Build Coastguard Worker                 {
1486*8975f5c5SAndroid Build Coastguard Worker                     mLinkedTransformFeedbackVaryings.emplace_back(*field, *varying);
1487*8975f5c5SAndroid Build Coastguard Worker                     break;
1488*8975f5c5SAndroid Build Coastguard Worker                 }
1489*8975f5c5SAndroid Build Coastguard Worker             }
1490*8975f5c5SAndroid Build Coastguard Worker         }
1491*8975f5c5SAndroid Build Coastguard Worker     }
1492*8975f5c5SAndroid Build Coastguard Worker }
1493*8975f5c5SAndroid Build Coastguard Worker 
updateTransformFeedbackStrides()1494*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::updateTransformFeedbackStrides()
1495*8975f5c5SAndroid Build Coastguard Worker {
1496*8975f5c5SAndroid Build Coastguard Worker     if (mLinkedTransformFeedbackVaryings.empty())
1497*8975f5c5SAndroid Build Coastguard Worker     {
1498*8975f5c5SAndroid Build Coastguard Worker         return;
1499*8975f5c5SAndroid Build Coastguard Worker     }
1500*8975f5c5SAndroid Build Coastguard Worker 
1501*8975f5c5SAndroid Build Coastguard Worker     if (mPod.transformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS)
1502*8975f5c5SAndroid Build Coastguard Worker     {
1503*8975f5c5SAndroid Build Coastguard Worker         mTransformFeedbackStrides.resize(1);
1504*8975f5c5SAndroid Build Coastguard Worker         size_t totalSize = 0;
1505*8975f5c5SAndroid Build Coastguard Worker         for (const TransformFeedbackVarying &varying : mLinkedTransformFeedbackVaryings)
1506*8975f5c5SAndroid Build Coastguard Worker         {
1507*8975f5c5SAndroid Build Coastguard Worker             totalSize += varying.size() * VariableExternalSize(varying.type);
1508*8975f5c5SAndroid Build Coastguard Worker         }
1509*8975f5c5SAndroid Build Coastguard Worker         mTransformFeedbackStrides[0] = static_cast<GLsizei>(totalSize);
1510*8975f5c5SAndroid Build Coastguard Worker     }
1511*8975f5c5SAndroid Build Coastguard Worker     else
1512*8975f5c5SAndroid Build Coastguard Worker     {
1513*8975f5c5SAndroid Build Coastguard Worker         mTransformFeedbackStrides.resize(mLinkedTransformFeedbackVaryings.size());
1514*8975f5c5SAndroid Build Coastguard Worker         for (size_t i = 0; i < mLinkedTransformFeedbackVaryings.size(); i++)
1515*8975f5c5SAndroid Build Coastguard Worker         {
1516*8975f5c5SAndroid Build Coastguard Worker             TransformFeedbackVarying &varying = mLinkedTransformFeedbackVaryings[i];
1517*8975f5c5SAndroid Build Coastguard Worker             mTransformFeedbackStrides[i] =
1518*8975f5c5SAndroid Build Coastguard Worker                 static_cast<GLsizei>(varying.size() * VariableExternalSize(varying.type));
1519*8975f5c5SAndroid Build Coastguard Worker         }
1520*8975f5c5SAndroid Build Coastguard Worker     }
1521*8975f5c5SAndroid Build Coastguard Worker }
1522*8975f5c5SAndroid Build Coastguard Worker 
validateSamplersImpl(const Caps & caps) const1523*8975f5c5SAndroid Build Coastguard Worker bool ProgramExecutable::validateSamplersImpl(const Caps &caps) const
1524*8975f5c5SAndroid Build Coastguard Worker {
1525*8975f5c5SAndroid Build Coastguard Worker     // if any two active samplers in a program are of different types, but refer to the same
1526*8975f5c5SAndroid Build Coastguard Worker     // texture image unit, and this is the current program, then ValidateProgram will fail, and
1527*8975f5c5SAndroid Build Coastguard Worker     // DrawArrays and DrawElements will issue the INVALID_OPERATION error.
1528*8975f5c5SAndroid Build Coastguard Worker     for (size_t textureUnit : mActiveSamplersMask)
1529*8975f5c5SAndroid Build Coastguard Worker     {
1530*8975f5c5SAndroid Build Coastguard Worker         if (mActiveSamplerTypes[textureUnit] == TextureType::InvalidEnum)
1531*8975f5c5SAndroid Build Coastguard Worker         {
1532*8975f5c5SAndroid Build Coastguard Worker             mCachedValidateSamplersResult = false;
1533*8975f5c5SAndroid Build Coastguard Worker             return false;
1534*8975f5c5SAndroid Build Coastguard Worker         }
1535*8975f5c5SAndroid Build Coastguard Worker 
1536*8975f5c5SAndroid Build Coastguard Worker         if (mActiveSamplerFormats[textureUnit] == SamplerFormat::InvalidEnum)
1537*8975f5c5SAndroid Build Coastguard Worker         {
1538*8975f5c5SAndroid Build Coastguard Worker             mCachedValidateSamplersResult = false;
1539*8975f5c5SAndroid Build Coastguard Worker             return false;
1540*8975f5c5SAndroid Build Coastguard Worker         }
1541*8975f5c5SAndroid Build Coastguard Worker     }
1542*8975f5c5SAndroid Build Coastguard Worker 
1543*8975f5c5SAndroid Build Coastguard Worker     mCachedValidateSamplersResult = true;
1544*8975f5c5SAndroid Build Coastguard Worker     return true;
1545*8975f5c5SAndroid Build Coastguard Worker }
1546*8975f5c5SAndroid Build Coastguard Worker 
linkValidateOutputVariables(const Caps & caps,const Version & version,GLuint combinedImageUniformsCount,GLuint combinedShaderStorageBlocksCount,int fragmentShaderVersion,const ProgramAliasedBindings & fragmentOutputLocations,const ProgramAliasedBindings & fragmentOutputIndices)1547*8975f5c5SAndroid Build Coastguard Worker bool ProgramExecutable::linkValidateOutputVariables(
1548*8975f5c5SAndroid Build Coastguard Worker     const Caps &caps,
1549*8975f5c5SAndroid Build Coastguard Worker     const Version &version,
1550*8975f5c5SAndroid Build Coastguard Worker     GLuint combinedImageUniformsCount,
1551*8975f5c5SAndroid Build Coastguard Worker     GLuint combinedShaderStorageBlocksCount,
1552*8975f5c5SAndroid Build Coastguard Worker     int fragmentShaderVersion,
1553*8975f5c5SAndroid Build Coastguard Worker     const ProgramAliasedBindings &fragmentOutputLocations,
1554*8975f5c5SAndroid Build Coastguard Worker     const ProgramAliasedBindings &fragmentOutputIndices)
1555*8975f5c5SAndroid Build Coastguard Worker {
1556*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mPod.activeOutputVariablesMask.none());
1557*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mPod.activeSecondaryOutputVariablesMask.none());
1558*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mPod.drawBufferTypeMask.none());
1559*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mPod.hasYUVOutput);
1560*8975f5c5SAndroid Build Coastguard Worker 
1561*8975f5c5SAndroid Build Coastguard Worker     if (fragmentShaderVersion == 100)
1562*8975f5c5SAndroid Build Coastguard Worker     {
1563*8975f5c5SAndroid Build Coastguard Worker         return gatherOutputTypes();
1564*8975f5c5SAndroid Build Coastguard Worker     }
1565*8975f5c5SAndroid Build Coastguard Worker 
1566*8975f5c5SAndroid Build Coastguard Worker     // EXT_blend_func_extended doesn't specify anything related to binding specific elements of an
1567*8975f5c5SAndroid Build Coastguard Worker     // output array in explicit terms.
1568*8975f5c5SAndroid Build Coastguard Worker     //
1569*8975f5c5SAndroid Build Coastguard Worker     // Assuming fragData is an output array, you can defend the position that:
1570*8975f5c5SAndroid Build Coastguard Worker     // P1) you must support binding "fragData" because it's specified
1571*8975f5c5SAndroid Build Coastguard Worker     // P2) you must support querying "fragData[x]" because it's specified
1572*8975f5c5SAndroid Build Coastguard Worker     // P3) you must support binding "fragData[0]" because it's a frequently used pattern
1573*8975f5c5SAndroid Build Coastguard Worker     //
1574*8975f5c5SAndroid Build Coastguard Worker     // Then you can make the leap of faith:
1575*8975f5c5SAndroid Build Coastguard Worker     // P4) you must support binding "fragData[x]" because you support "fragData[0]"
1576*8975f5c5SAndroid Build Coastguard Worker     // P5) you must support binding "fragData[x]" because you support querying "fragData[x]"
1577*8975f5c5SAndroid Build Coastguard Worker     //
1578*8975f5c5SAndroid Build Coastguard Worker     // The spec brings in the "world of arrays" when it mentions binding the arrays and the
1579*8975f5c5SAndroid Build Coastguard Worker     // automatic binding. Thus it must be interpreted that the thing is not undefined, rather you
1580*8975f5c5SAndroid Build Coastguard Worker     // must infer the only possible interpretation (?). Note again: this need of interpretation
1581*8975f5c5SAndroid Build Coastguard Worker     // might be completely off of what GL spec logic is.
1582*8975f5c5SAndroid Build Coastguard Worker     //
1583*8975f5c5SAndroid Build Coastguard Worker     // The other complexity is that unless you implement this feature, it's hard to understand what
1584*8975f5c5SAndroid Build Coastguard Worker     // should happen when the client invokes the feature. You cannot add an additional error as it
1585*8975f5c5SAndroid Build Coastguard Worker     // is not specified. One can ignore it, but obviously it creates the discrepancies...
1586*8975f5c5SAndroid Build Coastguard Worker 
1587*8975f5c5SAndroid Build Coastguard Worker     std::vector<VariableLocation> reservedLocations;
1588*8975f5c5SAndroid Build Coastguard Worker 
1589*8975f5c5SAndroid Build Coastguard Worker     // Process any output API bindings for arrays that don't alias to the first element.
1590*8975f5c5SAndroid Build Coastguard Worker     for (const auto &bindingPair : fragmentOutputLocations)
1591*8975f5c5SAndroid Build Coastguard Worker     {
1592*8975f5c5SAndroid Build Coastguard Worker         const std::string &name       = bindingPair.first;
1593*8975f5c5SAndroid Build Coastguard Worker         const ProgramBinding &binding = bindingPair.second;
1594*8975f5c5SAndroid Build Coastguard Worker 
1595*8975f5c5SAndroid Build Coastguard Worker         size_t nameLengthWithoutArrayIndex;
1596*8975f5c5SAndroid Build Coastguard Worker         unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
1597*8975f5c5SAndroid Build Coastguard Worker         if (arrayIndex == 0 || arrayIndex == GL_INVALID_INDEX)
1598*8975f5c5SAndroid Build Coastguard Worker         {
1599*8975f5c5SAndroid Build Coastguard Worker             continue;
1600*8975f5c5SAndroid Build Coastguard Worker         }
1601*8975f5c5SAndroid Build Coastguard Worker         for (unsigned int outputVariableIndex = 0; outputVariableIndex < mOutputVariables.size();
1602*8975f5c5SAndroid Build Coastguard Worker              outputVariableIndex++)
1603*8975f5c5SAndroid Build Coastguard Worker         {
1604*8975f5c5SAndroid Build Coastguard Worker             const ProgramOutput &outputVariable = mOutputVariables[outputVariableIndex];
1605*8975f5c5SAndroid Build Coastguard Worker             // Check that the binding corresponds to an output array and its array index fits.
1606*8975f5c5SAndroid Build Coastguard Worker             if (outputVariable.isBuiltIn() || !outputVariable.isArray() ||
1607*8975f5c5SAndroid Build Coastguard Worker                 !angle::BeginsWith(outputVariable.name, name, nameLengthWithoutArrayIndex) ||
1608*8975f5c5SAndroid Build Coastguard Worker                 arrayIndex >= outputVariable.getOutermostArraySize())
1609*8975f5c5SAndroid Build Coastguard Worker             {
1610*8975f5c5SAndroid Build Coastguard Worker                 continue;
1611*8975f5c5SAndroid Build Coastguard Worker             }
1612*8975f5c5SAndroid Build Coastguard Worker 
1613*8975f5c5SAndroid Build Coastguard Worker             // Get the API index that corresponds to this exact binding.
1614*8975f5c5SAndroid Build Coastguard Worker             // This index may differ from the index used for the array's base.
1615*8975f5c5SAndroid Build Coastguard Worker             std::vector<VariableLocation> &outputLocations =
1616*8975f5c5SAndroid Build Coastguard Worker                 fragmentOutputIndices.getBindingByName(name) == 1 ? mSecondaryOutputLocations
1617*8975f5c5SAndroid Build Coastguard Worker                                                                   : mOutputLocations;
1618*8975f5c5SAndroid Build Coastguard Worker             unsigned int location = binding.location;
1619*8975f5c5SAndroid Build Coastguard Worker             VariableLocation locationInfo(arrayIndex, outputVariableIndex);
1620*8975f5c5SAndroid Build Coastguard Worker             if (location >= outputLocations.size())
1621*8975f5c5SAndroid Build Coastguard Worker             {
1622*8975f5c5SAndroid Build Coastguard Worker                 outputLocations.resize(location + 1);
1623*8975f5c5SAndroid Build Coastguard Worker             }
1624*8975f5c5SAndroid Build Coastguard Worker             if (outputLocations[location].used())
1625*8975f5c5SAndroid Build Coastguard Worker             {
1626*8975f5c5SAndroid Build Coastguard Worker                 *mInfoLog << "Location of variable " << outputVariable.name
1627*8975f5c5SAndroid Build Coastguard Worker                           << " conflicts with another variable.";
1628*8975f5c5SAndroid Build Coastguard Worker                 return false;
1629*8975f5c5SAndroid Build Coastguard Worker             }
1630*8975f5c5SAndroid Build Coastguard Worker             outputLocations[location] = locationInfo;
1631*8975f5c5SAndroid Build Coastguard Worker 
1632*8975f5c5SAndroid Build Coastguard Worker             // Note the array binding location so that it can be skipped later.
1633*8975f5c5SAndroid Build Coastguard Worker             reservedLocations.push_back(locationInfo);
1634*8975f5c5SAndroid Build Coastguard Worker         }
1635*8975f5c5SAndroid Build Coastguard Worker     }
1636*8975f5c5SAndroid Build Coastguard Worker 
1637*8975f5c5SAndroid Build Coastguard Worker     // Reserve locations for output variables whose location is fixed in the shader or through the
1638*8975f5c5SAndroid Build Coastguard Worker     // API. Otherwise, the remaining unallocated outputs will be processed later.
1639*8975f5c5SAndroid Build Coastguard Worker     for (unsigned int outputVariableIndex = 0; outputVariableIndex < mOutputVariables.size();
1640*8975f5c5SAndroid Build Coastguard Worker          outputVariableIndex++)
1641*8975f5c5SAndroid Build Coastguard Worker     {
1642*8975f5c5SAndroid Build Coastguard Worker         ProgramOutput &outputVariable = mOutputVariables[outputVariableIndex];
1643*8975f5c5SAndroid Build Coastguard Worker 
1644*8975f5c5SAndroid Build Coastguard Worker         // Don't store outputs for gl_FragDepth, gl_FragColor, etc.
1645*8975f5c5SAndroid Build Coastguard Worker         if (outputVariable.isBuiltIn())
1646*8975f5c5SAndroid Build Coastguard Worker             continue;
1647*8975f5c5SAndroid Build Coastguard Worker 
1648*8975f5c5SAndroid Build Coastguard Worker         int fixedLocation = GetOutputLocationForLink(fragmentOutputLocations, outputVariable);
1649*8975f5c5SAndroid Build Coastguard Worker         if (fixedLocation == -1)
1650*8975f5c5SAndroid Build Coastguard Worker         {
1651*8975f5c5SAndroid Build Coastguard Worker             // Here we're only reserving locations for variables whose location is fixed.
1652*8975f5c5SAndroid Build Coastguard Worker             continue;
1653*8975f5c5SAndroid Build Coastguard Worker         }
1654*8975f5c5SAndroid Build Coastguard Worker         unsigned int baseLocation = static_cast<unsigned int>(fixedLocation);
1655*8975f5c5SAndroid Build Coastguard Worker 
1656*8975f5c5SAndroid Build Coastguard Worker         AssignOutputIndex(fragmentOutputIndices, outputVariable);
1657*8975f5c5SAndroid Build Coastguard Worker         ASSERT(outputVariable.pod.index == 0 || outputVariable.pod.index == 1);
1658*8975f5c5SAndroid Build Coastguard Worker         std::vector<VariableLocation> &outputLocations =
1659*8975f5c5SAndroid Build Coastguard Worker             outputVariable.pod.index == 0 ? mOutputLocations : mSecondaryOutputLocations;
1660*8975f5c5SAndroid Build Coastguard Worker 
1661*8975f5c5SAndroid Build Coastguard Worker         // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
1662*8975f5c5SAndroid Build Coastguard Worker         // structures, so we may use getBasicTypeElementCount().
1663*8975f5c5SAndroid Build Coastguard Worker         unsigned int elementCount = outputVariable.pod.basicTypeElementCount;
1664*8975f5c5SAndroid Build Coastguard Worker         if (FindUsedOutputLocation(outputLocations, baseLocation, elementCount, reservedLocations,
1665*8975f5c5SAndroid Build Coastguard Worker                                    outputVariableIndex))
1666*8975f5c5SAndroid Build Coastguard Worker         {
1667*8975f5c5SAndroid Build Coastguard Worker             *mInfoLog << "Location of variable " << outputVariable.name
1668*8975f5c5SAndroid Build Coastguard Worker                       << " conflicts with another variable.";
1669*8975f5c5SAndroid Build Coastguard Worker             return false;
1670*8975f5c5SAndroid Build Coastguard Worker         }
1671*8975f5c5SAndroid Build Coastguard Worker         bool hasApiAssignedLocation = !outputVariable.pod.hasShaderAssignedLocation &&
1672*8975f5c5SAndroid Build Coastguard Worker                                       (fragmentOutputLocations.getBinding(outputVariable) != -1);
1673*8975f5c5SAndroid Build Coastguard Worker         AssignOutputLocations(outputLocations, baseLocation, elementCount, reservedLocations,
1674*8975f5c5SAndroid Build Coastguard Worker                               outputVariableIndex, hasApiAssignedLocation, outputVariable);
1675*8975f5c5SAndroid Build Coastguard Worker     }
1676*8975f5c5SAndroid Build Coastguard Worker 
1677*8975f5c5SAndroid Build Coastguard Worker     // Here we assign locations for the output variables that don't yet have them. Note that we're
1678*8975f5c5SAndroid Build Coastguard Worker     // not necessarily able to fit the variables optimally, since then we might have to try
1679*8975f5c5SAndroid Build Coastguard Worker     // different arrangements of output arrays. Now we just assign the locations in the order that
1680*8975f5c5SAndroid Build Coastguard Worker     // we got the output variables. The spec isn't clear on what kind of algorithm is required for
1681*8975f5c5SAndroid Build Coastguard Worker     // finding locations for the output variables, so this should be acceptable at least for now.
1682*8975f5c5SAndroid Build Coastguard Worker     GLuint maxLocation = static_cast<GLuint>(caps.maxDrawBuffers);
1683*8975f5c5SAndroid Build Coastguard Worker     if (!mSecondaryOutputLocations.empty())
1684*8975f5c5SAndroid Build Coastguard Worker     {
1685*8975f5c5SAndroid Build Coastguard Worker         // EXT_blend_func_extended: Program outputs will be validated against
1686*8975f5c5SAndroid Build Coastguard Worker         // MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT if there's even one output with index one.
1687*8975f5c5SAndroid Build Coastguard Worker         maxLocation = caps.maxDualSourceDrawBuffers;
1688*8975f5c5SAndroid Build Coastguard Worker     }
1689*8975f5c5SAndroid Build Coastguard Worker 
1690*8975f5c5SAndroid Build Coastguard Worker     for (unsigned int outputVariableIndex = 0; outputVariableIndex < mOutputVariables.size();
1691*8975f5c5SAndroid Build Coastguard Worker          outputVariableIndex++)
1692*8975f5c5SAndroid Build Coastguard Worker     {
1693*8975f5c5SAndroid Build Coastguard Worker         ProgramOutput &outputVariable = mOutputVariables[outputVariableIndex];
1694*8975f5c5SAndroid Build Coastguard Worker 
1695*8975f5c5SAndroid Build Coastguard Worker         // Don't store outputs for gl_FragDepth, gl_FragColor, etc.
1696*8975f5c5SAndroid Build Coastguard Worker         if (outputVariable.isBuiltIn())
1697*8975f5c5SAndroid Build Coastguard Worker             continue;
1698*8975f5c5SAndroid Build Coastguard Worker 
1699*8975f5c5SAndroid Build Coastguard Worker         AssignOutputIndex(fragmentOutputIndices, outputVariable);
1700*8975f5c5SAndroid Build Coastguard Worker         ASSERT(outputVariable.pod.index == 0 || outputVariable.pod.index == 1);
1701*8975f5c5SAndroid Build Coastguard Worker         std::vector<VariableLocation> &outputLocations =
1702*8975f5c5SAndroid Build Coastguard Worker             outputVariable.pod.index == 0 ? mOutputLocations : mSecondaryOutputLocations;
1703*8975f5c5SAndroid Build Coastguard Worker 
1704*8975f5c5SAndroid Build Coastguard Worker         int fixedLocation = GetOutputLocationForLink(fragmentOutputLocations, outputVariable);
1705*8975f5c5SAndroid Build Coastguard Worker         unsigned int baseLocation = 0;
1706*8975f5c5SAndroid Build Coastguard Worker         unsigned int elementCount = outputVariable.pod.basicTypeElementCount;
1707*8975f5c5SAndroid Build Coastguard Worker         if (fixedLocation != -1)
1708*8975f5c5SAndroid Build Coastguard Worker         {
1709*8975f5c5SAndroid Build Coastguard Worker             // Secondary inputs might have caused the max location to drop below what has already
1710*8975f5c5SAndroid Build Coastguard Worker             // been explicitly assigned locations. Check for any fixed locations above the max
1711*8975f5c5SAndroid Build Coastguard Worker             // that should cause linking to fail.
1712*8975f5c5SAndroid Build Coastguard Worker             baseLocation = static_cast<unsigned int>(fixedLocation);
1713*8975f5c5SAndroid Build Coastguard Worker         }
1714*8975f5c5SAndroid Build Coastguard Worker         else
1715*8975f5c5SAndroid Build Coastguard Worker         {
1716*8975f5c5SAndroid Build Coastguard Worker             // No fixed location, so try to fit the output in unassigned locations.
1717*8975f5c5SAndroid Build Coastguard Worker             // Try baseLocations starting from 0 one at a time and see if the variable fits.
1718*8975f5c5SAndroid Build Coastguard Worker             while (FindUsedOutputLocation(outputLocations, baseLocation, elementCount,
1719*8975f5c5SAndroid Build Coastguard Worker                                           reservedLocations, outputVariableIndex))
1720*8975f5c5SAndroid Build Coastguard Worker             {
1721*8975f5c5SAndroid Build Coastguard Worker                 baseLocation++;
1722*8975f5c5SAndroid Build Coastguard Worker             }
1723*8975f5c5SAndroid Build Coastguard Worker             AssignOutputLocations(outputLocations, baseLocation, elementCount, reservedLocations,
1724*8975f5c5SAndroid Build Coastguard Worker                                   outputVariableIndex, false, outputVariable);
1725*8975f5c5SAndroid Build Coastguard Worker         }
1726*8975f5c5SAndroid Build Coastguard Worker 
1727*8975f5c5SAndroid Build Coastguard Worker         // Check for any elements assigned above the max location that are actually used.
1728*8975f5c5SAndroid Build Coastguard Worker         if (baseLocation + elementCount > maxLocation &&
1729*8975f5c5SAndroid Build Coastguard Worker             (baseLocation >= maxLocation ||
1730*8975f5c5SAndroid Build Coastguard Worker              FindUsedOutputLocation(outputLocations, maxLocation,
1731*8975f5c5SAndroid Build Coastguard Worker                                     baseLocation + elementCount - maxLocation, reservedLocations,
1732*8975f5c5SAndroid Build Coastguard Worker                                     outputVariableIndex)))
1733*8975f5c5SAndroid Build Coastguard Worker         {
1734*8975f5c5SAndroid Build Coastguard Worker             // EXT_blend_func_extended: Linking can fail:
1735*8975f5c5SAndroid Build Coastguard Worker             // "if the explicit binding assignments do not leave enough space for the linker to
1736*8975f5c5SAndroid Build Coastguard Worker             // automatically assign a location for a varying out array, which requires multiple
1737*8975f5c5SAndroid Build Coastguard Worker             // contiguous locations."
1738*8975f5c5SAndroid Build Coastguard Worker             *mInfoLog << "Could not fit output variable into available locations: "
1739*8975f5c5SAndroid Build Coastguard Worker                       << outputVariable.name;
1740*8975f5c5SAndroid Build Coastguard Worker             return false;
1741*8975f5c5SAndroid Build Coastguard Worker         }
1742*8975f5c5SAndroid Build Coastguard Worker     }
1743*8975f5c5SAndroid Build Coastguard Worker 
1744*8975f5c5SAndroid Build Coastguard Worker     if (!gatherOutputTypes())
1745*8975f5c5SAndroid Build Coastguard Worker     {
1746*8975f5c5SAndroid Build Coastguard Worker         return false;
1747*8975f5c5SAndroid Build Coastguard Worker     }
1748*8975f5c5SAndroid Build Coastguard Worker 
1749*8975f5c5SAndroid Build Coastguard Worker     if (version >= ES_3_1)
1750*8975f5c5SAndroid Build Coastguard Worker     {
1751*8975f5c5SAndroid Build Coastguard Worker         // [OpenGL ES 3.1] Chapter 8.22 Page 203:
1752*8975f5c5SAndroid Build Coastguard Worker         // A link error will be generated if the sum of the number of active image uniforms used in
1753*8975f5c5SAndroid Build Coastguard Worker         // all shaders, the number of active shader storage blocks, and the number of active
1754*8975f5c5SAndroid Build Coastguard Worker         // fragment shader outputs exceeds the implementation-dependent value of
1755*8975f5c5SAndroid Build Coastguard Worker         // MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
1756*8975f5c5SAndroid Build Coastguard Worker         if (combinedImageUniformsCount + combinedShaderStorageBlocksCount +
1757*8975f5c5SAndroid Build Coastguard Worker                 mPod.activeOutputVariablesMask.count() >
1758*8975f5c5SAndroid Build Coastguard Worker             static_cast<GLuint>(caps.maxCombinedShaderOutputResources))
1759*8975f5c5SAndroid Build Coastguard Worker         {
1760*8975f5c5SAndroid Build Coastguard Worker             *mInfoLog
1761*8975f5c5SAndroid Build Coastguard Worker                 << "The sum of the number of active image uniforms, active shader storage blocks "
1762*8975f5c5SAndroid Build Coastguard Worker                    "and active fragment shader outputs exceeds "
1763*8975f5c5SAndroid Build Coastguard Worker                    "MAX_COMBINED_SHADER_OUTPUT_RESOURCES ("
1764*8975f5c5SAndroid Build Coastguard Worker                 << caps.maxCombinedShaderOutputResources << ")";
1765*8975f5c5SAndroid Build Coastguard Worker             return false;
1766*8975f5c5SAndroid Build Coastguard Worker         }
1767*8975f5c5SAndroid Build Coastguard Worker     }
1768*8975f5c5SAndroid Build Coastguard Worker 
1769*8975f5c5SAndroid Build Coastguard Worker     return true;
1770*8975f5c5SAndroid Build Coastguard Worker }
1771*8975f5c5SAndroid Build Coastguard Worker 
gatherOutputTypes()1772*8975f5c5SAndroid Build Coastguard Worker bool ProgramExecutable::gatherOutputTypes()
1773*8975f5c5SAndroid Build Coastguard Worker {
1774*8975f5c5SAndroid Build Coastguard Worker     for (const ProgramOutput &outputVariable : mOutputVariables)
1775*8975f5c5SAndroid Build Coastguard Worker     {
1776*8975f5c5SAndroid Build Coastguard Worker         if (outputVariable.isBuiltIn() && outputVariable.name != "gl_FragColor" &&
1777*8975f5c5SAndroid Build Coastguard Worker             outputVariable.name != "gl_FragData" &&
1778*8975f5c5SAndroid Build Coastguard Worker             outputVariable.name != "gl_SecondaryFragColorEXT" &&
1779*8975f5c5SAndroid Build Coastguard Worker             outputVariable.name != "gl_SecondaryFragDataEXT")
1780*8975f5c5SAndroid Build Coastguard Worker         {
1781*8975f5c5SAndroid Build Coastguard Worker             continue;
1782*8975f5c5SAndroid Build Coastguard Worker         }
1783*8975f5c5SAndroid Build Coastguard Worker 
1784*8975f5c5SAndroid Build Coastguard Worker         unsigned int baseLocation = (outputVariable.pod.location == -1
1785*8975f5c5SAndroid Build Coastguard Worker                                          ? 0u
1786*8975f5c5SAndroid Build Coastguard Worker                                          : static_cast<unsigned int>(outputVariable.pod.location));
1787*8975f5c5SAndroid Build Coastguard Worker 
1788*8975f5c5SAndroid Build Coastguard Worker         const bool secondary =
1789*8975f5c5SAndroid Build Coastguard Worker             outputVariable.pod.index == 1 || (outputVariable.name == "gl_SecondaryFragColorEXT" ||
1790*8975f5c5SAndroid Build Coastguard Worker                                               outputVariable.name == "gl_SecondaryFragDataEXT");
1791*8975f5c5SAndroid Build Coastguard Worker 
1792*8975f5c5SAndroid Build Coastguard Worker         const ComponentType componentType =
1793*8975f5c5SAndroid Build Coastguard Worker             GLenumToComponentType(VariableComponentType(outputVariable.pod.type));
1794*8975f5c5SAndroid Build Coastguard Worker 
1795*8975f5c5SAndroid Build Coastguard Worker         // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
1796*8975f5c5SAndroid Build Coastguard Worker         // structures, so we may use getBasicTypeElementCount().
1797*8975f5c5SAndroid Build Coastguard Worker         unsigned int elementCount = outputVariable.pod.basicTypeElementCount;
1798*8975f5c5SAndroid Build Coastguard Worker         for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
1799*8975f5c5SAndroid Build Coastguard Worker         {
1800*8975f5c5SAndroid Build Coastguard Worker             const unsigned int location = baseLocation + elementIndex;
1801*8975f5c5SAndroid Build Coastguard Worker             ASSERT(location < mPod.activeOutputVariablesMask.size());
1802*8975f5c5SAndroid Build Coastguard Worker             ASSERT(location < mPod.activeSecondaryOutputVariablesMask.size());
1803*8975f5c5SAndroid Build Coastguard Worker             if (secondary)
1804*8975f5c5SAndroid Build Coastguard Worker             {
1805*8975f5c5SAndroid Build Coastguard Worker                 mPod.activeSecondaryOutputVariablesMask.set(location);
1806*8975f5c5SAndroid Build Coastguard Worker             }
1807*8975f5c5SAndroid Build Coastguard Worker             else
1808*8975f5c5SAndroid Build Coastguard Worker             {
1809*8975f5c5SAndroid Build Coastguard Worker                 mPod.activeOutputVariablesMask.set(location);
1810*8975f5c5SAndroid Build Coastguard Worker             }
1811*8975f5c5SAndroid Build Coastguard Worker             const ComponentType storedComponentType =
1812*8975f5c5SAndroid Build Coastguard Worker                 gl::GetComponentTypeMask(mPod.drawBufferTypeMask, location);
1813*8975f5c5SAndroid Build Coastguard Worker             if (storedComponentType == ComponentType::InvalidEnum)
1814*8975f5c5SAndroid Build Coastguard Worker             {
1815*8975f5c5SAndroid Build Coastguard Worker                 SetComponentTypeMask(componentType, location, &mPod.drawBufferTypeMask);
1816*8975f5c5SAndroid Build Coastguard Worker             }
1817*8975f5c5SAndroid Build Coastguard Worker             else if (storedComponentType != componentType)
1818*8975f5c5SAndroid Build Coastguard Worker             {
1819*8975f5c5SAndroid Build Coastguard Worker                 *mInfoLog << "Inconsistent component types for fragment outputs at location "
1820*8975f5c5SAndroid Build Coastguard Worker                           << location;
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         if (outputVariable.pod.yuv)
1826*8975f5c5SAndroid Build Coastguard Worker         {
1827*8975f5c5SAndroid Build Coastguard Worker             ASSERT(mOutputVariables.size() == 1);
1828*8975f5c5SAndroid Build Coastguard Worker             mPod.hasYUVOutput = true;
1829*8975f5c5SAndroid Build Coastguard Worker         }
1830*8975f5c5SAndroid Build Coastguard Worker     }
1831*8975f5c5SAndroid Build Coastguard Worker 
1832*8975f5c5SAndroid Build Coastguard Worker     return true;
1833*8975f5c5SAndroid Build Coastguard Worker }
1834*8975f5c5SAndroid Build Coastguard Worker 
linkUniforms(const Caps & caps,const ShaderMap<std::vector<sh::ShaderVariable>> & shaderUniforms,const ProgramAliasedBindings & uniformLocationBindings,GLuint * combinedImageUniformsCountOut,std::vector<UnusedUniform> * unusedUniformsOutOrNull)1835*8975f5c5SAndroid Build Coastguard Worker bool ProgramExecutable::linkUniforms(
1836*8975f5c5SAndroid Build Coastguard Worker     const Caps &caps,
1837*8975f5c5SAndroid Build Coastguard Worker     const ShaderMap<std::vector<sh::ShaderVariable>> &shaderUniforms,
1838*8975f5c5SAndroid Build Coastguard Worker     const ProgramAliasedBindings &uniformLocationBindings,
1839*8975f5c5SAndroid Build Coastguard Worker     GLuint *combinedImageUniformsCountOut,
1840*8975f5c5SAndroid Build Coastguard Worker     std::vector<UnusedUniform> *unusedUniformsOutOrNull)
1841*8975f5c5SAndroid Build Coastguard Worker {
1842*8975f5c5SAndroid Build Coastguard Worker     UniformLinker linker(mPod.linkedShaderStages, shaderUniforms);
1843*8975f5c5SAndroid Build Coastguard Worker     if (!linker.link(caps, *mInfoLog, uniformLocationBindings))
1844*8975f5c5SAndroid Build Coastguard Worker     {
1845*8975f5c5SAndroid Build Coastguard Worker         return false;
1846*8975f5c5SAndroid Build Coastguard Worker     }
1847*8975f5c5SAndroid Build Coastguard Worker 
1848*8975f5c5SAndroid Build Coastguard Worker     linker.getResults(&mUniforms, &mUniformNames, &mUniformMappedNames, unusedUniformsOutOrNull,
1849*8975f5c5SAndroid Build Coastguard Worker                       &mUniformLocations);
1850*8975f5c5SAndroid Build Coastguard Worker 
1851*8975f5c5SAndroid Build Coastguard Worker     linkSamplerAndImageBindings(combinedImageUniformsCountOut);
1852*8975f5c5SAndroid Build Coastguard Worker 
1853*8975f5c5SAndroid Build Coastguard Worker     if (!linkAtomicCounterBuffers(caps))
1854*8975f5c5SAndroid Build Coastguard Worker     {
1855*8975f5c5SAndroid Build Coastguard Worker         return false;
1856*8975f5c5SAndroid Build Coastguard Worker     }
1857*8975f5c5SAndroid Build Coastguard Worker 
1858*8975f5c5SAndroid Build Coastguard Worker     return true;
1859*8975f5c5SAndroid Build Coastguard Worker }
1860*8975f5c5SAndroid Build Coastguard Worker 
linkSamplerAndImageBindings(GLuint * combinedImageUniforms)1861*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::linkSamplerAndImageBindings(GLuint *combinedImageUniforms)
1862*8975f5c5SAndroid Build Coastguard Worker {
1863*8975f5c5SAndroid Build Coastguard Worker     ASSERT(combinedImageUniforms);
1864*8975f5c5SAndroid Build Coastguard Worker 
1865*8975f5c5SAndroid Build Coastguard Worker     // Iterate over mExecutable->mUniforms from the back, and find the range of subpass inputs,
1866*8975f5c5SAndroid Build Coastguard Worker     // atomic counters, images and samplers in that order.
1867*8975f5c5SAndroid Build Coastguard Worker     auto highIter = mUniforms.rbegin();
1868*8975f5c5SAndroid Build Coastguard Worker     auto lowIter  = highIter;
1869*8975f5c5SAndroid Build Coastguard Worker 
1870*8975f5c5SAndroid Build Coastguard Worker     unsigned int high = static_cast<unsigned int>(mUniforms.size());
1871*8975f5c5SAndroid Build Coastguard Worker     unsigned int low  = high;
1872*8975f5c5SAndroid Build Coastguard Worker 
1873*8975f5c5SAndroid Build Coastguard Worker     // Note that uniform block uniforms are not yet appended to this list.
1874*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mUniforms.empty() || highIter->isAtomicCounter() || highIter->isImage() ||
1875*8975f5c5SAndroid Build Coastguard Worker            highIter->isSampler() || highIter->isInDefaultBlock());
1876*8975f5c5SAndroid Build Coastguard Worker 
1877*8975f5c5SAndroid Build Coastguard Worker     for (; lowIter != mUniforms.rend() && lowIter->isAtomicCounter(); ++lowIter)
1878*8975f5c5SAndroid Build Coastguard Worker     {
1879*8975f5c5SAndroid Build Coastguard Worker         --low;
1880*8975f5c5SAndroid Build Coastguard Worker     }
1881*8975f5c5SAndroid Build Coastguard Worker 
1882*8975f5c5SAndroid Build Coastguard Worker     mPod.atomicCounterUniformRange = RangeUI(low, high);
1883*8975f5c5SAndroid Build Coastguard Worker 
1884*8975f5c5SAndroid Build Coastguard Worker     highIter = lowIter;
1885*8975f5c5SAndroid Build Coastguard Worker     high     = low;
1886*8975f5c5SAndroid Build Coastguard Worker 
1887*8975f5c5SAndroid Build Coastguard Worker     for (; lowIter != mUniforms.rend() && lowIter->isImage(); ++lowIter)
1888*8975f5c5SAndroid Build Coastguard Worker     {
1889*8975f5c5SAndroid Build Coastguard Worker         --low;
1890*8975f5c5SAndroid Build Coastguard Worker     }
1891*8975f5c5SAndroid Build Coastguard Worker 
1892*8975f5c5SAndroid Build Coastguard Worker     mPod.imageUniformRange = RangeUI(low, high);
1893*8975f5c5SAndroid Build Coastguard Worker     *combinedImageUniforms = 0u;
1894*8975f5c5SAndroid Build Coastguard Worker     // If uniform is a image type, insert it into the mImageBindings array.
1895*8975f5c5SAndroid Build Coastguard Worker     for (unsigned int imageIndex : mPod.imageUniformRange)
1896*8975f5c5SAndroid Build Coastguard Worker     {
1897*8975f5c5SAndroid Build Coastguard Worker         // ES3.1 (section 7.6.1) and GLSL ES3.1 (section 4.4.5), Uniform*i{v} commands
1898*8975f5c5SAndroid Build Coastguard Worker         // cannot load values into a uniform defined as an image. if declare without a
1899*8975f5c5SAndroid Build Coastguard Worker         // binding qualifier, any uniform image variable (include all elements of
1900*8975f5c5SAndroid Build Coastguard Worker         // unbound image array) should be bound to unit zero.
1901*8975f5c5SAndroid Build Coastguard Worker         auto &imageUniform      = mUniforms[imageIndex];
1902*8975f5c5SAndroid Build Coastguard Worker         TextureType textureType = ImageTypeToTextureType(imageUniform.getType());
1903*8975f5c5SAndroid Build Coastguard Worker         const GLuint arraySize  = imageUniform.getBasicTypeElementCount();
1904*8975f5c5SAndroid Build Coastguard Worker 
1905*8975f5c5SAndroid Build Coastguard Worker         if (imageUniform.getBinding() == -1)
1906*8975f5c5SAndroid Build Coastguard Worker         {
1907*8975f5c5SAndroid Build Coastguard Worker             mImageBindings.emplace_back(
1908*8975f5c5SAndroid Build Coastguard Worker                 ImageBinding(imageUniform.getBasicTypeElementCount(), textureType));
1909*8975f5c5SAndroid Build Coastguard Worker         }
1910*8975f5c5SAndroid Build Coastguard Worker         else
1911*8975f5c5SAndroid Build Coastguard Worker         {
1912*8975f5c5SAndroid Build Coastguard Worker             // The arrays of arrays are flattened to arrays, it needs to record the array offset for
1913*8975f5c5SAndroid Build Coastguard Worker             // the correct binding image unit.
1914*8975f5c5SAndroid Build Coastguard Worker             mImageBindings.emplace_back(ImageBinding(
1915*8975f5c5SAndroid Build Coastguard Worker                 imageUniform.getBinding() + imageUniform.pod.parentArrayIndex * arraySize,
1916*8975f5c5SAndroid Build Coastguard Worker                 imageUniform.getBasicTypeElementCount(), textureType));
1917*8975f5c5SAndroid Build Coastguard Worker         }
1918*8975f5c5SAndroid Build Coastguard Worker 
1919*8975f5c5SAndroid Build Coastguard Worker         *combinedImageUniforms += imageUniform.activeShaderCount() * arraySize;
1920*8975f5c5SAndroid Build Coastguard Worker     }
1921*8975f5c5SAndroid Build Coastguard Worker 
1922*8975f5c5SAndroid Build Coastguard Worker     highIter = lowIter;
1923*8975f5c5SAndroid Build Coastguard Worker     high     = low;
1924*8975f5c5SAndroid Build Coastguard Worker 
1925*8975f5c5SAndroid Build Coastguard Worker     for (; lowIter != mUniforms.rend() && lowIter->isSampler(); ++lowIter)
1926*8975f5c5SAndroid Build Coastguard Worker     {
1927*8975f5c5SAndroid Build Coastguard Worker         --low;
1928*8975f5c5SAndroid Build Coastguard Worker     }
1929*8975f5c5SAndroid Build Coastguard Worker 
1930*8975f5c5SAndroid Build Coastguard Worker     mPod.samplerUniformRange = RangeUI(low, high);
1931*8975f5c5SAndroid Build Coastguard Worker 
1932*8975f5c5SAndroid Build Coastguard Worker     // If uniform is a sampler type, insert it into the mSamplerBindings array.
1933*8975f5c5SAndroid Build Coastguard Worker     uint16_t totalCount = 0;
1934*8975f5c5SAndroid Build Coastguard Worker     for (unsigned int samplerIndex : mPod.samplerUniformRange)
1935*8975f5c5SAndroid Build Coastguard Worker     {
1936*8975f5c5SAndroid Build Coastguard Worker         const auto &samplerUniform = mUniforms[samplerIndex];
1937*8975f5c5SAndroid Build Coastguard Worker         TextureType textureType    = SamplerTypeToTextureType(samplerUniform.getType());
1938*8975f5c5SAndroid Build Coastguard Worker         GLenum samplerType         = samplerUniform.getType();
1939*8975f5c5SAndroid Build Coastguard Worker         uint16_t elementCount      = samplerUniform.getBasicTypeElementCount();
1940*8975f5c5SAndroid Build Coastguard Worker         SamplerFormat format       = GetUniformTypeInfo(samplerType).samplerFormat;
1941*8975f5c5SAndroid Build Coastguard Worker         mSamplerBindings.emplace_back(textureType, samplerType, format, totalCount, elementCount);
1942*8975f5c5SAndroid Build Coastguard Worker         totalCount += elementCount;
1943*8975f5c5SAndroid Build Coastguard Worker     }
1944*8975f5c5SAndroid Build Coastguard Worker     mSamplerBoundTextureUnits.resize(totalCount, 0);
1945*8975f5c5SAndroid Build Coastguard Worker 
1946*8975f5c5SAndroid Build Coastguard Worker     // Whatever is left constitutes the default uniforms.
1947*8975f5c5SAndroid Build Coastguard Worker     mPod.defaultUniformRange = RangeUI(0, low);
1948*8975f5c5SAndroid Build Coastguard Worker }
1949*8975f5c5SAndroid Build Coastguard Worker 
linkAtomicCounterBuffers(const Caps & caps)1950*8975f5c5SAndroid Build Coastguard Worker bool ProgramExecutable::linkAtomicCounterBuffers(const Caps &caps)
1951*8975f5c5SAndroid Build Coastguard Worker {
1952*8975f5c5SAndroid Build Coastguard Worker     for (unsigned int index : mPod.atomicCounterUniformRange)
1953*8975f5c5SAndroid Build Coastguard Worker     {
1954*8975f5c5SAndroid Build Coastguard Worker         auto &uniform = mUniforms[index];
1955*8975f5c5SAndroid Build Coastguard Worker 
1956*8975f5c5SAndroid Build Coastguard Worker         uniform.pod.blockOffset                    = uniform.getOffset();
1957*8975f5c5SAndroid Build Coastguard Worker         uniform.pod.blockArrayStride               = uniform.isArray() ? 4 : 0;
1958*8975f5c5SAndroid Build Coastguard Worker         uniform.pod.blockMatrixStride              = 0;
1959*8975f5c5SAndroid Build Coastguard Worker         uniform.pod.flagBits.blockIsRowMajorMatrix = false;
1960*8975f5c5SAndroid Build Coastguard Worker         uniform.pod.flagBits.isBlock               = true;
1961*8975f5c5SAndroid Build Coastguard Worker 
1962*8975f5c5SAndroid Build Coastguard Worker         bool found = false;
1963*8975f5c5SAndroid Build Coastguard Worker         for (size_t bufferIndex = 0; bufferIndex < mAtomicCounterBuffers.size(); ++bufferIndex)
1964*8975f5c5SAndroid Build Coastguard Worker         {
1965*8975f5c5SAndroid Build Coastguard Worker             AtomicCounterBuffer &buffer = mAtomicCounterBuffers[bufferIndex];
1966*8975f5c5SAndroid Build Coastguard Worker             if (buffer.pod.inShaderBinding == uniform.getBinding())
1967*8975f5c5SAndroid Build Coastguard Worker             {
1968*8975f5c5SAndroid Build Coastguard Worker                 buffer.memberIndexes.push_back(index);
1969*8975f5c5SAndroid Build Coastguard Worker                 SetBitField(uniform.pod.bufferIndex, bufferIndex);
1970*8975f5c5SAndroid Build Coastguard Worker                 found = true;
1971*8975f5c5SAndroid Build Coastguard Worker                 buffer.unionReferencesWith(uniform);
1972*8975f5c5SAndroid Build Coastguard Worker                 break;
1973*8975f5c5SAndroid Build Coastguard Worker             }
1974*8975f5c5SAndroid Build Coastguard Worker         }
1975*8975f5c5SAndroid Build Coastguard Worker         if (!found)
1976*8975f5c5SAndroid Build Coastguard Worker         {
1977*8975f5c5SAndroid Build Coastguard Worker             AtomicCounterBuffer atomicCounterBuffer;
1978*8975f5c5SAndroid Build Coastguard Worker             atomicCounterBuffer.pod.inShaderBinding = uniform.getBinding();
1979*8975f5c5SAndroid Build Coastguard Worker             atomicCounterBuffer.memberIndexes.push_back(index);
1980*8975f5c5SAndroid Build Coastguard Worker             atomicCounterBuffer.unionReferencesWith(uniform);
1981*8975f5c5SAndroid Build Coastguard Worker             mAtomicCounterBuffers.push_back(atomicCounterBuffer);
1982*8975f5c5SAndroid Build Coastguard Worker             SetBitField(uniform.pod.bufferIndex, mAtomicCounterBuffers.size() - 1);
1983*8975f5c5SAndroid Build Coastguard Worker         }
1984*8975f5c5SAndroid Build Coastguard Worker     }
1985*8975f5c5SAndroid Build Coastguard Worker 
1986*8975f5c5SAndroid Build Coastguard Worker     // Count each atomic counter buffer to validate against
1987*8975f5c5SAndroid Build Coastguard Worker     // per-stage and combined gl_Max*AtomicCounterBuffers.
1988*8975f5c5SAndroid Build Coastguard Worker     GLint combinedShaderACBCount           = 0;
1989*8975f5c5SAndroid Build Coastguard Worker     gl::ShaderMap<GLint> perShaderACBCount = {};
1990*8975f5c5SAndroid Build Coastguard Worker     for (size_t bufferIndex = 0; bufferIndex < mAtomicCounterBuffers.size(); ++bufferIndex)
1991*8975f5c5SAndroid Build Coastguard Worker     {
1992*8975f5c5SAndroid Build Coastguard Worker         AtomicCounterBuffer &acb        = mAtomicCounterBuffers[bufferIndex];
1993*8975f5c5SAndroid Build Coastguard Worker         const ShaderBitSet shaderStages = acb.activeShaders();
1994*8975f5c5SAndroid Build Coastguard Worker         for (gl::ShaderType shaderType : shaderStages)
1995*8975f5c5SAndroid Build Coastguard Worker         {
1996*8975f5c5SAndroid Build Coastguard Worker             ++perShaderACBCount[shaderType];
1997*8975f5c5SAndroid Build Coastguard Worker         }
1998*8975f5c5SAndroid Build Coastguard Worker         ++combinedShaderACBCount;
1999*8975f5c5SAndroid Build Coastguard Worker     }
2000*8975f5c5SAndroid Build Coastguard Worker     if (combinedShaderACBCount > caps.maxCombinedAtomicCounterBuffers)
2001*8975f5c5SAndroid Build Coastguard Worker     {
2002*8975f5c5SAndroid Build Coastguard Worker         *mInfoLog << " combined AtomicCounterBuffers count exceeds limit";
2003*8975f5c5SAndroid Build Coastguard Worker         return false;
2004*8975f5c5SAndroid Build Coastguard Worker     }
2005*8975f5c5SAndroid Build Coastguard Worker     for (gl::ShaderType stage : gl::AllShaderTypes())
2006*8975f5c5SAndroid Build Coastguard Worker     {
2007*8975f5c5SAndroid Build Coastguard Worker         if (perShaderACBCount[stage] > caps.maxShaderAtomicCounterBuffers[stage])
2008*8975f5c5SAndroid Build Coastguard Worker         {
2009*8975f5c5SAndroid Build Coastguard Worker             *mInfoLog << GetShaderTypeString(stage)
2010*8975f5c5SAndroid Build Coastguard Worker                       << " shader AtomicCounterBuffers count exceeds limit";
2011*8975f5c5SAndroid Build Coastguard Worker             return false;
2012*8975f5c5SAndroid Build Coastguard Worker         }
2013*8975f5c5SAndroid Build Coastguard Worker     }
2014*8975f5c5SAndroid Build Coastguard Worker     return true;
2015*8975f5c5SAndroid Build Coastguard Worker }
2016*8975f5c5SAndroid Build Coastguard Worker 
copyInputsFromProgram(const ProgramExecutable & executable)2017*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::copyInputsFromProgram(const ProgramExecutable &executable)
2018*8975f5c5SAndroid Build Coastguard Worker {
2019*8975f5c5SAndroid Build Coastguard Worker     mProgramInputs = executable.getProgramInputs();
2020*8975f5c5SAndroid Build Coastguard Worker }
2021*8975f5c5SAndroid Build Coastguard Worker 
copyUniformBuffersFromProgram(const ProgramExecutable & executable,ShaderType shaderType,ProgramUniformBlockArray<GLuint> * ppoUniformBlockMap)2022*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::copyUniformBuffersFromProgram(
2023*8975f5c5SAndroid Build Coastguard Worker     const ProgramExecutable &executable,
2024*8975f5c5SAndroid Build Coastguard Worker     ShaderType shaderType,
2025*8975f5c5SAndroid Build Coastguard Worker     ProgramUniformBlockArray<GLuint> *ppoUniformBlockMap)
2026*8975f5c5SAndroid Build Coastguard Worker {
2027*8975f5c5SAndroid Build Coastguard Worker     AppendActiveBlocks(shaderType, executable.getUniformBlocks(), mUniformBlocks,
2028*8975f5c5SAndroid Build Coastguard Worker                        ppoUniformBlockMap);
2029*8975f5c5SAndroid Build Coastguard Worker 
2030*8975f5c5SAndroid Build Coastguard Worker     const std::vector<InterfaceBlock> &blocks = executable.getUniformBlocks();
2031*8975f5c5SAndroid Build Coastguard Worker     for (size_t blockIndex = 0; blockIndex < blocks.size(); ++blockIndex)
2032*8975f5c5SAndroid Build Coastguard Worker     {
2033*8975f5c5SAndroid Build Coastguard Worker         if (!blocks[blockIndex].isActive(shaderType))
2034*8975f5c5SAndroid Build Coastguard Worker         {
2035*8975f5c5SAndroid Build Coastguard Worker             continue;
2036*8975f5c5SAndroid Build Coastguard Worker         }
2037*8975f5c5SAndroid Build Coastguard Worker         const uint32_t blockIndexInPPO = (*ppoUniformBlockMap)[static_cast<uint32_t>(blockIndex)];
2038*8975f5c5SAndroid Build Coastguard Worker         ASSERT(blockIndexInPPO < mUniformBlocks.size());
2039*8975f5c5SAndroid Build Coastguard Worker 
2040*8975f5c5SAndroid Build Coastguard Worker         // Set the block buffer binding in the PPO to the same binding as the program's.
2041*8975f5c5SAndroid Build Coastguard Worker         remapUniformBlockBinding({blockIndexInPPO}, executable.getUniformBlockBinding(blockIndex));
2042*8975f5c5SAndroid Build Coastguard Worker     }
2043*8975f5c5SAndroid Build Coastguard Worker }
2044*8975f5c5SAndroid Build Coastguard Worker 
copyStorageBuffersFromProgram(const ProgramExecutable & executable,ShaderType shaderType)2045*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::copyStorageBuffersFromProgram(const ProgramExecutable &executable,
2046*8975f5c5SAndroid Build Coastguard Worker                                                       ShaderType shaderType)
2047*8975f5c5SAndroid Build Coastguard Worker {
2048*8975f5c5SAndroid Build Coastguard Worker     AppendActiveBlocks(shaderType, executable.getShaderStorageBlocks(), mShaderStorageBlocks,
2049*8975f5c5SAndroid Build Coastguard Worker                        nullptr);
2050*8975f5c5SAndroid Build Coastguard Worker     AppendActiveBlocks(shaderType, executable.getAtomicCounterBuffers(), mAtomicCounterBuffers,
2051*8975f5c5SAndroid Build Coastguard Worker                        nullptr);
2052*8975f5c5SAndroid Build Coastguard Worker 
2053*8975f5c5SAndroid Build Coastguard Worker     // Buffer variable info is queried through the program, and program pipelines don't access it.
2054*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mBufferVariables.empty());
2055*8975f5c5SAndroid Build Coastguard Worker }
2056*8975f5c5SAndroid Build Coastguard Worker 
clearSamplerBindings()2057*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::clearSamplerBindings()
2058*8975f5c5SAndroid Build Coastguard Worker {
2059*8975f5c5SAndroid Build Coastguard Worker     mSamplerBindings.clear();
2060*8975f5c5SAndroid Build Coastguard Worker     mSamplerBoundTextureUnits.clear();
2061*8975f5c5SAndroid Build Coastguard Worker }
2062*8975f5c5SAndroid Build Coastguard Worker 
copySamplerBindingsFromProgram(const ProgramExecutable & executable)2063*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::copySamplerBindingsFromProgram(const ProgramExecutable &executable)
2064*8975f5c5SAndroid Build Coastguard Worker {
2065*8975f5c5SAndroid Build Coastguard Worker     const std::vector<SamplerBinding> &bindings = executable.getSamplerBindings();
2066*8975f5c5SAndroid Build Coastguard Worker     const std::vector<GLuint> &textureUnits     = executable.getSamplerBoundTextureUnits();
2067*8975f5c5SAndroid Build Coastguard Worker     uint16_t adjustedStartIndex                 = mSamplerBoundTextureUnits.size();
2068*8975f5c5SAndroid Build Coastguard Worker     mSamplerBoundTextureUnits.insert(mSamplerBoundTextureUnits.end(), textureUnits.begin(),
2069*8975f5c5SAndroid Build Coastguard Worker                                      textureUnits.end());
2070*8975f5c5SAndroid Build Coastguard Worker     for (const SamplerBinding &binding : bindings)
2071*8975f5c5SAndroid Build Coastguard Worker     {
2072*8975f5c5SAndroid Build Coastguard Worker         mSamplerBindings.push_back(binding);
2073*8975f5c5SAndroid Build Coastguard Worker         mSamplerBindings.back().textureUnitsStartIndex += adjustedStartIndex;
2074*8975f5c5SAndroid Build Coastguard Worker     }
2075*8975f5c5SAndroid Build Coastguard Worker }
2076*8975f5c5SAndroid Build Coastguard Worker 
copyImageBindingsFromProgram(const ProgramExecutable & executable)2077*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::copyImageBindingsFromProgram(const ProgramExecutable &executable)
2078*8975f5c5SAndroid Build Coastguard Worker {
2079*8975f5c5SAndroid Build Coastguard Worker     const std::vector<ImageBinding> &bindings = executable.getImageBindings();
2080*8975f5c5SAndroid Build Coastguard Worker     mImageBindings.insert(mImageBindings.end(), bindings.begin(), bindings.end());
2081*8975f5c5SAndroid Build Coastguard Worker }
2082*8975f5c5SAndroid Build Coastguard Worker 
copyOutputsFromProgram(const ProgramExecutable & executable)2083*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::copyOutputsFromProgram(const ProgramExecutable &executable)
2084*8975f5c5SAndroid Build Coastguard Worker {
2085*8975f5c5SAndroid Build Coastguard Worker     mOutputVariables          = executable.getOutputVariables();
2086*8975f5c5SAndroid Build Coastguard Worker     mOutputLocations          = executable.getOutputLocations();
2087*8975f5c5SAndroid Build Coastguard Worker     mSecondaryOutputLocations = executable.getSecondaryOutputLocations();
2088*8975f5c5SAndroid Build Coastguard Worker }
2089*8975f5c5SAndroid Build Coastguard Worker 
copyUniformsFromProgramMap(const ShaderMap<SharedProgramExecutable> & executables)2090*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::copyUniformsFromProgramMap(
2091*8975f5c5SAndroid Build Coastguard Worker     const ShaderMap<SharedProgramExecutable> &executables)
2092*8975f5c5SAndroid Build Coastguard Worker {
2093*8975f5c5SAndroid Build Coastguard Worker     // Merge default uniforms.
2094*8975f5c5SAndroid Build Coastguard Worker     auto getDefaultRange = [](const ProgramExecutable &state) {
2095*8975f5c5SAndroid Build Coastguard Worker         return state.getDefaultUniformRange();
2096*8975f5c5SAndroid Build Coastguard Worker     };
2097*8975f5c5SAndroid Build Coastguard Worker     mPod.defaultUniformRange = AddUniforms(executables, mPod.linkedShaderStages, &mUniforms,
2098*8975f5c5SAndroid Build Coastguard Worker                                            &mUniformNames, &mUniformMappedNames, getDefaultRange);
2099*8975f5c5SAndroid Build Coastguard Worker 
2100*8975f5c5SAndroid Build Coastguard Worker     // Merge sampler uniforms.
2101*8975f5c5SAndroid Build Coastguard Worker     auto getSamplerRange = [](const ProgramExecutable &state) {
2102*8975f5c5SAndroid Build Coastguard Worker         return state.getSamplerUniformRange();
2103*8975f5c5SAndroid Build Coastguard Worker     };
2104*8975f5c5SAndroid Build Coastguard Worker     mPod.samplerUniformRange = AddUniforms(executables, mPod.linkedShaderStages, &mUniforms,
2105*8975f5c5SAndroid Build Coastguard Worker                                            &mUniformNames, &mUniformMappedNames, getSamplerRange);
2106*8975f5c5SAndroid Build Coastguard Worker 
2107*8975f5c5SAndroid Build Coastguard Worker     // Merge image uniforms.
2108*8975f5c5SAndroid Build Coastguard Worker     auto getImageRange = [](const ProgramExecutable &state) {
2109*8975f5c5SAndroid Build Coastguard Worker         return state.getImageUniformRange();
2110*8975f5c5SAndroid Build Coastguard Worker     };
2111*8975f5c5SAndroid Build Coastguard Worker     mPod.imageUniformRange = AddUniforms(executables, mPod.linkedShaderStages, &mUniforms,
2112*8975f5c5SAndroid Build Coastguard Worker                                          &mUniformNames, &mUniformMappedNames, getImageRange);
2113*8975f5c5SAndroid Build Coastguard Worker 
2114*8975f5c5SAndroid Build Coastguard Worker     // Merge atomic counter uniforms.
2115*8975f5c5SAndroid Build Coastguard Worker     auto getAtomicRange = [](const ProgramExecutable &state) {
2116*8975f5c5SAndroid Build Coastguard Worker         return state.getAtomicCounterUniformRange();
2117*8975f5c5SAndroid Build Coastguard Worker     };
2118*8975f5c5SAndroid Build Coastguard Worker     mPod.atomicCounterUniformRange =
2119*8975f5c5SAndroid Build Coastguard Worker         AddUniforms(executables, mPod.linkedShaderStages, &mUniforms, &mUniformNames,
2120*8975f5c5SAndroid Build Coastguard Worker                     &mUniformMappedNames, getAtomicRange);
2121*8975f5c5SAndroid Build Coastguard Worker 
2122*8975f5c5SAndroid Build Coastguard Worker     // Note: uniforms are set through the program, and the program pipeline never needs it.
2123*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mUniformLocations.empty());
2124*8975f5c5SAndroid Build Coastguard Worker }
2125*8975f5c5SAndroid Build Coastguard Worker 
getResourceName(const std::string name,GLsizei bufSize,GLsizei * length,GLchar * dest) const2126*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::getResourceName(const std::string name,
2127*8975f5c5SAndroid Build Coastguard Worker                                         GLsizei bufSize,
2128*8975f5c5SAndroid Build Coastguard Worker                                         GLsizei *length,
2129*8975f5c5SAndroid Build Coastguard Worker                                         GLchar *dest) const
2130*8975f5c5SAndroid Build Coastguard Worker {
2131*8975f5c5SAndroid Build Coastguard Worker     if (length)
2132*8975f5c5SAndroid Build Coastguard Worker     {
2133*8975f5c5SAndroid Build Coastguard Worker         *length = 0;
2134*8975f5c5SAndroid Build Coastguard Worker     }
2135*8975f5c5SAndroid Build Coastguard Worker 
2136*8975f5c5SAndroid Build Coastguard Worker     if (bufSize > 0)
2137*8975f5c5SAndroid Build Coastguard Worker     {
2138*8975f5c5SAndroid Build Coastguard Worker         CopyStringToBuffer(dest, name, bufSize, length);
2139*8975f5c5SAndroid Build Coastguard Worker     }
2140*8975f5c5SAndroid Build Coastguard Worker }
2141*8975f5c5SAndroid Build Coastguard Worker 
getInputResourceIndex(const GLchar * name) const2142*8975f5c5SAndroid Build Coastguard Worker GLuint ProgramExecutable::getInputResourceIndex(const GLchar *name) const
2143*8975f5c5SAndroid Build Coastguard Worker {
2144*8975f5c5SAndroid Build Coastguard Worker     const std::string nameString = StripLastArrayIndex(name);
2145*8975f5c5SAndroid Build Coastguard Worker 
2146*8975f5c5SAndroid Build Coastguard Worker     for (size_t index = 0; index < mProgramInputs.size(); index++)
2147*8975f5c5SAndroid Build Coastguard Worker     {
2148*8975f5c5SAndroid Build Coastguard Worker         if (mProgramInputs[index].name == nameString)
2149*8975f5c5SAndroid Build Coastguard Worker         {
2150*8975f5c5SAndroid Build Coastguard Worker             return static_cast<GLuint>(index);
2151*8975f5c5SAndroid Build Coastguard Worker         }
2152*8975f5c5SAndroid Build Coastguard Worker     }
2153*8975f5c5SAndroid Build Coastguard Worker 
2154*8975f5c5SAndroid Build Coastguard Worker     return GL_INVALID_INDEX;
2155*8975f5c5SAndroid Build Coastguard Worker }
2156*8975f5c5SAndroid Build Coastguard Worker 
getInputResourceMaxNameSize() const2157*8975f5c5SAndroid Build Coastguard Worker GLuint ProgramExecutable::getInputResourceMaxNameSize() const
2158*8975f5c5SAndroid Build Coastguard Worker {
2159*8975f5c5SAndroid Build Coastguard Worker     GLint max = 0;
2160*8975f5c5SAndroid Build Coastguard Worker 
2161*8975f5c5SAndroid Build Coastguard Worker     for (const ProgramInput &resource : mProgramInputs)
2162*8975f5c5SAndroid Build Coastguard Worker     {
2163*8975f5c5SAndroid Build Coastguard Worker         max = GetResourceMaxNameSize(resource, max);
2164*8975f5c5SAndroid Build Coastguard Worker     }
2165*8975f5c5SAndroid Build Coastguard Worker 
2166*8975f5c5SAndroid Build Coastguard Worker     return max;
2167*8975f5c5SAndroid Build Coastguard Worker }
2168*8975f5c5SAndroid Build Coastguard Worker 
getOutputResourceMaxNameSize() const2169*8975f5c5SAndroid Build Coastguard Worker GLuint ProgramExecutable::getOutputResourceMaxNameSize() const
2170*8975f5c5SAndroid Build Coastguard Worker {
2171*8975f5c5SAndroid Build Coastguard Worker     GLint max = 0;
2172*8975f5c5SAndroid Build Coastguard Worker 
2173*8975f5c5SAndroid Build Coastguard Worker     for (const gl::ProgramOutput &resource : mOutputVariables)
2174*8975f5c5SAndroid Build Coastguard Worker     {
2175*8975f5c5SAndroid Build Coastguard Worker         max = GetResourceMaxNameSize(resource, max);
2176*8975f5c5SAndroid Build Coastguard Worker     }
2177*8975f5c5SAndroid Build Coastguard Worker 
2178*8975f5c5SAndroid Build Coastguard Worker     return max;
2179*8975f5c5SAndroid Build Coastguard Worker }
2180*8975f5c5SAndroid Build Coastguard Worker 
getInputResourceLocation(const GLchar * name) const2181*8975f5c5SAndroid Build Coastguard Worker GLuint ProgramExecutable::getInputResourceLocation(const GLchar *name) const
2182*8975f5c5SAndroid Build Coastguard Worker {
2183*8975f5c5SAndroid Build Coastguard Worker     const GLuint index = getInputResourceIndex(name);
2184*8975f5c5SAndroid Build Coastguard Worker     if (index == GL_INVALID_INDEX)
2185*8975f5c5SAndroid Build Coastguard Worker     {
2186*8975f5c5SAndroid Build Coastguard Worker         return index;
2187*8975f5c5SAndroid Build Coastguard Worker     }
2188*8975f5c5SAndroid Build Coastguard Worker 
2189*8975f5c5SAndroid Build Coastguard Worker     const ProgramInput &variable = getInputResource(index);
2190*8975f5c5SAndroid Build Coastguard Worker 
2191*8975f5c5SAndroid Build Coastguard Worker     return GetResourceLocation(name, variable, variable.getLocation());
2192*8975f5c5SAndroid Build Coastguard Worker }
2193*8975f5c5SAndroid Build Coastguard Worker 
getOutputResourceLocation(const GLchar * name) const2194*8975f5c5SAndroid Build Coastguard Worker GLuint ProgramExecutable::getOutputResourceLocation(const GLchar *name) const
2195*8975f5c5SAndroid Build Coastguard Worker {
2196*8975f5c5SAndroid Build Coastguard Worker     const GLuint index = getOutputResourceIndex(name);
2197*8975f5c5SAndroid Build Coastguard Worker     if (index == GL_INVALID_INDEX)
2198*8975f5c5SAndroid Build Coastguard Worker     {
2199*8975f5c5SAndroid Build Coastguard Worker         return index;
2200*8975f5c5SAndroid Build Coastguard Worker     }
2201*8975f5c5SAndroid Build Coastguard Worker 
2202*8975f5c5SAndroid Build Coastguard Worker     const gl::ProgramOutput &variable = getOutputResource(index);
2203*8975f5c5SAndroid Build Coastguard Worker 
2204*8975f5c5SAndroid Build Coastguard Worker     return GetResourceLocation(name, variable, variable.pod.location);
2205*8975f5c5SAndroid Build Coastguard Worker }
2206*8975f5c5SAndroid Build Coastguard Worker 
getOutputResourceIndex(const GLchar * name) const2207*8975f5c5SAndroid Build Coastguard Worker GLuint ProgramExecutable::getOutputResourceIndex(const GLchar *name) const
2208*8975f5c5SAndroid Build Coastguard Worker {
2209*8975f5c5SAndroid Build Coastguard Worker     const std::string nameString = StripLastArrayIndex(name);
2210*8975f5c5SAndroid Build Coastguard Worker 
2211*8975f5c5SAndroid Build Coastguard Worker     for (size_t index = 0; index < mOutputVariables.size(); index++)
2212*8975f5c5SAndroid Build Coastguard Worker     {
2213*8975f5c5SAndroid Build Coastguard Worker         if (mOutputVariables[index].name == nameString)
2214*8975f5c5SAndroid Build Coastguard Worker         {
2215*8975f5c5SAndroid Build Coastguard Worker             return static_cast<GLuint>(index);
2216*8975f5c5SAndroid Build Coastguard Worker         }
2217*8975f5c5SAndroid Build Coastguard Worker     }
2218*8975f5c5SAndroid Build Coastguard Worker 
2219*8975f5c5SAndroid Build Coastguard Worker     return GL_INVALID_INDEX;
2220*8975f5c5SAndroid Build Coastguard Worker }
2221*8975f5c5SAndroid Build Coastguard Worker 
getInputResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2222*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::getInputResourceName(GLuint index,
2223*8975f5c5SAndroid Build Coastguard Worker                                              GLsizei bufSize,
2224*8975f5c5SAndroid Build Coastguard Worker                                              GLsizei *length,
2225*8975f5c5SAndroid Build Coastguard Worker                                              GLchar *name) const
2226*8975f5c5SAndroid Build Coastguard Worker {
2227*8975f5c5SAndroid Build Coastguard Worker     getResourceName(getInputResourceName(index), bufSize, length, name);
2228*8975f5c5SAndroid Build Coastguard Worker }
2229*8975f5c5SAndroid Build Coastguard Worker 
getOutputResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2230*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::getOutputResourceName(GLuint index,
2231*8975f5c5SAndroid Build Coastguard Worker                                               GLsizei bufSize,
2232*8975f5c5SAndroid Build Coastguard Worker                                               GLsizei *length,
2233*8975f5c5SAndroid Build Coastguard Worker                                               GLchar *name) const
2234*8975f5c5SAndroid Build Coastguard Worker {
2235*8975f5c5SAndroid Build Coastguard Worker     getResourceName(getOutputResourceName(index), bufSize, length, name);
2236*8975f5c5SAndroid Build Coastguard Worker }
2237*8975f5c5SAndroid Build Coastguard Worker 
getUniformResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2238*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::getUniformResourceName(GLuint index,
2239*8975f5c5SAndroid Build Coastguard Worker                                                GLsizei bufSize,
2240*8975f5c5SAndroid Build Coastguard Worker                                                GLsizei *length,
2241*8975f5c5SAndroid Build Coastguard Worker                                                GLchar *name) const
2242*8975f5c5SAndroid Build Coastguard Worker {
2243*8975f5c5SAndroid Build Coastguard Worker     getResourceName(getUniformNameByIndex(index), bufSize, length, name);
2244*8975f5c5SAndroid Build Coastguard Worker }
2245*8975f5c5SAndroid Build Coastguard Worker 
getBufferVariableResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2246*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::getBufferVariableResourceName(GLuint index,
2247*8975f5c5SAndroid Build Coastguard Worker                                                       GLsizei bufSize,
2248*8975f5c5SAndroid Build Coastguard Worker                                                       GLsizei *length,
2249*8975f5c5SAndroid Build Coastguard Worker                                                       GLchar *name) const
2250*8975f5c5SAndroid Build Coastguard Worker {
2251*8975f5c5SAndroid Build Coastguard Worker     ASSERT(index < mBufferVariables.size());
2252*8975f5c5SAndroid Build Coastguard Worker     getResourceName(mBufferVariables[index].name, bufSize, length, name);
2253*8975f5c5SAndroid Build Coastguard Worker }
2254*8975f5c5SAndroid Build Coastguard Worker 
getInputResourceName(GLuint index) const2255*8975f5c5SAndroid Build Coastguard Worker const std::string ProgramExecutable::getInputResourceName(GLuint index) const
2256*8975f5c5SAndroid Build Coastguard Worker {
2257*8975f5c5SAndroid Build Coastguard Worker     return GetResourceName(getInputResource(index));
2258*8975f5c5SAndroid Build Coastguard Worker }
2259*8975f5c5SAndroid Build Coastguard Worker 
getOutputResourceName(GLuint index) const2260*8975f5c5SAndroid Build Coastguard Worker const std::string ProgramExecutable::getOutputResourceName(GLuint index) const
2261*8975f5c5SAndroid Build Coastguard Worker {
2262*8975f5c5SAndroid Build Coastguard Worker     return GetResourceName(getOutputResource(index));
2263*8975f5c5SAndroid Build Coastguard Worker }
2264*8975f5c5SAndroid Build Coastguard Worker 
getFragDataLocation(const std::string & name) const2265*8975f5c5SAndroid Build Coastguard Worker GLint ProgramExecutable::getFragDataLocation(const std::string &name) const
2266*8975f5c5SAndroid Build Coastguard Worker {
2267*8975f5c5SAndroid Build Coastguard Worker     const GLint primaryLocation = GetVariableLocation(mOutputVariables, mOutputLocations, name);
2268*8975f5c5SAndroid Build Coastguard Worker     if (primaryLocation != -1)
2269*8975f5c5SAndroid Build Coastguard Worker     {
2270*8975f5c5SAndroid Build Coastguard Worker         return primaryLocation;
2271*8975f5c5SAndroid Build Coastguard Worker     }
2272*8975f5c5SAndroid Build Coastguard Worker     return GetVariableLocation(mOutputVariables, mSecondaryOutputLocations, name);
2273*8975f5c5SAndroid Build Coastguard Worker }
2274*8975f5c5SAndroid Build Coastguard Worker 
getFragDataIndex(const std::string & name) const2275*8975f5c5SAndroid Build Coastguard Worker GLint ProgramExecutable::getFragDataIndex(const std::string &name) const
2276*8975f5c5SAndroid Build Coastguard Worker {
2277*8975f5c5SAndroid Build Coastguard Worker     if (GetVariableLocation(mOutputVariables, mOutputLocations, name) != -1)
2278*8975f5c5SAndroid Build Coastguard Worker     {
2279*8975f5c5SAndroid Build Coastguard Worker         return 0;
2280*8975f5c5SAndroid Build Coastguard Worker     }
2281*8975f5c5SAndroid Build Coastguard Worker     if (GetVariableLocation(mOutputVariables, mSecondaryOutputLocations, name) != -1)
2282*8975f5c5SAndroid Build Coastguard Worker     {
2283*8975f5c5SAndroid Build Coastguard Worker         return 1;
2284*8975f5c5SAndroid Build Coastguard Worker     }
2285*8975f5c5SAndroid Build Coastguard Worker     return -1;
2286*8975f5c5SAndroid Build Coastguard Worker }
2287*8975f5c5SAndroid Build Coastguard Worker 
getTransformFeedbackVaryingMaxLength() const2288*8975f5c5SAndroid Build Coastguard Worker GLsizei ProgramExecutable::getTransformFeedbackVaryingMaxLength() const
2289*8975f5c5SAndroid Build Coastguard Worker {
2290*8975f5c5SAndroid Build Coastguard Worker     GLsizei maxSize = 0;
2291*8975f5c5SAndroid Build Coastguard Worker     for (const TransformFeedbackVarying &var : mLinkedTransformFeedbackVaryings)
2292*8975f5c5SAndroid Build Coastguard Worker     {
2293*8975f5c5SAndroid Build Coastguard Worker         maxSize = std::max(maxSize, static_cast<GLsizei>(var.nameWithArrayIndex().length() + 1));
2294*8975f5c5SAndroid Build Coastguard Worker     }
2295*8975f5c5SAndroid Build Coastguard Worker 
2296*8975f5c5SAndroid Build Coastguard Worker     return maxSize;
2297*8975f5c5SAndroid Build Coastguard Worker }
2298*8975f5c5SAndroid Build Coastguard Worker 
getTransformFeedbackVaryingResourceIndex(const GLchar * name) const2299*8975f5c5SAndroid Build Coastguard Worker GLuint ProgramExecutable::getTransformFeedbackVaryingResourceIndex(const GLchar *name) const
2300*8975f5c5SAndroid Build Coastguard Worker {
2301*8975f5c5SAndroid Build Coastguard Worker     for (GLuint tfIndex = 0; tfIndex < mLinkedTransformFeedbackVaryings.size(); ++tfIndex)
2302*8975f5c5SAndroid Build Coastguard Worker     {
2303*8975f5c5SAndroid Build Coastguard Worker         if (mLinkedTransformFeedbackVaryings[tfIndex].nameWithArrayIndex() == name)
2304*8975f5c5SAndroid Build Coastguard Worker         {
2305*8975f5c5SAndroid Build Coastguard Worker             return tfIndex;
2306*8975f5c5SAndroid Build Coastguard Worker         }
2307*8975f5c5SAndroid Build Coastguard Worker     }
2308*8975f5c5SAndroid Build Coastguard Worker     return GL_INVALID_INDEX;
2309*8975f5c5SAndroid Build Coastguard Worker }
2310*8975f5c5SAndroid Build Coastguard Worker 
getTransformFeedbackVaryingResource(GLuint index) const2311*8975f5c5SAndroid Build Coastguard Worker const TransformFeedbackVarying &ProgramExecutable::getTransformFeedbackVaryingResource(
2312*8975f5c5SAndroid Build Coastguard Worker     GLuint index) const
2313*8975f5c5SAndroid Build Coastguard Worker {
2314*8975f5c5SAndroid Build Coastguard Worker     ASSERT(index < mLinkedTransformFeedbackVaryings.size());
2315*8975f5c5SAndroid Build Coastguard Worker     return mLinkedTransformFeedbackVaryings[index];
2316*8975f5c5SAndroid Build Coastguard Worker }
2317*8975f5c5SAndroid Build Coastguard Worker 
getTransformFeedbackVarying(GLuint index,GLsizei bufSize,GLsizei * length,GLsizei * size,GLenum * type,GLchar * name) const2318*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::getTransformFeedbackVarying(GLuint index,
2319*8975f5c5SAndroid Build Coastguard Worker                                                     GLsizei bufSize,
2320*8975f5c5SAndroid Build Coastguard Worker                                                     GLsizei *length,
2321*8975f5c5SAndroid Build Coastguard Worker                                                     GLsizei *size,
2322*8975f5c5SAndroid Build Coastguard Worker                                                     GLenum *type,
2323*8975f5c5SAndroid Build Coastguard Worker                                                     GLchar *name) const
2324*8975f5c5SAndroid Build Coastguard Worker {
2325*8975f5c5SAndroid Build Coastguard Worker     if (mLinkedTransformFeedbackVaryings.empty())
2326*8975f5c5SAndroid Build Coastguard Worker     {
2327*8975f5c5SAndroid Build Coastguard Worker         // Program is not successfully linked
2328*8975f5c5SAndroid Build Coastguard Worker         return;
2329*8975f5c5SAndroid Build Coastguard Worker     }
2330*8975f5c5SAndroid Build Coastguard Worker 
2331*8975f5c5SAndroid Build Coastguard Worker     ASSERT(index < mLinkedTransformFeedbackVaryings.size());
2332*8975f5c5SAndroid Build Coastguard Worker     const auto &var     = mLinkedTransformFeedbackVaryings[index];
2333*8975f5c5SAndroid Build Coastguard Worker     std::string varName = var.nameWithArrayIndex();
2334*8975f5c5SAndroid Build Coastguard Worker     GLsizei lastNameIdx = std::min(bufSize - 1, static_cast<GLsizei>(varName.length()));
2335*8975f5c5SAndroid Build Coastguard Worker     if (length)
2336*8975f5c5SAndroid Build Coastguard Worker     {
2337*8975f5c5SAndroid Build Coastguard Worker         *length = lastNameIdx;
2338*8975f5c5SAndroid Build Coastguard Worker     }
2339*8975f5c5SAndroid Build Coastguard Worker     if (size)
2340*8975f5c5SAndroid Build Coastguard Worker     {
2341*8975f5c5SAndroid Build Coastguard Worker         *size = var.size();
2342*8975f5c5SAndroid Build Coastguard Worker     }
2343*8975f5c5SAndroid Build Coastguard Worker     if (type)
2344*8975f5c5SAndroid Build Coastguard Worker     {
2345*8975f5c5SAndroid Build Coastguard Worker         *type = var.type;
2346*8975f5c5SAndroid Build Coastguard Worker     }
2347*8975f5c5SAndroid Build Coastguard Worker     if (name)
2348*8975f5c5SAndroid Build Coastguard Worker     {
2349*8975f5c5SAndroid Build Coastguard Worker         memcpy(name, varName.c_str(), lastNameIdx);
2350*8975f5c5SAndroid Build Coastguard Worker         name[lastNameIdx] = '\0';
2351*8975f5c5SAndroid Build Coastguard Worker     }
2352*8975f5c5SAndroid Build Coastguard Worker }
2353*8975f5c5SAndroid Build Coastguard Worker 
getActiveAttribute(GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,GLchar * name) const2354*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::getActiveAttribute(GLuint index,
2355*8975f5c5SAndroid Build Coastguard Worker                                            GLsizei bufsize,
2356*8975f5c5SAndroid Build Coastguard Worker                                            GLsizei *length,
2357*8975f5c5SAndroid Build Coastguard Worker                                            GLint *size,
2358*8975f5c5SAndroid Build Coastguard Worker                                            GLenum *type,
2359*8975f5c5SAndroid Build Coastguard Worker                                            GLchar *name) const
2360*8975f5c5SAndroid Build Coastguard Worker {
2361*8975f5c5SAndroid Build Coastguard Worker     if (mProgramInputs.empty())
2362*8975f5c5SAndroid Build Coastguard Worker     {
2363*8975f5c5SAndroid Build Coastguard Worker         // Program is not successfully linked
2364*8975f5c5SAndroid Build Coastguard Worker         if (bufsize > 0)
2365*8975f5c5SAndroid Build Coastguard Worker         {
2366*8975f5c5SAndroid Build Coastguard Worker             name[0] = '\0';
2367*8975f5c5SAndroid Build Coastguard Worker         }
2368*8975f5c5SAndroid Build Coastguard Worker 
2369*8975f5c5SAndroid Build Coastguard Worker         if (length)
2370*8975f5c5SAndroid Build Coastguard Worker         {
2371*8975f5c5SAndroid Build Coastguard Worker             *length = 0;
2372*8975f5c5SAndroid Build Coastguard Worker         }
2373*8975f5c5SAndroid Build Coastguard Worker 
2374*8975f5c5SAndroid Build Coastguard Worker         *type = GL_NONE;
2375*8975f5c5SAndroid Build Coastguard Worker         *size = 1;
2376*8975f5c5SAndroid Build Coastguard Worker         return;
2377*8975f5c5SAndroid Build Coastguard Worker     }
2378*8975f5c5SAndroid Build Coastguard Worker 
2379*8975f5c5SAndroid Build Coastguard Worker     ASSERT(index < mProgramInputs.size());
2380*8975f5c5SAndroid Build Coastguard Worker     const ProgramInput &attrib = mProgramInputs[index];
2381*8975f5c5SAndroid Build Coastguard Worker 
2382*8975f5c5SAndroid Build Coastguard Worker     if (bufsize > 0)
2383*8975f5c5SAndroid Build Coastguard Worker     {
2384*8975f5c5SAndroid Build Coastguard Worker         CopyStringToBuffer(name, attrib.name, bufsize, length);
2385*8975f5c5SAndroid Build Coastguard Worker     }
2386*8975f5c5SAndroid Build Coastguard Worker 
2387*8975f5c5SAndroid Build Coastguard Worker     // Always a single 'type' instance
2388*8975f5c5SAndroid Build Coastguard Worker     *size = 1;
2389*8975f5c5SAndroid Build Coastguard Worker     *type = attrib.getType();
2390*8975f5c5SAndroid Build Coastguard Worker }
2391*8975f5c5SAndroid Build Coastguard Worker 
getActiveAttributeMaxLength() const2392*8975f5c5SAndroid Build Coastguard Worker GLint ProgramExecutable::getActiveAttributeMaxLength() const
2393*8975f5c5SAndroid Build Coastguard Worker {
2394*8975f5c5SAndroid Build Coastguard Worker     size_t maxLength = 0;
2395*8975f5c5SAndroid Build Coastguard Worker 
2396*8975f5c5SAndroid Build Coastguard Worker     for (const ProgramInput &attrib : mProgramInputs)
2397*8975f5c5SAndroid Build Coastguard Worker     {
2398*8975f5c5SAndroid Build Coastguard Worker         maxLength = std::max(attrib.name.length() + 1, maxLength);
2399*8975f5c5SAndroid Build Coastguard Worker     }
2400*8975f5c5SAndroid Build Coastguard Worker 
2401*8975f5c5SAndroid Build Coastguard Worker     return static_cast<GLint>(maxLength);
2402*8975f5c5SAndroid Build Coastguard Worker }
2403*8975f5c5SAndroid Build Coastguard Worker 
getAttributeLocation(const std::string & name) const2404*8975f5c5SAndroid Build Coastguard Worker GLuint ProgramExecutable::getAttributeLocation(const std::string &name) const
2405*8975f5c5SAndroid Build Coastguard Worker {
2406*8975f5c5SAndroid Build Coastguard Worker     for (const ProgramInput &attribute : mProgramInputs)
2407*8975f5c5SAndroid Build Coastguard Worker     {
2408*8975f5c5SAndroid Build Coastguard Worker         if (attribute.name == name)
2409*8975f5c5SAndroid Build Coastguard Worker         {
2410*8975f5c5SAndroid Build Coastguard Worker             return attribute.getLocation();
2411*8975f5c5SAndroid Build Coastguard Worker         }
2412*8975f5c5SAndroid Build Coastguard Worker     }
2413*8975f5c5SAndroid Build Coastguard Worker 
2414*8975f5c5SAndroid Build Coastguard Worker     return static_cast<GLuint>(-1);
2415*8975f5c5SAndroid Build Coastguard Worker }
2416*8975f5c5SAndroid Build Coastguard Worker 
getActiveUniform(GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,GLchar * name) const2417*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::getActiveUniform(GLuint index,
2418*8975f5c5SAndroid Build Coastguard Worker                                          GLsizei bufsize,
2419*8975f5c5SAndroid Build Coastguard Worker                                          GLsizei *length,
2420*8975f5c5SAndroid Build Coastguard Worker                                          GLint *size,
2421*8975f5c5SAndroid Build Coastguard Worker                                          GLenum *type,
2422*8975f5c5SAndroid Build Coastguard Worker                                          GLchar *name) const
2423*8975f5c5SAndroid Build Coastguard Worker {
2424*8975f5c5SAndroid Build Coastguard Worker     if (mUniforms.empty())
2425*8975f5c5SAndroid Build Coastguard Worker     {
2426*8975f5c5SAndroid Build Coastguard Worker         // Program is not successfully linked
2427*8975f5c5SAndroid Build Coastguard Worker         if (bufsize > 0)
2428*8975f5c5SAndroid Build Coastguard Worker         {
2429*8975f5c5SAndroid Build Coastguard Worker             name[0] = '\0';
2430*8975f5c5SAndroid Build Coastguard Worker         }
2431*8975f5c5SAndroid Build Coastguard Worker 
2432*8975f5c5SAndroid Build Coastguard Worker         if (length)
2433*8975f5c5SAndroid Build Coastguard Worker         {
2434*8975f5c5SAndroid Build Coastguard Worker             *length = 0;
2435*8975f5c5SAndroid Build Coastguard Worker         }
2436*8975f5c5SAndroid Build Coastguard Worker 
2437*8975f5c5SAndroid Build Coastguard Worker         *size = 0;
2438*8975f5c5SAndroid Build Coastguard Worker         *type = GL_NONE;
2439*8975f5c5SAndroid Build Coastguard Worker     }
2440*8975f5c5SAndroid Build Coastguard Worker 
2441*8975f5c5SAndroid Build Coastguard Worker     ASSERT(index < mUniforms.size());
2442*8975f5c5SAndroid Build Coastguard Worker     const LinkedUniform &uniform = mUniforms[index];
2443*8975f5c5SAndroid Build Coastguard Worker 
2444*8975f5c5SAndroid Build Coastguard Worker     if (bufsize > 0)
2445*8975f5c5SAndroid Build Coastguard Worker     {
2446*8975f5c5SAndroid Build Coastguard Worker         const std::string &string = getUniformNameByIndex(index);
2447*8975f5c5SAndroid Build Coastguard Worker         CopyStringToBuffer(name, string, bufsize, length);
2448*8975f5c5SAndroid Build Coastguard Worker     }
2449*8975f5c5SAndroid Build Coastguard Worker 
2450*8975f5c5SAndroid Build Coastguard Worker     *size = clampCast<GLint>(uniform.getBasicTypeElementCount());
2451*8975f5c5SAndroid Build Coastguard Worker     *type = uniform.getType();
2452*8975f5c5SAndroid Build Coastguard Worker }
2453*8975f5c5SAndroid Build Coastguard Worker 
getActiveUniformMaxLength() const2454*8975f5c5SAndroid Build Coastguard Worker GLint ProgramExecutable::getActiveUniformMaxLength() const
2455*8975f5c5SAndroid Build Coastguard Worker {
2456*8975f5c5SAndroid Build Coastguard Worker     size_t maxLength = 0;
2457*8975f5c5SAndroid Build Coastguard Worker 
2458*8975f5c5SAndroid Build Coastguard Worker     for (GLuint index = 0; index < static_cast<size_t>(mUniformNames.size()); index++)
2459*8975f5c5SAndroid Build Coastguard Worker     {
2460*8975f5c5SAndroid Build Coastguard Worker         const std::string &uniformName = getUniformNameByIndex(index);
2461*8975f5c5SAndroid Build Coastguard Worker         if (!uniformName.empty())
2462*8975f5c5SAndroid Build Coastguard Worker         {
2463*8975f5c5SAndroid Build Coastguard Worker             size_t length = uniformName.length() + 1u;
2464*8975f5c5SAndroid Build Coastguard Worker             if (getUniformByIndex(index).isArray())
2465*8975f5c5SAndroid Build Coastguard Worker             {
2466*8975f5c5SAndroid Build Coastguard Worker                 length += 3;  // Counting in "[0]".
2467*8975f5c5SAndroid Build Coastguard Worker             }
2468*8975f5c5SAndroid Build Coastguard Worker             maxLength = std::max(length, maxLength);
2469*8975f5c5SAndroid Build Coastguard Worker         }
2470*8975f5c5SAndroid Build Coastguard Worker     }
2471*8975f5c5SAndroid Build Coastguard Worker 
2472*8975f5c5SAndroid Build Coastguard Worker     return static_cast<GLint>(maxLength);
2473*8975f5c5SAndroid Build Coastguard Worker }
2474*8975f5c5SAndroid Build Coastguard Worker 
isValidUniformLocation(UniformLocation location) const2475*8975f5c5SAndroid Build Coastguard Worker bool ProgramExecutable::isValidUniformLocation(UniformLocation location) const
2476*8975f5c5SAndroid Build Coastguard Worker {
2477*8975f5c5SAndroid Build Coastguard Worker     ASSERT(angle::IsValueInRangeForNumericType<GLint>(mUniformLocations.size()));
2478*8975f5c5SAndroid Build Coastguard Worker     return location.value >= 0 && static_cast<size_t>(location.value) < mUniformLocations.size() &&
2479*8975f5c5SAndroid Build Coastguard Worker            mUniformLocations[location.value].used();
2480*8975f5c5SAndroid Build Coastguard Worker }
2481*8975f5c5SAndroid Build Coastguard Worker 
getUniformByLocation(UniformLocation location) const2482*8975f5c5SAndroid Build Coastguard Worker const LinkedUniform &ProgramExecutable::getUniformByLocation(UniformLocation location) const
2483*8975f5c5SAndroid Build Coastguard Worker {
2484*8975f5c5SAndroid Build Coastguard Worker     ASSERT(location.value >= 0 && static_cast<size_t>(location.value) < mUniformLocations.size());
2485*8975f5c5SAndroid Build Coastguard Worker     return mUniforms[getUniformIndexFromLocation(location)];
2486*8975f5c5SAndroid Build Coastguard Worker }
2487*8975f5c5SAndroid Build Coastguard Worker 
getUniformLocation(UniformLocation location) const2488*8975f5c5SAndroid Build Coastguard Worker const VariableLocation &ProgramExecutable::getUniformLocation(UniformLocation location) const
2489*8975f5c5SAndroid Build Coastguard Worker {
2490*8975f5c5SAndroid Build Coastguard Worker     ASSERT(location.value >= 0 && static_cast<size_t>(location.value) < mUniformLocations.size());
2491*8975f5c5SAndroid Build Coastguard Worker     return mUniformLocations[location.value];
2492*8975f5c5SAndroid Build Coastguard Worker }
2493*8975f5c5SAndroid Build Coastguard Worker 
getUniformLocation(const std::string & name) const2494*8975f5c5SAndroid Build Coastguard Worker UniformLocation ProgramExecutable::getUniformLocation(const std::string &name) const
2495*8975f5c5SAndroid Build Coastguard Worker {
2496*8975f5c5SAndroid Build Coastguard Worker     return {GetUniformLocation(mUniforms, mUniformNames, mUniformLocations, name)};
2497*8975f5c5SAndroid Build Coastguard Worker }
2498*8975f5c5SAndroid Build Coastguard Worker 
getUniformIndex(const std::string & name) const2499*8975f5c5SAndroid Build Coastguard Worker GLuint ProgramExecutable::getUniformIndex(const std::string &name) const
2500*8975f5c5SAndroid Build Coastguard Worker {
2501*8975f5c5SAndroid Build Coastguard Worker     return getUniformIndexFromName(name);
2502*8975f5c5SAndroid Build Coastguard Worker }
2503*8975f5c5SAndroid Build Coastguard Worker 
shouldIgnoreUniform(UniformLocation location) const2504*8975f5c5SAndroid Build Coastguard Worker bool ProgramExecutable::shouldIgnoreUniform(UniformLocation location) const
2505*8975f5c5SAndroid Build Coastguard Worker {
2506*8975f5c5SAndroid Build Coastguard Worker     // Casting to size_t will convert negative values to large positive avoiding double check.
2507*8975f5c5SAndroid Build Coastguard Worker     // Adding ERR() log to report out of bound location harms performance on Android.
2508*8975f5c5SAndroid Build Coastguard Worker     return ANGLE_UNLIKELY(static_cast<size_t>(location.value) >= mUniformLocations.size() ||
2509*8975f5c5SAndroid Build Coastguard Worker                           mUniformLocations[location.value].ignored);
2510*8975f5c5SAndroid Build Coastguard Worker }
2511*8975f5c5SAndroid Build Coastguard Worker 
getUniformIndexFromName(const std::string & name) const2512*8975f5c5SAndroid Build Coastguard Worker GLuint ProgramExecutable::getUniformIndexFromName(const std::string &name) const
2513*8975f5c5SAndroid Build Coastguard Worker {
2514*8975f5c5SAndroid Build Coastguard Worker     return GetUniformIndexFromName(mUniforms, mUniformNames, name);
2515*8975f5c5SAndroid Build Coastguard Worker }
2516*8975f5c5SAndroid Build Coastguard Worker 
getBufferVariableIndexFromName(const std::string & name) const2517*8975f5c5SAndroid Build Coastguard Worker GLuint ProgramExecutable::getBufferVariableIndexFromName(const std::string &name) const
2518*8975f5c5SAndroid Build Coastguard Worker {
2519*8975f5c5SAndroid Build Coastguard Worker     return GetResourceIndexFromName(mBufferVariables, name);
2520*8975f5c5SAndroid Build Coastguard Worker }
2521*8975f5c5SAndroid Build Coastguard Worker 
getUniformIndexFromLocation(UniformLocation location) const2522*8975f5c5SAndroid Build Coastguard Worker GLuint ProgramExecutable::getUniformIndexFromLocation(UniformLocation location) const
2523*8975f5c5SAndroid Build Coastguard Worker {
2524*8975f5c5SAndroid Build Coastguard Worker     ASSERT(location.value >= 0 && static_cast<size_t>(location.value) < mUniformLocations.size());
2525*8975f5c5SAndroid Build Coastguard Worker     return mUniformLocations[location.value].index;
2526*8975f5c5SAndroid Build Coastguard Worker }
2527*8975f5c5SAndroid Build Coastguard Worker 
getSamplerIndex(UniformLocation location) const2528*8975f5c5SAndroid Build Coastguard Worker Optional<GLuint> ProgramExecutable::getSamplerIndex(UniformLocation location) const
2529*8975f5c5SAndroid Build Coastguard Worker {
2530*8975f5c5SAndroid Build Coastguard Worker     GLuint index = getUniformIndexFromLocation(location);
2531*8975f5c5SAndroid Build Coastguard Worker     if (!isSamplerUniformIndex(index))
2532*8975f5c5SAndroid Build Coastguard Worker     {
2533*8975f5c5SAndroid Build Coastguard Worker         return Optional<GLuint>::Invalid();
2534*8975f5c5SAndroid Build Coastguard Worker     }
2535*8975f5c5SAndroid Build Coastguard Worker 
2536*8975f5c5SAndroid Build Coastguard Worker     return getSamplerIndexFromUniformIndex(index);
2537*8975f5c5SAndroid Build Coastguard Worker }
2538*8975f5c5SAndroid Build Coastguard Worker 
isSamplerUniformIndex(GLuint index) const2539*8975f5c5SAndroid Build Coastguard Worker bool ProgramExecutable::isSamplerUniformIndex(GLuint index) const
2540*8975f5c5SAndroid Build Coastguard Worker {
2541*8975f5c5SAndroid Build Coastguard Worker     return mPod.samplerUniformRange.contains(index);
2542*8975f5c5SAndroid Build Coastguard Worker }
2543*8975f5c5SAndroid Build Coastguard Worker 
getSamplerIndexFromUniformIndex(GLuint uniformIndex) const2544*8975f5c5SAndroid Build Coastguard Worker GLuint ProgramExecutable::getSamplerIndexFromUniformIndex(GLuint uniformIndex) const
2545*8975f5c5SAndroid Build Coastguard Worker {
2546*8975f5c5SAndroid Build Coastguard Worker     ASSERT(isSamplerUniformIndex(uniformIndex));
2547*8975f5c5SAndroid Build Coastguard Worker     return uniformIndex - mPod.samplerUniformRange.low();
2548*8975f5c5SAndroid Build Coastguard Worker }
2549*8975f5c5SAndroid Build Coastguard Worker 
isImageUniformIndex(GLuint index) const2550*8975f5c5SAndroid Build Coastguard Worker bool ProgramExecutable::isImageUniformIndex(GLuint index) const
2551*8975f5c5SAndroid Build Coastguard Worker {
2552*8975f5c5SAndroid Build Coastguard Worker     return mPod.imageUniformRange.contains(index);
2553*8975f5c5SAndroid Build Coastguard Worker }
2554*8975f5c5SAndroid Build Coastguard Worker 
getImageIndexFromUniformIndex(GLuint uniformIndex) const2555*8975f5c5SAndroid Build Coastguard Worker GLuint ProgramExecutable::getImageIndexFromUniformIndex(GLuint uniformIndex) const
2556*8975f5c5SAndroid Build Coastguard Worker {
2557*8975f5c5SAndroid Build Coastguard Worker     ASSERT(isImageUniformIndex(uniformIndex));
2558*8975f5c5SAndroid Build Coastguard Worker     return uniformIndex - mPod.imageUniformRange.low();
2559*8975f5c5SAndroid Build Coastguard Worker }
2560*8975f5c5SAndroid Build Coastguard Worker 
getActiveUniformBlockName(const Context * context,const UniformBlockIndex blockIndex,GLsizei bufSize,GLsizei * length,GLchar * blockName) const2561*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::getActiveUniformBlockName(const Context *context,
2562*8975f5c5SAndroid Build Coastguard Worker                                                   const UniformBlockIndex blockIndex,
2563*8975f5c5SAndroid Build Coastguard Worker                                                   GLsizei bufSize,
2564*8975f5c5SAndroid Build Coastguard Worker                                                   GLsizei *length,
2565*8975f5c5SAndroid Build Coastguard Worker                                                   GLchar *blockName) const
2566*8975f5c5SAndroid Build Coastguard Worker {
2567*8975f5c5SAndroid Build Coastguard Worker     GetInterfaceBlockName(blockIndex, mUniformBlocks, bufSize, length, blockName);
2568*8975f5c5SAndroid Build Coastguard Worker }
2569*8975f5c5SAndroid Build Coastguard Worker 
getActiveShaderStorageBlockName(const GLuint blockIndex,GLsizei bufSize,GLsizei * length,GLchar * blockName) const2570*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::getActiveShaderStorageBlockName(const GLuint blockIndex,
2571*8975f5c5SAndroid Build Coastguard Worker                                                         GLsizei bufSize,
2572*8975f5c5SAndroid Build Coastguard Worker                                                         GLsizei *length,
2573*8975f5c5SAndroid Build Coastguard Worker                                                         GLchar *blockName) const
2574*8975f5c5SAndroid Build Coastguard Worker {
2575*8975f5c5SAndroid Build Coastguard Worker     GetInterfaceBlockName({blockIndex}, mShaderStorageBlocks, bufSize, length, blockName);
2576*8975f5c5SAndroid Build Coastguard Worker }
2577*8975f5c5SAndroid Build Coastguard Worker 
getActiveUniformBlockMaxNameLength() const2578*8975f5c5SAndroid Build Coastguard Worker GLint ProgramExecutable::getActiveUniformBlockMaxNameLength() const
2579*8975f5c5SAndroid Build Coastguard Worker {
2580*8975f5c5SAndroid Build Coastguard Worker     return GetActiveInterfaceBlockMaxNameLength(mUniformBlocks);
2581*8975f5c5SAndroid Build Coastguard Worker }
2582*8975f5c5SAndroid Build Coastguard Worker 
getActiveShaderStorageBlockMaxNameLength() const2583*8975f5c5SAndroid Build Coastguard Worker GLint ProgramExecutable::getActiveShaderStorageBlockMaxNameLength() const
2584*8975f5c5SAndroid Build Coastguard Worker {
2585*8975f5c5SAndroid Build Coastguard Worker     return GetActiveInterfaceBlockMaxNameLength(mShaderStorageBlocks);
2586*8975f5c5SAndroid Build Coastguard Worker }
2587*8975f5c5SAndroid Build Coastguard Worker 
getUniformBlockIndex(const std::string & name) const2588*8975f5c5SAndroid Build Coastguard Worker GLuint ProgramExecutable::getUniformBlockIndex(const std::string &name) const
2589*8975f5c5SAndroid Build Coastguard Worker {
2590*8975f5c5SAndroid Build Coastguard Worker     return GetInterfaceBlockIndex(mUniformBlocks, name);
2591*8975f5c5SAndroid Build Coastguard Worker }
2592*8975f5c5SAndroid Build Coastguard Worker 
getShaderStorageBlockIndex(const std::string & name) const2593*8975f5c5SAndroid Build Coastguard Worker GLuint ProgramExecutable::getShaderStorageBlockIndex(const std::string &name) const
2594*8975f5c5SAndroid Build Coastguard Worker {
2595*8975f5c5SAndroid Build Coastguard Worker     return GetInterfaceBlockIndex(mShaderStorageBlocks, name);
2596*8975f5c5SAndroid Build Coastguard Worker }
2597*8975f5c5SAndroid Build Coastguard Worker 
getSamplerUniformBinding(const VariableLocation & uniformLocation) const2598*8975f5c5SAndroid Build Coastguard Worker GLuint ProgramExecutable::getSamplerUniformBinding(const VariableLocation &uniformLocation) const
2599*8975f5c5SAndroid Build Coastguard Worker {
2600*8975f5c5SAndroid Build Coastguard Worker     GLuint samplerIndex                  = getSamplerIndexFromUniformIndex(uniformLocation.index);
2601*8975f5c5SAndroid Build Coastguard Worker     const SamplerBinding &samplerBinding = mSamplerBindings[samplerIndex];
2602*8975f5c5SAndroid Build Coastguard Worker     if (uniformLocation.arrayIndex >= samplerBinding.textureUnitsCount)
2603*8975f5c5SAndroid Build Coastguard Worker     {
2604*8975f5c5SAndroid Build Coastguard Worker         return 0;
2605*8975f5c5SAndroid Build Coastguard Worker     }
2606*8975f5c5SAndroid Build Coastguard Worker 
2607*8975f5c5SAndroid Build Coastguard Worker     const std::vector<GLuint> &boundTextureUnits = mSamplerBoundTextureUnits;
2608*8975f5c5SAndroid Build Coastguard Worker     return samplerBinding.getTextureUnit(boundTextureUnits, uniformLocation.arrayIndex);
2609*8975f5c5SAndroid Build Coastguard Worker }
2610*8975f5c5SAndroid Build Coastguard Worker 
getImageUniformBinding(const VariableLocation & uniformLocation) const2611*8975f5c5SAndroid Build Coastguard Worker GLuint ProgramExecutable::getImageUniformBinding(const VariableLocation &uniformLocation) const
2612*8975f5c5SAndroid Build Coastguard Worker {
2613*8975f5c5SAndroid Build Coastguard Worker     GLuint imageIndex = getImageIndexFromUniformIndex(uniformLocation.index);
2614*8975f5c5SAndroid Build Coastguard Worker 
2615*8975f5c5SAndroid Build Coastguard Worker     const std::vector<GLuint> &boundImageUnits = mImageBindings[imageIndex].boundImageUnits;
2616*8975f5c5SAndroid Build Coastguard Worker     return boundImageUnits[uniformLocation.arrayIndex];
2617*8975f5c5SAndroid Build Coastguard Worker }
2618*8975f5c5SAndroid Build Coastguard Worker 
2619*8975f5c5SAndroid Build Coastguard Worker template <typename UniformT,
2620*8975f5c5SAndroid Build Coastguard Worker           GLint UniformSize,
2621*8975f5c5SAndroid Build Coastguard Worker           void (rx::ProgramExecutableImpl::*SetUniformFunc)(GLint, GLsizei, const UniformT *)>
setUniformGeneric(UniformLocation location,GLsizei count,const UniformT * v)2622*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::setUniformGeneric(UniformLocation location,
2623*8975f5c5SAndroid Build Coastguard Worker                                           GLsizei count,
2624*8975f5c5SAndroid Build Coastguard Worker                                           const UniformT *v)
2625*8975f5c5SAndroid Build Coastguard Worker {
2626*8975f5c5SAndroid Build Coastguard Worker     if (shouldIgnoreUniform(location))
2627*8975f5c5SAndroid Build Coastguard Worker     {
2628*8975f5c5SAndroid Build Coastguard Worker         return;
2629*8975f5c5SAndroid Build Coastguard Worker     }
2630*8975f5c5SAndroid Build Coastguard Worker 
2631*8975f5c5SAndroid Build Coastguard Worker     const VariableLocation &locationInfo = mUniformLocations[location.value];
2632*8975f5c5SAndroid Build Coastguard Worker     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, UniformSize, v);
2633*8975f5c5SAndroid Build Coastguard Worker     (mImplementation->*SetUniformFunc)(location.value, clampedCount, v);
2634*8975f5c5SAndroid Build Coastguard Worker }
2635*8975f5c5SAndroid Build Coastguard Worker 
setUniform1fv(UniformLocation location,GLsizei count,const GLfloat * v)2636*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::setUniform1fv(UniformLocation location, GLsizei count, const GLfloat *v)
2637*8975f5c5SAndroid Build Coastguard Worker {
2638*8975f5c5SAndroid Build Coastguard Worker     setUniformGeneric<GLfloat, 1, &rx::ProgramExecutableImpl::setUniform1fv>(location, count, v);
2639*8975f5c5SAndroid Build Coastguard Worker }
2640*8975f5c5SAndroid Build Coastguard Worker 
setUniform2fv(UniformLocation location,GLsizei count,const GLfloat * v)2641*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::setUniform2fv(UniformLocation location, GLsizei count, const GLfloat *v)
2642*8975f5c5SAndroid Build Coastguard Worker {
2643*8975f5c5SAndroid Build Coastguard Worker     setUniformGeneric<GLfloat, 2, &rx::ProgramExecutableImpl::setUniform2fv>(location, count, v);
2644*8975f5c5SAndroid Build Coastguard Worker }
2645*8975f5c5SAndroid Build Coastguard Worker 
setUniform3fv(UniformLocation location,GLsizei count,const GLfloat * v)2646*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::setUniform3fv(UniformLocation location, GLsizei count, const GLfloat *v)
2647*8975f5c5SAndroid Build Coastguard Worker {
2648*8975f5c5SAndroid Build Coastguard Worker     setUniformGeneric<GLfloat, 3, &rx::ProgramExecutableImpl::setUniform3fv>(location, count, v);
2649*8975f5c5SAndroid Build Coastguard Worker }
2650*8975f5c5SAndroid Build Coastguard Worker 
setUniform4fv(UniformLocation location,GLsizei count,const GLfloat * v)2651*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::setUniform4fv(UniformLocation location, GLsizei count, const GLfloat *v)
2652*8975f5c5SAndroid Build Coastguard Worker {
2653*8975f5c5SAndroid Build Coastguard Worker     setUniformGeneric<GLfloat, 4, &rx::ProgramExecutableImpl::setUniform4fv>(location, count, v);
2654*8975f5c5SAndroid Build Coastguard Worker }
2655*8975f5c5SAndroid Build Coastguard Worker 
setUniform1iv(Context * context,UniformLocation location,GLsizei count,const GLint * v)2656*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::setUniform1iv(Context *context,
2657*8975f5c5SAndroid Build Coastguard Worker                                       UniformLocation location,
2658*8975f5c5SAndroid Build Coastguard Worker                                       GLsizei count,
2659*8975f5c5SAndroid Build Coastguard Worker                                       const GLint *v)
2660*8975f5c5SAndroid Build Coastguard Worker {
2661*8975f5c5SAndroid Build Coastguard Worker     if (shouldIgnoreUniform(location))
2662*8975f5c5SAndroid Build Coastguard Worker     {
2663*8975f5c5SAndroid Build Coastguard Worker         return;
2664*8975f5c5SAndroid Build Coastguard Worker     }
2665*8975f5c5SAndroid Build Coastguard Worker 
2666*8975f5c5SAndroid Build Coastguard Worker     const VariableLocation &locationInfo = mUniformLocations[location.value];
2667*8975f5c5SAndroid Build Coastguard Worker     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 1, v);
2668*8975f5c5SAndroid Build Coastguard Worker 
2669*8975f5c5SAndroid Build Coastguard Worker     mImplementation->setUniform1iv(location.value, clampedCount, v);
2670*8975f5c5SAndroid Build Coastguard Worker 
2671*8975f5c5SAndroid Build Coastguard Worker     if (isSamplerUniformIndex(locationInfo.index))
2672*8975f5c5SAndroid Build Coastguard Worker     {
2673*8975f5c5SAndroid Build Coastguard Worker         updateSamplerUniform(context, locationInfo, clampedCount, v);
2674*8975f5c5SAndroid Build Coastguard Worker     }
2675*8975f5c5SAndroid Build Coastguard Worker }
2676*8975f5c5SAndroid Build Coastguard Worker 
setUniform2iv(UniformLocation location,GLsizei count,const GLint * v)2677*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::setUniform2iv(UniformLocation location, GLsizei count, const GLint *v)
2678*8975f5c5SAndroid Build Coastguard Worker {
2679*8975f5c5SAndroid Build Coastguard Worker     setUniformGeneric<GLint, 2, &rx::ProgramExecutableImpl::setUniform2iv>(location, count, v);
2680*8975f5c5SAndroid Build Coastguard Worker }
2681*8975f5c5SAndroid Build Coastguard Worker 
setUniform3iv(UniformLocation location,GLsizei count,const GLint * v)2682*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::setUniform3iv(UniformLocation location, GLsizei count, const GLint *v)
2683*8975f5c5SAndroid Build Coastguard Worker {
2684*8975f5c5SAndroid Build Coastguard Worker     setUniformGeneric<GLint, 3, &rx::ProgramExecutableImpl::setUniform3iv>(location, count, v);
2685*8975f5c5SAndroid Build Coastguard Worker }
2686*8975f5c5SAndroid Build Coastguard Worker 
setUniform4iv(UniformLocation location,GLsizei count,const GLint * v)2687*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::setUniform4iv(UniformLocation location, GLsizei count, const GLint *v)
2688*8975f5c5SAndroid Build Coastguard Worker {
2689*8975f5c5SAndroid Build Coastguard Worker     setUniformGeneric<GLint, 4, &rx::ProgramExecutableImpl::setUniform4iv>(location, count, v);
2690*8975f5c5SAndroid Build Coastguard Worker }
2691*8975f5c5SAndroid Build Coastguard Worker 
setUniform1uiv(UniformLocation location,GLsizei count,const GLuint * v)2692*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::setUniform1uiv(UniformLocation location, GLsizei count, const GLuint *v)
2693*8975f5c5SAndroid Build Coastguard Worker {
2694*8975f5c5SAndroid Build Coastguard Worker     setUniformGeneric<GLuint, 1, &rx::ProgramExecutableImpl::setUniform1uiv>(location, count, v);
2695*8975f5c5SAndroid Build Coastguard Worker }
2696*8975f5c5SAndroid Build Coastguard Worker 
setUniform2uiv(UniformLocation location,GLsizei count,const GLuint * v)2697*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::setUniform2uiv(UniformLocation location, GLsizei count, const GLuint *v)
2698*8975f5c5SAndroid Build Coastguard Worker {
2699*8975f5c5SAndroid Build Coastguard Worker     setUniformGeneric<GLuint, 2, &rx::ProgramExecutableImpl::setUniform2uiv>(location, count, v);
2700*8975f5c5SAndroid Build Coastguard Worker }
2701*8975f5c5SAndroid Build Coastguard Worker 
setUniform3uiv(UniformLocation location,GLsizei count,const GLuint * v)2702*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::setUniform3uiv(UniformLocation location, GLsizei count, const GLuint *v)
2703*8975f5c5SAndroid Build Coastguard Worker {
2704*8975f5c5SAndroid Build Coastguard Worker     setUniformGeneric<GLuint, 3, &rx::ProgramExecutableImpl::setUniform3uiv>(location, count, v);
2705*8975f5c5SAndroid Build Coastguard Worker }
2706*8975f5c5SAndroid Build Coastguard Worker 
setUniform4uiv(UniformLocation location,GLsizei count,const GLuint * v)2707*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::setUniform4uiv(UniformLocation location, GLsizei count, const GLuint *v)
2708*8975f5c5SAndroid Build Coastguard Worker {
2709*8975f5c5SAndroid Build Coastguard Worker     setUniformGeneric<GLuint, 4, &rx::ProgramExecutableImpl::setUniform4uiv>(location, count, v);
2710*8975f5c5SAndroid Build Coastguard Worker }
2711*8975f5c5SAndroid Build Coastguard Worker 
2712*8975f5c5SAndroid Build Coastguard Worker template <typename UniformT,
2713*8975f5c5SAndroid Build Coastguard Worker           GLint MatrixC,
2714*8975f5c5SAndroid Build Coastguard Worker           GLint MatrixR,
2715*8975f5c5SAndroid Build Coastguard Worker           void (rx::ProgramExecutableImpl::*
2716*8975f5c5SAndroid Build Coastguard Worker                     SetUniformMatrixFunc)(GLint, GLsizei, GLboolean, const UniformT *)>
setUniformMatrixGeneric(UniformLocation location,GLsizei count,GLboolean transpose,const UniformT * v)2717*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::setUniformMatrixGeneric(UniformLocation location,
2718*8975f5c5SAndroid Build Coastguard Worker                                                 GLsizei count,
2719*8975f5c5SAndroid Build Coastguard Worker                                                 GLboolean transpose,
2720*8975f5c5SAndroid Build Coastguard Worker                                                 const UniformT *v)
2721*8975f5c5SAndroid Build Coastguard Worker {
2722*8975f5c5SAndroid Build Coastguard Worker     if (shouldIgnoreUniform(location))
2723*8975f5c5SAndroid Build Coastguard Worker     {
2724*8975f5c5SAndroid Build Coastguard Worker         return;
2725*8975f5c5SAndroid Build Coastguard Worker     }
2726*8975f5c5SAndroid Build Coastguard Worker 
2727*8975f5c5SAndroid Build Coastguard Worker     GLsizei clampedCount = clampMatrixUniformCount<MatrixC, MatrixR>(location, count, transpose, v);
2728*8975f5c5SAndroid Build Coastguard Worker     (mImplementation->*SetUniformMatrixFunc)(location.value, clampedCount, transpose, v);
2729*8975f5c5SAndroid Build Coastguard Worker }
2730*8975f5c5SAndroid Build Coastguard Worker 
setUniformMatrix2fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2731*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::setUniformMatrix2fv(UniformLocation location,
2732*8975f5c5SAndroid Build Coastguard Worker                                             GLsizei count,
2733*8975f5c5SAndroid Build Coastguard Worker                                             GLboolean transpose,
2734*8975f5c5SAndroid Build Coastguard Worker                                             const GLfloat *v)
2735*8975f5c5SAndroid Build Coastguard Worker {
2736*8975f5c5SAndroid Build Coastguard Worker     setUniformMatrixGeneric<GLfloat, 2, 2, &rx::ProgramExecutableImpl::setUniformMatrix2fv>(
2737*8975f5c5SAndroid Build Coastguard Worker         location, count, transpose, v);
2738*8975f5c5SAndroid Build Coastguard Worker }
2739*8975f5c5SAndroid Build Coastguard Worker 
setUniformMatrix3fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2740*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::setUniformMatrix3fv(UniformLocation location,
2741*8975f5c5SAndroid Build Coastguard Worker                                             GLsizei count,
2742*8975f5c5SAndroid Build Coastguard Worker                                             GLboolean transpose,
2743*8975f5c5SAndroid Build Coastguard Worker                                             const GLfloat *v)
2744*8975f5c5SAndroid Build Coastguard Worker {
2745*8975f5c5SAndroid Build Coastguard Worker     setUniformMatrixGeneric<GLfloat, 3, 3, &rx::ProgramExecutableImpl::setUniformMatrix3fv>(
2746*8975f5c5SAndroid Build Coastguard Worker         location, count, transpose, v);
2747*8975f5c5SAndroid Build Coastguard Worker }
2748*8975f5c5SAndroid Build Coastguard Worker 
setUniformMatrix4fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2749*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::setUniformMatrix4fv(UniformLocation location,
2750*8975f5c5SAndroid Build Coastguard Worker                                             GLsizei count,
2751*8975f5c5SAndroid Build Coastguard Worker                                             GLboolean transpose,
2752*8975f5c5SAndroid Build Coastguard Worker                                             const GLfloat *v)
2753*8975f5c5SAndroid Build Coastguard Worker {
2754*8975f5c5SAndroid Build Coastguard Worker     setUniformMatrixGeneric<GLfloat, 4, 4, &rx::ProgramExecutableImpl::setUniformMatrix4fv>(
2755*8975f5c5SAndroid Build Coastguard Worker         location, count, transpose, v);
2756*8975f5c5SAndroid Build Coastguard Worker }
2757*8975f5c5SAndroid Build Coastguard Worker 
setUniformMatrix2x3fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2758*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::setUniformMatrix2x3fv(UniformLocation location,
2759*8975f5c5SAndroid Build Coastguard Worker                                               GLsizei count,
2760*8975f5c5SAndroid Build Coastguard Worker                                               GLboolean transpose,
2761*8975f5c5SAndroid Build Coastguard Worker                                               const GLfloat *v)
2762*8975f5c5SAndroid Build Coastguard Worker {
2763*8975f5c5SAndroid Build Coastguard Worker     setUniformMatrixGeneric<GLfloat, 2, 3, &rx::ProgramExecutableImpl::setUniformMatrix2x3fv>(
2764*8975f5c5SAndroid Build Coastguard Worker         location, count, transpose, v);
2765*8975f5c5SAndroid Build Coastguard Worker }
2766*8975f5c5SAndroid Build Coastguard Worker 
setUniformMatrix2x4fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2767*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::setUniformMatrix2x4fv(UniformLocation location,
2768*8975f5c5SAndroid Build Coastguard Worker                                               GLsizei count,
2769*8975f5c5SAndroid Build Coastguard Worker                                               GLboolean transpose,
2770*8975f5c5SAndroid Build Coastguard Worker                                               const GLfloat *v)
2771*8975f5c5SAndroid Build Coastguard Worker {
2772*8975f5c5SAndroid Build Coastguard Worker     setUniformMatrixGeneric<GLfloat, 2, 4, &rx::ProgramExecutableImpl::setUniformMatrix2x4fv>(
2773*8975f5c5SAndroid Build Coastguard Worker         location, count, transpose, v);
2774*8975f5c5SAndroid Build Coastguard Worker }
2775*8975f5c5SAndroid Build Coastguard Worker 
setUniformMatrix3x2fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2776*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::setUniformMatrix3x2fv(UniformLocation location,
2777*8975f5c5SAndroid Build Coastguard Worker                                               GLsizei count,
2778*8975f5c5SAndroid Build Coastguard Worker                                               GLboolean transpose,
2779*8975f5c5SAndroid Build Coastguard Worker                                               const GLfloat *v)
2780*8975f5c5SAndroid Build Coastguard Worker {
2781*8975f5c5SAndroid Build Coastguard Worker     setUniformMatrixGeneric<GLfloat, 3, 2, &rx::ProgramExecutableImpl::setUniformMatrix3x2fv>(
2782*8975f5c5SAndroid Build Coastguard Worker         location, count, transpose, v);
2783*8975f5c5SAndroid Build Coastguard Worker }
2784*8975f5c5SAndroid Build Coastguard Worker 
setUniformMatrix3x4fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2785*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::setUniformMatrix3x4fv(UniformLocation location,
2786*8975f5c5SAndroid Build Coastguard Worker                                               GLsizei count,
2787*8975f5c5SAndroid Build Coastguard Worker                                               GLboolean transpose,
2788*8975f5c5SAndroid Build Coastguard Worker                                               const GLfloat *v)
2789*8975f5c5SAndroid Build Coastguard Worker {
2790*8975f5c5SAndroid Build Coastguard Worker     setUniformMatrixGeneric<GLfloat, 3, 4, &rx::ProgramExecutableImpl::setUniformMatrix3x4fv>(
2791*8975f5c5SAndroid Build Coastguard Worker         location, count, transpose, v);
2792*8975f5c5SAndroid Build Coastguard Worker }
2793*8975f5c5SAndroid Build Coastguard Worker 
setUniformMatrix4x2fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2794*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::setUniformMatrix4x2fv(UniformLocation location,
2795*8975f5c5SAndroid Build Coastguard Worker                                               GLsizei count,
2796*8975f5c5SAndroid Build Coastguard Worker                                               GLboolean transpose,
2797*8975f5c5SAndroid Build Coastguard Worker                                               const GLfloat *v)
2798*8975f5c5SAndroid Build Coastguard Worker {
2799*8975f5c5SAndroid Build Coastguard Worker     setUniformMatrixGeneric<GLfloat, 4, 2, &rx::ProgramExecutableImpl::setUniformMatrix4x2fv>(
2800*8975f5c5SAndroid Build Coastguard Worker         location, count, transpose, v);
2801*8975f5c5SAndroid Build Coastguard Worker }
2802*8975f5c5SAndroid Build Coastguard Worker 
setUniformMatrix4x3fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2803*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::setUniformMatrix4x3fv(UniformLocation location,
2804*8975f5c5SAndroid Build Coastguard Worker                                               GLsizei count,
2805*8975f5c5SAndroid Build Coastguard Worker                                               GLboolean transpose,
2806*8975f5c5SAndroid Build Coastguard Worker                                               const GLfloat *v)
2807*8975f5c5SAndroid Build Coastguard Worker {
2808*8975f5c5SAndroid Build Coastguard Worker     setUniformMatrixGeneric<GLfloat, 4, 3, &rx::ProgramExecutableImpl::setUniformMatrix4x3fv>(
2809*8975f5c5SAndroid Build Coastguard Worker         location, count, transpose, v);
2810*8975f5c5SAndroid Build Coastguard Worker }
2811*8975f5c5SAndroid Build Coastguard Worker 
getUniformfv(const Context * context,UniformLocation location,GLfloat * v) const2812*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::getUniformfv(const Context *context,
2813*8975f5c5SAndroid Build Coastguard Worker                                      UniformLocation location,
2814*8975f5c5SAndroid Build Coastguard Worker                                      GLfloat *v) const
2815*8975f5c5SAndroid Build Coastguard Worker {
2816*8975f5c5SAndroid Build Coastguard Worker     const VariableLocation &uniformLocation = mUniformLocations[location.value];
2817*8975f5c5SAndroid Build Coastguard Worker     const LinkedUniform &uniform            = mUniforms[uniformLocation.index];
2818*8975f5c5SAndroid Build Coastguard Worker 
2819*8975f5c5SAndroid Build Coastguard Worker     if (uniform.isSampler())
2820*8975f5c5SAndroid Build Coastguard Worker     {
2821*8975f5c5SAndroid Build Coastguard Worker         *v = static_cast<GLfloat>(getSamplerUniformBinding(uniformLocation));
2822*8975f5c5SAndroid Build Coastguard Worker         return;
2823*8975f5c5SAndroid Build Coastguard Worker     }
2824*8975f5c5SAndroid Build Coastguard Worker     else if (uniform.isImage())
2825*8975f5c5SAndroid Build Coastguard Worker     {
2826*8975f5c5SAndroid Build Coastguard Worker         *v = static_cast<GLfloat>(getImageUniformBinding(uniformLocation));
2827*8975f5c5SAndroid Build Coastguard Worker         return;
2828*8975f5c5SAndroid Build Coastguard Worker     }
2829*8975f5c5SAndroid Build Coastguard Worker 
2830*8975f5c5SAndroid Build Coastguard Worker     const GLenum nativeType = VariableComponentType(uniform.getType());
2831*8975f5c5SAndroid Build Coastguard Worker     if (nativeType == GL_FLOAT)
2832*8975f5c5SAndroid Build Coastguard Worker     {
2833*8975f5c5SAndroid Build Coastguard Worker         mImplementation->getUniformfv(context, location.value, v);
2834*8975f5c5SAndroid Build Coastguard Worker     }
2835*8975f5c5SAndroid Build Coastguard Worker     else
2836*8975f5c5SAndroid Build Coastguard Worker     {
2837*8975f5c5SAndroid Build Coastguard Worker         getUniformInternal(context, v, location, nativeType,
2838*8975f5c5SAndroid Build Coastguard Worker                            VariableComponentCount(uniform.getType()));
2839*8975f5c5SAndroid Build Coastguard Worker     }
2840*8975f5c5SAndroid Build Coastguard Worker }
2841*8975f5c5SAndroid Build Coastguard Worker 
getUniformiv(const Context * context,UniformLocation location,GLint * v) const2842*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::getUniformiv(const Context *context,
2843*8975f5c5SAndroid Build Coastguard Worker                                      UniformLocation location,
2844*8975f5c5SAndroid Build Coastguard Worker                                      GLint *v) const
2845*8975f5c5SAndroid Build Coastguard Worker {
2846*8975f5c5SAndroid Build Coastguard Worker     const VariableLocation &uniformLocation = mUniformLocations[location.value];
2847*8975f5c5SAndroid Build Coastguard Worker     const LinkedUniform &uniform            = mUniforms[uniformLocation.index];
2848*8975f5c5SAndroid Build Coastguard Worker 
2849*8975f5c5SAndroid Build Coastguard Worker     if (uniform.isSampler())
2850*8975f5c5SAndroid Build Coastguard Worker     {
2851*8975f5c5SAndroid Build Coastguard Worker         *v = static_cast<GLint>(getSamplerUniformBinding(uniformLocation));
2852*8975f5c5SAndroid Build Coastguard Worker         return;
2853*8975f5c5SAndroid Build Coastguard Worker     }
2854*8975f5c5SAndroid Build Coastguard Worker     else if (uniform.isImage())
2855*8975f5c5SAndroid Build Coastguard Worker     {
2856*8975f5c5SAndroid Build Coastguard Worker         *v = static_cast<GLint>(getImageUniformBinding(uniformLocation));
2857*8975f5c5SAndroid Build Coastguard Worker         return;
2858*8975f5c5SAndroid Build Coastguard Worker     }
2859*8975f5c5SAndroid Build Coastguard Worker 
2860*8975f5c5SAndroid Build Coastguard Worker     const GLenum nativeType = VariableComponentType(uniform.getType());
2861*8975f5c5SAndroid Build Coastguard Worker     if (nativeType == GL_INT || nativeType == GL_BOOL)
2862*8975f5c5SAndroid Build Coastguard Worker     {
2863*8975f5c5SAndroid Build Coastguard Worker         mImplementation->getUniformiv(context, location.value, v);
2864*8975f5c5SAndroid Build Coastguard Worker     }
2865*8975f5c5SAndroid Build Coastguard Worker     else
2866*8975f5c5SAndroid Build Coastguard Worker     {
2867*8975f5c5SAndroid Build Coastguard Worker         getUniformInternal(context, v, location, nativeType,
2868*8975f5c5SAndroid Build Coastguard Worker                            VariableComponentCount(uniform.getType()));
2869*8975f5c5SAndroid Build Coastguard Worker     }
2870*8975f5c5SAndroid Build Coastguard Worker }
2871*8975f5c5SAndroid Build Coastguard Worker 
getUniformuiv(const Context * context,UniformLocation location,GLuint * v) const2872*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::getUniformuiv(const Context *context,
2873*8975f5c5SAndroid Build Coastguard Worker                                       UniformLocation location,
2874*8975f5c5SAndroid Build Coastguard Worker                                       GLuint *v) const
2875*8975f5c5SAndroid Build Coastguard Worker {
2876*8975f5c5SAndroid Build Coastguard Worker     const VariableLocation &uniformLocation = mUniformLocations[location.value];
2877*8975f5c5SAndroid Build Coastguard Worker     const LinkedUniform &uniform            = mUniforms[uniformLocation.index];
2878*8975f5c5SAndroid Build Coastguard Worker 
2879*8975f5c5SAndroid Build Coastguard Worker     if (uniform.isSampler())
2880*8975f5c5SAndroid Build Coastguard Worker     {
2881*8975f5c5SAndroid Build Coastguard Worker         *v = getSamplerUniformBinding(uniformLocation);
2882*8975f5c5SAndroid Build Coastguard Worker         return;
2883*8975f5c5SAndroid Build Coastguard Worker     }
2884*8975f5c5SAndroid Build Coastguard Worker     else if (uniform.isImage())
2885*8975f5c5SAndroid Build Coastguard Worker     {
2886*8975f5c5SAndroid Build Coastguard Worker         *v = getImageUniformBinding(uniformLocation);
2887*8975f5c5SAndroid Build Coastguard Worker         return;
2888*8975f5c5SAndroid Build Coastguard Worker     }
2889*8975f5c5SAndroid Build Coastguard Worker 
2890*8975f5c5SAndroid Build Coastguard Worker     const GLenum nativeType = VariableComponentType(uniform.getType());
2891*8975f5c5SAndroid Build Coastguard Worker     if (nativeType == GL_UNSIGNED_INT)
2892*8975f5c5SAndroid Build Coastguard Worker     {
2893*8975f5c5SAndroid Build Coastguard Worker         mImplementation->getUniformuiv(context, location.value, v);
2894*8975f5c5SAndroid Build Coastguard Worker     }
2895*8975f5c5SAndroid Build Coastguard Worker     else
2896*8975f5c5SAndroid Build Coastguard Worker     {
2897*8975f5c5SAndroid Build Coastguard Worker         getUniformInternal(context, v, location, nativeType,
2898*8975f5c5SAndroid Build Coastguard Worker                            VariableComponentCount(uniform.getType()));
2899*8975f5c5SAndroid Build Coastguard Worker     }
2900*8975f5c5SAndroid Build Coastguard Worker }
2901*8975f5c5SAndroid Build Coastguard Worker 
initInterfaceBlockBindings()2902*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::initInterfaceBlockBindings()
2903*8975f5c5SAndroid Build Coastguard Worker {
2904*8975f5c5SAndroid Build Coastguard Worker     // Set initial bindings from shader.
2905*8975f5c5SAndroid Build Coastguard Worker     for (size_t blockIndex = 0; blockIndex < mUniformBlocks.size(); blockIndex++)
2906*8975f5c5SAndroid Build Coastguard Worker     {
2907*8975f5c5SAndroid Build Coastguard Worker         InterfaceBlock &uniformBlock = mUniformBlocks[blockIndex];
2908*8975f5c5SAndroid Build Coastguard Worker         // All interface blocks either have |binding| defined, or default to binding 0.
2909*8975f5c5SAndroid Build Coastguard Worker         ASSERT(uniformBlock.pod.inShaderBinding >= 0);
2910*8975f5c5SAndroid Build Coastguard Worker         remapUniformBlockBinding({static_cast<uint32_t>(blockIndex)},
2911*8975f5c5SAndroid Build Coastguard Worker                                  uniformBlock.pod.inShaderBinding);
2912*8975f5c5SAndroid Build Coastguard Worker 
2913*8975f5c5SAndroid Build Coastguard Worker         // This is called on program link/binary, which means the executable has changed.  There is
2914*8975f5c5SAndroid Build Coastguard Worker         // no need to send any additional notifications to the contexts (where the program may be
2915*8975f5c5SAndroid Build Coastguard Worker         // current) or program pipeline objects (that have this program attached), because they
2916*8975f5c5SAndroid Build Coastguard Worker         // already assume all blocks are dirty.
2917*8975f5c5SAndroid Build Coastguard Worker     }
2918*8975f5c5SAndroid Build Coastguard Worker }
2919*8975f5c5SAndroid Build Coastguard Worker 
remapUniformBlockBinding(UniformBlockIndex uniformBlockIndex,GLuint uniformBlockBinding)2920*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::remapUniformBlockBinding(UniformBlockIndex uniformBlockIndex,
2921*8975f5c5SAndroid Build Coastguard Worker                                                  GLuint uniformBlockBinding)
2922*8975f5c5SAndroid Build Coastguard Worker {
2923*8975f5c5SAndroid Build Coastguard Worker     // Remove previous binding
2924*8975f5c5SAndroid Build Coastguard Worker     const GLuint previousBinding = mUniformBlockIndexToBufferBinding[uniformBlockIndex.value];
2925*8975f5c5SAndroid Build Coastguard Worker     mUniformBufferBindingToUniformBlocks[previousBinding].reset(uniformBlockIndex.value);
2926*8975f5c5SAndroid Build Coastguard Worker 
2927*8975f5c5SAndroid Build Coastguard Worker     // Set new binding
2928*8975f5c5SAndroid Build Coastguard Worker     mUniformBlockIndexToBufferBinding[uniformBlockIndex.value] = uniformBlockBinding;
2929*8975f5c5SAndroid Build Coastguard Worker     mUniformBufferBindingToUniformBlocks[uniformBlockBinding].set(uniformBlockIndex.value);
2930*8975f5c5SAndroid Build Coastguard Worker }
2931*8975f5c5SAndroid Build Coastguard Worker 
setUniformValuesFromBindingQualifiers()2932*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::setUniformValuesFromBindingQualifiers()
2933*8975f5c5SAndroid Build Coastguard Worker {
2934*8975f5c5SAndroid Build Coastguard Worker     for (unsigned int samplerIndex : mPod.samplerUniformRange)
2935*8975f5c5SAndroid Build Coastguard Worker     {
2936*8975f5c5SAndroid Build Coastguard Worker         const auto &samplerUniform = mUniforms[samplerIndex];
2937*8975f5c5SAndroid Build Coastguard Worker         if (samplerUniform.getBinding() != -1)
2938*8975f5c5SAndroid Build Coastguard Worker         {
2939*8975f5c5SAndroid Build Coastguard Worker             const std::string &uniformName = getUniformNameByIndex(samplerIndex);
2940*8975f5c5SAndroid Build Coastguard Worker             UniformLocation location       = getUniformLocation(uniformName);
2941*8975f5c5SAndroid Build Coastguard Worker             ASSERT(location.value != -1);
2942*8975f5c5SAndroid Build Coastguard Worker             std::vector<GLint> boundTextureUnits;
2943*8975f5c5SAndroid Build Coastguard Worker             for (unsigned int elementIndex = 0;
2944*8975f5c5SAndroid Build Coastguard Worker                  elementIndex < samplerUniform.getBasicTypeElementCount(); ++elementIndex)
2945*8975f5c5SAndroid Build Coastguard Worker             {
2946*8975f5c5SAndroid Build Coastguard Worker                 boundTextureUnits.push_back(samplerUniform.getBinding() + elementIndex);
2947*8975f5c5SAndroid Build Coastguard Worker             }
2948*8975f5c5SAndroid Build Coastguard Worker 
2949*8975f5c5SAndroid Build Coastguard Worker             // Here we pass nullptr to avoid a large chain of calls that need a non-const Context.
2950*8975f5c5SAndroid Build Coastguard Worker             // We know it's safe not to notify the Context because this is only called after link.
2951*8975f5c5SAndroid Build Coastguard Worker             setUniform1iv(nullptr, location, static_cast<GLsizei>(boundTextureUnits.size()),
2952*8975f5c5SAndroid Build Coastguard Worker                           boundTextureUnits.data());
2953*8975f5c5SAndroid Build Coastguard Worker         }
2954*8975f5c5SAndroid Build Coastguard Worker     }
2955*8975f5c5SAndroid Build Coastguard Worker }
2956*8975f5c5SAndroid Build Coastguard Worker 
2957*8975f5c5SAndroid Build Coastguard Worker template <typename T>
clampUniformCount(const VariableLocation & locationInfo,GLsizei count,int vectorSize,const T * v)2958*8975f5c5SAndroid Build Coastguard Worker GLsizei ProgramExecutable::clampUniformCount(const VariableLocation &locationInfo,
2959*8975f5c5SAndroid Build Coastguard Worker                                              GLsizei count,
2960*8975f5c5SAndroid Build Coastguard Worker                                              int vectorSize,
2961*8975f5c5SAndroid Build Coastguard Worker                                              const T *v)
2962*8975f5c5SAndroid Build Coastguard Worker {
2963*8975f5c5SAndroid Build Coastguard Worker     if (count == 1)
2964*8975f5c5SAndroid Build Coastguard Worker         return 1;
2965*8975f5c5SAndroid Build Coastguard Worker 
2966*8975f5c5SAndroid Build Coastguard Worker     const LinkedUniform &linkedUniform = mUniforms[locationInfo.index];
2967*8975f5c5SAndroid Build Coastguard Worker 
2968*8975f5c5SAndroid Build Coastguard Worker     // OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array
2969*8975f5c5SAndroid Build Coastguard Worker     // element index used, as reported by GetActiveUniform, will be ignored by the GL."
2970*8975f5c5SAndroid Build Coastguard Worker     unsigned int remainingElements =
2971*8975f5c5SAndroid Build Coastguard Worker         linkedUniform.getBasicTypeElementCount() - locationInfo.arrayIndex;
2972*8975f5c5SAndroid Build Coastguard Worker     GLsizei maxElementCount =
2973*8975f5c5SAndroid Build Coastguard Worker         static_cast<GLsizei>(remainingElements * linkedUniform.getElementComponents());
2974*8975f5c5SAndroid Build Coastguard Worker 
2975*8975f5c5SAndroid Build Coastguard Worker     if (count * vectorSize > maxElementCount)
2976*8975f5c5SAndroid Build Coastguard Worker     {
2977*8975f5c5SAndroid Build Coastguard Worker         return maxElementCount / vectorSize;
2978*8975f5c5SAndroid Build Coastguard Worker     }
2979*8975f5c5SAndroid Build Coastguard Worker 
2980*8975f5c5SAndroid Build Coastguard Worker     return count;
2981*8975f5c5SAndroid Build Coastguard Worker }
2982*8975f5c5SAndroid Build Coastguard Worker 
2983*8975f5c5SAndroid Build Coastguard Worker template <size_t cols, size_t rows, typename T>
clampMatrixUniformCount(UniformLocation location,GLsizei count,GLboolean transpose,const T * v)2984*8975f5c5SAndroid Build Coastguard Worker GLsizei ProgramExecutable::clampMatrixUniformCount(UniformLocation location,
2985*8975f5c5SAndroid Build Coastguard Worker                                                    GLsizei count,
2986*8975f5c5SAndroid Build Coastguard Worker                                                    GLboolean transpose,
2987*8975f5c5SAndroid Build Coastguard Worker                                                    const T *v)
2988*8975f5c5SAndroid Build Coastguard Worker {
2989*8975f5c5SAndroid Build Coastguard Worker     const VariableLocation &locationInfo = mUniformLocations[location.value];
2990*8975f5c5SAndroid Build Coastguard Worker 
2991*8975f5c5SAndroid Build Coastguard Worker     if (!transpose)
2992*8975f5c5SAndroid Build Coastguard Worker     {
2993*8975f5c5SAndroid Build Coastguard Worker         return clampUniformCount(locationInfo, count, cols * rows, v);
2994*8975f5c5SAndroid Build Coastguard Worker     }
2995*8975f5c5SAndroid Build Coastguard Worker 
2996*8975f5c5SAndroid Build Coastguard Worker     const LinkedUniform &linkedUniform = mUniforms[locationInfo.index];
2997*8975f5c5SAndroid Build Coastguard Worker 
2998*8975f5c5SAndroid Build Coastguard Worker     // OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array
2999*8975f5c5SAndroid Build Coastguard Worker     // element index used, as reported by GetActiveUniform, will be ignored by the GL."
3000*8975f5c5SAndroid Build Coastguard Worker     unsigned int remainingElements =
3001*8975f5c5SAndroid Build Coastguard Worker         linkedUniform.getBasicTypeElementCount() - locationInfo.arrayIndex;
3002*8975f5c5SAndroid Build Coastguard Worker     return std::min(count, static_cast<GLsizei>(remainingElements));
3003*8975f5c5SAndroid Build Coastguard Worker }
3004*8975f5c5SAndroid Build Coastguard Worker 
updateSamplerUniform(Context * context,const VariableLocation & locationInfo,GLsizei clampedCount,const GLint * v)3005*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::updateSamplerUniform(Context *context,
3006*8975f5c5SAndroid Build Coastguard Worker                                              const VariableLocation &locationInfo,
3007*8975f5c5SAndroid Build Coastguard Worker                                              GLsizei clampedCount,
3008*8975f5c5SAndroid Build Coastguard Worker                                              const GLint *v)
3009*8975f5c5SAndroid Build Coastguard Worker {
3010*8975f5c5SAndroid Build Coastguard Worker     ASSERT(isSamplerUniformIndex(locationInfo.index));
3011*8975f5c5SAndroid Build Coastguard Worker     GLuint samplerIndex                    = getSamplerIndexFromUniformIndex(locationInfo.index);
3012*8975f5c5SAndroid Build Coastguard Worker     const SamplerBinding &samplerBinding   = mSamplerBindings[samplerIndex];
3013*8975f5c5SAndroid Build Coastguard Worker     std::vector<GLuint> &boundTextureUnits = mSamplerBoundTextureUnits;
3014*8975f5c5SAndroid Build Coastguard Worker 
3015*8975f5c5SAndroid Build Coastguard Worker     if (locationInfo.arrayIndex >= samplerBinding.textureUnitsCount)
3016*8975f5c5SAndroid Build Coastguard Worker     {
3017*8975f5c5SAndroid Build Coastguard Worker         return;
3018*8975f5c5SAndroid Build Coastguard Worker     }
3019*8975f5c5SAndroid Build Coastguard Worker     GLsizei safeUniformCount =
3020*8975f5c5SAndroid Build Coastguard Worker         std::min(clampedCount,
3021*8975f5c5SAndroid Build Coastguard Worker                  static_cast<GLsizei>(samplerBinding.textureUnitsCount - locationInfo.arrayIndex));
3022*8975f5c5SAndroid Build Coastguard Worker 
3023*8975f5c5SAndroid Build Coastguard Worker     // Update the sampler uniforms.
3024*8975f5c5SAndroid Build Coastguard Worker     for (uint16_t arrayIndex = 0; arrayIndex < safeUniformCount; ++arrayIndex)
3025*8975f5c5SAndroid Build Coastguard Worker     {
3026*8975f5c5SAndroid Build Coastguard Worker         GLint oldTextureUnit =
3027*8975f5c5SAndroid Build Coastguard Worker             samplerBinding.getTextureUnit(boundTextureUnits, arrayIndex + locationInfo.arrayIndex);
3028*8975f5c5SAndroid Build Coastguard Worker         GLint newTextureUnit = v[arrayIndex];
3029*8975f5c5SAndroid Build Coastguard Worker 
3030*8975f5c5SAndroid Build Coastguard Worker         if (oldTextureUnit == newTextureUnit)
3031*8975f5c5SAndroid Build Coastguard Worker         {
3032*8975f5c5SAndroid Build Coastguard Worker             continue;
3033*8975f5c5SAndroid Build Coastguard Worker         }
3034*8975f5c5SAndroid Build Coastguard Worker 
3035*8975f5c5SAndroid Build Coastguard Worker         // Update sampler's bound textureUnit
3036*8975f5c5SAndroid Build Coastguard Worker         boundTextureUnits[samplerBinding.textureUnitsStartIndex + arrayIndex +
3037*8975f5c5SAndroid Build Coastguard Worker                           locationInfo.arrayIndex] = newTextureUnit;
3038*8975f5c5SAndroid Build Coastguard Worker 
3039*8975f5c5SAndroid Build Coastguard Worker         // Update the reference counts.
3040*8975f5c5SAndroid Build Coastguard Worker         uint32_t &oldRefCount = mActiveSamplerRefCounts[oldTextureUnit];
3041*8975f5c5SAndroid Build Coastguard Worker         uint32_t &newRefCount = mActiveSamplerRefCounts[newTextureUnit];
3042*8975f5c5SAndroid Build Coastguard Worker         ASSERT(oldRefCount > 0);
3043*8975f5c5SAndroid Build Coastguard Worker         ASSERT(newRefCount < std::numeric_limits<uint32_t>::max());
3044*8975f5c5SAndroid Build Coastguard Worker         oldRefCount--;
3045*8975f5c5SAndroid Build Coastguard Worker         newRefCount++;
3046*8975f5c5SAndroid Build Coastguard Worker 
3047*8975f5c5SAndroid Build Coastguard Worker         // Check for binding type change.
3048*8975f5c5SAndroid Build Coastguard Worker         TextureType newSamplerType     = mActiveSamplerTypes[newTextureUnit];
3049*8975f5c5SAndroid Build Coastguard Worker         TextureType oldSamplerType     = mActiveSamplerTypes[oldTextureUnit];
3050*8975f5c5SAndroid Build Coastguard Worker         SamplerFormat newSamplerFormat = mActiveSamplerFormats[newTextureUnit];
3051*8975f5c5SAndroid Build Coastguard Worker         SamplerFormat oldSamplerFormat = mActiveSamplerFormats[oldTextureUnit];
3052*8975f5c5SAndroid Build Coastguard Worker         bool newSamplerYUV             = mActiveSamplerYUV.test(newTextureUnit);
3053*8975f5c5SAndroid Build Coastguard Worker 
3054*8975f5c5SAndroid Build Coastguard Worker         if (newRefCount == 1)
3055*8975f5c5SAndroid Build Coastguard Worker         {
3056*8975f5c5SAndroid Build Coastguard Worker             setActive(newTextureUnit, samplerBinding, mUniforms[locationInfo.index]);
3057*8975f5c5SAndroid Build Coastguard Worker         }
3058*8975f5c5SAndroid Build Coastguard Worker         else
3059*8975f5c5SAndroid Build Coastguard Worker         {
3060*8975f5c5SAndroid Build Coastguard Worker             if (newSamplerType != samplerBinding.textureType ||
3061*8975f5c5SAndroid Build Coastguard Worker                 newSamplerYUV != IsSamplerYUVType(samplerBinding.samplerType))
3062*8975f5c5SAndroid Build Coastguard Worker             {
3063*8975f5c5SAndroid Build Coastguard Worker                 hasSamplerTypeConflict(newTextureUnit);
3064*8975f5c5SAndroid Build Coastguard Worker             }
3065*8975f5c5SAndroid Build Coastguard Worker 
3066*8975f5c5SAndroid Build Coastguard Worker             if (newSamplerFormat != samplerBinding.format)
3067*8975f5c5SAndroid Build Coastguard Worker             {
3068*8975f5c5SAndroid Build Coastguard Worker                 hasSamplerFormatConflict(newTextureUnit);
3069*8975f5c5SAndroid Build Coastguard Worker             }
3070*8975f5c5SAndroid Build Coastguard Worker         }
3071*8975f5c5SAndroid Build Coastguard Worker 
3072*8975f5c5SAndroid Build Coastguard Worker         // Unset previously active sampler.
3073*8975f5c5SAndroid Build Coastguard Worker         if (oldRefCount == 0)
3074*8975f5c5SAndroid Build Coastguard Worker         {
3075*8975f5c5SAndroid Build Coastguard Worker             setInactive(oldTextureUnit);
3076*8975f5c5SAndroid Build Coastguard Worker         }
3077*8975f5c5SAndroid Build Coastguard Worker         else
3078*8975f5c5SAndroid Build Coastguard Worker         {
3079*8975f5c5SAndroid Build Coastguard Worker             if (oldSamplerType == TextureType::InvalidEnum ||
3080*8975f5c5SAndroid Build Coastguard Worker                 oldSamplerFormat == SamplerFormat::InvalidEnum)
3081*8975f5c5SAndroid Build Coastguard Worker             {
3082*8975f5c5SAndroid Build Coastguard Worker                 // Previous conflict. Check if this new change fixed the conflict.
3083*8975f5c5SAndroid Build Coastguard Worker                 setSamplerUniformTextureTypeAndFormat(oldTextureUnit);
3084*8975f5c5SAndroid Build Coastguard Worker             }
3085*8975f5c5SAndroid Build Coastguard Worker         }
3086*8975f5c5SAndroid Build Coastguard Worker 
3087*8975f5c5SAndroid Build Coastguard Worker         // Update the observing PPO's executable, if any.
3088*8975f5c5SAndroid Build Coastguard Worker         // Do this before any of the Context work, since that uses the current ProgramExecutable,
3089*8975f5c5SAndroid Build Coastguard Worker         // which will be the PPO's if this Program is bound to it, rather than this Program's.
3090*8975f5c5SAndroid Build Coastguard Worker         if (mPod.isSeparable)
3091*8975f5c5SAndroid Build Coastguard Worker         {
3092*8975f5c5SAndroid Build Coastguard Worker             onStateChange(angle::SubjectMessage::ProgramTextureOrImageBindingChanged);
3093*8975f5c5SAndroid Build Coastguard Worker         }
3094*8975f5c5SAndroid Build Coastguard Worker 
3095*8975f5c5SAndroid Build Coastguard Worker         // Notify context.
3096*8975f5c5SAndroid Build Coastguard Worker         if (context)
3097*8975f5c5SAndroid Build Coastguard Worker         {
3098*8975f5c5SAndroid Build Coastguard Worker             context->onSamplerUniformChange(newTextureUnit);
3099*8975f5c5SAndroid Build Coastguard Worker             context->onSamplerUniformChange(oldTextureUnit);
3100*8975f5c5SAndroid Build Coastguard Worker         }
3101*8975f5c5SAndroid Build Coastguard Worker     }
3102*8975f5c5SAndroid Build Coastguard Worker 
3103*8975f5c5SAndroid Build Coastguard Worker     // Invalidate the validation cache.
3104*8975f5c5SAndroid Build Coastguard Worker     resetCachedValidateSamplersResult();
3105*8975f5c5SAndroid Build Coastguard Worker     // Inform any PPOs this Program may be bound to.
3106*8975f5c5SAndroid Build Coastguard Worker     onStateChange(angle::SubjectMessage::SamplerUniformsUpdated);
3107*8975f5c5SAndroid Build Coastguard Worker }
3108*8975f5c5SAndroid Build Coastguard Worker 
3109*8975f5c5SAndroid Build Coastguard Worker // Driver differences mean that doing the uniform value cast ourselves gives consistent results.
3110*8975f5c5SAndroid Build Coastguard Worker // EG: on NVIDIA drivers, it was observed that getUniformi for MAX_INT+1 returned MIN_INT.
3111*8975f5c5SAndroid Build Coastguard Worker template <typename DestT>
getUniformInternal(const Context * context,DestT * dataOut,UniformLocation location,GLenum nativeType,int components) const3112*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::getUniformInternal(const Context *context,
3113*8975f5c5SAndroid Build Coastguard Worker                                            DestT *dataOut,
3114*8975f5c5SAndroid Build Coastguard Worker                                            UniformLocation location,
3115*8975f5c5SAndroid Build Coastguard Worker                                            GLenum nativeType,
3116*8975f5c5SAndroid Build Coastguard Worker                                            int components) const
3117*8975f5c5SAndroid Build Coastguard Worker {
3118*8975f5c5SAndroid Build Coastguard Worker     switch (nativeType)
3119*8975f5c5SAndroid Build Coastguard Worker     {
3120*8975f5c5SAndroid Build Coastguard Worker         case GL_BOOL:
3121*8975f5c5SAndroid Build Coastguard Worker         {
3122*8975f5c5SAndroid Build Coastguard Worker             GLint tempValue[16] = {0};
3123*8975f5c5SAndroid Build Coastguard Worker             mImplementation->getUniformiv(context, location.value, tempValue);
3124*8975f5c5SAndroid Build Coastguard Worker             UniformStateQueryCastLoop<GLboolean>(
3125*8975f5c5SAndroid Build Coastguard Worker                 dataOut, reinterpret_cast<const uint8_t *>(tempValue), components);
3126*8975f5c5SAndroid Build Coastguard Worker             break;
3127*8975f5c5SAndroid Build Coastguard Worker         }
3128*8975f5c5SAndroid Build Coastguard Worker         case GL_INT:
3129*8975f5c5SAndroid Build Coastguard Worker         {
3130*8975f5c5SAndroid Build Coastguard Worker             GLint tempValue[16] = {0};
3131*8975f5c5SAndroid Build Coastguard Worker             mImplementation->getUniformiv(context, location.value, tempValue);
3132*8975f5c5SAndroid Build Coastguard Worker             UniformStateQueryCastLoop<GLint>(dataOut, reinterpret_cast<const uint8_t *>(tempValue),
3133*8975f5c5SAndroid Build Coastguard Worker                                              components);
3134*8975f5c5SAndroid Build Coastguard Worker             break;
3135*8975f5c5SAndroid Build Coastguard Worker         }
3136*8975f5c5SAndroid Build Coastguard Worker         case GL_UNSIGNED_INT:
3137*8975f5c5SAndroid Build Coastguard Worker         {
3138*8975f5c5SAndroid Build Coastguard Worker             GLuint tempValue[16] = {0};
3139*8975f5c5SAndroid Build Coastguard Worker             mImplementation->getUniformuiv(context, location.value, tempValue);
3140*8975f5c5SAndroid Build Coastguard Worker             UniformStateQueryCastLoop<GLuint>(dataOut, reinterpret_cast<const uint8_t *>(tempValue),
3141*8975f5c5SAndroid Build Coastguard Worker                                               components);
3142*8975f5c5SAndroid Build Coastguard Worker             break;
3143*8975f5c5SAndroid Build Coastguard Worker         }
3144*8975f5c5SAndroid Build Coastguard Worker         case GL_FLOAT:
3145*8975f5c5SAndroid Build Coastguard Worker         {
3146*8975f5c5SAndroid Build Coastguard Worker             GLfloat tempValue[16] = {0};
3147*8975f5c5SAndroid Build Coastguard Worker             mImplementation->getUniformfv(context, location.value, tempValue);
3148*8975f5c5SAndroid Build Coastguard Worker             UniformStateQueryCastLoop<GLfloat>(
3149*8975f5c5SAndroid Build Coastguard Worker                 dataOut, reinterpret_cast<const uint8_t *>(tempValue), components);
3150*8975f5c5SAndroid Build Coastguard Worker             break;
3151*8975f5c5SAndroid Build Coastguard Worker         }
3152*8975f5c5SAndroid Build Coastguard Worker         default:
3153*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
3154*8975f5c5SAndroid Build Coastguard Worker             break;
3155*8975f5c5SAndroid Build Coastguard Worker     }
3156*8975f5c5SAndroid Build Coastguard Worker }
3157*8975f5c5SAndroid Build Coastguard Worker 
setDrawIDUniform(GLint drawid)3158*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::setDrawIDUniform(GLint drawid)
3159*8975f5c5SAndroid Build Coastguard Worker {
3160*8975f5c5SAndroid Build Coastguard Worker     ASSERT(hasDrawIDUniform());
3161*8975f5c5SAndroid Build Coastguard Worker     mImplementation->setUniform1iv(mPod.drawIDLocation, 1, &drawid);
3162*8975f5c5SAndroid Build Coastguard Worker }
3163*8975f5c5SAndroid Build Coastguard Worker 
setBaseVertexUniform(GLint baseVertex)3164*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::setBaseVertexUniform(GLint baseVertex)
3165*8975f5c5SAndroid Build Coastguard Worker {
3166*8975f5c5SAndroid Build Coastguard Worker     ASSERT(hasBaseVertexUniform());
3167*8975f5c5SAndroid Build Coastguard Worker     if (baseVertex == mCachedBaseVertex)
3168*8975f5c5SAndroid Build Coastguard Worker     {
3169*8975f5c5SAndroid Build Coastguard Worker         return;
3170*8975f5c5SAndroid Build Coastguard Worker     }
3171*8975f5c5SAndroid Build Coastguard Worker     mCachedBaseVertex = baseVertex;
3172*8975f5c5SAndroid Build Coastguard Worker     mImplementation->setUniform1iv(mPod.baseVertexLocation, 1, &baseVertex);
3173*8975f5c5SAndroid Build Coastguard Worker }
3174*8975f5c5SAndroid Build Coastguard Worker 
setBaseInstanceUniform(GLuint baseInstance)3175*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::setBaseInstanceUniform(GLuint baseInstance)
3176*8975f5c5SAndroid Build Coastguard Worker {
3177*8975f5c5SAndroid Build Coastguard Worker     ASSERT(hasBaseInstanceUniform());
3178*8975f5c5SAndroid Build Coastguard Worker     if (baseInstance == mCachedBaseInstance)
3179*8975f5c5SAndroid Build Coastguard Worker     {
3180*8975f5c5SAndroid Build Coastguard Worker         return;
3181*8975f5c5SAndroid Build Coastguard Worker     }
3182*8975f5c5SAndroid Build Coastguard Worker     mCachedBaseInstance   = baseInstance;
3183*8975f5c5SAndroid Build Coastguard Worker     GLint baseInstanceInt = baseInstance;
3184*8975f5c5SAndroid Build Coastguard Worker     mImplementation->setUniform1iv(mPod.baseInstanceLocation, 1, &baseInstanceInt);
3185*8975f5c5SAndroid Build Coastguard Worker }
3186*8975f5c5SAndroid Build Coastguard Worker 
waitForPostLinkTasks(const Context * context)3187*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutable::waitForPostLinkTasks(const Context *context)
3188*8975f5c5SAndroid Build Coastguard Worker {
3189*8975f5c5SAndroid Build Coastguard Worker     if (mPostLinkSubTasks.empty())
3190*8975f5c5SAndroid Build Coastguard Worker     {
3191*8975f5c5SAndroid Build Coastguard Worker         return;
3192*8975f5c5SAndroid Build Coastguard Worker     }
3193*8975f5c5SAndroid Build Coastguard Worker 
3194*8975f5c5SAndroid Build Coastguard Worker     mImplementation->waitForPostLinkTasks(context);
3195*8975f5c5SAndroid Build Coastguard Worker 
3196*8975f5c5SAndroid Build Coastguard Worker     // Implementation is expected to call |onPostLinkTasksComplete|.
3197*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mPostLinkSubTasks.empty());
3198*8975f5c5SAndroid Build Coastguard Worker }
3199*8975f5c5SAndroid Build Coastguard Worker 
InstallExecutable(const Context * context,const SharedProgramExecutable & toInstall,SharedProgramExecutable * executable)3200*8975f5c5SAndroid Build Coastguard Worker void InstallExecutable(const Context *context,
3201*8975f5c5SAndroid Build Coastguard Worker                        const SharedProgramExecutable &toInstall,
3202*8975f5c5SAndroid Build Coastguard Worker                        SharedProgramExecutable *executable)
3203*8975f5c5SAndroid Build Coastguard Worker {
3204*8975f5c5SAndroid Build Coastguard Worker     // There should never be a need to re-install the same executable.
3205*8975f5c5SAndroid Build Coastguard Worker     ASSERT(toInstall.get() != executable->get());
3206*8975f5c5SAndroid Build Coastguard Worker 
3207*8975f5c5SAndroid Build Coastguard Worker     // Destroy the old executable before it gets deleted.
3208*8975f5c5SAndroid Build Coastguard Worker     UninstallExecutable(context, executable);
3209*8975f5c5SAndroid Build Coastguard Worker 
3210*8975f5c5SAndroid Build Coastguard Worker     // Install the new executable.
3211*8975f5c5SAndroid Build Coastguard Worker     *executable = toInstall;
3212*8975f5c5SAndroid Build Coastguard Worker }
3213*8975f5c5SAndroid Build Coastguard Worker 
UninstallExecutable(const Context * context,SharedProgramExecutable * executable)3214*8975f5c5SAndroid Build Coastguard Worker void UninstallExecutable(const Context *context, SharedProgramExecutable *executable)
3215*8975f5c5SAndroid Build Coastguard Worker {
3216*8975f5c5SAndroid Build Coastguard Worker     if (executable->use_count() == 1)
3217*8975f5c5SAndroid Build Coastguard Worker     {
3218*8975f5c5SAndroid Build Coastguard Worker         (*executable)->destroy(context);
3219*8975f5c5SAndroid Build Coastguard Worker     }
3220*8975f5c5SAndroid Build Coastguard Worker 
3221*8975f5c5SAndroid Build Coastguard Worker     executable->reset();
3222*8975f5c5SAndroid Build Coastguard Worker }
3223*8975f5c5SAndroid Build Coastguard Worker 
3224*8975f5c5SAndroid Build Coastguard Worker }  // namespace gl
3225