blob: 0e2720899b8132fdf12beb2e057cead3e7123b8a [file] [log] [blame]
// 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.
#include <GLSLANG/ShaderVars.h>
#include "angle_gl.h"
#include "common/angleutils.h"
#include <map>
namespace gl
class InfoLog;
struct ProgramVaryingRef;
using ProgramMergedVaryings = std::map<std::string, ProgramVaryingRef>;
struct PackedVarying
PackedVarying(const sh::ShaderVariable &varyingIn, sh::InterpolationType interpolationIn)
: PackedVarying(varyingIn, interpolationIn, "", false)
PackedVarying(const sh::ShaderVariable &varyingIn,
sh::InterpolationType interpolationIn,
const std::string &parentStructNameIn,
GLuint fieldIndexIn)
: varying(&varyingIn),
bool isStructField() const { return !parentStructName.empty(); }
bool isArrayElement() const { return arrayIndex != GL_INVALID_INDEX; }
std::string fullName() const
std::stringstream fullNameStr;
if (isStructField())
fullNameStr << parentStructName << ".";
fullNameStr << varying->name;
if (arrayIndex != GL_INVALID_INDEX)
fullNameStr << "[" << arrayIndex << "]";
return fullNameStr.str();
const sh::ShaderVariable *varying;
// Transform feedback varyings can be only referenced in the VS.
bool vertexOnly;
// Cached so we can store sh::ShaderVariable to point to varying fields.
sh::InterpolationType interpolation;
// Struct name
std::string parentStructName;
GLuint arrayIndex;
// 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;
struct PackedVaryingRegister final
: packedVarying(nullptr),
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
if (packedVarying->isArrayElement() || packedVarying->isStructField())
return packedVarying->fullName();
return packedVarying->varying->name;
// 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.
// We allow mat2 to take a 2x2 chunk.
// Each varying takes a separate register. No register sharing.
class VaryingPacking final : angle::NonCopyable
VaryingPacking(GLuint maxVaryingVectors, PackMode packMode);
bool packUserVaryings(gl::InfoLog &infoLog, const std::vector<PackedVarying> &packedVaryings);
bool collectAndPackUserVaryings(gl::InfoLog &infoLog,
const ProgramMergedVaryings &mergedVaryings,
const std::vector<std::string> &tfVaryings);
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 std::vector<std::string> &getInactiveVaryingNames() const
return mInactiveVaryingNames;
bool packVarying(const PackedVarying &packedVarying);
bool isFree(unsigned int registerRow,
unsigned int registerColumn,
unsigned int varyingRows,
unsigned int varyingColumns) const;
void insert(unsigned int registerRow,
unsigned int registerColumn,
const PackedVarying &packedVarying);
std::vector<Register> mRegisterMap;
std::vector<PackedVaryingRegister> mRegisterList;
std::vector<PackedVarying> mPackedVaryings;
std::vector<std::string> mInactiveVaryingNames;
PackMode mPackMode;
} // namespace gl