1 // 2 // Copyright (c) 2017 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 7 // UniformLinker.h: implements link-time checks for default block uniforms, and generates uniform 8 // locations. Populates data structures related to uniforms so that they can be stored in program 9 // state. 10 11 #ifndef LIBANGLE_UNIFORMLINKER_H_ 12 #define LIBANGLE_UNIFORMLINKER_H_ 13 14 #include "libANGLE/Program.h" 15 #include "libANGLE/Uniform.h" 16 #include "libANGLE/VaryingPacking.h" 17 18 #include <functional> 19 20 namespace gl 21 { 22 23 class UniformLinker 24 { 25 public: 26 UniformLinker(const ProgramState &state); 27 ~UniformLinker(); 28 29 bool link(const Context *context, 30 InfoLog &infoLog, 31 const Program::Bindings &uniformLocationBindings); 32 33 void getResults(std::vector<LinkedUniform> *uniforms, 34 std::vector<VariableLocation> *uniformLocations); 35 36 private: 37 struct ShaderUniformCount 38 { ShaderUniformCountShaderUniformCount39 ShaderUniformCount() : vectorCount(0), samplerCount(0), imageCount(0), atomicCounterCount(0) 40 { 41 } 42 ShaderUniformCount(const ShaderUniformCount &other) = default; 43 ShaderUniformCount &operator=(const ShaderUniformCount &other) = default; 44 45 ShaderUniformCount &operator+=(const ShaderUniformCount &other) 46 { 47 vectorCount += other.vectorCount; 48 samplerCount += other.samplerCount; 49 imageCount += other.imageCount; 50 atomicCounterCount += other.atomicCounterCount; 51 return *this; 52 } 53 54 unsigned int vectorCount; 55 unsigned int samplerCount; 56 unsigned int imageCount; 57 unsigned int atomicCounterCount; 58 }; 59 60 bool validateVertexAndFragmentUniforms(const Context *context, InfoLog &infoLog) const; 61 62 static bool linkValidateUniforms(InfoLog &infoLog, 63 const std::string &uniformName, 64 const sh::Uniform &vertexUniform, 65 const sh::Uniform &fragmentUniform); 66 67 bool flattenUniformsAndCheckCapsForShader(const Context *context, 68 Shader *shader, 69 GLuint maxUniformComponents, 70 GLuint maxTextureImageUnits, 71 GLuint maxImageUnits, 72 GLuint maxAtomicCounters, 73 const std::string &componentsErrorMessage, 74 const std::string &samplerErrorMessage, 75 const std::string &imageErrorMessage, 76 const std::string &atomicCounterErrorMessage, 77 std::vector<LinkedUniform> &samplerUniforms, 78 std::vector<LinkedUniform> &imageUniforms, 79 std::vector<LinkedUniform> &atomicCounterUniforms, 80 InfoLog &infoLog); 81 82 bool flattenUniformsAndCheckCaps(const Context *context, InfoLog &infoLog); 83 bool checkMaxCombinedAtomicCounters(const Caps &caps, InfoLog &infoLog); 84 85 ShaderUniformCount flattenUniform(const sh::Uniform &uniform, 86 std::vector<LinkedUniform> *samplerUniforms, 87 std::vector<LinkedUniform> *imageUniforms, 88 std::vector<LinkedUniform> *atomicCounterUniforms, 89 GLenum shaderType); 90 91 ShaderUniformCount flattenArrayOfStructsUniform( 92 const sh::ShaderVariable &uniform, 93 unsigned int arrayNestingIndex, 94 const std::string &namePrefix, 95 const std::string &mappedNamePrefix, 96 std::vector<LinkedUniform> *samplerUniforms, 97 std::vector<LinkedUniform> *imageUniforms, 98 std::vector<LinkedUniform> *atomicCounterUniforms, 99 GLenum shaderType, 100 bool markStaticUse, 101 int binding, 102 int offset, 103 int *location); 104 105 ShaderUniformCount flattenStructUniform(const std::vector<sh::ShaderVariable> &fields, 106 const std::string &namePrefix, 107 const std::string &mappedNamePrefix, 108 std::vector<LinkedUniform> *samplerUniforms, 109 std::vector<LinkedUniform> *imageUniforms, 110 std::vector<LinkedUniform> *atomicCounterUniforms, 111 GLenum shaderType, 112 bool markStaticUse, 113 int binding, 114 int offset, 115 int *location); 116 117 ShaderUniformCount flattenArrayUniform(const sh::ShaderVariable &uniform, 118 const std::string &fullName, 119 const std::string &fullMappedName, 120 std::vector<LinkedUniform> *samplerUniforms, 121 std::vector<LinkedUniform> *imageUniforms, 122 std::vector<LinkedUniform> *atomicCounterUniforms, 123 GLenum shaderType, 124 bool markStaticUse, 125 int binding, 126 int offset, 127 int *location); 128 129 // markStaticUse is given as a separate parameter because it is tracked here at struct 130 // granularity. 131 ShaderUniformCount flattenUniformImpl(const sh::ShaderVariable &uniform, 132 const std::string &fullName, 133 const std::string &fullMappedName, 134 std::vector<LinkedUniform> *samplerUniforms, 135 std::vector<LinkedUniform> *imageUniforms, 136 std::vector<LinkedUniform> *atomicCounterUniforms, 137 GLenum shaderType, 138 bool markStaticUse, 139 int binding, 140 int offset, 141 int *location); 142 143 bool indexUniforms(InfoLog &infoLog, const Program::Bindings &uniformLocationBindings); 144 bool gatherUniformLocationsAndCheckConflicts(InfoLog &infoLog, 145 const Program::Bindings &uniformLocationBindings, 146 std::set<GLuint> *reservedLocations, 147 std::set<GLuint> *ignoredLocations, 148 int *maxUniformLocation); 149 void pruneUnusedUniforms(); 150 151 const ProgramState &mState; 152 std::vector<LinkedUniform> mUniforms; 153 std::vector<VariableLocation> mUniformLocations; 154 }; 155 156 // This class is intended to be used during the link step to store interface block information. 157 // It is called by the Impl class during ProgramImpl::link so that it has access to the 158 // real block size and layout. 159 class InterfaceBlockLinker : angle::NonCopyable 160 { 161 public: 162 virtual ~InterfaceBlockLinker(); 163 164 using GetBlockSize = std::function< 165 bool(const std::string &blockName, const std::string &blockMappedName, size_t *sizeOut)>; 166 using GetBlockMemberInfo = std::function< 167 bool(const std::string &name, const std::string &mappedName, sh::BlockMemberInfo *infoOut)>; 168 169 // This is called once per shader stage. It stores a pointer to the block vector, so it's 170 // important that this class does not persist longer than the duration of Program::link. 171 void addShaderBlocks(GLenum shader, const std::vector<sh::InterfaceBlock> *blocks); 172 173 // This is called once during a link operation, after all shader blocks are added. 174 void linkBlocks(const GetBlockSize &getBlockSize, 175 const GetBlockMemberInfo &getMemberInfo) const; 176 177 protected: 178 InterfaceBlockLinker(std::vector<InterfaceBlock> *blocksOut); 179 void defineInterfaceBlock(const GetBlockSize &getBlockSize, 180 const GetBlockMemberInfo &getMemberInfo, 181 const sh::InterfaceBlock &interfaceBlock, 182 GLenum shaderType) const; 183 184 template <typename VarT> 185 void defineBlockMembers(const GetBlockMemberInfo &getMemberInfo, 186 const std::vector<VarT> &fields, 187 const std::string &prefix, 188 const std::string &mappedPrefix, 189 int blockIndex, 190 bool singleEntryForTopLevelArray, 191 int topLevelArraySize) const; 192 template <typename VarT> 193 void defineBlockMember(const GetBlockMemberInfo &getMemberInfo, 194 const VarT &field, 195 const std::string &fullName, 196 const std::string &fullMappedName, 197 int blockIndex, 198 bool singleEntryForTopLevelArray, 199 int topLevelArraySize) const; 200 201 virtual void defineBlockMemberImpl(const sh::ShaderVariable &field, 202 const std::string &fullName, 203 const std::string &fullMappedName, 204 int blockIndex, 205 const sh::BlockMemberInfo &memberInfo, 206 int topLevelArraySize) const = 0; 207 virtual size_t getCurrentBlockMemberIndex() const = 0; 208 209 using ShaderBlocks = std::pair<GLenum, const std::vector<sh::InterfaceBlock> *>; 210 std::vector<ShaderBlocks> mShaderBlocks; 211 212 std::vector<InterfaceBlock> *mBlocksOut; 213 214 private: 215 template <typename VarT> 216 void defineArrayOfStructsBlockMembers(const GetBlockMemberInfo &getMemberInfo, 217 const VarT &field, 218 unsigned int arrayNestingIndex, 219 const std::string &prefix, 220 const std::string &mappedPrefix, 221 int blockIndex, 222 bool singleEntryForTopLevelArray, 223 int topLevelArraySize) const; 224 }; 225 226 class UniformBlockLinker final : public InterfaceBlockLinker 227 { 228 public: 229 UniformBlockLinker(std::vector<InterfaceBlock> *blocksOut, 230 std::vector<LinkedUniform> *uniformsOut); 231 ~UniformBlockLinker() override; 232 233 private: 234 void defineBlockMemberImpl(const sh::ShaderVariable &field, 235 const std::string &fullName, 236 const std::string &fullMappedName, 237 int blockIndex, 238 const sh::BlockMemberInfo &memberInfo, 239 int topLevelArraySize) const override; 240 size_t getCurrentBlockMemberIndex() const override; 241 std::vector<LinkedUniform> *mUniformsOut; 242 }; 243 244 class ShaderStorageBlockLinker final : public InterfaceBlockLinker 245 { 246 public: 247 ShaderStorageBlockLinker(std::vector<InterfaceBlock> *blocksOut, 248 std::vector<BufferVariable> *bufferVariablesOut); 249 ~ShaderStorageBlockLinker() override; 250 251 private: 252 void defineBlockMemberImpl(const sh::ShaderVariable &field, 253 const std::string &fullName, 254 const std::string &fullMappedName, 255 int blockIndex, 256 const sh::BlockMemberInfo &memberInfo, 257 int topLevelArraySize) const override; 258 size_t getCurrentBlockMemberIndex() const override; 259 std::vector<BufferVariable> *mBufferVariablesOut; 260 }; 261 262 // The link operation is responsible for finishing the link of uniform and interface blocks. 263 // This way it can filter out unreferenced resources and still have access to the info. 264 // TODO(jmadill): Integrate uniform linking/filtering as well as interface blocks. 265 struct ProgramLinkedResources 266 { 267 VaryingPacking varyingPacking; 268 UniformBlockLinker uniformBlockLinker; 269 ShaderStorageBlockLinker shaderStorageBlockLinker; 270 }; 271 272 } // namespace gl 273 274 #endif // LIBANGLE_UNIFORMLINKER_H_ 275