Commit 230e14dd by Shahbaz Youssefi Committed by Commit Bot

Add support for layout(early_fragment_tests) in;

Bug: angleproject:4314 Change-Id: I37b228f37201cc4188834e68459cd7294727c3ac Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2014240Reviewed-by: 's avatarCody Northrop <cnorthrop@google.com> Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
parent 01e28144
...@@ -1122,16 +1122,16 @@ struct TLayoutQualifier ...@@ -1122,16 +1122,16 @@ struct TLayoutQualifier
bool isEmpty() const bool isEmpty() const
{ {
return location == -1 && binding == -1 && offset == -1 && numViews == -1 && yuv == false && return location == -1 && binding == -1 && offset == -1 && numViews == -1 && yuv == false &&
matrixPacking == EmpUnspecified && blockStorage == EbsUnspecified && earlyFragmentTests == false && matrixPacking == EmpUnspecified &&
!localSize.isAnyValueSet() && imageInternalFormat == EiifUnspecified && blockStorage == EbsUnspecified && !localSize.isAnyValueSet() &&
primitiveType == EptUndefined && invocations == 0 && maxVertices == -1 && imageInternalFormat == EiifUnspecified && primitiveType == EptUndefined &&
index == -1; invocations == 0 && maxVertices == -1 && index == -1;
} }
bool isCombinationValid() const bool isCombinationValid() const
{ {
bool workSizeSpecified = localSize.isAnyValueSet(); bool workGroupSizeSpecified = localSize.isAnyValueSet();
bool numViewsSet = (numViews != -1); bool numViewsSet = (numViews != -1);
bool geometryShaderSpecified = bool geometryShaderSpecified =
(primitiveType != EptUndefined) || (invocations != 0) || (maxVertices != -1); (primitiveType != EptUndefined) || (invocations != 0) || (maxVertices != -1);
bool otherLayoutQualifiersSpecified = bool otherLayoutQualifiersSpecified =
...@@ -1139,9 +1139,11 @@ struct TLayoutQualifier ...@@ -1139,9 +1139,11 @@ struct TLayoutQualifier
blockStorage != EbsUnspecified || imageInternalFormat != EiifUnspecified); blockStorage != EbsUnspecified || imageInternalFormat != EiifUnspecified);
// we can have either the work group size specified, or number of views, // we can have either the work group size specified, or number of views,
// or yuv layout qualifier, or the other layout qualifiers. // or yuv layout qualifier, or early_fragment_tests layout qualifier, or the other layout
return (workSizeSpecified ? 1 : 0) + (numViewsSet ? 1 : 0) + (yuv ? 1 : 0) + // qualifiers.
(otherLayoutQualifiersSpecified ? 1 : 0) + (geometryShaderSpecified ? 1 : 0) <= return (workGroupSizeSpecified ? 1 : 0) + (numViewsSet ? 1 : 0) + (yuv ? 1 : 0) +
(earlyFragmentTests ? 1 : 0) + (otherLayoutQualifiersSpecified ? 1 : 0) +
(geometryShaderSpecified ? 1 : 0) <=
1; 1;
} }
...@@ -1170,6 +1172,9 @@ struct TLayoutQualifier ...@@ -1170,6 +1172,9 @@ struct TLayoutQualifier
// EXT_YUV_target yuv layout qualifier. // EXT_YUV_target yuv layout qualifier.
bool yuv; bool yuv;
// early_fragment_tests qualifier.
bool earlyFragmentTests;
// OES_geometry_shader layout qualifiers. // OES_geometry_shader layout qualifiers.
TLayoutPrimitiveType primitiveType; TLayoutPrimitiveType primitiveType;
int invocations; int invocations;
...@@ -1190,6 +1195,7 @@ struct TLayoutQualifier ...@@ -1190,6 +1195,7 @@ struct TLayoutQualifier
imageInternalFormat(EiifUnspecified), imageInternalFormat(EiifUnspecified),
numViews(-1), numViews(-1),
yuv(false), yuv(false),
earlyFragmentTests(false),
primitiveType(EptUndefined), primitiveType(EptUndefined),
invocations(0), invocations(0),
maxVertices(-1), maxVertices(-1),
......
...@@ -482,6 +482,8 @@ void TCompiler::setASTMetadata(const TParseContext &parseContext) ...@@ -482,6 +482,8 @@ void TCompiler::setASTMetadata(const TParseContext &parseContext)
mPragma = parseContext.pragma(); mPragma = parseContext.pragma();
mSymbolTable.setGlobalInvariant(mPragma.stdgl.invariantAll); mSymbolTable.setGlobalInvariant(mPragma.stdgl.invariantAll);
mEarlyFragmentTestsSpecified = parseContext.isEarlyFragmentTestsSpecified();
mComputeShaderLocalSizeDeclared = parseContext.isComputeShaderLocalSizeDeclared(); mComputeShaderLocalSizeDeclared = parseContext.isComputeShaderLocalSizeDeclared();
mComputeShaderLocalSize = parseContext.getComputeShaderLocalSize(); mComputeShaderLocalSize = parseContext.getComputeShaderLocalSize();
...@@ -1463,6 +1465,14 @@ bool TCompiler::isVaryingDefined(const char *varyingName) ...@@ -1463,6 +1465,14 @@ bool TCompiler::isVaryingDefined(const char *varyingName)
return false; return false;
} }
void EmitEarlyFragmentTestsGLSL(const TCompiler &compiler, TInfoSinkBase &sink)
{
if (compiler.isEarlyFragmentTestsSpecified())
{
sink << "layout (early_fragment_tests) in;\n";
}
}
void EmitWorkGroupSizeGLSL(const TCompiler &compiler, TInfoSinkBase &sink) void EmitWorkGroupSizeGLSL(const TCompiler &compiler, TInfoSinkBase &sink)
{ {
if (compiler.isComputeShaderLocalSizeDeclared()) if (compiler.isComputeShaderLocalSizeDeclared())
......
...@@ -98,6 +98,8 @@ class TCompiler : public TShHandleBase ...@@ -98,6 +98,8 @@ class TCompiler : public TShHandleBase
int getShaderVersion() const { return mShaderVersion; } int getShaderVersion() const { return mShaderVersion; }
TInfoSink &getInfoSink() { return mInfoSink; } TInfoSink &getInfoSink() { return mInfoSink; }
bool isEarlyFragmentTestsSpecified() const { return mEarlyFragmentTestsSpecified; }
bool isComputeShaderLocalSizeDeclared() const { return mComputeShaderLocalSizeDeclared; } bool isComputeShaderLocalSizeDeclared() const { return mComputeShaderLocalSizeDeclared; }
const sh::WorkGroupSize &getComputeShaderLocalSize() const { return mComputeShaderLocalSize; } const sh::WorkGroupSize &getComputeShaderLocalSize() const { return mComputeShaderLocalSize; }
int getNumViews() const { return mNumViews; } int getNumViews() const { return mNumViews; }
...@@ -268,6 +270,9 @@ class TCompiler : public TShHandleBase ...@@ -268,6 +270,9 @@ class TCompiler : public TShHandleBase
TDiagnostics mDiagnostics; TDiagnostics mDiagnostics;
const char *mSourcePath; // Path of source file or NULL const char *mSourcePath; // Path of source file or NULL
// fragment shader early fragment tests
bool mEarlyFragmentTestsSpecified;
// compute shader local group size // compute shader local group size
bool mComputeShaderLocalSizeDeclared; bool mComputeShaderLocalSizeDeclared;
sh::WorkGroupSize mComputeShaderLocalSize; sh::WorkGroupSize mComputeShaderLocalSize;
...@@ -304,6 +309,7 @@ class TCompiler : public TShHandleBase ...@@ -304,6 +309,7 @@ class TCompiler : public TShHandleBase
TCompiler *ConstructCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output); TCompiler *ConstructCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output);
void DeleteCompiler(TCompiler *); void DeleteCompiler(TCompiler *);
void EmitEarlyFragmentTestsGLSL(const TCompiler &, TInfoSinkBase &sink);
void EmitWorkGroupSizeGLSL(const TCompiler &, TInfoSinkBase &sink); void EmitWorkGroupSizeGLSL(const TCompiler &, TInfoSinkBase &sink);
void EmitMultiviewGLSL(const TCompiler &, void EmitMultiviewGLSL(const TCompiler &,
const ShCompileOptions &, const ShCompileOptions &,
......
...@@ -185,6 +185,7 @@ TParseContext::TParseContext(TSymbolTable &symt, ...@@ -185,6 +185,7 @@ TParseContext::TParseContext(TSymbolTable &symt,
mFunctionReturnsValue(false), mFunctionReturnsValue(false),
mChecksPrecisionErrors(checksPrecErrors), mChecksPrecisionErrors(checksPrecErrors),
mFragmentPrecisionHighOnESSL1(false), mFragmentPrecisionHighOnESSL1(false),
mEarlyFragmentTestsSpecified(false),
mDefaultUniformMatrixPacking(EmpColumnMajor), mDefaultUniformMatrixPacking(EmpColumnMajor),
mDefaultUniformBlockStorage(sh::IsWebGLBasedSpec(spec) ? EbsStd140 : EbsShared), mDefaultUniformBlockStorage(sh::IsWebGLBasedSpec(spec) ? EbsStd140 : EbsShared),
mDefaultBufferMatrixPacking(EmpColumnMajor), mDefaultBufferMatrixPacking(EmpColumnMajor),
...@@ -1360,6 +1361,11 @@ void TParseContext::declarationQualifierErrorCheck(const sh::TQualifier qualifie ...@@ -1360,6 +1361,11 @@ void TParseContext::declarationQualifierErrorCheck(const sh::TQualifier qualifie
checkYuvIsNotSpecified(location, layoutQualifier.yuv); checkYuvIsNotSpecified(location, layoutQualifier.yuv);
} }
if (qualifier != EvqFragmentIn)
{
checkEarlyFragmentTestsIsNotSpecified(location, layoutQualifier.earlyFragmentTests);
}
// If multiview extension is enabled, "in" qualifier is allowed in the vertex shader in previous // If multiview extension is enabled, "in" qualifier is allowed in the vertex shader in previous
// parsing steps. So it needs to be checked here. // parsing steps. So it needs to be checked here.
if (anyMultiviewExtensionAvailable() && mShaderVersion < 300 && qualifier == EvqVertexIn) if (anyMultiviewExtensionAvailable() && mShaderVersion < 300 && qualifier == EvqVertexIn)
...@@ -1736,6 +1742,17 @@ void TParseContext::checkYuvIsNotSpecified(const TSourceLoc &location, bool yuv) ...@@ -1736,6 +1742,17 @@ void TParseContext::checkYuvIsNotSpecified(const TSourceLoc &location, bool yuv)
} }
} }
void TParseContext::checkEarlyFragmentTestsIsNotSpecified(const TSourceLoc &location,
bool earlyFragmentTests)
{
if (earlyFragmentTests != false)
{
error(location,
"invalid layout qualifier: only valid when used with 'in' in a fragment shader",
"early_fragment_tests");
}
}
void TParseContext::functionCallRValueLValueErrorCheck(const TFunction *fnCandidate, void TParseContext::functionCallRValueLValueErrorCheck(const TFunction *fnCandidate,
TIntermAggregate *fnCall) TIntermAggregate *fnCall)
{ {
...@@ -2215,6 +2232,9 @@ TPublicType TParseContext::addFullySpecifiedType(const TTypeQualifierBuilder &ty ...@@ -2215,6 +2232,9 @@ TPublicType TParseContext::addFullySpecifiedType(const TTypeQualifierBuilder &ty
checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), returnType.layoutQualifier); checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), returnType.layoutQualifier);
checkEarlyFragmentTestsIsNotSpecified(typeSpecifier.getLine(),
returnType.layoutQualifier.earlyFragmentTests);
if (mShaderVersion < 300) if (mShaderVersion < 300)
{ {
if (typeSpecifier.isArray()) if (typeSpecifier.isArray())
...@@ -3067,6 +3087,12 @@ void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &type ...@@ -3067,6 +3087,12 @@ void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &type
checkStd430IsForShaderStorageBlock(typeQualifier.line, layoutQualifier.blockStorage, checkStd430IsForShaderStorageBlock(typeQualifier.line, layoutQualifier.blockStorage,
typeQualifier.qualifier); typeQualifier.qualifier);
if (typeQualifier.qualifier != EvqFragmentIn)
{
checkEarlyFragmentTestsIsNotSpecified(typeQualifier.line,
layoutQualifier.earlyFragmentTests);
}
if (typeQualifier.qualifier == EvqComputeIn) if (typeQualifier.qualifier == EvqComputeIn)
{ {
if (mComputeShaderLocalSizeDeclared && if (mComputeShaderLocalSizeDeclared &&
...@@ -3170,6 +3196,27 @@ void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &type ...@@ -3170,6 +3196,27 @@ void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &type
mNumViews = layoutQualifier.numViews; mNumViews = layoutQualifier.numViews;
} }
else if (typeQualifier.qualifier == EvqFragmentIn)
{
if (mShaderVersion < 310)
{
error(typeQualifier.line,
"in type qualifier without variable declaration supported in GLSL ES 3.10 only",
"layout");
return;
}
if (!layoutQualifier.earlyFragmentTests)
{
error(typeQualifier.line,
"only early_fragment_tests is allowed as layout qualifier when not declaring a "
"variable",
"layout");
return;
}
mEarlyFragmentTestsSpecified = true;
}
else else
{ {
if (!checkWorkGroupSizeIsNotSpecified(typeQualifier.line, layoutQualifier)) if (!checkWorkGroupSizeIsNotSpecified(typeQualifier.line, layoutQualifier))
...@@ -3713,6 +3760,8 @@ TIntermDeclaration *TParseContext::addInterfaceBlock( ...@@ -3713,6 +3760,8 @@ TIntermDeclaration *TParseContext::addInterfaceBlock(
} }
checkYuvIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.yuv); checkYuvIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.yuv);
checkEarlyFragmentTestsIsNotSpecified(typeQualifier.line,
typeQualifier.layoutQualifier.earlyFragmentTests);
TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier; TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier;
checkLocationIsNotSpecified(typeQualifier.line, blockLayoutQualifier); checkLocationIsNotSpecified(typeQualifier.line, blockLayoutQualifier);
...@@ -4348,6 +4397,11 @@ TLayoutQualifier TParseContext::parseLayoutQualifier(const ImmutableString &qual ...@@ -4348,6 +4397,11 @@ TLayoutQualifier TParseContext::parseLayoutQualifier(const ImmutableString &qual
qualifier.yuv = true; qualifier.yuv = true;
} }
} }
else if (qualifierType == "early_fragment_tests")
{
checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
qualifier.earlyFragmentTests = true;
}
else if (qualifierType == "rgba32f") else if (qualifierType == "rgba32f")
{ {
checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310); checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
...@@ -4858,6 +4912,8 @@ TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecif ...@@ -4858,6 +4912,8 @@ TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecif
typeSpecifier.getBasicType()); typeSpecifier.getBasicType());
checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), typeSpecifier.layoutQualifier); checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), typeSpecifier.layoutQualifier);
checkEarlyFragmentTestsIsNotSpecified(typeSpecifier.getLine(),
typeSpecifier.layoutQualifier.earlyFragmentTests);
TFieldList *fieldList = new TFieldList(); TFieldList *fieldList = new TFieldList();
......
...@@ -75,6 +75,8 @@ class TParseContext : angle::NonCopyable ...@@ -75,6 +75,8 @@ class TParseContext : angle::NonCopyable
mFragmentPrecisionHighOnESSL1 = fragmentPrecisionHigh; mFragmentPrecisionHighOnESSL1 = fragmentPrecisionHigh;
} }
bool isEarlyFragmentTestsSpecified() const { return mEarlyFragmentTestsSpecified; }
void setLoopNestingLevel(int loopNestintLevel) { mLoopNestingLevel = loopNestintLevel; } void setLoopNestingLevel(int loopNestintLevel) { mLoopNestingLevel = loopNestintLevel; }
void incrLoopNestingLevel() { ++mLoopNestingLevel; } void incrLoopNestingLevel() { ++mLoopNestingLevel; }
...@@ -543,6 +545,8 @@ class TParseContext : angle::NonCopyable ...@@ -543,6 +545,8 @@ class TParseContext : angle::NonCopyable
void checkYuvIsNotSpecified(const TSourceLoc &location, bool yuv); void checkYuvIsNotSpecified(const TSourceLoc &location, bool yuv);
void checkEarlyFragmentTestsIsNotSpecified(const TSourceLoc &location, bool earlyFragmentTests);
bool checkUnsizedArrayConstructorArgumentDimensionality(const TIntermSequence &arguments, bool checkUnsizedArrayConstructorArgumentDimensionality(const TIntermSequence &arguments,
TType type, TType type,
const TSourceLoc &line); const TSourceLoc &line);
...@@ -620,6 +624,7 @@ class TParseContext : angle::NonCopyable ...@@ -620,6 +624,7 @@ class TParseContext : angle::NonCopyable
// without precision, explicit or implicit. // without precision, explicit or implicit.
bool mFragmentPrecisionHighOnESSL1; // true if highp precision is supported when compiling bool mFragmentPrecisionHighOnESSL1; // true if highp precision is supported when compiling
// ESSL1. // ESSL1.
bool mEarlyFragmentTestsSpecified; // true if layout(early_fragment_tests) in; is specified.
TLayoutMatrixPacking mDefaultUniformMatrixPacking; TLayoutMatrixPacking mDefaultUniformMatrixPacking;
TLayoutBlockStorage mDefaultUniformBlockStorage; TLayoutBlockStorage mDefaultUniformBlockStorage;
TLayoutMatrixPacking mDefaultBufferMatrixPacking; TLayoutMatrixPacking mDefaultBufferMatrixPacking;
......
...@@ -638,6 +638,10 @@ TLayoutQualifier JoinLayoutQualifiers(TLayoutQualifier leftQualifier, ...@@ -638,6 +638,10 @@ TLayoutQualifier JoinLayoutQualifiers(TLayoutQualifier leftQualifier,
{ {
joinedQualifier.yuv = rightQualifier.yuv; joinedQualifier.yuv = rightQualifier.yuv;
} }
if (rightQualifier.earlyFragmentTests != false)
{
joinedQualifier.earlyFragmentTests = rightQualifier.earlyFragmentTests;
}
if (rightQualifier.binding != -1) if (rightQualifier.binding != -1)
{ {
joinedQualifier.binding = rightQualifier.binding; joinedQualifier.binding = rightQualifier.binding;
......
...@@ -90,6 +90,11 @@ bool TranslatorESSL::translate(TIntermBlock *root, ...@@ -90,6 +90,11 @@ bool TranslatorESSL::translate(TIntermBlock *root,
// Write array bounds clamping emulation if needed. // Write array bounds clamping emulation if needed.
getArrayBoundsClamper().OutputClampingFunctionDefinition(sink); getArrayBoundsClamper().OutputClampingFunctionDefinition(sink);
if (getShaderType() == GL_FRAGMENT_SHADER)
{
EmitEarlyFragmentTestsGLSL(*this, sink);
}
if (getShaderType() == GL_COMPUTE_SHADER) if (getShaderType() == GL_COMPUTE_SHADER)
{ {
EmitWorkGroupSizeGLSL(*this, sink); EmitWorkGroupSizeGLSL(*this, sink);
......
...@@ -201,6 +201,8 @@ bool TranslatorGLSL::translate(TIntermBlock *root, ...@@ -201,6 +201,8 @@ bool TranslatorGLSL::translate(TIntermBlock *root,
sink << "out vec4 angle_SecondaryFragData[" << getResources().MaxDualSourceDrawBuffers sink << "out vec4 angle_SecondaryFragData[" << getResources().MaxDualSourceDrawBuffers
<< "];\n"; << "];\n";
} }
EmitEarlyFragmentTestsGLSL(*this, sink);
} }
if (getShaderType() == GL_COMPUTE_SHADER) if (getShaderType() == GL_COMPUTE_SHADER)
......
...@@ -915,6 +915,8 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root, ...@@ -915,6 +915,8 @@ bool TranslatorVulkan::translateImpl(TIntermBlock *root,
return false; return false;
} }
} }
EmitEarlyFragmentTestsGLSL(*this, sink);
} }
else if (getShaderType() == GL_VERTEX_SHADER) else if (getShaderType() == GL_VERTEX_SHADER)
{ {
......
...@@ -1924,6 +1924,21 @@ TEST_F(ComputeShaderValidationTest, NoWorkGroupSizeSpecified) ...@@ -1924,6 +1924,21 @@ TEST_F(ComputeShaderValidationTest, NoWorkGroupSizeSpecified)
} }
} }
// Test that workgroup size declaration doesn't accept variable declaration.
TEST_F(ComputeShaderValidationTest, NoVariableDeclrationAfterWorkGroupSize)
{
constexpr char kShaderString[] =
R"(#version 310 es
layout(local_size_x = 1) in vec4 x;
void main()
{
})";
if (compile(kShaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
// Work group size is less than 1. It should be at least 1. // Work group size is less than 1. It should be at least 1.
// GLSL ES 3.10 Revision 4, 7.1.3 Compute Shader Special Variables // GLSL ES 3.10 Revision 4, 7.1.3 Compute Shader Special Variables
// The spec is not clear whether having a local size qualifier equal zero // The spec is not clear whether having a local size qualifier equal zero
...@@ -6185,3 +6200,155 @@ void main() { ...@@ -6185,3 +6200,155 @@ void main() {
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
} }
} }
// Test that layout(early_fragment_tests) in; is valid in fragment shader
TEST_F(FragmentShaderValidationTest, ValidEarlyFragmentTests)
{
constexpr char kShaderString[] =
R"(#version 310 es
precision mediump float;
layout(early_fragment_tests) in;
out vec4 color;
void main()
{
color = vec4(0.0);
})";
if (!compile(kShaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
// Test that layout(early_fragment_tests=x) in; is invalid
TEST_F(FragmentShaderValidationTest, InvalidValueForEarlyFragmentTests)
{
constexpr char kShaderString[] =
R"(#version 310 es
precision mediump float;
layout(early_fragment_tests=1) in;
out vec4 color;
void main()
{
color = vec4(0.0);
})";
if (compile(kShaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
// Test that layout(early_fragment_tests) in varying; is invalid
TEST_F(FragmentShaderValidationTest, InvalidEarlyFragmentTestsOnVariableDecl)
{
constexpr char kShaderString[] =
R"(#version 310 es
precision mediump float;
layout(early_fragment_tests) in vec4 v;
out vec4 color;
void main()
{
color = v;
})";
if (compile(kShaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
// Test that layout(early_fragment_tests) in; is invalid in vertex shader
TEST_F(VertexShaderValidationTest, InvalidEarlyFragmentTests)
{
constexpr char kShaderString[] =
R"(#version 310 es
layout(early_fragment_tests) in;
void main()
{
gl_Position = vec4(0.0);
})";
if (compile(kShaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
// Test that layout(early_fragment_tests) in; is invalid in compute shader
TEST_F(ComputeShaderValidationTest, InvalidEarlyFragmentTests)
{
constexpr char kShaderString[] =
R"(#version 310 es
layout(local_size_x = 1) in;
layout(early_fragment_tests) in;
void main() {})";
if (compile(kShaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
// Test that layout(x) in; only accepts x=early_fragment_tests.
TEST_F(FragmentShaderValidationTest, NothingButEarlyFragmentTestsWithInWithoutVariableDecl)
{
const char *noValueQualifiers[] = {
"shared", "packed",
"std140", "std430",
"row_major", "col_major",
"location", "yuv",
"rgba32f", "rgba16f",
"r32f", "rgba8",
"rgba8_snorm", "rgba32i",
"rgba16i", "rgba8i",
"r32i", "rgba32ui",
"rgba16ui", "rgba8ui",
"r32ui", "points",
"lines", "lines_adjacency",
"triangles", "triangles_adjacency",
"line_strip", "triangle_strip",
};
const char *withValueQualifiers[] = {
"location", "binding", "offset", "local_size_x", "local_size_y",
"local_size_z", "num_views", "invocations", "max_vertices", "index",
};
constexpr char kShaderStringPre[] =
R"(#version 310 es
precision mediump float;
layout()";
constexpr char kShaderStringPost[] =
R"() in;
out vec4 color;
void main()
{
color = vec4(0.0);
})";
// Make sure the method of constructing shaders is valid.
const std::string validShaderString =
kShaderStringPre + std::string("early_fragment_tests") + kShaderStringPost;
if (!compile(validShaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
for (size_t i = 0; i < ArraySize(noValueQualifiers); ++i)
{
const std::string shaderString =
kShaderStringPre + std::string(noValueQualifiers[i]) + kShaderStringPost;
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
for (size_t i = 0; i < ArraySize(withValueQualifiers); ++i)
{
const std::string shaderString =
kShaderStringPre + std::string(withValueQualifiers[i]) + "=1" + kShaderStringPost;
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
}
...@@ -60,7 +60,6 @@ ...@@ -60,7 +60,6 @@
// Image related failures // Image related failures
4314 : KHR-GLES31.core.shader_image_load_store.basic-glsl-earlyFragTests = FAIL
4316 : KHR-GLES31.core.shader_image_load_store.negative-linkErrors = FAIL 4316 : KHR-GLES31.core.shader_image_load_store.negative-linkErrors = FAIL
4312 VULKAN : KHR-GLES31.core.shader_image_load_store.basic-glsl-misc-fs = SKIP 4312 VULKAN : KHR-GLES31.core.shader_image_load_store.basic-glsl-misc-fs = SKIP
4312 VULKAN : KHR-GLES31.core.shader_image_load_store.advanced-sync-imageAccess = SKIP 4312 VULKAN : KHR-GLES31.core.shader_image_load_store.advanced-sync-imageAccess = SKIP
......
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