diff options
Diffstat (limited to 'gfx/angle/checkout/src/libANGLE/VaryingPacking.h')
-rw-r--r-- | gfx/angle/checkout/src/libANGLE/VaryingPacking.h | 330 |
1 files changed, 330 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/libANGLE/VaryingPacking.h b/gfx/angle/checkout/src/libANGLE/VaryingPacking.h new file mode 100644 index 0000000000..202cc21413 --- /dev/null +++ b/gfx/angle/checkout/src/libANGLE/VaryingPacking.h @@ -0,0 +1,330 @@ +// +// Copyright 2015 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. +// +// VaryingPacking: +// Class which describes a mapping from varyings to registers, according +// to the spec, or using custom packing algorithms. We also keep a register +// allocation list for the D3D renderer. +// + +#ifndef LIBANGLE_VARYINGPACKING_H_ +#define LIBANGLE_VARYINGPACKING_H_ + +#include <GLSLANG/ShaderVars.h> + +#include "angle_gl.h" +#include "common/angleutils.h" +#include "libANGLE/angletypes.h" + +#include <map> + +namespace gl +{ +class HasAttachedShaders; +class InfoLog; +class ProgramExecutable; +struct Caps; +struct ProgramVaryingRef; + +using ProgramMergedVaryings = std::vector<ProgramVaryingRef>; + +// A varying can have different names between stages if matched by the location layout qualifier. +// Additionally, same name varyings could still be of two identical struct types with different +// names. This struct contains information on the varying in one of the two stages. PackedVarying +// will thus contain two copies of this along with common information, such as interpolation or +// field index. +struct VaryingInShaderRef : angle::NonCopyable +{ + VaryingInShaderRef(ShaderType stageIn, const sh::ShaderVariable *varyingIn); + VaryingInShaderRef(VaryingInShaderRef &&other); + ~VaryingInShaderRef(); + + VaryingInShaderRef &operator=(VaryingInShaderRef &&other); + + const sh::ShaderVariable *varying; + + ShaderType stage; + + // Struct name + std::string parentStructName; + std::string parentStructMappedName; +}; + +struct PackedVarying : angle::NonCopyable +{ + // Throughout this file, the "front" stage refers to the stage that outputs the varying, and the + // "back" stage refers to the stage that takes the varying as input. Note that this struct + // contains linked varyings, which means both front and back stage varyings are valid, except + // for the following which may have only one valid stage. + // + // - transform-feedback-captured varyings + // - builtins + // - separable program stages, + // + PackedVarying(VaryingInShaderRef &&frontVaryingIn, + VaryingInShaderRef &&backVaryingIn, + sh::InterpolationType interpolationIn); + PackedVarying(VaryingInShaderRef &&frontVaryingIn, + VaryingInShaderRef &&backVaryingIn, + sh::InterpolationType interpolationIn, + GLuint arrayIndexIn, + GLuint fieldIndexIn, + GLuint secondaryFieldIndexIn); + PackedVarying(PackedVarying &&other); + ~PackedVarying(); + + PackedVarying &operator=(PackedVarying &&other); + + bool isStructField() const + { + return frontVarying.varying ? !frontVarying.parentStructName.empty() + : !backVarying.parentStructName.empty(); + } + + bool isTransformFeedbackArrayElement() const + { + return isTransformFeedback && arrayIndex != GL_INVALID_INDEX; + } + + // Return either front or back varying, whichever is available. Only used when the name of the + // varying is not important, but only the type is interesting. + const sh::ShaderVariable &varying() const + { + return frontVarying.varying ? *frontVarying.varying : *backVarying.varying; + } + + const std::string &getParentStructName() const + { + ASSERT(isStructField()); + return frontVarying.varying ? frontVarying.parentStructName : backVarying.parentStructName; + } + + std::string fullName(ShaderType stage) const + { + ASSERT(stage == frontVarying.stage || stage == backVarying.stage); + const VaryingInShaderRef &varying = + stage == frontVarying.stage ? frontVarying : backVarying; + + std::stringstream fullNameStr; + if (isStructField()) + { + fullNameStr << varying.parentStructName << "."; + } + + fullNameStr << varying.varying->name; + if (arrayIndex != GL_INVALID_INDEX) + { + fullNameStr << "[" << arrayIndex << "]"; + } + return fullNameStr.str(); + } + + // Transform feedback varyings can be only referenced in the VS. + bool vertexOnly() const + { + return frontVarying.stage == ShaderType::Vertex && backVarying.varying == nullptr; + } + + // Special handling for GS/TS array inputs. + unsigned int getBasicTypeElementCount() const; + + VaryingInShaderRef frontVarying; + VaryingInShaderRef backVarying; + + // Cached so we can store sh::ShaderVariable to point to varying fields. + sh::InterpolationType interpolation; + + // Used by varyings that are captured with transform feedback, xor arrays of shader I/O blocks, + // distinguished by isTransformFeedback; + GLuint arrayIndex; + bool isTransformFeedback; + + // Field index in the struct. In Vulkan, this is used to assign a + // struct-typed varying location to the location of its first field. + GLuint fieldIndex; + GLuint secondaryFieldIndex; +}; + +struct PackedVaryingRegister final +{ + PackedVaryingRegister() + : packedVarying(nullptr), + varyingArrayIndex(0), + varyingRowIndex(0), + registerRow(0), + registerColumn(0) + {} + + PackedVaryingRegister(const PackedVaryingRegister &) = default; + PackedVaryingRegister &operator=(const PackedVaryingRegister &) = default; + + bool operator<(const PackedVaryingRegister &other) const + { + return sortOrder() < other.sortOrder(); + } + + unsigned int sortOrder() const + { + // TODO(jmadill): Handle interpolation types + return registerRow * 4 + registerColumn; + } + + std::string tfVaryingName() const + { + return packedVarying->fullName(packedVarying->frontVarying.stage); + } + + // Index to the array of varyings. + const PackedVarying *packedVarying; + + // The array element of the packed varying. + unsigned int varyingArrayIndex; + + // The row of the array element of the packed varying. + unsigned int varyingRowIndex; + + // The register row to which we've assigned this packed varying. + unsigned int registerRow; + + // The column of the register row into which we've packed this varying. + unsigned int registerColumn; +}; + +// Supported packing modes: +enum class PackMode +{ + // We treat mat2 arrays as taking two full rows. + WEBGL_STRICT, + + // We allow mat2 to take a 2x2 chunk. + ANGLE_RELAXED, + + // Each varying takes a separate register. No register sharing. + ANGLE_NON_CONFORMANT_D3D9, +}; + +class VaryingPacking final : angle::NonCopyable +{ + public: + VaryingPacking(); + ~VaryingPacking(); + + ANGLE_NO_DISCARD bool collectAndPackUserVaryings(InfoLog &infoLog, + GLint maxVaryingVectors, + PackMode packMode, + ShaderType frontShaderStage, + ShaderType backShaderStage, + const ProgramMergedVaryings &mergedVaryings, + const std::vector<std::string> &tfVaryings, + const bool isSeparableProgram); + + struct Register + { + Register() { data[0] = data[1] = data[2] = data[3] = false; } + + bool &operator[](unsigned int index) { return data[index]; } + bool operator[](unsigned int index) const { return data[index]; } + + bool data[4]; + }; + + Register &operator[](unsigned int index) { return mRegisterMap[index]; } + const Register &operator[](unsigned int index) const { return mRegisterMap[index]; } + + const std::vector<PackedVaryingRegister> &getRegisterList() const { return mRegisterList; } + unsigned int getMaxSemanticIndex() const + { + return static_cast<unsigned int>(mRegisterList.size()); + } + + const ShaderMap<std::vector<std::string>> &getInactiveVaryingMappedNames() const + { + return mInactiveVaryingMappedNames; + } + + const ShaderMap<std::vector<std::string>> &getActiveOutputBuiltInNames() const + { + return mActiveOutputBuiltIns; + } + + void reset(); + + private: + using VaryingUniqueFullNames = ShaderMap<std::set<std::string>>; + + // Register map functions. + bool packUserVaryings(InfoLog &infoLog, + GLint maxVaryingVectors, + PackMode packMode, + const std::vector<PackedVarying> &packedVaryings); + bool packVaryingIntoRegisterMap(PackMode packMode, const PackedVarying &packedVarying); + bool isRegisterRangeFree(unsigned int registerRow, + unsigned int registerColumn, + unsigned int varyingRows, + unsigned int varyingColumns) const; + void insertVaryingIntoRegisterMap(unsigned int registerRow, + unsigned int registerColumn, + unsigned int varyingColumns, + const PackedVarying &packedVarying); + void clearRegisterMap(); + + // Collection functions. + void collectUserVarying(const ProgramVaryingRef &ref, VaryingUniqueFullNames *uniqueFullNames); + void collectUserVaryingField(const ProgramVaryingRef &ref, + GLuint arrayIndex, + GLuint fieldIndex, + GLuint secondaryFieldIndex, + VaryingUniqueFullNames *uniqueFullNames); + void collectUserVaryingTF(const ProgramVaryingRef &ref, size_t subscript); + void collectUserVaryingFieldTF(const ProgramVaryingRef &ref, + const sh::ShaderVariable &field, + GLuint fieldIndex, + GLuint secondaryFieldIndex); + void collectVarying(const sh::ShaderVariable &varying, + const ProgramVaryingRef &ref, + PackMode packMode, + VaryingUniqueFullNames *uniqueFullNames); + void collectTFVarying(const std::string &tfVarying, + const ProgramVaryingRef &ref, + VaryingUniqueFullNames *uniqueFullNames); + + std::vector<Register> mRegisterMap; + std::vector<PackedVaryingRegister> mRegisterList; + std::vector<PackedVarying> mPackedVaryings; + ShaderMap<std::vector<std::string>> mInactiveVaryingMappedNames; + ShaderMap<std::vector<std::string>> mActiveOutputBuiltIns; +}; + +class ProgramVaryingPacking final : angle::NonCopyable +{ + public: + ProgramVaryingPacking(); + ~ProgramVaryingPacking(); + + const VaryingPacking &getInputPacking(ShaderType backShaderStage) const; + const VaryingPacking &getOutputPacking(ShaderType frontShaderStage) const; + + ANGLE_NO_DISCARD bool collectAndPackUserVaryings(InfoLog &infoLog, + const Caps &caps, + PackMode packMode, + const ShaderBitSet &activeShadersMask, + const ProgramMergedVaryings &mergedVaryings, + const std::vector<std::string> &tfVaryings, + bool isSeparableProgram); + + private: + // Indexed by the front shader. + ShaderMap<VaryingPacking> mVaryingPackings; + + // Looks up the front stage from the back stage. + ShaderMap<ShaderType> mBackToFrontStageMap; +}; + +// Takes an abstract handle to a program or pipeline. +ProgramMergedVaryings GetMergedVaryingsFromShaders(const HasAttachedShaders &programOrPipeline, + const ProgramExecutable &programExecutable); +} // namespace gl + +#endif // LIBANGLE_VARYINGPACKING_H_ |