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