1 // 2 // Copyright 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 // ProgramLinkedResources.h: implements link-time checks for default block uniforms, and generates 8 // uniform locations. Populates data structures related to uniforms so that they can be stored in 9 // program state. 10 11 #ifndef LIBANGLE_UNIFORMLINKER_H_ 12 #define LIBANGLE_UNIFORMLINKER_H_ 13 14 #include "angle_gl.h" 15 #include "common/PackedEnums.h" 16 #include "common/angleutils.h" 17 #include "libANGLE/VaryingPacking.h" 18 19 #include <functional> 20 21 namespace sh 22 { 23 class BlockLayoutEncoder; 24 struct BlockMemberInfo; 25 struct InterfaceBlock; 26 struct ShaderVariable; 27 class BlockEncoderVisitor; 28 class ShaderVariableVisitor; 29 struct Uniform; 30 } // namespace sh 31 32 namespace gl 33 { 34 struct BufferVariable; 35 struct Caps; 36 class Context; 37 class InfoLog; 38 struct InterfaceBlock; 39 enum class LinkMismatchError; 40 struct LinkedUniform; 41 class ProgramState; 42 class ProgramBindings; 43 class Shader; 44 struct ShaderVariableBuffer; 45 struct UnusedUniform; 46 struct VariableLocation; 47 48 using AtomicCounterBuffer = ShaderVariableBuffer; 49 50 class UniformLinker final : angle::NonCopyable 51 { 52 public: 53 UniformLinker(const ProgramState &state); 54 ~UniformLinker(); 55 56 bool link(const Caps &caps, InfoLog &infoLog, const ProgramBindings &uniformLocationBindings); 57 58 void getResults(std::vector<LinkedUniform> *uniforms, 59 std::vector<UnusedUniform> *unusedUniforms, 60 std::vector<VariableLocation> *uniformLocations); 61 62 private: 63 bool validateGraphicsUniforms(InfoLog &infoLog) const; 64 65 bool flattenUniformsAndCheckCapsForShader(Shader *shader, 66 const Caps &caps, 67 std::vector<LinkedUniform> &samplerUniforms, 68 std::vector<LinkedUniform> &imageUniforms, 69 std::vector<LinkedUniform> &atomicCounterUniforms, 70 std::vector<UnusedUniform> &unusedUniforms, 71 InfoLog &infoLog); 72 73 bool flattenUniformsAndCheckCaps(const Caps &caps, InfoLog &infoLog); 74 bool checkMaxCombinedAtomicCounters(const Caps &caps, InfoLog &infoLog); 75 76 bool indexUniforms(InfoLog &infoLog, const ProgramBindings &uniformLocationBindings); 77 bool gatherUniformLocationsAndCheckConflicts(InfoLog &infoLog, 78 const ProgramBindings &uniformLocationBindings, 79 std::set<GLuint> *ignoredLocations, 80 int *maxUniformLocation); 81 void pruneUnusedUniforms(); 82 83 const ProgramState &mState; 84 std::vector<LinkedUniform> mUniforms; 85 std::vector<UnusedUniform> mUnusedUniforms; 86 std::vector<VariableLocation> mUniformLocations; 87 }; 88 89 using GetBlockSizeFunc = std::function< 90 bool(const std::string &blockName, const std::string &blockMappedName, size_t *sizeOut)>; 91 using GetBlockMemberInfoFunc = std::function< 92 bool(const std::string &name, const std::string &mappedName, sh::BlockMemberInfo *infoOut)>; 93 94 // This class is intended to be used during the link step to store interface block information. 95 // It is called by the Impl class during ProgramImpl::link so that it has access to the 96 // real block size and layout. 97 class InterfaceBlockLinker : angle::NonCopyable 98 { 99 public: 100 virtual ~InterfaceBlockLinker(); 101 102 // This is called once per shader stage. It stores a pointer to the block vector, so it's 103 // important that this class does not persist longer than the duration of Program::link. 104 void addShaderBlocks(ShaderType shader, const std::vector<sh::InterfaceBlock> *blocks); 105 106 // This is called once during a link operation, after all shader blocks are added. 107 void linkBlocks(const GetBlockSizeFunc &getBlockSize, 108 const GetBlockMemberInfoFunc &getMemberInfo) const; 109 110 protected: 111 InterfaceBlockLinker(std::vector<InterfaceBlock> *blocksOut, 112 std::vector<std::string> *unusedInterfaceBlocksOut); 113 void defineInterfaceBlock(const GetBlockSizeFunc &getBlockSize, 114 const GetBlockMemberInfoFunc &getMemberInfo, 115 const sh::InterfaceBlock &interfaceBlock, 116 ShaderType shaderType) const; 117 118 virtual size_t getCurrentBlockMemberIndex() const = 0; 119 120 ShaderMap<const std::vector<sh::InterfaceBlock> *> mShaderBlocks; 121 122 std::vector<InterfaceBlock> *mBlocksOut; 123 std::vector<std::string> *mUnusedInterfaceBlocksOut; 124 125 virtual sh::ShaderVariableVisitor *getVisitor(const GetBlockMemberInfoFunc &getMemberInfo, 126 const std::string &namePrefix, 127 const std::string &mappedNamePrefix, 128 ShaderType shaderType, 129 int blockIndex) const = 0; 130 }; 131 132 class UniformBlockLinker final : public InterfaceBlockLinker 133 { 134 public: 135 UniformBlockLinker(std::vector<InterfaceBlock> *blocksOut, 136 std::vector<LinkedUniform> *uniformsOut, 137 std::vector<std::string> *unusedInterfaceBlocksOut); 138 ~UniformBlockLinker() override; 139 140 private: 141 size_t getCurrentBlockMemberIndex() const override; 142 143 sh::ShaderVariableVisitor *getVisitor(const GetBlockMemberInfoFunc &getMemberInfo, 144 const std::string &namePrefix, 145 const std::string &mappedNamePrefix, 146 ShaderType shaderType, 147 int blockIndex) const override; 148 149 std::vector<LinkedUniform> *mUniformsOut; 150 }; 151 152 class ShaderStorageBlockLinker final : public InterfaceBlockLinker 153 { 154 public: 155 ShaderStorageBlockLinker(std::vector<InterfaceBlock> *blocksOut, 156 std::vector<BufferVariable> *bufferVariablesOut, 157 std::vector<std::string> *unusedInterfaceBlocksOut); 158 ~ShaderStorageBlockLinker() override; 159 160 private: 161 size_t getCurrentBlockMemberIndex() const override; 162 163 sh::ShaderVariableVisitor *getVisitor(const GetBlockMemberInfoFunc &getMemberInfo, 164 const std::string &namePrefix, 165 const std::string &mappedNamePrefix, 166 ShaderType shaderType, 167 int blockIndex) const override; 168 169 std::vector<BufferVariable> *mBufferVariablesOut; 170 }; 171 172 class AtomicCounterBufferLinker final : angle::NonCopyable 173 { 174 public: 175 AtomicCounterBufferLinker(std::vector<AtomicCounterBuffer> *atomicCounterBuffersOut); 176 ~AtomicCounterBufferLinker(); 177 178 void link(const std::map<int, unsigned int> &sizeMap) const; 179 180 private: 181 std::vector<AtomicCounterBuffer> *mAtomicCounterBuffersOut; 182 }; 183 184 // The link operation is responsible for finishing the link of uniform and interface blocks. 185 // This way it can filter out unreferenced resources and still have access to the info. 186 // TODO(jmadill): Integrate uniform linking/filtering as well as interface blocks. 187 struct UnusedUniform 188 { UnusedUniformUnusedUniform189 UnusedUniform(std::string name, bool isSampler) 190 { 191 this->name = name; 192 this->isSampler = isSampler; 193 } 194 195 std::string name; 196 bool isSampler; 197 }; 198 199 struct ProgramLinkedResources 200 { 201 ProgramLinkedResources(GLuint maxVaryingVectors, 202 PackMode packMode, 203 std::vector<InterfaceBlock> *uniformBlocksOut, 204 std::vector<LinkedUniform> *uniformsOut, 205 std::vector<InterfaceBlock> *shaderStorageBlocksOut, 206 std::vector<BufferVariable> *bufferVariablesOut, 207 std::vector<AtomicCounterBuffer> *atomicCounterBuffersOut); 208 ~ProgramLinkedResources(); 209 210 VaryingPacking varyingPacking; 211 UniformBlockLinker uniformBlockLinker; 212 ShaderStorageBlockLinker shaderStorageBlockLinker; 213 AtomicCounterBufferLinker atomicCounterBufferLinker; 214 std::vector<UnusedUniform> unusedUniforms; 215 std::vector<std::string> unusedInterfaceBlocks; 216 }; 217 218 class CustomBlockLayoutEncoderFactory : angle::NonCopyable 219 { 220 public: ~CustomBlockLayoutEncoderFactory()221 virtual ~CustomBlockLayoutEncoderFactory() {} 222 223 virtual sh::BlockLayoutEncoder *makeEncoder() = 0; 224 }; 225 226 // Used by the backends in Program*::linkResources to parse interface blocks and provide 227 // information to ProgramLinkedResources' linkers. 228 class ProgramLinkedResourcesLinker final : angle::NonCopyable 229 { 230 public: ProgramLinkedResourcesLinker(CustomBlockLayoutEncoderFactory * customEncoderFactory)231 ProgramLinkedResourcesLinker(CustomBlockLayoutEncoderFactory *customEncoderFactory) 232 : mCustomEncoderFactory(customEncoderFactory) 233 {} 234 235 void linkResources(const ProgramState &programState, 236 const ProgramLinkedResources &resources) const; 237 238 private: 239 void getAtomicCounterBufferSizeMap(const ProgramState &programState, 240 std::map<int, unsigned int> &sizeMapOut) const; 241 242 CustomBlockLayoutEncoderFactory *mCustomEncoderFactory; 243 }; 244 245 } // namespace gl 246 247 #endif // LIBANGLE_UNIFORMLINKER_H_ 248