Commit e670fc72 by Jamie Madill Committed by Commit Bot

Implement shader compiler changes for Tessellation.

Numerous rule changes to support validating Tessellation Control and Evaluation shaders. New per-patch inputs and output variable support. Includes a new traverser step that validates barrier function calls. Functionality changes upcoming in http://crrev.com/c/2568234 Bug: angleproject:3572 Change-Id: If8da1c21d30efa12c60ed0d6c3f8cf0b27e4c86f Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2633936 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarMohan Maiya <m.maiya@samsung.com>
parent 20f8828c
......@@ -26,7 +26,7 @@
// Version number for shader translation API.
// It is incremented every time the API changes.
#define ANGLE_SH_VERSION 250
#define ANGLE_SH_VERSION 251
enum ShShaderSpec
{
......@@ -789,11 +789,20 @@ const std::set<std::string> *GetUsedImage2DFunctionNames(const ShHandle handle);
bool HasValidGeometryShaderInputPrimitiveType(const ShHandle handle);
bool HasValidGeometryShaderOutputPrimitiveType(const ShHandle handle);
bool HasValidGeometryShaderMaxVertices(const ShHandle handle);
bool HasValidTessGenMode(const ShHandle handle);
bool HasValidTessGenSpacing(const ShHandle handle);
bool HasValidTessGenVertexOrder(const ShHandle handle);
bool HasValidTessGenPointMode(const ShHandle handle);
GLenum GetGeometryShaderInputPrimitiveType(const ShHandle handle);
GLenum GetGeometryShaderOutputPrimitiveType(const ShHandle handle);
int GetGeometryShaderInvocations(const ShHandle handle);
int GetGeometryShaderMaxVertices(const ShHandle handle);
unsigned int GetShaderSharedMemorySize(const ShHandle handle);
int GetTessControlShaderVertices(const ShHandle handle);
GLenum GetTessGenMode(const ShHandle handle);
GLenum GetTessGenSpacing(const ShHandle handle);
GLenum GetTessGenVertexOrder(const ShHandle handle);
GLenum GetTessGenPointMode(const ShHandle handle);
//
// Helper function to identify specs that are based on the WebGL spec.
......
......@@ -201,6 +201,8 @@ struct ShaderVariable
InterpolationType interpolation;
bool isInvariant;
bool isShaderIOBlock;
bool isPatch;
// 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:
......
......@@ -6,11 +6,11 @@
"src/compiler/translator/glslang.l":
"a04170178bdc8511bff69ec4ff144576",
"src/compiler/translator/glslang.y":
"1c7a2f4fa0f62ebc42f855bb8a8deeaf",
"d5e97733e569b408728a1645b6763890",
"src/compiler/translator/glslang_lex_autogen.cpp":
"5d6469e58f9855f93987b5ddbd663920",
"src/compiler/translator/glslang_tab_autogen.cpp":
"821a6cccd98a7d89666bfb3fabee3585",
"f4d714cad4bd92c4b9ecfebc81349dc7",
"src/compiler/translator/glslang_tab_autogen.h":
"840c12db9f7824afd05b5306c8816d95",
"tools/flex-bison/linux/bison.sha1":
......
......@@ -92,6 +92,8 @@ angle_translator_sources = [
"src/compiler/translator/Types.h",
"src/compiler/translator/ValidateAST.cpp",
"src/compiler/translator/ValidateAST.h",
"src/compiler/translator/ValidateBarrierFunctionCall.cpp",
"src/compiler/translator/ValidateBarrierFunctionCall.h",
"src/compiler/translator/ValidateClipCullDistance.cpp",
"src/compiler/translator/ValidateClipCullDistance.h",
"src/compiler/translator/ValidateGlobalInitializer.cpp",
......
......@@ -1060,6 +1060,8 @@ inline bool IsShaderIn(TQualifier qualifier)
switch (qualifier)
{
case EvqVertexIn:
case EvqTessControlIn:
case EvqTessEvaluationIn:
case EvqGeometryIn:
case EvqFragmentIn:
case EvqAttribute:
......@@ -1069,6 +1071,7 @@ inline bool IsShaderIn(TQualifier qualifier)
case EvqNoPerspectiveIn:
case EvqCentroidIn:
case EvqSampleIn:
case EvqPatchIn:
return true;
default:
return false;
......@@ -1080,6 +1083,8 @@ inline bool IsShaderOut(TQualifier qualifier)
switch (qualifier)
{
case EvqVertexOut:
case EvqTessControlOut:
case EvqTessEvaluationOut:
case EvqGeometryOut:
case EvqFragmentOut:
case EvqVaryingOut:
......@@ -1088,6 +1093,7 @@ inline bool IsShaderOut(TQualifier qualifier)
case EvqNoPerspectiveOut:
case EvqCentroidOut:
case EvqSampleOut:
case EvqPatchOut:
return true;
default:
return false;
......@@ -1168,6 +1174,20 @@ enum TLayoutPrimitiveType
EptTriangleStrip
};
enum TLayoutTessEvaluationType
{
EtetUndefined,
EtetTriangles,
EtetQuads,
EtetIsolines,
EtetEqualSpacing,
EtetFractionalEvenSpacing,
EtetFractionalOddSpacing,
EtetCw,
EtetCcw,
EtetPointMode
};
struct TLayoutQualifier
{
// Must have a trivial default constructor since it is used in YYSTYPE.
......@@ -1181,7 +1201,9 @@ struct TLayoutQualifier
earlyFragmentTests == false && matrixPacking == EmpUnspecified &&
blockStorage == EbsUnspecified && !localSize.isAnyValueSet() &&
imageInternalFormat == EiifUnspecified && primitiveType == EptUndefined &&
invocations == 0 && maxVertices == -1 && index == -1;
invocations == 0 && maxVertices == -1 && vertices == 0 &&
tesPrimitiveType == EtetUndefined && tesVertexSpacingType == EtetUndefined &&
tesOrderingType == EtetUndefined && tesPointType == EtetUndefined && index == -1;
}
bool isCombinationValid() const
......@@ -1236,6 +1258,13 @@ struct TLayoutQualifier
int invocations;
int maxVertices;
// EXT_tessellation_control shader layout qualifiers
int vertices;
TLayoutTessEvaluationType tesPrimitiveType;
TLayoutTessEvaluationType tesVertexSpacingType;
TLayoutTessEvaluationType tesOrderingType;
TLayoutTessEvaluationType tesPointType;
// EXT_blend_func_extended fragment output layout qualifier
int index;
......@@ -1255,6 +1284,11 @@ struct TLayoutQualifier
primitiveType(EptUndefined),
invocations(0),
maxVertices(-1),
vertices(0),
tesPrimitiveType(EtetUndefined),
tesVertexSpacingType(EtetUndefined),
tesOrderingType(EtetUndefined),
tesPointType(EtetUndefined),
index(-1)
{}
};
......@@ -1324,6 +1358,7 @@ inline const char *getQualifierString(TQualifier q)
case EvqVaryingOut: return "varying";
case EvqUniform: return "uniform";
case EvqBuffer: return "buffer";
case EvqPatch: return "patch";
case EvqVertexIn: return "in";
case EvqFragmentOut: return "out";
case EvqVertexOut: return "out";
......@@ -1389,6 +1424,17 @@ inline const char *getQualifierString(TQualifier q)
case EvqSampleMaskIn: return "SampleMaskIn";
case EvqSampleMask: return "SampleMask";
case EvqNumSamples: return "NumSamples";
case EvqPatchIn: return "patch in";
case EvqPatchOut: return "patch out";
case EvqTessControlIn: return "in";
case EvqTessControlOut: return "out";
case EvqPerVertexOut: return "gl_out";
case EvqPatchVerticesIn: return "PatchVerticesIn";
case EvqTessLevelOuter: return "TessLevelOuter";
case EvqTessLevelInner: return "TessLevelInner";
case EvqTessEvaluationIn: return "in";
case EvqTessEvaluationOut: return "out";
case EvqTessCoord: return "TessCoord";
default: UNREACHABLE(); return "unknown qualifier";
}
// clang-format on
......@@ -1517,6 +1563,34 @@ inline const char *getGeometryShaderPrimitiveTypeString(TLayoutPrimitiveType pri
}
}
inline const char *getTessEvaluationShaderTypeString(TLayoutTessEvaluationType type)
{
switch (type)
{
case EtetTriangles:
return "triangles";
case EtetQuads:
return "quads";
case EtetIsolines:
return "isolines";
case EtetEqualSpacing:
return "equal_spacing";
case EtetFractionalEvenSpacing:
return "fractional_even_spacing";
case EtetFractionalOddSpacing:
return "fractional_odd_spacing";
case EtetCw:
return "cw";
case EtetCcw:
return "ccw";
case EtetPointMode:
return "point_mode";
default:
UNREACHABLE();
return "unknown tessellation evaluation shader variable type";
}
}
} // namespace sh
#endif // COMPILER_TRANSLATOR_BASETYPES_H_
......@@ -30,7 +30,9 @@ void CollectVariables(TIntermBlock *root,
ShHashFunction64 hashFunction,
TSymbolTable *symbolTable,
GLenum shaderType,
const TExtensionBehavior &extensionBehavior);
const TExtensionBehavior &extensionBehavior,
const ShBuiltInResources &resources,
int tessControlShaderOutputVertices);
} // namespace sh
#endif // COMPILER_TRANSLATOR_COLLECTVARIABLES_H_
......@@ -16,6 +16,7 @@
#include "compiler/translator/IsASTDepthBelowLimit.h"
#include "compiler/translator/OutputTree.h"
#include "compiler/translator/ParseContext.h"
#include "compiler/translator/ValidateBarrierFunctionCall.h"
#include "compiler/translator/ValidateClipCullDistance.h"
#include "compiler/translator/ValidateLimitations.h"
#include "compiler/translator/ValidateMaxParameters.h"
......@@ -305,6 +306,11 @@ TCompiler::TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
mGeometryShaderInvocations(0),
mGeometryShaderInputPrimitiveType(EptUndefined),
mGeometryShaderOutputPrimitiveType(EptUndefined),
mTessControlShaderOutputVertices(0),
mTessEvaluationShaderInputPrimitiveType(EtetUndefined),
mTessEvaluationShaderInputVertexSpacingType(EtetUndefined),
mTessEvaluationShaderInputOrderingType(EtetUndefined),
mTessEvaluationShaderInputPointType(EtetUndefined),
mCompileOptions(0)
{}
......@@ -492,6 +498,20 @@ void TCompiler::setASTMetadata(const TParseContext &parseContext)
mGeometryShaderMaxVertices = parseContext.getGeometryShaderMaxVertices();
mGeometryShaderInvocations = parseContext.getGeometryShaderInvocations();
}
if (mShaderType == GL_TESS_CONTROL_SHADER_EXT)
{
mTessControlShaderOutputVertices = parseContext.getTessControlShaderOutputVertices();
}
if (mShaderType == GL_TESS_EVALUATION_SHADER_EXT)
{
mTessEvaluationShaderInputPrimitiveType =
parseContext.getTessEvaluationShaderInputPrimitiveType();
mTessEvaluationShaderInputVertexSpacingType =
parseContext.getTessEvaluationShaderInputVertexSpacingType();
mTessEvaluationShaderInputOrderingType =
parseContext.getTessEvaluationShaderInputOrderingType();
mTessEvaluationShaderInputPointType = parseContext.getTessEvaluationShaderInputPointType();
}
}
unsigned int TCompiler::getSharedMemorySize() const
......@@ -620,6 +640,11 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root,
return false;
}
if (mShaderType == GL_TESS_CONTROL_SHADER && !ValidateBarrierFunctionCall(root, &mDiagnostics))
{
return false;
}
// Fail compilation if precision emulation not supported.
if (getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision &&
!EmulatePrecision::SupportedInLanguage(mOutputType))
......@@ -816,7 +841,7 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root,
CollectVariables(root, &mAttributes, &mOutputVariables, &mUniforms, &mInputVaryings,
&mOutputVaryings, &mSharedVariables, &mUniformBlocks,
&mShaderStorageBlocks, mResources.HashFunction, &mSymbolTable, mShaderType,
mExtensionBehavior);
mExtensionBehavior, mResources, mTessControlShaderOutputVertices);
collectInterfaceBlocks();
mVariablesCollected = true;
if ((compileOptions & SH_USE_UNUSED_STANDARD_SHARED_BLOCKS) != 0)
......@@ -1115,6 +1140,7 @@ void TCompiler::setResourceString()
<< ":EXT_shadow_samplers:" << mResources.EXT_shadow_samplers
<< ":OES_shader_multisample_interpolation:" << mResources.OES_shader_multisample_interpolation
<< ":OES_shader_image_atomic:" << mResources.OES_shader_image_atomic
<< ":EXT_tessellation_shader:" << mResources.EXT_tessellation_shader
<< ":OES_texture_buffer:" << mResources.OES_texture_buffer
<< ":EXT_texture_buffer:" << mResources.EXT_texture_buffer
<< ":OES_sample_variables:" << mResources.OES_sample_variables
......@@ -1160,7 +1186,25 @@ void TCompiler::setResourceString()
<< ":MaxGeometryImageUniforms:" << mResources.MaxGeometryImageUniforms
<< ":MaxClipDistances" << mResources.MaxClipDistances
<< ":MaxCullDistances" << mResources.MaxCullDistances
<< ":MaxCombinedClipAndCullDistances" << mResources.MaxCombinedClipAndCullDistances;
<< ":MaxCombinedClipAndCullDistances" << mResources.MaxCombinedClipAndCullDistances
<< ":MaxTessControlInputComponents:" << mResources.MaxTessControlInputComponents
<< ":MaxTessControlOutputComponents:" << mResources.MaxTessControlOutputComponents
<< ":MaxTessControlTextureImageUnits:" << mResources.MaxTessControlTextureImageUnits
<< ":MaxTessControlUniformComponents:" << mResources.MaxTessControlUniformComponents
<< ":MaxTessControlTotalOutputComponents:" << mResources.MaxTessControlTotalOutputComponents
<< ":MaxTessControlImageUniforms:" << mResources.MaxTessControlImageUniforms
<< ":MaxTessControlAtomicCounters:" << mResources.MaxTessControlAtomicCounters
<< ":MaxTessControlAtomicCounterBuffers:" << mResources.MaxTessControlAtomicCounterBuffers
<< ":MaxTessPatchComponents:" << mResources.MaxTessPatchComponents
<< ":MaxPatchVertices:" << mResources.MaxPatchVertices
<< ":MaxTessGenLevel:" << mResources.MaxTessGenLevel
<< ":MaxTessEvaluationInputComponents:" << mResources.MaxTessEvaluationInputComponents
<< ":MaxTessEvaluationOutputComponents:" << mResources.MaxTessEvaluationOutputComponents
<< ":MaxTessEvaluationTextureImageUnits:" << mResources.MaxTessEvaluationTextureImageUnits
<< ":MaxTessEvaluationUniformComponents:" << mResources.MaxTessEvaluationUniformComponents
<< ":MaxTessEvaluationImageUniforms:" << mResources.MaxTessEvaluationImageUniforms
<< ":MaxTessEvaluationAtomicCounters:" << mResources.MaxTessEvaluationAtomicCounters
<< ":MaxTessEvaluationAtomicCounterBuffers:" << mResources.MaxTessEvaluationAtomicCounterBuffers;
// clang-format on
mBuiltInResourcesString = strstream.str();
......@@ -1222,6 +1266,12 @@ void TCompiler::clearResults()
mGeometryShaderInvocations = 0;
mGeometryShaderMaxVertices = -1;
mTessControlShaderOutputVertices = 0;
mTessEvaluationShaderInputPrimitiveType = EtetUndefined;
mTessEvaluationShaderInputVertexSpacingType = EtetUndefined;
mTessEvaluationShaderInputOrderingType = EtetUndefined;
mTessEvaluationShaderInputPointType = EtetUndefined;
mBuiltInFunctionEmulator.cleanup();
mNameMap.clear();
......
......@@ -148,6 +148,25 @@ class TCompiler : public TShHandleBase
}
unsigned int getStructSize(const ShaderVariable &var) const;
int getTessControlShaderOutputVertices() const { return mTessControlShaderOutputVertices; }
TLayoutTessEvaluationType getTessEvaluationShaderInputPrimitiveType() const
{
return mTessEvaluationShaderInputPrimitiveType;
}
TLayoutTessEvaluationType getTessEvaluationShaderInputVertexSpacingType() const
{
return mTessEvaluationShaderInputVertexSpacingType;
}
TLayoutTessEvaluationType getTessEvaluationShaderInputOrderingType() const
{
return mTessEvaluationShaderInputOrderingType;
}
TLayoutTessEvaluationType getTessEvaluationShaderInputPointType() const
{
return mTessEvaluationShaderInputPointType;
}
unsigned int getSharedMemorySize() const;
sh::GLenum getShaderType() const { return mShaderType; }
......@@ -299,6 +318,13 @@ class TCompiler : public TShHandleBase
TLayoutPrimitiveType mGeometryShaderInputPrimitiveType;
TLayoutPrimitiveType mGeometryShaderOutputPrimitiveType;
// tesssellation shader parameters
int mTessControlShaderOutputVertices;
TLayoutTessEvaluationType mTessEvaluationShaderInputPrimitiveType;
TLayoutTessEvaluationType mTessEvaluationShaderInputVertexSpacingType;
TLayoutTessEvaluationType mTessEvaluationShaderInputOrderingType;
TLayoutTessEvaluationType mTessEvaluationShaderInputPointType;
// name hashing.
NameMap mNameMap;
......
......@@ -1404,7 +1404,8 @@ void TOutputGLSLBase::declareInterfaceBlock(const TType &type)
const TFieldList &fields = interfaceBlock->fields();
for (const TField *field : fields)
{
if (!IsShaderIoBlock(type.getQualifier()))
if (!IsShaderIoBlock(type.getQualifier()) && type.getQualifier() != EvqPatchIn &&
type.getQualifier() != EvqPatchOut)
{
writeFieldLayoutQualifier(field);
}
......@@ -1473,6 +1474,40 @@ void WriteGeometryShaderLayoutQualifiers(TInfoSinkBase &out,
}
}
void WriteTessControlShaderLayoutQualifiers(TInfoSinkBase &out, int inputVertices)
{
if (inputVertices != 0)
{
out << "layout (vertices = " << inputVertices << ") out;\n";
}
}
void WriteTessEvaluationShaderLayoutQualifiers(TInfoSinkBase &out,
sh::TLayoutTessEvaluationType inputPrimitive,
sh::TLayoutTessEvaluationType inputVertexSpacing,
sh::TLayoutTessEvaluationType inputOrdering,
sh::TLayoutTessEvaluationType inputPoint)
{
if (inputPrimitive != EtetUndefined)
{
out << "layout (";
out << getTessEvaluationShaderTypeString(inputPrimitive);
if (inputVertexSpacing != EtetUndefined)
{
out << ", " << getTessEvaluationShaderTypeString(inputVertexSpacing);
}
if (inputOrdering != EtetUndefined)
{
out << ", " << getTessEvaluationShaderTypeString(inputOrdering);
}
if (inputPoint != EtetUndefined)
{
out << ", " << getTessEvaluationShaderTypeString(inputPoint);
}
out << ") in;\n";
}
}
// If SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS is enabled, layout qualifiers are spilled whenever
// variables with specified layout qualifiers are copied. Additional checks are needed against the
// type and storage qualifier of the variable to verify that layout qualifiers have to be outputted.
......
......@@ -129,6 +129,14 @@ void WriteGeometryShaderLayoutQualifiers(TInfoSinkBase &out,
sh::TLayoutPrimitiveType outputPrimitive,
int maxVertices);
void WriteTessControlShaderLayoutQualifiers(TInfoSinkBase &out, int inputVertices);
void WriteTessEvaluationShaderLayoutQualifiers(TInfoSinkBase &out,
sh::TLayoutTessEvaluationType inputPrimitive,
sh::TLayoutTessEvaluationType inputVertexSpacing,
sh::TLayoutTessEvaluationType inputOrdering,
sh::TLayoutTessEvaluationType inputPoint);
bool NeedsToWriteLayoutQualifier(const TType &type);
} // namespace sh
......
......@@ -177,7 +177,7 @@ class TParseContext : angle::NonCopyable
// Done only for empty declarations.
void emptyDeclarationErrorCheck(const TType &type, const TSourceLoc &location);
void checkLayoutQualifierSupported(const TSourceLoc &location,
bool checkLayoutQualifierSupported(const TSourceLoc &location,
const ImmutableString &layoutQualifierName,
int versionRequired);
bool checkWorkGroupSizeIsNotSpecified(const TSourceLoc &location,
......@@ -380,6 +380,10 @@ class TParseContext : angle::NonCopyable
const TSourceLoc &intValueLine,
const std::string &intValueString,
int *numMaxVertices);
void parseVertices(int intValue,
const TSourceLoc &intValueLine,
const std::string &intValueString,
int *numVertices);
void parseIndexLayoutQualifier(int intValue,
const TSourceLoc &intValueLine,
const std::string &intValueString,
......@@ -465,6 +469,23 @@ class TParseContext : angle::NonCopyable
{
return mGeometryShaderOutputPrimitiveType;
}
int getTessControlShaderOutputVertices() const { return mTessControlShaderOutputVertices; }
TLayoutTessEvaluationType getTessEvaluationShaderInputPrimitiveType() const
{
return mTessEvaluationShaderInputPrimitiveType;
}
TLayoutTessEvaluationType getTessEvaluationShaderInputVertexSpacingType() const
{
return mTessEvaluationShaderInputVertexSpacingType;
}
TLayoutTessEvaluationType getTessEvaluationShaderInputOrderingType() const
{
return mTessEvaluationShaderInputOrderingType;
}
TLayoutTessEvaluationType getTessEvaluationShaderInputPointType() const
{
return mTessEvaluationShaderInputPointType;
}
ShShaderOutput getOutputType() const { return mOutputType; }
......@@ -574,6 +595,11 @@ class TParseContext : angle::NonCopyable
const ImmutableString &token,
TType *type);
// Similar, for tessellation shaders.
void checkTessellationShaderUnsizedArraysAndSetSize(const TSourceLoc &location,
const ImmutableString &token,
TType *type);
// Will size any unsized array type so unsized arrays won't need to be taken into account
// further along the line in parsing.
void checkIsNotUnsizedArray(const TSourceLoc &line,
......@@ -616,6 +642,9 @@ class TParseContext : angle::NonCopyable
bool parseGeometryShaderOutputLayoutQualifier(const TTypeQualifier &typeQualifier);
void setGeometryShaderInputArraySize(unsigned int inputArraySize, const TSourceLoc &line);
bool parseTessControlShaderOutputLayoutQualifier(const TTypeQualifier &typeQualifier);
bool parseTessEvaluationShaderInputLayoutQualifier(const TTypeQualifier &typeQualifier);
// Set to true when the last/current declarator list was started with an empty declaration. The
// non-empty declaration error check will need to be performed if the empty declaration is
// followed by a declarator.
......@@ -681,6 +710,13 @@ class TParseContext : angle::NonCopyable
int mMaxGeometryShaderMaxVertices;
unsigned int mGeometryInputArraySize;
int mMaxPatchVertices;
int mTessControlShaderOutputVertices;
TLayoutTessEvaluationType mTessEvaluationShaderInputPrimitiveType;
TLayoutTessEvaluationType mTessEvaluationShaderInputVertexSpacingType;
TLayoutTessEvaluationType mTessEvaluationShaderInputOrderingType;
TLayoutTessEvaluationType mTessEvaluationShaderInputPointType;
// Track when we add new scope for func body in ESSL 1.00 spec
bool mFunctionBodyNewScope;
......
......@@ -372,10 +372,14 @@ bool JoinVariableStorageQualifier(TQualifier *joinedQualifier, TQualifier storag
break;
case EvqVertexOut:
case EvqGeometryOut:
case EvqTessControlOut:
case EvqTessEvaluationOut:
*joinedQualifier = EvqSmoothOut;
break;
case EvqFragmentIn:
case EvqGeometryIn:
case EvqTessControlIn:
case EvqTessEvaluationIn:
*joinedQualifier = EvqSmoothIn;
break;
default:
......@@ -392,10 +396,14 @@ bool JoinVariableStorageQualifier(TQualifier *joinedQualifier, TQualifier storag
break;
case EvqVertexOut:
case EvqGeometryOut:
case EvqTessControlOut:
case EvqTessEvaluationOut:
*joinedQualifier = EvqFlatOut;
break;
case EvqFragmentIn:
case EvqGeometryIn:
case EvqTessControlIn:
case EvqTessEvaluationIn:
*joinedQualifier = EvqFlatIn;
break;
default:
......@@ -412,10 +420,14 @@ bool JoinVariableStorageQualifier(TQualifier *joinedQualifier, TQualifier storag
break;
case EvqVertexOut:
case EvqGeometryOut:
case EvqTessControlOut:
case EvqTessEvaluationOut:
*joinedQualifier = EvqNoPerspectiveOut;
break;
case EvqFragmentIn:
case EvqGeometryIn:
case EvqTessControlIn:
case EvqTessEvaluationIn:
*joinedQualifier = EvqNoPerspectiveIn;
break;
default:
......@@ -429,10 +441,14 @@ bool JoinVariableStorageQualifier(TQualifier *joinedQualifier, TQualifier storag
{
case EvqVertexOut:
case EvqGeometryOut:
case EvqTessControlOut:
case EvqTessEvaluationOut:
*joinedQualifier = EvqCentroidOut;
break;
case EvqFragmentIn:
case EvqGeometryIn:
case EvqTessControlIn:
case EvqTessEvaluationIn:
*joinedQualifier = EvqCentroidIn;
break;
default:
......@@ -446,10 +462,14 @@ bool JoinVariableStorageQualifier(TQualifier *joinedQualifier, TQualifier storag
{
case EvqVertexOut:
case EvqGeometryOut:
case EvqTessControlOut:
case EvqTessEvaluationOut:
*joinedQualifier = EvqSampleOut;
break;
case EvqFragmentIn:
case EvqGeometryIn:
case EvqTessControlIn:
case EvqTessEvaluationIn:
*joinedQualifier = EvqSampleIn;
break;
default:
......@@ -457,6 +477,21 @@ bool JoinVariableStorageQualifier(TQualifier *joinedQualifier, TQualifier storag
}
break;
}
case EvqPatch:
{
switch (storageQualifier)
{
case EvqTessControlOut:
*joinedQualifier = EvqPatchOut;
break;
case EvqTessEvaluationIn:
*joinedQualifier = EvqPatchIn;
break;
default:
return false;
}
break;
}
default:
return false;
}
......@@ -757,6 +792,48 @@ TLayoutQualifier JoinLayoutQualifiers(TLayoutQualifier leftQualifier,
joinedQualifier.maxVertices = rightQualifier.maxVertices;
}
if (rightQualifier.tesPrimitiveType != EtetUndefined)
{
if (joinedQualifier.tesPrimitiveType == EtetUndefined)
{
joinedQualifier.tesPrimitiveType = rightQualifier.tesPrimitiveType;
}
}
if (rightQualifier.tesVertexSpacingType != EtetUndefined)
{
if (joinedQualifier.tesVertexSpacingType == EtetUndefined)
{
joinedQualifier.tesVertexSpacingType = rightQualifier.tesVertexSpacingType;
}
}
if (rightQualifier.tesOrderingType != EtetUndefined)
{
if (joinedQualifier.tesOrderingType == EtetUndefined)
{
joinedQualifier.tesOrderingType = rightQualifier.tesOrderingType;
}
}
if (rightQualifier.tesPointType != EtetUndefined)
{
if (joinedQualifier.tesPointType == EtetUndefined)
{
joinedQualifier.tesPointType = rightQualifier.tesPointType;
}
}
if (rightQualifier.vertices != 0)
{
if (joinedQualifier.vertices != 0 && joinedQualifier.vertices != rightQualifier.vertices)
{
diagnostics->error(rightQualifierLocation,
"Cannot have multiple different vertices specifiers", "vertices");
}
joinedQualifier.vertices = rightQualifier.vertices;
}
if (rightQualifier.index != -1)
{
if (joinedQualifier.index != -1)
......
......@@ -102,6 +102,36 @@ GLenum GetGeometryShaderPrimitiveTypeEnum(sh::TLayoutPrimitiveType primitiveType
}
}
GLenum GetTessellationShaderTypeEnum(sh::TLayoutTessEvaluationType type)
{
switch (type)
{
case EtetTriangles:
return GL_TRIANGLES;
case EtetQuads:
return GL_QUADS;
case EtetIsolines:
return GL_ISOLINES;
case EtetEqualSpacing:
return GL_EQUAL;
case EtetFractionalEvenSpacing:
return GL_FRACTIONAL_EVEN;
case EtetFractionalOddSpacing:
return GL_FRACTIONAL_ODD;
case EtetCw:
return GL_CW;
case EtetCcw:
return GL_CCW;
case EtetPointMode:
return GL_TESS_GEN_POINT_MODE;
case EtetUndefined:
default:
UNREACHABLE();
return GL_INVALID_VALUE;
}
}
} // anonymous namespace
//
......@@ -713,6 +743,50 @@ bool HasValidGeometryShaderMaxVertices(const ShHandle handle)
return compiler->getGeometryShaderMaxVertices() >= 0;
}
bool HasValidTessGenMode(const ShHandle handle)
{
ASSERT(handle);
TShHandleBase *base = static_cast<TShHandleBase *>(handle);
TCompiler *compiler = base->getAsCompiler();
ASSERT(compiler);
return compiler->getTessEvaluationShaderInputPrimitiveType() != EtetUndefined;
}
bool HasValidTessGenSpacing(const ShHandle handle)
{
ASSERT(handle);
TShHandleBase *base = static_cast<TShHandleBase *>(handle);
TCompiler *compiler = base->getAsCompiler();
ASSERT(compiler);
return compiler->getTessEvaluationShaderInputVertexSpacingType() != EtetUndefined;
}
bool HasValidTessGenVertexOrder(const ShHandle handle)
{
ASSERT(handle);
TShHandleBase *base = static_cast<TShHandleBase *>(handle);
TCompiler *compiler = base->getAsCompiler();
ASSERT(compiler);
return compiler->getTessEvaluationShaderInputOrderingType() != EtetUndefined;
}
bool HasValidTessGenPointMode(const ShHandle handle)
{
ASSERT(handle);
TShHandleBase *base = static_cast<TShHandleBase *>(handle);
TCompiler *compiler = base->getAsCompiler();
ASSERT(compiler);
return compiler->getTessEvaluationShaderInputPointType() != EtetUndefined;
}
GLenum GetGeometryShaderInputPrimitiveType(const ShHandle handle)
{
ASSERT(handle);
......@@ -759,6 +833,62 @@ int GetGeometryShaderMaxVertices(const ShHandle handle)
return maxVertices;
}
int GetTessControlShaderVertices(const ShHandle handle)
{
ASSERT(handle);
TShHandleBase *base = static_cast<TShHandleBase *>(handle);
TCompiler *compiler = base->getAsCompiler();
ASSERT(compiler);
int vertices = compiler->getTessControlShaderOutputVertices();
return vertices;
}
GLenum GetTessGenMode(const ShHandle handle)
{
ASSERT(handle);
TShHandleBase *base = static_cast<TShHandleBase *>(handle);
TCompiler *compiler = base->getAsCompiler();
ASSERT(compiler);
return GetTessellationShaderTypeEnum(compiler->getTessEvaluationShaderInputPrimitiveType());
}
GLenum GetTessGenSpacing(const ShHandle handle)
{
ASSERT(handle);
TShHandleBase *base = static_cast<TShHandleBase *>(handle);
TCompiler *compiler = base->getAsCompiler();
ASSERT(compiler);
return GetTessellationShaderTypeEnum(compiler->getTessEvaluationShaderInputVertexSpacingType());
}
GLenum GetTessGenVertexOrder(const ShHandle handle)
{
ASSERT(handle);
TShHandleBase *base = static_cast<TShHandleBase *>(handle);
TCompiler *compiler = base->getAsCompiler();
ASSERT(compiler);
return GetTessellationShaderTypeEnum(compiler->getTessEvaluationShaderInputOrderingType());
}
GLenum GetTessGenPointMode(const ShHandle handle)
{
ASSERT(handle);
TShHandleBase *base = static_cast<TShHandleBase *>(handle);
TCompiler *compiler = base->getAsCompiler();
ASSERT(compiler);
return GetTessellationShaderTypeEnum(compiler->getTessEvaluationShaderInputPointType());
}
unsigned int GetShaderSharedMemorySize(const ShHandle handle)
{
ASSERT(handle);
......
......@@ -51,6 +51,7 @@ ShaderVariable::ShaderVariable(GLenum typeIn)
interpolation(INTERPOLATION_SMOOTH),
isInvariant(false),
isShaderIOBlock(false),
isPatch(false),
texelFetchStaticUse(false),
flattenedOffsetInParentArrays(-1)
{}
......@@ -87,6 +88,7 @@ ShaderVariable::ShaderVariable(const ShaderVariable &other)
interpolation(other.interpolation),
isInvariant(other.isInvariant),
isShaderIOBlock(other.isShaderIOBlock),
isPatch(other.isPatch),
texelFetchStaticUse(other.texelFetchStaticUse),
flattenedOffsetInParentArrays(other.flattenedOffsetInParentArrays)
{}
......@@ -117,6 +119,7 @@ ShaderVariable &ShaderVariable::operator=(const ShaderVariable &other)
interpolation = other.interpolation;
isInvariant = other.isInvariant;
isShaderIOBlock = other.isShaderIOBlock;
isPatch = other.isPatch;
texelFetchStaticUse = other.texelFetchStaticUse;
return *this;
}
......@@ -133,7 +136,7 @@ bool ShaderVariable::operator==(const ShaderVariable &other) const
offset != other.offset || readonly != other.readonly || writeonly != other.writeonly ||
index != other.index || yuv != other.yuv || interpolation != other.interpolation ||
isInvariant != other.isInvariant || isShaderIOBlock != other.isShaderIOBlock ||
texelFetchStaticUse != other.texelFetchStaticUse)
isPatch != other.isPatch || texelFetchStaticUse != other.texelFetchStaticUse)
{
return false;
}
......@@ -444,7 +447,7 @@ bool ShaderVariable::isSameVaryingAtLinkTime(const ShaderVariable &other, int sh
return ShaderVariable::isSameVariableAtLinkTime(other, false, false) &&
InterpolationTypesMatch(interpolation, other.interpolation) &&
(shaderVersion >= 300 || isInvariant == other.isInvariant) &&
location == other.location &&
(isPatch == other.isPatch) && location == other.location &&
(isSameNameAtLinkTime(other) || (shaderVersion >= 310 && location >= 0));
}
......
......@@ -39,6 +39,10 @@ bool CheckShaderType(Shader expected, GLenum actual)
return actual == GL_GEOMETRY_SHADER;
case Shader::GEOMETRY_EXT:
return actual == GL_GEOMETRY_SHADER_EXT;
case Shader::TESS_CONTROL_EXT:
return actual == GL_TESS_CONTROL_SHADER_EXT;
case Shader::TESS_EVALUATION_EXT:
return actual == GL_TESS_EVALUATION_SHADER_EXT;
case Shader::NOT_COMPUTE:
return actual != GL_COMPUTE_SHADER;
default:
......@@ -411,6 +415,8 @@ void TSymbolTable::initializeBuiltIns(sh::GLenum type,
case GL_VERTEX_SHADER:
case GL_COMPUTE_SHADER:
case GL_GEOMETRY_SHADER_EXT:
case GL_TESS_CONTROL_SHADER_EXT:
case GL_TESS_EVALUATION_SHADER_EXT:
setDefaultPrecision(EbtInt, EbpHigh);
setDefaultPrecision(EbtFloat, EbpHigh);
break;
......
......@@ -171,6 +171,8 @@ constexpr ImmutableString kFlippedFragCoordName = ImmutableString("flippedFragC
constexpr gl::ShaderMap<const char *> kDefaultUniformNames = {
{gl::ShaderType::Vertex, vk::kDefaultUniformsNameVS},
{gl::ShaderType::TessControl, vk::kDefaultUniformsNameTCS},
{gl::ShaderType::TessEvaluation, vk::kDefaultUniformsNameTES},
{gl::ShaderType::Geometry, vk::kDefaultUniformsNameGS},
{gl::ShaderType::Fragment, vk::kDefaultUniformsNameFS},
{gl::ShaderType::Compute, vk::kDefaultUniformsNameCS},
......@@ -1156,6 +1158,22 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root,
break;
}
case gl::ShaderType::TessControl:
{
WriteTessControlShaderLayoutQualifiers(sink, getTessControlShaderOutputVertices());
break;
}
case gl::ShaderType::TessEvaluation:
{
WriteTessEvaluationShaderLayoutQualifiers(
sink, getTessEvaluationShaderInputPrimitiveType(),
getTessEvaluationShaderInputVertexSpacingType(),
getTessEvaluationShaderInputOrderingType(),
getTessEvaluationShaderInputPointType());
break;
}
case gl::ShaderType::Compute:
{
EmitWorkGroupSizeGLSL(*this, sink);
......
//
// Copyright 2020 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.
//
// ValidateBarrierFunctionCalls:
// Runs compilation checks related to the "barrier built-in function.
#include "compiler/translator/ValidateBarrierFunctionCall.h"
#include "compiler/translator/Diagnostics.h"
#include "compiler/translator/SymbolTable.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
namespace sh
{
namespace
{
class Traverser : public TIntermTraverser
{
public:
Traverser(TDiagnostics *diagnostics)
: TIntermTraverser(true, false, true), mDiagnostics(diagnostics)
{}
bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override
{
if (!node->getFunction()->isMain())
{
return false;
}
mInMain = visit == PreVisit;
return true;
}
bool visitBranch(Visit visit, TIntermBranch *branch) override
{
if (branch->getFlowOp() == EOpReturn)
{
mSeenReturn = true;
}
return true;
}
bool visitAggregate(Visit visit, TIntermAggregate *node) override
{
if (node->getOp() != EOpBarrier)
{
return true;
}
if (mSeenReturn)
{
mDiagnostics->error(node->getLine(),
"barrier() may not be called at any point after a return statement "
"in the function main().",
"barrier");
mValid = false;
return false;
}
// TODO(anglebug.com/5557): Determine if we should check loops as well.
if (mBranchCount > 0)
{
mDiagnostics->error(
node->getLine(),
"barrier() may not be called in potentially divergent flow control.", "barrier");
mValid = false;
return false;
}
return true;
}
bool visitIfElse(Visit visit, TIntermIfElse *node) override
{
mBranchCount += ((visit == PreVisit) ? 1 : -1);
return true;
}
bool valid() const { return mValid; }
private:
TDiagnostics *mDiagnostics = nullptr;
bool mInMain = false;
bool mSeenReturn = false;
bool mValid = true;
uint32_t mBranchCount = 0;
};
} // anonymous namespace
bool ValidateBarrierFunctionCall(TIntermBlock *root, TDiagnostics *diagnostics)
{
Traverser traverser(diagnostics);
root->traverse(&traverser);
return traverser.valid();
}
} // namespace sh
//
// Copyright 2020 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.
//
// ValidateBarrierFunctionCalls:
// Runs compilation checks related to the "barrier built-in function.
#ifndef COMPILER_TRANSLATOR_VALIDATEBARRIERFUNCTIONCALL_H_
#define COMPILER_TRANSLATOR_VALIDATEBARRIERFUNCTIONCALL_H_
#include "common/angleutils.h"
namespace sh
{
class TDiagnostics;
class TIntermBlock;
ANGLE_NO_DISCARD bool ValidateBarrierFunctionCall(TIntermBlock *root, TDiagnostics *diagnostics);
} // namespace sh
#endif // COMPILER_TRANSLATOR_VALIDATEBARRIERFUNCTIONCALL_H_
......@@ -116,6 +116,22 @@ int GetLocationCount(const TIntermSymbol *varying, bool ignoreVaryingArraySize)
return elementLocationCount * varyingType.getArraySizeProduct();
}
bool ShouldIgnoreVaryingArraySize(TQualifier qualifier, GLenum shaderType)
{
bool isVaryingIn = IsShaderIn(qualifier) && qualifier != EvqPatchIn;
switch (shaderType)
{
case GL_GEOMETRY_SHADER:
case GL_TESS_EVALUATION_SHADER:
return isVaryingIn;
case GL_TESS_CONTROL_SHADER:
return (IsShaderOut(qualifier) && qualifier != EvqPatchOut) || isVaryingIn;
default:
return false;
}
}
struct SymbolAndField
{
const TIntermSymbol *symbol;
......@@ -159,9 +175,9 @@ void MarkVaryingLocations(TDiagnostics *diagnostics,
using VaryingVector = std::vector<const TIntermSymbol *>;
void ValidateShaderInterface(TDiagnostics *diagnostics,
VaryingVector &varyingVector,
bool ignoreVaryingArraySize)
void ValidateShaderInterfaceAndAssignLocations(TDiagnostics *diagnostics,
const VaryingVector &varyingVector,
GLenum shaderType)
{
// Location conflicts can only happen when there are two or more varyings in varyingVector.
if (varyingVector.size() <= 1)
......@@ -176,6 +192,9 @@ void ValidateShaderInterface(TDiagnostics *diagnostics,
const int location = varyingType.getLayoutQualifier().location;
ASSERT(location >= 0);
bool ignoreVaryingArraySize =
ShouldIgnoreVaryingArraySize(varying->getQualifier(), shaderType);
// A varying is either:
//
// - A vector or matrix, which can take a number of contiguous locations
......@@ -318,9 +337,9 @@ void ValidateVaryingLocationsTraverser::validate(TDiagnostics *diagnostics)
{
ASSERT(diagnostics);
ValidateShaderInterface(diagnostics, mInputVaryingsWithLocation,
mShaderType == GL_GEOMETRY_SHADER_EXT);
ValidateShaderInterface(diagnostics, mOutputVaryingsWithLocation, false);
ValidateShaderInterfaceAndAssignLocations(diagnostics, mInputVaryingsWithLocation, mShaderType);
ValidateShaderInterfaceAndAssignLocations(diagnostics, mOutputVaryingsWithLocation,
mShaderType);
}
} // anonymous namespace
......@@ -329,8 +348,7 @@ unsigned int CalculateVaryingLocationCount(TIntermSymbol *varying, GLenum shader
{
const TType &varyingType = varying->getType();
const TQualifier qualifier = varyingType.getQualifier();
const bool isShaderIn = IsShaderIn(qualifier);
const bool ignoreVaryingArraySize = isShaderIn && shaderType == GL_GEOMETRY_SHADER_EXT;
const bool ignoreVaryingArraySize = ShouldIgnoreVaryingArraySize(qualifier, shaderType);
if (varyingType.isInterfaceBlock())
{
......
......@@ -868,7 +868,11 @@ storage_qualifier
$$ = new TStorageQualifierWrapper(EvqCentroid, @1);
}
| PATCH {
ES3_1_OR_NEWER("patch", @1, "storage qualifier");
if (context->getShaderVersion() < 320 &&
!context->checkCanUseExtension(@1, TExtension::EXT_tessellation_shader))
{
context->error(@1, "unsupported storage qualifier", "patch");
}
$$ = new TStorageQualifierWrapper(EvqPatch, @1);
}
| UNIFORM {
......
......@@ -752,19 +752,19 @@ static const yytype_uint16 yyrline[] = {
557, 561, 565, 569, 573, 580, 583, 589, 596, 603, 606, 609, 613, 617, 621, 625,
629, 636, 643, 646, 653, 661, 678, 688, 691, 697, 701, 705, 709, 716, 723, 726,
730, 734, 739, 746, 750, 754, 758, 763, 770, 774, 780, 783, 786, 796, 800, 807,
813, 819, 823, 827, 830, 833, 837, 845, 850, 854, 857, 860, 863, 866, 870, 874,
877, 881, 884, 887, 890, 893, 896, 900, 907, 914, 917, 920, 926, 933, 936, 942,
945, 948, 951, 957, 960, 967, 972, 979, 984, 995, 998, 1001, 1004, 1007, 1010, 1014,
1018, 1022, 1026, 1030, 1034, 1038, 1042, 1046, 1050, 1054, 1058, 1062, 1066, 1070, 1074, 1078,
1082, 1086, 1090, 1094, 1101, 1104, 1107, 1110, 1113, 1116, 1119, 1127, 1135, 1145, 1148, 1151,
1154, 1157, 1160, 1163, 1171, 1179, 1189, 1192, 1195, 1198, 1201, 1204, 1207, 1215, 1223, 1233,
1236, 1239, 1242, 1250, 1258, 1265, 1275, 1282, 1289, 1292, 1295, 1298, 1301, 1304, 1307, 1310,
1313, 1316, 1319, 1322, 1325, 1333, 1341, 1349, 1357, 1365, 1373, 1383, 1393, 1403, 1406, 1409,
1417, 1417, 1420, 1420, 1426, 1429, 1435, 1438, 1445, 1449, 1455, 1458, 1464, 1468, 1472, 1473,
1479, 1480, 1481, 1482, 1483, 1484, 1485, 1489, 1493, 1493, 1493, 1500, 1501, 1505, 1505, 1506,
1506, 1511, 1515, 1522, 1526, 1533, 1534, 1538, 1544, 1548, 1557, 1557, 1564, 1567, 1573, 1577,
1583, 1583, 1588, 1588, 1592, 1592, 1600, 1603, 1609, 1612, 1618, 1622, 1629, 1632, 1635, 1638,
1641, 1649, 1655, 1661, 1664, 1670, 1670};
813, 819, 823, 827, 830, 833, 837, 845, 850, 854, 857, 860, 863, 866, 870, 878,
881, 885, 888, 891, 894, 897, 900, 904, 911, 918, 921, 924, 930, 937, 940, 946,
949, 952, 955, 961, 964, 971, 976, 983, 988, 999, 1002, 1005, 1008, 1011, 1014, 1018,
1022, 1026, 1030, 1034, 1038, 1042, 1046, 1050, 1054, 1058, 1062, 1066, 1070, 1074, 1078, 1082,
1086, 1090, 1094, 1098, 1105, 1108, 1111, 1114, 1117, 1120, 1123, 1131, 1139, 1149, 1152, 1155,
1158, 1161, 1164, 1167, 1175, 1183, 1193, 1196, 1199, 1202, 1205, 1208, 1211, 1219, 1227, 1237,
1240, 1243, 1246, 1254, 1262, 1269, 1279, 1286, 1293, 1296, 1299, 1302, 1305, 1308, 1311, 1314,
1317, 1320, 1323, 1326, 1329, 1337, 1345, 1353, 1361, 1369, 1377, 1387, 1397, 1407, 1410, 1413,
1421, 1421, 1424, 1424, 1430, 1433, 1439, 1442, 1449, 1453, 1459, 1462, 1468, 1472, 1476, 1477,
1483, 1484, 1485, 1486, 1487, 1488, 1489, 1493, 1497, 1497, 1497, 1504, 1505, 1509, 1509, 1510,
1510, 1515, 1519, 1526, 1530, 1537, 1538, 1542, 1548, 1552, 1561, 1561, 1568, 1571, 1577, 1581,
1587, 1587, 1592, 1592, 1596, 1596, 1604, 1607, 1613, 1616, 1622, 1626, 1633, 1636, 1639, 1642,
1645, 1653, 1659, 1665, 1668, 1674, 1674};
#endif
#if YYDEBUG || YYERROR_VERBOSE || 0
......@@ -3670,7 +3670,11 @@ yyreduce:
case 142:
{
ES3_1_OR_NEWER("patch", (yylsp[0]), "storage qualifier");
if (context->getShaderVersion() < 320 &&
!context->checkCanUseExtension((yylsp[0]), TExtension::EXT_tessellation_shader))
{
context->error((yylsp[0]), "unsupported storage qualifier", "patch");
}
(yyval.interm.qualifierWrapper) = new TStorageQualifierWrapper(EvqPatch, (yylsp[0]));
}
......
......@@ -102,7 +102,8 @@ bool RemoveInactiveInterfaceVariablesTraverser::visitDeclaration(Visit visit,
// When a member has an explicit location, interface block should not be removed.
// If the member or interface would be removed, GetProgramResource could not return the
// location.
if (!IsShaderIoBlock(type.getQualifier()))
if (!IsShaderIoBlock(type.getQualifier()) && type.getQualifier() != EvqPatchIn &&
type.getQualifier() != EvqPatchOut)
{
removeDeclaration =
!IsVariableActive(mInterfaceBlocks, type.getInterfaceBlock()->name());
......
......@@ -26,7 +26,6 @@ namespace sh
namespace
{
bool IsInterpolationIn(TQualifier qualifier)
{
switch (qualifier)
......@@ -42,6 +41,20 @@ bool IsInterpolationIn(TQualifier qualifier)
}
}
bool IsInterpolationOut(TQualifier qualifier)
{
switch (qualifier)
{
case EvqSmoothOut:
case EvqFlatOut:
case EvqNoPerspectiveOut:
case EvqCentroidOut:
case EvqSampleOut:
return true;
default:
return false;
}
}
} // anonymous namespace
float NumericLexFloat32OutOfRangeToInfinity(const std::string &str)
......@@ -554,6 +567,7 @@ bool IsVaryingOut(TQualifier qualifier)
case EvqTessControlOut:
case EvqTessEvaluationOut:
case EvqSampleOut:
case EvqPatchOut:
return true;
default:
......@@ -577,6 +591,7 @@ bool IsVaryingIn(TQualifier qualifier)
case EvqTessControlIn:
case EvqTessEvaluationIn:
case EvqSampleIn:
case EvqPatchIn:
return true;
default:
......@@ -597,12 +612,34 @@ bool IsGeometryShaderInput(GLenum shaderType, TQualifier qualifier)
((shaderType == GL_GEOMETRY_SHADER_EXT) && IsInterpolationIn(qualifier));
}
bool IsTessellationControlShaderInput(GLenum shaderType, TQualifier qualifier)
{
return qualifier == EvqTessControlIn ||
((shaderType == GL_TESS_CONTROL_SHADER) && IsInterpolationIn(qualifier));
}
bool IsTessellationControlShaderOutput(GLenum shaderType, TQualifier qualifier)
{
return qualifier == EvqTessControlOut ||
((shaderType == GL_TESS_CONTROL_SHADER) && IsInterpolationOut(qualifier));
}
bool IsTessellationEvaluationShaderInput(GLenum shaderType, TQualifier qualifier)
{
return qualifier == EvqTessEvaluationIn ||
((shaderType == GL_TESS_EVALUATION_SHADER) && IsInterpolationIn(qualifier));
}
InterpolationType GetInterpolationType(TQualifier qualifier)
{
switch (qualifier)
{
case EvqFlatIn:
case EvqFlatOut:
// The auxiliary storage qualifier patch is not used for interpolation
// it is a compile-time error to use interpolation qualifiers with patch
case EvqPatchIn:
case EvqPatchOut:
return INTERPOLATION_FLAT;
case EvqNoPerspectiveIn:
......@@ -617,6 +654,10 @@ InterpolationType GetInterpolationType(TQualifier qualifier)
case EvqVaryingOut:
case EvqGeometryIn:
case EvqGeometryOut:
case EvqTessControlIn:
case EvqTessControlOut:
case EvqTessEvaluationIn:
case EvqTessEvaluationOut:
return INTERPOLATION_SMOOTH;
case EvqCentroidIn:
......
......@@ -55,6 +55,9 @@ bool IsVaryingIn(TQualifier qualifier);
bool IsVaryingOut(TQualifier qualifier);
bool IsVarying(TQualifier qualifier);
bool IsGeometryShaderInput(GLenum shaderType, TQualifier qualifier);
bool IsTessellationControlShaderInput(GLenum shaderType, TQualifier qualifier);
bool IsTessellationControlShaderOutput(GLenum shaderType, TQualifier qualifier);
bool IsTessellationEvaluationShaderInput(GLenum shaderType, TQualifier qualifier);
InterpolationType GetInterpolationType(TQualifier qualifier);
InterpolationType GetFieldInterpolationType(TQualifier qualifier);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment