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/angletypes.h" 20 21 #include <map> 22 23 namespace gl 24 { 25 class InfoLog; 26 struct ProgramVaryingRef; 27 28 using ProgramMergedVaryings = std::vector<ProgramVaryingRef>; 29 30 // A varying can have different names between stages if matched by the location layout qualifier. 31 // Additionally, same name varyings could still be of two identical struct types with different 32 // names. This struct contains information on the varying in one of the two stages. PackedVarying 33 // will thus contain two copies of this along with common information, such as interpolation or 34 // field index. 35 struct VaryingInShaderRef : angle::NonCopyable 36 { 37 VaryingInShaderRef(ShaderType stageIn, const sh::ShaderVariable *varyingIn); 38 VaryingInShaderRef(VaryingInShaderRef &&other); 39 ~VaryingInShaderRef(); 40 41 VaryingInShaderRef &operator=(VaryingInShaderRef &&other); 42 43 const sh::ShaderVariable *varying; 44 45 ShaderType stage; 46 47 // Struct name 48 std::string parentStructName; 49 std::string parentStructMappedName; 50 }; 51 52 struct PackedVarying : angle::NonCopyable 53 { 54 // Throughout this file, the "front" stage refers to the stage that outputs the varying, and the 55 // "back" stage refers to the stage that takes the varying as input. Note that this struct 56 // contains linked varyings, which means both front and back stage varyings are valid, except 57 // for the following which may have only one valid stage. 58 // 59 // - transform-feedback-captured varyings 60 // - builtins 61 // - separable program stages, 62 // 63 PackedVarying(VaryingInShaderRef &&frontVaryingIn, 64 VaryingInShaderRef &&backVaryingIn, 65 sh::InterpolationType interpolationIn); 66 PackedVarying(VaryingInShaderRef &&frontVaryingIn, 67 VaryingInShaderRef &&backVaryingIn, 68 sh::InterpolationType interpolationIn, 69 GLuint fieldIndexIn); 70 PackedVarying(PackedVarying &&other); 71 ~PackedVarying(); 72 73 PackedVarying &operator=(PackedVarying &&other); 74 isStructFieldPackedVarying75 bool isStructField() const 76 { 77 return frontVarying.varying ? !frontVarying.parentStructName.empty() 78 : !backVarying.parentStructName.empty(); 79 } 80 isArrayElementPackedVarying81 bool isArrayElement() const { return arrayIndex != GL_INVALID_INDEX; } 82 83 // Return either front or back varying, whichever is available. Only used when the name of the 84 // varying is not important, but only the type is interesting. varyingPackedVarying85 const sh::ShaderVariable &varying() const 86 { 87 return frontVarying.varying ? *frontVarying.varying : *backVarying.varying; 88 } 89 fullNamePackedVarying90 std::string fullName(ShaderType stage) const 91 { 92 ASSERT(stage == frontVarying.stage || stage == backVarying.stage); 93 const VaryingInShaderRef &varying = 94 stage == frontVarying.stage ? frontVarying : backVarying; 95 96 std::stringstream fullNameStr; 97 if (isStructField()) 98 { 99 fullNameStr << varying.parentStructName << "."; 100 } 101 102 fullNameStr << varying.varying->name; 103 if (arrayIndex != GL_INVALID_INDEX) 104 { 105 fullNameStr << "[" << arrayIndex << "]"; 106 } 107 return fullNameStr.str(); 108 } 109 110 // Transform feedback varyings can be only referenced in the VS. vertexOnlyPackedVarying111 bool vertexOnly() const 112 { 113 return frontVarying.stage == ShaderType::Vertex && backVarying.varying == nullptr; 114 } 115 116 VaryingInShaderRef frontVarying; 117 VaryingInShaderRef backVarying; 118 119 // Cached so we can store sh::ShaderVariable to point to varying fields. 120 sh::InterpolationType interpolation; 121 122 GLuint arrayIndex; 123 124 // Field index in the struct. In Vulkan, this is used to assign a 125 // struct-typed varying location to the location of its first field. 126 GLuint fieldIndex; 127 }; 128 129 struct PackedVaryingRegister final 130 { PackedVaryingRegisterfinal131 PackedVaryingRegister() 132 : packedVarying(nullptr), 133 varyingArrayIndex(0), 134 varyingRowIndex(0), 135 registerRow(0), 136 registerColumn(0) 137 {} 138 139 PackedVaryingRegister(const PackedVaryingRegister &) = default; 140 PackedVaryingRegister &operator=(const PackedVaryingRegister &) = default; 141 142 bool operator<(const PackedVaryingRegister &other) const 143 { 144 return sortOrder() < other.sortOrder(); 145 } 146 sortOrderfinal147 unsigned int sortOrder() const 148 { 149 // TODO(jmadill): Handle interpolation types 150 return registerRow * 4 + registerColumn; 151 } 152 tfVaryingNamefinal153 std::string tfVaryingName() const 154 { 155 return packedVarying->fullName(packedVarying->frontVarying.stage); 156 } 157 158 // Index to the array of varyings. 159 const PackedVarying *packedVarying; 160 161 // The array element of the packed varying. 162 unsigned int varyingArrayIndex; 163 164 // The row of the array element of the packed varying. 165 unsigned int varyingRowIndex; 166 167 // The register row to which we've assigned this packed varying. 168 unsigned int registerRow; 169 170 // The column of the register row into which we've packed this varying. 171 unsigned int registerColumn; 172 }; 173 174 // Supported packing modes: 175 enum class PackMode 176 { 177 // We treat mat2 arrays as taking two full rows. 178 WEBGL_STRICT, 179 180 // We allow mat2 to take a 2x2 chunk. 181 ANGLE_RELAXED, 182 183 // Each varying takes a separate register. No register sharing. 184 ANGLE_NON_CONFORMANT_D3D9, 185 }; 186 187 class VaryingPacking final : angle::NonCopyable 188 { 189 public: 190 VaryingPacking(GLuint maxVaryingVectors, PackMode packMode); 191 ~VaryingPacking(); 192 193 bool packUserVaryings(gl::InfoLog &infoLog, const std::vector<PackedVarying> &packedVaryings); 194 195 bool collectAndPackUserVaryings(gl::InfoLog &infoLog, 196 const ProgramMergedVaryings &mergedVaryings, 197 const std::vector<std::string> &tfVaryings, 198 const bool isSeparableProgram); 199 200 struct Register 201 { RegisterRegister202 Register() { data[0] = data[1] = data[2] = data[3] = false; } 203 204 bool &operator[](unsigned int index) { return data[index]; } 205 bool operator[](unsigned int index) const { return data[index]; } 206 207 bool data[4]; 208 }; 209 210 Register &operator[](unsigned int index) { return mRegisterMap[index]; } 211 const Register &operator[](unsigned int index) const { return mRegisterMap[index]; } 212 getRegisterList()213 const std::vector<PackedVaryingRegister> &getRegisterList() const { return mRegisterList; } getMaxSemanticIndex()214 unsigned int getMaxSemanticIndex() const 215 { 216 return static_cast<unsigned int>(mRegisterList.size()); 217 } 218 getInactiveVaryingMappedNames()219 const ShaderMap<std::vector<std::string>> &getInactiveVaryingMappedNames() const 220 { 221 return mInactiveVaryingMappedNames; 222 } 223 224 void reset(); 225 226 private: 227 bool packVarying(const PackedVarying &packedVarying); 228 bool isFree(unsigned int registerRow, 229 unsigned int registerColumn, 230 unsigned int varyingRows, 231 unsigned int varyingColumns) const; 232 void insert(unsigned int registerRow, 233 unsigned int registerColumn, 234 const PackedVarying &packedVarying); 235 236 using VaryingUniqueFullNames = ShaderMap<std::set<std::string>>; 237 void packUserVarying(const ProgramVaryingRef &ref, VaryingUniqueFullNames *uniqueFullNames); 238 void packUserVaryingField(const ProgramVaryingRef &ref, 239 GLuint fieldIndex, 240 VaryingUniqueFullNames *uniqueFullNames); 241 void packUserVaryingTF(const ProgramVaryingRef &ref, size_t subscript); 242 void packUserVaryingFieldTF(const ProgramVaryingRef &ref, 243 const sh::ShaderVariable &field, 244 GLuint fieldIndex); 245 246 void clearRegisterMap(); 247 248 std::vector<Register> mRegisterMap; 249 std::vector<PackedVaryingRegister> mRegisterList; 250 std::vector<PackedVarying> mPackedVaryings; 251 ShaderMap<std::vector<std::string>> mInactiveVaryingMappedNames; 252 253 PackMode mPackMode; 254 }; 255 256 } // namespace gl 257 258 #endif // LIBANGLE_VARYINGPACKING_H_ 259