1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2015 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 // VaryingPacking:
7*8975f5c5SAndroid Build Coastguard Worker // Class which describes a mapping from varyings to registers, according
8*8975f5c5SAndroid Build Coastguard Worker // to the spec, or using custom packing algorithms. We also keep a register
9*8975f5c5SAndroid Build Coastguard Worker // allocation list for the D3D renderer.
10*8975f5c5SAndroid Build Coastguard Worker //
11*8975f5c5SAndroid Build Coastguard Worker
12*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/VaryingPacking.h"
13*8975f5c5SAndroid Build Coastguard Worker
14*8975f5c5SAndroid Build Coastguard Worker #include "common/CompiledShaderState.h"
15*8975f5c5SAndroid Build Coastguard Worker #include "common/utilities.h"
16*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Program.h"
17*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/ProgramExecutable.h"
18*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Shader.h"
19*8975f5c5SAndroid Build Coastguard Worker
20*8975f5c5SAndroid Build Coastguard Worker namespace gl
21*8975f5c5SAndroid Build Coastguard Worker {
22*8975f5c5SAndroid Build Coastguard Worker
23*8975f5c5SAndroid Build Coastguard Worker namespace
24*8975f5c5SAndroid Build Coastguard Worker {
25*8975f5c5SAndroid Build Coastguard Worker // true if varying x has a higher priority in packing than y
ComparePackedVarying(const PackedVarying & x,const PackedVarying & y)26*8975f5c5SAndroid Build Coastguard Worker bool ComparePackedVarying(const PackedVarying &x, const PackedVarying &y)
27*8975f5c5SAndroid Build Coastguard Worker {
28*8975f5c5SAndroid Build Coastguard Worker // If the PackedVarying 'x' or 'y' to be compared is an array element for transform feedback,
29*8975f5c5SAndroid Build Coastguard Worker // this clones an equivalent non-array shader variable 'vx' or 'vy' for actual comparison
30*8975f5c5SAndroid Build Coastguard Worker // instead. For I/O block arrays, the array index is used in the comparison.
31*8975f5c5SAndroid Build Coastguard Worker sh::ShaderVariable vx, vy;
32*8975f5c5SAndroid Build Coastguard Worker const sh::ShaderVariable *px, *py;
33*8975f5c5SAndroid Build Coastguard Worker
34*8975f5c5SAndroid Build Coastguard Worker px = &x.varying();
35*8975f5c5SAndroid Build Coastguard Worker py = &y.varying();
36*8975f5c5SAndroid Build Coastguard Worker
37*8975f5c5SAndroid Build Coastguard Worker if (x.isTransformFeedbackArrayElement())
38*8975f5c5SAndroid Build Coastguard Worker {
39*8975f5c5SAndroid Build Coastguard Worker vx = *px;
40*8975f5c5SAndroid Build Coastguard Worker vx.arraySizes.clear();
41*8975f5c5SAndroid Build Coastguard Worker px = &vx;
42*8975f5c5SAndroid Build Coastguard Worker }
43*8975f5c5SAndroid Build Coastguard Worker
44*8975f5c5SAndroid Build Coastguard Worker if (y.isTransformFeedbackArrayElement())
45*8975f5c5SAndroid Build Coastguard Worker {
46*8975f5c5SAndroid Build Coastguard Worker vy = *py;
47*8975f5c5SAndroid Build Coastguard Worker vy.arraySizes.clear();
48*8975f5c5SAndroid Build Coastguard Worker py = &vy;
49*8975f5c5SAndroid Build Coastguard Worker }
50*8975f5c5SAndroid Build Coastguard Worker
51*8975f5c5SAndroid Build Coastguard Worker // Make sure struct fields end up together.
52*8975f5c5SAndroid Build Coastguard Worker if (x.isStructField() != y.isStructField())
53*8975f5c5SAndroid Build Coastguard Worker {
54*8975f5c5SAndroid Build Coastguard Worker return x.isStructField();
55*8975f5c5SAndroid Build Coastguard Worker }
56*8975f5c5SAndroid Build Coastguard Worker
57*8975f5c5SAndroid Build Coastguard Worker if (x.isStructField())
58*8975f5c5SAndroid Build Coastguard Worker {
59*8975f5c5SAndroid Build Coastguard Worker ASSERT(y.isStructField());
60*8975f5c5SAndroid Build Coastguard Worker
61*8975f5c5SAndroid Build Coastguard Worker if (x.getParentStructName() != y.getParentStructName())
62*8975f5c5SAndroid Build Coastguard Worker {
63*8975f5c5SAndroid Build Coastguard Worker return x.getParentStructName() < y.getParentStructName();
64*8975f5c5SAndroid Build Coastguard Worker }
65*8975f5c5SAndroid Build Coastguard Worker }
66*8975f5c5SAndroid Build Coastguard Worker
67*8975f5c5SAndroid Build Coastguard Worker // For I/O block fields, order first by array index:
68*8975f5c5SAndroid Build Coastguard Worker if (!x.isTransformFeedbackArrayElement() && !y.isTransformFeedbackArrayElement())
69*8975f5c5SAndroid Build Coastguard Worker {
70*8975f5c5SAndroid Build Coastguard Worker if (x.arrayIndex != y.arrayIndex)
71*8975f5c5SAndroid Build Coastguard Worker {
72*8975f5c5SAndroid Build Coastguard Worker return x.arrayIndex < y.arrayIndex;
73*8975f5c5SAndroid Build Coastguard Worker }
74*8975f5c5SAndroid Build Coastguard Worker }
75*8975f5c5SAndroid Build Coastguard Worker
76*8975f5c5SAndroid Build Coastguard Worker // Then order by field index
77*8975f5c5SAndroid Build Coastguard Worker if (x.fieldIndex != y.fieldIndex)
78*8975f5c5SAndroid Build Coastguard Worker {
79*8975f5c5SAndroid Build Coastguard Worker return x.fieldIndex < y.fieldIndex;
80*8975f5c5SAndroid Build Coastguard Worker }
81*8975f5c5SAndroid Build Coastguard Worker
82*8975f5c5SAndroid Build Coastguard Worker // Then order by secondary field index
83*8975f5c5SAndroid Build Coastguard Worker if (x.secondaryFieldIndex != y.secondaryFieldIndex)
84*8975f5c5SAndroid Build Coastguard Worker {
85*8975f5c5SAndroid Build Coastguard Worker return x.secondaryFieldIndex < y.secondaryFieldIndex;
86*8975f5c5SAndroid Build Coastguard Worker }
87*8975f5c5SAndroid Build Coastguard Worker
88*8975f5c5SAndroid Build Coastguard Worker // Otherwise order by variable
89*8975f5c5SAndroid Build Coastguard Worker return gl::CompareShaderVar(*px, *py);
90*8975f5c5SAndroid Build Coastguard Worker }
91*8975f5c5SAndroid Build Coastguard Worker
InterfaceVariablesMatch(const sh::ShaderVariable & front,const sh::ShaderVariable & back)92*8975f5c5SAndroid Build Coastguard Worker bool InterfaceVariablesMatch(const sh::ShaderVariable &front, const sh::ShaderVariable &back)
93*8975f5c5SAndroid Build Coastguard Worker {
94*8975f5c5SAndroid Build Coastguard Worker // Matching ruels from 7.4.1 Shader Interface Matching from the GLES 3.2 spec:
95*8975f5c5SAndroid Build Coastguard Worker // - the two variables match in name, type, and qualification; or
96*8975f5c5SAndroid Build Coastguard Worker // - the two variables are declared with the same location qualifier and match in type and
97*8975f5c5SAndroid Build Coastguard Worker // qualification. Note that we use a more permissive check here thanks to front-end validation.
98*8975f5c5SAndroid Build Coastguard Worker if (back.location != -1 && back.location == front.location)
99*8975f5c5SAndroid Build Coastguard Worker {
100*8975f5c5SAndroid Build Coastguard Worker return true;
101*8975f5c5SAndroid Build Coastguard Worker }
102*8975f5c5SAndroid Build Coastguard Worker
103*8975f5c5SAndroid Build Coastguard Worker if (front.isShaderIOBlock != back.isShaderIOBlock)
104*8975f5c5SAndroid Build Coastguard Worker {
105*8975f5c5SAndroid Build Coastguard Worker return false;
106*8975f5c5SAndroid Build Coastguard Worker }
107*8975f5c5SAndroid Build Coastguard Worker
108*8975f5c5SAndroid Build Coastguard Worker // Compare names, or if shader I/O blocks, block names.
109*8975f5c5SAndroid Build Coastguard Worker const std::string &backName = back.isShaderIOBlock ? back.structOrBlockName : back.name;
110*8975f5c5SAndroid Build Coastguard Worker const std::string &frontName = front.isShaderIOBlock ? front.structOrBlockName : front.name;
111*8975f5c5SAndroid Build Coastguard Worker return backName == frontName;
112*8975f5c5SAndroid Build Coastguard Worker }
113*8975f5c5SAndroid Build Coastguard Worker
GetMaxShaderInputVectors(const Caps & caps,ShaderType shaderStage)114*8975f5c5SAndroid Build Coastguard Worker GLint GetMaxShaderInputVectors(const Caps &caps, ShaderType shaderStage)
115*8975f5c5SAndroid Build Coastguard Worker {
116*8975f5c5SAndroid Build Coastguard Worker switch (shaderStage)
117*8975f5c5SAndroid Build Coastguard Worker {
118*8975f5c5SAndroid Build Coastguard Worker case ShaderType::TessControl:
119*8975f5c5SAndroid Build Coastguard Worker return caps.maxTessControlInputComponents / 4;
120*8975f5c5SAndroid Build Coastguard Worker case ShaderType::TessEvaluation:
121*8975f5c5SAndroid Build Coastguard Worker return caps.maxTessEvaluationInputComponents / 4;
122*8975f5c5SAndroid Build Coastguard Worker case ShaderType::Geometry:
123*8975f5c5SAndroid Build Coastguard Worker return caps.maxGeometryInputComponents / 4;
124*8975f5c5SAndroid Build Coastguard Worker case ShaderType::Fragment:
125*8975f5c5SAndroid Build Coastguard Worker return caps.maxFragmentInputComponents / 4;
126*8975f5c5SAndroid Build Coastguard Worker default:
127*8975f5c5SAndroid Build Coastguard Worker return std::numeric_limits<GLint>::max();
128*8975f5c5SAndroid Build Coastguard Worker }
129*8975f5c5SAndroid Build Coastguard Worker }
130*8975f5c5SAndroid Build Coastguard Worker
GetMaxShaderOutputVectors(const Caps & caps,ShaderType shaderStage)131*8975f5c5SAndroid Build Coastguard Worker GLint GetMaxShaderOutputVectors(const Caps &caps, ShaderType shaderStage)
132*8975f5c5SAndroid Build Coastguard Worker {
133*8975f5c5SAndroid Build Coastguard Worker switch (shaderStage)
134*8975f5c5SAndroid Build Coastguard Worker {
135*8975f5c5SAndroid Build Coastguard Worker case ShaderType::Vertex:
136*8975f5c5SAndroid Build Coastguard Worker return caps.maxVertexOutputComponents / 4;
137*8975f5c5SAndroid Build Coastguard Worker case ShaderType::TessControl:
138*8975f5c5SAndroid Build Coastguard Worker return caps.maxTessControlOutputComponents / 4;
139*8975f5c5SAndroid Build Coastguard Worker case ShaderType::TessEvaluation:
140*8975f5c5SAndroid Build Coastguard Worker return caps.maxTessEvaluationOutputComponents / 4;
141*8975f5c5SAndroid Build Coastguard Worker case ShaderType::Geometry:
142*8975f5c5SAndroid Build Coastguard Worker return caps.maxGeometryOutputComponents / 4;
143*8975f5c5SAndroid Build Coastguard Worker default:
144*8975f5c5SAndroid Build Coastguard Worker return std::numeric_limits<GLint>::max();
145*8975f5c5SAndroid Build Coastguard Worker }
146*8975f5c5SAndroid Build Coastguard Worker }
147*8975f5c5SAndroid Build Coastguard Worker
ShouldSkipPackedVarying(const sh::ShaderVariable & varying,PackMode packMode)148*8975f5c5SAndroid Build Coastguard Worker bool ShouldSkipPackedVarying(const sh::ShaderVariable &varying, PackMode packMode)
149*8975f5c5SAndroid Build Coastguard Worker {
150*8975f5c5SAndroid Build Coastguard Worker // Don't pack gl_Position. Also don't count gl_PointSize for D3D9.
151*8975f5c5SAndroid Build Coastguard Worker // Additionally, gl_TessLevelInner and gl_TessLevelOuter should not be packed.
152*8975f5c5SAndroid Build Coastguard Worker return varying.name == "gl_Position" ||
153*8975f5c5SAndroid Build Coastguard Worker (varying.name == "gl_PointSize" && packMode == PackMode::ANGLE_NON_CONFORMANT_D3D9) ||
154*8975f5c5SAndroid Build Coastguard Worker varying.name == "gl_TessLevelInner" || varying.name == "gl_TessLevelOuter";
155*8975f5c5SAndroid Build Coastguard Worker }
156*8975f5c5SAndroid Build Coastguard Worker
StripVaryingArrayDimension(const sh::ShaderVariable * frontVarying,ShaderType frontShaderStage,const sh::ShaderVariable * backVarying,ShaderType backShaderStage,bool isStructField)157*8975f5c5SAndroid Build Coastguard Worker std::vector<unsigned int> StripVaryingArrayDimension(const sh::ShaderVariable *frontVarying,
158*8975f5c5SAndroid Build Coastguard Worker ShaderType frontShaderStage,
159*8975f5c5SAndroid Build Coastguard Worker const sh::ShaderVariable *backVarying,
160*8975f5c5SAndroid Build Coastguard Worker ShaderType backShaderStage,
161*8975f5c5SAndroid Build Coastguard Worker bool isStructField)
162*8975f5c5SAndroid Build Coastguard Worker {
163*8975f5c5SAndroid Build Coastguard Worker // "Geometry shader inputs, tessellation control shader inputs and outputs, and tessellation
164*8975f5c5SAndroid Build Coastguard Worker // evaluation inputs all have an additional level of arrayness relative to other shader inputs
165*8975f5c5SAndroid Build Coastguard Worker // and outputs. This outer array level is removed from the type before considering how many
166*8975f5c5SAndroid Build Coastguard Worker // locations the type consumes."
167*8975f5c5SAndroid Build Coastguard Worker
168*8975f5c5SAndroid Build Coastguard Worker if (backVarying && backVarying->isArray() && !backVarying->isPatch && !isStructField &&
169*8975f5c5SAndroid Build Coastguard Worker (backShaderStage == ShaderType::Geometry || backShaderStage == ShaderType::TessEvaluation ||
170*8975f5c5SAndroid Build Coastguard Worker backShaderStage == ShaderType::TessControl))
171*8975f5c5SAndroid Build Coastguard Worker {
172*8975f5c5SAndroid Build Coastguard Worker std::vector<unsigned int> arr = backVarying->arraySizes;
173*8975f5c5SAndroid Build Coastguard Worker arr.pop_back();
174*8975f5c5SAndroid Build Coastguard Worker return arr;
175*8975f5c5SAndroid Build Coastguard Worker }
176*8975f5c5SAndroid Build Coastguard Worker
177*8975f5c5SAndroid Build Coastguard Worker if (frontVarying && frontVarying->isArray() && !frontVarying->isPatch && !isStructField &&
178*8975f5c5SAndroid Build Coastguard Worker frontShaderStage == ShaderType::TessControl)
179*8975f5c5SAndroid Build Coastguard Worker {
180*8975f5c5SAndroid Build Coastguard Worker std::vector<unsigned int> arr = frontVarying->arraySizes;
181*8975f5c5SAndroid Build Coastguard Worker arr.pop_back();
182*8975f5c5SAndroid Build Coastguard Worker return arr;
183*8975f5c5SAndroid Build Coastguard Worker }
184*8975f5c5SAndroid Build Coastguard Worker
185*8975f5c5SAndroid Build Coastguard Worker return frontVarying ? frontVarying->arraySizes : backVarying->arraySizes;
186*8975f5c5SAndroid Build Coastguard Worker }
187*8975f5c5SAndroid Build Coastguard Worker
GetPerVertexMember(const std::string & name)188*8975f5c5SAndroid Build Coastguard Worker PerVertexMember GetPerVertexMember(const std::string &name)
189*8975f5c5SAndroid Build Coastguard Worker {
190*8975f5c5SAndroid Build Coastguard Worker if (name == "gl_Position")
191*8975f5c5SAndroid Build Coastguard Worker {
192*8975f5c5SAndroid Build Coastguard Worker return PerVertexMember::Position;
193*8975f5c5SAndroid Build Coastguard Worker }
194*8975f5c5SAndroid Build Coastguard Worker if (name == "gl_PointSize")
195*8975f5c5SAndroid Build Coastguard Worker {
196*8975f5c5SAndroid Build Coastguard Worker return PerVertexMember::PointSize;
197*8975f5c5SAndroid Build Coastguard Worker }
198*8975f5c5SAndroid Build Coastguard Worker if (name == "gl_ClipDistance")
199*8975f5c5SAndroid Build Coastguard Worker {
200*8975f5c5SAndroid Build Coastguard Worker return PerVertexMember::ClipDistance;
201*8975f5c5SAndroid Build Coastguard Worker }
202*8975f5c5SAndroid Build Coastguard Worker if (name == "gl_CullDistance")
203*8975f5c5SAndroid Build Coastguard Worker {
204*8975f5c5SAndroid Build Coastguard Worker return PerVertexMember::CullDistance;
205*8975f5c5SAndroid Build Coastguard Worker }
206*8975f5c5SAndroid Build Coastguard Worker return PerVertexMember::InvalidEnum;
207*8975f5c5SAndroid Build Coastguard Worker }
208*8975f5c5SAndroid Build Coastguard Worker
SetActivePerVertexMembers(const sh::ShaderVariable * var,PerVertexMemberBitSet * bitset)209*8975f5c5SAndroid Build Coastguard Worker void SetActivePerVertexMembers(const sh::ShaderVariable *var, PerVertexMemberBitSet *bitset)
210*8975f5c5SAndroid Build Coastguard Worker {
211*8975f5c5SAndroid Build Coastguard Worker ASSERT(var->isBuiltIn() && var->active);
212*8975f5c5SAndroid Build Coastguard Worker
213*8975f5c5SAndroid Build Coastguard Worker // Only process gl_Position, gl_PointSize, gl_ClipDistance, gl_CullDistance and the fields of
214*8975f5c5SAndroid Build Coastguard Worker // gl_in/out.
215*8975f5c5SAndroid Build Coastguard Worker if (var->fields.empty())
216*8975f5c5SAndroid Build Coastguard Worker {
217*8975f5c5SAndroid Build Coastguard Worker PerVertexMember member = GetPerVertexMember(var->name);
218*8975f5c5SAndroid Build Coastguard Worker // Skip gl_TessLevelInner/Outer etc.
219*8975f5c5SAndroid Build Coastguard Worker if (member != PerVertexMember::InvalidEnum)
220*8975f5c5SAndroid Build Coastguard Worker {
221*8975f5c5SAndroid Build Coastguard Worker bitset->set(member);
222*8975f5c5SAndroid Build Coastguard Worker }
223*8975f5c5SAndroid Build Coastguard Worker return;
224*8975f5c5SAndroid Build Coastguard Worker }
225*8975f5c5SAndroid Build Coastguard Worker
226*8975f5c5SAndroid Build Coastguard Worker // This must be gl_out. Note that only `out gl_PerVertex` is processed; the input of the
227*8975f5c5SAndroid Build Coastguard Worker // next stage is implicitly identically active.
228*8975f5c5SAndroid Build Coastguard Worker ASSERT(var->name == "gl_out");
229*8975f5c5SAndroid Build Coastguard Worker for (const sh::ShaderVariable &field : var->fields)
230*8975f5c5SAndroid Build Coastguard Worker {
231*8975f5c5SAndroid Build Coastguard Worker bitset->set(GetPerVertexMember(field.name));
232*8975f5c5SAndroid Build Coastguard Worker }
233*8975f5c5SAndroid Build Coastguard Worker }
234*8975f5c5SAndroid Build Coastguard Worker } // anonymous namespace
235*8975f5c5SAndroid Build Coastguard Worker
236*8975f5c5SAndroid Build Coastguard Worker // Implementation of VaryingInShaderRef
VaryingInShaderRef(ShaderType stageIn,const sh::ShaderVariable * varyingIn)237*8975f5c5SAndroid Build Coastguard Worker VaryingInShaderRef::VaryingInShaderRef(ShaderType stageIn, const sh::ShaderVariable *varyingIn)
238*8975f5c5SAndroid Build Coastguard Worker : varying(varyingIn), stage(stageIn)
239*8975f5c5SAndroid Build Coastguard Worker {}
240*8975f5c5SAndroid Build Coastguard Worker
241*8975f5c5SAndroid Build Coastguard Worker VaryingInShaderRef::~VaryingInShaderRef() = default;
242*8975f5c5SAndroid Build Coastguard Worker
VaryingInShaderRef(VaryingInShaderRef && other)243*8975f5c5SAndroid Build Coastguard Worker VaryingInShaderRef::VaryingInShaderRef(VaryingInShaderRef &&other)
244*8975f5c5SAndroid Build Coastguard Worker : varying(other.varying),
245*8975f5c5SAndroid Build Coastguard Worker stage(other.stage),
246*8975f5c5SAndroid Build Coastguard Worker parentStructName(std::move(other.parentStructName))
247*8975f5c5SAndroid Build Coastguard Worker {}
248*8975f5c5SAndroid Build Coastguard Worker
operator =(VaryingInShaderRef && other)249*8975f5c5SAndroid Build Coastguard Worker VaryingInShaderRef &VaryingInShaderRef::operator=(VaryingInShaderRef &&other)
250*8975f5c5SAndroid Build Coastguard Worker {
251*8975f5c5SAndroid Build Coastguard Worker std::swap(varying, other.varying);
252*8975f5c5SAndroid Build Coastguard Worker std::swap(stage, other.stage);
253*8975f5c5SAndroid Build Coastguard Worker std::swap(parentStructName, other.parentStructName);
254*8975f5c5SAndroid Build Coastguard Worker
255*8975f5c5SAndroid Build Coastguard Worker return *this;
256*8975f5c5SAndroid Build Coastguard Worker }
257*8975f5c5SAndroid Build Coastguard Worker
258*8975f5c5SAndroid Build Coastguard Worker // Implementation of PackedVarying
PackedVarying(VaryingInShaderRef && frontVaryingIn,VaryingInShaderRef && backVaryingIn,sh::InterpolationType interpolationIn)259*8975f5c5SAndroid Build Coastguard Worker PackedVarying::PackedVarying(VaryingInShaderRef &&frontVaryingIn,
260*8975f5c5SAndroid Build Coastguard Worker VaryingInShaderRef &&backVaryingIn,
261*8975f5c5SAndroid Build Coastguard Worker sh::InterpolationType interpolationIn)
262*8975f5c5SAndroid Build Coastguard Worker : PackedVarying(std::move(frontVaryingIn),
263*8975f5c5SAndroid Build Coastguard Worker std::move(backVaryingIn),
264*8975f5c5SAndroid Build Coastguard Worker interpolationIn,
265*8975f5c5SAndroid Build Coastguard Worker GL_INVALID_INDEX,
266*8975f5c5SAndroid Build Coastguard Worker 0,
267*8975f5c5SAndroid Build Coastguard Worker 0)
268*8975f5c5SAndroid Build Coastguard Worker {}
269*8975f5c5SAndroid Build Coastguard Worker
PackedVarying(VaryingInShaderRef && frontVaryingIn,VaryingInShaderRef && backVaryingIn,sh::InterpolationType interpolationIn,GLuint arrayIndexIn,GLuint fieldIndexIn,GLuint secondaryFieldIndexIn)270*8975f5c5SAndroid Build Coastguard Worker PackedVarying::PackedVarying(VaryingInShaderRef &&frontVaryingIn,
271*8975f5c5SAndroid Build Coastguard Worker VaryingInShaderRef &&backVaryingIn,
272*8975f5c5SAndroid Build Coastguard Worker sh::InterpolationType interpolationIn,
273*8975f5c5SAndroid Build Coastguard Worker GLuint arrayIndexIn,
274*8975f5c5SAndroid Build Coastguard Worker GLuint fieldIndexIn,
275*8975f5c5SAndroid Build Coastguard Worker GLuint secondaryFieldIndexIn)
276*8975f5c5SAndroid Build Coastguard Worker : frontVarying(std::move(frontVaryingIn)),
277*8975f5c5SAndroid Build Coastguard Worker backVarying(std::move(backVaryingIn)),
278*8975f5c5SAndroid Build Coastguard Worker interpolation(interpolationIn),
279*8975f5c5SAndroid Build Coastguard Worker arrayIndex(arrayIndexIn),
280*8975f5c5SAndroid Build Coastguard Worker isTransformFeedback(false),
281*8975f5c5SAndroid Build Coastguard Worker fieldIndex(fieldIndexIn),
282*8975f5c5SAndroid Build Coastguard Worker secondaryFieldIndex(secondaryFieldIndexIn)
283*8975f5c5SAndroid Build Coastguard Worker {}
284*8975f5c5SAndroid Build Coastguard Worker
285*8975f5c5SAndroid Build Coastguard Worker PackedVarying::~PackedVarying() = default;
286*8975f5c5SAndroid Build Coastguard Worker
PackedVarying(PackedVarying && other)287*8975f5c5SAndroid Build Coastguard Worker PackedVarying::PackedVarying(PackedVarying &&other)
288*8975f5c5SAndroid Build Coastguard Worker : frontVarying(std::move(other.frontVarying)),
289*8975f5c5SAndroid Build Coastguard Worker backVarying(std::move(other.backVarying)),
290*8975f5c5SAndroid Build Coastguard Worker interpolation(other.interpolation),
291*8975f5c5SAndroid Build Coastguard Worker arrayIndex(other.arrayIndex),
292*8975f5c5SAndroid Build Coastguard Worker isTransformFeedback(other.isTransformFeedback),
293*8975f5c5SAndroid Build Coastguard Worker fieldIndex(other.fieldIndex),
294*8975f5c5SAndroid Build Coastguard Worker secondaryFieldIndex(other.secondaryFieldIndex)
295*8975f5c5SAndroid Build Coastguard Worker {}
296*8975f5c5SAndroid Build Coastguard Worker
operator =(PackedVarying && other)297*8975f5c5SAndroid Build Coastguard Worker PackedVarying &PackedVarying::operator=(PackedVarying &&other)
298*8975f5c5SAndroid Build Coastguard Worker {
299*8975f5c5SAndroid Build Coastguard Worker std::swap(frontVarying, other.frontVarying);
300*8975f5c5SAndroid Build Coastguard Worker std::swap(backVarying, other.backVarying);
301*8975f5c5SAndroid Build Coastguard Worker std::swap(interpolation, other.interpolation);
302*8975f5c5SAndroid Build Coastguard Worker std::swap(arrayIndex, other.arrayIndex);
303*8975f5c5SAndroid Build Coastguard Worker std::swap(isTransformFeedback, other.isTransformFeedback);
304*8975f5c5SAndroid Build Coastguard Worker std::swap(fieldIndex, other.fieldIndex);
305*8975f5c5SAndroid Build Coastguard Worker std::swap(secondaryFieldIndex, other.secondaryFieldIndex);
306*8975f5c5SAndroid Build Coastguard Worker
307*8975f5c5SAndroid Build Coastguard Worker return *this;
308*8975f5c5SAndroid Build Coastguard Worker }
309*8975f5c5SAndroid Build Coastguard Worker
getBasicTypeElementCount() const310*8975f5c5SAndroid Build Coastguard Worker unsigned int PackedVarying::getBasicTypeElementCount() const
311*8975f5c5SAndroid Build Coastguard Worker {
312*8975f5c5SAndroid Build Coastguard Worker // "Geometry shader inputs, tessellation control shader inputs and outputs, and tessellation
313*8975f5c5SAndroid Build Coastguard Worker // evaluation inputs all have an additional level of arrayness relative to other shader inputs
314*8975f5c5SAndroid Build Coastguard Worker // and outputs. This outer array level is removed from the type before considering how many
315*8975f5c5SAndroid Build Coastguard Worker // locations the type consumes."
316*8975f5c5SAndroid Build Coastguard Worker std::vector<unsigned int> arr =
317*8975f5c5SAndroid Build Coastguard Worker StripVaryingArrayDimension(frontVarying.varying, frontVarying.stage, backVarying.varying,
318*8975f5c5SAndroid Build Coastguard Worker backVarying.stage, isStructField());
319*8975f5c5SAndroid Build Coastguard Worker return arr.empty() ? 1u : arr.back();
320*8975f5c5SAndroid Build Coastguard Worker }
321*8975f5c5SAndroid Build Coastguard Worker
322*8975f5c5SAndroid Build Coastguard Worker // Implementation of VaryingPacking
323*8975f5c5SAndroid Build Coastguard Worker VaryingPacking::VaryingPacking() = default;
324*8975f5c5SAndroid Build Coastguard Worker
325*8975f5c5SAndroid Build Coastguard Worker VaryingPacking::~VaryingPacking() = default;
326*8975f5c5SAndroid Build Coastguard Worker
reset()327*8975f5c5SAndroid Build Coastguard Worker void VaryingPacking::reset()
328*8975f5c5SAndroid Build Coastguard Worker {
329*8975f5c5SAndroid Build Coastguard Worker clearRegisterMap();
330*8975f5c5SAndroid Build Coastguard Worker mRegisterList.clear();
331*8975f5c5SAndroid Build Coastguard Worker mPackedVaryings.clear();
332*8975f5c5SAndroid Build Coastguard Worker
333*8975f5c5SAndroid Build Coastguard Worker for (std::vector<uint32_t> &inactiveVaryingIds : mInactiveVaryingIds)
334*8975f5c5SAndroid Build Coastguard Worker {
335*8975f5c5SAndroid Build Coastguard Worker inactiveVaryingIds.clear();
336*8975f5c5SAndroid Build Coastguard Worker }
337*8975f5c5SAndroid Build Coastguard Worker
338*8975f5c5SAndroid Build Coastguard Worker std::fill(mOutputPerVertexActiveMembers.begin(), mOutputPerVertexActiveMembers.end(),
339*8975f5c5SAndroid Build Coastguard Worker gl::PerVertexMemberBitSet{});
340*8975f5c5SAndroid Build Coastguard Worker }
341*8975f5c5SAndroid Build Coastguard Worker
clearRegisterMap()342*8975f5c5SAndroid Build Coastguard Worker void VaryingPacking::clearRegisterMap()
343*8975f5c5SAndroid Build Coastguard Worker {
344*8975f5c5SAndroid Build Coastguard Worker std::fill(mRegisterMap.begin(), mRegisterMap.end(), Register());
345*8975f5c5SAndroid Build Coastguard Worker }
346*8975f5c5SAndroid Build Coastguard Worker
347*8975f5c5SAndroid Build Coastguard Worker // Packs varyings into generic varying registers, using the algorithm from
348*8975f5c5SAndroid Build Coastguard Worker // See [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111
349*8975f5c5SAndroid Build Coastguard Worker // Also [OpenGL ES Shading Language 3.00 rev. 4] Section 11 page 119
350*8975f5c5SAndroid Build Coastguard Worker // Returns false if unsuccessful.
packVaryingIntoRegisterMap(PackMode packMode,const PackedVarying & packedVarying)351*8975f5c5SAndroid Build Coastguard Worker bool VaryingPacking::packVaryingIntoRegisterMap(PackMode packMode,
352*8975f5c5SAndroid Build Coastguard Worker const PackedVarying &packedVarying)
353*8975f5c5SAndroid Build Coastguard Worker {
354*8975f5c5SAndroid Build Coastguard Worker const sh::ShaderVariable &varying = packedVarying.varying();
355*8975f5c5SAndroid Build Coastguard Worker
356*8975f5c5SAndroid Build Coastguard Worker // "Non - square matrices of type matCxR consume the same space as a square matrix of type matN
357*8975f5c5SAndroid Build Coastguard Worker // where N is the greater of C and R."
358*8975f5c5SAndroid Build Coastguard Worker // Here we are a bit more conservative and allow packing non-square matrices more tightly.
359*8975f5c5SAndroid Build Coastguard Worker // Make sure we use transposed matrix types to count registers correctly.
360*8975f5c5SAndroid Build Coastguard Worker ASSERT(!varying.isStruct());
361*8975f5c5SAndroid Build Coastguard Worker GLenum transposedType = gl::TransposeMatrixType(varying.type);
362*8975f5c5SAndroid Build Coastguard Worker unsigned int varyingRows = gl::VariableRowCount(transposedType);
363*8975f5c5SAndroid Build Coastguard Worker unsigned int varyingColumns = gl::VariableColumnCount(transposedType);
364*8975f5c5SAndroid Build Coastguard Worker
365*8975f5c5SAndroid Build Coastguard Worker // Special pack mode for D3D9. Each varying takes a full register, no sharing.
366*8975f5c5SAndroid Build Coastguard Worker // TODO(jmadill): Implement more sophisticated component packing in D3D9.
367*8975f5c5SAndroid Build Coastguard Worker if (packMode == PackMode::ANGLE_NON_CONFORMANT_D3D9)
368*8975f5c5SAndroid Build Coastguard Worker {
369*8975f5c5SAndroid Build Coastguard Worker varyingColumns = 4;
370*8975f5c5SAndroid Build Coastguard Worker }
371*8975f5c5SAndroid Build Coastguard Worker
372*8975f5c5SAndroid Build Coastguard Worker // "Variables of type mat2 occupies 2 complete rows."
373*8975f5c5SAndroid Build Coastguard Worker // For non-WebGL contexts, we allow mat2 to occupy only two columns per row.
374*8975f5c5SAndroid Build Coastguard Worker else if (packMode == PackMode::WEBGL_STRICT && varying.type == GL_FLOAT_MAT2)
375*8975f5c5SAndroid Build Coastguard Worker {
376*8975f5c5SAndroid Build Coastguard Worker varyingColumns = 4;
377*8975f5c5SAndroid Build Coastguard Worker }
378*8975f5c5SAndroid Build Coastguard Worker
379*8975f5c5SAndroid Build Coastguard Worker // "Arrays of size N are assumed to take N times the size of the base type"
380*8975f5c5SAndroid Build Coastguard Worker // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
381*8975f5c5SAndroid Build Coastguard Worker // structures, so we may use getBasicTypeElementCount().
382*8975f5c5SAndroid Build Coastguard Worker const unsigned int elementCount = packedVarying.getBasicTypeElementCount();
383*8975f5c5SAndroid Build Coastguard Worker varyingRows *= (packedVarying.isTransformFeedbackArrayElement() ? 1 : elementCount);
384*8975f5c5SAndroid Build Coastguard Worker
385*8975f5c5SAndroid Build Coastguard Worker unsigned int maxVaryingVectors = static_cast<unsigned int>(mRegisterMap.size());
386*8975f5c5SAndroid Build Coastguard Worker
387*8975f5c5SAndroid Build Coastguard Worker // Fail if we are packing a single over-large varying.
388*8975f5c5SAndroid Build Coastguard Worker if (varyingRows > maxVaryingVectors)
389*8975f5c5SAndroid Build Coastguard Worker {
390*8975f5c5SAndroid Build Coastguard Worker return false;
391*8975f5c5SAndroid Build Coastguard Worker }
392*8975f5c5SAndroid Build Coastguard Worker
393*8975f5c5SAndroid Build Coastguard Worker // "For 2, 3 and 4 component variables packing is started using the 1st column of the 1st row.
394*8975f5c5SAndroid Build Coastguard Worker // Variables are then allocated to successive rows, aligning them to the 1st column."
395*8975f5c5SAndroid Build Coastguard Worker if (varyingColumns >= 2 && varyingColumns <= 4)
396*8975f5c5SAndroid Build Coastguard Worker {
397*8975f5c5SAndroid Build Coastguard Worker for (unsigned int row = 0; row <= maxVaryingVectors - varyingRows; ++row)
398*8975f5c5SAndroid Build Coastguard Worker {
399*8975f5c5SAndroid Build Coastguard Worker if (isRegisterRangeFree(row, 0, varyingRows, varyingColumns))
400*8975f5c5SAndroid Build Coastguard Worker {
401*8975f5c5SAndroid Build Coastguard Worker insertVaryingIntoRegisterMap(row, 0, varyingColumns, packedVarying);
402*8975f5c5SAndroid Build Coastguard Worker return true;
403*8975f5c5SAndroid Build Coastguard Worker }
404*8975f5c5SAndroid Build Coastguard Worker }
405*8975f5c5SAndroid Build Coastguard Worker
406*8975f5c5SAndroid Build Coastguard Worker // "For 2 component variables, when there are no spare rows, the strategy is switched to
407*8975f5c5SAndroid Build Coastguard Worker // using the highest numbered row and the lowest numbered column where the variable will
408*8975f5c5SAndroid Build Coastguard Worker // fit."
409*8975f5c5SAndroid Build Coastguard Worker if (varyingColumns == 2)
410*8975f5c5SAndroid Build Coastguard Worker {
411*8975f5c5SAndroid Build Coastguard Worker for (unsigned int r = maxVaryingVectors - varyingRows + 1; r-- >= 1;)
412*8975f5c5SAndroid Build Coastguard Worker {
413*8975f5c5SAndroid Build Coastguard Worker if (isRegisterRangeFree(r, 2, varyingRows, 2))
414*8975f5c5SAndroid Build Coastguard Worker {
415*8975f5c5SAndroid Build Coastguard Worker insertVaryingIntoRegisterMap(r, 2, varyingColumns, packedVarying);
416*8975f5c5SAndroid Build Coastguard Worker return true;
417*8975f5c5SAndroid Build Coastguard Worker }
418*8975f5c5SAndroid Build Coastguard Worker }
419*8975f5c5SAndroid Build Coastguard Worker }
420*8975f5c5SAndroid Build Coastguard Worker
421*8975f5c5SAndroid Build Coastguard Worker return false;
422*8975f5c5SAndroid Build Coastguard Worker }
423*8975f5c5SAndroid Build Coastguard Worker
424*8975f5c5SAndroid Build Coastguard Worker // "1 component variables have their own packing rule. They are packed in order of size, largest
425*8975f5c5SAndroid Build Coastguard Worker // first. Each variable is placed in the column that leaves the least amount of space in the
426*8975f5c5SAndroid Build Coastguard Worker // column and aligned to the lowest available rows within that column."
427*8975f5c5SAndroid Build Coastguard Worker ASSERT(varyingColumns == 1);
428*8975f5c5SAndroid Build Coastguard Worker unsigned int contiguousSpace[4] = {0};
429*8975f5c5SAndroid Build Coastguard Worker unsigned int bestContiguousSpace[4] = {0};
430*8975f5c5SAndroid Build Coastguard Worker unsigned int totalSpace[4] = {0};
431*8975f5c5SAndroid Build Coastguard Worker
432*8975f5c5SAndroid Build Coastguard Worker for (unsigned int row = 0; row < maxVaryingVectors; ++row)
433*8975f5c5SAndroid Build Coastguard Worker {
434*8975f5c5SAndroid Build Coastguard Worker for (unsigned int column = 0; column < 4; ++column)
435*8975f5c5SAndroid Build Coastguard Worker {
436*8975f5c5SAndroid Build Coastguard Worker if (mRegisterMap[row][column])
437*8975f5c5SAndroid Build Coastguard Worker {
438*8975f5c5SAndroid Build Coastguard Worker contiguousSpace[column] = 0;
439*8975f5c5SAndroid Build Coastguard Worker }
440*8975f5c5SAndroid Build Coastguard Worker else
441*8975f5c5SAndroid Build Coastguard Worker {
442*8975f5c5SAndroid Build Coastguard Worker contiguousSpace[column]++;
443*8975f5c5SAndroid Build Coastguard Worker totalSpace[column]++;
444*8975f5c5SAndroid Build Coastguard Worker
445*8975f5c5SAndroid Build Coastguard Worker if (contiguousSpace[column] > bestContiguousSpace[column])
446*8975f5c5SAndroid Build Coastguard Worker {
447*8975f5c5SAndroid Build Coastguard Worker bestContiguousSpace[column] = contiguousSpace[column];
448*8975f5c5SAndroid Build Coastguard Worker }
449*8975f5c5SAndroid Build Coastguard Worker }
450*8975f5c5SAndroid Build Coastguard Worker }
451*8975f5c5SAndroid Build Coastguard Worker }
452*8975f5c5SAndroid Build Coastguard Worker
453*8975f5c5SAndroid Build Coastguard Worker unsigned int bestColumn = 0;
454*8975f5c5SAndroid Build Coastguard Worker for (unsigned int column = 1; column < 4; ++column)
455*8975f5c5SAndroid Build Coastguard Worker {
456*8975f5c5SAndroid Build Coastguard Worker if (bestContiguousSpace[column] >= varyingRows &&
457*8975f5c5SAndroid Build Coastguard Worker (bestContiguousSpace[bestColumn] < varyingRows ||
458*8975f5c5SAndroid Build Coastguard Worker totalSpace[column] < totalSpace[bestColumn]))
459*8975f5c5SAndroid Build Coastguard Worker {
460*8975f5c5SAndroid Build Coastguard Worker bestColumn = column;
461*8975f5c5SAndroid Build Coastguard Worker }
462*8975f5c5SAndroid Build Coastguard Worker }
463*8975f5c5SAndroid Build Coastguard Worker
464*8975f5c5SAndroid Build Coastguard Worker if (bestContiguousSpace[bestColumn] >= varyingRows)
465*8975f5c5SAndroid Build Coastguard Worker {
466*8975f5c5SAndroid Build Coastguard Worker for (unsigned int row = 0; row < maxVaryingVectors; row++)
467*8975f5c5SAndroid Build Coastguard Worker {
468*8975f5c5SAndroid Build Coastguard Worker if (isRegisterRangeFree(row, bestColumn, varyingRows, 1))
469*8975f5c5SAndroid Build Coastguard Worker {
470*8975f5c5SAndroid Build Coastguard Worker for (unsigned int arrayIndex = 0; arrayIndex < varyingRows; ++arrayIndex)
471*8975f5c5SAndroid Build Coastguard Worker {
472*8975f5c5SAndroid Build Coastguard Worker // If varyingRows > 1, it must be an array.
473*8975f5c5SAndroid Build Coastguard Worker PackedVaryingRegister registerInfo;
474*8975f5c5SAndroid Build Coastguard Worker registerInfo.packedVarying = &packedVarying;
475*8975f5c5SAndroid Build Coastguard Worker registerInfo.registerRow = row + arrayIndex;
476*8975f5c5SAndroid Build Coastguard Worker registerInfo.registerColumn = bestColumn;
477*8975f5c5SAndroid Build Coastguard Worker registerInfo.varyingArrayIndex =
478*8975f5c5SAndroid Build Coastguard Worker (packedVarying.isTransformFeedbackArrayElement() ? packedVarying.arrayIndex
479*8975f5c5SAndroid Build Coastguard Worker : arrayIndex);
480*8975f5c5SAndroid Build Coastguard Worker registerInfo.varyingRowIndex = 0;
481*8975f5c5SAndroid Build Coastguard Worker // Do not record register info for builtins.
482*8975f5c5SAndroid Build Coastguard Worker // TODO(jmadill): Clean this up.
483*8975f5c5SAndroid Build Coastguard Worker if (!varying.isBuiltIn())
484*8975f5c5SAndroid Build Coastguard Worker {
485*8975f5c5SAndroid Build Coastguard Worker mRegisterList.push_back(registerInfo);
486*8975f5c5SAndroid Build Coastguard Worker }
487*8975f5c5SAndroid Build Coastguard Worker mRegisterMap[row + arrayIndex][bestColumn] = true;
488*8975f5c5SAndroid Build Coastguard Worker }
489*8975f5c5SAndroid Build Coastguard Worker break;
490*8975f5c5SAndroid Build Coastguard Worker }
491*8975f5c5SAndroid Build Coastguard Worker }
492*8975f5c5SAndroid Build Coastguard Worker return true;
493*8975f5c5SAndroid Build Coastguard Worker }
494*8975f5c5SAndroid Build Coastguard Worker
495*8975f5c5SAndroid Build Coastguard Worker return false;
496*8975f5c5SAndroid Build Coastguard Worker }
497*8975f5c5SAndroid Build Coastguard Worker
isRegisterRangeFree(unsigned int registerRow,unsigned int registerColumn,unsigned int varyingRows,unsigned int varyingColumns) const498*8975f5c5SAndroid Build Coastguard Worker bool VaryingPacking::isRegisterRangeFree(unsigned int registerRow,
499*8975f5c5SAndroid Build Coastguard Worker unsigned int registerColumn,
500*8975f5c5SAndroid Build Coastguard Worker unsigned int varyingRows,
501*8975f5c5SAndroid Build Coastguard Worker unsigned int varyingColumns) const
502*8975f5c5SAndroid Build Coastguard Worker {
503*8975f5c5SAndroid Build Coastguard Worker for (unsigned int row = 0; row < varyingRows; ++row)
504*8975f5c5SAndroid Build Coastguard Worker {
505*8975f5c5SAndroid Build Coastguard Worker ASSERT(registerRow + row < mRegisterMap.size());
506*8975f5c5SAndroid Build Coastguard Worker for (unsigned int column = 0; column < varyingColumns; ++column)
507*8975f5c5SAndroid Build Coastguard Worker {
508*8975f5c5SAndroid Build Coastguard Worker ASSERT(registerColumn + column < 4);
509*8975f5c5SAndroid Build Coastguard Worker if (mRegisterMap[registerRow + row][registerColumn + column])
510*8975f5c5SAndroid Build Coastguard Worker {
511*8975f5c5SAndroid Build Coastguard Worker return false;
512*8975f5c5SAndroid Build Coastguard Worker }
513*8975f5c5SAndroid Build Coastguard Worker }
514*8975f5c5SAndroid Build Coastguard Worker }
515*8975f5c5SAndroid Build Coastguard Worker
516*8975f5c5SAndroid Build Coastguard Worker return true;
517*8975f5c5SAndroid Build Coastguard Worker }
518*8975f5c5SAndroid Build Coastguard Worker
insertVaryingIntoRegisterMap(unsigned int registerRow,unsigned int registerColumn,unsigned int varyingColumns,const PackedVarying & packedVarying)519*8975f5c5SAndroid Build Coastguard Worker void VaryingPacking::insertVaryingIntoRegisterMap(unsigned int registerRow,
520*8975f5c5SAndroid Build Coastguard Worker unsigned int registerColumn,
521*8975f5c5SAndroid Build Coastguard Worker unsigned int varyingColumns,
522*8975f5c5SAndroid Build Coastguard Worker const PackedVarying &packedVarying)
523*8975f5c5SAndroid Build Coastguard Worker {
524*8975f5c5SAndroid Build Coastguard Worker unsigned int varyingRows = 0;
525*8975f5c5SAndroid Build Coastguard Worker
526*8975f5c5SAndroid Build Coastguard Worker const sh::ShaderVariable &varying = packedVarying.varying();
527*8975f5c5SAndroid Build Coastguard Worker ASSERT(!varying.isStruct());
528*8975f5c5SAndroid Build Coastguard Worker GLenum transposedType = gl::TransposeMatrixType(varying.type);
529*8975f5c5SAndroid Build Coastguard Worker varyingRows = gl::VariableRowCount(transposedType);
530*8975f5c5SAndroid Build Coastguard Worker
531*8975f5c5SAndroid Build Coastguard Worker PackedVaryingRegister registerInfo;
532*8975f5c5SAndroid Build Coastguard Worker registerInfo.packedVarying = &packedVarying;
533*8975f5c5SAndroid Build Coastguard Worker registerInfo.registerColumn = registerColumn;
534*8975f5c5SAndroid Build Coastguard Worker
535*8975f5c5SAndroid Build Coastguard Worker // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
536*8975f5c5SAndroid Build Coastguard Worker // structures, so we may use getBasicTypeElementCount().
537*8975f5c5SAndroid Build Coastguard Worker const unsigned int arrayElementCount = packedVarying.getBasicTypeElementCount();
538*8975f5c5SAndroid Build Coastguard Worker for (unsigned int arrayElement = 0; arrayElement < arrayElementCount; ++arrayElement)
539*8975f5c5SAndroid Build Coastguard Worker {
540*8975f5c5SAndroid Build Coastguard Worker if (packedVarying.isTransformFeedbackArrayElement() &&
541*8975f5c5SAndroid Build Coastguard Worker arrayElement != packedVarying.arrayIndex)
542*8975f5c5SAndroid Build Coastguard Worker {
543*8975f5c5SAndroid Build Coastguard Worker continue;
544*8975f5c5SAndroid Build Coastguard Worker }
545*8975f5c5SAndroid Build Coastguard Worker for (unsigned int varyingRow = 0; varyingRow < varyingRows; ++varyingRow)
546*8975f5c5SAndroid Build Coastguard Worker {
547*8975f5c5SAndroid Build Coastguard Worker registerInfo.registerRow = registerRow + (arrayElement * varyingRows) + varyingRow;
548*8975f5c5SAndroid Build Coastguard Worker registerInfo.varyingRowIndex = varyingRow;
549*8975f5c5SAndroid Build Coastguard Worker registerInfo.varyingArrayIndex = arrayElement;
550*8975f5c5SAndroid Build Coastguard Worker // Do not record register info for builtins.
551*8975f5c5SAndroid Build Coastguard Worker // TODO(jmadill): Clean this up.
552*8975f5c5SAndroid Build Coastguard Worker if (!varying.isBuiltIn())
553*8975f5c5SAndroid Build Coastguard Worker {
554*8975f5c5SAndroid Build Coastguard Worker mRegisterList.push_back(registerInfo);
555*8975f5c5SAndroid Build Coastguard Worker }
556*8975f5c5SAndroid Build Coastguard Worker
557*8975f5c5SAndroid Build Coastguard Worker for (unsigned int columnIndex = 0; columnIndex < varyingColumns; ++columnIndex)
558*8975f5c5SAndroid Build Coastguard Worker {
559*8975f5c5SAndroid Build Coastguard Worker mRegisterMap[registerInfo.registerRow][registerColumn + columnIndex] = true;
560*8975f5c5SAndroid Build Coastguard Worker }
561*8975f5c5SAndroid Build Coastguard Worker }
562*8975f5c5SAndroid Build Coastguard Worker }
563*8975f5c5SAndroid Build Coastguard Worker }
564*8975f5c5SAndroid Build Coastguard Worker
collectUserVarying(const ProgramVaryingRef & ref,VaryingUniqueFullNames * uniqueFullNames)565*8975f5c5SAndroid Build Coastguard Worker void VaryingPacking::collectUserVarying(const ProgramVaryingRef &ref,
566*8975f5c5SAndroid Build Coastguard Worker VaryingUniqueFullNames *uniqueFullNames)
567*8975f5c5SAndroid Build Coastguard Worker {
568*8975f5c5SAndroid Build Coastguard Worker const sh::ShaderVariable *input = ref.frontShader;
569*8975f5c5SAndroid Build Coastguard Worker const sh::ShaderVariable *output = ref.backShader;
570*8975f5c5SAndroid Build Coastguard Worker
571*8975f5c5SAndroid Build Coastguard Worker // Will get the vertex shader interpolation by default.
572*8975f5c5SAndroid Build Coastguard Worker sh::InterpolationType interpolation = input ? input->interpolation : output->interpolation;
573*8975f5c5SAndroid Build Coastguard Worker
574*8975f5c5SAndroid Build Coastguard Worker VaryingInShaderRef frontVarying(ref.frontShaderStage, input);
575*8975f5c5SAndroid Build Coastguard Worker VaryingInShaderRef backVarying(ref.backShaderStage, output);
576*8975f5c5SAndroid Build Coastguard Worker
577*8975f5c5SAndroid Build Coastguard Worker mPackedVaryings.emplace_back(std::move(frontVarying), std::move(backVarying), interpolation);
578*8975f5c5SAndroid Build Coastguard Worker if (input && !input->isBuiltIn())
579*8975f5c5SAndroid Build Coastguard Worker {
580*8975f5c5SAndroid Build Coastguard Worker (*uniqueFullNames)[ref.frontShaderStage].insert(
581*8975f5c5SAndroid Build Coastguard Worker mPackedVaryings.back().fullName(ref.frontShaderStage));
582*8975f5c5SAndroid Build Coastguard Worker }
583*8975f5c5SAndroid Build Coastguard Worker if (output && !output->isBuiltIn())
584*8975f5c5SAndroid Build Coastguard Worker {
585*8975f5c5SAndroid Build Coastguard Worker (*uniqueFullNames)[ref.backShaderStage].insert(
586*8975f5c5SAndroid Build Coastguard Worker mPackedVaryings.back().fullName(ref.backShaderStage));
587*8975f5c5SAndroid Build Coastguard Worker }
588*8975f5c5SAndroid Build Coastguard Worker }
589*8975f5c5SAndroid Build Coastguard Worker
collectUserVaryingField(const ProgramVaryingRef & ref,GLuint arrayIndex,GLuint fieldIndex,GLuint secondaryFieldIndex,VaryingUniqueFullNames * uniqueFullNames)590*8975f5c5SAndroid Build Coastguard Worker void VaryingPacking::collectUserVaryingField(const ProgramVaryingRef &ref,
591*8975f5c5SAndroid Build Coastguard Worker GLuint arrayIndex,
592*8975f5c5SAndroid Build Coastguard Worker GLuint fieldIndex,
593*8975f5c5SAndroid Build Coastguard Worker GLuint secondaryFieldIndex,
594*8975f5c5SAndroid Build Coastguard Worker VaryingUniqueFullNames *uniqueFullNames)
595*8975f5c5SAndroid Build Coastguard Worker {
596*8975f5c5SAndroid Build Coastguard Worker const sh::ShaderVariable *input = ref.frontShader;
597*8975f5c5SAndroid Build Coastguard Worker const sh::ShaderVariable *output = ref.backShader;
598*8975f5c5SAndroid Build Coastguard Worker
599*8975f5c5SAndroid Build Coastguard Worker // Will get the vertex shader interpolation by default.
600*8975f5c5SAndroid Build Coastguard Worker sh::InterpolationType interpolation = input ? input->interpolation : output->interpolation;
601*8975f5c5SAndroid Build Coastguard Worker
602*8975f5c5SAndroid Build Coastguard Worker const sh::ShaderVariable *frontField = input ? &input->fields[fieldIndex] : nullptr;
603*8975f5c5SAndroid Build Coastguard Worker const sh::ShaderVariable *backField = output ? &output->fields[fieldIndex] : nullptr;
604*8975f5c5SAndroid Build Coastguard Worker
605*8975f5c5SAndroid Build Coastguard Worker if (secondaryFieldIndex != GL_INVALID_INDEX)
606*8975f5c5SAndroid Build Coastguard Worker {
607*8975f5c5SAndroid Build Coastguard Worker frontField = frontField ? &frontField->fields[secondaryFieldIndex] : nullptr;
608*8975f5c5SAndroid Build Coastguard Worker backField = backField ? &backField->fields[secondaryFieldIndex] : nullptr;
609*8975f5c5SAndroid Build Coastguard Worker }
610*8975f5c5SAndroid Build Coastguard Worker
611*8975f5c5SAndroid Build Coastguard Worker VaryingInShaderRef frontVarying(ref.frontShaderStage, frontField);
612*8975f5c5SAndroid Build Coastguard Worker VaryingInShaderRef backVarying(ref.backShaderStage, backField);
613*8975f5c5SAndroid Build Coastguard Worker
614*8975f5c5SAndroid Build Coastguard Worker if (input)
615*8975f5c5SAndroid Build Coastguard Worker {
616*8975f5c5SAndroid Build Coastguard Worker if (frontField->isShaderIOBlock)
617*8975f5c5SAndroid Build Coastguard Worker {
618*8975f5c5SAndroid Build Coastguard Worker frontVarying.parentStructName = input->structOrBlockName;
619*8975f5c5SAndroid Build Coastguard Worker }
620*8975f5c5SAndroid Build Coastguard Worker else
621*8975f5c5SAndroid Build Coastguard Worker {
622*8975f5c5SAndroid Build Coastguard Worker ASSERT(!frontField->isStruct() && !frontField->isArray());
623*8975f5c5SAndroid Build Coastguard Worker frontVarying.parentStructName = input->name;
624*8975f5c5SAndroid Build Coastguard Worker }
625*8975f5c5SAndroid Build Coastguard Worker }
626*8975f5c5SAndroid Build Coastguard Worker if (output)
627*8975f5c5SAndroid Build Coastguard Worker {
628*8975f5c5SAndroid Build Coastguard Worker if (backField->isShaderIOBlock)
629*8975f5c5SAndroid Build Coastguard Worker {
630*8975f5c5SAndroid Build Coastguard Worker backVarying.parentStructName = output->structOrBlockName;
631*8975f5c5SAndroid Build Coastguard Worker }
632*8975f5c5SAndroid Build Coastguard Worker else
633*8975f5c5SAndroid Build Coastguard Worker {
634*8975f5c5SAndroid Build Coastguard Worker ASSERT(!backField->isStruct() && !backField->isArray());
635*8975f5c5SAndroid Build Coastguard Worker backVarying.parentStructName = output->name;
636*8975f5c5SAndroid Build Coastguard Worker }
637*8975f5c5SAndroid Build Coastguard Worker }
638*8975f5c5SAndroid Build Coastguard Worker
639*8975f5c5SAndroid Build Coastguard Worker mPackedVaryings.emplace_back(std::move(frontVarying), std::move(backVarying), interpolation,
640*8975f5c5SAndroid Build Coastguard Worker arrayIndex, fieldIndex,
641*8975f5c5SAndroid Build Coastguard Worker secondaryFieldIndex == GL_INVALID_INDEX ? 0 : secondaryFieldIndex);
642*8975f5c5SAndroid Build Coastguard Worker
643*8975f5c5SAndroid Build Coastguard Worker if (input)
644*8975f5c5SAndroid Build Coastguard Worker {
645*8975f5c5SAndroid Build Coastguard Worker (*uniqueFullNames)[ref.frontShaderStage].insert(
646*8975f5c5SAndroid Build Coastguard Worker mPackedVaryings.back().fullName(ref.frontShaderStage));
647*8975f5c5SAndroid Build Coastguard Worker }
648*8975f5c5SAndroid Build Coastguard Worker if (output)
649*8975f5c5SAndroid Build Coastguard Worker {
650*8975f5c5SAndroid Build Coastguard Worker (*uniqueFullNames)[ref.backShaderStage].insert(
651*8975f5c5SAndroid Build Coastguard Worker mPackedVaryings.back().fullName(ref.backShaderStage));
652*8975f5c5SAndroid Build Coastguard Worker }
653*8975f5c5SAndroid Build Coastguard Worker }
654*8975f5c5SAndroid Build Coastguard Worker
collectUserVaryingTF(const ProgramVaryingRef & ref,size_t subscript)655*8975f5c5SAndroid Build Coastguard Worker void VaryingPacking::collectUserVaryingTF(const ProgramVaryingRef &ref, size_t subscript)
656*8975f5c5SAndroid Build Coastguard Worker {
657*8975f5c5SAndroid Build Coastguard Worker const sh::ShaderVariable *input = ref.frontShader;
658*8975f5c5SAndroid Build Coastguard Worker
659*8975f5c5SAndroid Build Coastguard Worker VaryingInShaderRef frontVarying(ref.frontShaderStage, input);
660*8975f5c5SAndroid Build Coastguard Worker VaryingInShaderRef backVarying(ref.backShaderStage, nullptr);
661*8975f5c5SAndroid Build Coastguard Worker
662*8975f5c5SAndroid Build Coastguard Worker mPackedVaryings.emplace_back(std::move(frontVarying), std::move(backVarying),
663*8975f5c5SAndroid Build Coastguard Worker input->interpolation);
664*8975f5c5SAndroid Build Coastguard Worker mPackedVaryings.back().arrayIndex = static_cast<GLuint>(subscript);
665*8975f5c5SAndroid Build Coastguard Worker mPackedVaryings.back().isTransformFeedback = true;
666*8975f5c5SAndroid Build Coastguard Worker }
667*8975f5c5SAndroid Build Coastguard Worker
collectUserVaryingFieldTF(const ProgramVaryingRef & ref,const sh::ShaderVariable & field,GLuint fieldIndex,GLuint secondaryFieldIndex)668*8975f5c5SAndroid Build Coastguard Worker void VaryingPacking::collectUserVaryingFieldTF(const ProgramVaryingRef &ref,
669*8975f5c5SAndroid Build Coastguard Worker const sh::ShaderVariable &field,
670*8975f5c5SAndroid Build Coastguard Worker GLuint fieldIndex,
671*8975f5c5SAndroid Build Coastguard Worker GLuint secondaryFieldIndex)
672*8975f5c5SAndroid Build Coastguard Worker {
673*8975f5c5SAndroid Build Coastguard Worker const sh::ShaderVariable *input = ref.frontShader;
674*8975f5c5SAndroid Build Coastguard Worker
675*8975f5c5SAndroid Build Coastguard Worker const sh::ShaderVariable *frontField = &field;
676*8975f5c5SAndroid Build Coastguard Worker if (secondaryFieldIndex != GL_INVALID_INDEX)
677*8975f5c5SAndroid Build Coastguard Worker {
678*8975f5c5SAndroid Build Coastguard Worker frontField = &frontField->fields[secondaryFieldIndex];
679*8975f5c5SAndroid Build Coastguard Worker }
680*8975f5c5SAndroid Build Coastguard Worker
681*8975f5c5SAndroid Build Coastguard Worker VaryingInShaderRef frontVarying(ref.frontShaderStage, frontField);
682*8975f5c5SAndroid Build Coastguard Worker VaryingInShaderRef backVarying(ref.backShaderStage, nullptr);
683*8975f5c5SAndroid Build Coastguard Worker
684*8975f5c5SAndroid Build Coastguard Worker if (frontField->isShaderIOBlock)
685*8975f5c5SAndroid Build Coastguard Worker {
686*8975f5c5SAndroid Build Coastguard Worker frontVarying.parentStructName = input->structOrBlockName;
687*8975f5c5SAndroid Build Coastguard Worker }
688*8975f5c5SAndroid Build Coastguard Worker else
689*8975f5c5SAndroid Build Coastguard Worker {
690*8975f5c5SAndroid Build Coastguard Worker ASSERT(!frontField->isStruct() && !frontField->isArray());
691*8975f5c5SAndroid Build Coastguard Worker frontVarying.parentStructName = input->name;
692*8975f5c5SAndroid Build Coastguard Worker }
693*8975f5c5SAndroid Build Coastguard Worker
694*8975f5c5SAndroid Build Coastguard Worker mPackedVaryings.emplace_back(std::move(frontVarying), std::move(backVarying),
695*8975f5c5SAndroid Build Coastguard Worker input->interpolation, GL_INVALID_INDEX, fieldIndex,
696*8975f5c5SAndroid Build Coastguard Worker secondaryFieldIndex == GL_INVALID_INDEX ? 0 : secondaryFieldIndex);
697*8975f5c5SAndroid Build Coastguard Worker }
698*8975f5c5SAndroid Build Coastguard Worker
collectVarying(const sh::ShaderVariable & varying,const ProgramVaryingRef & ref,PackMode packMode,VaryingUniqueFullNames * uniqueFullNames)699*8975f5c5SAndroid Build Coastguard Worker void VaryingPacking::collectVarying(const sh::ShaderVariable &varying,
700*8975f5c5SAndroid Build Coastguard Worker const ProgramVaryingRef &ref,
701*8975f5c5SAndroid Build Coastguard Worker PackMode packMode,
702*8975f5c5SAndroid Build Coastguard Worker VaryingUniqueFullNames *uniqueFullNames)
703*8975f5c5SAndroid Build Coastguard Worker {
704*8975f5c5SAndroid Build Coastguard Worker const sh::ShaderVariable *input = ref.frontShader;
705*8975f5c5SAndroid Build Coastguard Worker const sh::ShaderVariable *output = ref.backShader;
706*8975f5c5SAndroid Build Coastguard Worker
707*8975f5c5SAndroid Build Coastguard Worker if (varying.isStruct())
708*8975f5c5SAndroid Build Coastguard Worker {
709*8975f5c5SAndroid Build Coastguard Worker std::vector<unsigned int> arraySizes = StripVaryingArrayDimension(
710*8975f5c5SAndroid Build Coastguard Worker ref.frontShader, ref.frontShaderStage, ref.backShader, ref.backShaderStage, false);
711*8975f5c5SAndroid Build Coastguard Worker const bool isArray = !arraySizes.empty();
712*8975f5c5SAndroid Build Coastguard Worker const GLuint arraySize = isArray ? arraySizes[0] : 1;
713*8975f5c5SAndroid Build Coastguard Worker
714*8975f5c5SAndroid Build Coastguard Worker for (GLuint arrayIndex = 0; arrayIndex < arraySize; ++arrayIndex)
715*8975f5c5SAndroid Build Coastguard Worker {
716*8975f5c5SAndroid Build Coastguard Worker const GLuint effectiveArrayIndex = isArray ? arrayIndex : GL_INVALID_INDEX;
717*8975f5c5SAndroid Build Coastguard Worker for (GLuint fieldIndex = 0; fieldIndex < varying.fields.size(); ++fieldIndex)
718*8975f5c5SAndroid Build Coastguard Worker {
719*8975f5c5SAndroid Build Coastguard Worker const sh::ShaderVariable &fieldVarying = varying.fields[fieldIndex];
720*8975f5c5SAndroid Build Coastguard Worker if (ShouldSkipPackedVarying(fieldVarying, packMode))
721*8975f5c5SAndroid Build Coastguard Worker {
722*8975f5c5SAndroid Build Coastguard Worker continue;
723*8975f5c5SAndroid Build Coastguard Worker }
724*8975f5c5SAndroid Build Coastguard Worker
725*8975f5c5SAndroid Build Coastguard Worker if (fieldVarying.isStruct())
726*8975f5c5SAndroid Build Coastguard Worker {
727*8975f5c5SAndroid Build Coastguard Worker if (fieldVarying.isArray())
728*8975f5c5SAndroid Build Coastguard Worker {
729*8975f5c5SAndroid Build Coastguard Worker unsigned int structFieldArraySize = fieldVarying.arraySizes[0];
730*8975f5c5SAndroid Build Coastguard Worker for (unsigned int fieldArrayIndex = 0;
731*8975f5c5SAndroid Build Coastguard Worker fieldArrayIndex < structFieldArraySize; ++fieldArrayIndex)
732*8975f5c5SAndroid Build Coastguard Worker {
733*8975f5c5SAndroid Build Coastguard Worker for (GLuint nestedIndex = 0; nestedIndex < fieldVarying.fields.size();
734*8975f5c5SAndroid Build Coastguard Worker nestedIndex++)
735*8975f5c5SAndroid Build Coastguard Worker {
736*8975f5c5SAndroid Build Coastguard Worker collectUserVaryingField(ref, effectiveArrayIndex, fieldIndex,
737*8975f5c5SAndroid Build Coastguard Worker nestedIndex, uniqueFullNames);
738*8975f5c5SAndroid Build Coastguard Worker }
739*8975f5c5SAndroid Build Coastguard Worker }
740*8975f5c5SAndroid Build Coastguard Worker }
741*8975f5c5SAndroid Build Coastguard Worker else
742*8975f5c5SAndroid Build Coastguard Worker {
743*8975f5c5SAndroid Build Coastguard Worker for (GLuint nestedIndex = 0; nestedIndex < fieldVarying.fields.size();
744*8975f5c5SAndroid Build Coastguard Worker nestedIndex++)
745*8975f5c5SAndroid Build Coastguard Worker {
746*8975f5c5SAndroid Build Coastguard Worker collectUserVaryingField(ref, effectiveArrayIndex, fieldIndex,
747*8975f5c5SAndroid Build Coastguard Worker nestedIndex, uniqueFullNames);
748*8975f5c5SAndroid Build Coastguard Worker }
749*8975f5c5SAndroid Build Coastguard Worker }
750*8975f5c5SAndroid Build Coastguard Worker }
751*8975f5c5SAndroid Build Coastguard Worker else
752*8975f5c5SAndroid Build Coastguard Worker {
753*8975f5c5SAndroid Build Coastguard Worker collectUserVaryingField(ref, effectiveArrayIndex, fieldIndex, GL_INVALID_INDEX,
754*8975f5c5SAndroid Build Coastguard Worker uniqueFullNames);
755*8975f5c5SAndroid Build Coastguard Worker }
756*8975f5c5SAndroid Build Coastguard Worker }
757*8975f5c5SAndroid Build Coastguard Worker }
758*8975f5c5SAndroid Build Coastguard Worker if (input)
759*8975f5c5SAndroid Build Coastguard Worker {
760*8975f5c5SAndroid Build Coastguard Worker (*uniqueFullNames)[ref.frontShaderStage].insert(input->name);
761*8975f5c5SAndroid Build Coastguard Worker if (input->isShaderIOBlock)
762*8975f5c5SAndroid Build Coastguard Worker {
763*8975f5c5SAndroid Build Coastguard Worker (*uniqueFullNames)[ref.frontShaderStage].insert(input->structOrBlockName);
764*8975f5c5SAndroid Build Coastguard Worker }
765*8975f5c5SAndroid Build Coastguard Worker }
766*8975f5c5SAndroid Build Coastguard Worker if (output)
767*8975f5c5SAndroid Build Coastguard Worker {
768*8975f5c5SAndroid Build Coastguard Worker (*uniqueFullNames)[ref.backShaderStage].insert(output->name);
769*8975f5c5SAndroid Build Coastguard Worker }
770*8975f5c5SAndroid Build Coastguard Worker }
771*8975f5c5SAndroid Build Coastguard Worker else
772*8975f5c5SAndroid Build Coastguard Worker {
773*8975f5c5SAndroid Build Coastguard Worker collectUserVarying(ref, uniqueFullNames);
774*8975f5c5SAndroid Build Coastguard Worker }
775*8975f5c5SAndroid Build Coastguard Worker }
776*8975f5c5SAndroid Build Coastguard Worker
collectTFVarying(const std::string & tfVarying,const ProgramVaryingRef & ref,VaryingUniqueFullNames * uniqueFullNames)777*8975f5c5SAndroid Build Coastguard Worker void VaryingPacking::collectTFVarying(const std::string &tfVarying,
778*8975f5c5SAndroid Build Coastguard Worker const ProgramVaryingRef &ref,
779*8975f5c5SAndroid Build Coastguard Worker VaryingUniqueFullNames *uniqueFullNames)
780*8975f5c5SAndroid Build Coastguard Worker {
781*8975f5c5SAndroid Build Coastguard Worker const sh::ShaderVariable *input = ref.frontShader;
782*8975f5c5SAndroid Build Coastguard Worker
783*8975f5c5SAndroid Build Coastguard Worker std::vector<unsigned int> subscripts;
784*8975f5c5SAndroid Build Coastguard Worker std::string baseName = ParseResourceName(tfVarying, &subscripts);
785*8975f5c5SAndroid Build Coastguard Worker
786*8975f5c5SAndroid Build Coastguard Worker // Already packed as active varying.
787*8975f5c5SAndroid Build Coastguard Worker if ((*uniqueFullNames)[ref.frontShaderStage].count(tfVarying) > 0 ||
788*8975f5c5SAndroid Build Coastguard Worker (*uniqueFullNames)[ref.frontShaderStage].count(baseName) > 0 ||
789*8975f5c5SAndroid Build Coastguard Worker (input->isShaderIOBlock &&
790*8975f5c5SAndroid Build Coastguard Worker (*uniqueFullNames)[ref.frontShaderStage].count(input->structOrBlockName) > 0))
791*8975f5c5SAndroid Build Coastguard Worker {
792*8975f5c5SAndroid Build Coastguard Worker return;
793*8975f5c5SAndroid Build Coastguard Worker }
794*8975f5c5SAndroid Build Coastguard Worker
795*8975f5c5SAndroid Build Coastguard Worker if (input->isStruct())
796*8975f5c5SAndroid Build Coastguard Worker {
797*8975f5c5SAndroid Build Coastguard Worker GLuint fieldIndex = 0;
798*8975f5c5SAndroid Build Coastguard Worker const sh::ShaderVariable *field = input->findField(tfVarying, &fieldIndex);
799*8975f5c5SAndroid Build Coastguard Worker if (field != nullptr)
800*8975f5c5SAndroid Build Coastguard Worker {
801*8975f5c5SAndroid Build Coastguard Worker ASSERT(input->isShaderIOBlock || (!field->isStruct() && !field->isArray()));
802*8975f5c5SAndroid Build Coastguard Worker
803*8975f5c5SAndroid Build Coastguard Worker // If it's an I/O block whose member is being captured, pack every member of the
804*8975f5c5SAndroid Build Coastguard Worker // block. Currently, we pack either all or none of an I/O block.
805*8975f5c5SAndroid Build Coastguard Worker if (input->isShaderIOBlock)
806*8975f5c5SAndroid Build Coastguard Worker {
807*8975f5c5SAndroid Build Coastguard Worker for (fieldIndex = 0; fieldIndex < input->fields.size(); ++fieldIndex)
808*8975f5c5SAndroid Build Coastguard Worker {
809*8975f5c5SAndroid Build Coastguard Worker if (input->fields[fieldIndex].isStruct())
810*8975f5c5SAndroid Build Coastguard Worker {
811*8975f5c5SAndroid Build Coastguard Worker
812*8975f5c5SAndroid Build Coastguard Worker for (GLuint nestedIndex = 0;
813*8975f5c5SAndroid Build Coastguard Worker nestedIndex < input->fields[fieldIndex].fields.size(); nestedIndex++)
814*8975f5c5SAndroid Build Coastguard Worker {
815*8975f5c5SAndroid Build Coastguard Worker collectUserVaryingFieldTF(ref, input->fields[fieldIndex], fieldIndex,
816*8975f5c5SAndroid Build Coastguard Worker nestedIndex);
817*8975f5c5SAndroid Build Coastguard Worker }
818*8975f5c5SAndroid Build Coastguard Worker }
819*8975f5c5SAndroid Build Coastguard Worker else
820*8975f5c5SAndroid Build Coastguard Worker {
821*8975f5c5SAndroid Build Coastguard Worker collectUserVaryingFieldTF(ref, input->fields[fieldIndex], fieldIndex,
822*8975f5c5SAndroid Build Coastguard Worker GL_INVALID_INDEX);
823*8975f5c5SAndroid Build Coastguard Worker }
824*8975f5c5SAndroid Build Coastguard Worker }
825*8975f5c5SAndroid Build Coastguard Worker
826*8975f5c5SAndroid Build Coastguard Worker (*uniqueFullNames)[ref.frontShaderStage].insert(input->structOrBlockName);
827*8975f5c5SAndroid Build Coastguard Worker }
828*8975f5c5SAndroid Build Coastguard Worker else
829*8975f5c5SAndroid Build Coastguard Worker {
830*8975f5c5SAndroid Build Coastguard Worker collectUserVaryingFieldTF(ref, *field, fieldIndex, GL_INVALID_INDEX);
831*8975f5c5SAndroid Build Coastguard Worker }
832*8975f5c5SAndroid Build Coastguard Worker (*uniqueFullNames)[ref.frontShaderStage].insert(tfVarying);
833*8975f5c5SAndroid Build Coastguard Worker (*uniqueFullNames)[ref.frontShaderStage].insert(input->name);
834*8975f5c5SAndroid Build Coastguard Worker }
835*8975f5c5SAndroid Build Coastguard Worker }
836*8975f5c5SAndroid Build Coastguard Worker // Array as a whole and array element conflict has already been checked in
837*8975f5c5SAndroid Build Coastguard Worker // linkValidateTransformFeedback.
838*8975f5c5SAndroid Build Coastguard Worker else if (baseName == input->name)
839*8975f5c5SAndroid Build Coastguard Worker {
840*8975f5c5SAndroid Build Coastguard Worker size_t subscript = GL_INVALID_INDEX;
841*8975f5c5SAndroid Build Coastguard Worker if (!subscripts.empty())
842*8975f5c5SAndroid Build Coastguard Worker {
843*8975f5c5SAndroid Build Coastguard Worker subscript = subscripts.back();
844*8975f5c5SAndroid Build Coastguard Worker }
845*8975f5c5SAndroid Build Coastguard Worker
846*8975f5c5SAndroid Build Coastguard Worker // only pack varyings that are not builtins.
847*8975f5c5SAndroid Build Coastguard Worker if (tfVarying.compare(0, 3, "gl_") != 0)
848*8975f5c5SAndroid Build Coastguard Worker {
849*8975f5c5SAndroid Build Coastguard Worker collectUserVaryingTF(ref, subscript);
850*8975f5c5SAndroid Build Coastguard Worker (*uniqueFullNames)[ref.frontShaderStage].insert(tfVarying);
851*8975f5c5SAndroid Build Coastguard Worker }
852*8975f5c5SAndroid Build Coastguard Worker }
853*8975f5c5SAndroid Build Coastguard Worker }
854*8975f5c5SAndroid Build Coastguard Worker
collectAndPackUserVaryings(gl::InfoLog & infoLog,GLint maxVaryingVectors,PackMode packMode,ShaderType frontShaderStage,ShaderType backShaderStage,const ProgramMergedVaryings & mergedVaryings,const std::vector<std::string> & tfVaryings,const bool isSeparableProgram)855*8975f5c5SAndroid Build Coastguard Worker bool VaryingPacking::collectAndPackUserVaryings(gl::InfoLog &infoLog,
856*8975f5c5SAndroid Build Coastguard Worker GLint maxVaryingVectors,
857*8975f5c5SAndroid Build Coastguard Worker PackMode packMode,
858*8975f5c5SAndroid Build Coastguard Worker ShaderType frontShaderStage,
859*8975f5c5SAndroid Build Coastguard Worker ShaderType backShaderStage,
860*8975f5c5SAndroid Build Coastguard Worker const ProgramMergedVaryings &mergedVaryings,
861*8975f5c5SAndroid Build Coastguard Worker const std::vector<std::string> &tfVaryings,
862*8975f5c5SAndroid Build Coastguard Worker const bool isSeparableProgram)
863*8975f5c5SAndroid Build Coastguard Worker {
864*8975f5c5SAndroid Build Coastguard Worker VaryingUniqueFullNames uniqueFullNames;
865*8975f5c5SAndroid Build Coastguard Worker
866*8975f5c5SAndroid Build Coastguard Worker reset();
867*8975f5c5SAndroid Build Coastguard Worker
868*8975f5c5SAndroid Build Coastguard Worker for (const ProgramVaryingRef &ref : mergedVaryings)
869*8975f5c5SAndroid Build Coastguard Worker {
870*8975f5c5SAndroid Build Coastguard Worker const sh::ShaderVariable *input = ref.frontShader;
871*8975f5c5SAndroid Build Coastguard Worker const sh::ShaderVariable *output = ref.backShader;
872*8975f5c5SAndroid Build Coastguard Worker
873*8975f5c5SAndroid Build Coastguard Worker if ((input && ref.frontShaderStage != frontShaderStage) ||
874*8975f5c5SAndroid Build Coastguard Worker (output && ref.backShaderStage != backShaderStage))
875*8975f5c5SAndroid Build Coastguard Worker {
876*8975f5c5SAndroid Build Coastguard Worker continue;
877*8975f5c5SAndroid Build Coastguard Worker }
878*8975f5c5SAndroid Build Coastguard Worker
879*8975f5c5SAndroid Build Coastguard Worker const bool isActiveBuiltInInput = input && input->isBuiltIn() && input->active;
880*8975f5c5SAndroid Build Coastguard Worker const bool isActiveBuiltInOutput = output && output->isBuiltIn() && output->active;
881*8975f5c5SAndroid Build Coastguard Worker
882*8975f5c5SAndroid Build Coastguard Worker if (isActiveBuiltInInput)
883*8975f5c5SAndroid Build Coastguard Worker {
884*8975f5c5SAndroid Build Coastguard Worker SetActivePerVertexMembers(input, &mOutputPerVertexActiveMembers[frontShaderStage]);
885*8975f5c5SAndroid Build Coastguard Worker }
886*8975f5c5SAndroid Build Coastguard Worker
887*8975f5c5SAndroid Build Coastguard Worker // Only pack statically used varyings that have a matched input or output, plus special
888*8975f5c5SAndroid Build Coastguard Worker // builtins. Note that we pack all statically used user-defined varyings even if they are
889*8975f5c5SAndroid Build Coastguard Worker // not active. GLES specs are a bit vague on whether it's allowed to only pack active
890*8975f5c5SAndroid Build Coastguard Worker // varyings, though GLES 3.1 spec section 11.1.2.1 says that "device-dependent
891*8975f5c5SAndroid Build Coastguard Worker // optimizations" may be used to make vertex shader outputs fit.
892*8975f5c5SAndroid Build Coastguard Worker //
893*8975f5c5SAndroid Build Coastguard Worker // When separable programs are linked, varyings at the separable program's boundary are
894*8975f5c5SAndroid Build Coastguard Worker // treated as active. See section 7.4.1 in
895*8975f5c5SAndroid Build Coastguard Worker // https://www.khronos.org/registry/OpenGL/specs/es/3.2/es_spec_3.2.pdf
896*8975f5c5SAndroid Build Coastguard Worker bool matchedInputOutputStaticUse = (input && output && output->staticUse);
897*8975f5c5SAndroid Build Coastguard Worker bool activeBuiltIn = (isActiveBuiltInInput || isActiveBuiltInOutput);
898*8975f5c5SAndroid Build Coastguard Worker
899*8975f5c5SAndroid Build Coastguard Worker // Output variable in TCS can be read as input in another invocation by barrier.
900*8975f5c5SAndroid Build Coastguard Worker // See section 11.2.1.2.4 Tessellation Control Shader Execution Order in OpenGL ES 3.2.
901*8975f5c5SAndroid Build Coastguard Worker bool staticUseInTCS =
902*8975f5c5SAndroid Build Coastguard Worker (input && input->staticUse && ref.frontShaderStage == ShaderType::TessControl);
903*8975f5c5SAndroid Build Coastguard Worker
904*8975f5c5SAndroid Build Coastguard Worker // Separable program requirements
905*8975f5c5SAndroid Build Coastguard Worker bool separableActiveInput = (input && (input->active || !output));
906*8975f5c5SAndroid Build Coastguard Worker bool separableActiveOutput = (output && (output->active || !input));
907*8975f5c5SAndroid Build Coastguard Worker bool separableActiveVarying =
908*8975f5c5SAndroid Build Coastguard Worker (isSeparableProgram && (separableActiveInput || separableActiveOutput));
909*8975f5c5SAndroid Build Coastguard Worker
910*8975f5c5SAndroid Build Coastguard Worker if (matchedInputOutputStaticUse || activeBuiltIn || separableActiveVarying ||
911*8975f5c5SAndroid Build Coastguard Worker staticUseInTCS)
912*8975f5c5SAndroid Build Coastguard Worker {
913*8975f5c5SAndroid Build Coastguard Worker const sh::ShaderVariable *varying = output ? output : input;
914*8975f5c5SAndroid Build Coastguard Worker
915*8975f5c5SAndroid Build Coastguard Worker if (!ShouldSkipPackedVarying(*varying, packMode))
916*8975f5c5SAndroid Build Coastguard Worker {
917*8975f5c5SAndroid Build Coastguard Worker collectVarying(*varying, ref, packMode, &uniqueFullNames);
918*8975f5c5SAndroid Build Coastguard Worker continue;
919*8975f5c5SAndroid Build Coastguard Worker }
920*8975f5c5SAndroid Build Coastguard Worker }
921*8975f5c5SAndroid Build Coastguard Worker
922*8975f5c5SAndroid Build Coastguard Worker // If the varying is not used in the input, we know it is inactive, unless it's a separable
923*8975f5c5SAndroid Build Coastguard Worker // program, in which case the input shader may not exist in this program.
924*8975f5c5SAndroid Build Coastguard Worker if (!input && !isSeparableProgram)
925*8975f5c5SAndroid Build Coastguard Worker {
926*8975f5c5SAndroid Build Coastguard Worker if (!output->isBuiltIn() && output->id != 0)
927*8975f5c5SAndroid Build Coastguard Worker {
928*8975f5c5SAndroid Build Coastguard Worker mInactiveVaryingIds[ref.backShaderStage].push_back(output->id);
929*8975f5c5SAndroid Build Coastguard Worker }
930*8975f5c5SAndroid Build Coastguard Worker continue;
931*8975f5c5SAndroid Build Coastguard Worker }
932*8975f5c5SAndroid Build Coastguard Worker
933*8975f5c5SAndroid Build Coastguard Worker // Keep Transform FB varyings in the merged list always.
934*8975f5c5SAndroid Build Coastguard Worker for (const std::string &tfVarying : tfVaryings)
935*8975f5c5SAndroid Build Coastguard Worker {
936*8975f5c5SAndroid Build Coastguard Worker collectTFVarying(tfVarying, ref, &uniqueFullNames);
937*8975f5c5SAndroid Build Coastguard Worker }
938*8975f5c5SAndroid Build Coastguard Worker
939*8975f5c5SAndroid Build Coastguard Worker if (input && !input->isBuiltIn())
940*8975f5c5SAndroid Build Coastguard Worker {
941*8975f5c5SAndroid Build Coastguard Worker const std::string &name =
942*8975f5c5SAndroid Build Coastguard Worker input->isShaderIOBlock ? input->structOrBlockName : input->name;
943*8975f5c5SAndroid Build Coastguard Worker if (uniqueFullNames[ref.frontShaderStage].count(name) == 0 && input->id != 0)
944*8975f5c5SAndroid Build Coastguard Worker {
945*8975f5c5SAndroid Build Coastguard Worker mInactiveVaryingIds[ref.frontShaderStage].push_back(input->id);
946*8975f5c5SAndroid Build Coastguard Worker }
947*8975f5c5SAndroid Build Coastguard Worker }
948*8975f5c5SAndroid Build Coastguard Worker if (output && !output->isBuiltIn())
949*8975f5c5SAndroid Build Coastguard Worker {
950*8975f5c5SAndroid Build Coastguard Worker const std::string &name =
951*8975f5c5SAndroid Build Coastguard Worker output->isShaderIOBlock ? output->structOrBlockName : output->name;
952*8975f5c5SAndroid Build Coastguard Worker if (uniqueFullNames[ref.backShaderStage].count(name) == 0 && output->id != 0)
953*8975f5c5SAndroid Build Coastguard Worker {
954*8975f5c5SAndroid Build Coastguard Worker mInactiveVaryingIds[ref.backShaderStage].push_back(output->id);
955*8975f5c5SAndroid Build Coastguard Worker }
956*8975f5c5SAndroid Build Coastguard Worker }
957*8975f5c5SAndroid Build Coastguard Worker }
958*8975f5c5SAndroid Build Coastguard Worker
959*8975f5c5SAndroid Build Coastguard Worker std::sort(mPackedVaryings.begin(), mPackedVaryings.end(), ComparePackedVarying);
960*8975f5c5SAndroid Build Coastguard Worker
961*8975f5c5SAndroid Build Coastguard Worker return packUserVaryings(infoLog, maxVaryingVectors, packMode, mPackedVaryings);
962*8975f5c5SAndroid Build Coastguard Worker }
963*8975f5c5SAndroid Build Coastguard Worker
964*8975f5c5SAndroid Build Coastguard Worker // See comment on packVarying.
packUserVaryings(gl::InfoLog & infoLog,GLint maxVaryingVectors,PackMode packMode,const std::vector<PackedVarying> & packedVaryings)965*8975f5c5SAndroid Build Coastguard Worker bool VaryingPacking::packUserVaryings(gl::InfoLog &infoLog,
966*8975f5c5SAndroid Build Coastguard Worker GLint maxVaryingVectors,
967*8975f5c5SAndroid Build Coastguard Worker PackMode packMode,
968*8975f5c5SAndroid Build Coastguard Worker const std::vector<PackedVarying> &packedVaryings)
969*8975f5c5SAndroid Build Coastguard Worker {
970*8975f5c5SAndroid Build Coastguard Worker clearRegisterMap();
971*8975f5c5SAndroid Build Coastguard Worker mRegisterMap.resize(maxVaryingVectors);
972*8975f5c5SAndroid Build Coastguard Worker
973*8975f5c5SAndroid Build Coastguard Worker // "Variables are packed into the registers one at a time so that they each occupy a contiguous
974*8975f5c5SAndroid Build Coastguard Worker // subrectangle. No splitting of variables is permitted."
975*8975f5c5SAndroid Build Coastguard Worker for (const PackedVarying &packedVarying : packedVaryings)
976*8975f5c5SAndroid Build Coastguard Worker {
977*8975f5c5SAndroid Build Coastguard Worker if (!packVaryingIntoRegisterMap(packMode, packedVarying))
978*8975f5c5SAndroid Build Coastguard Worker {
979*8975f5c5SAndroid Build Coastguard Worker ShaderType eitherStage = packedVarying.frontVarying.varying
980*8975f5c5SAndroid Build Coastguard Worker ? packedVarying.frontVarying.stage
981*8975f5c5SAndroid Build Coastguard Worker : packedVarying.backVarying.stage;
982*8975f5c5SAndroid Build Coastguard Worker infoLog << "Could not pack varying " << packedVarying.fullName(eitherStage);
983*8975f5c5SAndroid Build Coastguard Worker
984*8975f5c5SAndroid Build Coastguard Worker // TODO(jmadill): Implement more sophisticated component packing in D3D9.
985*8975f5c5SAndroid Build Coastguard Worker if (packMode == PackMode::ANGLE_NON_CONFORMANT_D3D9)
986*8975f5c5SAndroid Build Coastguard Worker {
987*8975f5c5SAndroid Build Coastguard Worker infoLog << "Note: Additional non-conformant packing restrictions are enforced on "
988*8975f5c5SAndroid Build Coastguard Worker "D3D9.";
989*8975f5c5SAndroid Build Coastguard Worker }
990*8975f5c5SAndroid Build Coastguard Worker
991*8975f5c5SAndroid Build Coastguard Worker return false;
992*8975f5c5SAndroid Build Coastguard Worker }
993*8975f5c5SAndroid Build Coastguard Worker }
994*8975f5c5SAndroid Build Coastguard Worker
995*8975f5c5SAndroid Build Coastguard Worker // Sort the packed register list
996*8975f5c5SAndroid Build Coastguard Worker std::sort(mRegisterList.begin(), mRegisterList.end());
997*8975f5c5SAndroid Build Coastguard Worker
998*8975f5c5SAndroid Build Coastguard Worker return true;
999*8975f5c5SAndroid Build Coastguard Worker }
1000*8975f5c5SAndroid Build Coastguard Worker
1001*8975f5c5SAndroid Build Coastguard Worker // ProgramVaryingPacking implementation.
1002*8975f5c5SAndroid Build Coastguard Worker ProgramVaryingPacking::ProgramVaryingPacking() = default;
1003*8975f5c5SAndroid Build Coastguard Worker
1004*8975f5c5SAndroid Build Coastguard Worker ProgramVaryingPacking::~ProgramVaryingPacking() = default;
1005*8975f5c5SAndroid Build Coastguard Worker
getInputPacking(ShaderType backShaderStage) const1006*8975f5c5SAndroid Build Coastguard Worker const VaryingPacking &ProgramVaryingPacking::getInputPacking(ShaderType backShaderStage) const
1007*8975f5c5SAndroid Build Coastguard Worker {
1008*8975f5c5SAndroid Build Coastguard Worker ShaderType frontShaderStage = mBackToFrontStageMap[backShaderStage];
1009*8975f5c5SAndroid Build Coastguard Worker
1010*8975f5c5SAndroid Build Coastguard Worker // If there's a missing shader stage, return the compute shader packing which is always empty.
1011*8975f5c5SAndroid Build Coastguard Worker if (frontShaderStage == ShaderType::InvalidEnum)
1012*8975f5c5SAndroid Build Coastguard Worker {
1013*8975f5c5SAndroid Build Coastguard Worker ASSERT(mVaryingPackings[ShaderType::Compute].getMaxSemanticIndex() == 0);
1014*8975f5c5SAndroid Build Coastguard Worker return mVaryingPackings[ShaderType::Compute];
1015*8975f5c5SAndroid Build Coastguard Worker }
1016*8975f5c5SAndroid Build Coastguard Worker
1017*8975f5c5SAndroid Build Coastguard Worker return mVaryingPackings[frontShaderStage];
1018*8975f5c5SAndroid Build Coastguard Worker }
1019*8975f5c5SAndroid Build Coastguard Worker
getOutputPacking(ShaderType frontShaderStage) const1020*8975f5c5SAndroid Build Coastguard Worker const VaryingPacking &ProgramVaryingPacking::getOutputPacking(ShaderType frontShaderStage) const
1021*8975f5c5SAndroid Build Coastguard Worker {
1022*8975f5c5SAndroid Build Coastguard Worker return mVaryingPackings[frontShaderStage];
1023*8975f5c5SAndroid Build Coastguard Worker }
1024*8975f5c5SAndroid Build Coastguard Worker
collectAndPackUserVaryings(InfoLog & infoLog,const Caps & caps,PackMode packMode,const ShaderBitSet & activeShadersMask,const ProgramMergedVaryings & mergedVaryings,const std::vector<std::string> & tfVaryings,bool isSeparableProgram)1025*8975f5c5SAndroid Build Coastguard Worker bool ProgramVaryingPacking::collectAndPackUserVaryings(InfoLog &infoLog,
1026*8975f5c5SAndroid Build Coastguard Worker const Caps &caps,
1027*8975f5c5SAndroid Build Coastguard Worker PackMode packMode,
1028*8975f5c5SAndroid Build Coastguard Worker const ShaderBitSet &activeShadersMask,
1029*8975f5c5SAndroid Build Coastguard Worker const ProgramMergedVaryings &mergedVaryings,
1030*8975f5c5SAndroid Build Coastguard Worker const std::vector<std::string> &tfVaryings,
1031*8975f5c5SAndroid Build Coastguard Worker bool isSeparableProgram)
1032*8975f5c5SAndroid Build Coastguard Worker {
1033*8975f5c5SAndroid Build Coastguard Worker mBackToFrontStageMap.fill(ShaderType::InvalidEnum);
1034*8975f5c5SAndroid Build Coastguard Worker
1035*8975f5c5SAndroid Build Coastguard Worker ShaderBitSet activeShaders = activeShadersMask;
1036*8975f5c5SAndroid Build Coastguard Worker
1037*8975f5c5SAndroid Build Coastguard Worker ASSERT(activeShaders.any());
1038*8975f5c5SAndroid Build Coastguard Worker ShaderType frontShaderStage = activeShaders.first();
1039*8975f5c5SAndroid Build Coastguard Worker activeShaders[frontShaderStage] = false;
1040*8975f5c5SAndroid Build Coastguard Worker
1041*8975f5c5SAndroid Build Coastguard Worker // Special case for start-after-vertex.
1042*8975f5c5SAndroid Build Coastguard Worker if (frontShaderStage != ShaderType::Vertex)
1043*8975f5c5SAndroid Build Coastguard Worker {
1044*8975f5c5SAndroid Build Coastguard Worker ShaderType emulatedFrontShaderStage = ShaderType::Vertex;
1045*8975f5c5SAndroid Build Coastguard Worker ShaderType backShaderStage = frontShaderStage;
1046*8975f5c5SAndroid Build Coastguard Worker
1047*8975f5c5SAndroid Build Coastguard Worker if (!mVaryingPackings[emulatedFrontShaderStage].collectAndPackUserVaryings(
1048*8975f5c5SAndroid Build Coastguard Worker infoLog, GetMaxShaderInputVectors(caps, backShaderStage), packMode,
1049*8975f5c5SAndroid Build Coastguard Worker ShaderType::InvalidEnum, backShaderStage, mergedVaryings, tfVaryings,
1050*8975f5c5SAndroid Build Coastguard Worker isSeparableProgram))
1051*8975f5c5SAndroid Build Coastguard Worker {
1052*8975f5c5SAndroid Build Coastguard Worker return false;
1053*8975f5c5SAndroid Build Coastguard Worker }
1054*8975f5c5SAndroid Build Coastguard Worker mBackToFrontStageMap[backShaderStage] = emulatedFrontShaderStage;
1055*8975f5c5SAndroid Build Coastguard Worker }
1056*8975f5c5SAndroid Build Coastguard Worker
1057*8975f5c5SAndroid Build Coastguard Worker // Process input/output shader pairs.
1058*8975f5c5SAndroid Build Coastguard Worker for (ShaderType backShaderStage : activeShaders)
1059*8975f5c5SAndroid Build Coastguard Worker {
1060*8975f5c5SAndroid Build Coastguard Worker GLint maxVaryingVectors;
1061*8975f5c5SAndroid Build Coastguard Worker if (frontShaderStage == ShaderType::Vertex && backShaderStage == ShaderType::Fragment)
1062*8975f5c5SAndroid Build Coastguard Worker {
1063*8975f5c5SAndroid Build Coastguard Worker maxVaryingVectors = caps.maxVaryingVectors;
1064*8975f5c5SAndroid Build Coastguard Worker }
1065*8975f5c5SAndroid Build Coastguard Worker else
1066*8975f5c5SAndroid Build Coastguard Worker {
1067*8975f5c5SAndroid Build Coastguard Worker GLint outputVaryingsMax = GetMaxShaderOutputVectors(caps, frontShaderStage);
1068*8975f5c5SAndroid Build Coastguard Worker GLint inputVaryingsMax = GetMaxShaderInputVectors(caps, backShaderStage);
1069*8975f5c5SAndroid Build Coastguard Worker maxVaryingVectors = std::min(inputVaryingsMax, outputVaryingsMax);
1070*8975f5c5SAndroid Build Coastguard Worker }
1071*8975f5c5SAndroid Build Coastguard Worker
1072*8975f5c5SAndroid Build Coastguard Worker ASSERT(maxVaryingVectors > 0 && maxVaryingVectors < std::numeric_limits<GLint>::max());
1073*8975f5c5SAndroid Build Coastguard Worker
1074*8975f5c5SAndroid Build Coastguard Worker if (!mVaryingPackings[frontShaderStage].collectAndPackUserVaryings(
1075*8975f5c5SAndroid Build Coastguard Worker infoLog, maxVaryingVectors, packMode, frontShaderStage, backShaderStage,
1076*8975f5c5SAndroid Build Coastguard Worker mergedVaryings, tfVaryings, isSeparableProgram))
1077*8975f5c5SAndroid Build Coastguard Worker {
1078*8975f5c5SAndroid Build Coastguard Worker return false;
1079*8975f5c5SAndroid Build Coastguard Worker }
1080*8975f5c5SAndroid Build Coastguard Worker
1081*8975f5c5SAndroid Build Coastguard Worker mBackToFrontStageMap[backShaderStage] = frontShaderStage;
1082*8975f5c5SAndroid Build Coastguard Worker frontShaderStage = backShaderStage;
1083*8975f5c5SAndroid Build Coastguard Worker }
1084*8975f5c5SAndroid Build Coastguard Worker
1085*8975f5c5SAndroid Build Coastguard Worker // Special case for stop-before-fragment.
1086*8975f5c5SAndroid Build Coastguard Worker if (frontShaderStage != ShaderType::Fragment)
1087*8975f5c5SAndroid Build Coastguard Worker {
1088*8975f5c5SAndroid Build Coastguard Worker if (!mVaryingPackings[frontShaderStage].collectAndPackUserVaryings(
1089*8975f5c5SAndroid Build Coastguard Worker infoLog, GetMaxShaderOutputVectors(caps, frontShaderStage), packMode,
1090*8975f5c5SAndroid Build Coastguard Worker frontShaderStage, ShaderType::InvalidEnum, mergedVaryings, tfVaryings,
1091*8975f5c5SAndroid Build Coastguard Worker isSeparableProgram))
1092*8975f5c5SAndroid Build Coastguard Worker {
1093*8975f5c5SAndroid Build Coastguard Worker return false;
1094*8975f5c5SAndroid Build Coastguard Worker }
1095*8975f5c5SAndroid Build Coastguard Worker
1096*8975f5c5SAndroid Build Coastguard Worker ShaderType emulatedBackShaderStage = ShaderType::Fragment;
1097*8975f5c5SAndroid Build Coastguard Worker mBackToFrontStageMap[emulatedBackShaderStage] = frontShaderStage;
1098*8975f5c5SAndroid Build Coastguard Worker }
1099*8975f5c5SAndroid Build Coastguard Worker
1100*8975f5c5SAndroid Build Coastguard Worker return true;
1101*8975f5c5SAndroid Build Coastguard Worker }
1102*8975f5c5SAndroid Build Coastguard Worker
GetMergedVaryingsFromLinkingVariables(const LinkingVariables & linkingVariables)1103*8975f5c5SAndroid Build Coastguard Worker ProgramMergedVaryings GetMergedVaryingsFromLinkingVariables(
1104*8975f5c5SAndroid Build Coastguard Worker const LinkingVariables &linkingVariables)
1105*8975f5c5SAndroid Build Coastguard Worker {
1106*8975f5c5SAndroid Build Coastguard Worker ShaderType frontShaderType = ShaderType::InvalidEnum;
1107*8975f5c5SAndroid Build Coastguard Worker ProgramMergedVaryings merged;
1108*8975f5c5SAndroid Build Coastguard Worker
1109*8975f5c5SAndroid Build Coastguard Worker for (ShaderType backShaderType : kAllGraphicsShaderTypes)
1110*8975f5c5SAndroid Build Coastguard Worker {
1111*8975f5c5SAndroid Build Coastguard Worker if (!linkingVariables.isShaderStageUsedBitset[backShaderType])
1112*8975f5c5SAndroid Build Coastguard Worker {
1113*8975f5c5SAndroid Build Coastguard Worker continue;
1114*8975f5c5SAndroid Build Coastguard Worker }
1115*8975f5c5SAndroid Build Coastguard Worker const std::vector<sh::ShaderVariable> &backShaderOutputVaryings =
1116*8975f5c5SAndroid Build Coastguard Worker linkingVariables.outputVaryings[backShaderType];
1117*8975f5c5SAndroid Build Coastguard Worker const std::vector<sh::ShaderVariable> &backShaderInputVaryings =
1118*8975f5c5SAndroid Build Coastguard Worker linkingVariables.inputVaryings[backShaderType];
1119*8975f5c5SAndroid Build Coastguard Worker
1120*8975f5c5SAndroid Build Coastguard Worker // Add outputs. These are always unmatched since we walk shader stages sequentially.
1121*8975f5c5SAndroid Build Coastguard Worker for (const sh::ShaderVariable &frontVarying : backShaderOutputVaryings)
1122*8975f5c5SAndroid Build Coastguard Worker {
1123*8975f5c5SAndroid Build Coastguard Worker ProgramVaryingRef ref;
1124*8975f5c5SAndroid Build Coastguard Worker ref.frontShader = &frontVarying;
1125*8975f5c5SAndroid Build Coastguard Worker ref.frontShaderStage = backShaderType;
1126*8975f5c5SAndroid Build Coastguard Worker merged.push_back(ref);
1127*8975f5c5SAndroid Build Coastguard Worker }
1128*8975f5c5SAndroid Build Coastguard Worker
1129*8975f5c5SAndroid Build Coastguard Worker if (frontShaderType == ShaderType::InvalidEnum)
1130*8975f5c5SAndroid Build Coastguard Worker {
1131*8975f5c5SAndroid Build Coastguard Worker // If this is our first shader stage, and not a VS, we might have unmatched inputs.
1132*8975f5c5SAndroid Build Coastguard Worker for (const sh::ShaderVariable &backVarying : backShaderInputVaryings)
1133*8975f5c5SAndroid Build Coastguard Worker {
1134*8975f5c5SAndroid Build Coastguard Worker ProgramVaryingRef ref;
1135*8975f5c5SAndroid Build Coastguard Worker ref.backShader = &backVarying;
1136*8975f5c5SAndroid Build Coastguard Worker ref.backShaderStage = backShaderType;
1137*8975f5c5SAndroid Build Coastguard Worker merged.push_back(ref);
1138*8975f5c5SAndroid Build Coastguard Worker }
1139*8975f5c5SAndroid Build Coastguard Worker }
1140*8975f5c5SAndroid Build Coastguard Worker else
1141*8975f5c5SAndroid Build Coastguard Worker {
1142*8975f5c5SAndroid Build Coastguard Worker // Match inputs with the prior shader stage outputs.
1143*8975f5c5SAndroid Build Coastguard Worker for (const sh::ShaderVariable &backVarying : backShaderInputVaryings)
1144*8975f5c5SAndroid Build Coastguard Worker {
1145*8975f5c5SAndroid Build Coastguard Worker bool found = false;
1146*8975f5c5SAndroid Build Coastguard Worker for (ProgramVaryingRef &ref : merged)
1147*8975f5c5SAndroid Build Coastguard Worker {
1148*8975f5c5SAndroid Build Coastguard Worker if (ref.frontShader && ref.frontShaderStage == frontShaderType &&
1149*8975f5c5SAndroid Build Coastguard Worker InterfaceVariablesMatch(*ref.frontShader, backVarying))
1150*8975f5c5SAndroid Build Coastguard Worker {
1151*8975f5c5SAndroid Build Coastguard Worker ASSERT(ref.backShader == nullptr);
1152*8975f5c5SAndroid Build Coastguard Worker
1153*8975f5c5SAndroid Build Coastguard Worker ref.backShader = &backVarying;
1154*8975f5c5SAndroid Build Coastguard Worker ref.backShaderStage = backShaderType;
1155*8975f5c5SAndroid Build Coastguard Worker found = true;
1156*8975f5c5SAndroid Build Coastguard Worker break;
1157*8975f5c5SAndroid Build Coastguard Worker }
1158*8975f5c5SAndroid Build Coastguard Worker }
1159*8975f5c5SAndroid Build Coastguard Worker
1160*8975f5c5SAndroid Build Coastguard Worker // Some outputs are never matched, e.g. some builtin variables.
1161*8975f5c5SAndroid Build Coastguard Worker if (!found)
1162*8975f5c5SAndroid Build Coastguard Worker {
1163*8975f5c5SAndroid Build Coastguard Worker ProgramVaryingRef ref;
1164*8975f5c5SAndroid Build Coastguard Worker ref.backShader = &backVarying;
1165*8975f5c5SAndroid Build Coastguard Worker ref.backShaderStage = backShaderType;
1166*8975f5c5SAndroid Build Coastguard Worker merged.push_back(ref);
1167*8975f5c5SAndroid Build Coastguard Worker }
1168*8975f5c5SAndroid Build Coastguard Worker }
1169*8975f5c5SAndroid Build Coastguard Worker }
1170*8975f5c5SAndroid Build Coastguard Worker
1171*8975f5c5SAndroid Build Coastguard Worker // Save the current back shader to use as the next front shader.
1172*8975f5c5SAndroid Build Coastguard Worker frontShaderType = backShaderType;
1173*8975f5c5SAndroid Build Coastguard Worker }
1174*8975f5c5SAndroid Build Coastguard Worker
1175*8975f5c5SAndroid Build Coastguard Worker return merged;
1176*8975f5c5SAndroid Build Coastguard Worker }
1177*8975f5c5SAndroid Build Coastguard Worker } // namespace gl
1178