blob: 5d2d14683604f4b4504938caaaca9fa50b192f0b [file] [log] [blame]
// Copyright 2013 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.
// ShaderVars.h:
// Types to represent GL variables (varyings, uniforms, etc)
#include <algorithm>
#include <array>
#include <cstdint>
#include <string>
#include <vector>
// This type is defined here to simplify ANGLE's integration with glslang for SPIRv.
using ShCompileOptions = uint64_t;
namespace sh
// GLenum alias
typedef unsigned int GLenum;
// Varying interpolation qualifier, see section 4.3.9 of the ESSL 3.00.4 spec
enum InterpolationType
// Validate link & SSO consistency of interpolation qualifiers
bool InterpolationTypesMatch(InterpolationType a, InterpolationType b);
// Uniform block layout qualifier, see section of the ESSL 3.00.4 spec
enum BlockLayoutType
BLOCKLAYOUT_STD430, // Shader storage block layout qualifier
// Interface Blocks, see section 4.3.9 of the ESSL 3.10 spec
enum class BlockType
// Required in OpenGL ES 3.1 extension GL_OES_shader_io_blocks.
// Also used in GLSL
// Base class for all variables defined in shaders, including Varyings, Uniforms, etc
// Note: we must override the copy constructor and assignment operator so we can
// work around excessive GCC binary bloating:
// See
struct ShaderVariable
ShaderVariable(GLenum typeIn);
ShaderVariable(GLenum typeIn, unsigned int arraySizeIn);
ShaderVariable(const ShaderVariable &other);
ShaderVariable &operator=(const ShaderVariable &other);
bool operator==(const ShaderVariable &other) const;
bool operator!=(const ShaderVariable &other) const { return !operator==(other); }
bool isArrayOfArrays() const { return arraySizes.size() >= 2u; }
bool isArray() const { return !arraySizes.empty(); }
unsigned int getArraySizeProduct() const;
// Return the inner array size product.
// For example, if there's a variable declared as size 3 array of size 4 array of size 5 array
// of int:
// int a[3][4][5];
// then getInnerArraySizeProduct of a would be 4*5.
unsigned int getInnerArraySizeProduct() const;
// Array size 0 means not an array when passed to or returned from these functions.
// Note that setArraySize() is deprecated and should not be used inside ANGLE.
unsigned int getOutermostArraySize() const { return isArray() ? arraySizes.back() : 0; }
void setArraySize(unsigned int size);
// Turn this ShaderVariable from an array into a specific element in that array. Will update
// flattenedOffsetInParentArrays.
void indexIntoArray(unsigned int arrayIndex);
// Get the nth nested array size from the top. Caller is responsible for range checking
// arrayNestingIndex.
unsigned int getNestedArraySize(unsigned int arrayNestingIndex) const;
// This function should only be used with variables that are of a basic type or an array of a
// basic type. Shader interface variables that are enumerated according to rules in GLES 3.1
// spec section page 77 are fine. For those variables the return value should match the
// ARRAY_SIZE value that can be queried through the API.
unsigned int getBasicTypeElementCount() const;
unsigned int getExternalSize() const;
bool isStruct() const { return !fields.empty(); }
// All of the shader's variables are described using nested data
// structures. This is needed in order to disambiguate similar looking
// types, such as two structs containing the same fields, but in
// different orders. "findInfoByMappedName" provides an easy query for
// users to dive into the data structure and fetch the unique variable
// instance corresponding to a dereferencing chain of the top-level
// variable.
// Given a mapped name like 'a[0].b.c[0]', return the ShaderVariable
// that defines 'c' in |leafVar|, and the original name 'A[0].B.C[0]'
// in |originalName|, based on the assumption that |this| defines 'a'.
// If no match is found, return false.
bool findInfoByMappedName(const std::string &mappedFullName,
const ShaderVariable **leafVar,
std::string *originalFullName) const;
bool isBuiltIn() const;
bool isEmulatedBuiltIn() const;
GLenum type;
GLenum precision;
std::string name;
std::string mappedName;
// Used to make an array type. Outermost array size is stored at the end of the vector.
std::vector<unsigned int> arraySizes;
// Offset of this variable in parent arrays. In case the parent is an array of arrays, the
// offset is outerArrayElement * innerArraySize + innerArrayElement.
// For example, if there's a variable declared as size 3 array of size 4 array of int:
// int a[3][4];
// then the flattenedOffsetInParentArrays of a[2] would be 2.
// and flattenedOffsetInParentArrays of a[2][1] would be 2*4 + 1 = 9.
int parentArrayIndex() const
return hasParentArrayIndex() ? flattenedOffsetInParentArrays : 0;
void setParentArrayIndex(int indexIn) { flattenedOffsetInParentArrays = indexIn; }
bool hasParentArrayIndex() const { return flattenedOffsetInParentArrays != -1; }
// Static use means that the variable is accessed somewhere in the shader source.
bool staticUse;
// A variable is active unless the compiler determined that it is not accessed by the shader.
// All active variables are statically used, but not all statically used variables are
// necessarily active. GLES 3.0.5 section 2.12.6. GLES 3.1 section 7.3.1.
bool active;
std::vector<ShaderVariable> fields;
std::string structName;
// Only applies to interface block fields. Kept here for simplicity.
bool isRowMajorLayout;
// VariableWithLocation
int location;
// Uniform
int binding;
// Decide whether two uniforms are the same at shader link time,
// assuming one from vertex shader and the other from fragment shader.
// GLSL ES Spec 3.00.3, section 4.3.5.
// GLSL ES Spec 3.10.4, section 4.4.5
bool isSameUniformAtLinkTime(const ShaderVariable &other) const;
GLenum imageUnitFormat;
int offset;
bool readonly;
bool writeonly;
// OutputVariable
// From EXT_blend_func_extended.
int index;
// InterfaceBlockField
// Decide whether two InterfaceBlock fields are the same at shader
// link time, assuming one from vertex shader and the other from
// fragment shader.
// See GLSL ES Spec 3.00.3, sec 4.3.7.
bool isSameInterfaceBlockFieldAtLinkTime(const ShaderVariable &other) const;
// Varying
InterpolationType interpolation;
bool isInvariant;
// Decide whether two varyings are the same at shader link time,
// assuming one from vertex shader and the other from fragment shader.
// Invariance needs to match only in ESSL1. Relevant spec sections:
// GLSL ES 3.00.4, sections 4.6.1 and 4.3.9.
// GLSL ES 1.00.17, section 4.6.4.
bool isSameVaryingAtLinkTime(const ShaderVariable &other, int shaderVersion) const;
// Deprecated version of isSameVaryingAtLinkTime, which assumes ESSL1.
bool isSameVaryingAtLinkTime(const ShaderVariable &other) const;
bool isSameVariableAtLinkTime(const ShaderVariable &other,
bool matchPrecision,
bool matchName) const;
int flattenedOffsetInParentArrays;
// TODO:
// For backwards compatibility for other codebases (e.g., chromium/src/gpu/command_buffer/service)
using Uniform = ShaderVariable;
using Attribute = ShaderVariable;
using OutputVariable = ShaderVariable;
using InterfaceBlockField = ShaderVariable;
using Varying = ShaderVariable;
struct InterfaceBlock
InterfaceBlock(const InterfaceBlock &other);
InterfaceBlock &operator=(const InterfaceBlock &other);
// Fields from blocks with non-empty instance names are prefixed with the block name.
std::string fieldPrefix() const;
std::string fieldMappedPrefix() const;
// Decide whether two interface blocks are the same at shader link time.
bool isSameInterfaceBlockAtLinkTime(const InterfaceBlock &other) const;
bool isBuiltIn() const;
bool isArray() const { return arraySize > 0; }
unsigned int elementCount() const { return std::max(1u, arraySize); }
std::string name;
std::string mappedName;
std::string instanceName;
unsigned int arraySize;
BlockLayoutType layout;
// Deprecated. Matrix packing should only be queried from individual fields of the block.
// TODO(oetuaho): Remove this once it is no longer used in Chromium.
bool isRowMajorLayout;
int binding;
bool staticUse;
bool active;
BlockType blockType;
std::vector<ShaderVariable> fields;
struct WorkGroupSize
// Must have a trivial default constructor since it is used in YYSTYPE.
inline WorkGroupSize() = default;
inline explicit constexpr WorkGroupSize(int initialSize);
void fill(int fillValue);
void setLocalSize(int localSizeX, int localSizeY, int localSizeZ);
int &operator[](size_t index);
int operator[](size_t index) const;
size_t size() const;
// Checks whether two work group size declarations match.
// Two work group size declarations are the same if the explicitly specified elements are the
// same or if one of them is specified as one and the other one is not specified
bool isWorkGroupSizeMatching(const WorkGroupSize &right) const;
// Checks whether any of the values are set.
bool isAnyValueSet() const;
// Checks whether all of the values are set.
bool isDeclared() const;
// Checks whether either all of the values are set, or none of them are.
bool isLocalSizeValid() const;
int localSizeQualifiers[3];
inline constexpr WorkGroupSize::WorkGroupSize(int initialSize)
: localSizeQualifiers{initialSize, initialSize, initialSize}
} // namespace sh