1 //
2 // Copyright 2015 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // VaryingPacking:
7 //   Class which describes a mapping from varyings to registers, according
8 //   to the spec, or using custom packing algorithms. We also keep a register
9 //   allocation list for the D3D renderer.
10 //
11 
12 #ifndef LIBANGLE_VARYINGPACKING_H_
13 #define LIBANGLE_VARYINGPACKING_H_
14 
15 #include <GLSLANG/ShaderVars.h>
16 
17 #include "angle_gl.h"
18 #include "common/angleutils.h"
19 #include "libANGLE/Program.h"
20 
21 namespace gl
22 {
23 class InfoLog;
24 
25 struct PackedVarying
26 {
PackedVaryingPackedVarying27     PackedVarying(const sh::ShaderVariable &varyingIn, sh::InterpolationType interpolationIn)
28         : PackedVarying(varyingIn, interpolationIn, "")
29     {
30     }
PackedVaryingPackedVarying31     PackedVarying(const sh::ShaderVariable &varyingIn,
32                   sh::InterpolationType interpolationIn,
33                   const std::string &parentStructNameIn)
34         : varying(&varyingIn),
35           vertexOnly(false),
36           interpolation(interpolationIn),
37           parentStructName(parentStructNameIn),
38           arrayIndex(GL_INVALID_INDEX)
39     {
40     }
41 
isStructFieldPackedVarying42     bool isStructField() const { return !parentStructName.empty(); }
43 
isArrayElementPackedVarying44     bool isArrayElement() const { return arrayIndex != GL_INVALID_INDEX; }
45 
nameWithArrayIndexPackedVarying46     std::string nameWithArrayIndex() const
47     {
48         std::stringstream fullNameStr;
49         fullNameStr << varying->name;
50         if (arrayIndex != GL_INVALID_INDEX)
51         {
52             fullNameStr << "[" << arrayIndex << "]";
53         }
54         return fullNameStr.str();
55     }
56 
57     const sh::ShaderVariable *varying;
58 
59     // Transform feedback varyings can be only referenced in the VS.
60     bool vertexOnly;
61 
62     // Cached so we can store sh::ShaderVariable to point to varying fields.
63     sh::InterpolationType interpolation;
64 
65     // Struct name
66     std::string parentStructName;
67 
68     GLuint arrayIndex;
69 };
70 
71 struct PackedVaryingRegister final
72 {
PackedVaryingRegisterfinal73     PackedVaryingRegister()
74         : packedVarying(nullptr),
75           varyingArrayIndex(0),
76           varyingRowIndex(0),
77           registerRow(0),
78           registerColumn(0)
79     {
80     }
81 
82     PackedVaryingRegister(const PackedVaryingRegister &) = default;
83     PackedVaryingRegister &operator=(const PackedVaryingRegister &) = default;
84 
85     bool operator<(const PackedVaryingRegister &other) const
86     {
87         return sortOrder() < other.sortOrder();
88     }
89 
sortOrderfinal90     unsigned int sortOrder() const
91     {
92         // TODO(jmadill): Handle interpolation types
93         return registerRow * 4 + registerColumn;
94     }
95 
isStructFieldfinal96     bool isStructField() const { return !structFieldName.empty(); }
97 
98     // Index to the array of varyings.
99     const PackedVarying *packedVarying;
100 
101     // The array element of the packed varying.
102     unsigned int varyingArrayIndex;
103 
104     // The row of the array element of the packed varying.
105     unsigned int varyingRowIndex;
106 
107     // The register row to which we've assigned this packed varying.
108     unsigned int registerRow;
109 
110     // The column of the register row into which we've packed this varying.
111     unsigned int registerColumn;
112 
113     // Assigned after packing
114     unsigned int semanticIndex;
115 
116     // Struct member this varying corresponds to.
117     std::string structFieldName;
118 };
119 
120 // Supported packing modes:
121 enum class PackMode
122 {
123     // We treat mat2 arrays as taking two full rows.
124     WEBGL_STRICT,
125 
126     // We allow mat2 to take a 2x2 chunk.
127     ANGLE_RELAXED,
128 };
129 
130 class VaryingPacking final : angle::NonCopyable
131 {
132   public:
133     VaryingPacking(GLuint maxVaryingVectors, PackMode packMode);
134     ~VaryingPacking();
135 
136     bool packUserVaryings(gl::InfoLog &infoLog,
137                           const std::vector<PackedVarying> &packedVaryings,
138                           const std::vector<std::string> &tfVaryings);
139 
140     bool collectAndPackUserVaryings(gl::InfoLog &infoLog,
141                                     const Program::MergedVaryings &mergedVaryings,
142                                     const std::vector<std::string> &tfVaryings);
143 
144     struct Register
145     {
RegisterRegister146         Register() { data[0] = data[1] = data[2] = data[3] = false; }
147 
148         bool &operator[](unsigned int index) { return data[index]; }
149         bool operator[](unsigned int index) const { return data[index]; }
150 
151         bool data[4];
152     };
153 
154     Register &operator[](unsigned int index) { return mRegisterMap[index]; }
155     const Register &operator[](unsigned int index) const { return mRegisterMap[index]; }
156 
getRegisterList()157     const std::vector<PackedVaryingRegister> &getRegisterList() const { return mRegisterList; }
getMaxSemanticIndex()158     unsigned int getMaxSemanticIndex() const
159     {
160         return static_cast<unsigned int>(mRegisterList.size());
161     }
162     unsigned int getRegisterCount() const;
getRegisterMapSize()163     size_t getRegisterMapSize() const { return mRegisterMap.size(); }
164 
165   private:
166     bool packVarying(const PackedVarying &packedVarying);
167     bool isFree(unsigned int registerRow,
168                 unsigned int registerColumn,
169                 unsigned int varyingRows,
170                 unsigned int varyingColumns) const;
171     void insert(unsigned int registerRow,
172                 unsigned int registerColumn,
173                 const PackedVarying &packedVarying);
174 
175     std::vector<Register> mRegisterMap;
176     std::vector<PackedVaryingRegister> mRegisterList;
177     std::vector<PackedVarying> mPackedVaryings;
178 
179     PackMode mPackMode;
180 };
181 
182 }  // namespace gl
183 
184 #endif  // LIBANGLE_VARYINGPACKING_H_
185