blocklayout.h (12022B)
1 // 2 // Copyright 2013 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 // blocklayout.h: 7 // Methods and classes related to uniform layout and packing in GLSL and HLSL. 8 // 9 10 #ifndef COMMON_BLOCKLAYOUT_H_ 11 #define COMMON_BLOCKLAYOUT_H_ 12 13 #include <cstddef> 14 #include <map> 15 #include <vector> 16 17 #include <GLSLANG/ShaderLang.h> 18 #include "angle_gl.h" 19 20 namespace sh 21 { 22 struct ShaderVariable; 23 struct InterfaceBlock; 24 25 struct BlockMemberInfo 26 { 27 constexpr BlockMemberInfo() = default; 28 29 constexpr BlockMemberInfo(int offset, int arrayStride, int matrixStride, bool isRowMajorMatrix) 30 : offset(offset), 31 arrayStride(arrayStride), 32 matrixStride(matrixStride), 33 isRowMajorMatrix(isRowMajorMatrix) 34 {} 35 36 constexpr BlockMemberInfo(int offset, 37 int arrayStride, 38 int matrixStride, 39 bool isRowMajorMatrix, 40 int topLevelArrayStride) 41 : offset(offset), 42 arrayStride(arrayStride), 43 matrixStride(matrixStride), 44 isRowMajorMatrix(isRowMajorMatrix), 45 topLevelArrayStride(topLevelArrayStride) 46 {} 47 48 // A single integer identifying the offset of an active variable. 49 int offset = -1; 50 51 // A single integer identifying the stride between array elements in an active variable. 52 int arrayStride = -1; 53 54 // A single integer identifying the stride between columns of a column-major matrix or rows of a 55 // row-major matrix. 56 int matrixStride = -1; 57 58 // A single integer identifying whether an active variable is a row-major matrix. 59 bool isRowMajorMatrix = false; 60 61 // A single integer identifying the number of active array elements of the top-level shader 62 // storage block member containing the active variable. 63 int topLevelArrayStride = -1; 64 }; 65 66 constexpr size_t ComponentAlignment(size_t numComponents) 67 { 68 return (numComponents == 3u ? 4u : numComponents); 69 } 70 71 constexpr BlockMemberInfo kDefaultBlockMemberInfo; 72 73 class BlockLayoutEncoder 74 { 75 public: 76 BlockLayoutEncoder(); 77 virtual ~BlockLayoutEncoder() {} 78 79 BlockMemberInfo encodeType(GLenum type, 80 const std::vector<unsigned int> &arraySizes, 81 bool isRowMajorMatrix); 82 // Advance the offset based on struct size and array dimensions. Size can be calculated with 83 // getShaderVariableSize() or equivalent. |enterAggregateType|/|exitAggregateType| is necessary 84 // around this call. 85 BlockMemberInfo encodeArrayOfPreEncodedStructs(size_t size, 86 const std::vector<unsigned int> &arraySizes); 87 88 size_t getCurrentOffset() const; 89 size_t getShaderVariableSize(const ShaderVariable &structVar, bool isRowMajor); 90 91 // Called when entering/exiting a structure variable. 92 virtual void enterAggregateType(const ShaderVariable &structVar) = 0; 93 virtual void exitAggregateType(const ShaderVariable &structVar) = 0; 94 95 static constexpr size_t kBytesPerComponent = 4u; 96 static constexpr unsigned int kComponentsPerRegister = 4u; 97 98 static size_t GetBlockRegister(const BlockMemberInfo &info); 99 static size_t GetBlockRegisterElement(const BlockMemberInfo &info); 100 101 protected: 102 void align(size_t baseAlignment); 103 104 virtual void getBlockLayoutInfo(GLenum type, 105 const std::vector<unsigned int> &arraySizes, 106 bool isRowMajorMatrix, 107 int *arrayStrideOut, 108 int *matrixStrideOut) = 0; 109 virtual void advanceOffset(GLenum type, 110 const std::vector<unsigned int> &arraySizes, 111 bool isRowMajorMatrix, 112 int arrayStride, 113 int matrixStride) = 0; 114 115 size_t mCurrentOffset; 116 }; 117 118 // Will return default values for everything. 119 class StubBlockEncoder : public BlockLayoutEncoder 120 { 121 public: 122 StubBlockEncoder() = default; 123 124 void enterAggregateType(const ShaderVariable &structVar) override {} 125 void exitAggregateType(const ShaderVariable &structVar) override {} 126 127 protected: 128 void getBlockLayoutInfo(GLenum type, 129 const std::vector<unsigned int> &arraySizes, 130 bool isRowMajorMatrix, 131 int *arrayStrideOut, 132 int *matrixStrideOut) override; 133 134 void advanceOffset(GLenum type, 135 const std::vector<unsigned int> &arraySizes, 136 bool isRowMajorMatrix, 137 int arrayStride, 138 int matrixStride) override 139 {} 140 }; 141 142 // Block layout according to the std140 block layout 143 // See "Standard Uniform Block Layout" in Section 2.11.6 of the OpenGL ES 3.0 specification 144 145 class Std140BlockEncoder : public BlockLayoutEncoder 146 { 147 public: 148 Std140BlockEncoder(); 149 150 void enterAggregateType(const ShaderVariable &structVar) override; 151 void exitAggregateType(const ShaderVariable &structVar) override; 152 153 protected: 154 void getBlockLayoutInfo(GLenum type, 155 const std::vector<unsigned int> &arraySizes, 156 bool isRowMajorMatrix, 157 int *arrayStrideOut, 158 int *matrixStrideOut) override; 159 void advanceOffset(GLenum type, 160 const std::vector<unsigned int> &arraySizes, 161 bool isRowMajorMatrix, 162 int arrayStride, 163 int matrixStride) override; 164 165 virtual size_t getBaseAlignment(const ShaderVariable &variable) const; 166 virtual size_t getTypeBaseAlignment(GLenum type, bool isRowMajorMatrix) const; 167 }; 168 169 class Std430BlockEncoder : public Std140BlockEncoder 170 { 171 public: 172 Std430BlockEncoder(); 173 174 protected: 175 size_t getBaseAlignment(const ShaderVariable &variable) const override; 176 size_t getTypeBaseAlignment(GLenum type, bool isRowMajorMatrix) const override; 177 }; 178 179 using BlockLayoutMap = std::map<std::string, BlockMemberInfo>; 180 181 void GetInterfaceBlockInfo(const std::vector<ShaderVariable> &fields, 182 const std::string &prefix, 183 BlockLayoutEncoder *encoder, 184 BlockLayoutMap *blockInfoOut); 185 186 // Used for laying out the default uniform block on the Vulkan backend. 187 void GetActiveUniformBlockInfo(const std::vector<ShaderVariable> &uniforms, 188 const std::string &prefix, 189 BlockLayoutEncoder *encoder, 190 BlockLayoutMap *blockInfoOut); 191 192 class ShaderVariableVisitor 193 { 194 public: 195 virtual ~ShaderVariableVisitor() {} 196 197 virtual void enterStruct(const ShaderVariable &structVar) {} 198 virtual void exitStruct(const ShaderVariable &structVar) {} 199 200 virtual void enterStructAccess(const ShaderVariable &structVar, bool isRowMajor) {} 201 virtual void exitStructAccess(const ShaderVariable &structVar, bool isRowMajor) {} 202 203 virtual void enterArray(const ShaderVariable &arrayVar) {} 204 virtual void exitArray(const ShaderVariable &arrayVar) {} 205 206 virtual void enterArrayElement(const ShaderVariable &arrayVar, unsigned int arrayElement) {} 207 virtual void exitArrayElement(const ShaderVariable &arrayVar, unsigned int arrayElement) {} 208 209 virtual void visitOpaqueObject(const sh::ShaderVariable &variable) {} 210 211 virtual void visitVariable(const ShaderVariable &variable, bool isRowMajor) = 0; 212 213 protected: 214 ShaderVariableVisitor() {} 215 }; 216 217 class VariableNameVisitor : public ShaderVariableVisitor 218 { 219 public: 220 VariableNameVisitor(const std::string &namePrefix, const std::string &mappedNamePrefix); 221 ~VariableNameVisitor() override; 222 223 void enterStruct(const ShaderVariable &structVar) override; 224 void exitStruct(const ShaderVariable &structVar) override; 225 void enterStructAccess(const ShaderVariable &structVar, bool isRowMajor) override; 226 void exitStructAccess(const ShaderVariable &structVar, bool isRowMajor) override; 227 void enterArray(const ShaderVariable &arrayVar) override; 228 void exitArray(const ShaderVariable &arrayVar) override; 229 void enterArrayElement(const ShaderVariable &arrayVar, unsigned int arrayElement) override; 230 void exitArrayElement(const ShaderVariable &arrayVar, unsigned int arrayElement) override; 231 232 protected: 233 virtual void visitNamedOpaqueObject(const sh::ShaderVariable &variable, 234 const std::string &name, 235 const std::string &mappedName, 236 const std::vector<unsigned int> &arraySizes) 237 {} 238 virtual void visitNamedVariable(const ShaderVariable &variable, 239 bool isRowMajor, 240 const std::string &name, 241 const std::string &mappedName, 242 const std::vector<unsigned int> &arraySizes) = 0; 243 244 std::string collapseNameStack() const; 245 std::string collapseMappedNameStack() const; 246 247 private: 248 void visitOpaqueObject(const sh::ShaderVariable &variable) final; 249 void visitVariable(const ShaderVariable &variable, bool isRowMajor) final; 250 251 std::vector<std::string> mNameStack; 252 std::vector<std::string> mMappedNameStack; 253 std::vector<unsigned int> mArraySizeStack; 254 }; 255 256 class BlockEncoderVisitor : public VariableNameVisitor 257 { 258 public: 259 BlockEncoderVisitor(const std::string &namePrefix, 260 const std::string &mappedNamePrefix, 261 BlockLayoutEncoder *encoder); 262 ~BlockEncoderVisitor() override; 263 264 void enterStructAccess(const ShaderVariable &structVar, bool isRowMajor) override; 265 void exitStructAccess(const ShaderVariable &structVar, bool isRowMajor) override; 266 void enterArrayElement(const ShaderVariable &arrayVar, unsigned int arrayElement) override; 267 void exitArrayElement(const ShaderVariable &arrayVar, unsigned int arrayElement) override; 268 269 void visitNamedVariable(const ShaderVariable &variable, 270 bool isRowMajor, 271 const std::string &name, 272 const std::string &mappedName, 273 const std::vector<unsigned int> &arraySizes) override; 274 275 virtual void encodeVariable(const ShaderVariable &variable, 276 const BlockMemberInfo &variableInfo, 277 const std::string &name, 278 const std::string &mappedName) 279 {} 280 281 protected: 282 int mTopLevelArraySize = 1; 283 int mTopLevelArrayStride = 0; 284 bool mIsTopLevelArrayStrideReady = true; 285 bool mSkipEnabled = false; 286 287 private: 288 BlockLayoutEncoder *mEncoder; 289 unsigned int mStructStackSize = 0; 290 }; 291 292 void TraverseShaderVariable(const ShaderVariable &variable, 293 bool isRowMajorLayout, 294 ShaderVariableVisitor *visitor); 295 296 template <typename T> 297 void TraverseShaderVariables(const std::vector<T> &vars, 298 bool isRowMajorLayout, 299 ShaderVariableVisitor *visitor) 300 { 301 for (const T &var : vars) 302 { 303 TraverseShaderVariable(var, isRowMajorLayout, visitor); 304 } 305 } 306 307 template <typename T> 308 void TraverseActiveShaderVariables(const std::vector<T> &vars, 309 bool isRowMajorLayout, 310 ShaderVariableVisitor *visitor) 311 { 312 for (const T &var : vars) 313 { 314 if (var.active) 315 { 316 TraverseShaderVariable(var, isRowMajorLayout, visitor); 317 } 318 } 319 } 320 } // namespace sh 321 322 #endif // COMMON_BLOCKLAYOUT_H_