Commit 795a3559 by Shahbaz Youssefi Committed by Commit Bot

Vulkan: EXT_gpu_shader5 support: precise

The precise keyword is used in tessellation shaders but introduced in this extension. EXT_gpu_shader5 introduces a handful of features to shaders. This change only implements the `precise` keyword. Bug: angleproject:3569 Change-Id: I2252b79098eb8ba2d2faa040d7eaed7548b7051e Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1939851 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarCody Northrop <cnorthrop@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent e20560fa
...@@ -361,6 +361,7 @@ struct ShBuiltInResources ...@@ -361,6 +361,7 @@ struct ShBuiltInResources
int EXT_multisampled_render_to_texture; int EXT_multisampled_render_to_texture;
int EXT_YUV_target; int EXT_YUV_target;
int EXT_geometry_shader; int EXT_geometry_shader;
int EXT_gpu_shader5;
int OES_texture_storage_multisample_2d_array; int OES_texture_storage_multisample_2d_array;
int OES_texture_3D; int OES_texture_3D;
int ANGLE_texture_multisample; int ANGLE_texture_multisample;
......
...@@ -2,15 +2,15 @@ ...@@ -2,15 +2,15 @@
"src/compiler/translator/generate_parser.py": "src/compiler/translator/generate_parser.py":
"566178ecdfae3a29803b3687fc518ebb", "566178ecdfae3a29803b3687fc518ebb",
"src/compiler/translator/glslang.l": "src/compiler/translator/glslang.l":
"75adc098def35a464dfb5ca1a0e99799", "1aaddb610e7bde7f7cffc993ba762c93",
"src/compiler/translator/glslang.y": "src/compiler/translator/glslang.y":
"7b6b24685a467cbb7f50dc62176c2fef", "2570cc8e33a11cbff3fcbe278f96e5ba",
"src/compiler/translator/glslang_lex_autogen.cpp": "src/compiler/translator/glslang_lex_autogen.cpp":
"5f55ca207583009489d136e47c71beb5", "2958d0637093e53e1330c67cc323bbb9",
"src/compiler/translator/glslang_tab_autogen.cpp": "src/compiler/translator/glslang_tab_autogen.cpp":
"050bddb6103769b9e55f7fe62972ac86", "a1c116b14fc63d802487b5d404669d93",
"src/compiler/translator/glslang_tab_autogen.h": "src/compiler/translator/glslang_tab_autogen.h":
"4133ae84a4c17051cf114f404fea0046", "c33cc1947462ebb31778181a48538b6b",
"tools/flex-bison/linux/bison.sha1": "tools/flex-bison/linux/bison.sha1":
"efa86001f00e7bcfdbe899dd15fc88e0", "efa86001f00e7bcfdbe899dd15fc88e0",
"tools/flex-bison/linux/flex.sha1": "tools/flex-bison/linux/flex.sha1":
......
...@@ -162,6 +162,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) ...@@ -162,6 +162,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
resources.ARM_shader_framebuffer_fetch = 1; resources.ARM_shader_framebuffer_fetch = 1;
resources.EXT_YUV_target = 1; resources.EXT_YUV_target = 1;
resources.MaxDualSourceDrawBuffers = 1; resources.MaxDualSourceDrawBuffers = 1;
resources.EXT_gpu_shader5 = 1;
if (!translator->Init(resources)) if (!translator->Init(resources))
{ {
......
...@@ -999,6 +999,9 @@ enum TQualifier ...@@ -999,6 +999,9 @@ enum TQualifier
EvqPrimitiveID, // gl_PrimitiveID EvqPrimitiveID, // gl_PrimitiveID
EvqLayer, // gl_Layer EvqLayer, // gl_Layer
// GLSL ES 3.1 extension EXT_gpu_shader5 qualifiers
EvqPrecise,
// end of list // end of list
EvqLast EvqLast
}; };
...@@ -1269,6 +1272,7 @@ inline const char *getQualifierString(TQualifier q) ...@@ -1269,6 +1272,7 @@ inline const char *getQualifierString(TQualifier q)
case EvqGeometryIn: return "in"; case EvqGeometryIn: return "in";
case EvqGeometryOut: return "out"; case EvqGeometryOut: return "out";
case EvqPerVertexIn: return "gl_in"; case EvqPerVertexIn: return "gl_in";
case EvqPrecise: return "precise";
default: UNREACHABLE(); return "unknown qualifier"; default: UNREACHABLE(); return "unknown qualifier";
} }
// clang-format on // clang-format on
......
...@@ -361,8 +361,8 @@ bool CollectVariablesTraverser::visitGlobalQualifierDeclaration( ...@@ -361,8 +361,8 @@ bool CollectVariablesTraverser::visitGlobalQualifierDeclaration(
Visit visit, Visit visit,
TIntermGlobalQualifierDeclaration *node) TIntermGlobalQualifierDeclaration *node)
{ {
// We should not mark variables as active just based on an invariant declaration, so we don't // We should not mark variables as active just based on an invariant/precise declaration, so we
// traverse the symbols declared invariant. // don't traverse the symbols declared invariant.
return false; return false;
} }
......
...@@ -1047,6 +1047,7 @@ void TCompiler::setResourceString() ...@@ -1047,6 +1047,7 @@ void TCompiler::setResourceString()
<< ":OVR_multiview:" << mResources.OVR_multiview << ":OVR_multiview:" << mResources.OVR_multiview
<< ":EXT_YUV_target:" << mResources.EXT_YUV_target << ":EXT_YUV_target:" << mResources.EXT_YUV_target
<< ":EXT_geometry_shader:" << mResources.EXT_geometry_shader << ":EXT_geometry_shader:" << mResources.EXT_geometry_shader
<< ":EXT_gpu_shader5:" << mResources.EXT_gpu_shader5
<< ":OES_texture_3D:" << mResources.OES_texture_3D << ":OES_texture_3D:" << mResources.OES_texture_3D
<< ":MaxVertexOutputVectors:" << mResources.MaxVertexOutputVectors << ":MaxVertexOutputVectors:" << mResources.MaxVertexOutputVectors
<< ":MaxFragmentInputVectors:" << mResources.MaxFragmentInputVectors << ":MaxFragmentInputVectors:" << mResources.MaxFragmentInputVectors
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
OP(EXT_draw_buffers) \ OP(EXT_draw_buffers) \
OP(EXT_frag_depth) \ OP(EXT_frag_depth) \
OP(EXT_geometry_shader) \ OP(EXT_geometry_shader) \
OP(EXT_gpu_shader5) \
OP(EXT_shader_framebuffer_fetch) \ OP(EXT_shader_framebuffer_fetch) \
OP(EXT_shader_texture_lod) \ OP(EXT_shader_texture_lod) \
OP(EXT_YUV_target) \ OP(EXT_YUV_target) \
......
...@@ -25,6 +25,7 @@ enum class TExtension ...@@ -25,6 +25,7 @@ enum class TExtension
EXT_draw_buffers, EXT_draw_buffers,
EXT_frag_depth, EXT_frag_depth,
EXT_geometry_shader, EXT_geometry_shader,
EXT_gpu_shader5,
EXT_shader_framebuffer_fetch, EXT_shader_framebuffer_fetch,
EXT_shader_texture_lod, EXT_shader_texture_lod,
EXT_YUV_target, EXT_YUV_target,
......
...@@ -77,6 +77,10 @@ void InitExtensionBehavior(const ShBuiltInResources &resources, TExtensionBehavi ...@@ -77,6 +77,10 @@ void InitExtensionBehavior(const ShBuiltInResources &resources, TExtensionBehavi
{ {
extBehavior[TExtension::EXT_geometry_shader] = EBhUndefined; extBehavior[TExtension::EXT_geometry_shader] = EBhUndefined;
} }
if (resources.EXT_gpu_shader5)
{
extBehavior[TExtension::EXT_gpu_shader5] = EBhUndefined;
}
if (resources.OES_texture_storage_multisample_2d_array) if (resources.OES_texture_storage_multisample_2d_array)
{ {
extBehavior[TExtension::OES_texture_storage_multisample_2d_array] = EBhUndefined; extBehavior[TExtension::OES_texture_storage_multisample_2d_array] = EBhUndefined;
......
...@@ -1334,8 +1334,9 @@ TIntermBinary *TIntermBinary::CreateComma(TIntermTyped *left, ...@@ -1334,8 +1334,9 @@ TIntermBinary *TIntermBinary::CreateComma(TIntermTyped *left,
} }
TIntermGlobalQualifierDeclaration::TIntermGlobalQualifierDeclaration(TIntermSymbol *symbol, TIntermGlobalQualifierDeclaration::TIntermGlobalQualifierDeclaration(TIntermSymbol *symbol,
bool isPrecise,
const TSourceLoc &line) const TSourceLoc &line)
: TIntermNode(), mSymbol(symbol) : TIntermNode(), mSymbol(symbol), mIsPrecise(isPrecise)
{ {
ASSERT(symbol); ASSERT(symbol);
setLine(line); setLine(line);
...@@ -1344,6 +1345,7 @@ TIntermGlobalQualifierDeclaration::TIntermGlobalQualifierDeclaration(TIntermSymb ...@@ -1344,6 +1345,7 @@ TIntermGlobalQualifierDeclaration::TIntermGlobalQualifierDeclaration(TIntermSymb
TIntermGlobalQualifierDeclaration::TIntermGlobalQualifierDeclaration( TIntermGlobalQualifierDeclaration::TIntermGlobalQualifierDeclaration(
const TIntermGlobalQualifierDeclaration &node) const TIntermGlobalQualifierDeclaration &node)
: TIntermGlobalQualifierDeclaration(static_cast<TIntermSymbol *>(node.mSymbol->deepCopy()), : TIntermGlobalQualifierDeclaration(static_cast<TIntermSymbol *>(node.mSymbol->deepCopy()),
node.mIsPrecise,
node.mLine) node.mLine)
{} {}
......
...@@ -807,7 +807,9 @@ class TIntermDeclaration : public TIntermNode, public TIntermAggregateBase ...@@ -807,7 +807,9 @@ class TIntermDeclaration : public TIntermNode, public TIntermAggregateBase
class TIntermGlobalQualifierDeclaration : public TIntermNode class TIntermGlobalQualifierDeclaration : public TIntermNode
{ {
public: public:
TIntermGlobalQualifierDeclaration(TIntermSymbol *symbol, const TSourceLoc &line); TIntermGlobalQualifierDeclaration(TIntermSymbol *symbol,
bool isPrecise,
const TSourceLoc &line);
virtual TIntermGlobalQualifierDeclaration *getAsGlobalQualifierDeclarationNode() override virtual TIntermGlobalQualifierDeclaration *getAsGlobalQualifierDeclarationNode() override
{ {
...@@ -816,6 +818,8 @@ class TIntermGlobalQualifierDeclaration : public TIntermNode ...@@ -816,6 +818,8 @@ class TIntermGlobalQualifierDeclaration : public TIntermNode
bool visit(Visit visit, TIntermTraverser *it) final; bool visit(Visit visit, TIntermTraverser *it) final;
TIntermSymbol *getSymbol() { return mSymbol; } TIntermSymbol *getSymbol() { return mSymbol; }
bool isInvariant() const { return !mIsPrecise; }
bool isPrecise() const { return mIsPrecise; }
size_t getChildCount() const final; size_t getChildCount() const final;
TIntermNode *getChildNode(size_t index) const final; TIntermNode *getChildNode(size_t index) const final;
...@@ -828,6 +832,8 @@ class TIntermGlobalQualifierDeclaration : public TIntermNode ...@@ -828,6 +832,8 @@ class TIntermGlobalQualifierDeclaration : public TIntermNode
private: private:
TIntermSymbol *mSymbol; TIntermSymbol *mSymbol;
// Either |precise| or |invariant|, determined based on this flag.
bool mIsPrecise;
TIntermGlobalQualifierDeclaration(const TIntermGlobalQualifierDeclaration &); TIntermGlobalQualifierDeclaration(const TIntermGlobalQualifierDeclaration &);
}; };
......
...@@ -111,6 +111,12 @@ void TOutputGLSLBase::writeInvariantQualifier(const TType &type) ...@@ -111,6 +111,12 @@ void TOutputGLSLBase::writeInvariantQualifier(const TType &type)
} }
} }
void TOutputGLSLBase::writePreciseQualifier(const TType &type)
{
TInfoSinkBase &out = objSink();
out << "precise ";
}
void TOutputGLSLBase::writeFloat(TInfoSinkBase &out, float f) void TOutputGLSLBase::writeFloat(TInfoSinkBase &out, float f)
{ {
if ((gl::isInf(f) || gl::isNaN(f)) && mShaderVersion >= 300) if ((gl::isInf(f) || gl::isNaN(f)) && mShaderVersion >= 300)
...@@ -377,6 +383,10 @@ void TOutputGLSLBase::writeVariableType(const TType &type, const TSymbol *symbol ...@@ -377,6 +383,10 @@ void TOutputGLSLBase::writeVariableType(const TType &type, const TSymbol *symbol
{ {
writeInvariantQualifier(type); writeInvariantQualifier(type);
} }
if (type.isPrecise())
{
writePreciseQualifier(type);
}
if (qualifier != EvqTemporary && qualifier != EvqGlobal) if (qualifier != EvqTemporary && qualifier != EvqGlobal)
{ {
writeQualifier(qualifier, type, symbol); writeQualifier(qualifier, type, symbol);
...@@ -958,7 +968,7 @@ bool TOutputGLSLBase::visitGlobalQualifierDeclaration(Visit visit, ...@@ -958,7 +968,7 @@ bool TOutputGLSLBase::visitGlobalQualifierDeclaration(Visit visit,
TInfoSinkBase &out = objSink(); TInfoSinkBase &out = objSink();
ASSERT(visit == PreVisit); ASSERT(visit == PreVisit);
const TIntermSymbol *symbol = node->getSymbol(); const TIntermSymbol *symbol = node->getSymbol();
out << "invariant " << hashName(&symbol->variable()); out << (node->isPrecise() ? "precise " : "invariant ") << hashName(&symbol->variable());
return false; return false;
} }
......
...@@ -45,6 +45,7 @@ class TOutputGLSLBase : public TIntermTraverser ...@@ -45,6 +45,7 @@ class TOutputGLSLBase : public TIntermTraverser
virtual void writeLayoutQualifier(TIntermTyped *variable); virtual void writeLayoutQualifier(TIntermTyped *variable);
virtual void writeFieldLayoutQualifier(const TField *field); virtual void writeFieldLayoutQualifier(const TField *field);
void writeInvariantQualifier(const TType &type); void writeInvariantQualifier(const TType &type);
void writePreciseQualifier(const TType &type);
virtual void writeVariableType(const TType &type, const TSymbol *symbol); virtual void writeVariableType(const TType &type, const TSymbol *symbol);
virtual bool writeVariablePrecision(TPrecision precision) = 0; virtual bool writeVariablePrecision(TPrecision precision) = 0;
void writeFunctionParameters(const TFunction *func); void writeFunctionParameters(const TFunction *func);
......
...@@ -363,7 +363,14 @@ bool TOutputTraverser::visitGlobalQualifierDeclaration(Visit visit, ...@@ -363,7 +363,14 @@ bool TOutputTraverser::visitGlobalQualifierDeclaration(Visit visit,
TIntermGlobalQualifierDeclaration *node) TIntermGlobalQualifierDeclaration *node)
{ {
OutputTreeText(mOut, node, getCurrentIndentDepth()); OutputTreeText(mOut, node, getCurrentIndentDepth());
mOut << "Invariant Declaration:\n"; if (node->isPrecise())
{
mOut << "Precise Declaration:\n";
}
else
{
mOut << "Invariant Declaration:\n";
}
return true; return true;
} }
......
...@@ -34,4 +34,4 @@ class TOutputVulkanGLSLForMetal : public TOutputVulkanGLSL ...@@ -34,4 +34,4 @@ class TOutputVulkanGLSLForMetal : public TOutputVulkanGLSL
void writeVariableType(const TType &type, const TSymbol *symbol) override; void writeVariableType(const TType &type, const TSymbol *symbol) override;
}; };
} // namespace sh } // namespace sh
\ No newline at end of file
...@@ -94,6 +94,10 @@ bool TOutputVulkanGLSLForMetal::visitGlobalQualifierDeclaration( ...@@ -94,6 +94,10 @@ bool TOutputVulkanGLSLForMetal::visitGlobalQualifierDeclaration(
TInfoSinkBase &out = objSink(); TInfoSinkBase &out = objSink();
ASSERT(visit == PreVisit); ASSERT(visit == PreVisit);
const TIntermSymbol *symbol = node->getSymbol(); const TIntermSymbol *symbol = node->getSymbol();
// No support for the |precise| keyword from EXT_gpu_shader5 (or ES3.2).
ASSERT(node->isInvariant());
if (!ShoudRemoveInvariant(symbol->getType())) if (!ShoudRemoveInvariant(symbol->getType()))
{ {
out << "invariant "; out << "invariant ";
......
...@@ -2198,6 +2198,7 @@ TPublicType TParseContext::addFullySpecifiedType(const TTypeQualifierBuilder &ty ...@@ -2198,6 +2198,7 @@ TPublicType TParseContext::addFullySpecifiedType(const TTypeQualifierBuilder &ty
TPublicType returnType = typeSpecifier; TPublicType returnType = typeSpecifier;
returnType.qualifier = typeQualifier.qualifier; returnType.qualifier = typeQualifier.qualifier;
returnType.invariant = typeQualifier.invariant; returnType.invariant = typeQualifier.invariant;
returnType.precise = typeQualifier.precise;
returnType.layoutQualifier = typeQualifier.layoutQualifier; returnType.layoutQualifier = typeQualifier.layoutQualifier;
returnType.memoryQualifier = typeQualifier.memoryQualifier; returnType.memoryQualifier = typeQualifier.memoryQualifier;
returnType.precision = typeSpecifier.precision; returnType.precision = typeSpecifier.precision;
...@@ -2653,33 +2654,33 @@ TIntermGlobalQualifierDeclaration *TParseContext::parseGlobalQualifierDeclaratio ...@@ -2653,33 +2654,33 @@ TIntermGlobalQualifierDeclaration *TParseContext::parseGlobalQualifierDeclaratio
{ {
TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics); TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
if (!typeQualifier.invariant) if (!typeQualifier.invariant && !typeQualifier.precise)
{ {
error(identifierLoc, "Expected invariant", identifier); error(identifierLoc, "Expected invariant or precise", identifier);
return nullptr; return nullptr;
} }
if (!checkIsAtGlobalLevel(identifierLoc, "invariant varying")) if (typeQualifier.invariant && !checkIsAtGlobalLevel(identifierLoc, "invariant varying"))
{ {
return nullptr; return nullptr;
} }
if (!symbol) if (!symbol)
{ {
error(identifierLoc, "undeclared identifier declared as invariant", identifier); error(identifierLoc, "undeclared identifier declared as invariant or precise", identifier);
return nullptr; return nullptr;
} }
if (!IsQualifierUnspecified(typeQualifier.qualifier)) if (!IsQualifierUnspecified(typeQualifier.qualifier))
{ {
error(identifierLoc, "invariant declaration specifies qualifier", error(identifierLoc, "invariant or precise declaration specifies qualifier",
getQualifierString(typeQualifier.qualifier)); getQualifierString(typeQualifier.qualifier));
} }
if (typeQualifier.precision != EbpUndefined) if (typeQualifier.precision != EbpUndefined)
{ {
error(identifierLoc, "invariant declaration specifies precision", error(identifierLoc, "invariant or precise declaration specifies precision",
getPrecisionString(typeQualifier.precision)); getPrecisionString(typeQualifier.precision));
} }
if (!typeQualifier.layoutQualifier.isEmpty()) if (!typeQualifier.layoutQualifier.isEmpty())
{ {
error(identifierLoc, "invariant declaration specifies layout", "'layout'"); error(identifierLoc, "invariant or precise declaration specifies layout", "'layout'");
} }
const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol); const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol);
...@@ -2698,7 +2699,8 @@ TIntermGlobalQualifierDeclaration *TParseContext::parseGlobalQualifierDeclaratio ...@@ -2698,7 +2699,8 @@ TIntermGlobalQualifierDeclaration *TParseContext::parseGlobalQualifierDeclaratio
TIntermSymbol *intermSymbol = new TIntermSymbol(variable); TIntermSymbol *intermSymbol = new TIntermSymbol(variable);
intermSymbol->setLine(identifierLoc); intermSymbol->setLine(identifierLoc);
return new TIntermGlobalQualifierDeclaration(intermSymbol, identifierLoc); return new TIntermGlobalQualifierDeclaration(intermSymbol, typeQualifier.precise,
identifierLoc);
} }
void TParseContext::parseDeclarator(TPublicType &publicType, void TParseContext::parseDeclarator(TPublicType &publicType,
...@@ -4824,6 +4826,7 @@ TFieldList *TParseContext::addStructDeclaratorListWithQualifiers( ...@@ -4824,6 +4826,7 @@ TFieldList *TParseContext::addStructDeclaratorListWithQualifiers(
typeSpecifier->layoutQualifier = typeQualifier.layoutQualifier; typeSpecifier->layoutQualifier = typeQualifier.layoutQualifier;
typeSpecifier->memoryQualifier = typeQualifier.memoryQualifier; typeSpecifier->memoryQualifier = typeQualifier.memoryQualifier;
typeSpecifier->invariant = typeQualifier.invariant; typeSpecifier->invariant = typeQualifier.invariant;
typeSpecifier->precise = typeQualifier.precise;
if (typeQualifier.precision != EbpUndefined) if (typeQualifier.precision != EbpUndefined)
{ {
typeSpecifier->precision = typeQualifier.precision; typeSpecifier->precision = typeQualifier.precision;
......
...@@ -20,6 +20,8 @@ namespace ...@@ -20,6 +20,8 @@ namespace
constexpr const ImmutableString kSpecifiedMultipleTimes(" specified multiple times"); constexpr const ImmutableString kSpecifiedMultipleTimes(" specified multiple times");
constexpr const ImmutableString kInvariantMultipleTimes( constexpr const ImmutableString kInvariantMultipleTimes(
"The invariant qualifier specified multiple times."); "The invariant qualifier specified multiple times.");
constexpr const ImmutableString kPreciseMultipleTimes(
"The precise qualifier specified multiple times.");
constexpr const ImmutableString kPrecisionMultipleTimes( constexpr const ImmutableString kPrecisionMultipleTimes(
"The precision qualifier specified multiple times."); "The precision qualifier specified multiple times.");
constexpr const ImmutableString kLayoutMultipleTimes( constexpr const ImmutableString kLayoutMultipleTimes(
...@@ -69,7 +71,7 @@ bool IsScopeQualifierWrapper(const TQualifierWrapperBase *qualifier) ...@@ -69,7 +71,7 @@ bool IsScopeQualifierWrapper(const TQualifierWrapperBase *qualifier)
return IsScopeQualifier(q); return IsScopeQualifier(q);
} }
// Returns true if the invariant for the qualifier sequence holds // Returns true if the invariant/precise for the qualifier sequence holds
bool IsInvariantCorrect(const TTypeQualifierBuilder::QualifierSequence &qualifiers) bool IsInvariantCorrect(const TTypeQualifierBuilder::QualifierSequence &qualifiers)
{ {
// We should have at least one qualifier. // We should have at least one qualifier.
...@@ -91,6 +93,7 @@ bool HasRepeatingQualifiers(const TTypeQualifierBuilder::QualifierSequence &qual ...@@ -91,6 +93,7 @@ bool HasRepeatingQualifiers(const TTypeQualifierBuilder::QualifierSequence &qual
ImmutableString *errorMessage) ImmutableString *errorMessage)
{ {
bool invariantFound = false; bool invariantFound = false;
bool preciseFound = false;
bool precisionFound = false; bool precisionFound = false;
bool layoutFound = false; bool layoutFound = false;
bool interpolationFound = false; bool interpolationFound = false;
...@@ -114,6 +117,16 @@ bool HasRepeatingQualifiers(const TTypeQualifierBuilder::QualifierSequence &qual ...@@ -114,6 +117,16 @@ bool HasRepeatingQualifiers(const TTypeQualifierBuilder::QualifierSequence &qual
invariantFound = true; invariantFound = true;
break; break;
} }
case QtPrecise:
{
if (preciseFound)
{
*errorMessage = kPreciseMultipleTimes;
return true;
}
preciseFound = true;
break;
}
case QtPrecision: case QtPrecision:
{ {
if (precisionFound) if (precisionFound)
...@@ -231,9 +244,19 @@ bool HasRepeatingQualifiers(const TTypeQualifierBuilder::QualifierSequence &qual ...@@ -231,9 +244,19 @@ bool HasRepeatingQualifiers(const TTypeQualifierBuilder::QualifierSequence &qual
// The correct order of qualifiers is: // The correct order of qualifiers is:
// invariant-qualifier interpolation-qualifier storage-qualifier precision-qualifier // invariant-qualifier interpolation-qualifier storage-qualifier precision-qualifier
// layout-qualifier has to be before storage-qualifier. // layout-qualifier has to be before storage-qualifier.
//
// GLSL ES 3.1 relaxes the order of qualification:
// When multiple qualifiers are present in a declaration, they may appear in any order, but they
// must all appear before the type.
bool AreQualifiersInOrder(const TTypeQualifierBuilder::QualifierSequence &qualifiers, bool AreQualifiersInOrder(const TTypeQualifierBuilder::QualifierSequence &qualifiers,
int shaderVersion,
ImmutableString *errorMessage) ImmutableString *errorMessage)
{ {
if (shaderVersion >= 310)
{
return true;
}
bool foundInterpolation = false; bool foundInterpolation = false;
bool foundStorage = false; bool foundStorage = false;
bool foundPrecision = false; bool foundPrecision = false;
...@@ -291,6 +314,12 @@ bool AreQualifiersInOrder(const TTypeQualifierBuilder::QualifierSequence &qualif ...@@ -291,6 +314,12 @@ bool AreQualifiersInOrder(const TTypeQualifierBuilder::QualifierSequence &qualif
case QtPrecision: case QtPrecision:
foundPrecision = true; foundPrecision = true;
break; break;
case QtPrecise:
// This keyword is available in ES3.1 (with extension) or in ES3.2, but the function
// should early-out in such a case as the spec doesn't require a particular order to
// the qualifiers.
UNREACHABLE();
break;
default: default:
UNREACHABLE(); UNREACHABLE();
} }
...@@ -468,6 +497,10 @@ TTypeQualifier GetVariableTypeQualifierFromSortedSequence( ...@@ -468,6 +497,10 @@ TTypeQualifier GetVariableTypeQualifierFromSortedSequence(
isQualifierValid = true; isQualifierValid = true;
typeQualifier.invariant = true; typeQualifier.invariant = true;
break; break;
case QtPrecise:
isQualifierValid = true;
typeQualifier.precise = true;
break;
case QtInterpolation: case QtInterpolation:
{ {
switch (typeQualifier.qualifier) switch (typeQualifier.qualifier)
...@@ -535,6 +568,7 @@ TTypeQualifier GetParameterTypeQualifierFromSortedSequence( ...@@ -535,6 +568,7 @@ TTypeQualifier GetParameterTypeQualifierFromSortedSequence(
switch (qualifier->getType()) switch (qualifier->getType())
{ {
case QtInvariant: case QtInvariant:
case QtPrecise:
case QtInterpolation: case QtInterpolation:
case QtLayout: case QtLayout:
break; break;
...@@ -701,38 +735,43 @@ unsigned int TInvariantQualifierWrapper::getRank() const ...@@ -701,38 +735,43 @@ unsigned int TInvariantQualifierWrapper::getRank() const
return 0u; return 0u;
} }
unsigned int TInterpolationQualifierWrapper::getRank() const unsigned int TPreciseQualifierWrapper::getRank() const
{ {
return 1u; return 1u;
} }
unsigned int TLayoutQualifierWrapper::getRank() const unsigned int TInterpolationQualifierWrapper::getRank() const
{ {
return 2u; return 2u;
} }
unsigned int TLayoutQualifierWrapper::getRank() const
{
return 3u;
}
unsigned int TStorageQualifierWrapper::getRank() const unsigned int TStorageQualifierWrapper::getRank() const
{ {
// Force the 'centroid' auxilary storage qualifier to be always first among all storage // Force the 'centroid' auxilary storage qualifier to be always first among all storage
// qualifiers. // qualifiers.
if (mStorageQualifier == EvqCentroid) if (mStorageQualifier == EvqCentroid)
{ {
return 3u; return 4u;
} }
else else
{ {
return 4u; return 5u;
} }
} }
unsigned int TMemoryQualifierWrapper::getRank() const unsigned int TMemoryQualifierWrapper::getRank() const
{ {
return 4u; return 5u;
} }
unsigned int TPrecisionQualifierWrapper::getRank() const unsigned int TPrecisionQualifierWrapper::getRank() const
{ {
return 5u; return 6u;
} }
TTypeQualifier::TTypeQualifier(TQualifier scope, const TSourceLoc &loc) TTypeQualifier::TTypeQualifier(TQualifier scope, const TSourceLoc &loc)
...@@ -741,6 +780,7 @@ TTypeQualifier::TTypeQualifier(TQualifier scope, const TSourceLoc &loc) ...@@ -741,6 +780,7 @@ TTypeQualifier::TTypeQualifier(TQualifier scope, const TSourceLoc &loc)
precision(EbpUndefined), precision(EbpUndefined),
qualifier(scope), qualifier(scope),
invariant(false), invariant(false),
precise(false),
line(loc) line(loc)
{ {
ASSERT(IsScopeQualifier(qualifier)); ASSERT(IsScopeQualifier(qualifier));
...@@ -769,7 +809,8 @@ bool TTypeQualifierBuilder::checkSequenceIsValid(TDiagnostics *diagnostics) cons ...@@ -769,7 +809,8 @@ bool TTypeQualifierBuilder::checkSequenceIsValid(TDiagnostics *diagnostics) cons
return false; return false;
} }
if (!areQualifierChecksRelaxed && !AreQualifiersInOrder(mQualifiers, &errorMessage)) if (!areQualifierChecksRelaxed &&
!AreQualifiersInOrder(mQualifiers, mShaderVersion, &errorMessage))
{ {
diagnostics->error(mQualifiers[0]->getLine(), errorMessage.data(), "qualifier sequence"); diagnostics->error(mQualifiers[0]->getLine(), errorMessage.data(), "qualifier sequence");
return false; return false;
......
...@@ -24,6 +24,7 @@ TLayoutQualifier JoinLayoutQualifiers(TLayoutQualifier leftQualifier, ...@@ -24,6 +24,7 @@ TLayoutQualifier JoinLayoutQualifiers(TLayoutQualifier leftQualifier,
enum TQualifierType enum TQualifierType
{ {
QtInvariant, QtInvariant,
QtPrecise,
QtInterpolation, QtInterpolation,
QtLayout, QtLayout,
QtStorage, QtStorage,
...@@ -57,6 +58,17 @@ class TInvariantQualifierWrapper final : public TQualifierWrapperBase ...@@ -57,6 +58,17 @@ class TInvariantQualifierWrapper final : public TQualifierWrapperBase
unsigned int getRank() const override; unsigned int getRank() const override;
}; };
class TPreciseQualifierWrapper final : public TQualifierWrapperBase
{
public:
TPreciseQualifierWrapper(const TSourceLoc &line) : TQualifierWrapperBase(line) {}
~TPreciseQualifierWrapper() override {}
TQualifierType getType() const override { return QtPrecise; }
ImmutableString getQualifierString() const override { return ImmutableString("precise"); }
unsigned int getRank() const override;
};
class TInterpolationQualifierWrapper final : public TQualifierWrapperBase class TInterpolationQualifierWrapper final : public TQualifierWrapperBase
{ {
public: public:
...@@ -165,6 +177,7 @@ struct TTypeQualifier ...@@ -165,6 +177,7 @@ struct TTypeQualifier
TPrecision precision; TPrecision precision;
TQualifier qualifier; TQualifier qualifier;
bool invariant; bool invariant;
bool precise;
TSourceLoc line; TSourceLoc line;
}; };
......
...@@ -166,6 +166,7 @@ void InitBuiltInResources(ShBuiltInResources *resources) ...@@ -166,6 +166,7 @@ void InitBuiltInResources(ShBuiltInResources *resources)
resources->OVR_multiview2 = 0; resources->OVR_multiview2 = 0;
resources->EXT_YUV_target = 0; resources->EXT_YUV_target = 0;
resources->EXT_geometry_shader = 0; resources->EXT_geometry_shader = 0;
resources->EXT_gpu_shader5 = 0;
resources->OES_texture_storage_multisample_2d_array = 0; resources->OES_texture_storage_multisample_2d_array = 0;
resources->OES_texture_3D = 0; resources->OES_texture_3D = 0;
resources->ANGLE_texture_multisample = 0; resources->ANGLE_texture_multisample = 0;
......
...@@ -126,6 +126,7 @@ TType::TType() ...@@ -126,6 +126,7 @@ TType::TType()
precision(EbpUndefined), precision(EbpUndefined),
qualifier(EvqGlobal), qualifier(EvqGlobal),
invariant(false), invariant(false),
precise(false),
memoryQualifier(TMemoryQualifier::Create()), memoryQualifier(TMemoryQualifier::Create()),
layoutQualifier(TLayoutQualifier::Create()), layoutQualifier(TLayoutQualifier::Create()),
primarySize(0), primarySize(0),
...@@ -142,6 +143,7 @@ TType::TType(TBasicType t, unsigned char ps, unsigned char ss) ...@@ -142,6 +143,7 @@ TType::TType(TBasicType t, unsigned char ps, unsigned char ss)
precision(EbpUndefined), precision(EbpUndefined),
qualifier(EvqGlobal), qualifier(EvqGlobal),
invariant(false), invariant(false),
precise(false),
memoryQualifier(TMemoryQualifier::Create()), memoryQualifier(TMemoryQualifier::Create()),
layoutQualifier(TLayoutQualifier::Create()), layoutQualifier(TLayoutQualifier::Create()),
primarySize(ps), primarySize(ps),
...@@ -158,6 +160,7 @@ TType::TType(TBasicType t, TPrecision p, TQualifier q, unsigned char ps, unsigne ...@@ -158,6 +160,7 @@ TType::TType(TBasicType t, TPrecision p, TQualifier q, unsigned char ps, unsigne
precision(p), precision(p),
qualifier(q), qualifier(q),
invariant(false), invariant(false),
precise(false),
memoryQualifier(TMemoryQualifier::Create()), memoryQualifier(TMemoryQualifier::Create()),
layoutQualifier(TLayoutQualifier::Create()), layoutQualifier(TLayoutQualifier::Create()),
primarySize(ps), primarySize(ps),
...@@ -174,6 +177,7 @@ TType::TType(const TPublicType &p) ...@@ -174,6 +177,7 @@ TType::TType(const TPublicType &p)
precision(p.precision), precision(p.precision),
qualifier(p.qualifier), qualifier(p.qualifier),
invariant(p.invariant), invariant(p.invariant),
precise(p.precise),
memoryQualifier(p.memoryQualifier), memoryQualifier(p.memoryQualifier),
layoutQualifier(p.layoutQualifier), layoutQualifier(p.layoutQualifier),
primarySize(p.getPrimarySize()), primarySize(p.getPrimarySize()),
...@@ -202,6 +206,7 @@ TType::TType(const TStructure *userDef, bool isStructSpecifier) ...@@ -202,6 +206,7 @@ TType::TType(const TStructure *userDef, bool isStructSpecifier)
precision(EbpUndefined), precision(EbpUndefined),
qualifier(EvqTemporary), qualifier(EvqTemporary),
invariant(false), invariant(false),
precise(false),
memoryQualifier(TMemoryQualifier::Create()), memoryQualifier(TMemoryQualifier::Create()),
layoutQualifier(TLayoutQualifier::Create()), layoutQualifier(TLayoutQualifier::Create()),
primarySize(1), primarySize(1),
...@@ -220,6 +225,7 @@ TType::TType(const TInterfaceBlock *interfaceBlockIn, ...@@ -220,6 +225,7 @@ TType::TType(const TInterfaceBlock *interfaceBlockIn,
precision(EbpUndefined), precision(EbpUndefined),
qualifier(qualifierIn), qualifier(qualifierIn),
invariant(false), invariant(false),
precise(false),
memoryQualifier(TMemoryQualifier::Create()), memoryQualifier(TMemoryQualifier::Create()),
layoutQualifier(layoutQualifierIn), layoutQualifier(layoutQualifierIn),
primarySize(1), primarySize(1),
...@@ -236,6 +242,7 @@ TType::TType(const TType &t) ...@@ -236,6 +242,7 @@ TType::TType(const TType &t)
precision(t.precision), precision(t.precision),
qualifier(t.qualifier), qualifier(t.qualifier),
invariant(t.invariant), invariant(t.invariant),
precise(t.precise),
memoryQualifier(t.memoryQualifier), memoryQualifier(t.memoryQualifier),
layoutQualifier(t.layoutQualifier), layoutQualifier(t.layoutQualifier),
primarySize(t.primarySize), primarySize(t.primarySize),
...@@ -253,6 +260,7 @@ TType &TType::operator=(const TType &t) ...@@ -253,6 +260,7 @@ TType &TType::operator=(const TType &t)
precision = t.precision; precision = t.precision;
qualifier = t.qualifier; qualifier = t.qualifier;
invariant = t.invariant; invariant = t.invariant;
precise = t.precise;
memoryQualifier = t.memoryQualifier; memoryQualifier = t.memoryQualifier;
layoutQualifier = t.layoutQualifier; layoutQualifier = t.layoutQualifier;
primarySize = t.primarySize; primarySize = t.primarySize;
...@@ -926,6 +934,7 @@ void TPublicType::initialize(const TTypeSpecifierNonArray &typeSpecifier, TQuali ...@@ -926,6 +934,7 @@ void TPublicType::initialize(const TTypeSpecifierNonArray &typeSpecifier, TQuali
memoryQualifier = TMemoryQualifier::Create(); memoryQualifier = TMemoryQualifier::Create();
qualifier = q; qualifier = q;
invariant = false; invariant = false;
precise = false;
precision = EbpUndefined; precision = EbpUndefined;
arraySizes = nullptr; arraySizes = nullptr;
} }
...@@ -939,6 +948,7 @@ void TPublicType::initializeBasicType(TBasicType basicType) ...@@ -939,6 +948,7 @@ void TPublicType::initializeBasicType(TBasicType basicType)
memoryQualifier = TMemoryQualifier::Create(); memoryQualifier = TMemoryQualifier::Create();
qualifier = EvqTemporary; qualifier = EvqTemporary;
invariant = false; invariant = false;
precise = false;
precision = EbpUndefined; precision = EbpUndefined;
arraySizes = nullptr; arraySizes = nullptr;
} }
......
...@@ -117,6 +117,7 @@ class TType ...@@ -117,6 +117,7 @@ class TType
precision(p), precision(p),
qualifier(q), qualifier(q),
invariant(false), invariant(false),
precise(false),
memoryQualifier(TMemoryQualifier::Create()), memoryQualifier(TMemoryQualifier::Create()),
layoutQualifier(TLayoutQualifier::Create()), layoutQualifier(TLayoutQualifier::Create()),
primarySize(ps), primarySize(ps),
...@@ -133,6 +134,7 @@ class TType ...@@ -133,6 +134,7 @@ class TType
precision(t.precision), precision(t.precision),
qualifier(t.qualifier), qualifier(t.qualifier),
invariant(t.invariant), invariant(t.invariant),
precise(t.precise),
memoryQualifier(t.memoryQualifier), memoryQualifier(t.memoryQualifier),
layoutQualifier(t.layoutQualifier), layoutQualifier(t.layoutQualifier),
primarySize(t.primarySize), primarySize(t.primarySize),
...@@ -154,9 +156,11 @@ class TType ...@@ -154,9 +156,11 @@ class TType
void setQualifier(TQualifier q) { qualifier = q; } void setQualifier(TQualifier q) { qualifier = q; }
bool isInvariant() const { return invariant; } bool isInvariant() const { return invariant; }
void setInvariant(bool i) { invariant = i; } void setInvariant(bool i) { invariant = i; }
bool isPrecise() const { return precise; }
void setPrecise(bool i) { precise = i; }
TMemoryQualifier getMemoryQualifier() const { return memoryQualifier; } TMemoryQualifier getMemoryQualifier() const { return memoryQualifier; }
void setMemoryQualifier(const TMemoryQualifier &mq) { memoryQualifier = mq; } void setMemoryQualifier(const TMemoryQualifier &mq) { memoryQualifier = mq; }
...@@ -342,6 +346,7 @@ class TType ...@@ -342,6 +346,7 @@ class TType
TPrecision precision; TPrecision precision;
TQualifier qualifier; TQualifier qualifier;
bool invariant; bool invariant;
bool precise;
TMemoryQualifier memoryQualifier; TMemoryQualifier memoryQualifier;
TLayoutQualifier layoutQualifier; TLayoutQualifier layoutQualifier;
unsigned char primarySize; // size of vector or cols matrix unsigned char primarySize; // size of vector or cols matrix
...@@ -454,6 +459,7 @@ struct TPublicType ...@@ -454,6 +459,7 @@ struct TPublicType
TMemoryQualifier memoryQualifier; TMemoryQualifier memoryQualifier;
TQualifier qualifier; TQualifier qualifier;
bool invariant; bool invariant;
bool precise;
TPrecision precision; TPrecision precision;
// Either nullptr or empty in case the type is not an array. The last element is the outermost // Either nullptr or empty in case the type is not an array. The last element is the outermost
......
...@@ -101,7 +101,14 @@ bool TVersionGLSL::visitDeclaration(Visit, TIntermDeclaration *node) ...@@ -101,7 +101,14 @@ bool TVersionGLSL::visitDeclaration(Visit, TIntermDeclaration *node)
bool TVersionGLSL::visitGlobalQualifierDeclaration(Visit, TIntermGlobalQualifierDeclaration *node) bool TVersionGLSL::visitGlobalQualifierDeclaration(Visit, TIntermGlobalQualifierDeclaration *node)
{ {
ensureVersionIsAtLeast(GLSL_VERSION_120); if (node->isPrecise())
{
ensureVersionIsAtLeast(GLSL_VERSION_420);
}
else
{
ensureVersionIsAtLeast(GLSL_VERSION_120);
}
return true; return true;
} }
......
...@@ -108,6 +108,7 @@ static int ES2_reserved_ES2_extension_ES3_keyword(TParseContext *context, TExten ...@@ -108,6 +108,7 @@ static int ES2_reserved_ES2_extension_ES3_keyword(TParseContext *context, TExten
static int ES3_extension(TParseContext *context, TExtension extension, int token); static int ES3_extension(TParseContext *context, TExtension extension, int token);
static int ES3_reserved_ES3_1_extension_ES3_2_keyword(TParseContext *context, TExtension extension, int token); static int ES3_reserved_ES3_1_extension_ES3_2_keyword(TParseContext *context, TExtension extension, int token);
static int ES3_reserved_ES3_extension_ES3_1_keyword(TParseContext *context, TExtension extension, int token); static int ES3_reserved_ES3_extension_ES3_1_keyword(TParseContext *context, TExtension extension, int token);
static int ES3_1_reserved_ES3_1_extension_ES3_2_keyword(TParseContext *context, TExtension extension, int token);
static int uint_constant(TParseContext *context); static int uint_constant(TParseContext *context);
static int int_constant(TParseContext *context); static int int_constant(TParseContext *context);
static int float_constant(yyscan_t yyscanner); static int float_constant(yyscan_t yyscanner);
...@@ -258,6 +259,8 @@ O [0-7] ...@@ -258,6 +259,8 @@ O [0-7]
"volatile" { return ES2_reserved_ES3_1_keyword(context, VOLATILE); } "volatile" { return ES2_reserved_ES3_1_keyword(context, VOLATILE); }
"atomic_uint" { return ES3_reserved_ES3_1_keyword(context, ATOMICUINT); } "atomic_uint" { return ES3_reserved_ES3_1_keyword(context, ATOMICUINT); }
"precise" { return ES3_1_reserved_ES3_1_extension_ES3_2_keyword(context, TExtension::EXT_gpu_shader5, PRECISE); }
/* Reserved keywords for GLSL ES 3.00 that are not reserved for GLSL ES 1.00 */ /* Reserved keywords for GLSL ES 3.00 that are not reserved for GLSL ES 1.00 */
"resource" | "resource" |
"noperspective" | "noperspective" |
...@@ -653,6 +656,27 @@ int ES3_reserved_ES3_extension_ES3_1_keyword(TParseContext *context, TExtension ...@@ -653,6 +656,27 @@ int ES3_reserved_ES3_extension_ES3_1_keyword(TParseContext *context, TExtension
return check_type(yyscanner); return check_type(yyscanner);
} }
static int ES3_1_reserved_ES3_1_extension_ES3_2_keyword(TParseContext *context, TExtension extension, int token)
{
struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
yyscan_t yyscanner = (yyscan_t) context->getScanner();
// A keyword in GLSL ES 3.20 or GLSL ES 3.10 with enabled extension.
if (is_extension_enabled_or_is_core(context, 310, extension, 320))
{
return token;
}
// A reserved word in GLSL ES 3.10
if (context->getShaderVersion() == 310)
{
return reserved_word(yyscanner);
}
yylval->lex.string = AllocatePoolCharArray(yytext, yyleng);
return check_type(yyscanner);
}
int uint_constant(TParseContext *context) int uint_constant(TParseContext *context)
{ {
struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner(); struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
......
...@@ -160,7 +160,7 @@ extern void yyerror(YYLTYPE* yylloc, TParseContext* context, void *scanner, cons ...@@ -160,7 +160,7 @@ extern void yyerror(YYLTYPE* yylloc, TParseContext* context, void *scanner, cons
} while (0) } while (0)
%} %}
%token <lex> INVARIANT HIGH_PRECISION MEDIUM_PRECISION LOW_PRECISION PRECISION %token <lex> INVARIANT PRECISE HIGH_PRECISION MEDIUM_PRECISION LOW_PRECISION PRECISION
%token <lex> ATTRIBUTE CONST_QUAL BOOL_TYPE FLOAT_TYPE INT_TYPE UINT_TYPE %token <lex> ATTRIBUTE CONST_QUAL BOOL_TYPE FLOAT_TYPE INT_TYPE UINT_TYPE
%token <lex> BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN SWITCH CASE DEFAULT %token <lex> BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN SWITCH CASE DEFAULT
%token <lex> BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 VEC2 VEC3 VEC4 UVEC2 UVEC3 UVEC4 %token <lex> BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 VEC2 VEC3 VEC4 UVEC2 UVEC3 UVEC4
...@@ -229,7 +229,7 @@ extern void yyerror(YYLTYPE* yylloc, TParseContext* context, void *scanner, cons ...@@ -229,7 +229,7 @@ extern void yyerror(YYLTYPE* yylloc, TParseContext* context, void *scanner, cons
%type <interm.precision> precision_qualifier %type <interm.precision> precision_qualifier
%type <interm.layoutQualifier> layout_qualifier %type <interm.layoutQualifier> layout_qualifier
%type <interm.qualifier> interpolation_qualifier %type <interm.qualifier> interpolation_qualifier
%type <interm.qualifierWrapper> storage_qualifier single_type_qualifier invariant_qualifier %type <interm.qualifierWrapper> storage_qualifier single_type_qualifier invariant_qualifier precise_qualifier
%type <interm.typeQualifierBuilder> type_qualifier %type <interm.typeQualifierBuilder> type_qualifier
%type <interm.typeSpecifierNonArray> type_specifier_nonarray struct_specifier %type <interm.typeSpecifierNonArray> type_specifier_nonarray struct_specifier
...@@ -622,7 +622,7 @@ declaration ...@@ -622,7 +622,7 @@ declaration
context->parseGlobalLayoutQualifier(*$1); context->parseGlobalLayoutQualifier(*$1);
$$ = nullptr; $$ = nullptr;
} }
| type_qualifier IDENTIFIER SEMICOLON // e.g. to qualify an existing variable as invariant | type_qualifier IDENTIFIER SEMICOLON // e.g. to qualify an existing variable as invariant or precise
{ {
$$ = context->parseGlobalQualifierDeclaration(*$1, @2, ImmutableString($2.string), $2.symbol); $$ = context->parseGlobalQualifierDeclaration(*$1, @2, ImmutableString($2.string), $2.symbol);
} }
...@@ -798,6 +798,12 @@ invariant_qualifier ...@@ -798,6 +798,12 @@ invariant_qualifier
} }
; ;
precise_qualifier
: PRECISE {
// empty
}
;
single_type_qualifier single_type_qualifier
: storage_qualifier { : storage_qualifier {
context->checkLocalVariableConstStorageQualifier(*$1); context->checkLocalVariableConstStorageQualifier(*$1);
...@@ -817,6 +823,9 @@ single_type_qualifier ...@@ -817,6 +823,9 @@ single_type_qualifier
context->checkIsAtGlobalLevel(@1, "invariant"); context->checkIsAtGlobalLevel(@1, "invariant");
$$ = new TInvariantQualifierWrapper(@1); $$ = new TInvariantQualifierWrapper(@1);
} }
| precise_qualifier {
$$ = new TPreciseQualifierWrapper(@1);
}
; ;
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -25,9 +25,12 @@ class RemoveInvariantDeclarationTraverser : public TIntermTraverser ...@@ -25,9 +25,12 @@ class RemoveInvariantDeclarationTraverser : public TIntermTraverser
bool visitGlobalQualifierDeclaration(Visit visit, bool visitGlobalQualifierDeclaration(Visit visit,
TIntermGlobalQualifierDeclaration *node) override TIntermGlobalQualifierDeclaration *node) override
{ {
TIntermSequence emptyReplacement; if (node->isInvariant())
mMultiReplacements.push_back( {
NodeReplaceWithMultipleEntry(getParentNode()->getAsBlock(), node, emptyReplacement)); TIntermSequence emptyReplacement;
mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(getParentNode()->getAsBlock(),
node, emptyReplacement));
}
return false; return false;
} }
}; };
......
...@@ -900,6 +900,7 @@ const ExtensionInfoMap &GetExtensionInfoMap() ...@@ -900,6 +900,7 @@ const ExtensionInfoMap &GetExtensionInfoMap()
map["GL_ANGLE_get_image"] = enableableExtension(&Extensions::getImageANGLE); map["GL_ANGLE_get_image"] = enableableExtension(&Extensions::getImageANGLE);
map["GL_OES_draw_elements_base_vertex"] = enableableExtension(&Extensions::drawElementsBaseVertexOES); map["GL_OES_draw_elements_base_vertex"] = enableableExtension(&Extensions::drawElementsBaseVertexOES);
map["GL_EXT_draw_elements_base_vertex"] = enableableExtension(&Extensions::drawElementsBaseVertexEXT); map["GL_EXT_draw_elements_base_vertex"] = enableableExtension(&Extensions::drawElementsBaseVertexEXT);
map["GL_EXT_gpu_shader5"] = enableableExtension(&Extensions::gpuShader5EXT);
// GLES1 extensinos // GLES1 extensinos
map["GL_OES_point_size_array"] = enableableExtension(&Extensions::pointSizeArray); map["GL_OES_point_size_array"] = enableableExtension(&Extensions::pointSizeArray);
map["GL_OES_texture_cube_map"] = enableableExtension(&Extensions::textureCubeMap); map["GL_OES_texture_cube_map"] = enableableExtension(&Extensions::textureCubeMap);
......
...@@ -557,6 +557,9 @@ struct Extensions ...@@ -557,6 +557,9 @@ struct Extensions
{ {
return (drawElementsBaseVertexOES || drawElementsBaseVertexEXT); return (drawElementsBaseVertexOES || drawElementsBaseVertexEXT);
} }
// GL_EXT_gpu_shader5
bool gpuShader5EXT = false;
}; };
// Pointer to a boolean memeber of the Extensions struct // Pointer to a boolean memeber of the Extensions struct
......
...@@ -94,6 +94,7 @@ Compiler::Compiler(rx::GLImplFactory *implFactory, const State &state) ...@@ -94,6 +94,7 @@ Compiler::Compiler(rx::GLImplFactory *implFactory, const State &state)
mResources.OES_EGL_image_external_essl3 = extensions.eglImageExternalEssl3; mResources.OES_EGL_image_external_essl3 = extensions.eglImageExternalEssl3;
mResources.NV_EGL_stream_consumer_external = extensions.eglStreamConsumerExternal; mResources.NV_EGL_stream_consumer_external = extensions.eglStreamConsumerExternal;
mResources.ARB_texture_rectangle = extensions.textureRectangle; mResources.ARB_texture_rectangle = extensions.textureRectangle;
mResources.EXT_gpu_shader5 = extensions.gpuShader5EXT;
mResources.OES_texture_storage_multisample_2d_array = mResources.OES_texture_storage_multisample_2d_array =
extensions.textureStorageMultisample2DArray; extensions.textureStorageMultisample2DArray;
mResources.OES_texture_3D = extensions.texture3DOES; mResources.OES_texture_3D = extensions.texture3DOES;
......
...@@ -1226,6 +1226,12 @@ gl::Version RendererVk::getMaxSupportedESVersion() const ...@@ -1226,6 +1226,12 @@ gl::Version RendererVk::getMaxSupportedESVersion() const
// Current highest supported version // Current highest supported version
gl::Version maxVersion = gl::Version(3, 1); gl::Version maxVersion = gl::Version(3, 1);
// Limit to ES3.1 if there are any blockers for 3.2.
if (!vk::CanSupportGPUShader5EXT(mPhysicalDeviceFeatures))
{
maxVersion = std::min(maxVersion, gl::Version(3, 1));
}
// Limit to ES3.0 if there are any blockers for 3.1. // Limit to ES3.0 if there are any blockers for 3.1.
// ES3.1 requires at least one atomic counter buffer and four storage buffers in compute. // ES3.1 requires at least one atomic counter buffer and four storage buffers in compute.
......
...@@ -139,6 +139,8 @@ void RendererVk::ensureCapsInitialized() const ...@@ -139,6 +139,8 @@ void RendererVk::ensureCapsInitialized() const
// We support getting image data for Textures and Renderbuffers. // We support getting image data for Textures and Renderbuffers.
mNativeExtensions.getImageANGLE = true; mNativeExtensions.getImageANGLE = true;
mNativeExtensions.gpuShader5EXT = vk::CanSupportGPUShader5EXT(mPhysicalDeviceFeatures);
// https://vulkan.lunarg.com/doc/view/1.0.30.0/linux/vkspec.chunked/ch31s02.html // https://vulkan.lunarg.com/doc/view/1.0.30.0/linux/vkspec.chunked/ch31s02.html
mNativeCaps.maxElementIndex = std::numeric_limits<GLuint>::max() - 1; mNativeCaps.maxElementIndex = std::numeric_limits<GLuint>::max() - 1;
mNativeCaps.max3DTextureSize = LimitToInt(limitsVk.maxImageDimension3D); mNativeCaps.max3DTextureSize = LimitToInt(limitsVk.maxImageDimension3D);
...@@ -476,6 +478,25 @@ void RendererVk::ensureCapsInitialized() const ...@@ -476,6 +478,25 @@ void RendererVk::ensureCapsInitialized() const
} }
} }
namespace vk
{
bool CanSupportGPUShader5EXT(const VkPhysicalDeviceFeatures &features)
{
// We use the following Vulkan features to implement EXT_gpu_shader5:
// - shaderImageGatherExtended: textureGatherOffset family of functions
// - shaderSampledImageArrayDynamicIndexing and shaderUniformBufferArrayDynamicIndexing:
// dynamically uniform indices for samplers and uniform buffers.
// - shaderStorageBufferArrayDynamicIndexing: While EXT_gpu_shader5 doesn't require dynamically
// uniform indices on storage buffers, we need it as we emulate atomic counter buffers with
// storage buffers (and atomic counter buffers *can* be indexed in that way).
return features.shaderImageGatherExtended && features.shaderSampledImageArrayDynamicIndexing &&
features.shaderUniformBufferArrayDynamicIndexing &&
features.shaderStorageBufferArrayDynamicIndexing;
}
} // namespace vk
namespace egl_vk namespace egl_vk
{ {
......
...@@ -53,6 +53,13 @@ egl::ConfigSet GenerateConfigs(const GLenum (&colorFormats)[ColorFormatCount], ...@@ -53,6 +53,13 @@ egl::ConfigSet GenerateConfigs(const GLenum (&colorFormats)[ColorFormatCount],
} }
} // namespace egl_vk } // namespace egl_vk
namespace vk
{
// Functions that determine support for a feature or extension, used both to advertise support for
// an extension, and to determine if a context version can be supported.
bool CanSupportGPUShader5EXT(const VkPhysicalDeviceFeatures &features);
} // namespace vk
} // namespace rx } // namespace rx
#endif #endif
...@@ -618,6 +618,9 @@ ...@@ -618,6 +618,9 @@
2703 VULKAN ANDROID : dEQP-GLES31.functional.shaders.opaque_type_indexing.atomic_counter.const_expression_vertex = FAIL 2703 VULKAN ANDROID : dEQP-GLES31.functional.shaders.opaque_type_indexing.atomic_counter.const_expression_vertex = FAIL
2703 VULKAN ANDROID : dEQP-GLES31.functional.shaders.opaque_type_indexing.atomic_counter.const_expression_fragment = FAIL 2703 VULKAN ANDROID : dEQP-GLES31.functional.shaders.opaque_type_indexing.atomic_counter.const_expression_fragment = FAIL
2703 VULKAN ANDROID : dEQP-GLES31.functional.shaders.opaque_type_indexing.atomic_counter.const_expression_compute = FAIL 2703 VULKAN ANDROID : dEQP-GLES31.functional.shaders.opaque_type_indexing.atomic_counter.const_expression_compute = FAIL
2703 VULKAN ANDROID : dEQP-GLES31.functional.shaders.opaque_type_indexing.atomic_counter.*uniform_vertex = FAIL
2703 VULKAN ANDROID : dEQP-GLES31.functional.shaders.opaque_type_indexing.atomic_counter.*uniform_fragment = FAIL
2703 VULKAN ANDROID : dEQP-GLES31.functional.shaders.opaque_type_indexing.atomic_counter.*uniform_compute = FAIL
// General Vulkan failures // General Vulkan failures
...@@ -692,3 +695,22 @@ ...@@ -692,3 +695,22 @@
4105 SWIFTSHADER : dEQP-GLES31.functional.stencil_texturing.format.depth24_stencil8_cube = FAIL 4105 SWIFTSHADER : dEQP-GLES31.functional.stencil_texturing.format.depth24_stencil8_cube = FAIL
4105 SWIFTSHADER : dEQP-GLES31.functional.stencil_texturing.format.depth32f_stencil8_cube = FAIL 4105 SWIFTSHADER : dEQP-GLES31.functional.stencil_texturing.format.depth32f_stencil8_cube = FAIL
// OpenGL ES 3.2 / 3.2 extensions
// EXT_gpu_shader5: Note: this extension is not yet fully implemented, so should be disabled in the
// Vulkan backend for the ES 3.1 conformance run.
3569 VULKAN : dEQP-GLES31.functional.shaders.builtin_functions.common.fma.*vertex = FAIL
3569 VULKAN : dEQP-GLES31.functional.shaders.builtin_functions.common.fma.*fragment = FAIL
3569 VULKAN : dEQP-GLES31.functional.shaders.builtin_functions.common.fma.*compute = FAIL
3569 VULKAN : dEQP-GLES31.functional.shaders.builtin_functions.precision.fma*vertex* = FAIL
3569 VULKAN : dEQP-GLES31.functional.shaders.builtin_functions.precision.fma*fragment* = FAIL
3569 VULKAN : dEQP-GLES31.functional.shaders.builtin_functions.precision.fma*compute* = FAIL
3569 VULKAN : dEQP-GLES31.functional.shaders.opaque_type_indexing.sampler.*uniform.*vertex* = FAIL
3569 VULKAN : dEQP-GLES31.functional.shaders.opaque_type_indexing.sampler.*uniform.*fragment* = FAIL
3569 VULKAN : dEQP-GLES31.functional.shaders.opaque_type_indexing.sampler.*uniform.*compute* = FAIL
3569 VULKAN : dEQP-GLES31.functional.shaders.opaque_type_indexing.ubo.*uniform_vertex = FAIL
3569 VULKAN : dEQP-GLES31.functional.shaders.opaque_type_indexing.ubo.*uniform_fragment = FAIL
3569 VULKAN : dEQP-GLES31.functional.shaders.opaque_type_indexing.ubo.*uniform_compute = FAIL
3569 VULKAN : dEQP-GLES31.functional.texture.gather.offset_dynamic.* = FAIL
3569 VULKAN : dEQP-GLES31.functional.texture.gather.offsets.* = FAIL
...@@ -146,3 +146,9 @@ ...@@ -146,3 +146,9 @@
4106 SWIFTSHADER : KHR-GLES31.core.layout_binding.sampler*_layout_binding_texture_* = FAIL 4106 SWIFTSHADER : KHR-GLES31.core.layout_binding.sampler*_layout_binding_texture_* = FAIL
4108 SWIFTSHADER : KHR-GLES31.core.shader_image_size.*-nonMS-* = SKIP 4108 SWIFTSHADER : KHR-GLES31.core.shader_image_size.*-nonMS-* = SKIP
// OpenGL ES 3.2 / 3.2 extensions
// EXT_gpu_shader5: Note: this extension is not yet fully implemented, so should be disabled in the
// Vulkan backend for the ES 3.1 conformance run.
3569 VULKAN : KHR-GLES31.core.arrays_of_arrays.ExpressionsDynamicIndexing2 = FAIL
...@@ -7449,6 +7449,53 @@ void main() ...@@ -7449,6 +7449,53 @@ void main()
EXPECT_TRUE(VerifyBuffer(ssbo, data, size)); EXPECT_TRUE(VerifyBuffer(ssbo, data, size));
} }
// Test that the precise keyword is not reserved before ES3.1.
TEST_P(GLSLTest_ES3, PreciseNotReserved)
{
// Skip in ES3.1+ as the precise keyword is reserved/core.
ANGLE_SKIP_TEST_IF(getClientMajorVersion() > 3 ||
(getClientMajorVersion() == 3 && getClientMinorVersion() >= 1));
constexpr char kFS[] = R"(#version 300 es
precision mediump float;
in float precise;
out vec4 my_FragColor;
void main() { my_FragColor = vec4(precise, 0, 0, 1.0); })";
constexpr char kVS[] = R"(#version 300 es
in vec4 a_position;
out float precise;
void main() { precise = a_position.x; gl_Position = a_position; })";
GLuint program = CompileProgram(kVS, kFS);
EXPECT_NE(0u, program);
}
// Test that the precise keyword is reserved on ES3.0 without GL_EXT_gpu_shader5.
TEST_P(GLSLTest_ES31, PreciseReservedWithoutExtension)
{
// Skip if EXT_gpu_shader5 is enabled.
ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_EXT_gpu_shader5"));
// Skip in ES3.2+ as the precise keyword is core.
ANGLE_SKIP_TEST_IF(getClientMajorVersion() > 3 ||
(getClientMajorVersion() == 3 && getClientMinorVersion() >= 2));
constexpr char kFS[] = R"(#version 310 es
precision mediump float;
in float v_varying;
out vec4 my_FragColor;
void main() { my_FragColor = vec4(v_varying, 0, 0, 1.0); })";
constexpr char kVS[] = R"(#version 310 es
in vec4 a_position;
precise out float v_varying;
void main() { v_varying = a_position.x; gl_Position = a_position; })";
// Should fail, as precise is a reserved keyword when the extension is not enabled.
GLuint program = CompileProgram(kVS, kFS);
EXPECT_EQ(0u, program);
}
} // anonymous namespace } // anonymous namespace
// Use this to select which configurations (e.g. which renderer, which GLES major version) these // Use this to select which configurations (e.g. which renderer, which GLES major version) these
......
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