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