diff options
Diffstat (limited to 'gfx/angle/checkout/src/libANGLE/ProgramLinkedResources.h')
-rw-r--r-- | gfx/angle/checkout/src/libANGLE/ProgramLinkedResources.h | 333 |
1 files changed, 333 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/libANGLE/ProgramLinkedResources.h b/gfx/angle/checkout/src/libANGLE/ProgramLinkedResources.h new file mode 100644 index 0000000000..0bb6cbb96f --- /dev/null +++ b/gfx/angle/checkout/src/libANGLE/ProgramLinkedResources.h @@ -0,0 +1,333 @@ +// +// Copyright 2017 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// ProgramLinkedResources.h: implements link-time checks for default block uniforms, and generates +// uniform locations. Populates data structures related to uniforms so that they can be stored in +// program state. + +#ifndef LIBANGLE_UNIFORMLINKER_H_ +#define LIBANGLE_UNIFORMLINKER_H_ + +#include "angle_gl.h" +#include "common/PackedEnums.h" +#include "common/angleutils.h" +#include "libANGLE/VaryingPacking.h" + +#include <functional> + +namespace sh +{ +class BlockLayoutEncoder; +struct BlockMemberInfo; +struct InterfaceBlock; +struct ShaderVariable; +class BlockEncoderVisitor; +class ShaderVariableVisitor; +struct ShaderVariable; +} // namespace sh + +namespace gl +{ +struct BufferVariable; +struct Caps; +class Context; +class InfoLog; +struct InterfaceBlock; +enum class LinkMismatchError; +struct LinkedUniform; +class ProgramState; +class ProgramPipelineState; +class ProgramBindings; +class ProgramAliasedBindings; +class Shader; +struct ShaderVariableBuffer; +struct UnusedUniform; +struct VariableLocation; + +using AtomicCounterBuffer = ShaderVariableBuffer; +using ShaderUniform = std::pair<ShaderType, const sh::ShaderVariable *>; + +class UniformLinker final : angle::NonCopyable +{ + public: + UniformLinker(const ShaderBitSet &activeShaderStages, + const ShaderMap<std::vector<sh::ShaderVariable>> &shaderUniforms); + ~UniformLinker(); + + bool link(const Caps &caps, + InfoLog &infoLog, + const ProgramAliasedBindings &uniformLocationBindings); + + void getResults(std::vector<LinkedUniform> *uniforms, + std::vector<UnusedUniform> *unusedUniformsOutOrNull, + std::vector<VariableLocation> *uniformLocationsOutOrNull); + + private: + bool validateGraphicsUniforms(InfoLog &infoLog) const; + bool validateGraphicsUniformsPerShader(ShaderType shaderToLink, + bool extendLinkedUniforms, + std::map<std::string, ShaderUniform> *linkedUniforms, + InfoLog &infoLog) const; + bool flattenUniformsAndCheckCapsForShader(ShaderType shaderType, + const Caps &caps, + std::vector<LinkedUniform> &samplerUniforms, + std::vector<LinkedUniform> &imageUniforms, + std::vector<LinkedUniform> &atomicCounterUniforms, + std::vector<LinkedUniform> &inputAttachmentUniforms, + std::vector<UnusedUniform> &unusedUniforms, + InfoLog &infoLog); + + bool flattenUniformsAndCheckCaps(const Caps &caps, InfoLog &infoLog); + bool checkMaxCombinedAtomicCounters(const Caps &caps, InfoLog &infoLog); + + bool indexUniforms(InfoLog &infoLog, const ProgramAliasedBindings &uniformLocationBindings); + bool gatherUniformLocationsAndCheckConflicts( + InfoLog &infoLog, + const ProgramAliasedBindings &uniformLocationBindings, + std::set<GLuint> *ignoredLocations, + int *maxUniformLocation); + void pruneUnusedUniforms(); + + ShaderBitSet mActiveShaderStages; + const ShaderMap<std::vector<sh::ShaderVariable>> &mShaderUniforms; + std::vector<LinkedUniform> mUniforms; + std::vector<UnusedUniform> mUnusedUniforms; + std::vector<VariableLocation> mUniformLocations; +}; + +using GetBlockSizeFunc = std::function< + bool(const std::string &blockName, const std::string &blockMappedName, size_t *sizeOut)>; +using GetBlockMemberInfoFunc = std::function< + bool(const std::string &name, const std::string &mappedName, sh::BlockMemberInfo *infoOut)>; + +// This class is intended to be used during the link step to store interface block information. +// It is called by the Impl class during ProgramImpl::link so that it has access to the +// real block size and layout. +class InterfaceBlockLinker : angle::NonCopyable +{ + public: + virtual ~InterfaceBlockLinker(); + + // This is called once per shader stage. It stores a pointer to the block vector, so it's + // important that this class does not persist longer than the duration of Program::link. + void addShaderBlocks(ShaderType shader, const std::vector<sh::InterfaceBlock> *blocks); + + // This is called once during a link operation, after all shader blocks are added. + void linkBlocks(const GetBlockSizeFunc &getBlockSize, + const GetBlockMemberInfoFunc &getMemberInfo) const; + + const std::vector<sh::InterfaceBlock> &getShaderBlocks(ShaderType shaderType) const + { + ASSERT(mShaderBlocks[shaderType]); + return *mShaderBlocks[shaderType]; + } + + protected: + InterfaceBlockLinker(); + void init(std::vector<InterfaceBlock> *blocksOut, + std::vector<std::string> *unusedInterfaceBlocksOut); + void defineInterfaceBlock(const GetBlockSizeFunc &getBlockSize, + const GetBlockMemberInfoFunc &getMemberInfo, + const sh::InterfaceBlock &interfaceBlock, + ShaderType shaderType) const; + + virtual size_t getCurrentBlockMemberIndex() const = 0; + + virtual sh::ShaderVariableVisitor *getVisitor(const GetBlockMemberInfoFunc &getMemberInfo, + const std::string &namePrefix, + const std::string &mappedNamePrefix, + ShaderType shaderType, + int blockIndex) const = 0; + + ShaderMap<const std::vector<sh::InterfaceBlock> *> mShaderBlocks = {}; + + std::vector<InterfaceBlock> *mBlocksOut = nullptr; + std::vector<std::string> *mUnusedInterfaceBlocksOut = nullptr; +}; + +class UniformBlockLinker final : public InterfaceBlockLinker +{ + public: + UniformBlockLinker(); + ~UniformBlockLinker() override; + + void init(std::vector<InterfaceBlock> *blocksOut, + std::vector<LinkedUniform> *uniformsOut, + std::vector<std::string> *unusedInterfaceBlocksOut); + + private: + size_t getCurrentBlockMemberIndex() const override; + + sh::ShaderVariableVisitor *getVisitor(const GetBlockMemberInfoFunc &getMemberInfo, + const std::string &namePrefix, + const std::string &mappedNamePrefix, + ShaderType shaderType, + int blockIndex) const override; + + std::vector<LinkedUniform> *mUniformsOut = nullptr; +}; + +class ShaderStorageBlockLinker final : public InterfaceBlockLinker +{ + public: + ShaderStorageBlockLinker(); + ~ShaderStorageBlockLinker() override; + + void init(std::vector<InterfaceBlock> *blocksOut, + std::vector<BufferVariable> *bufferVariablesOut, + std::vector<std::string> *unusedInterfaceBlocksOut); + + private: + size_t getCurrentBlockMemberIndex() const override; + + sh::ShaderVariableVisitor *getVisitor(const GetBlockMemberInfoFunc &getMemberInfo, + const std::string &namePrefix, + const std::string &mappedNamePrefix, + ShaderType shaderType, + int blockIndex) const override; + + std::vector<BufferVariable> *mBufferVariablesOut = nullptr; +}; + +class AtomicCounterBufferLinker final : angle::NonCopyable +{ + public: + AtomicCounterBufferLinker(); + ~AtomicCounterBufferLinker(); + + void init(std::vector<AtomicCounterBuffer> *atomicCounterBuffersOut); + void link(const std::map<int, unsigned int> &sizeMap) const; + + private: + std::vector<AtomicCounterBuffer> *mAtomicCounterBuffersOut = nullptr; +}; + +// The link operation is responsible for finishing the link of uniform and interface blocks. +// This way it can filter out unreferenced resources and still have access to the info. +// TODO(jmadill): Integrate uniform linking/filtering as well as interface blocks. +struct UnusedUniform +{ + UnusedUniform(std::string name, + bool isSampler, + bool isImage, + bool isAtomicCounter, + bool isFragmentInOut) + { + this->name = name; + this->isSampler = isSampler; + this->isImage = isImage; + this->isAtomicCounter = isAtomicCounter; + this->isFragmentInOut = isFragmentInOut; + } + + std::string name; + bool isSampler; + bool isImage; + bool isAtomicCounter; + bool isFragmentInOut; +}; + +struct ProgramLinkedResources +{ + ProgramLinkedResources(); + ~ProgramLinkedResources(); + + void init(std::vector<InterfaceBlock> *uniformBlocksOut, + std::vector<LinkedUniform> *uniformsOut, + std::vector<InterfaceBlock> *shaderStorageBlocksOut, + std::vector<BufferVariable> *bufferVariablesOut, + std::vector<AtomicCounterBuffer> *atomicCounterBuffersOut); + + ProgramVaryingPacking varyingPacking; + UniformBlockLinker uniformBlockLinker; + ShaderStorageBlockLinker shaderStorageBlockLinker; + AtomicCounterBufferLinker atomicCounterBufferLinker; + std::vector<UnusedUniform> unusedUniforms; + std::vector<std::string> unusedInterfaceBlocks; +}; + +struct LinkingVariables final : private angle::NonCopyable +{ + LinkingVariables(const Context *context, const ProgramState &state); + LinkingVariables(const ProgramPipelineState &state); + ~LinkingVariables(); + + ShaderMap<std::vector<sh::ShaderVariable>> outputVaryings; + ShaderMap<std::vector<sh::ShaderVariable>> inputVaryings; + ShaderMap<std::vector<sh::ShaderVariable>> uniforms; + ShaderMap<std::vector<sh::InterfaceBlock>> uniformBlocks; + ShaderBitSet isShaderStageUsedBitset; +}; + +class CustomBlockLayoutEncoderFactory : angle::NonCopyable +{ + public: + virtual ~CustomBlockLayoutEncoderFactory() {} + + virtual sh::BlockLayoutEncoder *makeEncoder() = 0; +}; + +// Used by the backends in Program*::linkResources to parse interface blocks and provide +// information to ProgramLinkedResources' linkers. +class ProgramLinkedResourcesLinker final : angle::NonCopyable +{ + public: + ProgramLinkedResourcesLinker(CustomBlockLayoutEncoderFactory *customEncoderFactory) + : mCustomEncoderFactory(customEncoderFactory) + {} + + void linkResources(const Context *context, + const ProgramState &programState, + const ProgramLinkedResources &resources) const; + + private: + void getAtomicCounterBufferSizeMap(const ProgramState &programState, + std::map<int, unsigned int> &sizeMapOut) const; + + CustomBlockLayoutEncoderFactory *mCustomEncoderFactory; +}; + +using ShaderInterfaceBlock = std::pair<ShaderType, const sh::InterfaceBlock *>; +using InterfaceBlockMap = std::map<std::string, ShaderInterfaceBlock>; + +bool LinkValidateProgramGlobalNames(InfoLog &infoLog, + const ProgramExecutable &executable, + const LinkingVariables &linkingVariables); +bool LinkValidateShaderInterfaceMatching(const std::vector<sh::ShaderVariable> &outputVaryings, + const std::vector<sh::ShaderVariable> &inputVaryings, + ShaderType frontShaderType, + ShaderType backShaderType, + int frontShaderVersion, + int backShaderVersion, + bool isSeparable, + InfoLog &infoLog); +bool LinkValidateBuiltInVaryingsInvariant(const std::vector<sh::ShaderVariable> &vertexVaryings, + const std::vector<sh::ShaderVariable> &fragmentVaryings, + int vertexShaderVersion, + InfoLog &infoLog); +bool LinkValidateBuiltInVaryings(const std::vector<sh::ShaderVariable> &inputVaryings, + const std::vector<sh::ShaderVariable> &outputVaryings, + ShaderType inputShaderType, + ShaderType outputShaderType, + int inputShaderVersion, + int outputShaderVersion, + InfoLog &infoLog); +LinkMismatchError LinkValidateProgramVariables(const sh::ShaderVariable &variable1, + const sh::ShaderVariable &variable2, + bool validatePrecision, + bool treatVariable1AsNonArray, + bool treatVariable2AsNonArray, + std::string *mismatchedStructOrBlockMemberName); +void AddProgramVariableParentPrefix(const std::string &parentName, + std::string *mismatchedFieldName); +bool LinkValidateProgramInterfaceBlocks(const Context *context, + ShaderBitSet activeProgramStages, + const ProgramLinkedResources &resources, + InfoLog &infoLog, + GLuint *combinedShaderStorageBlocksCountOut); +} // namespace gl + +#endif // LIBANGLE_UNIFORMLINKER_H_ |