summaryrefslogtreecommitdiffstats
path: root/gfx/angle/checkout/src/libANGLE/VaryingPacking.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--gfx/angle/checkout/src/libANGLE/VaryingPacking.h329
1 files changed, 329 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..3edb9326be
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/VaryingPacking.h
@@ -0,0 +1,329 @@
+//
+// 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 InfoLog;
+class ProgramExecutable;
+struct Caps;
+struct LinkingVariables;
+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();
+
+ [[nodiscard]] 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;
+
+ [[nodiscard]] 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;
+};
+
+ProgramMergedVaryings GetMergedVaryingsFromLinkingVariables(
+ const LinkingVariables &linkingVariables);
+} // namespace gl
+
+#endif // LIBANGLE_VARYINGPACKING_H_