331 lines
12 KiB
C++
331 lines
12 KiB
C++
//
|
|
// 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)
|
|
//
|
|
|
|
#ifndef GLSLANG_SHADERVARS_H_
|
|
#define GLSLANG_SHADERVARS_H_
|
|
|
|
#include <algorithm>
|
|
#include <array>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
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
|
|
{
|
|
INTERPOLATION_SMOOTH,
|
|
INTERPOLATION_CENTROID,
|
|
INTERPOLATION_SAMPLE,
|
|
INTERPOLATION_FLAT,
|
|
INTERPOLATION_NOPERSPECTIVE
|
|
};
|
|
|
|
const char *InterpolationTypeToString(InterpolationType type);
|
|
|
|
// Validate link & SSO consistency of interpolation qualifiers
|
|
bool InterpolationTypesMatch(InterpolationType a, InterpolationType b);
|
|
|
|
// Uniform block layout qualifier, see section 4.3.8.3 of the ESSL 3.00.4 spec
|
|
enum BlockLayoutType
|
|
{
|
|
BLOCKLAYOUT_STANDARD,
|
|
BLOCKLAYOUT_STD140 = BLOCKLAYOUT_STANDARD,
|
|
BLOCKLAYOUT_STD430, // Shader storage block layout qualifier
|
|
BLOCKLAYOUT_PACKED,
|
|
BLOCKLAYOUT_SHARED
|
|
};
|
|
|
|
const char *BlockLayoutTypeToString(BlockLayoutType type);
|
|
|
|
// Interface Blocks, see section 4.3.9 of the ESSL 3.10 spec
|
|
enum class BlockType
|
|
{
|
|
BLOCK_UNIFORM,
|
|
BLOCK_BUFFER,
|
|
};
|
|
|
|
const char *BlockTypeToString(BlockType type);
|
|
|
|
// 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 https://code.google.com/p/angleproject/issues/detail?id=697
|
|
struct ShaderVariable
|
|
{
|
|
ShaderVariable();
|
|
ShaderVariable(GLenum typeIn);
|
|
ShaderVariable(GLenum typeIn, unsigned int arraySizeIn);
|
|
~ShaderVariable();
|
|
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 7.3.1.1 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(); }
|
|
const std::string &getStructName() const { return structOrBlockName; }
|
|
void setStructName(const std::string &newName) { structOrBlockName = newName; }
|
|
|
|
// 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;
|
|
|
|
// Find the child field which matches 'fullName' == var.name + "." + field.name.
|
|
// Return nullptr if not found.
|
|
const sh::ShaderVariable *findField(const std::string &fullName, uint32_t *fieldIndexOut) const;
|
|
|
|
bool isBuiltIn() const;
|
|
bool isEmulatedBuiltIn() const;
|
|
|
|
// 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;
|
|
}
|
|
|
|
int getFlattenedOffsetInParentArrays() const { return flattenedOffsetInParentArrays; }
|
|
void setParentArrayIndex(int indexIn) { flattenedOffsetInParentArrays = indexIn; }
|
|
|
|
bool hasParentArrayIndex() const { return flattenedOffsetInParentArrays != -1; }
|
|
|
|
void resetEffectiveLocation();
|
|
void updateEffectiveLocation(const sh::ShaderVariable &parent);
|
|
|
|
// Decide whether two uniforms are the same at shader link time,
|
|
// assuming they are from consecutive shader stages.
|
|
// 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;
|
|
|
|
// InterfaceBlockField
|
|
// Decide whether two InterfaceBlock fields are the same at shader
|
|
// link time, assuming they are from consecutive shader stages.
|
|
// See GLSL ES Spec 3.00.3, sec 4.3.7.
|
|
bool isSameInterfaceBlockFieldAtLinkTime(const ShaderVariable &other) const;
|
|
|
|
// Decide whether two varyings are the same at shader link time,
|
|
// assuming they are from consecutive shader stages.
|
|
// 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;
|
|
|
|
// Shader I/O blocks may match by block name or instance, based on whether both stages have an
|
|
// instance name or not.
|
|
bool isSameNameAtLinkTime(const ShaderVariable &other) const;
|
|
|
|
// NOTE: When adding new members, the following functions also need to be updated:
|
|
// gl::WriteShaderVar(BinaryOutputStream *stream, const sh::ShaderVariable &var)
|
|
// gl::LoadShaderVar(BinaryInputStream *stream, sh::ShaderVariable *var)
|
|
|
|
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;
|
|
|
|
// 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;
|
|
// structOrBlockName is used for:
|
|
// - varyings of struct type, in which case it contains the struct name.
|
|
// - shader I/O blocks, in which case it contains the block name.
|
|
std::string structOrBlockName;
|
|
std::string mappedStructOrBlockName;
|
|
|
|
// Only applies to interface block fields. Kept here for simplicity.
|
|
bool isRowMajorLayout;
|
|
|
|
// VariableWithLocation
|
|
int location;
|
|
|
|
// The location of inputs or outputs without location layout quailifer will be updated to '-1'.
|
|
// GLES Spec 3.1, Section 7.3. PROGRAM OBJECTS
|
|
// Not all active variables are assigned valid locations;
|
|
// the following variables will have an effective location of -1:
|
|
bool hasImplicitLocation;
|
|
|
|
// Uniform
|
|
int binding;
|
|
GLenum imageUnitFormat;
|
|
int offset;
|
|
bool readonly;
|
|
bool writeonly;
|
|
|
|
// From EXT_shader_framebuffer_fetch / KHR_blend_equation_advanced
|
|
bool isFragmentInOut;
|
|
|
|
// OutputVariable
|
|
// From EXT_blend_func_extended.
|
|
int index;
|
|
|
|
// From EXT_YUV_target
|
|
bool yuv;
|
|
|
|
// Varying
|
|
InterpolationType interpolation;
|
|
bool isInvariant;
|
|
bool isShaderIOBlock;
|
|
bool isPatch;
|
|
|
|
// If the variable is a sampler that has ever been statically used with texelFetch
|
|
bool texelFetchStaticUse;
|
|
|
|
protected:
|
|
bool isSameVariableAtLinkTime(const ShaderVariable &other,
|
|
bool matchPrecision,
|
|
bool matchName) const;
|
|
|
|
// NOTE: When adding new members, the following functions also need to be updated:
|
|
// gl::WriteShaderVar(BinaryOutputStream *stream, const sh::ShaderVariable &var)
|
|
// gl::LoadShaderVar(BinaryInputStream *stream, sh::ShaderVariable *var)
|
|
|
|
int flattenedOffsetInParentArrays;
|
|
};
|
|
|
|
// TODO: anglebug.com/3899
|
|
// 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();
|
|
~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
|
|
|
|
#endif // GLSLANG_SHADERVARS_H_
|