1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2017 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker
7*8975f5c5SAndroid Build Coastguard Worker // ProgramLinkedResources.cpp: implements link-time checks for default block uniforms, and generates
8*8975f5c5SAndroid Build Coastguard Worker // uniform locations. Populates data structures related to uniforms so that they can be stored in
9*8975f5c5SAndroid Build Coastguard Worker // program state.
10*8975f5c5SAndroid Build Coastguard Worker
11*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/ProgramLinkedResources.h"
12*8975f5c5SAndroid Build Coastguard Worker
13*8975f5c5SAndroid Build Coastguard Worker #include "common/string_utils.h"
14*8975f5c5SAndroid Build Coastguard Worker #include "common/utilities.h"
15*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Caps.h"
16*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Context.h"
17*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Shader.h"
18*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/features.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 {
FindUniform(std::vector<UsedUniform> & list,const std::string & name)24*8975f5c5SAndroid Build Coastguard Worker UsedUniform *FindUniform(std::vector<UsedUniform> &list, const std::string &name)
25*8975f5c5SAndroid Build Coastguard Worker {
26*8975f5c5SAndroid Build Coastguard Worker for (UsedUniform &uniform : list)
27*8975f5c5SAndroid Build Coastguard Worker {
28*8975f5c5SAndroid Build Coastguard Worker if (uniform.name == name)
29*8975f5c5SAndroid Build Coastguard Worker return &uniform;
30*8975f5c5SAndroid Build Coastguard Worker }
31*8975f5c5SAndroid Build Coastguard Worker
32*8975f5c5SAndroid Build Coastguard Worker return nullptr;
33*8975f5c5SAndroid Build Coastguard Worker }
34*8975f5c5SAndroid Build Coastguard Worker
35*8975f5c5SAndroid Build Coastguard Worker template <typename VarT>
SetActive(std::vector<VarT> * list,const std::string & name,ShaderType shaderType,bool active,uint32_t id)36*8975f5c5SAndroid Build Coastguard Worker void SetActive(std::vector<VarT> *list,
37*8975f5c5SAndroid Build Coastguard Worker const std::string &name,
38*8975f5c5SAndroid Build Coastguard Worker ShaderType shaderType,
39*8975f5c5SAndroid Build Coastguard Worker bool active,
40*8975f5c5SAndroid Build Coastguard Worker uint32_t id)
41*8975f5c5SAndroid Build Coastguard Worker {
42*8975f5c5SAndroid Build Coastguard Worker for (auto &variable : *list)
43*8975f5c5SAndroid Build Coastguard Worker {
44*8975f5c5SAndroid Build Coastguard Worker if (variable.name == name)
45*8975f5c5SAndroid Build Coastguard Worker {
46*8975f5c5SAndroid Build Coastguard Worker variable.setActive(shaderType, active, id);
47*8975f5c5SAndroid Build Coastguard Worker return;
48*8975f5c5SAndroid Build Coastguard Worker }
49*8975f5c5SAndroid Build Coastguard Worker }
50*8975f5c5SAndroid Build Coastguard Worker }
51*8975f5c5SAndroid Build Coastguard Worker
52*8975f5c5SAndroid Build Coastguard Worker template <typename VarT>
SetActive(std::vector<VarT> * list,std::vector<std::string> * nameList,const std::string & name,ShaderType shaderType,bool active,uint32_t id)53*8975f5c5SAndroid Build Coastguard Worker void SetActive(std::vector<VarT> *list,
54*8975f5c5SAndroid Build Coastguard Worker std::vector<std::string> *nameList,
55*8975f5c5SAndroid Build Coastguard Worker const std::string &name,
56*8975f5c5SAndroid Build Coastguard Worker ShaderType shaderType,
57*8975f5c5SAndroid Build Coastguard Worker bool active,
58*8975f5c5SAndroid Build Coastguard Worker uint32_t id)
59*8975f5c5SAndroid Build Coastguard Worker {
60*8975f5c5SAndroid Build Coastguard Worker for (GLint index = 0; index < static_cast<GLint>(nameList->size()); index++)
61*8975f5c5SAndroid Build Coastguard Worker {
62*8975f5c5SAndroid Build Coastguard Worker if ((*nameList)[index] == name)
63*8975f5c5SAndroid Build Coastguard Worker {
64*8975f5c5SAndroid Build Coastguard Worker (*list)[index].setActive(shaderType, active, id);
65*8975f5c5SAndroid Build Coastguard Worker return;
66*8975f5c5SAndroid Build Coastguard Worker }
67*8975f5c5SAndroid Build Coastguard Worker }
68*8975f5c5SAndroid Build Coastguard Worker }
69*8975f5c5SAndroid Build Coastguard Worker
70*8975f5c5SAndroid Build Coastguard Worker // GLSL ES Spec 3.00.3, section 4.3.5.
LinkValidateUniforms(const sh::ShaderVariable & uniform1,const sh::ShaderVariable & uniform2,std::string * mismatchedStructFieldName)71*8975f5c5SAndroid Build Coastguard Worker LinkMismatchError LinkValidateUniforms(const sh::ShaderVariable &uniform1,
72*8975f5c5SAndroid Build Coastguard Worker const sh::ShaderVariable &uniform2,
73*8975f5c5SAndroid Build Coastguard Worker std::string *mismatchedStructFieldName)
74*8975f5c5SAndroid Build Coastguard Worker {
75*8975f5c5SAndroid Build Coastguard Worker #if ANGLE_PROGRAM_LINK_VALIDATE_UNIFORM_PRECISION
76*8975f5c5SAndroid Build Coastguard Worker const bool validatePrecisionFeature = true;
77*8975f5c5SAndroid Build Coastguard Worker #else
78*8975f5c5SAndroid Build Coastguard Worker const bool validatePrecisionFeature = false;
79*8975f5c5SAndroid Build Coastguard Worker #endif
80*8975f5c5SAndroid Build Coastguard Worker
81*8975f5c5SAndroid Build Coastguard Worker // Validate precision match of uniforms iff they are statically used
82*8975f5c5SAndroid Build Coastguard Worker bool validatePrecision = uniform1.staticUse && uniform2.staticUse && validatePrecisionFeature;
83*8975f5c5SAndroid Build Coastguard Worker LinkMismatchError linkError = LinkValidateProgramVariables(
84*8975f5c5SAndroid Build Coastguard Worker uniform1, uniform2, validatePrecision, false, false, mismatchedStructFieldName);
85*8975f5c5SAndroid Build Coastguard Worker if (linkError != LinkMismatchError::NO_MISMATCH)
86*8975f5c5SAndroid Build Coastguard Worker {
87*8975f5c5SAndroid Build Coastguard Worker return linkError;
88*8975f5c5SAndroid Build Coastguard Worker }
89*8975f5c5SAndroid Build Coastguard Worker
90*8975f5c5SAndroid Build Coastguard Worker // GLSL ES Spec 3.10.4, section 4.4.5.
91*8975f5c5SAndroid Build Coastguard Worker if (uniform1.binding != -1 && uniform2.binding != -1 && uniform1.binding != uniform2.binding)
92*8975f5c5SAndroid Build Coastguard Worker {
93*8975f5c5SAndroid Build Coastguard Worker return LinkMismatchError::BINDING_MISMATCH;
94*8975f5c5SAndroid Build Coastguard Worker }
95*8975f5c5SAndroid Build Coastguard Worker
96*8975f5c5SAndroid Build Coastguard Worker // GLSL ES Spec 3.10.4, section 9.2.1.
97*8975f5c5SAndroid Build Coastguard Worker if (uniform1.location != -1 && uniform2.location != -1 &&
98*8975f5c5SAndroid Build Coastguard Worker uniform1.location != uniform2.location)
99*8975f5c5SAndroid Build Coastguard Worker {
100*8975f5c5SAndroid Build Coastguard Worker return LinkMismatchError::LOCATION_MISMATCH;
101*8975f5c5SAndroid Build Coastguard Worker }
102*8975f5c5SAndroid Build Coastguard Worker if (uniform1.offset != uniform2.offset)
103*8975f5c5SAndroid Build Coastguard Worker {
104*8975f5c5SAndroid Build Coastguard Worker return LinkMismatchError::OFFSET_MISMATCH;
105*8975f5c5SAndroid Build Coastguard Worker }
106*8975f5c5SAndroid Build Coastguard Worker
107*8975f5c5SAndroid Build Coastguard Worker return LinkMismatchError::NO_MISMATCH;
108*8975f5c5SAndroid Build Coastguard Worker }
109*8975f5c5SAndroid Build Coastguard Worker
GetMaximumShaderUniformVectors(ShaderType shaderType,const Caps & caps)110*8975f5c5SAndroid Build Coastguard Worker GLuint GetMaximumShaderUniformVectors(ShaderType shaderType, const Caps &caps)
111*8975f5c5SAndroid Build Coastguard Worker {
112*8975f5c5SAndroid Build Coastguard Worker switch (shaderType)
113*8975f5c5SAndroid Build Coastguard Worker {
114*8975f5c5SAndroid Build Coastguard Worker case ShaderType::Vertex:
115*8975f5c5SAndroid Build Coastguard Worker return static_cast<GLuint>(caps.maxVertexUniformVectors);
116*8975f5c5SAndroid Build Coastguard Worker case ShaderType::Fragment:
117*8975f5c5SAndroid Build Coastguard Worker return static_cast<GLuint>(caps.maxFragmentUniformVectors);
118*8975f5c5SAndroid Build Coastguard Worker
119*8975f5c5SAndroid Build Coastguard Worker case ShaderType::Compute:
120*8975f5c5SAndroid Build Coastguard Worker case ShaderType::Geometry:
121*8975f5c5SAndroid Build Coastguard Worker case ShaderType::TessControl:
122*8975f5c5SAndroid Build Coastguard Worker case ShaderType::TessEvaluation:
123*8975f5c5SAndroid Build Coastguard Worker return static_cast<GLuint>(caps.maxShaderUniformComponents[shaderType]) / 4;
124*8975f5c5SAndroid Build Coastguard Worker
125*8975f5c5SAndroid Build Coastguard Worker default:
126*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
127*8975f5c5SAndroid Build Coastguard Worker return 0u;
128*8975f5c5SAndroid Build Coastguard Worker }
129*8975f5c5SAndroid Build Coastguard Worker }
130*8975f5c5SAndroid Build Coastguard Worker
131*8975f5c5SAndroid Build Coastguard Worker enum class UniformType : uint8_t
132*8975f5c5SAndroid Build Coastguard Worker {
133*8975f5c5SAndroid Build Coastguard Worker Variable = 0,
134*8975f5c5SAndroid Build Coastguard Worker Sampler = 1,
135*8975f5c5SAndroid Build Coastguard Worker Image = 2,
136*8975f5c5SAndroid Build Coastguard Worker AtomicCounter = 3,
137*8975f5c5SAndroid Build Coastguard Worker
138*8975f5c5SAndroid Build Coastguard Worker InvalidEnum = 4,
139*8975f5c5SAndroid Build Coastguard Worker EnumCount = 4,
140*8975f5c5SAndroid Build Coastguard Worker };
141*8975f5c5SAndroid Build Coastguard Worker
GetUniformResourceNameString(UniformType uniformType)142*8975f5c5SAndroid Build Coastguard Worker const char *GetUniformResourceNameString(UniformType uniformType)
143*8975f5c5SAndroid Build Coastguard Worker {
144*8975f5c5SAndroid Build Coastguard Worker switch (uniformType)
145*8975f5c5SAndroid Build Coastguard Worker {
146*8975f5c5SAndroid Build Coastguard Worker case UniformType::Variable:
147*8975f5c5SAndroid Build Coastguard Worker return "uniform";
148*8975f5c5SAndroid Build Coastguard Worker case UniformType::Sampler:
149*8975f5c5SAndroid Build Coastguard Worker return "texture image unit";
150*8975f5c5SAndroid Build Coastguard Worker case UniformType::Image:
151*8975f5c5SAndroid Build Coastguard Worker return "image uniform";
152*8975f5c5SAndroid Build Coastguard Worker case UniformType::AtomicCounter:
153*8975f5c5SAndroid Build Coastguard Worker return "atomic counter";
154*8975f5c5SAndroid Build Coastguard Worker default:
155*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
156*8975f5c5SAndroid Build Coastguard Worker return "";
157*8975f5c5SAndroid Build Coastguard Worker }
158*8975f5c5SAndroid Build Coastguard Worker }
159*8975f5c5SAndroid Build Coastguard Worker
GetUniformResourceLimitName(ShaderType shaderType,UniformType uniformType)160*8975f5c5SAndroid Build Coastguard Worker std::string GetUniformResourceLimitName(ShaderType shaderType, UniformType uniformType)
161*8975f5c5SAndroid Build Coastguard Worker {
162*8975f5c5SAndroid Build Coastguard Worker // Special case: MAX_TEXTURE_IMAGE_UNITS (no "MAX_FRAGMENT_TEXTURE_IMAGE_UNITS")
163*8975f5c5SAndroid Build Coastguard Worker if (shaderType == ShaderType::Fragment && uniformType == UniformType::Sampler)
164*8975f5c5SAndroid Build Coastguard Worker {
165*8975f5c5SAndroid Build Coastguard Worker return "MAX_TEXTURE_IMAGE_UNITS";
166*8975f5c5SAndroid Build Coastguard Worker }
167*8975f5c5SAndroid Build Coastguard Worker
168*8975f5c5SAndroid Build Coastguard Worker std::ostringstream ostream;
169*8975f5c5SAndroid Build Coastguard Worker ostream << "MAX_" << GetShaderTypeString(shaderType) << "_";
170*8975f5c5SAndroid Build Coastguard Worker
171*8975f5c5SAndroid Build Coastguard Worker switch (uniformType)
172*8975f5c5SAndroid Build Coastguard Worker {
173*8975f5c5SAndroid Build Coastguard Worker case UniformType::Variable:
174*8975f5c5SAndroid Build Coastguard Worker // For vertex and fragment shaders, ES 2.0 only defines MAX_VERTEX_UNIFORM_VECTORS and
175*8975f5c5SAndroid Build Coastguard Worker // MAX_FRAGMENT_UNIFORM_VECTORS ([OpenGL ES 2.0] Table 6.20).
176*8975f5c5SAndroid Build Coastguard Worker if (shaderType == ShaderType::Vertex || shaderType == ShaderType::Fragment)
177*8975f5c5SAndroid Build Coastguard Worker {
178*8975f5c5SAndroid Build Coastguard Worker ostream << "UNIFORM_VECTORS";
179*8975f5c5SAndroid Build Coastguard Worker break;
180*8975f5c5SAndroid Build Coastguard Worker }
181*8975f5c5SAndroid Build Coastguard Worker // For compute and geometry shaders, there are no definitions on
182*8975f5c5SAndroid Build Coastguard Worker // "MAX_COMPUTE_UNIFORM_VECTORS" or "MAX_GEOMETRY_UNIFORM_VECTORS_EXT"
183*8975f5c5SAndroid Build Coastguard Worker // ([OpenGL ES 3.1] Table 20.45, [EXT_geometry_shader] Table 20.43gs).
184*8975f5c5SAndroid Build Coastguard Worker else
185*8975f5c5SAndroid Build Coastguard Worker {
186*8975f5c5SAndroid Build Coastguard Worker ostream << "UNIFORM_COMPONENTS";
187*8975f5c5SAndroid Build Coastguard Worker }
188*8975f5c5SAndroid Build Coastguard Worker break;
189*8975f5c5SAndroid Build Coastguard Worker case UniformType::Sampler:
190*8975f5c5SAndroid Build Coastguard Worker ostream << "TEXTURE_IMAGE_UNITS";
191*8975f5c5SAndroid Build Coastguard Worker break;
192*8975f5c5SAndroid Build Coastguard Worker case UniformType::Image:
193*8975f5c5SAndroid Build Coastguard Worker ostream << "IMAGE_UNIFORMS";
194*8975f5c5SAndroid Build Coastguard Worker break;
195*8975f5c5SAndroid Build Coastguard Worker case UniformType::AtomicCounter:
196*8975f5c5SAndroid Build Coastguard Worker ostream << "ATOMIC_COUNTERS";
197*8975f5c5SAndroid Build Coastguard Worker break;
198*8975f5c5SAndroid Build Coastguard Worker default:
199*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
200*8975f5c5SAndroid Build Coastguard Worker return "";
201*8975f5c5SAndroid Build Coastguard Worker }
202*8975f5c5SAndroid Build Coastguard Worker
203*8975f5c5SAndroid Build Coastguard Worker if (shaderType == ShaderType::Geometry)
204*8975f5c5SAndroid Build Coastguard Worker {
205*8975f5c5SAndroid Build Coastguard Worker ostream << "_EXT";
206*8975f5c5SAndroid Build Coastguard Worker }
207*8975f5c5SAndroid Build Coastguard Worker
208*8975f5c5SAndroid Build Coastguard Worker return ostream.str();
209*8975f5c5SAndroid Build Coastguard Worker }
210*8975f5c5SAndroid Build Coastguard Worker
LogUniformsExceedLimit(ShaderType shaderType,UniformType uniformType,GLuint limit,InfoLog & infoLog)211*8975f5c5SAndroid Build Coastguard Worker void LogUniformsExceedLimit(ShaderType shaderType,
212*8975f5c5SAndroid Build Coastguard Worker UniformType uniformType,
213*8975f5c5SAndroid Build Coastguard Worker GLuint limit,
214*8975f5c5SAndroid Build Coastguard Worker InfoLog &infoLog)
215*8975f5c5SAndroid Build Coastguard Worker {
216*8975f5c5SAndroid Build Coastguard Worker infoLog << GetShaderTypeString(shaderType) << " shader "
217*8975f5c5SAndroid Build Coastguard Worker << GetUniformResourceNameString(uniformType) << "s count exceeds "
218*8975f5c5SAndroid Build Coastguard Worker << GetUniformResourceLimitName(shaderType, uniformType) << "(" << limit << ")";
219*8975f5c5SAndroid Build Coastguard Worker }
220*8975f5c5SAndroid Build Coastguard Worker
221*8975f5c5SAndroid Build Coastguard Worker // The purpose of this visitor is to capture the uniforms in a uniform block. Each new uniform is
222*8975f5c5SAndroid Build Coastguard Worker // added to "uniformsOut".
223*8975f5c5SAndroid Build Coastguard Worker class UniformBlockEncodingVisitor : public sh::VariableNameVisitor
224*8975f5c5SAndroid Build Coastguard Worker {
225*8975f5c5SAndroid Build Coastguard Worker public:
UniformBlockEncodingVisitor(const GetBlockMemberInfoFunc & getMemberInfo,const std::string & namePrefix,const std::string & mappedNamePrefix,std::vector<LinkedUniform> * uniformsOut,std::vector<std::string> * uniformNamesOut,std::vector<std::string> * uniformMappedNamesOut,ShaderType shaderType,int blockIndex)226*8975f5c5SAndroid Build Coastguard Worker UniformBlockEncodingVisitor(const GetBlockMemberInfoFunc &getMemberInfo,
227*8975f5c5SAndroid Build Coastguard Worker const std::string &namePrefix,
228*8975f5c5SAndroid Build Coastguard Worker const std::string &mappedNamePrefix,
229*8975f5c5SAndroid Build Coastguard Worker std::vector<LinkedUniform> *uniformsOut,
230*8975f5c5SAndroid Build Coastguard Worker std::vector<std::string> *uniformNamesOut,
231*8975f5c5SAndroid Build Coastguard Worker std::vector<std::string> *uniformMappedNamesOut,
232*8975f5c5SAndroid Build Coastguard Worker ShaderType shaderType,
233*8975f5c5SAndroid Build Coastguard Worker int blockIndex)
234*8975f5c5SAndroid Build Coastguard Worker : sh::VariableNameVisitor(namePrefix, mappedNamePrefix),
235*8975f5c5SAndroid Build Coastguard Worker mGetMemberInfo(getMemberInfo),
236*8975f5c5SAndroid Build Coastguard Worker mUniformsOut(uniformsOut),
237*8975f5c5SAndroid Build Coastguard Worker mUniformNamesOut(uniformNamesOut),
238*8975f5c5SAndroid Build Coastguard Worker mUniformMappedNamesOut(uniformMappedNamesOut),
239*8975f5c5SAndroid Build Coastguard Worker mShaderType(shaderType),
240*8975f5c5SAndroid Build Coastguard Worker mBlockIndex(blockIndex)
241*8975f5c5SAndroid Build Coastguard Worker {}
242*8975f5c5SAndroid Build Coastguard Worker
visitNamedVariable(const sh::ShaderVariable & variable,bool isRowMajor,const std::string & name,const std::string & mappedName,const std::vector<unsigned int> & arraySizes)243*8975f5c5SAndroid Build Coastguard Worker void visitNamedVariable(const sh::ShaderVariable &variable,
244*8975f5c5SAndroid Build Coastguard Worker bool isRowMajor,
245*8975f5c5SAndroid Build Coastguard Worker const std::string &name,
246*8975f5c5SAndroid Build Coastguard Worker const std::string &mappedName,
247*8975f5c5SAndroid Build Coastguard Worker const std::vector<unsigned int> &arraySizes) override
248*8975f5c5SAndroid Build Coastguard Worker {
249*8975f5c5SAndroid Build Coastguard Worker // If getBlockMemberInfo returns false, the variable is optimized out.
250*8975f5c5SAndroid Build Coastguard Worker sh::BlockMemberInfo variableInfo;
251*8975f5c5SAndroid Build Coastguard Worker if (!mGetMemberInfo(name, mappedName, &variableInfo))
252*8975f5c5SAndroid Build Coastguard Worker return;
253*8975f5c5SAndroid Build Coastguard Worker
254*8975f5c5SAndroid Build Coastguard Worker std::string nameWithArrayIndex = name;
255*8975f5c5SAndroid Build Coastguard Worker std::string mappedNameWithArrayIndex = mappedName;
256*8975f5c5SAndroid Build Coastguard Worker
257*8975f5c5SAndroid Build Coastguard Worker if (variable.isArray())
258*8975f5c5SAndroid Build Coastguard Worker {
259*8975f5c5SAndroid Build Coastguard Worker nameWithArrayIndex += "[0]";
260*8975f5c5SAndroid Build Coastguard Worker mappedNameWithArrayIndex += "[0]";
261*8975f5c5SAndroid Build Coastguard Worker }
262*8975f5c5SAndroid Build Coastguard Worker
263*8975f5c5SAndroid Build Coastguard Worker if (mBlockIndex == -1)
264*8975f5c5SAndroid Build Coastguard Worker {
265*8975f5c5SAndroid Build Coastguard Worker SetActive(mUniformsOut, mUniformNamesOut, nameWithArrayIndex, mShaderType,
266*8975f5c5SAndroid Build Coastguard Worker variable.active, variable.id);
267*8975f5c5SAndroid Build Coastguard Worker return;
268*8975f5c5SAndroid Build Coastguard Worker }
269*8975f5c5SAndroid Build Coastguard Worker
270*8975f5c5SAndroid Build Coastguard Worker LinkedUniform newUniform(variable.type, variable.precision, variable.arraySizes, -1, -1, -1,
271*8975f5c5SAndroid Build Coastguard Worker mBlockIndex, variableInfo);
272*8975f5c5SAndroid Build Coastguard Worker newUniform.setActive(mShaderType, variable.active, variable.id);
273*8975f5c5SAndroid Build Coastguard Worker
274*8975f5c5SAndroid Build Coastguard Worker // Since block uniforms have no location, we don't need to store them in the uniform
275*8975f5c5SAndroid Build Coastguard Worker // locations list.
276*8975f5c5SAndroid Build Coastguard Worker mUniformsOut->push_back(newUniform);
277*8975f5c5SAndroid Build Coastguard Worker mUniformNamesOut->push_back(nameWithArrayIndex);
278*8975f5c5SAndroid Build Coastguard Worker mUniformMappedNamesOut->push_back(mappedNameWithArrayIndex);
279*8975f5c5SAndroid Build Coastguard Worker }
280*8975f5c5SAndroid Build Coastguard Worker
281*8975f5c5SAndroid Build Coastguard Worker private:
282*8975f5c5SAndroid Build Coastguard Worker const GetBlockMemberInfoFunc &mGetMemberInfo;
283*8975f5c5SAndroid Build Coastguard Worker std::vector<LinkedUniform> *mUniformsOut;
284*8975f5c5SAndroid Build Coastguard Worker std::vector<std::string> *mUniformNamesOut;
285*8975f5c5SAndroid Build Coastguard Worker std::vector<std::string> *mUniformMappedNamesOut;
286*8975f5c5SAndroid Build Coastguard Worker const ShaderType mShaderType;
287*8975f5c5SAndroid Build Coastguard Worker const int mBlockIndex;
288*8975f5c5SAndroid Build Coastguard Worker };
289*8975f5c5SAndroid Build Coastguard Worker
290*8975f5c5SAndroid Build Coastguard Worker // The purpose of this visitor is to capture the buffer variables in a shader storage block. Each
291*8975f5c5SAndroid Build Coastguard Worker // new buffer variable is stored in "bufferVariablesOut".
292*8975f5c5SAndroid Build Coastguard Worker class ShaderStorageBlockVisitor : public sh::BlockEncoderVisitor
293*8975f5c5SAndroid Build Coastguard Worker {
294*8975f5c5SAndroid Build Coastguard Worker public:
ShaderStorageBlockVisitor(const GetBlockMemberInfoFunc & getMemberInfo,const std::string & namePrefix,const std::string & mappedNamePrefix,std::vector<BufferVariable> * bufferVariablesOut,ShaderType shaderType,int blockIndex)295*8975f5c5SAndroid Build Coastguard Worker ShaderStorageBlockVisitor(const GetBlockMemberInfoFunc &getMemberInfo,
296*8975f5c5SAndroid Build Coastguard Worker const std::string &namePrefix,
297*8975f5c5SAndroid Build Coastguard Worker const std::string &mappedNamePrefix,
298*8975f5c5SAndroid Build Coastguard Worker std::vector<BufferVariable> *bufferVariablesOut,
299*8975f5c5SAndroid Build Coastguard Worker ShaderType shaderType,
300*8975f5c5SAndroid Build Coastguard Worker int blockIndex)
301*8975f5c5SAndroid Build Coastguard Worker : sh::BlockEncoderVisitor(namePrefix, mappedNamePrefix, &mStubEncoder),
302*8975f5c5SAndroid Build Coastguard Worker mGetMemberInfo(getMemberInfo),
303*8975f5c5SAndroid Build Coastguard Worker mBufferVariablesOut(bufferVariablesOut),
304*8975f5c5SAndroid Build Coastguard Worker mShaderType(shaderType),
305*8975f5c5SAndroid Build Coastguard Worker mBlockIndex(blockIndex)
306*8975f5c5SAndroid Build Coastguard Worker {}
307*8975f5c5SAndroid Build Coastguard Worker
visitNamedVariable(const sh::ShaderVariable & variable,bool isRowMajor,const std::string & name,const std::string & mappedName,const std::vector<unsigned int> & arraySizes)308*8975f5c5SAndroid Build Coastguard Worker void visitNamedVariable(const sh::ShaderVariable &variable,
309*8975f5c5SAndroid Build Coastguard Worker bool isRowMajor,
310*8975f5c5SAndroid Build Coastguard Worker const std::string &name,
311*8975f5c5SAndroid Build Coastguard Worker const std::string &mappedName,
312*8975f5c5SAndroid Build Coastguard Worker const std::vector<unsigned int> &arraySizes) override
313*8975f5c5SAndroid Build Coastguard Worker {
314*8975f5c5SAndroid Build Coastguard Worker if (mSkipEnabled)
315*8975f5c5SAndroid Build Coastguard Worker return;
316*8975f5c5SAndroid Build Coastguard Worker
317*8975f5c5SAndroid Build Coastguard Worker // If getBlockMemberInfo returns false, the variable is optimized out.
318*8975f5c5SAndroid Build Coastguard Worker sh::BlockMemberInfo variableInfo;
319*8975f5c5SAndroid Build Coastguard Worker if (!mGetMemberInfo(name, mappedName, &variableInfo))
320*8975f5c5SAndroid Build Coastguard Worker return;
321*8975f5c5SAndroid Build Coastguard Worker
322*8975f5c5SAndroid Build Coastguard Worker std::string nameWithArrayIndex = name;
323*8975f5c5SAndroid Build Coastguard Worker std::string mappedNameWithArrayIndex = mappedName;
324*8975f5c5SAndroid Build Coastguard Worker
325*8975f5c5SAndroid Build Coastguard Worker if (variable.isArray())
326*8975f5c5SAndroid Build Coastguard Worker {
327*8975f5c5SAndroid Build Coastguard Worker nameWithArrayIndex += "[0]";
328*8975f5c5SAndroid Build Coastguard Worker mappedNameWithArrayIndex += "[0]";
329*8975f5c5SAndroid Build Coastguard Worker }
330*8975f5c5SAndroid Build Coastguard Worker
331*8975f5c5SAndroid Build Coastguard Worker if (mBlockIndex == -1)
332*8975f5c5SAndroid Build Coastguard Worker {
333*8975f5c5SAndroid Build Coastguard Worker SetActive(mBufferVariablesOut, nameWithArrayIndex, mShaderType, variable.active,
334*8975f5c5SAndroid Build Coastguard Worker variable.id);
335*8975f5c5SAndroid Build Coastguard Worker return;
336*8975f5c5SAndroid Build Coastguard Worker }
337*8975f5c5SAndroid Build Coastguard Worker
338*8975f5c5SAndroid Build Coastguard Worker BufferVariable newBufferVariable(variable.type, variable.precision, nameWithArrayIndex,
339*8975f5c5SAndroid Build Coastguard Worker variable.arraySizes, mBlockIndex, mTopLevelArraySize,
340*8975f5c5SAndroid Build Coastguard Worker variableInfo);
341*8975f5c5SAndroid Build Coastguard Worker newBufferVariable.mappedName = mappedNameWithArrayIndex;
342*8975f5c5SAndroid Build Coastguard Worker newBufferVariable.setActive(mShaderType, variable.active, variable.id);
343*8975f5c5SAndroid Build Coastguard Worker
344*8975f5c5SAndroid Build Coastguard Worker mBufferVariablesOut->push_back(newBufferVariable);
345*8975f5c5SAndroid Build Coastguard Worker }
346*8975f5c5SAndroid Build Coastguard Worker
347*8975f5c5SAndroid Build Coastguard Worker private:
348*8975f5c5SAndroid Build Coastguard Worker const GetBlockMemberInfoFunc &mGetMemberInfo;
349*8975f5c5SAndroid Build Coastguard Worker std::vector<BufferVariable> *mBufferVariablesOut;
350*8975f5c5SAndroid Build Coastguard Worker const ShaderType mShaderType;
351*8975f5c5SAndroid Build Coastguard Worker const int mBlockIndex;
352*8975f5c5SAndroid Build Coastguard Worker sh::StubBlockEncoder mStubEncoder;
353*8975f5c5SAndroid Build Coastguard Worker };
354*8975f5c5SAndroid Build Coastguard Worker
355*8975f5c5SAndroid Build Coastguard Worker struct ShaderUniformCount
356*8975f5c5SAndroid Build Coastguard Worker {
357*8975f5c5SAndroid Build Coastguard Worker unsigned int vectorCount = 0;
358*8975f5c5SAndroid Build Coastguard Worker unsigned int samplerCount = 0;
359*8975f5c5SAndroid Build Coastguard Worker unsigned int imageCount = 0;
360*8975f5c5SAndroid Build Coastguard Worker unsigned int atomicCounterCount = 0;
361*8975f5c5SAndroid Build Coastguard Worker unsigned int fragmentInOutCount = 0;
362*8975f5c5SAndroid Build Coastguard Worker };
363*8975f5c5SAndroid Build Coastguard Worker
operator +=(ShaderUniformCount & lhs,const ShaderUniformCount & rhs)364*8975f5c5SAndroid Build Coastguard Worker ShaderUniformCount &operator+=(ShaderUniformCount &lhs, const ShaderUniformCount &rhs)
365*8975f5c5SAndroid Build Coastguard Worker {
366*8975f5c5SAndroid Build Coastguard Worker lhs.vectorCount += rhs.vectorCount;
367*8975f5c5SAndroid Build Coastguard Worker lhs.samplerCount += rhs.samplerCount;
368*8975f5c5SAndroid Build Coastguard Worker lhs.imageCount += rhs.imageCount;
369*8975f5c5SAndroid Build Coastguard Worker lhs.atomicCounterCount += rhs.atomicCounterCount;
370*8975f5c5SAndroid Build Coastguard Worker lhs.fragmentInOutCount += rhs.fragmentInOutCount;
371*8975f5c5SAndroid Build Coastguard Worker return lhs;
372*8975f5c5SAndroid Build Coastguard Worker }
373*8975f5c5SAndroid Build Coastguard Worker
374*8975f5c5SAndroid Build Coastguard Worker // The purpose of this visitor is to flatten struct and array uniforms into a list of singleton
375*8975f5c5SAndroid Build Coastguard Worker // uniforms. They are stored in separate lists by uniform type so they can be sorted in order.
376*8975f5c5SAndroid Build Coastguard Worker // Counts for each uniform category are stored and can be queried with "getCounts".
377*8975f5c5SAndroid Build Coastguard Worker class FlattenUniformVisitor : public sh::VariableNameVisitor
378*8975f5c5SAndroid Build Coastguard Worker {
379*8975f5c5SAndroid Build Coastguard Worker public:
FlattenUniformVisitor(ShaderType shaderType,const sh::ShaderVariable & uniform,std::vector<UsedUniform> * uniforms,std::vector<UsedUniform> * samplerUniforms,std::vector<UsedUniform> * imageUniforms,std::vector<UsedUniform> * atomicCounterUniforms,std::vector<UsedUniform> * inputAttachmentUniforms,std::vector<UnusedUniform> * unusedUniforms)380*8975f5c5SAndroid Build Coastguard Worker FlattenUniformVisitor(ShaderType shaderType,
381*8975f5c5SAndroid Build Coastguard Worker const sh::ShaderVariable &uniform,
382*8975f5c5SAndroid Build Coastguard Worker std::vector<UsedUniform> *uniforms,
383*8975f5c5SAndroid Build Coastguard Worker std::vector<UsedUniform> *samplerUniforms,
384*8975f5c5SAndroid Build Coastguard Worker std::vector<UsedUniform> *imageUniforms,
385*8975f5c5SAndroid Build Coastguard Worker std::vector<UsedUniform> *atomicCounterUniforms,
386*8975f5c5SAndroid Build Coastguard Worker std::vector<UsedUniform> *inputAttachmentUniforms,
387*8975f5c5SAndroid Build Coastguard Worker std::vector<UnusedUniform> *unusedUniforms)
388*8975f5c5SAndroid Build Coastguard Worker : sh::VariableNameVisitor("", ""),
389*8975f5c5SAndroid Build Coastguard Worker mShaderType(shaderType),
390*8975f5c5SAndroid Build Coastguard Worker mMarkActive(uniform.active),
391*8975f5c5SAndroid Build Coastguard Worker mMarkStaticUse(uniform.staticUse),
392*8975f5c5SAndroid Build Coastguard Worker mBinding(uniform.binding),
393*8975f5c5SAndroid Build Coastguard Worker mOffset(uniform.offset),
394*8975f5c5SAndroid Build Coastguard Worker mLocation(uniform.location),
395*8975f5c5SAndroid Build Coastguard Worker mUniforms(uniforms),
396*8975f5c5SAndroid Build Coastguard Worker mSamplerUniforms(samplerUniforms),
397*8975f5c5SAndroid Build Coastguard Worker mImageUniforms(imageUniforms),
398*8975f5c5SAndroid Build Coastguard Worker mAtomicCounterUniforms(atomicCounterUniforms),
399*8975f5c5SAndroid Build Coastguard Worker mInputAttachmentUniforms(inputAttachmentUniforms),
400*8975f5c5SAndroid Build Coastguard Worker mUnusedUniforms(unusedUniforms)
401*8975f5c5SAndroid Build Coastguard Worker {}
402*8975f5c5SAndroid Build Coastguard Worker
visitNamedOpaqueObject(const sh::ShaderVariable & variable,const std::string & name,const std::string & mappedName,const std::vector<unsigned int> & arraySizes)403*8975f5c5SAndroid Build Coastguard Worker void visitNamedOpaqueObject(const sh::ShaderVariable &variable,
404*8975f5c5SAndroid Build Coastguard Worker const std::string &name,
405*8975f5c5SAndroid Build Coastguard Worker const std::string &mappedName,
406*8975f5c5SAndroid Build Coastguard Worker const std::vector<unsigned int> &arraySizes) override
407*8975f5c5SAndroid Build Coastguard Worker {
408*8975f5c5SAndroid Build Coastguard Worker visitNamedVariable(variable, false, name, mappedName, arraySizes);
409*8975f5c5SAndroid Build Coastguard Worker }
410*8975f5c5SAndroid Build Coastguard Worker
visitNamedVariable(const sh::ShaderVariable & variable,bool isRowMajor,const std::string & name,const std::string & mappedName,const std::vector<unsigned int> & arraySizes)411*8975f5c5SAndroid Build Coastguard Worker void visitNamedVariable(const sh::ShaderVariable &variable,
412*8975f5c5SAndroid Build Coastguard Worker bool isRowMajor,
413*8975f5c5SAndroid Build Coastguard Worker const std::string &name,
414*8975f5c5SAndroid Build Coastguard Worker const std::string &mappedName,
415*8975f5c5SAndroid Build Coastguard Worker const std::vector<unsigned int> &arraySizes) override
416*8975f5c5SAndroid Build Coastguard Worker {
417*8975f5c5SAndroid Build Coastguard Worker bool isSampler = IsSamplerType(variable.type);
418*8975f5c5SAndroid Build Coastguard Worker bool isImage = IsImageType(variable.type);
419*8975f5c5SAndroid Build Coastguard Worker bool isAtomicCounter = IsAtomicCounterType(variable.type);
420*8975f5c5SAndroid Build Coastguard Worker bool isFragmentInOut = variable.isFragmentInOut;
421*8975f5c5SAndroid Build Coastguard Worker std::vector<UsedUniform> *uniformList = mUniforms;
422*8975f5c5SAndroid Build Coastguard Worker if (isSampler)
423*8975f5c5SAndroid Build Coastguard Worker {
424*8975f5c5SAndroid Build Coastguard Worker uniformList = mSamplerUniforms;
425*8975f5c5SAndroid Build Coastguard Worker }
426*8975f5c5SAndroid Build Coastguard Worker else if (isImage)
427*8975f5c5SAndroid Build Coastguard Worker {
428*8975f5c5SAndroid Build Coastguard Worker uniformList = mImageUniforms;
429*8975f5c5SAndroid Build Coastguard Worker }
430*8975f5c5SAndroid Build Coastguard Worker else if (isAtomicCounter)
431*8975f5c5SAndroid Build Coastguard Worker {
432*8975f5c5SAndroid Build Coastguard Worker uniformList = mAtomicCounterUniforms;
433*8975f5c5SAndroid Build Coastguard Worker }
434*8975f5c5SAndroid Build Coastguard Worker else if (isFragmentInOut)
435*8975f5c5SAndroid Build Coastguard Worker {
436*8975f5c5SAndroid Build Coastguard Worker uniformList = mInputAttachmentUniforms;
437*8975f5c5SAndroid Build Coastguard Worker }
438*8975f5c5SAndroid Build Coastguard Worker
439*8975f5c5SAndroid Build Coastguard Worker std::string fullNameWithArrayIndex(name);
440*8975f5c5SAndroid Build Coastguard Worker std::string fullMappedNameWithArrayIndex(mappedName);
441*8975f5c5SAndroid Build Coastguard Worker
442*8975f5c5SAndroid Build Coastguard Worker if (variable.isArray())
443*8975f5c5SAndroid Build Coastguard Worker {
444*8975f5c5SAndroid Build Coastguard Worker // We're following the GLES 3.1 November 2016 spec section 7.3.1.1 Naming Active
445*8975f5c5SAndroid Build Coastguard Worker // Resources and including [0] at the end of array variable names.
446*8975f5c5SAndroid Build Coastguard Worker fullNameWithArrayIndex += "[0]";
447*8975f5c5SAndroid Build Coastguard Worker fullMappedNameWithArrayIndex += "[0]";
448*8975f5c5SAndroid Build Coastguard Worker }
449*8975f5c5SAndroid Build Coastguard Worker
450*8975f5c5SAndroid Build Coastguard Worker UsedUniform *existingUniform = FindUniform(*uniformList, fullNameWithArrayIndex);
451*8975f5c5SAndroid Build Coastguard Worker if (existingUniform)
452*8975f5c5SAndroid Build Coastguard Worker {
453*8975f5c5SAndroid Build Coastguard Worker if (getBinding() != -1)
454*8975f5c5SAndroid Build Coastguard Worker {
455*8975f5c5SAndroid Build Coastguard Worker existingUniform->binding = getBinding();
456*8975f5c5SAndroid Build Coastguard Worker }
457*8975f5c5SAndroid Build Coastguard Worker if (getOffset() != -1)
458*8975f5c5SAndroid Build Coastguard Worker {
459*8975f5c5SAndroid Build Coastguard Worker existingUniform->offset = getOffset();
460*8975f5c5SAndroid Build Coastguard Worker }
461*8975f5c5SAndroid Build Coastguard Worker if (mLocation != -1)
462*8975f5c5SAndroid Build Coastguard Worker {
463*8975f5c5SAndroid Build Coastguard Worker existingUniform->location = mLocation;
464*8975f5c5SAndroid Build Coastguard Worker }
465*8975f5c5SAndroid Build Coastguard Worker if (mMarkActive)
466*8975f5c5SAndroid Build Coastguard Worker {
467*8975f5c5SAndroid Build Coastguard Worker existingUniform->active = true;
468*8975f5c5SAndroid Build Coastguard Worker existingUniform->setActive(mShaderType, true, variable.id);
469*8975f5c5SAndroid Build Coastguard Worker }
470*8975f5c5SAndroid Build Coastguard Worker if (mMarkStaticUse)
471*8975f5c5SAndroid Build Coastguard Worker {
472*8975f5c5SAndroid Build Coastguard Worker existingUniform->staticUse = true;
473*8975f5c5SAndroid Build Coastguard Worker }
474*8975f5c5SAndroid Build Coastguard Worker }
475*8975f5c5SAndroid Build Coastguard Worker else
476*8975f5c5SAndroid Build Coastguard Worker {
477*8975f5c5SAndroid Build Coastguard Worker UsedUniform linkedUniform(variable.type, variable.precision, fullNameWithArrayIndex,
478*8975f5c5SAndroid Build Coastguard Worker variable.arraySizes, getBinding(), getOffset(), mLocation, -1,
479*8975f5c5SAndroid Build Coastguard Worker sh::kDefaultBlockMemberInfo);
480*8975f5c5SAndroid Build Coastguard Worker linkedUniform.mappedName = fullMappedNameWithArrayIndex;
481*8975f5c5SAndroid Build Coastguard Worker linkedUniform.active = mMarkActive;
482*8975f5c5SAndroid Build Coastguard Worker linkedUniform.staticUse = mMarkStaticUse;
483*8975f5c5SAndroid Build Coastguard Worker linkedUniform.outerArraySizes = arraySizes;
484*8975f5c5SAndroid Build Coastguard Worker linkedUniform.texelFetchStaticUse = variable.texelFetchStaticUse;
485*8975f5c5SAndroid Build Coastguard Worker linkedUniform.id = variable.id;
486*8975f5c5SAndroid Build Coastguard Worker linkedUniform.imageUnitFormat = variable.imageUnitFormat;
487*8975f5c5SAndroid Build Coastguard Worker linkedUniform.isFragmentInOut = variable.isFragmentInOut;
488*8975f5c5SAndroid Build Coastguard Worker if (variable.hasParentArrayIndex())
489*8975f5c5SAndroid Build Coastguard Worker {
490*8975f5c5SAndroid Build Coastguard Worker linkedUniform.setParentArrayIndex(variable.parentArrayIndex());
491*8975f5c5SAndroid Build Coastguard Worker }
492*8975f5c5SAndroid Build Coastguard Worker
493*8975f5c5SAndroid Build Coastguard Worker std::vector<unsigned int> arrayDims = arraySizes;
494*8975f5c5SAndroid Build Coastguard Worker ASSERT(variable.arraySizes.size() == 1 || variable.arraySizes.size() == 0);
495*8975f5c5SAndroid Build Coastguard Worker arrayDims.push_back(variable.arraySizes.empty() ? 1 : variable.arraySizes[0]);
496*8975f5c5SAndroid Build Coastguard Worker
497*8975f5c5SAndroid Build Coastguard Worker size_t numDimensions = arraySizes.size();
498*8975f5c5SAndroid Build Coastguard Worker uint32_t arrayStride = 1;
499*8975f5c5SAndroid Build Coastguard Worker for (size_t dimension = numDimensions; dimension > 0;)
500*8975f5c5SAndroid Build Coastguard Worker {
501*8975f5c5SAndroid Build Coastguard Worker --dimension;
502*8975f5c5SAndroid Build Coastguard Worker arrayStride *= arrayDims[dimension + 1];
503*8975f5c5SAndroid Build Coastguard Worker linkedUniform.outerArrayOffset += arrayStride * mArrayElementStack[dimension];
504*8975f5c5SAndroid Build Coastguard Worker }
505*8975f5c5SAndroid Build Coastguard Worker
506*8975f5c5SAndroid Build Coastguard Worker if (mMarkActive)
507*8975f5c5SAndroid Build Coastguard Worker {
508*8975f5c5SAndroid Build Coastguard Worker linkedUniform.setActive(mShaderType, true, variable.id);
509*8975f5c5SAndroid Build Coastguard Worker }
510*8975f5c5SAndroid Build Coastguard Worker else
511*8975f5c5SAndroid Build Coastguard Worker {
512*8975f5c5SAndroid Build Coastguard Worker mUnusedUniforms->emplace_back(
513*8975f5c5SAndroid Build Coastguard Worker linkedUniform.name, linkedUniform.isSampler(), linkedUniform.isImage(),
514*8975f5c5SAndroid Build Coastguard Worker linkedUniform.isAtomicCounter(), linkedUniform.isFragmentInOut);
515*8975f5c5SAndroid Build Coastguard Worker }
516*8975f5c5SAndroid Build Coastguard Worker
517*8975f5c5SAndroid Build Coastguard Worker uniformList->push_back(linkedUniform);
518*8975f5c5SAndroid Build Coastguard Worker }
519*8975f5c5SAndroid Build Coastguard Worker
520*8975f5c5SAndroid Build Coastguard Worker unsigned int elementCount = variable.getBasicTypeElementCount();
521*8975f5c5SAndroid Build Coastguard Worker
522*8975f5c5SAndroid Build Coastguard Worker // Samplers and images aren't "real" uniforms, so they don't count towards register usage.
523*8975f5c5SAndroid Build Coastguard Worker // Likewise, don't count "real" uniforms towards opaque count.
524*8975f5c5SAndroid Build Coastguard Worker
525*8975f5c5SAndroid Build Coastguard Worker if (!IsOpaqueType(variable.type) && !isFragmentInOut)
526*8975f5c5SAndroid Build Coastguard Worker {
527*8975f5c5SAndroid Build Coastguard Worker mUniformCount.vectorCount += VariableRegisterCount(variable.type) * elementCount;
528*8975f5c5SAndroid Build Coastguard Worker }
529*8975f5c5SAndroid Build Coastguard Worker
530*8975f5c5SAndroid Build Coastguard Worker mUniformCount.samplerCount += (isSampler ? elementCount : 0);
531*8975f5c5SAndroid Build Coastguard Worker mUniformCount.imageCount += (isImage ? elementCount : 0);
532*8975f5c5SAndroid Build Coastguard Worker mUniformCount.atomicCounterCount += (isAtomicCounter ? elementCount : 0);
533*8975f5c5SAndroid Build Coastguard Worker mUniformCount.fragmentInOutCount += (isFragmentInOut ? elementCount : 0);
534*8975f5c5SAndroid Build Coastguard Worker
535*8975f5c5SAndroid Build Coastguard Worker if (mLocation != -1)
536*8975f5c5SAndroid Build Coastguard Worker {
537*8975f5c5SAndroid Build Coastguard Worker mLocation += elementCount;
538*8975f5c5SAndroid Build Coastguard Worker }
539*8975f5c5SAndroid Build Coastguard Worker }
540*8975f5c5SAndroid Build Coastguard Worker
enterStructAccess(const sh::ShaderVariable & structVar,bool isRowMajor)541*8975f5c5SAndroid Build Coastguard Worker void enterStructAccess(const sh::ShaderVariable &structVar, bool isRowMajor) override
542*8975f5c5SAndroid Build Coastguard Worker {
543*8975f5c5SAndroid Build Coastguard Worker mStructStackSize++;
544*8975f5c5SAndroid Build Coastguard Worker sh::VariableNameVisitor::enterStructAccess(structVar, isRowMajor);
545*8975f5c5SAndroid Build Coastguard Worker }
546*8975f5c5SAndroid Build Coastguard Worker
exitStructAccess(const sh::ShaderVariable & structVar,bool isRowMajor)547*8975f5c5SAndroid Build Coastguard Worker void exitStructAccess(const sh::ShaderVariable &structVar, bool isRowMajor) override
548*8975f5c5SAndroid Build Coastguard Worker {
549*8975f5c5SAndroid Build Coastguard Worker mStructStackSize--;
550*8975f5c5SAndroid Build Coastguard Worker sh::VariableNameVisitor::exitStructAccess(structVar, isRowMajor);
551*8975f5c5SAndroid Build Coastguard Worker }
552*8975f5c5SAndroid Build Coastguard Worker
enterArrayElement(const sh::ShaderVariable & arrayVar,unsigned int arrayElement)553*8975f5c5SAndroid Build Coastguard Worker void enterArrayElement(const sh::ShaderVariable &arrayVar, unsigned int arrayElement) override
554*8975f5c5SAndroid Build Coastguard Worker {
555*8975f5c5SAndroid Build Coastguard Worker mArrayElementStack.push_back(arrayElement);
556*8975f5c5SAndroid Build Coastguard Worker sh::VariableNameVisitor::enterArrayElement(arrayVar, arrayElement);
557*8975f5c5SAndroid Build Coastguard Worker }
558*8975f5c5SAndroid Build Coastguard Worker
exitArrayElement(const sh::ShaderVariable & arrayVar,unsigned int arrayElement)559*8975f5c5SAndroid Build Coastguard Worker void exitArrayElement(const sh::ShaderVariable &arrayVar, unsigned int arrayElement) override
560*8975f5c5SAndroid Build Coastguard Worker {
561*8975f5c5SAndroid Build Coastguard Worker mArrayElementStack.pop_back();
562*8975f5c5SAndroid Build Coastguard Worker sh::VariableNameVisitor::exitArrayElement(arrayVar, arrayElement);
563*8975f5c5SAndroid Build Coastguard Worker }
564*8975f5c5SAndroid Build Coastguard Worker
getCounts() const565*8975f5c5SAndroid Build Coastguard Worker ShaderUniformCount getCounts() const { return mUniformCount; }
566*8975f5c5SAndroid Build Coastguard Worker
567*8975f5c5SAndroid Build Coastguard Worker private:
getBinding() const568*8975f5c5SAndroid Build Coastguard Worker int getBinding() const { return mStructStackSize == 0 ? mBinding : -1; }
getOffset() const569*8975f5c5SAndroid Build Coastguard Worker int getOffset() const { return mStructStackSize == 0 ? mOffset : -1; }
570*8975f5c5SAndroid Build Coastguard Worker
571*8975f5c5SAndroid Build Coastguard Worker ShaderType mShaderType;
572*8975f5c5SAndroid Build Coastguard Worker
573*8975f5c5SAndroid Build Coastguard Worker // Active and StaticUse are given separately because they are tracked at struct granularity.
574*8975f5c5SAndroid Build Coastguard Worker bool mMarkActive;
575*8975f5c5SAndroid Build Coastguard Worker bool mMarkStaticUse;
576*8975f5c5SAndroid Build Coastguard Worker int mBinding;
577*8975f5c5SAndroid Build Coastguard Worker int mOffset;
578*8975f5c5SAndroid Build Coastguard Worker int mLocation;
579*8975f5c5SAndroid Build Coastguard Worker std::vector<UsedUniform> *mUniforms;
580*8975f5c5SAndroid Build Coastguard Worker std::vector<UsedUniform> *mSamplerUniforms;
581*8975f5c5SAndroid Build Coastguard Worker std::vector<UsedUniform> *mImageUniforms;
582*8975f5c5SAndroid Build Coastguard Worker std::vector<UsedUniform> *mAtomicCounterUniforms;
583*8975f5c5SAndroid Build Coastguard Worker std::vector<UsedUniform> *mInputAttachmentUniforms;
584*8975f5c5SAndroid Build Coastguard Worker std::vector<UnusedUniform> *mUnusedUniforms;
585*8975f5c5SAndroid Build Coastguard Worker std::vector<unsigned int> mArrayElementStack;
586*8975f5c5SAndroid Build Coastguard Worker ShaderUniformCount mUniformCount;
587*8975f5c5SAndroid Build Coastguard Worker unsigned int mStructStackSize = 0;
588*8975f5c5SAndroid Build Coastguard Worker };
589*8975f5c5SAndroid Build Coastguard Worker
590*8975f5c5SAndroid Build Coastguard Worker class InterfaceBlockInfo final : angle::NonCopyable
591*8975f5c5SAndroid Build Coastguard Worker {
592*8975f5c5SAndroid Build Coastguard Worker public:
InterfaceBlockInfo(CustomBlockLayoutEncoderFactory * customEncoderFactory)593*8975f5c5SAndroid Build Coastguard Worker InterfaceBlockInfo(CustomBlockLayoutEncoderFactory *customEncoderFactory)
594*8975f5c5SAndroid Build Coastguard Worker : mCustomEncoderFactory(customEncoderFactory)
595*8975f5c5SAndroid Build Coastguard Worker {}
596*8975f5c5SAndroid Build Coastguard Worker
597*8975f5c5SAndroid Build Coastguard Worker void getShaderBlockInfo(const std::vector<sh::InterfaceBlock> &interfaceBlocks);
598*8975f5c5SAndroid Build Coastguard Worker
599*8975f5c5SAndroid Build Coastguard Worker bool getBlockSize(const std::string &name, const std::string &mappedName, size_t *sizeOut);
600*8975f5c5SAndroid Build Coastguard Worker bool getBlockMemberInfo(const std::string &name,
601*8975f5c5SAndroid Build Coastguard Worker const std::string &mappedName,
602*8975f5c5SAndroid Build Coastguard Worker sh::BlockMemberInfo *infoOut);
603*8975f5c5SAndroid Build Coastguard Worker
604*8975f5c5SAndroid Build Coastguard Worker private:
605*8975f5c5SAndroid Build Coastguard Worker size_t getBlockInfo(const sh::InterfaceBlock &interfaceBlock);
606*8975f5c5SAndroid Build Coastguard Worker
607*8975f5c5SAndroid Build Coastguard Worker std::map<std::string, size_t> mBlockSizes;
608*8975f5c5SAndroid Build Coastguard Worker sh::BlockLayoutMap mBlockLayout;
609*8975f5c5SAndroid Build Coastguard Worker // Based on the interface block layout, the std140 or std430 encoders are used. On some
610*8975f5c5SAndroid Build Coastguard Worker // platforms (currently only D3D), there could be another non-standard encoder used.
611*8975f5c5SAndroid Build Coastguard Worker CustomBlockLayoutEncoderFactory *mCustomEncoderFactory;
612*8975f5c5SAndroid Build Coastguard Worker };
613*8975f5c5SAndroid Build Coastguard Worker
getShaderBlockInfo(const std::vector<sh::InterfaceBlock> & interfaceBlocks)614*8975f5c5SAndroid Build Coastguard Worker void InterfaceBlockInfo::getShaderBlockInfo(const std::vector<sh::InterfaceBlock> &interfaceBlocks)
615*8975f5c5SAndroid Build Coastguard Worker {
616*8975f5c5SAndroid Build Coastguard Worker for (const sh::InterfaceBlock &interfaceBlock : interfaceBlocks)
617*8975f5c5SAndroid Build Coastguard Worker {
618*8975f5c5SAndroid Build Coastguard Worker if (!IsActiveInterfaceBlock(interfaceBlock))
619*8975f5c5SAndroid Build Coastguard Worker continue;
620*8975f5c5SAndroid Build Coastguard Worker
621*8975f5c5SAndroid Build Coastguard Worker if (mBlockSizes.count(interfaceBlock.name) > 0)
622*8975f5c5SAndroid Build Coastguard Worker continue;
623*8975f5c5SAndroid Build Coastguard Worker
624*8975f5c5SAndroid Build Coastguard Worker size_t dataSize = getBlockInfo(interfaceBlock);
625*8975f5c5SAndroid Build Coastguard Worker mBlockSizes[interfaceBlock.name] = dataSize;
626*8975f5c5SAndroid Build Coastguard Worker }
627*8975f5c5SAndroid Build Coastguard Worker }
628*8975f5c5SAndroid Build Coastguard Worker
getBlockInfo(const sh::InterfaceBlock & interfaceBlock)629*8975f5c5SAndroid Build Coastguard Worker size_t InterfaceBlockInfo::getBlockInfo(const sh::InterfaceBlock &interfaceBlock)
630*8975f5c5SAndroid Build Coastguard Worker {
631*8975f5c5SAndroid Build Coastguard Worker ASSERT(IsActiveInterfaceBlock(interfaceBlock));
632*8975f5c5SAndroid Build Coastguard Worker
633*8975f5c5SAndroid Build Coastguard Worker // define member uniforms
634*8975f5c5SAndroid Build Coastguard Worker sh::Std140BlockEncoder std140Encoder;
635*8975f5c5SAndroid Build Coastguard Worker sh::Std430BlockEncoder std430Encoder;
636*8975f5c5SAndroid Build Coastguard Worker sh::BlockLayoutEncoder *customEncoder = nullptr;
637*8975f5c5SAndroid Build Coastguard Worker sh::BlockLayoutEncoder *encoder = nullptr;
638*8975f5c5SAndroid Build Coastguard Worker
639*8975f5c5SAndroid Build Coastguard Worker if (interfaceBlock.layout == sh::BLOCKLAYOUT_STD140)
640*8975f5c5SAndroid Build Coastguard Worker {
641*8975f5c5SAndroid Build Coastguard Worker encoder = &std140Encoder;
642*8975f5c5SAndroid Build Coastguard Worker }
643*8975f5c5SAndroid Build Coastguard Worker else if (interfaceBlock.layout == sh::BLOCKLAYOUT_STD430)
644*8975f5c5SAndroid Build Coastguard Worker {
645*8975f5c5SAndroid Build Coastguard Worker encoder = &std430Encoder;
646*8975f5c5SAndroid Build Coastguard Worker }
647*8975f5c5SAndroid Build Coastguard Worker else if (mCustomEncoderFactory)
648*8975f5c5SAndroid Build Coastguard Worker {
649*8975f5c5SAndroid Build Coastguard Worker encoder = customEncoder = mCustomEncoderFactory->makeEncoder();
650*8975f5c5SAndroid Build Coastguard Worker }
651*8975f5c5SAndroid Build Coastguard Worker else
652*8975f5c5SAndroid Build Coastguard Worker {
653*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
654*8975f5c5SAndroid Build Coastguard Worker return 0;
655*8975f5c5SAndroid Build Coastguard Worker }
656*8975f5c5SAndroid Build Coastguard Worker
657*8975f5c5SAndroid Build Coastguard Worker sh::GetInterfaceBlockInfo(interfaceBlock.fields, interfaceBlock.fieldPrefix(), encoder,
658*8975f5c5SAndroid Build Coastguard Worker &mBlockLayout);
659*8975f5c5SAndroid Build Coastguard Worker
660*8975f5c5SAndroid Build Coastguard Worker size_t offset = encoder->getCurrentOffset();
661*8975f5c5SAndroid Build Coastguard Worker
662*8975f5c5SAndroid Build Coastguard Worker SafeDelete(customEncoder);
663*8975f5c5SAndroid Build Coastguard Worker
664*8975f5c5SAndroid Build Coastguard Worker return offset;
665*8975f5c5SAndroid Build Coastguard Worker }
666*8975f5c5SAndroid Build Coastguard Worker
getBlockSize(const std::string & name,const std::string & mappedName,size_t * sizeOut)667*8975f5c5SAndroid Build Coastguard Worker bool InterfaceBlockInfo::getBlockSize(const std::string &name,
668*8975f5c5SAndroid Build Coastguard Worker const std::string &mappedName,
669*8975f5c5SAndroid Build Coastguard Worker size_t *sizeOut)
670*8975f5c5SAndroid Build Coastguard Worker {
671*8975f5c5SAndroid Build Coastguard Worker size_t nameLengthWithoutArrayIndex;
672*8975f5c5SAndroid Build Coastguard Worker ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
673*8975f5c5SAndroid Build Coastguard Worker std::string baseName = name.substr(0u, nameLengthWithoutArrayIndex);
674*8975f5c5SAndroid Build Coastguard Worker auto sizeIter = mBlockSizes.find(baseName);
675*8975f5c5SAndroid Build Coastguard Worker if (sizeIter == mBlockSizes.end())
676*8975f5c5SAndroid Build Coastguard Worker {
677*8975f5c5SAndroid Build Coastguard Worker *sizeOut = 0;
678*8975f5c5SAndroid Build Coastguard Worker return false;
679*8975f5c5SAndroid Build Coastguard Worker }
680*8975f5c5SAndroid Build Coastguard Worker
681*8975f5c5SAndroid Build Coastguard Worker *sizeOut = sizeIter->second;
682*8975f5c5SAndroid Build Coastguard Worker return true;
683*8975f5c5SAndroid Build Coastguard Worker }
684*8975f5c5SAndroid Build Coastguard Worker
getBlockMemberInfo(const std::string & name,const std::string & mappedName,sh::BlockMemberInfo * infoOut)685*8975f5c5SAndroid Build Coastguard Worker bool InterfaceBlockInfo::getBlockMemberInfo(const std::string &name,
686*8975f5c5SAndroid Build Coastguard Worker const std::string &mappedName,
687*8975f5c5SAndroid Build Coastguard Worker sh::BlockMemberInfo *infoOut)
688*8975f5c5SAndroid Build Coastguard Worker {
689*8975f5c5SAndroid Build Coastguard Worker auto infoIter = mBlockLayout.find(name);
690*8975f5c5SAndroid Build Coastguard Worker if (infoIter == mBlockLayout.end())
691*8975f5c5SAndroid Build Coastguard Worker {
692*8975f5c5SAndroid Build Coastguard Worker *infoOut = sh::kDefaultBlockMemberInfo;
693*8975f5c5SAndroid Build Coastguard Worker return false;
694*8975f5c5SAndroid Build Coastguard Worker }
695*8975f5c5SAndroid Build Coastguard Worker
696*8975f5c5SAndroid Build Coastguard Worker *infoOut = infoIter->second;
697*8975f5c5SAndroid Build Coastguard Worker return true;
698*8975f5c5SAndroid Build Coastguard Worker }
699*8975f5c5SAndroid Build Coastguard Worker
GetFilteredVaryings(const std::vector<sh::ShaderVariable> & varyings,std::vector<const sh::ShaderVariable * > * filteredVaryingsOut)700*8975f5c5SAndroid Build Coastguard Worker void GetFilteredVaryings(const std::vector<sh::ShaderVariable> &varyings,
701*8975f5c5SAndroid Build Coastguard Worker std::vector<const sh::ShaderVariable *> *filteredVaryingsOut)
702*8975f5c5SAndroid Build Coastguard Worker {
703*8975f5c5SAndroid Build Coastguard Worker for (const sh::ShaderVariable &varying : varyings)
704*8975f5c5SAndroid Build Coastguard Worker {
705*8975f5c5SAndroid Build Coastguard Worker // Built-in varyings obey special rules
706*8975f5c5SAndroid Build Coastguard Worker if (varying.isBuiltIn())
707*8975f5c5SAndroid Build Coastguard Worker {
708*8975f5c5SAndroid Build Coastguard Worker continue;
709*8975f5c5SAndroid Build Coastguard Worker }
710*8975f5c5SAndroid Build Coastguard Worker
711*8975f5c5SAndroid Build Coastguard Worker filteredVaryingsOut->push_back(&varying);
712*8975f5c5SAndroid Build Coastguard Worker }
713*8975f5c5SAndroid Build Coastguard Worker }
714*8975f5c5SAndroid Build Coastguard Worker
LinkValidateVaryings(const sh::ShaderVariable & outputVarying,const sh::ShaderVariable & inputVarying,int shaderVersion,ShaderType frontShaderType,ShaderType backShaderType,bool isSeparable,std::string * mismatchedStructFieldName)715*8975f5c5SAndroid Build Coastguard Worker LinkMismatchError LinkValidateVaryings(const sh::ShaderVariable &outputVarying,
716*8975f5c5SAndroid Build Coastguard Worker const sh::ShaderVariable &inputVarying,
717*8975f5c5SAndroid Build Coastguard Worker int shaderVersion,
718*8975f5c5SAndroid Build Coastguard Worker ShaderType frontShaderType,
719*8975f5c5SAndroid Build Coastguard Worker ShaderType backShaderType,
720*8975f5c5SAndroid Build Coastguard Worker bool isSeparable,
721*8975f5c5SAndroid Build Coastguard Worker std::string *mismatchedStructFieldName)
722*8975f5c5SAndroid Build Coastguard Worker {
723*8975f5c5SAndroid Build Coastguard Worker // [ES 3.2 spec] 7.4.1 Shader Interface Matching:
724*8975f5c5SAndroid Build Coastguard Worker // Tessellation control shader per-vertex output variables and blocks and tessellation control,
725*8975f5c5SAndroid Build Coastguard Worker // tessellation evaluation, and geometry shader per-vertex input variables and blocks are
726*8975f5c5SAndroid Build Coastguard Worker // required to be declared as arrays, with each element representing input or output values for
727*8975f5c5SAndroid Build Coastguard Worker // a single vertex of a multi-vertex primitive. For the purposes of interface matching, such
728*8975f5c5SAndroid Build Coastguard Worker // variables and blocks are treated as though they were not declared as arrays.
729*8975f5c5SAndroid Build Coastguard Worker bool treatOutputAsNonArray =
730*8975f5c5SAndroid Build Coastguard Worker (frontShaderType == ShaderType::TessControl && !outputVarying.isPatch);
731*8975f5c5SAndroid Build Coastguard Worker bool treatInputAsNonArray =
732*8975f5c5SAndroid Build Coastguard Worker ((backShaderType == ShaderType::TessControl ||
733*8975f5c5SAndroid Build Coastguard Worker backShaderType == ShaderType::TessEvaluation || backShaderType == ShaderType::Geometry) &&
734*8975f5c5SAndroid Build Coastguard Worker !inputVarying.isPatch);
735*8975f5c5SAndroid Build Coastguard Worker
736*8975f5c5SAndroid Build Coastguard Worker // Skip the validation on the array sizes between a vertex output varying and a geometry input
737*8975f5c5SAndroid Build Coastguard Worker // varying as it has been done before.
738*8975f5c5SAndroid Build Coastguard Worker bool validatePrecision = isSeparable && (shaderVersion > 100);
739*8975f5c5SAndroid Build Coastguard Worker LinkMismatchError linkError = LinkValidateProgramVariables(
740*8975f5c5SAndroid Build Coastguard Worker outputVarying, inputVarying, validatePrecision, treatOutputAsNonArray, treatInputAsNonArray,
741*8975f5c5SAndroid Build Coastguard Worker mismatchedStructFieldName);
742*8975f5c5SAndroid Build Coastguard Worker if (linkError != LinkMismatchError::NO_MISMATCH)
743*8975f5c5SAndroid Build Coastguard Worker {
744*8975f5c5SAndroid Build Coastguard Worker return linkError;
745*8975f5c5SAndroid Build Coastguard Worker }
746*8975f5c5SAndroid Build Coastguard Worker
747*8975f5c5SAndroid Build Coastguard Worker // Explicit locations must match if the names match.
748*8975f5c5SAndroid Build Coastguard Worker if (outputVarying.isSameNameAtLinkTime(inputVarying) &&
749*8975f5c5SAndroid Build Coastguard Worker outputVarying.location != inputVarying.location)
750*8975f5c5SAndroid Build Coastguard Worker {
751*8975f5c5SAndroid Build Coastguard Worker return LinkMismatchError::LOCATION_MISMATCH;
752*8975f5c5SAndroid Build Coastguard Worker }
753*8975f5c5SAndroid Build Coastguard Worker
754*8975f5c5SAndroid Build Coastguard Worker if (!sh::InterpolationTypesMatch(outputVarying.interpolation, inputVarying.interpolation))
755*8975f5c5SAndroid Build Coastguard Worker {
756*8975f5c5SAndroid Build Coastguard Worker return LinkMismatchError::INTERPOLATION_TYPE_MISMATCH;
757*8975f5c5SAndroid Build Coastguard Worker }
758*8975f5c5SAndroid Build Coastguard Worker
759*8975f5c5SAndroid Build Coastguard Worker if (shaderVersion == 100 && outputVarying.isInvariant != inputVarying.isInvariant)
760*8975f5c5SAndroid Build Coastguard Worker {
761*8975f5c5SAndroid Build Coastguard Worker return LinkMismatchError::INVARIANCE_MISMATCH;
762*8975f5c5SAndroid Build Coastguard Worker }
763*8975f5c5SAndroid Build Coastguard Worker
764*8975f5c5SAndroid Build Coastguard Worker return LinkMismatchError::NO_MISMATCH;
765*8975f5c5SAndroid Build Coastguard Worker }
766*8975f5c5SAndroid Build Coastguard Worker
DoShaderVariablesMatch(int frontShaderVersion,ShaderType frontShaderType,ShaderType backShaderType,const sh::ShaderVariable & input,const sh::ShaderVariable & output,bool isSeparable,gl::InfoLog & infoLog)767*8975f5c5SAndroid Build Coastguard Worker bool DoShaderVariablesMatch(int frontShaderVersion,
768*8975f5c5SAndroid Build Coastguard Worker ShaderType frontShaderType,
769*8975f5c5SAndroid Build Coastguard Worker ShaderType backShaderType,
770*8975f5c5SAndroid Build Coastguard Worker const sh::ShaderVariable &input,
771*8975f5c5SAndroid Build Coastguard Worker const sh::ShaderVariable &output,
772*8975f5c5SAndroid Build Coastguard Worker bool isSeparable,
773*8975f5c5SAndroid Build Coastguard Worker gl::InfoLog &infoLog)
774*8975f5c5SAndroid Build Coastguard Worker {
775*8975f5c5SAndroid Build Coastguard Worker bool namesMatch = input.isSameNameAtLinkTime(output);
776*8975f5c5SAndroid Build Coastguard Worker bool locationsMatch = input.location != -1 && input.location == output.location;
777*8975f5c5SAndroid Build Coastguard Worker
778*8975f5c5SAndroid Build Coastguard Worker // An output block is considered to match an input block in the subsequent
779*8975f5c5SAndroid Build Coastguard Worker // shader if the two blocks have the same block name, and the members of the
780*8975f5c5SAndroid Build Coastguard Worker // block match exactly in name, type, qualification, and declaration order.
781*8975f5c5SAndroid Build Coastguard Worker //
782*8975f5c5SAndroid Build Coastguard Worker // - For the purposes of shader interface matching, the gl_PointSize
783*8975f5c5SAndroid Build Coastguard Worker // member of the intrinsically declared gl_PerVertex shader interface
784*8975f5c5SAndroid Build Coastguard Worker // block is ignored.
785*8975f5c5SAndroid Build Coastguard Worker // - Output blocks that do not match in name, but have a location and match
786*8975f5c5SAndroid Build Coastguard Worker // in every other way listed above may be considered to match by some
787*8975f5c5SAndroid Build Coastguard Worker // implementations, but not all - so this behaviour should not be relied
788*8975f5c5SAndroid Build Coastguard Worker // upon.
789*8975f5c5SAndroid Build Coastguard Worker
790*8975f5c5SAndroid Build Coastguard Worker // An output variable is considered to match an input variable in the subsequent
791*8975f5c5SAndroid Build Coastguard Worker // shader if:
792*8975f5c5SAndroid Build Coastguard Worker //
793*8975f5c5SAndroid Build Coastguard Worker // - the two variables match in name, type, and qualification; or
794*8975f5c5SAndroid Build Coastguard Worker // - the two variables are declared with the same location qualifier and
795*8975f5c5SAndroid Build Coastguard Worker // match in type and qualification.
796*8975f5c5SAndroid Build Coastguard Worker
797*8975f5c5SAndroid Build Coastguard Worker if (namesMatch || locationsMatch)
798*8975f5c5SAndroid Build Coastguard Worker {
799*8975f5c5SAndroid Build Coastguard Worker std::string mismatchedStructFieldName;
800*8975f5c5SAndroid Build Coastguard Worker LinkMismatchError linkError =
801*8975f5c5SAndroid Build Coastguard Worker LinkValidateVaryings(output, input, frontShaderVersion, frontShaderType, backShaderType,
802*8975f5c5SAndroid Build Coastguard Worker isSeparable, &mismatchedStructFieldName);
803*8975f5c5SAndroid Build Coastguard Worker if (linkError != LinkMismatchError::NO_MISMATCH)
804*8975f5c5SAndroid Build Coastguard Worker {
805*8975f5c5SAndroid Build Coastguard Worker LogLinkMismatch(infoLog, input.name, "varying", linkError, mismatchedStructFieldName,
806*8975f5c5SAndroid Build Coastguard Worker frontShaderType, backShaderType);
807*8975f5c5SAndroid Build Coastguard Worker return false;
808*8975f5c5SAndroid Build Coastguard Worker }
809*8975f5c5SAndroid Build Coastguard Worker
810*8975f5c5SAndroid Build Coastguard Worker return true;
811*8975f5c5SAndroid Build Coastguard Worker }
812*8975f5c5SAndroid Build Coastguard Worker
813*8975f5c5SAndroid Build Coastguard Worker return false;
814*8975f5c5SAndroid Build Coastguard Worker }
815*8975f5c5SAndroid Build Coastguard Worker
GetInterfaceBlockTypeString(sh::BlockType blockType)816*8975f5c5SAndroid Build Coastguard Worker const char *GetInterfaceBlockTypeString(sh::BlockType blockType)
817*8975f5c5SAndroid Build Coastguard Worker {
818*8975f5c5SAndroid Build Coastguard Worker switch (blockType)
819*8975f5c5SAndroid Build Coastguard Worker {
820*8975f5c5SAndroid Build Coastguard Worker case sh::BlockType::kBlockUniform:
821*8975f5c5SAndroid Build Coastguard Worker return "uniform block";
822*8975f5c5SAndroid Build Coastguard Worker case sh::BlockType::kBlockBuffer:
823*8975f5c5SAndroid Build Coastguard Worker return "shader storage block";
824*8975f5c5SAndroid Build Coastguard Worker default:
825*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
826*8975f5c5SAndroid Build Coastguard Worker return "";
827*8975f5c5SAndroid Build Coastguard Worker }
828*8975f5c5SAndroid Build Coastguard Worker }
829*8975f5c5SAndroid Build Coastguard Worker
GetInterfaceBlockLimitName(ShaderType shaderType,sh::BlockType blockType)830*8975f5c5SAndroid Build Coastguard Worker std::string GetInterfaceBlockLimitName(ShaderType shaderType, sh::BlockType blockType)
831*8975f5c5SAndroid Build Coastguard Worker {
832*8975f5c5SAndroid Build Coastguard Worker std::ostringstream stream;
833*8975f5c5SAndroid Build Coastguard Worker stream << "GL_MAX_" << GetShaderTypeString(shaderType) << "_";
834*8975f5c5SAndroid Build Coastguard Worker
835*8975f5c5SAndroid Build Coastguard Worker switch (blockType)
836*8975f5c5SAndroid Build Coastguard Worker {
837*8975f5c5SAndroid Build Coastguard Worker case sh::BlockType::kBlockUniform:
838*8975f5c5SAndroid Build Coastguard Worker stream << "UNIFORM_BUFFERS";
839*8975f5c5SAndroid Build Coastguard Worker break;
840*8975f5c5SAndroid Build Coastguard Worker case sh::BlockType::kBlockBuffer:
841*8975f5c5SAndroid Build Coastguard Worker stream << "SHADER_STORAGE_BLOCKS";
842*8975f5c5SAndroid Build Coastguard Worker break;
843*8975f5c5SAndroid Build Coastguard Worker default:
844*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
845*8975f5c5SAndroid Build Coastguard Worker return "";
846*8975f5c5SAndroid Build Coastguard Worker }
847*8975f5c5SAndroid Build Coastguard Worker
848*8975f5c5SAndroid Build Coastguard Worker if (shaderType == ShaderType::Geometry)
849*8975f5c5SAndroid Build Coastguard Worker {
850*8975f5c5SAndroid Build Coastguard Worker stream << "_EXT";
851*8975f5c5SAndroid Build Coastguard Worker }
852*8975f5c5SAndroid Build Coastguard Worker
853*8975f5c5SAndroid Build Coastguard Worker return stream.str();
854*8975f5c5SAndroid Build Coastguard Worker }
855*8975f5c5SAndroid Build Coastguard Worker
LogInterfaceBlocksExceedLimit(InfoLog & infoLog,ShaderType shaderType,sh::BlockType blockType,GLuint limit)856*8975f5c5SAndroid Build Coastguard Worker void LogInterfaceBlocksExceedLimit(InfoLog &infoLog,
857*8975f5c5SAndroid Build Coastguard Worker ShaderType shaderType,
858*8975f5c5SAndroid Build Coastguard Worker sh::BlockType blockType,
859*8975f5c5SAndroid Build Coastguard Worker GLuint limit)
860*8975f5c5SAndroid Build Coastguard Worker {
861*8975f5c5SAndroid Build Coastguard Worker infoLog << GetShaderTypeString(shaderType) << " shader "
862*8975f5c5SAndroid Build Coastguard Worker << GetInterfaceBlockTypeString(blockType) << " count exceeds "
863*8975f5c5SAndroid Build Coastguard Worker << GetInterfaceBlockLimitName(shaderType, blockType) << " (" << limit << ")";
864*8975f5c5SAndroid Build Coastguard Worker }
865*8975f5c5SAndroid Build Coastguard Worker
ValidateInterfaceBlocksCount(GLuint maxInterfaceBlocks,const std::vector<sh::InterfaceBlock> & interfaceBlocks,ShaderType shaderType,sh::BlockType blockType,GLuint * combinedInterfaceBlocksCount,InfoLog & infoLog)866*8975f5c5SAndroid Build Coastguard Worker bool ValidateInterfaceBlocksCount(GLuint maxInterfaceBlocks,
867*8975f5c5SAndroid Build Coastguard Worker const std::vector<sh::InterfaceBlock> &interfaceBlocks,
868*8975f5c5SAndroid Build Coastguard Worker ShaderType shaderType,
869*8975f5c5SAndroid Build Coastguard Worker sh::BlockType blockType,
870*8975f5c5SAndroid Build Coastguard Worker GLuint *combinedInterfaceBlocksCount,
871*8975f5c5SAndroid Build Coastguard Worker InfoLog &infoLog)
872*8975f5c5SAndroid Build Coastguard Worker {
873*8975f5c5SAndroid Build Coastguard Worker GLuint blockCount = 0;
874*8975f5c5SAndroid Build Coastguard Worker for (const sh::InterfaceBlock &block : interfaceBlocks)
875*8975f5c5SAndroid Build Coastguard Worker {
876*8975f5c5SAndroid Build Coastguard Worker if (IsActiveInterfaceBlock(block))
877*8975f5c5SAndroid Build Coastguard Worker {
878*8975f5c5SAndroid Build Coastguard Worker blockCount += std::max(block.arraySize, 1u);
879*8975f5c5SAndroid Build Coastguard Worker if (blockCount > maxInterfaceBlocks)
880*8975f5c5SAndroid Build Coastguard Worker {
881*8975f5c5SAndroid Build Coastguard Worker LogInterfaceBlocksExceedLimit(infoLog, shaderType, blockType, maxInterfaceBlocks);
882*8975f5c5SAndroid Build Coastguard Worker return false;
883*8975f5c5SAndroid Build Coastguard Worker }
884*8975f5c5SAndroid Build Coastguard Worker }
885*8975f5c5SAndroid Build Coastguard Worker }
886*8975f5c5SAndroid Build Coastguard Worker
887*8975f5c5SAndroid Build Coastguard Worker // [OpenGL ES 3.1] Chapter 7.6.2 Page 105:
888*8975f5c5SAndroid Build Coastguard Worker // If a uniform block is used by multiple shader stages, each such use counts separately
889*8975f5c5SAndroid Build Coastguard Worker // against this combined limit.
890*8975f5c5SAndroid Build Coastguard Worker // [OpenGL ES 3.1] Chapter 7.8 Page 111:
891*8975f5c5SAndroid Build Coastguard Worker // If a shader storage block in a program is referenced by multiple shaders, each such
892*8975f5c5SAndroid Build Coastguard Worker // reference counts separately against this combined limit.
893*8975f5c5SAndroid Build Coastguard Worker if (combinedInterfaceBlocksCount)
894*8975f5c5SAndroid Build Coastguard Worker {
895*8975f5c5SAndroid Build Coastguard Worker *combinedInterfaceBlocksCount += blockCount;
896*8975f5c5SAndroid Build Coastguard Worker }
897*8975f5c5SAndroid Build Coastguard Worker
898*8975f5c5SAndroid Build Coastguard Worker return true;
899*8975f5c5SAndroid Build Coastguard Worker }
900*8975f5c5SAndroid Build Coastguard Worker } // anonymous namespace
901*8975f5c5SAndroid Build Coastguard Worker
902*8975f5c5SAndroid Build Coastguard Worker // UsedUniform implementation
UsedUniform()903*8975f5c5SAndroid Build Coastguard Worker UsedUniform::UsedUniform() {}
904*8975f5c5SAndroid Build Coastguard Worker
UsedUniform(GLenum typeIn,GLenum precisionIn,const std::string & nameIn,const std::vector<unsigned int> & arraySizesIn,const int bindingIn,const int offsetIn,const int locationIn,const int bufferIndexIn,const sh::BlockMemberInfo & blockInfoIn)905*8975f5c5SAndroid Build Coastguard Worker UsedUniform::UsedUniform(GLenum typeIn,
906*8975f5c5SAndroid Build Coastguard Worker GLenum precisionIn,
907*8975f5c5SAndroid Build Coastguard Worker const std::string &nameIn,
908*8975f5c5SAndroid Build Coastguard Worker const std::vector<unsigned int> &arraySizesIn,
909*8975f5c5SAndroid Build Coastguard Worker const int bindingIn,
910*8975f5c5SAndroid Build Coastguard Worker const int offsetIn,
911*8975f5c5SAndroid Build Coastguard Worker const int locationIn,
912*8975f5c5SAndroid Build Coastguard Worker const int bufferIndexIn,
913*8975f5c5SAndroid Build Coastguard Worker const sh::BlockMemberInfo &blockInfoIn)
914*8975f5c5SAndroid Build Coastguard Worker : typeInfo(&GetUniformTypeInfo(typeIn)),
915*8975f5c5SAndroid Build Coastguard Worker bufferIndex(bufferIndexIn),
916*8975f5c5SAndroid Build Coastguard Worker blockInfo(blockInfoIn),
917*8975f5c5SAndroid Build Coastguard Worker outerArrayOffset(0)
918*8975f5c5SAndroid Build Coastguard Worker {
919*8975f5c5SAndroid Build Coastguard Worker type = typeIn;
920*8975f5c5SAndroid Build Coastguard Worker precision = precisionIn;
921*8975f5c5SAndroid Build Coastguard Worker name = nameIn;
922*8975f5c5SAndroid Build Coastguard Worker arraySizes = arraySizesIn;
923*8975f5c5SAndroid Build Coastguard Worker binding = bindingIn;
924*8975f5c5SAndroid Build Coastguard Worker offset = offsetIn;
925*8975f5c5SAndroid Build Coastguard Worker location = locationIn;
926*8975f5c5SAndroid Build Coastguard Worker ASSERT(!isArrayOfArrays());
927*8975f5c5SAndroid Build Coastguard Worker ASSERT(!isArray() || !isStruct());
928*8975f5c5SAndroid Build Coastguard Worker }
929*8975f5c5SAndroid Build Coastguard Worker
UsedUniform(const UsedUniform & other)930*8975f5c5SAndroid Build Coastguard Worker UsedUniform::UsedUniform(const UsedUniform &other)
931*8975f5c5SAndroid Build Coastguard Worker {
932*8975f5c5SAndroid Build Coastguard Worker *this = other;
933*8975f5c5SAndroid Build Coastguard Worker }
934*8975f5c5SAndroid Build Coastguard Worker
operator =(const UsedUniform & other)935*8975f5c5SAndroid Build Coastguard Worker UsedUniform &UsedUniform::operator=(const UsedUniform &other)
936*8975f5c5SAndroid Build Coastguard Worker {
937*8975f5c5SAndroid Build Coastguard Worker if (this != &other)
938*8975f5c5SAndroid Build Coastguard Worker {
939*8975f5c5SAndroid Build Coastguard Worker sh::ShaderVariable::operator=(other);
940*8975f5c5SAndroid Build Coastguard Worker activeVariable = other.activeVariable;
941*8975f5c5SAndroid Build Coastguard Worker
942*8975f5c5SAndroid Build Coastguard Worker typeInfo = other.typeInfo;
943*8975f5c5SAndroid Build Coastguard Worker bufferIndex = other.bufferIndex;
944*8975f5c5SAndroid Build Coastguard Worker blockInfo = other.blockInfo;
945*8975f5c5SAndroid Build Coastguard Worker outerArraySizes = other.outerArraySizes;
946*8975f5c5SAndroid Build Coastguard Worker outerArrayOffset = other.outerArrayOffset;
947*8975f5c5SAndroid Build Coastguard Worker }
948*8975f5c5SAndroid Build Coastguard Worker return *this;
949*8975f5c5SAndroid Build Coastguard Worker }
950*8975f5c5SAndroid Build Coastguard Worker
~UsedUniform()951*8975f5c5SAndroid Build Coastguard Worker UsedUniform::~UsedUniform() {}
952*8975f5c5SAndroid Build Coastguard Worker
953*8975f5c5SAndroid Build Coastguard Worker // UniformLinker implementation
UniformLinker(const ShaderBitSet & activeShaderStages,const ShaderMap<std::vector<sh::ShaderVariable>> & shaderUniforms)954*8975f5c5SAndroid Build Coastguard Worker UniformLinker::UniformLinker(const ShaderBitSet &activeShaderStages,
955*8975f5c5SAndroid Build Coastguard Worker const ShaderMap<std::vector<sh::ShaderVariable>> &shaderUniforms)
956*8975f5c5SAndroid Build Coastguard Worker : mActiveShaderStages(activeShaderStages), mShaderUniforms(shaderUniforms)
957*8975f5c5SAndroid Build Coastguard Worker {}
958*8975f5c5SAndroid Build Coastguard Worker
959*8975f5c5SAndroid Build Coastguard Worker UniformLinker::~UniformLinker() = default;
960*8975f5c5SAndroid Build Coastguard Worker
getResults(std::vector<LinkedUniform> * uniforms,std::vector<std::string> * uniformNames,std::vector<std::string> * uniformMappedNames,std::vector<UnusedUniform> * unusedUniformsOutOrNull,std::vector<VariableLocation> * uniformLocationsOutOrNull)961*8975f5c5SAndroid Build Coastguard Worker void UniformLinker::getResults(std::vector<LinkedUniform> *uniforms,
962*8975f5c5SAndroid Build Coastguard Worker std::vector<std::string> *uniformNames,
963*8975f5c5SAndroid Build Coastguard Worker std::vector<std::string> *uniformMappedNames,
964*8975f5c5SAndroid Build Coastguard Worker std::vector<UnusedUniform> *unusedUniformsOutOrNull,
965*8975f5c5SAndroid Build Coastguard Worker std::vector<VariableLocation> *uniformLocationsOutOrNull)
966*8975f5c5SAndroid Build Coastguard Worker {
967*8975f5c5SAndroid Build Coastguard Worker uniforms->reserve(mUniforms.size());
968*8975f5c5SAndroid Build Coastguard Worker uniformNames->reserve(mUniforms.size());
969*8975f5c5SAndroid Build Coastguard Worker uniformMappedNames->reserve(mUniforms.size());
970*8975f5c5SAndroid Build Coastguard Worker for (const UsedUniform &usedUniform : mUniforms)
971*8975f5c5SAndroid Build Coastguard Worker {
972*8975f5c5SAndroid Build Coastguard Worker uniforms->emplace_back(usedUniform);
973*8975f5c5SAndroid Build Coastguard Worker uniformNames->emplace_back(usedUniform.name);
974*8975f5c5SAndroid Build Coastguard Worker uniformMappedNames->emplace_back(usedUniform.mappedName);
975*8975f5c5SAndroid Build Coastguard Worker }
976*8975f5c5SAndroid Build Coastguard Worker
977*8975f5c5SAndroid Build Coastguard Worker if (unusedUniformsOutOrNull)
978*8975f5c5SAndroid Build Coastguard Worker {
979*8975f5c5SAndroid Build Coastguard Worker unusedUniformsOutOrNull->swap(mUnusedUniforms);
980*8975f5c5SAndroid Build Coastguard Worker }
981*8975f5c5SAndroid Build Coastguard Worker
982*8975f5c5SAndroid Build Coastguard Worker if (uniformLocationsOutOrNull)
983*8975f5c5SAndroid Build Coastguard Worker {
984*8975f5c5SAndroid Build Coastguard Worker uniformLocationsOutOrNull->swap(mUniformLocations);
985*8975f5c5SAndroid Build Coastguard Worker }
986*8975f5c5SAndroid Build Coastguard Worker }
987*8975f5c5SAndroid Build Coastguard Worker
link(const Caps & caps,InfoLog & infoLog,const ProgramAliasedBindings & uniformLocationBindings)988*8975f5c5SAndroid Build Coastguard Worker bool UniformLinker::link(const Caps &caps,
989*8975f5c5SAndroid Build Coastguard Worker InfoLog &infoLog,
990*8975f5c5SAndroid Build Coastguard Worker const ProgramAliasedBindings &uniformLocationBindings)
991*8975f5c5SAndroid Build Coastguard Worker {
992*8975f5c5SAndroid Build Coastguard Worker if (mActiveShaderStages[ShaderType::Vertex] && mActiveShaderStages[ShaderType::Fragment])
993*8975f5c5SAndroid Build Coastguard Worker {
994*8975f5c5SAndroid Build Coastguard Worker if (!validateGraphicsUniforms(infoLog))
995*8975f5c5SAndroid Build Coastguard Worker {
996*8975f5c5SAndroid Build Coastguard Worker return false;
997*8975f5c5SAndroid Build Coastguard Worker }
998*8975f5c5SAndroid Build Coastguard Worker }
999*8975f5c5SAndroid Build Coastguard Worker
1000*8975f5c5SAndroid Build Coastguard Worker // Flatten the uniforms list (nested fields) into a simple list (no nesting).
1001*8975f5c5SAndroid Build Coastguard Worker // Also check the maximum uniform vector and sampler counts.
1002*8975f5c5SAndroid Build Coastguard Worker if (!flattenUniformsAndCheckCaps(caps, infoLog))
1003*8975f5c5SAndroid Build Coastguard Worker {
1004*8975f5c5SAndroid Build Coastguard Worker return false;
1005*8975f5c5SAndroid Build Coastguard Worker }
1006*8975f5c5SAndroid Build Coastguard Worker
1007*8975f5c5SAndroid Build Coastguard Worker if (!checkMaxCombinedAtomicCounters(caps, infoLog))
1008*8975f5c5SAndroid Build Coastguard Worker {
1009*8975f5c5SAndroid Build Coastguard Worker return false;
1010*8975f5c5SAndroid Build Coastguard Worker }
1011*8975f5c5SAndroid Build Coastguard Worker
1012*8975f5c5SAndroid Build Coastguard Worker if (!indexUniforms(infoLog, uniformLocationBindings))
1013*8975f5c5SAndroid Build Coastguard Worker {
1014*8975f5c5SAndroid Build Coastguard Worker return false;
1015*8975f5c5SAndroid Build Coastguard Worker }
1016*8975f5c5SAndroid Build Coastguard Worker
1017*8975f5c5SAndroid Build Coastguard Worker return true;
1018*8975f5c5SAndroid Build Coastguard Worker }
1019*8975f5c5SAndroid Build Coastguard Worker
validateGraphicsUniforms(InfoLog & infoLog) const1020*8975f5c5SAndroid Build Coastguard Worker bool UniformLinker::validateGraphicsUniforms(InfoLog &infoLog) const
1021*8975f5c5SAndroid Build Coastguard Worker {
1022*8975f5c5SAndroid Build Coastguard Worker // Check that uniforms defined in the graphics shaders are identical
1023*8975f5c5SAndroid Build Coastguard Worker std::map<std::string, ShaderUniform> linkedUniforms;
1024*8975f5c5SAndroid Build Coastguard Worker
1025*8975f5c5SAndroid Build Coastguard Worker for (const ShaderType shaderType : mActiveShaderStages)
1026*8975f5c5SAndroid Build Coastguard Worker {
1027*8975f5c5SAndroid Build Coastguard Worker if (shaderType == ShaderType::Vertex)
1028*8975f5c5SAndroid Build Coastguard Worker {
1029*8975f5c5SAndroid Build Coastguard Worker for (const sh::ShaderVariable &vertexUniform : mShaderUniforms[ShaderType::Vertex])
1030*8975f5c5SAndroid Build Coastguard Worker {
1031*8975f5c5SAndroid Build Coastguard Worker linkedUniforms[vertexUniform.name] =
1032*8975f5c5SAndroid Build Coastguard Worker std::make_pair(ShaderType::Vertex, &vertexUniform);
1033*8975f5c5SAndroid Build Coastguard Worker }
1034*8975f5c5SAndroid Build Coastguard Worker }
1035*8975f5c5SAndroid Build Coastguard Worker else
1036*8975f5c5SAndroid Build Coastguard Worker {
1037*8975f5c5SAndroid Build Coastguard Worker bool isLastShader = (shaderType == ShaderType::Fragment);
1038*8975f5c5SAndroid Build Coastguard Worker if (!validateGraphicsUniformsPerShader(shaderType, !isLastShader, &linkedUniforms,
1039*8975f5c5SAndroid Build Coastguard Worker infoLog))
1040*8975f5c5SAndroid Build Coastguard Worker {
1041*8975f5c5SAndroid Build Coastguard Worker return false;
1042*8975f5c5SAndroid Build Coastguard Worker }
1043*8975f5c5SAndroid Build Coastguard Worker }
1044*8975f5c5SAndroid Build Coastguard Worker }
1045*8975f5c5SAndroid Build Coastguard Worker
1046*8975f5c5SAndroid Build Coastguard Worker return true;
1047*8975f5c5SAndroid Build Coastguard Worker }
1048*8975f5c5SAndroid Build Coastguard Worker
validateGraphicsUniformsPerShader(ShaderType shaderToLink,bool extendLinkedUniforms,std::map<std::string,ShaderUniform> * linkedUniforms,InfoLog & infoLog) const1049*8975f5c5SAndroid Build Coastguard Worker bool UniformLinker::validateGraphicsUniformsPerShader(
1050*8975f5c5SAndroid Build Coastguard Worker ShaderType shaderToLink,
1051*8975f5c5SAndroid Build Coastguard Worker bool extendLinkedUniforms,
1052*8975f5c5SAndroid Build Coastguard Worker std::map<std::string, ShaderUniform> *linkedUniforms,
1053*8975f5c5SAndroid Build Coastguard Worker InfoLog &infoLog) const
1054*8975f5c5SAndroid Build Coastguard Worker {
1055*8975f5c5SAndroid Build Coastguard Worker ASSERT(mActiveShaderStages[shaderToLink] && linkedUniforms);
1056*8975f5c5SAndroid Build Coastguard Worker
1057*8975f5c5SAndroid Build Coastguard Worker for (const sh::ShaderVariable &uniform : mShaderUniforms[shaderToLink])
1058*8975f5c5SAndroid Build Coastguard Worker {
1059*8975f5c5SAndroid Build Coastguard Worker const auto &entry = linkedUniforms->find(uniform.name);
1060*8975f5c5SAndroid Build Coastguard Worker if (entry != linkedUniforms->end())
1061*8975f5c5SAndroid Build Coastguard Worker {
1062*8975f5c5SAndroid Build Coastguard Worker const sh::ShaderVariable &linkedUniform = *(entry->second.second);
1063*8975f5c5SAndroid Build Coastguard Worker std::string mismatchedStructFieldName;
1064*8975f5c5SAndroid Build Coastguard Worker LinkMismatchError linkError =
1065*8975f5c5SAndroid Build Coastguard Worker LinkValidateUniforms(uniform, linkedUniform, &mismatchedStructFieldName);
1066*8975f5c5SAndroid Build Coastguard Worker if (linkError != LinkMismatchError::NO_MISMATCH)
1067*8975f5c5SAndroid Build Coastguard Worker {
1068*8975f5c5SAndroid Build Coastguard Worker LogLinkMismatch(infoLog, uniform.name, "uniform", linkError,
1069*8975f5c5SAndroid Build Coastguard Worker mismatchedStructFieldName, entry->second.first, shaderToLink);
1070*8975f5c5SAndroid Build Coastguard Worker return false;
1071*8975f5c5SAndroid Build Coastguard Worker }
1072*8975f5c5SAndroid Build Coastguard Worker }
1073*8975f5c5SAndroid Build Coastguard Worker else if (extendLinkedUniforms)
1074*8975f5c5SAndroid Build Coastguard Worker {
1075*8975f5c5SAndroid Build Coastguard Worker (*linkedUniforms)[uniform.name] = std::make_pair(shaderToLink, &uniform);
1076*8975f5c5SAndroid Build Coastguard Worker }
1077*8975f5c5SAndroid Build Coastguard Worker }
1078*8975f5c5SAndroid Build Coastguard Worker
1079*8975f5c5SAndroid Build Coastguard Worker return true;
1080*8975f5c5SAndroid Build Coastguard Worker }
1081*8975f5c5SAndroid Build Coastguard Worker
indexUniforms(InfoLog & infoLog,const ProgramAliasedBindings & uniformLocationBindings)1082*8975f5c5SAndroid Build Coastguard Worker bool UniformLinker::indexUniforms(InfoLog &infoLog,
1083*8975f5c5SAndroid Build Coastguard Worker const ProgramAliasedBindings &uniformLocationBindings)
1084*8975f5c5SAndroid Build Coastguard Worker {
1085*8975f5c5SAndroid Build Coastguard Worker // Locations which have been allocated for an unused uniform.
1086*8975f5c5SAndroid Build Coastguard Worker std::set<GLuint> ignoredLocations;
1087*8975f5c5SAndroid Build Coastguard Worker
1088*8975f5c5SAndroid Build Coastguard Worker int maxUniformLocation = -1;
1089*8975f5c5SAndroid Build Coastguard Worker
1090*8975f5c5SAndroid Build Coastguard Worker // Gather uniform locations that have been set either using the bindUniformLocationCHROMIUM API
1091*8975f5c5SAndroid Build Coastguard Worker // or by using a location layout qualifier and check conflicts between them.
1092*8975f5c5SAndroid Build Coastguard Worker if (!gatherUniformLocationsAndCheckConflicts(infoLog, uniformLocationBindings,
1093*8975f5c5SAndroid Build Coastguard Worker &ignoredLocations, &maxUniformLocation))
1094*8975f5c5SAndroid Build Coastguard Worker {
1095*8975f5c5SAndroid Build Coastguard Worker return false;
1096*8975f5c5SAndroid Build Coastguard Worker }
1097*8975f5c5SAndroid Build Coastguard Worker
1098*8975f5c5SAndroid Build Coastguard Worker // Conflicts have been checked, now we can prune non-statically used uniforms. Code further down
1099*8975f5c5SAndroid Build Coastguard Worker // the line relies on only having statically used uniforms in mUniforms.
1100*8975f5c5SAndroid Build Coastguard Worker pruneUnusedUniforms();
1101*8975f5c5SAndroid Build Coastguard Worker
1102*8975f5c5SAndroid Build Coastguard Worker // Gather uniforms that have their location pre-set and uniforms that don't yet have a location.
1103*8975f5c5SAndroid Build Coastguard Worker std::vector<VariableLocation> unlocatedUniforms;
1104*8975f5c5SAndroid Build Coastguard Worker std::map<GLuint, VariableLocation> preLocatedUniforms;
1105*8975f5c5SAndroid Build Coastguard Worker
1106*8975f5c5SAndroid Build Coastguard Worker for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
1107*8975f5c5SAndroid Build Coastguard Worker {
1108*8975f5c5SAndroid Build Coastguard Worker const UsedUniform &uniform = mUniforms[uniformIndex];
1109*8975f5c5SAndroid Build Coastguard Worker
1110*8975f5c5SAndroid Build Coastguard Worker if ((uniform.isBuiltIn() && !uniform.isEmulatedBuiltIn()) ||
1111*8975f5c5SAndroid Build Coastguard Worker IsAtomicCounterType(uniform.type) || uniform.isFragmentInOut)
1112*8975f5c5SAndroid Build Coastguard Worker {
1113*8975f5c5SAndroid Build Coastguard Worker continue;
1114*8975f5c5SAndroid Build Coastguard Worker }
1115*8975f5c5SAndroid Build Coastguard Worker
1116*8975f5c5SAndroid Build Coastguard Worker int preSetLocation = uniformLocationBindings.getBinding(uniform);
1117*8975f5c5SAndroid Build Coastguard Worker int shaderLocation = uniform.location;
1118*8975f5c5SAndroid Build Coastguard Worker
1119*8975f5c5SAndroid Build Coastguard Worker if (shaderLocation != -1)
1120*8975f5c5SAndroid Build Coastguard Worker {
1121*8975f5c5SAndroid Build Coastguard Worker preSetLocation = shaderLocation;
1122*8975f5c5SAndroid Build Coastguard Worker }
1123*8975f5c5SAndroid Build Coastguard Worker
1124*8975f5c5SAndroid Build Coastguard Worker unsigned int elementCount = uniform.getBasicTypeElementCount();
1125*8975f5c5SAndroid Build Coastguard Worker for (unsigned int arrayIndex = 0; arrayIndex < elementCount; arrayIndex++)
1126*8975f5c5SAndroid Build Coastguard Worker {
1127*8975f5c5SAndroid Build Coastguard Worker VariableLocation location(arrayIndex, static_cast<unsigned int>(uniformIndex));
1128*8975f5c5SAndroid Build Coastguard Worker
1129*8975f5c5SAndroid Build Coastguard Worker if ((arrayIndex == 0 && preSetLocation != -1) || shaderLocation != -1)
1130*8975f5c5SAndroid Build Coastguard Worker {
1131*8975f5c5SAndroid Build Coastguard Worker int elementLocation = preSetLocation + arrayIndex;
1132*8975f5c5SAndroid Build Coastguard Worker preLocatedUniforms[elementLocation] = location;
1133*8975f5c5SAndroid Build Coastguard Worker }
1134*8975f5c5SAndroid Build Coastguard Worker else
1135*8975f5c5SAndroid Build Coastguard Worker {
1136*8975f5c5SAndroid Build Coastguard Worker unlocatedUniforms.push_back(location);
1137*8975f5c5SAndroid Build Coastguard Worker }
1138*8975f5c5SAndroid Build Coastguard Worker }
1139*8975f5c5SAndroid Build Coastguard Worker }
1140*8975f5c5SAndroid Build Coastguard Worker
1141*8975f5c5SAndroid Build Coastguard Worker // Make enough space for all uniforms, with pre-set locations or not.
1142*8975f5c5SAndroid Build Coastguard Worker mUniformLocations.resize(
1143*8975f5c5SAndroid Build Coastguard Worker std::max(unlocatedUniforms.size() + preLocatedUniforms.size() + ignoredLocations.size(),
1144*8975f5c5SAndroid Build Coastguard Worker static_cast<size_t>(maxUniformLocation + 1)));
1145*8975f5c5SAndroid Build Coastguard Worker
1146*8975f5c5SAndroid Build Coastguard Worker // Assign uniforms with pre-set locations
1147*8975f5c5SAndroid Build Coastguard Worker for (const auto &uniform : preLocatedUniforms)
1148*8975f5c5SAndroid Build Coastguard Worker {
1149*8975f5c5SAndroid Build Coastguard Worker mUniformLocations[uniform.first] = uniform.second;
1150*8975f5c5SAndroid Build Coastguard Worker }
1151*8975f5c5SAndroid Build Coastguard Worker
1152*8975f5c5SAndroid Build Coastguard Worker // Assign ignored uniforms
1153*8975f5c5SAndroid Build Coastguard Worker for (const auto &ignoredLocation : ignoredLocations)
1154*8975f5c5SAndroid Build Coastguard Worker {
1155*8975f5c5SAndroid Build Coastguard Worker mUniformLocations[ignoredLocation].markIgnored();
1156*8975f5c5SAndroid Build Coastguard Worker }
1157*8975f5c5SAndroid Build Coastguard Worker
1158*8975f5c5SAndroid Build Coastguard Worker // Automatically assign locations for the rest of the uniforms
1159*8975f5c5SAndroid Build Coastguard Worker size_t nextUniformLocation = 0;
1160*8975f5c5SAndroid Build Coastguard Worker for (const auto &unlocatedUniform : unlocatedUniforms)
1161*8975f5c5SAndroid Build Coastguard Worker {
1162*8975f5c5SAndroid Build Coastguard Worker while (mUniformLocations[nextUniformLocation].used() ||
1163*8975f5c5SAndroid Build Coastguard Worker mUniformLocations[nextUniformLocation].ignored)
1164*8975f5c5SAndroid Build Coastguard Worker {
1165*8975f5c5SAndroid Build Coastguard Worker nextUniformLocation++;
1166*8975f5c5SAndroid Build Coastguard Worker }
1167*8975f5c5SAndroid Build Coastguard Worker
1168*8975f5c5SAndroid Build Coastguard Worker ASSERT(nextUniformLocation < mUniformLocations.size());
1169*8975f5c5SAndroid Build Coastguard Worker mUniformLocations[nextUniformLocation] = unlocatedUniform;
1170*8975f5c5SAndroid Build Coastguard Worker nextUniformLocation++;
1171*8975f5c5SAndroid Build Coastguard Worker }
1172*8975f5c5SAndroid Build Coastguard Worker
1173*8975f5c5SAndroid Build Coastguard Worker return true;
1174*8975f5c5SAndroid Build Coastguard Worker }
1175*8975f5c5SAndroid Build Coastguard Worker
gatherUniformLocationsAndCheckConflicts(InfoLog & infoLog,const ProgramAliasedBindings & uniformLocationBindings,std::set<GLuint> * ignoredLocations,int * maxUniformLocation)1176*8975f5c5SAndroid Build Coastguard Worker bool UniformLinker::gatherUniformLocationsAndCheckConflicts(
1177*8975f5c5SAndroid Build Coastguard Worker InfoLog &infoLog,
1178*8975f5c5SAndroid Build Coastguard Worker const ProgramAliasedBindings &uniformLocationBindings,
1179*8975f5c5SAndroid Build Coastguard Worker std::set<GLuint> *ignoredLocations,
1180*8975f5c5SAndroid Build Coastguard Worker int *maxUniformLocation)
1181*8975f5c5SAndroid Build Coastguard Worker {
1182*8975f5c5SAndroid Build Coastguard Worker // All the locations where another uniform can't be located.
1183*8975f5c5SAndroid Build Coastguard Worker std::set<GLuint> reservedLocations;
1184*8975f5c5SAndroid Build Coastguard Worker
1185*8975f5c5SAndroid Build Coastguard Worker for (const UsedUniform &uniform : mUniforms)
1186*8975f5c5SAndroid Build Coastguard Worker {
1187*8975f5c5SAndroid Build Coastguard Worker if ((uniform.isBuiltIn() && !uniform.isEmulatedBuiltIn()) || uniform.isFragmentInOut)
1188*8975f5c5SAndroid Build Coastguard Worker {
1189*8975f5c5SAndroid Build Coastguard Worker // The uniform of the fragment inout is not a normal uniform type. So, in the case of
1190*8975f5c5SAndroid Build Coastguard Worker // the fragment inout, this routine should be skipped.
1191*8975f5c5SAndroid Build Coastguard Worker continue;
1192*8975f5c5SAndroid Build Coastguard Worker }
1193*8975f5c5SAndroid Build Coastguard Worker
1194*8975f5c5SAndroid Build Coastguard Worker int apiBoundLocation = uniformLocationBindings.getBinding(uniform);
1195*8975f5c5SAndroid Build Coastguard Worker int shaderLocation = uniform.location;
1196*8975f5c5SAndroid Build Coastguard Worker
1197*8975f5c5SAndroid Build Coastguard Worker if (shaderLocation != -1)
1198*8975f5c5SAndroid Build Coastguard Worker {
1199*8975f5c5SAndroid Build Coastguard Worker unsigned int elementCount = uniform.getBasicTypeElementCount();
1200*8975f5c5SAndroid Build Coastguard Worker
1201*8975f5c5SAndroid Build Coastguard Worker for (unsigned int arrayIndex = 0; arrayIndex < elementCount; arrayIndex++)
1202*8975f5c5SAndroid Build Coastguard Worker {
1203*8975f5c5SAndroid Build Coastguard Worker // GLSL ES 3.10 section 4.4.3
1204*8975f5c5SAndroid Build Coastguard Worker int elementLocation = shaderLocation + arrayIndex;
1205*8975f5c5SAndroid Build Coastguard Worker *maxUniformLocation = std::max(*maxUniformLocation, elementLocation);
1206*8975f5c5SAndroid Build Coastguard Worker if (reservedLocations.find(elementLocation) != reservedLocations.end())
1207*8975f5c5SAndroid Build Coastguard Worker {
1208*8975f5c5SAndroid Build Coastguard Worker infoLog << "Multiple uniforms bound to location " << elementLocation << ".";
1209*8975f5c5SAndroid Build Coastguard Worker return false;
1210*8975f5c5SAndroid Build Coastguard Worker }
1211*8975f5c5SAndroid Build Coastguard Worker reservedLocations.insert(elementLocation);
1212*8975f5c5SAndroid Build Coastguard Worker if (!uniform.active)
1213*8975f5c5SAndroid Build Coastguard Worker {
1214*8975f5c5SAndroid Build Coastguard Worker ignoredLocations->insert(elementLocation);
1215*8975f5c5SAndroid Build Coastguard Worker }
1216*8975f5c5SAndroid Build Coastguard Worker }
1217*8975f5c5SAndroid Build Coastguard Worker }
1218*8975f5c5SAndroid Build Coastguard Worker else if (apiBoundLocation != -1 && uniform.staticUse)
1219*8975f5c5SAndroid Build Coastguard Worker {
1220*8975f5c5SAndroid Build Coastguard Worker // Only the first location is reserved even if the uniform is an array.
1221*8975f5c5SAndroid Build Coastguard Worker *maxUniformLocation = std::max(*maxUniformLocation, apiBoundLocation);
1222*8975f5c5SAndroid Build Coastguard Worker if (reservedLocations.find(apiBoundLocation) != reservedLocations.end())
1223*8975f5c5SAndroid Build Coastguard Worker {
1224*8975f5c5SAndroid Build Coastguard Worker infoLog << "Multiple uniforms bound to location " << apiBoundLocation << ".";
1225*8975f5c5SAndroid Build Coastguard Worker return false;
1226*8975f5c5SAndroid Build Coastguard Worker }
1227*8975f5c5SAndroid Build Coastguard Worker reservedLocations.insert(apiBoundLocation);
1228*8975f5c5SAndroid Build Coastguard Worker if (!uniform.active)
1229*8975f5c5SAndroid Build Coastguard Worker {
1230*8975f5c5SAndroid Build Coastguard Worker ignoredLocations->insert(apiBoundLocation);
1231*8975f5c5SAndroid Build Coastguard Worker }
1232*8975f5c5SAndroid Build Coastguard Worker }
1233*8975f5c5SAndroid Build Coastguard Worker }
1234*8975f5c5SAndroid Build Coastguard Worker
1235*8975f5c5SAndroid Build Coastguard Worker // Record the uniform locations that were bound using the API for uniforms that were not found
1236*8975f5c5SAndroid Build Coastguard Worker // from the shader. Other uniforms should not be assigned to those locations.
1237*8975f5c5SAndroid Build Coastguard Worker for (const auto &locationBinding : uniformLocationBindings)
1238*8975f5c5SAndroid Build Coastguard Worker {
1239*8975f5c5SAndroid Build Coastguard Worker GLuint location = locationBinding.second.location;
1240*8975f5c5SAndroid Build Coastguard Worker if (reservedLocations.find(location) == reservedLocations.end())
1241*8975f5c5SAndroid Build Coastguard Worker {
1242*8975f5c5SAndroid Build Coastguard Worker ignoredLocations->insert(location);
1243*8975f5c5SAndroid Build Coastguard Worker *maxUniformLocation = std::max(*maxUniformLocation, static_cast<int>(location));
1244*8975f5c5SAndroid Build Coastguard Worker }
1245*8975f5c5SAndroid Build Coastguard Worker }
1246*8975f5c5SAndroid Build Coastguard Worker
1247*8975f5c5SAndroid Build Coastguard Worker return true;
1248*8975f5c5SAndroid Build Coastguard Worker }
1249*8975f5c5SAndroid Build Coastguard Worker
pruneUnusedUniforms()1250*8975f5c5SAndroid Build Coastguard Worker void UniformLinker::pruneUnusedUniforms()
1251*8975f5c5SAndroid Build Coastguard Worker {
1252*8975f5c5SAndroid Build Coastguard Worker auto uniformIter = mUniforms.begin();
1253*8975f5c5SAndroid Build Coastguard Worker while (uniformIter != mUniforms.end())
1254*8975f5c5SAndroid Build Coastguard Worker {
1255*8975f5c5SAndroid Build Coastguard Worker if (uniformIter->active)
1256*8975f5c5SAndroid Build Coastguard Worker {
1257*8975f5c5SAndroid Build Coastguard Worker ++uniformIter;
1258*8975f5c5SAndroid Build Coastguard Worker }
1259*8975f5c5SAndroid Build Coastguard Worker else
1260*8975f5c5SAndroid Build Coastguard Worker {
1261*8975f5c5SAndroid Build Coastguard Worker mUnusedUniforms.emplace_back(uniformIter->name, uniformIter->isSampler(),
1262*8975f5c5SAndroid Build Coastguard Worker uniformIter->isImage(), uniformIter->isAtomicCounter(),
1263*8975f5c5SAndroid Build Coastguard Worker uniformIter->isFragmentInOut);
1264*8975f5c5SAndroid Build Coastguard Worker uniformIter = mUniforms.erase(uniformIter);
1265*8975f5c5SAndroid Build Coastguard Worker }
1266*8975f5c5SAndroid Build Coastguard Worker }
1267*8975f5c5SAndroid Build Coastguard Worker }
1268*8975f5c5SAndroid Build Coastguard Worker
flattenUniformsAndCheckCapsForShader(ShaderType shaderType,const Caps & caps,std::vector<UsedUniform> & samplerUniforms,std::vector<UsedUniform> & imageUniforms,std::vector<UsedUniform> & atomicCounterUniforms,std::vector<UsedUniform> & inputAttachmentUniforms,std::vector<UnusedUniform> & unusedUniforms,InfoLog & infoLog)1269*8975f5c5SAndroid Build Coastguard Worker bool UniformLinker::flattenUniformsAndCheckCapsForShader(
1270*8975f5c5SAndroid Build Coastguard Worker ShaderType shaderType,
1271*8975f5c5SAndroid Build Coastguard Worker const Caps &caps,
1272*8975f5c5SAndroid Build Coastguard Worker std::vector<UsedUniform> &samplerUniforms,
1273*8975f5c5SAndroid Build Coastguard Worker std::vector<UsedUniform> &imageUniforms,
1274*8975f5c5SAndroid Build Coastguard Worker std::vector<UsedUniform> &atomicCounterUniforms,
1275*8975f5c5SAndroid Build Coastguard Worker std::vector<UsedUniform> &inputAttachmentUniforms,
1276*8975f5c5SAndroid Build Coastguard Worker std::vector<UnusedUniform> &unusedUniforms,
1277*8975f5c5SAndroid Build Coastguard Worker InfoLog &infoLog)
1278*8975f5c5SAndroid Build Coastguard Worker {
1279*8975f5c5SAndroid Build Coastguard Worker ShaderUniformCount shaderUniformCount;
1280*8975f5c5SAndroid Build Coastguard Worker for (const sh::ShaderVariable &uniform : mShaderUniforms[shaderType])
1281*8975f5c5SAndroid Build Coastguard Worker {
1282*8975f5c5SAndroid Build Coastguard Worker FlattenUniformVisitor flattener(shaderType, uniform, &mUniforms, &samplerUniforms,
1283*8975f5c5SAndroid Build Coastguard Worker &imageUniforms, &atomicCounterUniforms,
1284*8975f5c5SAndroid Build Coastguard Worker &inputAttachmentUniforms, &unusedUniforms);
1285*8975f5c5SAndroid Build Coastguard Worker sh::TraverseShaderVariable(uniform, false, &flattener);
1286*8975f5c5SAndroid Build Coastguard Worker
1287*8975f5c5SAndroid Build Coastguard Worker if (uniform.active)
1288*8975f5c5SAndroid Build Coastguard Worker {
1289*8975f5c5SAndroid Build Coastguard Worker shaderUniformCount += flattener.getCounts();
1290*8975f5c5SAndroid Build Coastguard Worker }
1291*8975f5c5SAndroid Build Coastguard Worker else
1292*8975f5c5SAndroid Build Coastguard Worker {
1293*8975f5c5SAndroid Build Coastguard Worker unusedUniforms.emplace_back(uniform.name, IsSamplerType(uniform.type),
1294*8975f5c5SAndroid Build Coastguard Worker IsImageType(uniform.type),
1295*8975f5c5SAndroid Build Coastguard Worker IsAtomicCounterType(uniform.type), uniform.isFragmentInOut);
1296*8975f5c5SAndroid Build Coastguard Worker }
1297*8975f5c5SAndroid Build Coastguard Worker }
1298*8975f5c5SAndroid Build Coastguard Worker
1299*8975f5c5SAndroid Build Coastguard Worker // This code does not do fine-grained component counting.
1300*8975f5c5SAndroid Build Coastguard Worker GLuint maxUniformVectorsCount = GetMaximumShaderUniformVectors(shaderType, caps);
1301*8975f5c5SAndroid Build Coastguard Worker if (shaderUniformCount.vectorCount > maxUniformVectorsCount)
1302*8975f5c5SAndroid Build Coastguard Worker {
1303*8975f5c5SAndroid Build Coastguard Worker GLuint maxUniforms = 0u;
1304*8975f5c5SAndroid Build Coastguard Worker
1305*8975f5c5SAndroid Build Coastguard Worker // See comments in GetUniformResourceLimitName()
1306*8975f5c5SAndroid Build Coastguard Worker if (shaderType == ShaderType::Vertex || shaderType == ShaderType::Fragment)
1307*8975f5c5SAndroid Build Coastguard Worker {
1308*8975f5c5SAndroid Build Coastguard Worker maxUniforms = maxUniformVectorsCount;
1309*8975f5c5SAndroid Build Coastguard Worker }
1310*8975f5c5SAndroid Build Coastguard Worker else
1311*8975f5c5SAndroid Build Coastguard Worker {
1312*8975f5c5SAndroid Build Coastguard Worker maxUniforms = maxUniformVectorsCount * 4;
1313*8975f5c5SAndroid Build Coastguard Worker }
1314*8975f5c5SAndroid Build Coastguard Worker
1315*8975f5c5SAndroid Build Coastguard Worker LogUniformsExceedLimit(shaderType, UniformType::Variable, maxUniforms, infoLog);
1316*8975f5c5SAndroid Build Coastguard Worker return false;
1317*8975f5c5SAndroid Build Coastguard Worker }
1318*8975f5c5SAndroid Build Coastguard Worker
1319*8975f5c5SAndroid Build Coastguard Worker if (shaderUniformCount.samplerCount >
1320*8975f5c5SAndroid Build Coastguard Worker static_cast<GLuint>(caps.maxShaderTextureImageUnits[shaderType]))
1321*8975f5c5SAndroid Build Coastguard Worker {
1322*8975f5c5SAndroid Build Coastguard Worker LogUniformsExceedLimit(shaderType, UniformType::Sampler,
1323*8975f5c5SAndroid Build Coastguard Worker caps.maxShaderTextureImageUnits[shaderType], infoLog);
1324*8975f5c5SAndroid Build Coastguard Worker return false;
1325*8975f5c5SAndroid Build Coastguard Worker }
1326*8975f5c5SAndroid Build Coastguard Worker
1327*8975f5c5SAndroid Build Coastguard Worker if (shaderUniformCount.imageCount >
1328*8975f5c5SAndroid Build Coastguard Worker static_cast<GLuint>(caps.maxShaderImageUniforms[shaderType]))
1329*8975f5c5SAndroid Build Coastguard Worker {
1330*8975f5c5SAndroid Build Coastguard Worker LogUniformsExceedLimit(shaderType, UniformType::Image,
1331*8975f5c5SAndroid Build Coastguard Worker caps.maxShaderImageUniforms[shaderType], infoLog);
1332*8975f5c5SAndroid Build Coastguard Worker return false;
1333*8975f5c5SAndroid Build Coastguard Worker }
1334*8975f5c5SAndroid Build Coastguard Worker
1335*8975f5c5SAndroid Build Coastguard Worker if (shaderUniformCount.atomicCounterCount >
1336*8975f5c5SAndroid Build Coastguard Worker static_cast<GLuint>(caps.maxShaderAtomicCounters[shaderType]))
1337*8975f5c5SAndroid Build Coastguard Worker {
1338*8975f5c5SAndroid Build Coastguard Worker LogUniformsExceedLimit(shaderType, UniformType::AtomicCounter,
1339*8975f5c5SAndroid Build Coastguard Worker caps.maxShaderAtomicCounters[shaderType], infoLog);
1340*8975f5c5SAndroid Build Coastguard Worker return false;
1341*8975f5c5SAndroid Build Coastguard Worker }
1342*8975f5c5SAndroid Build Coastguard Worker
1343*8975f5c5SAndroid Build Coastguard Worker return true;
1344*8975f5c5SAndroid Build Coastguard Worker }
1345*8975f5c5SAndroid Build Coastguard Worker
flattenUniformsAndCheckCaps(const Caps & caps,InfoLog & infoLog)1346*8975f5c5SAndroid Build Coastguard Worker bool UniformLinker::flattenUniformsAndCheckCaps(const Caps &caps, InfoLog &infoLog)
1347*8975f5c5SAndroid Build Coastguard Worker {
1348*8975f5c5SAndroid Build Coastguard Worker std::vector<UsedUniform> samplerUniforms;
1349*8975f5c5SAndroid Build Coastguard Worker std::vector<UsedUniform> imageUniforms;
1350*8975f5c5SAndroid Build Coastguard Worker std::vector<UsedUniform> atomicCounterUniforms;
1351*8975f5c5SAndroid Build Coastguard Worker std::vector<UsedUniform> inputAttachmentUniforms;
1352*8975f5c5SAndroid Build Coastguard Worker std::vector<UnusedUniform> unusedUniforms;
1353*8975f5c5SAndroid Build Coastguard Worker
1354*8975f5c5SAndroid Build Coastguard Worker for (const ShaderType shaderType : mActiveShaderStages)
1355*8975f5c5SAndroid Build Coastguard Worker {
1356*8975f5c5SAndroid Build Coastguard Worker if (!flattenUniformsAndCheckCapsForShader(shaderType, caps, samplerUniforms, imageUniforms,
1357*8975f5c5SAndroid Build Coastguard Worker atomicCounterUniforms, inputAttachmentUniforms,
1358*8975f5c5SAndroid Build Coastguard Worker unusedUniforms, infoLog))
1359*8975f5c5SAndroid Build Coastguard Worker {
1360*8975f5c5SAndroid Build Coastguard Worker return false;
1361*8975f5c5SAndroid Build Coastguard Worker }
1362*8975f5c5SAndroid Build Coastguard Worker }
1363*8975f5c5SAndroid Build Coastguard Worker
1364*8975f5c5SAndroid Build Coastguard Worker mUniforms.insert(mUniforms.end(), samplerUniforms.begin(), samplerUniforms.end());
1365*8975f5c5SAndroid Build Coastguard Worker mUniforms.insert(mUniforms.end(), imageUniforms.begin(), imageUniforms.end());
1366*8975f5c5SAndroid Build Coastguard Worker mUniforms.insert(mUniforms.end(), atomicCounterUniforms.begin(), atomicCounterUniforms.end());
1367*8975f5c5SAndroid Build Coastguard Worker mUniforms.insert(mUniforms.end(), inputAttachmentUniforms.begin(),
1368*8975f5c5SAndroid Build Coastguard Worker inputAttachmentUniforms.end());
1369*8975f5c5SAndroid Build Coastguard Worker mUnusedUniforms.insert(mUnusedUniforms.end(), unusedUniforms.begin(), unusedUniforms.end());
1370*8975f5c5SAndroid Build Coastguard Worker return true;
1371*8975f5c5SAndroid Build Coastguard Worker }
1372*8975f5c5SAndroid Build Coastguard Worker
checkMaxCombinedAtomicCounters(const Caps & caps,InfoLog & infoLog)1373*8975f5c5SAndroid Build Coastguard Worker bool UniformLinker::checkMaxCombinedAtomicCounters(const Caps &caps, InfoLog &infoLog)
1374*8975f5c5SAndroid Build Coastguard Worker {
1375*8975f5c5SAndroid Build Coastguard Worker unsigned int atomicCounterCount = 0;
1376*8975f5c5SAndroid Build Coastguard Worker for (const auto &uniform : mUniforms)
1377*8975f5c5SAndroid Build Coastguard Worker {
1378*8975f5c5SAndroid Build Coastguard Worker if (IsAtomicCounterType(uniform.type) && uniform.active)
1379*8975f5c5SAndroid Build Coastguard Worker {
1380*8975f5c5SAndroid Build Coastguard Worker atomicCounterCount += uniform.getBasicTypeElementCount();
1381*8975f5c5SAndroid Build Coastguard Worker if (atomicCounterCount > static_cast<GLuint>(caps.maxCombinedAtomicCounters))
1382*8975f5c5SAndroid Build Coastguard Worker {
1383*8975f5c5SAndroid Build Coastguard Worker infoLog << "atomic counter count exceeds MAX_COMBINED_ATOMIC_COUNTERS"
1384*8975f5c5SAndroid Build Coastguard Worker << caps.maxCombinedAtomicCounters << ").";
1385*8975f5c5SAndroid Build Coastguard Worker return false;
1386*8975f5c5SAndroid Build Coastguard Worker }
1387*8975f5c5SAndroid Build Coastguard Worker }
1388*8975f5c5SAndroid Build Coastguard Worker }
1389*8975f5c5SAndroid Build Coastguard Worker return true;
1390*8975f5c5SAndroid Build Coastguard Worker }
1391*8975f5c5SAndroid Build Coastguard Worker
1392*8975f5c5SAndroid Build Coastguard Worker // InterfaceBlockLinker implementation.
1393*8975f5c5SAndroid Build Coastguard Worker InterfaceBlockLinker::InterfaceBlockLinker() = default;
1394*8975f5c5SAndroid Build Coastguard Worker
1395*8975f5c5SAndroid Build Coastguard Worker InterfaceBlockLinker::~InterfaceBlockLinker() = default;
1396*8975f5c5SAndroid Build Coastguard Worker
init(std::vector<InterfaceBlock> * blocksOut,std::vector<std::string> * unusedInterfaceBlocksOut)1397*8975f5c5SAndroid Build Coastguard Worker void InterfaceBlockLinker::init(std::vector<InterfaceBlock> *blocksOut,
1398*8975f5c5SAndroid Build Coastguard Worker std::vector<std::string> *unusedInterfaceBlocksOut)
1399*8975f5c5SAndroid Build Coastguard Worker {
1400*8975f5c5SAndroid Build Coastguard Worker mBlocksOut = blocksOut;
1401*8975f5c5SAndroid Build Coastguard Worker mUnusedInterfaceBlocksOut = unusedInterfaceBlocksOut;
1402*8975f5c5SAndroid Build Coastguard Worker }
1403*8975f5c5SAndroid Build Coastguard Worker
addShaderBlocks(ShaderType shaderType,const std::vector<sh::InterfaceBlock> * blocks)1404*8975f5c5SAndroid Build Coastguard Worker void InterfaceBlockLinker::addShaderBlocks(ShaderType shaderType,
1405*8975f5c5SAndroid Build Coastguard Worker const std::vector<sh::InterfaceBlock> *blocks)
1406*8975f5c5SAndroid Build Coastguard Worker {
1407*8975f5c5SAndroid Build Coastguard Worker mShaderBlocks[shaderType] = blocks;
1408*8975f5c5SAndroid Build Coastguard Worker }
1409*8975f5c5SAndroid Build Coastguard Worker
linkBlocks(const GetBlockSizeFunc & getBlockSize,const GetBlockMemberInfoFunc & getMemberInfo) const1410*8975f5c5SAndroid Build Coastguard Worker void InterfaceBlockLinker::linkBlocks(const GetBlockSizeFunc &getBlockSize,
1411*8975f5c5SAndroid Build Coastguard Worker const GetBlockMemberInfoFunc &getMemberInfo) const
1412*8975f5c5SAndroid Build Coastguard Worker {
1413*8975f5c5SAndroid Build Coastguard Worker ASSERT(mBlocksOut->empty());
1414*8975f5c5SAndroid Build Coastguard Worker
1415*8975f5c5SAndroid Build Coastguard Worker std::set<std::string> visitedList;
1416*8975f5c5SAndroid Build Coastguard Worker
1417*8975f5c5SAndroid Build Coastguard Worker for (const ShaderType shaderType : AllShaderTypes())
1418*8975f5c5SAndroid Build Coastguard Worker {
1419*8975f5c5SAndroid Build Coastguard Worker if (!mShaderBlocks[shaderType])
1420*8975f5c5SAndroid Build Coastguard Worker {
1421*8975f5c5SAndroid Build Coastguard Worker continue;
1422*8975f5c5SAndroid Build Coastguard Worker }
1423*8975f5c5SAndroid Build Coastguard Worker
1424*8975f5c5SAndroid Build Coastguard Worker for (const sh::InterfaceBlock &block : *mShaderBlocks[shaderType])
1425*8975f5c5SAndroid Build Coastguard Worker {
1426*8975f5c5SAndroid Build Coastguard Worker if (!IsActiveInterfaceBlock(block))
1427*8975f5c5SAndroid Build Coastguard Worker {
1428*8975f5c5SAndroid Build Coastguard Worker mUnusedInterfaceBlocksOut->push_back(block.name);
1429*8975f5c5SAndroid Build Coastguard Worker continue;
1430*8975f5c5SAndroid Build Coastguard Worker }
1431*8975f5c5SAndroid Build Coastguard Worker
1432*8975f5c5SAndroid Build Coastguard Worker if (visitedList.count(block.name) == 0)
1433*8975f5c5SAndroid Build Coastguard Worker {
1434*8975f5c5SAndroid Build Coastguard Worker defineInterfaceBlock(getBlockSize, getMemberInfo, block, shaderType);
1435*8975f5c5SAndroid Build Coastguard Worker visitedList.insert(block.name);
1436*8975f5c5SAndroid Build Coastguard Worker continue;
1437*8975f5c5SAndroid Build Coastguard Worker }
1438*8975f5c5SAndroid Build Coastguard Worker
1439*8975f5c5SAndroid Build Coastguard Worker if (!block.active)
1440*8975f5c5SAndroid Build Coastguard Worker {
1441*8975f5c5SAndroid Build Coastguard Worker mUnusedInterfaceBlocksOut->push_back(block.name);
1442*8975f5c5SAndroid Build Coastguard Worker continue;
1443*8975f5c5SAndroid Build Coastguard Worker }
1444*8975f5c5SAndroid Build Coastguard Worker
1445*8975f5c5SAndroid Build Coastguard Worker for (InterfaceBlock &priorBlock : *mBlocksOut)
1446*8975f5c5SAndroid Build Coastguard Worker {
1447*8975f5c5SAndroid Build Coastguard Worker if (block.name == priorBlock.name)
1448*8975f5c5SAndroid Build Coastguard Worker {
1449*8975f5c5SAndroid Build Coastguard Worker priorBlock.setActive(shaderType, true, block.id);
1450*8975f5c5SAndroid Build Coastguard Worker
1451*8975f5c5SAndroid Build Coastguard Worker std::unique_ptr<sh::ShaderVariableVisitor> visitor(
1452*8975f5c5SAndroid Build Coastguard Worker getVisitor(getMemberInfo, block.fieldPrefix(), block.fieldMappedPrefix(),
1453*8975f5c5SAndroid Build Coastguard Worker shaderType, -1));
1454*8975f5c5SAndroid Build Coastguard Worker
1455*8975f5c5SAndroid Build Coastguard Worker sh::TraverseShaderVariables(block.fields, false, visitor.get());
1456*8975f5c5SAndroid Build Coastguard Worker }
1457*8975f5c5SAndroid Build Coastguard Worker }
1458*8975f5c5SAndroid Build Coastguard Worker }
1459*8975f5c5SAndroid Build Coastguard Worker }
1460*8975f5c5SAndroid Build Coastguard Worker }
1461*8975f5c5SAndroid Build Coastguard Worker
defineInterfaceBlock(const GetBlockSizeFunc & getBlockSize,const GetBlockMemberInfoFunc & getMemberInfo,const sh::InterfaceBlock & interfaceBlock,ShaderType shaderType) const1462*8975f5c5SAndroid Build Coastguard Worker void InterfaceBlockLinker::defineInterfaceBlock(const GetBlockSizeFunc &getBlockSize,
1463*8975f5c5SAndroid Build Coastguard Worker const GetBlockMemberInfoFunc &getMemberInfo,
1464*8975f5c5SAndroid Build Coastguard Worker const sh::InterfaceBlock &interfaceBlock,
1465*8975f5c5SAndroid Build Coastguard Worker ShaderType shaderType) const
1466*8975f5c5SAndroid Build Coastguard Worker {
1467*8975f5c5SAndroid Build Coastguard Worker size_t blockSize = 0;
1468*8975f5c5SAndroid Build Coastguard Worker std::vector<unsigned int> blockIndexes;
1469*8975f5c5SAndroid Build Coastguard Worker
1470*8975f5c5SAndroid Build Coastguard Worker const int blockIndex = static_cast<int>(mBlocksOut->size());
1471*8975f5c5SAndroid Build Coastguard Worker // Track the first and last block member index to determine the range of active block members in
1472*8975f5c5SAndroid Build Coastguard Worker // the block.
1473*8975f5c5SAndroid Build Coastguard Worker const size_t firstBlockMemberIndex = getCurrentBlockMemberIndex();
1474*8975f5c5SAndroid Build Coastguard Worker
1475*8975f5c5SAndroid Build Coastguard Worker std::unique_ptr<sh::ShaderVariableVisitor> visitor(
1476*8975f5c5SAndroid Build Coastguard Worker getVisitor(getMemberInfo, interfaceBlock.fieldPrefix(), interfaceBlock.fieldMappedPrefix(),
1477*8975f5c5SAndroid Build Coastguard Worker shaderType, blockIndex));
1478*8975f5c5SAndroid Build Coastguard Worker sh::TraverseShaderVariables(interfaceBlock.fields, false, visitor.get());
1479*8975f5c5SAndroid Build Coastguard Worker
1480*8975f5c5SAndroid Build Coastguard Worker const size_t lastBlockMemberIndex = getCurrentBlockMemberIndex();
1481*8975f5c5SAndroid Build Coastguard Worker
1482*8975f5c5SAndroid Build Coastguard Worker for (size_t blockMemberIndex = firstBlockMemberIndex; blockMemberIndex < lastBlockMemberIndex;
1483*8975f5c5SAndroid Build Coastguard Worker ++blockMemberIndex)
1484*8975f5c5SAndroid Build Coastguard Worker {
1485*8975f5c5SAndroid Build Coastguard Worker blockIndexes.push_back(static_cast<unsigned int>(blockMemberIndex));
1486*8975f5c5SAndroid Build Coastguard Worker }
1487*8975f5c5SAndroid Build Coastguard Worker
1488*8975f5c5SAndroid Build Coastguard Worker const unsigned int firstFieldArraySize = interfaceBlock.fields[0].getArraySizeProduct();
1489*8975f5c5SAndroid Build Coastguard Worker
1490*8975f5c5SAndroid Build Coastguard Worker for (unsigned int arrayElement = 0; arrayElement < interfaceBlock.elementCount();
1491*8975f5c5SAndroid Build Coastguard Worker ++arrayElement)
1492*8975f5c5SAndroid Build Coastguard Worker {
1493*8975f5c5SAndroid Build Coastguard Worker std::string blockArrayName = interfaceBlock.name;
1494*8975f5c5SAndroid Build Coastguard Worker std::string blockMappedArrayName = interfaceBlock.mappedName;
1495*8975f5c5SAndroid Build Coastguard Worker if (interfaceBlock.isArray())
1496*8975f5c5SAndroid Build Coastguard Worker {
1497*8975f5c5SAndroid Build Coastguard Worker blockArrayName += ArrayString(arrayElement);
1498*8975f5c5SAndroid Build Coastguard Worker blockMappedArrayName += ArrayString(arrayElement);
1499*8975f5c5SAndroid Build Coastguard Worker }
1500*8975f5c5SAndroid Build Coastguard Worker
1501*8975f5c5SAndroid Build Coastguard Worker // Don't define this block at all if it's not active in the implementation.
1502*8975f5c5SAndroid Build Coastguard Worker if (!getBlockSize(blockArrayName, blockMappedArrayName, &blockSize))
1503*8975f5c5SAndroid Build Coastguard Worker {
1504*8975f5c5SAndroid Build Coastguard Worker continue;
1505*8975f5c5SAndroid Build Coastguard Worker }
1506*8975f5c5SAndroid Build Coastguard Worker
1507*8975f5c5SAndroid Build Coastguard Worker // ESSL 3.10 section 4.4.4 page 58:
1508*8975f5c5SAndroid Build Coastguard Worker // Any uniform or shader storage block declared without a binding qualifier is initially
1509*8975f5c5SAndroid Build Coastguard Worker // assigned to block binding point zero.
1510*8975f5c5SAndroid Build Coastguard Worker const int blockBinding =
1511*8975f5c5SAndroid Build Coastguard Worker (interfaceBlock.binding == -1 ? 0 : interfaceBlock.binding + arrayElement);
1512*8975f5c5SAndroid Build Coastguard Worker InterfaceBlock block(interfaceBlock.name, interfaceBlock.mappedName,
1513*8975f5c5SAndroid Build Coastguard Worker interfaceBlock.isArray(), interfaceBlock.isReadOnly, arrayElement,
1514*8975f5c5SAndroid Build Coastguard Worker firstFieldArraySize, blockBinding);
1515*8975f5c5SAndroid Build Coastguard Worker block.memberIndexes = blockIndexes;
1516*8975f5c5SAndroid Build Coastguard Worker block.setActive(shaderType, interfaceBlock.active, interfaceBlock.id);
1517*8975f5c5SAndroid Build Coastguard Worker
1518*8975f5c5SAndroid Build Coastguard Worker // Since all block elements in an array share the same active interface blocks, they
1519*8975f5c5SAndroid Build Coastguard Worker // will all be active once any block member is used. So, since interfaceBlock.name[0]
1520*8975f5c5SAndroid Build Coastguard Worker // was active, here we will add every block element in the array.
1521*8975f5c5SAndroid Build Coastguard Worker block.pod.dataSize = static_cast<unsigned int>(blockSize);
1522*8975f5c5SAndroid Build Coastguard Worker mBlocksOut->push_back(block);
1523*8975f5c5SAndroid Build Coastguard Worker }
1524*8975f5c5SAndroid Build Coastguard Worker }
1525*8975f5c5SAndroid Build Coastguard Worker
1526*8975f5c5SAndroid Build Coastguard Worker // UniformBlockLinker implementation.
1527*8975f5c5SAndroid Build Coastguard Worker UniformBlockLinker::UniformBlockLinker() = default;
1528*8975f5c5SAndroid Build Coastguard Worker
~UniformBlockLinker()1529*8975f5c5SAndroid Build Coastguard Worker UniformBlockLinker::~UniformBlockLinker() {}
1530*8975f5c5SAndroid Build Coastguard Worker
init(std::vector<InterfaceBlock> * blocksOut,std::vector<LinkedUniform> * uniformsOut,std::vector<std::string> * uniformNamesOut,std::vector<std::string> * uniformMappedNamesOut,std::vector<std::string> * unusedInterfaceBlocksOut)1531*8975f5c5SAndroid Build Coastguard Worker void UniformBlockLinker::init(std::vector<InterfaceBlock> *blocksOut,
1532*8975f5c5SAndroid Build Coastguard Worker std::vector<LinkedUniform> *uniformsOut,
1533*8975f5c5SAndroid Build Coastguard Worker std::vector<std::string> *uniformNamesOut,
1534*8975f5c5SAndroid Build Coastguard Worker std::vector<std::string> *uniformMappedNamesOut,
1535*8975f5c5SAndroid Build Coastguard Worker std::vector<std::string> *unusedInterfaceBlocksOut)
1536*8975f5c5SAndroid Build Coastguard Worker {
1537*8975f5c5SAndroid Build Coastguard Worker InterfaceBlockLinker::init(blocksOut, unusedInterfaceBlocksOut);
1538*8975f5c5SAndroid Build Coastguard Worker mUniformsOut = uniformsOut;
1539*8975f5c5SAndroid Build Coastguard Worker mUniformNamesOut = uniformNamesOut;
1540*8975f5c5SAndroid Build Coastguard Worker mUniformMappedNamesOut = uniformMappedNamesOut;
1541*8975f5c5SAndroid Build Coastguard Worker }
1542*8975f5c5SAndroid Build Coastguard Worker
getCurrentBlockMemberIndex() const1543*8975f5c5SAndroid Build Coastguard Worker size_t UniformBlockLinker::getCurrentBlockMemberIndex() const
1544*8975f5c5SAndroid Build Coastguard Worker {
1545*8975f5c5SAndroid Build Coastguard Worker return mUniformsOut->size();
1546*8975f5c5SAndroid Build Coastguard Worker }
1547*8975f5c5SAndroid Build Coastguard Worker
getVisitor(const GetBlockMemberInfoFunc & getMemberInfo,const std::string & namePrefix,const std::string & mappedNamePrefix,ShaderType shaderType,int blockIndex) const1548*8975f5c5SAndroid Build Coastguard Worker sh::ShaderVariableVisitor *UniformBlockLinker::getVisitor(
1549*8975f5c5SAndroid Build Coastguard Worker const GetBlockMemberInfoFunc &getMemberInfo,
1550*8975f5c5SAndroid Build Coastguard Worker const std::string &namePrefix,
1551*8975f5c5SAndroid Build Coastguard Worker const std::string &mappedNamePrefix,
1552*8975f5c5SAndroid Build Coastguard Worker ShaderType shaderType,
1553*8975f5c5SAndroid Build Coastguard Worker int blockIndex) const
1554*8975f5c5SAndroid Build Coastguard Worker {
1555*8975f5c5SAndroid Build Coastguard Worker return new UniformBlockEncodingVisitor(getMemberInfo, namePrefix, mappedNamePrefix,
1556*8975f5c5SAndroid Build Coastguard Worker mUniformsOut, mUniformNamesOut, mUniformMappedNamesOut,
1557*8975f5c5SAndroid Build Coastguard Worker shaderType, blockIndex);
1558*8975f5c5SAndroid Build Coastguard Worker }
1559*8975f5c5SAndroid Build Coastguard Worker
1560*8975f5c5SAndroid Build Coastguard Worker // ShaderStorageBlockLinker implementation.
1561*8975f5c5SAndroid Build Coastguard Worker ShaderStorageBlockLinker::ShaderStorageBlockLinker() = default;
1562*8975f5c5SAndroid Build Coastguard Worker
1563*8975f5c5SAndroid Build Coastguard Worker ShaderStorageBlockLinker::~ShaderStorageBlockLinker() = default;
1564*8975f5c5SAndroid Build Coastguard Worker
init(std::vector<InterfaceBlock> * blocksOut,std::vector<BufferVariable> * bufferVariablesOut,std::vector<std::string> * unusedInterfaceBlocksOut)1565*8975f5c5SAndroid Build Coastguard Worker void ShaderStorageBlockLinker::init(std::vector<InterfaceBlock> *blocksOut,
1566*8975f5c5SAndroid Build Coastguard Worker std::vector<BufferVariable> *bufferVariablesOut,
1567*8975f5c5SAndroid Build Coastguard Worker std::vector<std::string> *unusedInterfaceBlocksOut)
1568*8975f5c5SAndroid Build Coastguard Worker {
1569*8975f5c5SAndroid Build Coastguard Worker InterfaceBlockLinker::init(blocksOut, unusedInterfaceBlocksOut);
1570*8975f5c5SAndroid Build Coastguard Worker mBufferVariablesOut = bufferVariablesOut;
1571*8975f5c5SAndroid Build Coastguard Worker }
1572*8975f5c5SAndroid Build Coastguard Worker
getCurrentBlockMemberIndex() const1573*8975f5c5SAndroid Build Coastguard Worker size_t ShaderStorageBlockLinker::getCurrentBlockMemberIndex() const
1574*8975f5c5SAndroid Build Coastguard Worker {
1575*8975f5c5SAndroid Build Coastguard Worker return mBufferVariablesOut->size();
1576*8975f5c5SAndroid Build Coastguard Worker }
1577*8975f5c5SAndroid Build Coastguard Worker
getVisitor(const GetBlockMemberInfoFunc & getMemberInfo,const std::string & namePrefix,const std::string & mappedNamePrefix,ShaderType shaderType,int blockIndex) const1578*8975f5c5SAndroid Build Coastguard Worker sh::ShaderVariableVisitor *ShaderStorageBlockLinker::getVisitor(
1579*8975f5c5SAndroid Build Coastguard Worker const GetBlockMemberInfoFunc &getMemberInfo,
1580*8975f5c5SAndroid Build Coastguard Worker const std::string &namePrefix,
1581*8975f5c5SAndroid Build Coastguard Worker const std::string &mappedNamePrefix,
1582*8975f5c5SAndroid Build Coastguard Worker ShaderType shaderType,
1583*8975f5c5SAndroid Build Coastguard Worker int blockIndex) const
1584*8975f5c5SAndroid Build Coastguard Worker {
1585*8975f5c5SAndroid Build Coastguard Worker return new ShaderStorageBlockVisitor(getMemberInfo, namePrefix, mappedNamePrefix,
1586*8975f5c5SAndroid Build Coastguard Worker mBufferVariablesOut, shaderType, blockIndex);
1587*8975f5c5SAndroid Build Coastguard Worker }
1588*8975f5c5SAndroid Build Coastguard Worker
1589*8975f5c5SAndroid Build Coastguard Worker // AtomicCounterBufferLinker implementation.
1590*8975f5c5SAndroid Build Coastguard Worker AtomicCounterBufferLinker::AtomicCounterBufferLinker() = default;
1591*8975f5c5SAndroid Build Coastguard Worker
1592*8975f5c5SAndroid Build Coastguard Worker AtomicCounterBufferLinker::~AtomicCounterBufferLinker() = default;
1593*8975f5c5SAndroid Build Coastguard Worker
init(std::vector<AtomicCounterBuffer> * atomicCounterBuffersOut)1594*8975f5c5SAndroid Build Coastguard Worker void AtomicCounterBufferLinker::init(std::vector<AtomicCounterBuffer> *atomicCounterBuffersOut)
1595*8975f5c5SAndroid Build Coastguard Worker {
1596*8975f5c5SAndroid Build Coastguard Worker mAtomicCounterBuffersOut = atomicCounterBuffersOut;
1597*8975f5c5SAndroid Build Coastguard Worker }
1598*8975f5c5SAndroid Build Coastguard Worker
link(const std::map<int,unsigned int> & sizeMap) const1599*8975f5c5SAndroid Build Coastguard Worker void AtomicCounterBufferLinker::link(const std::map<int, unsigned int> &sizeMap) const
1600*8975f5c5SAndroid Build Coastguard Worker {
1601*8975f5c5SAndroid Build Coastguard Worker for (auto &atomicCounterBuffer : *mAtomicCounterBuffersOut)
1602*8975f5c5SAndroid Build Coastguard Worker {
1603*8975f5c5SAndroid Build Coastguard Worker auto bufferSize = sizeMap.find(atomicCounterBuffer.pod.inShaderBinding);
1604*8975f5c5SAndroid Build Coastguard Worker ASSERT(bufferSize != sizeMap.end());
1605*8975f5c5SAndroid Build Coastguard Worker atomicCounterBuffer.pod.dataSize = bufferSize->second;
1606*8975f5c5SAndroid Build Coastguard Worker }
1607*8975f5c5SAndroid Build Coastguard Worker }
1608*8975f5c5SAndroid Build Coastguard Worker
1609*8975f5c5SAndroid Build Coastguard Worker PixelLocalStorageLinker::PixelLocalStorageLinker() = default;
1610*8975f5c5SAndroid Build Coastguard Worker
1611*8975f5c5SAndroid Build Coastguard Worker PixelLocalStorageLinker::~PixelLocalStorageLinker() = default;
1612*8975f5c5SAndroid Build Coastguard Worker
init(std::vector<ShPixelLocalStorageFormat> * pixelLocalStorageFormatsOut)1613*8975f5c5SAndroid Build Coastguard Worker void PixelLocalStorageLinker::init(
1614*8975f5c5SAndroid Build Coastguard Worker std::vector<ShPixelLocalStorageFormat> *pixelLocalStorageFormatsOut)
1615*8975f5c5SAndroid Build Coastguard Worker {
1616*8975f5c5SAndroid Build Coastguard Worker mPixelLocalStorageFormatsOut = pixelLocalStorageFormatsOut;
1617*8975f5c5SAndroid Build Coastguard Worker }
1618*8975f5c5SAndroid Build Coastguard Worker
link(const std::vector<ShPixelLocalStorageFormat> & pixelLocalStorageFormats) const1619*8975f5c5SAndroid Build Coastguard Worker void PixelLocalStorageLinker::link(
1620*8975f5c5SAndroid Build Coastguard Worker const std::vector<ShPixelLocalStorageFormat> &pixelLocalStorageFormats) const
1621*8975f5c5SAndroid Build Coastguard Worker {
1622*8975f5c5SAndroid Build Coastguard Worker *mPixelLocalStorageFormatsOut = pixelLocalStorageFormats;
1623*8975f5c5SAndroid Build Coastguard Worker }
1624*8975f5c5SAndroid Build Coastguard Worker
1625*8975f5c5SAndroid Build Coastguard Worker LinkingVariables::LinkingVariables() = default;
1626*8975f5c5SAndroid Build Coastguard Worker LinkingVariables::~LinkingVariables() = default;
1627*8975f5c5SAndroid Build Coastguard Worker
initForProgram(const ProgramState & state)1628*8975f5c5SAndroid Build Coastguard Worker void LinkingVariables::initForProgram(const ProgramState &state)
1629*8975f5c5SAndroid Build Coastguard Worker {
1630*8975f5c5SAndroid Build Coastguard Worker for (ShaderType shaderType : kAllGraphicsShaderTypes)
1631*8975f5c5SAndroid Build Coastguard Worker {
1632*8975f5c5SAndroid Build Coastguard Worker const SharedCompiledShaderState &shader = state.getAttachedShader(shaderType);
1633*8975f5c5SAndroid Build Coastguard Worker if (shader)
1634*8975f5c5SAndroid Build Coastguard Worker {
1635*8975f5c5SAndroid Build Coastguard Worker outputVaryings[shaderType] = shader->outputVaryings;
1636*8975f5c5SAndroid Build Coastguard Worker inputVaryings[shaderType] = shader->inputVaryings;
1637*8975f5c5SAndroid Build Coastguard Worker uniforms[shaderType] = shader->uniforms;
1638*8975f5c5SAndroid Build Coastguard Worker uniformBlocks[shaderType] = shader->uniformBlocks;
1639*8975f5c5SAndroid Build Coastguard Worker isShaderStageUsedBitset.set(shaderType);
1640*8975f5c5SAndroid Build Coastguard Worker }
1641*8975f5c5SAndroid Build Coastguard Worker }
1642*8975f5c5SAndroid Build Coastguard Worker }
1643*8975f5c5SAndroid Build Coastguard Worker
initForProgramPipeline(const ProgramPipelineState & state)1644*8975f5c5SAndroid Build Coastguard Worker void LinkingVariables::initForProgramPipeline(const ProgramPipelineState &state)
1645*8975f5c5SAndroid Build Coastguard Worker {
1646*8975f5c5SAndroid Build Coastguard Worker for (ShaderType shaderType : state.getExecutable().getLinkedShaderStages())
1647*8975f5c5SAndroid Build Coastguard Worker {
1648*8975f5c5SAndroid Build Coastguard Worker const SharedProgramExecutable &executable = state.getShaderProgramExecutable(shaderType);
1649*8975f5c5SAndroid Build Coastguard Worker ASSERT(executable);
1650*8975f5c5SAndroid Build Coastguard Worker outputVaryings[shaderType] = executable->getLinkedOutputVaryings(shaderType);
1651*8975f5c5SAndroid Build Coastguard Worker inputVaryings[shaderType] = executable->getLinkedInputVaryings(shaderType);
1652*8975f5c5SAndroid Build Coastguard Worker uniforms[shaderType] = executable->getLinkedUniforms(shaderType);
1653*8975f5c5SAndroid Build Coastguard Worker uniformBlocks[shaderType] = executable->getLinkedUniformBlocks(shaderType);
1654*8975f5c5SAndroid Build Coastguard Worker isShaderStageUsedBitset.set(shaderType);
1655*8975f5c5SAndroid Build Coastguard Worker }
1656*8975f5c5SAndroid Build Coastguard Worker }
1657*8975f5c5SAndroid Build Coastguard Worker
1658*8975f5c5SAndroid Build Coastguard Worker ProgramLinkedResources::ProgramLinkedResources() = default;
1659*8975f5c5SAndroid Build Coastguard Worker ProgramLinkedResources::~ProgramLinkedResources() = default;
1660*8975f5c5SAndroid Build Coastguard Worker
init(std::vector<InterfaceBlock> * uniformBlocksOut,std::vector<LinkedUniform> * uniformsOut,std::vector<std::string> * uniformNamesOut,std::vector<std::string> * uniformMappedNamesOut,std::vector<InterfaceBlock> * shaderStorageBlocksOut,std::vector<BufferVariable> * bufferVariablesOut,std::vector<AtomicCounterBuffer> * atomicCounterBuffersOut,std::vector<ShPixelLocalStorageFormat> * pixelLocalStorageFormatsOut)1661*8975f5c5SAndroid Build Coastguard Worker void ProgramLinkedResources::init(
1662*8975f5c5SAndroid Build Coastguard Worker std::vector<InterfaceBlock> *uniformBlocksOut,
1663*8975f5c5SAndroid Build Coastguard Worker std::vector<LinkedUniform> *uniformsOut,
1664*8975f5c5SAndroid Build Coastguard Worker std::vector<std::string> *uniformNamesOut,
1665*8975f5c5SAndroid Build Coastguard Worker std::vector<std::string> *uniformMappedNamesOut,
1666*8975f5c5SAndroid Build Coastguard Worker std::vector<InterfaceBlock> *shaderStorageBlocksOut,
1667*8975f5c5SAndroid Build Coastguard Worker std::vector<BufferVariable> *bufferVariablesOut,
1668*8975f5c5SAndroid Build Coastguard Worker std::vector<AtomicCounterBuffer> *atomicCounterBuffersOut,
1669*8975f5c5SAndroid Build Coastguard Worker std::vector<ShPixelLocalStorageFormat> *pixelLocalStorageFormatsOut)
1670*8975f5c5SAndroid Build Coastguard Worker {
1671*8975f5c5SAndroid Build Coastguard Worker uniformBlockLinker.init(uniformBlocksOut, uniformsOut, uniformNamesOut, uniformMappedNamesOut,
1672*8975f5c5SAndroid Build Coastguard Worker &unusedInterfaceBlocks);
1673*8975f5c5SAndroid Build Coastguard Worker shaderStorageBlockLinker.init(shaderStorageBlocksOut, bufferVariablesOut,
1674*8975f5c5SAndroid Build Coastguard Worker &unusedInterfaceBlocks);
1675*8975f5c5SAndroid Build Coastguard Worker atomicCounterBufferLinker.init(atomicCounterBuffersOut);
1676*8975f5c5SAndroid Build Coastguard Worker pixelLocalStorageLinker.init(pixelLocalStorageFormatsOut);
1677*8975f5c5SAndroid Build Coastguard Worker }
1678*8975f5c5SAndroid Build Coastguard Worker
linkResources(const ProgramState & programState,const ProgramLinkedResources & resources) const1679*8975f5c5SAndroid Build Coastguard Worker void ProgramLinkedResourcesLinker::linkResources(const ProgramState &programState,
1680*8975f5c5SAndroid Build Coastguard Worker const ProgramLinkedResources &resources) const
1681*8975f5c5SAndroid Build Coastguard Worker {
1682*8975f5c5SAndroid Build Coastguard Worker // Gather uniform interface block info.
1683*8975f5c5SAndroid Build Coastguard Worker InterfaceBlockInfo uniformBlockInfo(mCustomEncoderFactory);
1684*8975f5c5SAndroid Build Coastguard Worker for (const ShaderType shaderType : AllShaderTypes())
1685*8975f5c5SAndroid Build Coastguard Worker {
1686*8975f5c5SAndroid Build Coastguard Worker const SharedCompiledShaderState &shader = programState.getAttachedShader(shaderType);
1687*8975f5c5SAndroid Build Coastguard Worker if (shader)
1688*8975f5c5SAndroid Build Coastguard Worker {
1689*8975f5c5SAndroid Build Coastguard Worker uniformBlockInfo.getShaderBlockInfo(shader->uniformBlocks);
1690*8975f5c5SAndroid Build Coastguard Worker }
1691*8975f5c5SAndroid Build Coastguard Worker }
1692*8975f5c5SAndroid Build Coastguard Worker
1693*8975f5c5SAndroid Build Coastguard Worker auto getUniformBlockSize = [&uniformBlockInfo](const std::string &name,
1694*8975f5c5SAndroid Build Coastguard Worker const std::string &mappedName, size_t *sizeOut) {
1695*8975f5c5SAndroid Build Coastguard Worker return uniformBlockInfo.getBlockSize(name, mappedName, sizeOut);
1696*8975f5c5SAndroid Build Coastguard Worker };
1697*8975f5c5SAndroid Build Coastguard Worker
1698*8975f5c5SAndroid Build Coastguard Worker auto getUniformBlockMemberInfo = [&uniformBlockInfo](const std::string &name,
1699*8975f5c5SAndroid Build Coastguard Worker const std::string &mappedName,
1700*8975f5c5SAndroid Build Coastguard Worker sh::BlockMemberInfo *infoOut) {
1701*8975f5c5SAndroid Build Coastguard Worker return uniformBlockInfo.getBlockMemberInfo(name, mappedName, infoOut);
1702*8975f5c5SAndroid Build Coastguard Worker };
1703*8975f5c5SAndroid Build Coastguard Worker
1704*8975f5c5SAndroid Build Coastguard Worker // Link uniform interface blocks.
1705*8975f5c5SAndroid Build Coastguard Worker resources.uniformBlockLinker.linkBlocks(getUniformBlockSize, getUniformBlockMemberInfo);
1706*8975f5c5SAndroid Build Coastguard Worker
1707*8975f5c5SAndroid Build Coastguard Worker // Gather storage buffer interface block info.
1708*8975f5c5SAndroid Build Coastguard Worker InterfaceBlockInfo shaderStorageBlockInfo(mCustomEncoderFactory);
1709*8975f5c5SAndroid Build Coastguard Worker for (const ShaderType shaderType : AllShaderTypes())
1710*8975f5c5SAndroid Build Coastguard Worker {
1711*8975f5c5SAndroid Build Coastguard Worker const SharedCompiledShaderState &shader = programState.getAttachedShader(shaderType);
1712*8975f5c5SAndroid Build Coastguard Worker if (shader)
1713*8975f5c5SAndroid Build Coastguard Worker {
1714*8975f5c5SAndroid Build Coastguard Worker shaderStorageBlockInfo.getShaderBlockInfo(shader->shaderStorageBlocks);
1715*8975f5c5SAndroid Build Coastguard Worker }
1716*8975f5c5SAndroid Build Coastguard Worker }
1717*8975f5c5SAndroid Build Coastguard Worker auto getShaderStorageBlockSize = [&shaderStorageBlockInfo](const std::string &name,
1718*8975f5c5SAndroid Build Coastguard Worker const std::string &mappedName,
1719*8975f5c5SAndroid Build Coastguard Worker size_t *sizeOut) {
1720*8975f5c5SAndroid Build Coastguard Worker return shaderStorageBlockInfo.getBlockSize(name, mappedName, sizeOut);
1721*8975f5c5SAndroid Build Coastguard Worker };
1722*8975f5c5SAndroid Build Coastguard Worker
1723*8975f5c5SAndroid Build Coastguard Worker auto getShaderStorageBlockMemberInfo = [&shaderStorageBlockInfo](const std::string &name,
1724*8975f5c5SAndroid Build Coastguard Worker const std::string &mappedName,
1725*8975f5c5SAndroid Build Coastguard Worker sh::BlockMemberInfo *infoOut) {
1726*8975f5c5SAndroid Build Coastguard Worker return shaderStorageBlockInfo.getBlockMemberInfo(name, mappedName, infoOut);
1727*8975f5c5SAndroid Build Coastguard Worker };
1728*8975f5c5SAndroid Build Coastguard Worker
1729*8975f5c5SAndroid Build Coastguard Worker // Link storage buffer interface blocks.
1730*8975f5c5SAndroid Build Coastguard Worker resources.shaderStorageBlockLinker.linkBlocks(getShaderStorageBlockSize,
1731*8975f5c5SAndroid Build Coastguard Worker getShaderStorageBlockMemberInfo);
1732*8975f5c5SAndroid Build Coastguard Worker
1733*8975f5c5SAndroid Build Coastguard Worker // Gather and link atomic counter buffer interface blocks.
1734*8975f5c5SAndroid Build Coastguard Worker std::map<int, unsigned int> sizeMap;
1735*8975f5c5SAndroid Build Coastguard Worker getAtomicCounterBufferSizeMap(programState.getExecutable(), sizeMap);
1736*8975f5c5SAndroid Build Coastguard Worker resources.atomicCounterBufferLinker.link(sizeMap);
1737*8975f5c5SAndroid Build Coastguard Worker
1738*8975f5c5SAndroid Build Coastguard Worker const gl::SharedCompiledShaderState &fragmentShader =
1739*8975f5c5SAndroid Build Coastguard Worker programState.getAttachedShader(gl::ShaderType::Fragment);
1740*8975f5c5SAndroid Build Coastguard Worker if (fragmentShader != nullptr)
1741*8975f5c5SAndroid Build Coastguard Worker {
1742*8975f5c5SAndroid Build Coastguard Worker resources.pixelLocalStorageLinker.link(fragmentShader->pixelLocalStorageFormats);
1743*8975f5c5SAndroid Build Coastguard Worker }
1744*8975f5c5SAndroid Build Coastguard Worker }
1745*8975f5c5SAndroid Build Coastguard Worker
getAtomicCounterBufferSizeMap(const ProgramExecutable & executable,std::map<int,unsigned int> & sizeMapOut) const1746*8975f5c5SAndroid Build Coastguard Worker void ProgramLinkedResourcesLinker::getAtomicCounterBufferSizeMap(
1747*8975f5c5SAndroid Build Coastguard Worker const ProgramExecutable &executable,
1748*8975f5c5SAndroid Build Coastguard Worker std::map<int, unsigned int> &sizeMapOut) const
1749*8975f5c5SAndroid Build Coastguard Worker {
1750*8975f5c5SAndroid Build Coastguard Worker for (unsigned int index : executable.getAtomicCounterUniformRange())
1751*8975f5c5SAndroid Build Coastguard Worker {
1752*8975f5c5SAndroid Build Coastguard Worker const LinkedUniform &glUniform = executable.getUniforms()[index];
1753*8975f5c5SAndroid Build Coastguard Worker
1754*8975f5c5SAndroid Build Coastguard Worker auto &bufferDataSize = sizeMapOut[glUniform.getBinding()];
1755*8975f5c5SAndroid Build Coastguard Worker
1756*8975f5c5SAndroid Build Coastguard Worker // Calculate the size of the buffer by finding the end of the last uniform with the same
1757*8975f5c5SAndroid Build Coastguard Worker // binding. The end of the uniform is calculated by finding the initial offset of the
1758*8975f5c5SAndroid Build Coastguard Worker // uniform and adding size of the uniform. For arrays, the size is the number of elements
1759*8975f5c5SAndroid Build Coastguard Worker // times the element size (should always by 4 for atomic_units).
1760*8975f5c5SAndroid Build Coastguard Worker unsigned dataOffset =
1761*8975f5c5SAndroid Build Coastguard Worker glUniform.getOffset() + static_cast<unsigned int>(glUniform.getBasicTypeElementCount() *
1762*8975f5c5SAndroid Build Coastguard Worker glUniform.getElementSize());
1763*8975f5c5SAndroid Build Coastguard Worker if (dataOffset > bufferDataSize)
1764*8975f5c5SAndroid Build Coastguard Worker {
1765*8975f5c5SAndroid Build Coastguard Worker bufferDataSize = dataOffset;
1766*8975f5c5SAndroid Build Coastguard Worker }
1767*8975f5c5SAndroid Build Coastguard Worker }
1768*8975f5c5SAndroid Build Coastguard Worker }
1769*8975f5c5SAndroid Build Coastguard Worker
LinkValidateProgramGlobalNames(InfoLog & infoLog,const ProgramExecutable & executable,const LinkingVariables & linkingVariables)1770*8975f5c5SAndroid Build Coastguard Worker bool LinkValidateProgramGlobalNames(InfoLog &infoLog,
1771*8975f5c5SAndroid Build Coastguard Worker const ProgramExecutable &executable,
1772*8975f5c5SAndroid Build Coastguard Worker const LinkingVariables &linkingVariables)
1773*8975f5c5SAndroid Build Coastguard Worker {
1774*8975f5c5SAndroid Build Coastguard Worker angle::HashMap<std::string, const sh::ShaderVariable *> uniformMap;
1775*8975f5c5SAndroid Build Coastguard Worker using BlockAndFieldPair = std::pair<const sh::InterfaceBlock *, const sh::ShaderVariable *>;
1776*8975f5c5SAndroid Build Coastguard Worker angle::HashMap<std::string, std::vector<BlockAndFieldPair>> uniformBlockFieldMap;
1777*8975f5c5SAndroid Build Coastguard Worker
1778*8975f5c5SAndroid Build Coastguard Worker for (ShaderType shaderType : kAllGraphicsShaderTypes)
1779*8975f5c5SAndroid Build Coastguard Worker {
1780*8975f5c5SAndroid Build Coastguard Worker if (!linkingVariables.isShaderStageUsedBitset[shaderType])
1781*8975f5c5SAndroid Build Coastguard Worker {
1782*8975f5c5SAndroid Build Coastguard Worker continue;
1783*8975f5c5SAndroid Build Coastguard Worker }
1784*8975f5c5SAndroid Build Coastguard Worker
1785*8975f5c5SAndroid Build Coastguard Worker // Build a map of Uniforms
1786*8975f5c5SAndroid Build Coastguard Worker const std::vector<sh::ShaderVariable> &uniforms = linkingVariables.uniforms[shaderType];
1787*8975f5c5SAndroid Build Coastguard Worker for (const auto &uniform : uniforms)
1788*8975f5c5SAndroid Build Coastguard Worker {
1789*8975f5c5SAndroid Build Coastguard Worker uniformMap[uniform.name] = &uniform;
1790*8975f5c5SAndroid Build Coastguard Worker }
1791*8975f5c5SAndroid Build Coastguard Worker
1792*8975f5c5SAndroid Build Coastguard Worker // Build a map of Uniform Blocks
1793*8975f5c5SAndroid Build Coastguard Worker // This will also detect any field name conflicts between Uniform Blocks without instance
1794*8975f5c5SAndroid Build Coastguard Worker // names
1795*8975f5c5SAndroid Build Coastguard Worker const std::vector<sh::InterfaceBlock> &uniformBlocks =
1796*8975f5c5SAndroid Build Coastguard Worker linkingVariables.uniformBlocks[shaderType];
1797*8975f5c5SAndroid Build Coastguard Worker
1798*8975f5c5SAndroid Build Coastguard Worker for (const auto &uniformBlock : uniformBlocks)
1799*8975f5c5SAndroid Build Coastguard Worker {
1800*8975f5c5SAndroid Build Coastguard Worker // Only uniform blocks without an instance name can create a conflict with their field
1801*8975f5c5SAndroid Build Coastguard Worker // names
1802*8975f5c5SAndroid Build Coastguard Worker if (!uniformBlock.instanceName.empty())
1803*8975f5c5SAndroid Build Coastguard Worker {
1804*8975f5c5SAndroid Build Coastguard Worker continue;
1805*8975f5c5SAndroid Build Coastguard Worker }
1806*8975f5c5SAndroid Build Coastguard Worker
1807*8975f5c5SAndroid Build Coastguard Worker for (const auto &field : uniformBlock.fields)
1808*8975f5c5SAndroid Build Coastguard Worker {
1809*8975f5c5SAndroid Build Coastguard Worker if (!uniformBlockFieldMap.count(field.name))
1810*8975f5c5SAndroid Build Coastguard Worker {
1811*8975f5c5SAndroid Build Coastguard Worker // First time we've seen this uniform block field name, so add the
1812*8975f5c5SAndroid Build Coastguard Worker // (Uniform Block, Field) pair immediately since there can't be a conflict yet
1813*8975f5c5SAndroid Build Coastguard Worker BlockAndFieldPair blockAndFieldPair(&uniformBlock, &field);
1814*8975f5c5SAndroid Build Coastguard Worker std::vector<BlockAndFieldPair> newUniformBlockList;
1815*8975f5c5SAndroid Build Coastguard Worker newUniformBlockList.push_back(blockAndFieldPair);
1816*8975f5c5SAndroid Build Coastguard Worker uniformBlockFieldMap[field.name] = newUniformBlockList;
1817*8975f5c5SAndroid Build Coastguard Worker continue;
1818*8975f5c5SAndroid Build Coastguard Worker }
1819*8975f5c5SAndroid Build Coastguard Worker
1820*8975f5c5SAndroid Build Coastguard Worker // We've seen this name before.
1821*8975f5c5SAndroid Build Coastguard Worker // We need to check each of the uniform blocks that contain a field with this name
1822*8975f5c5SAndroid Build Coastguard Worker // to see if there's a conflict or not.
1823*8975f5c5SAndroid Build Coastguard Worker std::vector<BlockAndFieldPair> prevBlockFieldPairs =
1824*8975f5c5SAndroid Build Coastguard Worker uniformBlockFieldMap[field.name];
1825*8975f5c5SAndroid Build Coastguard Worker for (const auto &prevBlockFieldPair : prevBlockFieldPairs)
1826*8975f5c5SAndroid Build Coastguard Worker {
1827*8975f5c5SAndroid Build Coastguard Worker const sh::InterfaceBlock *prevUniformBlock = prevBlockFieldPair.first;
1828*8975f5c5SAndroid Build Coastguard Worker const sh::ShaderVariable *prevUniformBlockField = prevBlockFieldPair.second;
1829*8975f5c5SAndroid Build Coastguard Worker
1830*8975f5c5SAndroid Build Coastguard Worker if (uniformBlock.isSameInterfaceBlockAtLinkTime(*prevUniformBlock))
1831*8975f5c5SAndroid Build Coastguard Worker {
1832*8975f5c5SAndroid Build Coastguard Worker // The same uniform block should, by definition, contain the same field name
1833*8975f5c5SAndroid Build Coastguard Worker continue;
1834*8975f5c5SAndroid Build Coastguard Worker }
1835*8975f5c5SAndroid Build Coastguard Worker
1836*8975f5c5SAndroid Build Coastguard Worker // The uniform blocks don't match, so check if the necessary field properties
1837*8975f5c5SAndroid Build Coastguard Worker // also match
1838*8975f5c5SAndroid Build Coastguard Worker if ((field.name == prevUniformBlockField->name) &&
1839*8975f5c5SAndroid Build Coastguard Worker (field.type == prevUniformBlockField->type) &&
1840*8975f5c5SAndroid Build Coastguard Worker (field.precision == prevUniformBlockField->precision))
1841*8975f5c5SAndroid Build Coastguard Worker {
1842*8975f5c5SAndroid Build Coastguard Worker infoLog << "Name conflicts between uniform block field names: "
1843*8975f5c5SAndroid Build Coastguard Worker << field.name;
1844*8975f5c5SAndroid Build Coastguard Worker return false;
1845*8975f5c5SAndroid Build Coastguard Worker }
1846*8975f5c5SAndroid Build Coastguard Worker }
1847*8975f5c5SAndroid Build Coastguard Worker
1848*8975f5c5SAndroid Build Coastguard Worker // No conflict, so record this pair
1849*8975f5c5SAndroid Build Coastguard Worker BlockAndFieldPair blockAndFieldPair(&uniformBlock, &field);
1850*8975f5c5SAndroid Build Coastguard Worker uniformBlockFieldMap[field.name].push_back(blockAndFieldPair);
1851*8975f5c5SAndroid Build Coastguard Worker }
1852*8975f5c5SAndroid Build Coastguard Worker }
1853*8975f5c5SAndroid Build Coastguard Worker }
1854*8975f5c5SAndroid Build Coastguard Worker
1855*8975f5c5SAndroid Build Coastguard Worker // Validate no uniform names conflict with attribute names
1856*8975f5c5SAndroid Build Coastguard Worker if (linkingVariables.isShaderStageUsedBitset[ShaderType::Vertex])
1857*8975f5c5SAndroid Build Coastguard Worker {
1858*8975f5c5SAndroid Build Coastguard Worker // ESSL 3.00.6 section 4.3.5:
1859*8975f5c5SAndroid Build Coastguard Worker // If a uniform variable name is declared in one stage (e.g., a vertex shader)
1860*8975f5c5SAndroid Build Coastguard Worker // but not in another (e.g., a fragment shader), then that name is still
1861*8975f5c5SAndroid Build Coastguard Worker // available in the other stage for a different use.
1862*8975f5c5SAndroid Build Coastguard Worker std::unordered_set<std::string> uniforms;
1863*8975f5c5SAndroid Build Coastguard Worker for (const sh::ShaderVariable &uniform : linkingVariables.uniforms[ShaderType::Vertex])
1864*8975f5c5SAndroid Build Coastguard Worker {
1865*8975f5c5SAndroid Build Coastguard Worker uniforms.insert(uniform.name);
1866*8975f5c5SAndroid Build Coastguard Worker }
1867*8975f5c5SAndroid Build Coastguard Worker for (const auto &attrib : executable.getProgramInputs())
1868*8975f5c5SAndroid Build Coastguard Worker {
1869*8975f5c5SAndroid Build Coastguard Worker if (uniforms.count(attrib.name))
1870*8975f5c5SAndroid Build Coastguard Worker {
1871*8975f5c5SAndroid Build Coastguard Worker infoLog << "Name conflicts between a uniform and an attribute: " << attrib.name;
1872*8975f5c5SAndroid Build Coastguard Worker return false;
1873*8975f5c5SAndroid Build Coastguard Worker }
1874*8975f5c5SAndroid Build Coastguard Worker }
1875*8975f5c5SAndroid Build Coastguard Worker }
1876*8975f5c5SAndroid Build Coastguard Worker
1877*8975f5c5SAndroid Build Coastguard Worker // Validate no Uniform Block fields conflict with other Uniforms
1878*8975f5c5SAndroid Build Coastguard Worker for (const auto &uniformBlockField : uniformBlockFieldMap)
1879*8975f5c5SAndroid Build Coastguard Worker {
1880*8975f5c5SAndroid Build Coastguard Worker const std::string &fieldName = uniformBlockField.first;
1881*8975f5c5SAndroid Build Coastguard Worker if (uniformMap.count(fieldName))
1882*8975f5c5SAndroid Build Coastguard Worker {
1883*8975f5c5SAndroid Build Coastguard Worker infoLog << "Name conflicts between a uniform and a uniform block field: " << fieldName;
1884*8975f5c5SAndroid Build Coastguard Worker return false;
1885*8975f5c5SAndroid Build Coastguard Worker }
1886*8975f5c5SAndroid Build Coastguard Worker }
1887*8975f5c5SAndroid Build Coastguard Worker
1888*8975f5c5SAndroid Build Coastguard Worker return true;
1889*8975f5c5SAndroid Build Coastguard Worker }
1890*8975f5c5SAndroid Build Coastguard Worker
1891*8975f5c5SAndroid Build Coastguard Worker // [OpenGL ES 3.2] Chapter 7.4.1 "Shader Interface Matching"
LinkValidateShaderInterfaceMatching(const std::vector<sh::ShaderVariable> & outputVaryings,const std::vector<sh::ShaderVariable> & inputVaryings,ShaderType frontShaderType,ShaderType backShaderType,int frontShaderVersion,int backShaderVersion,bool isSeparable,gl::InfoLog & infoLog)1892*8975f5c5SAndroid Build Coastguard Worker bool LinkValidateShaderInterfaceMatching(const std::vector<sh::ShaderVariable> &outputVaryings,
1893*8975f5c5SAndroid Build Coastguard Worker const std::vector<sh::ShaderVariable> &inputVaryings,
1894*8975f5c5SAndroid Build Coastguard Worker ShaderType frontShaderType,
1895*8975f5c5SAndroid Build Coastguard Worker ShaderType backShaderType,
1896*8975f5c5SAndroid Build Coastguard Worker int frontShaderVersion,
1897*8975f5c5SAndroid Build Coastguard Worker int backShaderVersion,
1898*8975f5c5SAndroid Build Coastguard Worker bool isSeparable,
1899*8975f5c5SAndroid Build Coastguard Worker gl::InfoLog &infoLog)
1900*8975f5c5SAndroid Build Coastguard Worker {
1901*8975f5c5SAndroid Build Coastguard Worker ASSERT(frontShaderVersion == backShaderVersion);
1902*8975f5c5SAndroid Build Coastguard Worker
1903*8975f5c5SAndroid Build Coastguard Worker std::vector<const sh::ShaderVariable *> filteredInputVaryings;
1904*8975f5c5SAndroid Build Coastguard Worker std::vector<const sh::ShaderVariable *> filteredOutputVaryings;
1905*8975f5c5SAndroid Build Coastguard Worker
1906*8975f5c5SAndroid Build Coastguard Worker GetFilteredVaryings(inputVaryings, &filteredInputVaryings);
1907*8975f5c5SAndroid Build Coastguard Worker GetFilteredVaryings(outputVaryings, &filteredOutputVaryings);
1908*8975f5c5SAndroid Build Coastguard Worker
1909*8975f5c5SAndroid Build Coastguard Worker // Separable programs require the number of inputs and outputs match
1910*8975f5c5SAndroid Build Coastguard Worker if (isSeparable && filteredInputVaryings.size() < filteredOutputVaryings.size())
1911*8975f5c5SAndroid Build Coastguard Worker {
1912*8975f5c5SAndroid Build Coastguard Worker infoLog << GetShaderTypeString(backShaderType)
1913*8975f5c5SAndroid Build Coastguard Worker << " does not consume all varyings generated by "
1914*8975f5c5SAndroid Build Coastguard Worker << GetShaderTypeString(frontShaderType);
1915*8975f5c5SAndroid Build Coastguard Worker return false;
1916*8975f5c5SAndroid Build Coastguard Worker }
1917*8975f5c5SAndroid Build Coastguard Worker if (isSeparable && filteredInputVaryings.size() > filteredOutputVaryings.size())
1918*8975f5c5SAndroid Build Coastguard Worker {
1919*8975f5c5SAndroid Build Coastguard Worker infoLog << GetShaderTypeString(frontShaderType)
1920*8975f5c5SAndroid Build Coastguard Worker << " does not generate all varyings consumed by "
1921*8975f5c5SAndroid Build Coastguard Worker << GetShaderTypeString(backShaderType);
1922*8975f5c5SAndroid Build Coastguard Worker return false;
1923*8975f5c5SAndroid Build Coastguard Worker }
1924*8975f5c5SAndroid Build Coastguard Worker
1925*8975f5c5SAndroid Build Coastguard Worker // All inputs must match all outputs
1926*8975f5c5SAndroid Build Coastguard Worker for (const sh::ShaderVariable *input : filteredInputVaryings)
1927*8975f5c5SAndroid Build Coastguard Worker {
1928*8975f5c5SAndroid Build Coastguard Worker bool match = false;
1929*8975f5c5SAndroid Build Coastguard Worker for (const sh::ShaderVariable *output : filteredOutputVaryings)
1930*8975f5c5SAndroid Build Coastguard Worker {
1931*8975f5c5SAndroid Build Coastguard Worker if (DoShaderVariablesMatch(frontShaderVersion, frontShaderType, backShaderType, *input,
1932*8975f5c5SAndroid Build Coastguard Worker *output, isSeparable, infoLog))
1933*8975f5c5SAndroid Build Coastguard Worker {
1934*8975f5c5SAndroid Build Coastguard Worker match = true;
1935*8975f5c5SAndroid Build Coastguard Worker break;
1936*8975f5c5SAndroid Build Coastguard Worker }
1937*8975f5c5SAndroid Build Coastguard Worker }
1938*8975f5c5SAndroid Build Coastguard Worker
1939*8975f5c5SAndroid Build Coastguard Worker // We permit unmatched, unreferenced varyings. Note that this specifically depends on
1940*8975f5c5SAndroid Build Coastguard Worker // whether the input is statically used - a statically used input should fail this test even
1941*8975f5c5SAndroid Build Coastguard Worker // if it is not active. GLSL ES 3.00.6 section 4.3.10.
1942*8975f5c5SAndroid Build Coastguard Worker if (!match && input->staticUse)
1943*8975f5c5SAndroid Build Coastguard Worker {
1944*8975f5c5SAndroid Build Coastguard Worker const std::string &name =
1945*8975f5c5SAndroid Build Coastguard Worker input->isShaderIOBlock ? input->structOrBlockName : input->name;
1946*8975f5c5SAndroid Build Coastguard Worker infoLog << GetShaderTypeString(backShaderType) << " varying " << name
1947*8975f5c5SAndroid Build Coastguard Worker << " does not match any " << GetShaderTypeString(frontShaderType) << " varying";
1948*8975f5c5SAndroid Build Coastguard Worker return false;
1949*8975f5c5SAndroid Build Coastguard Worker }
1950*8975f5c5SAndroid Build Coastguard Worker }
1951*8975f5c5SAndroid Build Coastguard Worker
1952*8975f5c5SAndroid Build Coastguard Worker return true;
1953*8975f5c5SAndroid Build Coastguard Worker }
1954*8975f5c5SAndroid Build Coastguard Worker
LinkValidateProgramVariables(const sh::ShaderVariable & variable1,const sh::ShaderVariable & variable2,bool validatePrecision,bool treatVariable1AsNonArray,bool treatVariable2AsNonArray,std::string * mismatchedStructOrBlockMemberName)1955*8975f5c5SAndroid Build Coastguard Worker LinkMismatchError LinkValidateProgramVariables(const sh::ShaderVariable &variable1,
1956*8975f5c5SAndroid Build Coastguard Worker const sh::ShaderVariable &variable2,
1957*8975f5c5SAndroid Build Coastguard Worker bool validatePrecision,
1958*8975f5c5SAndroid Build Coastguard Worker bool treatVariable1AsNonArray,
1959*8975f5c5SAndroid Build Coastguard Worker bool treatVariable2AsNonArray,
1960*8975f5c5SAndroid Build Coastguard Worker std::string *mismatchedStructOrBlockMemberName)
1961*8975f5c5SAndroid Build Coastguard Worker {
1962*8975f5c5SAndroid Build Coastguard Worker if (variable1.type != variable2.type)
1963*8975f5c5SAndroid Build Coastguard Worker {
1964*8975f5c5SAndroid Build Coastguard Worker return LinkMismatchError::TYPE_MISMATCH;
1965*8975f5c5SAndroid Build Coastguard Worker }
1966*8975f5c5SAndroid Build Coastguard Worker
1967*8975f5c5SAndroid Build Coastguard Worker bool variable1IsArray = variable1.isArray();
1968*8975f5c5SAndroid Build Coastguard Worker bool variable2IsArray = variable2.isArray();
1969*8975f5c5SAndroid Build Coastguard Worker if (treatVariable1AsNonArray)
1970*8975f5c5SAndroid Build Coastguard Worker {
1971*8975f5c5SAndroid Build Coastguard Worker ASSERT(variable1IsArray);
1972*8975f5c5SAndroid Build Coastguard Worker variable1IsArray = false;
1973*8975f5c5SAndroid Build Coastguard Worker }
1974*8975f5c5SAndroid Build Coastguard Worker if (treatVariable2AsNonArray)
1975*8975f5c5SAndroid Build Coastguard Worker {
1976*8975f5c5SAndroid Build Coastguard Worker ASSERT(variable2IsArray);
1977*8975f5c5SAndroid Build Coastguard Worker variable2IsArray = false;
1978*8975f5c5SAndroid Build Coastguard Worker }
1979*8975f5c5SAndroid Build Coastguard Worker // TODO(anglebug.com/42264094): Investigate interactions with arrays-of-arrays.
1980*8975f5c5SAndroid Build Coastguard Worker if (variable1IsArray != variable2IsArray)
1981*8975f5c5SAndroid Build Coastguard Worker {
1982*8975f5c5SAndroid Build Coastguard Worker return LinkMismatchError::ARRAYNESS_MISMATCH;
1983*8975f5c5SAndroid Build Coastguard Worker }
1984*8975f5c5SAndroid Build Coastguard Worker if (!treatVariable1AsNonArray && !treatVariable2AsNonArray &&
1985*8975f5c5SAndroid Build Coastguard Worker variable1.arraySizes != variable2.arraySizes)
1986*8975f5c5SAndroid Build Coastguard Worker {
1987*8975f5c5SAndroid Build Coastguard Worker return LinkMismatchError::ARRAY_SIZE_MISMATCH;
1988*8975f5c5SAndroid Build Coastguard Worker }
1989*8975f5c5SAndroid Build Coastguard Worker if (validatePrecision && variable1.precision != variable2.precision)
1990*8975f5c5SAndroid Build Coastguard Worker {
1991*8975f5c5SAndroid Build Coastguard Worker return LinkMismatchError::PRECISION_MISMATCH;
1992*8975f5c5SAndroid Build Coastguard Worker }
1993*8975f5c5SAndroid Build Coastguard Worker if (!variable1.isShaderIOBlock && !variable2.isShaderIOBlock &&
1994*8975f5c5SAndroid Build Coastguard Worker variable1.structOrBlockName != variable2.structOrBlockName)
1995*8975f5c5SAndroid Build Coastguard Worker {
1996*8975f5c5SAndroid Build Coastguard Worker return LinkMismatchError::STRUCT_NAME_MISMATCH;
1997*8975f5c5SAndroid Build Coastguard Worker }
1998*8975f5c5SAndroid Build Coastguard Worker if (variable1.imageUnitFormat != variable2.imageUnitFormat)
1999*8975f5c5SAndroid Build Coastguard Worker {
2000*8975f5c5SAndroid Build Coastguard Worker return LinkMismatchError::FORMAT_MISMATCH;
2001*8975f5c5SAndroid Build Coastguard Worker }
2002*8975f5c5SAndroid Build Coastguard Worker
2003*8975f5c5SAndroid Build Coastguard Worker if (variable1.fields.size() != variable2.fields.size())
2004*8975f5c5SAndroid Build Coastguard Worker {
2005*8975f5c5SAndroid Build Coastguard Worker return LinkMismatchError::FIELD_NUMBER_MISMATCH;
2006*8975f5c5SAndroid Build Coastguard Worker }
2007*8975f5c5SAndroid Build Coastguard Worker const unsigned int numMembers = static_cast<unsigned int>(variable1.fields.size());
2008*8975f5c5SAndroid Build Coastguard Worker for (unsigned int memberIndex = 0; memberIndex < numMembers; memberIndex++)
2009*8975f5c5SAndroid Build Coastguard Worker {
2010*8975f5c5SAndroid Build Coastguard Worker const sh::ShaderVariable &member1 = variable1.fields[memberIndex];
2011*8975f5c5SAndroid Build Coastguard Worker const sh::ShaderVariable &member2 = variable2.fields[memberIndex];
2012*8975f5c5SAndroid Build Coastguard Worker
2013*8975f5c5SAndroid Build Coastguard Worker if (member1.name != member2.name)
2014*8975f5c5SAndroid Build Coastguard Worker {
2015*8975f5c5SAndroid Build Coastguard Worker return LinkMismatchError::FIELD_NAME_MISMATCH;
2016*8975f5c5SAndroid Build Coastguard Worker }
2017*8975f5c5SAndroid Build Coastguard Worker
2018*8975f5c5SAndroid Build Coastguard Worker if (member1.interpolation != member2.interpolation)
2019*8975f5c5SAndroid Build Coastguard Worker {
2020*8975f5c5SAndroid Build Coastguard Worker return LinkMismatchError::INTERPOLATION_TYPE_MISMATCH;
2021*8975f5c5SAndroid Build Coastguard Worker }
2022*8975f5c5SAndroid Build Coastguard Worker
2023*8975f5c5SAndroid Build Coastguard Worker if (variable1.isShaderIOBlock && variable2.isShaderIOBlock)
2024*8975f5c5SAndroid Build Coastguard Worker {
2025*8975f5c5SAndroid Build Coastguard Worker if (member1.location != member2.location)
2026*8975f5c5SAndroid Build Coastguard Worker {
2027*8975f5c5SAndroid Build Coastguard Worker return LinkMismatchError::FIELD_LOCATION_MISMATCH;
2028*8975f5c5SAndroid Build Coastguard Worker }
2029*8975f5c5SAndroid Build Coastguard Worker
2030*8975f5c5SAndroid Build Coastguard Worker if (member1.structOrBlockName != member2.structOrBlockName)
2031*8975f5c5SAndroid Build Coastguard Worker {
2032*8975f5c5SAndroid Build Coastguard Worker return LinkMismatchError::FIELD_STRUCT_NAME_MISMATCH;
2033*8975f5c5SAndroid Build Coastguard Worker }
2034*8975f5c5SAndroid Build Coastguard Worker }
2035*8975f5c5SAndroid Build Coastguard Worker
2036*8975f5c5SAndroid Build Coastguard Worker LinkMismatchError linkErrorOnField = LinkValidateProgramVariables(
2037*8975f5c5SAndroid Build Coastguard Worker member1, member2, validatePrecision, false, false, mismatchedStructOrBlockMemberName);
2038*8975f5c5SAndroid Build Coastguard Worker if (linkErrorOnField != LinkMismatchError::NO_MISMATCH)
2039*8975f5c5SAndroid Build Coastguard Worker {
2040*8975f5c5SAndroid Build Coastguard Worker AddProgramVariableParentPrefix(member1.name, mismatchedStructOrBlockMemberName);
2041*8975f5c5SAndroid Build Coastguard Worker return linkErrorOnField;
2042*8975f5c5SAndroid Build Coastguard Worker }
2043*8975f5c5SAndroid Build Coastguard Worker }
2044*8975f5c5SAndroid Build Coastguard Worker
2045*8975f5c5SAndroid Build Coastguard Worker return LinkMismatchError::NO_MISMATCH;
2046*8975f5c5SAndroid Build Coastguard Worker }
2047*8975f5c5SAndroid Build Coastguard Worker
AddProgramVariableParentPrefix(const std::string & parentName,std::string * mismatchedFieldName)2048*8975f5c5SAndroid Build Coastguard Worker void AddProgramVariableParentPrefix(const std::string &parentName, std::string *mismatchedFieldName)
2049*8975f5c5SAndroid Build Coastguard Worker {
2050*8975f5c5SAndroid Build Coastguard Worker ASSERT(mismatchedFieldName);
2051*8975f5c5SAndroid Build Coastguard Worker if (mismatchedFieldName->empty())
2052*8975f5c5SAndroid Build Coastguard Worker {
2053*8975f5c5SAndroid Build Coastguard Worker *mismatchedFieldName = parentName;
2054*8975f5c5SAndroid Build Coastguard Worker }
2055*8975f5c5SAndroid Build Coastguard Worker else
2056*8975f5c5SAndroid Build Coastguard Worker {
2057*8975f5c5SAndroid Build Coastguard Worker std::ostringstream stream;
2058*8975f5c5SAndroid Build Coastguard Worker stream << parentName << "." << *mismatchedFieldName;
2059*8975f5c5SAndroid Build Coastguard Worker *mismatchedFieldName = stream.str();
2060*8975f5c5SAndroid Build Coastguard Worker }
2061*8975f5c5SAndroid Build Coastguard Worker }
2062*8975f5c5SAndroid Build Coastguard Worker
LinkValidateBuiltInVaryingsInvariant(const std::vector<sh::ShaderVariable> & vertexVaryings,const std::vector<sh::ShaderVariable> & fragmentVaryings,int vertexShaderVersion,InfoLog & infoLog)2063*8975f5c5SAndroid Build Coastguard Worker bool LinkValidateBuiltInVaryingsInvariant(const std::vector<sh::ShaderVariable> &vertexVaryings,
2064*8975f5c5SAndroid Build Coastguard Worker const std::vector<sh::ShaderVariable> &fragmentVaryings,
2065*8975f5c5SAndroid Build Coastguard Worker int vertexShaderVersion,
2066*8975f5c5SAndroid Build Coastguard Worker InfoLog &infoLog)
2067*8975f5c5SAndroid Build Coastguard Worker {
2068*8975f5c5SAndroid Build Coastguard Worker bool glPositionIsInvariant = false;
2069*8975f5c5SAndroid Build Coastguard Worker bool glPointSizeIsInvariant = false;
2070*8975f5c5SAndroid Build Coastguard Worker bool glFragCoordIsInvariant = false;
2071*8975f5c5SAndroid Build Coastguard Worker bool glPointCoordIsInvariant = false;
2072*8975f5c5SAndroid Build Coastguard Worker
2073*8975f5c5SAndroid Build Coastguard Worker for (const sh::ShaderVariable &varying : vertexVaryings)
2074*8975f5c5SAndroid Build Coastguard Worker {
2075*8975f5c5SAndroid Build Coastguard Worker if (!varying.isBuiltIn())
2076*8975f5c5SAndroid Build Coastguard Worker {
2077*8975f5c5SAndroid Build Coastguard Worker continue;
2078*8975f5c5SAndroid Build Coastguard Worker }
2079*8975f5c5SAndroid Build Coastguard Worker if (varying.name.compare("gl_Position") == 0)
2080*8975f5c5SAndroid Build Coastguard Worker {
2081*8975f5c5SAndroid Build Coastguard Worker glPositionIsInvariant = varying.isInvariant;
2082*8975f5c5SAndroid Build Coastguard Worker }
2083*8975f5c5SAndroid Build Coastguard Worker else if (varying.name.compare("gl_PointSize") == 0)
2084*8975f5c5SAndroid Build Coastguard Worker {
2085*8975f5c5SAndroid Build Coastguard Worker glPointSizeIsInvariant = varying.isInvariant;
2086*8975f5c5SAndroid Build Coastguard Worker }
2087*8975f5c5SAndroid Build Coastguard Worker }
2088*8975f5c5SAndroid Build Coastguard Worker
2089*8975f5c5SAndroid Build Coastguard Worker for (const sh::ShaderVariable &varying : fragmentVaryings)
2090*8975f5c5SAndroid Build Coastguard Worker {
2091*8975f5c5SAndroid Build Coastguard Worker if (!varying.isBuiltIn())
2092*8975f5c5SAndroid Build Coastguard Worker {
2093*8975f5c5SAndroid Build Coastguard Worker continue;
2094*8975f5c5SAndroid Build Coastguard Worker }
2095*8975f5c5SAndroid Build Coastguard Worker if (varying.name.compare("gl_FragCoord") == 0)
2096*8975f5c5SAndroid Build Coastguard Worker {
2097*8975f5c5SAndroid Build Coastguard Worker glFragCoordIsInvariant = varying.isInvariant;
2098*8975f5c5SAndroid Build Coastguard Worker }
2099*8975f5c5SAndroid Build Coastguard Worker else if (varying.name.compare("gl_PointCoord") == 0)
2100*8975f5c5SAndroid Build Coastguard Worker {
2101*8975f5c5SAndroid Build Coastguard Worker glPointCoordIsInvariant = varying.isInvariant;
2102*8975f5c5SAndroid Build Coastguard Worker }
2103*8975f5c5SAndroid Build Coastguard Worker }
2104*8975f5c5SAndroid Build Coastguard Worker
2105*8975f5c5SAndroid Build Coastguard Worker // There is some ambiguity in ESSL 1.00.17 paragraph 4.6.4 interpretation,
2106*8975f5c5SAndroid Build Coastguard Worker // for example, https://cvs.khronos.org/bugzilla/show_bug.cgi?id=13842.
2107*8975f5c5SAndroid Build Coastguard Worker // Not requiring invariance to match is supported by:
2108*8975f5c5SAndroid Build Coastguard Worker // dEQP, WebGL CTS, Nexus 5X GLES
2109*8975f5c5SAndroid Build Coastguard Worker if (glFragCoordIsInvariant && !glPositionIsInvariant)
2110*8975f5c5SAndroid Build Coastguard Worker {
2111*8975f5c5SAndroid Build Coastguard Worker infoLog << "gl_FragCoord can only be declared invariant if and only if gl_Position is "
2112*8975f5c5SAndroid Build Coastguard Worker "declared invariant.";
2113*8975f5c5SAndroid Build Coastguard Worker return false;
2114*8975f5c5SAndroid Build Coastguard Worker }
2115*8975f5c5SAndroid Build Coastguard Worker if (glPointCoordIsInvariant && !glPointSizeIsInvariant)
2116*8975f5c5SAndroid Build Coastguard Worker {
2117*8975f5c5SAndroid Build Coastguard Worker infoLog << "gl_PointCoord can only be declared invariant if and only if gl_PointSize is "
2118*8975f5c5SAndroid Build Coastguard Worker "declared invariant.";
2119*8975f5c5SAndroid Build Coastguard Worker return false;
2120*8975f5c5SAndroid Build Coastguard Worker }
2121*8975f5c5SAndroid Build Coastguard Worker
2122*8975f5c5SAndroid Build Coastguard Worker return true;
2123*8975f5c5SAndroid Build Coastguard Worker }
2124*8975f5c5SAndroid Build Coastguard Worker
LinkValidateBuiltInVaryings(const std::vector<sh::ShaderVariable> & outputVaryings,const std::vector<sh::ShaderVariable> & inputVaryings,ShaderType outputShaderType,ShaderType inputShaderType,int outputShaderVersion,int inputShaderVersion,InfoLog & infoLog)2125*8975f5c5SAndroid Build Coastguard Worker bool LinkValidateBuiltInVaryings(const std::vector<sh::ShaderVariable> &outputVaryings,
2126*8975f5c5SAndroid Build Coastguard Worker const std::vector<sh::ShaderVariable> &inputVaryings,
2127*8975f5c5SAndroid Build Coastguard Worker ShaderType outputShaderType,
2128*8975f5c5SAndroid Build Coastguard Worker ShaderType inputShaderType,
2129*8975f5c5SAndroid Build Coastguard Worker int outputShaderVersion,
2130*8975f5c5SAndroid Build Coastguard Worker int inputShaderVersion,
2131*8975f5c5SAndroid Build Coastguard Worker InfoLog &infoLog)
2132*8975f5c5SAndroid Build Coastguard Worker {
2133*8975f5c5SAndroid Build Coastguard Worker ASSERT(outputShaderVersion == inputShaderVersion);
2134*8975f5c5SAndroid Build Coastguard Worker
2135*8975f5c5SAndroid Build Coastguard Worker // Only ESSL 1.0 has restrictions on matching input and output invariance
2136*8975f5c5SAndroid Build Coastguard Worker if (inputShaderVersion == 100 && outputShaderType == ShaderType::Vertex &&
2137*8975f5c5SAndroid Build Coastguard Worker inputShaderType == ShaderType::Fragment)
2138*8975f5c5SAndroid Build Coastguard Worker {
2139*8975f5c5SAndroid Build Coastguard Worker return LinkValidateBuiltInVaryingsInvariant(outputVaryings, inputVaryings,
2140*8975f5c5SAndroid Build Coastguard Worker outputShaderVersion, infoLog);
2141*8975f5c5SAndroid Build Coastguard Worker }
2142*8975f5c5SAndroid Build Coastguard Worker
2143*8975f5c5SAndroid Build Coastguard Worker uint32_t sizeClipDistance = 0;
2144*8975f5c5SAndroid Build Coastguard Worker uint32_t sizeCullDistance = 0;
2145*8975f5c5SAndroid Build Coastguard Worker
2146*8975f5c5SAndroid Build Coastguard Worker for (const sh::ShaderVariable &varying : outputVaryings)
2147*8975f5c5SAndroid Build Coastguard Worker {
2148*8975f5c5SAndroid Build Coastguard Worker if (!varying.isBuiltIn())
2149*8975f5c5SAndroid Build Coastguard Worker {
2150*8975f5c5SAndroid Build Coastguard Worker continue;
2151*8975f5c5SAndroid Build Coastguard Worker }
2152*8975f5c5SAndroid Build Coastguard Worker if (varying.name.compare("gl_ClipDistance") == 0)
2153*8975f5c5SAndroid Build Coastguard Worker {
2154*8975f5c5SAndroid Build Coastguard Worker sizeClipDistance = varying.getOutermostArraySize();
2155*8975f5c5SAndroid Build Coastguard Worker }
2156*8975f5c5SAndroid Build Coastguard Worker else if (varying.name.compare("gl_CullDistance") == 0)
2157*8975f5c5SAndroid Build Coastguard Worker {
2158*8975f5c5SAndroid Build Coastguard Worker sizeCullDistance = varying.getOutermostArraySize();
2159*8975f5c5SAndroid Build Coastguard Worker }
2160*8975f5c5SAndroid Build Coastguard Worker }
2161*8975f5c5SAndroid Build Coastguard Worker
2162*8975f5c5SAndroid Build Coastguard Worker for (const sh::ShaderVariable &varying : inputVaryings)
2163*8975f5c5SAndroid Build Coastguard Worker {
2164*8975f5c5SAndroid Build Coastguard Worker if (!varying.isBuiltIn())
2165*8975f5c5SAndroid Build Coastguard Worker {
2166*8975f5c5SAndroid Build Coastguard Worker continue;
2167*8975f5c5SAndroid Build Coastguard Worker }
2168*8975f5c5SAndroid Build Coastguard Worker if (varying.name.compare("gl_ClipDistance") == 0)
2169*8975f5c5SAndroid Build Coastguard Worker {
2170*8975f5c5SAndroid Build Coastguard Worker if (sizeClipDistance != varying.getOutermostArraySize())
2171*8975f5c5SAndroid Build Coastguard Worker {
2172*8975f5c5SAndroid Build Coastguard Worker infoLog
2173*8975f5c5SAndroid Build Coastguard Worker << "If a fragment shader statically uses the gl_ClipDistance built-in array, "
2174*8975f5c5SAndroid Build Coastguard Worker "the array must have the same size as in the previous shader stage. "
2175*8975f5c5SAndroid Build Coastguard Worker << "Output size " << sizeClipDistance << ", input size "
2176*8975f5c5SAndroid Build Coastguard Worker << varying.getOutermostArraySize() << ".";
2177*8975f5c5SAndroid Build Coastguard Worker return false;
2178*8975f5c5SAndroid Build Coastguard Worker }
2179*8975f5c5SAndroid Build Coastguard Worker }
2180*8975f5c5SAndroid Build Coastguard Worker else if (varying.name.compare("gl_CullDistance") == 0)
2181*8975f5c5SAndroid Build Coastguard Worker {
2182*8975f5c5SAndroid Build Coastguard Worker if (sizeCullDistance != varying.getOutermostArraySize())
2183*8975f5c5SAndroid Build Coastguard Worker {
2184*8975f5c5SAndroid Build Coastguard Worker infoLog
2185*8975f5c5SAndroid Build Coastguard Worker << "If a fragment shader statically uses the gl_ClipDistance built-in array, "
2186*8975f5c5SAndroid Build Coastguard Worker "the array must have the same size as in the previous shader stage. "
2187*8975f5c5SAndroid Build Coastguard Worker << "Output size " << sizeCullDistance << ", input size "
2188*8975f5c5SAndroid Build Coastguard Worker << varying.getOutermostArraySize() << ".";
2189*8975f5c5SAndroid Build Coastguard Worker
2190*8975f5c5SAndroid Build Coastguard Worker return false;
2191*8975f5c5SAndroid Build Coastguard Worker }
2192*8975f5c5SAndroid Build Coastguard Worker }
2193*8975f5c5SAndroid Build Coastguard Worker }
2194*8975f5c5SAndroid Build Coastguard Worker return true;
2195*8975f5c5SAndroid Build Coastguard Worker }
2196*8975f5c5SAndroid Build Coastguard Worker
LogAmbiguousFieldLinkMismatch(InfoLog & infoLog,const std::string & blockName1,const std::string & blockName2,const std::string & fieldName,ShaderType shaderType1,ShaderType shaderType2)2197*8975f5c5SAndroid Build Coastguard Worker void LogAmbiguousFieldLinkMismatch(InfoLog &infoLog,
2198*8975f5c5SAndroid Build Coastguard Worker const std::string &blockName1,
2199*8975f5c5SAndroid Build Coastguard Worker const std::string &blockName2,
2200*8975f5c5SAndroid Build Coastguard Worker const std::string &fieldName,
2201*8975f5c5SAndroid Build Coastguard Worker ShaderType shaderType1,
2202*8975f5c5SAndroid Build Coastguard Worker ShaderType shaderType2)
2203*8975f5c5SAndroid Build Coastguard Worker {
2204*8975f5c5SAndroid Build Coastguard Worker infoLog << "Ambiguous field '" << fieldName << "' in blocks '" << blockName1 << "' ("
2205*8975f5c5SAndroid Build Coastguard Worker << GetShaderTypeString(shaderType1) << " shader) and '" << blockName2 << "' ("
2206*8975f5c5SAndroid Build Coastguard Worker << GetShaderTypeString(shaderType2) << " shader) which don't have instance names.";
2207*8975f5c5SAndroid Build Coastguard Worker }
2208*8975f5c5SAndroid Build Coastguard Worker
ValidateInstancelessGraphicsInterfaceBlocksPerShader(const std::vector<sh::InterfaceBlock> & interfaceBlocks,ShaderType shaderType,InterfaceBlockMap * instancelessBlocksFields,InfoLog & infoLog)2209*8975f5c5SAndroid Build Coastguard Worker bool ValidateInstancelessGraphicsInterfaceBlocksPerShader(
2210*8975f5c5SAndroid Build Coastguard Worker const std::vector<sh::InterfaceBlock> &interfaceBlocks,
2211*8975f5c5SAndroid Build Coastguard Worker ShaderType shaderType,
2212*8975f5c5SAndroid Build Coastguard Worker InterfaceBlockMap *instancelessBlocksFields,
2213*8975f5c5SAndroid Build Coastguard Worker InfoLog &infoLog)
2214*8975f5c5SAndroid Build Coastguard Worker {
2215*8975f5c5SAndroid Build Coastguard Worker ASSERT(instancelessBlocksFields);
2216*8975f5c5SAndroid Build Coastguard Worker
2217*8975f5c5SAndroid Build Coastguard Worker for (const sh::InterfaceBlock &block : interfaceBlocks)
2218*8975f5c5SAndroid Build Coastguard Worker {
2219*8975f5c5SAndroid Build Coastguard Worker if (!block.instanceName.empty())
2220*8975f5c5SAndroid Build Coastguard Worker {
2221*8975f5c5SAndroid Build Coastguard Worker continue;
2222*8975f5c5SAndroid Build Coastguard Worker }
2223*8975f5c5SAndroid Build Coastguard Worker
2224*8975f5c5SAndroid Build Coastguard Worker for (const sh::ShaderVariable &field : block.fields)
2225*8975f5c5SAndroid Build Coastguard Worker {
2226*8975f5c5SAndroid Build Coastguard Worker const auto &entry = instancelessBlocksFields->find(field.name);
2227*8975f5c5SAndroid Build Coastguard Worker if (entry != instancelessBlocksFields->end())
2228*8975f5c5SAndroid Build Coastguard Worker {
2229*8975f5c5SAndroid Build Coastguard Worker const sh::InterfaceBlock &linkedBlock = *(entry->second.second);
2230*8975f5c5SAndroid Build Coastguard Worker if (block.name != linkedBlock.name)
2231*8975f5c5SAndroid Build Coastguard Worker {
2232*8975f5c5SAndroid Build Coastguard Worker LogAmbiguousFieldLinkMismatch(infoLog, block.name, linkedBlock.name, field.name,
2233*8975f5c5SAndroid Build Coastguard Worker entry->second.first, shaderType);
2234*8975f5c5SAndroid Build Coastguard Worker return false;
2235*8975f5c5SAndroid Build Coastguard Worker }
2236*8975f5c5SAndroid Build Coastguard Worker }
2237*8975f5c5SAndroid Build Coastguard Worker else
2238*8975f5c5SAndroid Build Coastguard Worker {
2239*8975f5c5SAndroid Build Coastguard Worker (*instancelessBlocksFields)[field.name] = std::make_pair(shaderType, &block);
2240*8975f5c5SAndroid Build Coastguard Worker }
2241*8975f5c5SAndroid Build Coastguard Worker }
2242*8975f5c5SAndroid Build Coastguard Worker }
2243*8975f5c5SAndroid Build Coastguard Worker
2244*8975f5c5SAndroid Build Coastguard Worker return true;
2245*8975f5c5SAndroid Build Coastguard Worker }
2246*8975f5c5SAndroid Build Coastguard Worker
LinkValidateInterfaceBlockFields(const sh::ShaderVariable & blockField1,const sh::ShaderVariable & blockField2,bool webglCompatibility,std::string * mismatchedBlockFieldName)2247*8975f5c5SAndroid Build Coastguard Worker LinkMismatchError LinkValidateInterfaceBlockFields(const sh::ShaderVariable &blockField1,
2248*8975f5c5SAndroid Build Coastguard Worker const sh::ShaderVariable &blockField2,
2249*8975f5c5SAndroid Build Coastguard Worker bool webglCompatibility,
2250*8975f5c5SAndroid Build Coastguard Worker std::string *mismatchedBlockFieldName)
2251*8975f5c5SAndroid Build Coastguard Worker {
2252*8975f5c5SAndroid Build Coastguard Worker if (blockField1.name != blockField2.name)
2253*8975f5c5SAndroid Build Coastguard Worker {
2254*8975f5c5SAndroid Build Coastguard Worker return LinkMismatchError::FIELD_NAME_MISMATCH;
2255*8975f5c5SAndroid Build Coastguard Worker }
2256*8975f5c5SAndroid Build Coastguard Worker
2257*8975f5c5SAndroid Build Coastguard Worker // If webgl, validate precision of UBO fields, otherwise don't. See Khronos bug 10287.
2258*8975f5c5SAndroid Build Coastguard Worker LinkMismatchError linkError = LinkValidateProgramVariables(
2259*8975f5c5SAndroid Build Coastguard Worker blockField1, blockField2, webglCompatibility, false, false, mismatchedBlockFieldName);
2260*8975f5c5SAndroid Build Coastguard Worker if (linkError != LinkMismatchError::NO_MISMATCH)
2261*8975f5c5SAndroid Build Coastguard Worker {
2262*8975f5c5SAndroid Build Coastguard Worker AddProgramVariableParentPrefix(blockField1.name, mismatchedBlockFieldName);
2263*8975f5c5SAndroid Build Coastguard Worker return linkError;
2264*8975f5c5SAndroid Build Coastguard Worker }
2265*8975f5c5SAndroid Build Coastguard Worker
2266*8975f5c5SAndroid Build Coastguard Worker if (blockField1.isRowMajorLayout != blockField2.isRowMajorLayout)
2267*8975f5c5SAndroid Build Coastguard Worker {
2268*8975f5c5SAndroid Build Coastguard Worker AddProgramVariableParentPrefix(blockField1.name, mismatchedBlockFieldName);
2269*8975f5c5SAndroid Build Coastguard Worker return LinkMismatchError::MATRIX_PACKING_MISMATCH;
2270*8975f5c5SAndroid Build Coastguard Worker }
2271*8975f5c5SAndroid Build Coastguard Worker
2272*8975f5c5SAndroid Build Coastguard Worker return LinkMismatchError::NO_MISMATCH;
2273*8975f5c5SAndroid Build Coastguard Worker }
2274*8975f5c5SAndroid Build Coastguard Worker
AreMatchingInterfaceBlocks(const sh::InterfaceBlock & interfaceBlock1,const sh::InterfaceBlock & interfaceBlock2,bool webglCompatibility,std::string * mismatchedBlockFieldName)2275*8975f5c5SAndroid Build Coastguard Worker LinkMismatchError AreMatchingInterfaceBlocks(const sh::InterfaceBlock &interfaceBlock1,
2276*8975f5c5SAndroid Build Coastguard Worker const sh::InterfaceBlock &interfaceBlock2,
2277*8975f5c5SAndroid Build Coastguard Worker bool webglCompatibility,
2278*8975f5c5SAndroid Build Coastguard Worker std::string *mismatchedBlockFieldName)
2279*8975f5c5SAndroid Build Coastguard Worker {
2280*8975f5c5SAndroid Build Coastguard Worker // validate blocks for the same member types
2281*8975f5c5SAndroid Build Coastguard Worker if (interfaceBlock1.fields.size() != interfaceBlock2.fields.size())
2282*8975f5c5SAndroid Build Coastguard Worker {
2283*8975f5c5SAndroid Build Coastguard Worker return LinkMismatchError::FIELD_NUMBER_MISMATCH;
2284*8975f5c5SAndroid Build Coastguard Worker }
2285*8975f5c5SAndroid Build Coastguard Worker if (interfaceBlock1.arraySize != interfaceBlock2.arraySize)
2286*8975f5c5SAndroid Build Coastguard Worker {
2287*8975f5c5SAndroid Build Coastguard Worker return LinkMismatchError::ARRAY_SIZE_MISMATCH;
2288*8975f5c5SAndroid Build Coastguard Worker }
2289*8975f5c5SAndroid Build Coastguard Worker if (interfaceBlock1.layout != interfaceBlock2.layout ||
2290*8975f5c5SAndroid Build Coastguard Worker interfaceBlock1.binding != interfaceBlock2.binding)
2291*8975f5c5SAndroid Build Coastguard Worker {
2292*8975f5c5SAndroid Build Coastguard Worker return LinkMismatchError::LAYOUT_QUALIFIER_MISMATCH;
2293*8975f5c5SAndroid Build Coastguard Worker }
2294*8975f5c5SAndroid Build Coastguard Worker if (interfaceBlock1.instanceName.empty() != interfaceBlock2.instanceName.empty())
2295*8975f5c5SAndroid Build Coastguard Worker {
2296*8975f5c5SAndroid Build Coastguard Worker return LinkMismatchError::INSTANCE_NAME_MISMATCH;
2297*8975f5c5SAndroid Build Coastguard Worker }
2298*8975f5c5SAndroid Build Coastguard Worker const unsigned int numBlockMembers = static_cast<unsigned int>(interfaceBlock1.fields.size());
2299*8975f5c5SAndroid Build Coastguard Worker for (unsigned int blockMemberIndex = 0; blockMemberIndex < numBlockMembers; blockMemberIndex++)
2300*8975f5c5SAndroid Build Coastguard Worker {
2301*8975f5c5SAndroid Build Coastguard Worker const sh::ShaderVariable &member1 = interfaceBlock1.fields[blockMemberIndex];
2302*8975f5c5SAndroid Build Coastguard Worker const sh::ShaderVariable &member2 = interfaceBlock2.fields[blockMemberIndex];
2303*8975f5c5SAndroid Build Coastguard Worker
2304*8975f5c5SAndroid Build Coastguard Worker LinkMismatchError linkError = LinkValidateInterfaceBlockFields(
2305*8975f5c5SAndroid Build Coastguard Worker member1, member2, webglCompatibility, mismatchedBlockFieldName);
2306*8975f5c5SAndroid Build Coastguard Worker if (linkError != LinkMismatchError::NO_MISMATCH)
2307*8975f5c5SAndroid Build Coastguard Worker {
2308*8975f5c5SAndroid Build Coastguard Worker return linkError;
2309*8975f5c5SAndroid Build Coastguard Worker }
2310*8975f5c5SAndroid Build Coastguard Worker }
2311*8975f5c5SAndroid Build Coastguard Worker return LinkMismatchError::NO_MISMATCH;
2312*8975f5c5SAndroid Build Coastguard Worker }
2313*8975f5c5SAndroid Build Coastguard Worker
InitializeInterfaceBlockMap(const std::vector<sh::InterfaceBlock> & interfaceBlocks,ShaderType shaderType,InterfaceBlockMap * linkedInterfaceBlocks)2314*8975f5c5SAndroid Build Coastguard Worker void InitializeInterfaceBlockMap(const std::vector<sh::InterfaceBlock> &interfaceBlocks,
2315*8975f5c5SAndroid Build Coastguard Worker ShaderType shaderType,
2316*8975f5c5SAndroid Build Coastguard Worker InterfaceBlockMap *linkedInterfaceBlocks)
2317*8975f5c5SAndroid Build Coastguard Worker {
2318*8975f5c5SAndroid Build Coastguard Worker ASSERT(linkedInterfaceBlocks);
2319*8975f5c5SAndroid Build Coastguard Worker
2320*8975f5c5SAndroid Build Coastguard Worker for (const sh::InterfaceBlock &interfaceBlock : interfaceBlocks)
2321*8975f5c5SAndroid Build Coastguard Worker {
2322*8975f5c5SAndroid Build Coastguard Worker (*linkedInterfaceBlocks)[interfaceBlock.name] = std::make_pair(shaderType, &interfaceBlock);
2323*8975f5c5SAndroid Build Coastguard Worker }
2324*8975f5c5SAndroid Build Coastguard Worker }
2325*8975f5c5SAndroid Build Coastguard Worker
ValidateGraphicsInterfaceBlocksPerShader(const std::vector<sh::InterfaceBlock> & interfaceBlocksToLink,ShaderType shaderType,bool webglCompatibility,InterfaceBlockMap * linkedBlocks,InfoLog & infoLog)2326*8975f5c5SAndroid Build Coastguard Worker bool ValidateGraphicsInterfaceBlocksPerShader(
2327*8975f5c5SAndroid Build Coastguard Worker const std::vector<sh::InterfaceBlock> &interfaceBlocksToLink,
2328*8975f5c5SAndroid Build Coastguard Worker ShaderType shaderType,
2329*8975f5c5SAndroid Build Coastguard Worker bool webglCompatibility,
2330*8975f5c5SAndroid Build Coastguard Worker InterfaceBlockMap *linkedBlocks,
2331*8975f5c5SAndroid Build Coastguard Worker InfoLog &infoLog)
2332*8975f5c5SAndroid Build Coastguard Worker {
2333*8975f5c5SAndroid Build Coastguard Worker ASSERT(linkedBlocks);
2334*8975f5c5SAndroid Build Coastguard Worker
2335*8975f5c5SAndroid Build Coastguard Worker for (const sh::InterfaceBlock &block : interfaceBlocksToLink)
2336*8975f5c5SAndroid Build Coastguard Worker {
2337*8975f5c5SAndroid Build Coastguard Worker const auto &entry = linkedBlocks->find(block.name);
2338*8975f5c5SAndroid Build Coastguard Worker if (entry != linkedBlocks->end())
2339*8975f5c5SAndroid Build Coastguard Worker {
2340*8975f5c5SAndroid Build Coastguard Worker const sh::InterfaceBlock &linkedBlock = *(entry->second.second);
2341*8975f5c5SAndroid Build Coastguard Worker std::string mismatchedStructFieldName;
2342*8975f5c5SAndroid Build Coastguard Worker LinkMismatchError linkError = AreMatchingInterfaceBlocks(
2343*8975f5c5SAndroid Build Coastguard Worker block, linkedBlock, webglCompatibility, &mismatchedStructFieldName);
2344*8975f5c5SAndroid Build Coastguard Worker if (linkError != LinkMismatchError::NO_MISMATCH)
2345*8975f5c5SAndroid Build Coastguard Worker {
2346*8975f5c5SAndroid Build Coastguard Worker LogLinkMismatch(infoLog, block.name, GetInterfaceBlockTypeString(block.blockType),
2347*8975f5c5SAndroid Build Coastguard Worker linkError, mismatchedStructFieldName, entry->second.first,
2348*8975f5c5SAndroid Build Coastguard Worker shaderType);
2349*8975f5c5SAndroid Build Coastguard Worker return false;
2350*8975f5c5SAndroid Build Coastguard Worker }
2351*8975f5c5SAndroid Build Coastguard Worker }
2352*8975f5c5SAndroid Build Coastguard Worker else
2353*8975f5c5SAndroid Build Coastguard Worker {
2354*8975f5c5SAndroid Build Coastguard Worker (*linkedBlocks)[block.name] = std::make_pair(shaderType, &block);
2355*8975f5c5SAndroid Build Coastguard Worker }
2356*8975f5c5SAndroid Build Coastguard Worker }
2357*8975f5c5SAndroid Build Coastguard Worker
2358*8975f5c5SAndroid Build Coastguard Worker return true;
2359*8975f5c5SAndroid Build Coastguard Worker }
2360*8975f5c5SAndroid Build Coastguard Worker
ValidateInterfaceBlocksMatch(GLuint numShadersHasInterfaceBlocks,const ShaderMap<const std::vector<sh::InterfaceBlock> * > & shaderInterfaceBlocks,InfoLog & infoLog,bool webglCompatibility,InterfaceBlockMap * instancelessInterfaceBlocksFields)2361*8975f5c5SAndroid Build Coastguard Worker bool ValidateInterfaceBlocksMatch(
2362*8975f5c5SAndroid Build Coastguard Worker GLuint numShadersHasInterfaceBlocks,
2363*8975f5c5SAndroid Build Coastguard Worker const ShaderMap<const std::vector<sh::InterfaceBlock> *> &shaderInterfaceBlocks,
2364*8975f5c5SAndroid Build Coastguard Worker InfoLog &infoLog,
2365*8975f5c5SAndroid Build Coastguard Worker bool webglCompatibility,
2366*8975f5c5SAndroid Build Coastguard Worker InterfaceBlockMap *instancelessInterfaceBlocksFields)
2367*8975f5c5SAndroid Build Coastguard Worker {
2368*8975f5c5SAndroid Build Coastguard Worker for (ShaderType shaderType : kAllGraphicsShaderTypes)
2369*8975f5c5SAndroid Build Coastguard Worker {
2370*8975f5c5SAndroid Build Coastguard Worker // Validate that instanceless blocks of different names don't have fields of the same name.
2371*8975f5c5SAndroid Build Coastguard Worker if (shaderInterfaceBlocks[shaderType] &&
2372*8975f5c5SAndroid Build Coastguard Worker !ValidateInstancelessGraphicsInterfaceBlocksPerShader(
2373*8975f5c5SAndroid Build Coastguard Worker *shaderInterfaceBlocks[shaderType], shaderType, instancelessInterfaceBlocksFields,
2374*8975f5c5SAndroid Build Coastguard Worker infoLog))
2375*8975f5c5SAndroid Build Coastguard Worker {
2376*8975f5c5SAndroid Build Coastguard Worker return false;
2377*8975f5c5SAndroid Build Coastguard Worker }
2378*8975f5c5SAndroid Build Coastguard Worker }
2379*8975f5c5SAndroid Build Coastguard Worker
2380*8975f5c5SAndroid Build Coastguard Worker if (numShadersHasInterfaceBlocks < 2u)
2381*8975f5c5SAndroid Build Coastguard Worker {
2382*8975f5c5SAndroid Build Coastguard Worker return true;
2383*8975f5c5SAndroid Build Coastguard Worker }
2384*8975f5c5SAndroid Build Coastguard Worker
2385*8975f5c5SAndroid Build Coastguard Worker ASSERT(!shaderInterfaceBlocks[ShaderType::Compute]);
2386*8975f5c5SAndroid Build Coastguard Worker
2387*8975f5c5SAndroid Build Coastguard Worker // Check that interface blocks defined in the graphics shaders are identical
2388*8975f5c5SAndroid Build Coastguard Worker
2389*8975f5c5SAndroid Build Coastguard Worker InterfaceBlockMap linkedInterfaceBlocks;
2390*8975f5c5SAndroid Build Coastguard Worker
2391*8975f5c5SAndroid Build Coastguard Worker bool interfaceBlockMapInitialized = false;
2392*8975f5c5SAndroid Build Coastguard Worker for (ShaderType shaderType : kAllGraphicsShaderTypes)
2393*8975f5c5SAndroid Build Coastguard Worker {
2394*8975f5c5SAndroid Build Coastguard Worker if (!shaderInterfaceBlocks[shaderType])
2395*8975f5c5SAndroid Build Coastguard Worker {
2396*8975f5c5SAndroid Build Coastguard Worker continue;
2397*8975f5c5SAndroid Build Coastguard Worker }
2398*8975f5c5SAndroid Build Coastguard Worker
2399*8975f5c5SAndroid Build Coastguard Worker if (!interfaceBlockMapInitialized)
2400*8975f5c5SAndroid Build Coastguard Worker {
2401*8975f5c5SAndroid Build Coastguard Worker InitializeInterfaceBlockMap(*shaderInterfaceBlocks[shaderType], shaderType,
2402*8975f5c5SAndroid Build Coastguard Worker &linkedInterfaceBlocks);
2403*8975f5c5SAndroid Build Coastguard Worker interfaceBlockMapInitialized = true;
2404*8975f5c5SAndroid Build Coastguard Worker }
2405*8975f5c5SAndroid Build Coastguard Worker else if (!ValidateGraphicsInterfaceBlocksPerShader(*shaderInterfaceBlocks[shaderType],
2406*8975f5c5SAndroid Build Coastguard Worker shaderType, webglCompatibility,
2407*8975f5c5SAndroid Build Coastguard Worker &linkedInterfaceBlocks, infoLog))
2408*8975f5c5SAndroid Build Coastguard Worker {
2409*8975f5c5SAndroid Build Coastguard Worker return false;
2410*8975f5c5SAndroid Build Coastguard Worker }
2411*8975f5c5SAndroid Build Coastguard Worker }
2412*8975f5c5SAndroid Build Coastguard Worker
2413*8975f5c5SAndroid Build Coastguard Worker return true;
2414*8975f5c5SAndroid Build Coastguard Worker }
2415*8975f5c5SAndroid Build Coastguard Worker
LinkValidateProgramInterfaceBlocks(const Caps & caps,const Version & clientVersion,bool webglCompatibility,ShaderBitSet activeProgramStages,const ProgramLinkedResources & resources,InfoLog & infoLog,GLuint * combinedShaderStorageBlocksCountOut)2416*8975f5c5SAndroid Build Coastguard Worker bool LinkValidateProgramInterfaceBlocks(const Caps &caps,
2417*8975f5c5SAndroid Build Coastguard Worker const Version &clientVersion,
2418*8975f5c5SAndroid Build Coastguard Worker bool webglCompatibility,
2419*8975f5c5SAndroid Build Coastguard Worker ShaderBitSet activeProgramStages,
2420*8975f5c5SAndroid Build Coastguard Worker const ProgramLinkedResources &resources,
2421*8975f5c5SAndroid Build Coastguard Worker InfoLog &infoLog,
2422*8975f5c5SAndroid Build Coastguard Worker GLuint *combinedShaderStorageBlocksCountOut)
2423*8975f5c5SAndroid Build Coastguard Worker {
2424*8975f5c5SAndroid Build Coastguard Worker ASSERT(combinedShaderStorageBlocksCountOut);
2425*8975f5c5SAndroid Build Coastguard Worker
2426*8975f5c5SAndroid Build Coastguard Worker GLuint combinedUniformBlocksCount = 0u;
2427*8975f5c5SAndroid Build Coastguard Worker GLuint numShadersHasUniformBlocks = 0u;
2428*8975f5c5SAndroid Build Coastguard Worker ShaderMap<const std::vector<sh::InterfaceBlock> *> allShaderUniformBlocks = {};
2429*8975f5c5SAndroid Build Coastguard Worker InterfaceBlockMap instancelessInterfaceBlocksFields;
2430*8975f5c5SAndroid Build Coastguard Worker
2431*8975f5c5SAndroid Build Coastguard Worker for (ShaderType shaderType : activeProgramStages)
2432*8975f5c5SAndroid Build Coastguard Worker {
2433*8975f5c5SAndroid Build Coastguard Worker const std::vector<sh::InterfaceBlock> &uniformBlocks =
2434*8975f5c5SAndroid Build Coastguard Worker resources.uniformBlockLinker.getShaderBlocks(shaderType);
2435*8975f5c5SAndroid Build Coastguard Worker if (!uniformBlocks.empty())
2436*8975f5c5SAndroid Build Coastguard Worker {
2437*8975f5c5SAndroid Build Coastguard Worker if (!ValidateInterfaceBlocksCount(
2438*8975f5c5SAndroid Build Coastguard Worker static_cast<GLuint>(caps.maxShaderUniformBlocks[shaderType]), uniformBlocks,
2439*8975f5c5SAndroid Build Coastguard Worker shaderType, sh::BlockType::kBlockUniform, &combinedUniformBlocksCount, infoLog))
2440*8975f5c5SAndroid Build Coastguard Worker {
2441*8975f5c5SAndroid Build Coastguard Worker return false;
2442*8975f5c5SAndroid Build Coastguard Worker }
2443*8975f5c5SAndroid Build Coastguard Worker
2444*8975f5c5SAndroid Build Coastguard Worker allShaderUniformBlocks[shaderType] = &uniformBlocks;
2445*8975f5c5SAndroid Build Coastguard Worker ++numShadersHasUniformBlocks;
2446*8975f5c5SAndroid Build Coastguard Worker }
2447*8975f5c5SAndroid Build Coastguard Worker }
2448*8975f5c5SAndroid Build Coastguard Worker
2449*8975f5c5SAndroid Build Coastguard Worker if (combinedUniformBlocksCount > static_cast<GLuint>(caps.maxCombinedUniformBlocks))
2450*8975f5c5SAndroid Build Coastguard Worker {
2451*8975f5c5SAndroid Build Coastguard Worker infoLog << "The sum of the number of active uniform blocks exceeds "
2452*8975f5c5SAndroid Build Coastguard Worker "MAX_COMBINED_UNIFORM_BLOCKS ("
2453*8975f5c5SAndroid Build Coastguard Worker << caps.maxCombinedUniformBlocks << ").";
2454*8975f5c5SAndroid Build Coastguard Worker return false;
2455*8975f5c5SAndroid Build Coastguard Worker }
2456*8975f5c5SAndroid Build Coastguard Worker
2457*8975f5c5SAndroid Build Coastguard Worker if (!ValidateInterfaceBlocksMatch(numShadersHasUniformBlocks, allShaderUniformBlocks, infoLog,
2458*8975f5c5SAndroid Build Coastguard Worker webglCompatibility, &instancelessInterfaceBlocksFields))
2459*8975f5c5SAndroid Build Coastguard Worker {
2460*8975f5c5SAndroid Build Coastguard Worker return false;
2461*8975f5c5SAndroid Build Coastguard Worker }
2462*8975f5c5SAndroid Build Coastguard Worker
2463*8975f5c5SAndroid Build Coastguard Worker if (clientVersion >= Version(3, 1))
2464*8975f5c5SAndroid Build Coastguard Worker {
2465*8975f5c5SAndroid Build Coastguard Worker *combinedShaderStorageBlocksCountOut = 0u;
2466*8975f5c5SAndroid Build Coastguard Worker GLuint numShadersHasShaderStorageBlocks = 0u;
2467*8975f5c5SAndroid Build Coastguard Worker ShaderMap<const std::vector<sh::InterfaceBlock> *> allShaderStorageBlocks = {};
2468*8975f5c5SAndroid Build Coastguard Worker for (ShaderType shaderType : activeProgramStages)
2469*8975f5c5SAndroid Build Coastguard Worker {
2470*8975f5c5SAndroid Build Coastguard Worker const std::vector<sh::InterfaceBlock> &shaderStorageBlocks =
2471*8975f5c5SAndroid Build Coastguard Worker resources.shaderStorageBlockLinker.getShaderBlocks(shaderType);
2472*8975f5c5SAndroid Build Coastguard Worker if (!shaderStorageBlocks.empty())
2473*8975f5c5SAndroid Build Coastguard Worker {
2474*8975f5c5SAndroid Build Coastguard Worker if (!ValidateInterfaceBlocksCount(
2475*8975f5c5SAndroid Build Coastguard Worker static_cast<GLuint>(caps.maxShaderStorageBlocks[shaderType]),
2476*8975f5c5SAndroid Build Coastguard Worker shaderStorageBlocks, shaderType, sh::BlockType::kBlockBuffer,
2477*8975f5c5SAndroid Build Coastguard Worker combinedShaderStorageBlocksCountOut, infoLog))
2478*8975f5c5SAndroid Build Coastguard Worker {
2479*8975f5c5SAndroid Build Coastguard Worker return false;
2480*8975f5c5SAndroid Build Coastguard Worker }
2481*8975f5c5SAndroid Build Coastguard Worker
2482*8975f5c5SAndroid Build Coastguard Worker allShaderStorageBlocks[shaderType] = &shaderStorageBlocks;
2483*8975f5c5SAndroid Build Coastguard Worker ++numShadersHasShaderStorageBlocks;
2484*8975f5c5SAndroid Build Coastguard Worker }
2485*8975f5c5SAndroid Build Coastguard Worker }
2486*8975f5c5SAndroid Build Coastguard Worker
2487*8975f5c5SAndroid Build Coastguard Worker if (*combinedShaderStorageBlocksCountOut >
2488*8975f5c5SAndroid Build Coastguard Worker static_cast<GLuint>(caps.maxCombinedShaderStorageBlocks))
2489*8975f5c5SAndroid Build Coastguard Worker {
2490*8975f5c5SAndroid Build Coastguard Worker infoLog << "The sum of the number of active shader storage blocks exceeds "
2491*8975f5c5SAndroid Build Coastguard Worker "MAX_COMBINED_SHADER_STORAGE_BLOCKS ("
2492*8975f5c5SAndroid Build Coastguard Worker << caps.maxCombinedShaderStorageBlocks << ").";
2493*8975f5c5SAndroid Build Coastguard Worker return false;
2494*8975f5c5SAndroid Build Coastguard Worker }
2495*8975f5c5SAndroid Build Coastguard Worker
2496*8975f5c5SAndroid Build Coastguard Worker if (!ValidateInterfaceBlocksMatch(numShadersHasShaderStorageBlocks, allShaderStorageBlocks,
2497*8975f5c5SAndroid Build Coastguard Worker infoLog, webglCompatibility,
2498*8975f5c5SAndroid Build Coastguard Worker &instancelessInterfaceBlocksFields))
2499*8975f5c5SAndroid Build Coastguard Worker {
2500*8975f5c5SAndroid Build Coastguard Worker return false;
2501*8975f5c5SAndroid Build Coastguard Worker }
2502*8975f5c5SAndroid Build Coastguard Worker }
2503*8975f5c5SAndroid Build Coastguard Worker
2504*8975f5c5SAndroid Build Coastguard Worker return true;
2505*8975f5c5SAndroid Build Coastguard Worker }
2506*8975f5c5SAndroid Build Coastguard Worker
2507*8975f5c5SAndroid Build Coastguard Worker } // namespace gl
2508