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