#include "GLSLANG/ShaderLang.h"
#include "angle_gl.h"
#include "compiler/translator/BaseTypes.h"
#include "gtest/gtest.h"
#include "tests/test_utils/ShaderCompileTreeTest.h"
#include "tests/test_utils/compiler_test.h"
using namespace sh;
class GeometryShaderTest : public ShaderCompileTreeTest
{
public:
GeometryShaderTest() {}
protected:
void initResources(ShBuiltInResources *resources) override
{
resources->EXT_geometry_shader = 1;
}
::GLenum getShaderType() const override { return GL_GEOMETRY_SHADER_EXT; }
ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; }
bool compileGeometryShader(const std::string &statement1, const std::string &statement2)
{
std::ostringstream sstream;
sstream << kHeader << statement1 << statement2 << kEmptyBody;
return compile(sstream.str());
}
bool compileGeometryShader(const std::string &statement1,
const std::string &statement2,
const std::string &statement3,
const std::string &statement4)
{
std::ostringstream sstream;
sstream << kHeader << statement1 << statement2 << statement3 << statement4 << kEmptyBody;
return compile(sstream.str());
}
static std::string GetGeometryShaderLayout(const std::string &layoutType,
const std::string &primitive,
int invocations,
int maxVertices)
{
std::ostringstream sstream;
sstream << "layout (";
if (!primitive.empty())
{
sstream << primitive;
}
if (invocations > 0)
{
sstream << ", invocations = " << invocations;
}
if (maxVertices >= 0)
{
sstream << ", max_vertices = " << maxVertices;
}
sstream << ") " << layoutType << ";" << std::endl;
return sstream.str();
}
static std::string GetInputDeclaration(const std::string &var, int size)
{
std::ostringstream sstream;
sstream << "in ";
if (size < 0)
{
sstream << var << "[];\n";
}
else
{
sstream << var << "[" << size << "];\n";
}
return sstream.str();
}
const std::string kVersion = "#version 310 es\n";
const std::string kHeader =
"#version 310 es\n"
"#extension GL_EXT_geometry_shader : require\n";
const std::string kInputLayout = "layout (points) in;\n";
const std::string kOutputLayout = "layout (points, max_vertices = 1) out;\n";
const std::array<std::string, 4> kInterpolationQualifiers = {{"flat", "smooth", "centroid"}};
const std::map<std::string, int> kInputPrimitivesAndInputArraySizeMap = {
{"points", 1},
{"lines", 2},
{"lines_adjacency", 4},
{"triangles", 3},
{"triangles_adjacency", 6}};
const std::string kEmptyBody =
"void main()\n"
"{\n"
"}\n";
};
class GeometryShaderOutputCodeTest : public MatchOutputCodeTest
{
public:
GeometryShaderOutputCodeTest() : MatchOutputCodeTest(GL_GEOMETRY_SHADER_EXT, SH_ESSL_OUTPUT)
{
ShCompileOptions defaultCompileOptions = {};
defaultCompileOptions.objectCode = true;
setDefaultCompileOptions(defaultCompileOptions);
getResources()->EXT_geometry_shader = 1;
}
};
TEST_F(GeometryShaderTest, Version300)
{
const std::string &shaderString =
R"(#version 300 es
void main()
{
})";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, Version310WithoutExtension)
{
const std::string &shaderString =
R"(#version 310 es
void main()
{
})";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, Version310ExtensionDisabled)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : disable
void main()
{
})";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, Version310WithEXTExtension)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout(points) in;
layout(points, max_vertices = 1) out;
void main()
{
})";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, NoInputPrimitives)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout(points, max_vertices = 1) out;
void main()
{
})";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, ValidInputPrimitives)
{
const std::array<std::string, 4> kInputPrimitives = {
{"lines", "lines_adjacency", "triangles", "triangles_adjacency"}};
for (const std::string &inputPrimitive : kInputPrimitives)
{
if (!compileGeometryShader(GetGeometryShaderLayout("in", inputPrimitive, -1, -1),
kOutputLayout))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
if (compileGeometryShader(kInputLayout,
GetGeometryShaderLayout("out", inputPrimitive, -1, 6)))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
}
TEST_F(GeometryShaderTest, RedeclareInputPrimitives)
{
const std::array<std::string, 5> kInputPrimitives = {
{"points", "lines", "lines_adjacency", "triangles", "triangles_adjacency"}};
for (GLuint i = 0; i < kInputPrimitives.size(); ++i)
{
const std::string &inputLayoutStr1 =
GetGeometryShaderLayout("in", kInputPrimitives[i], -1, -1);
if (!compileGeometryShader(inputLayoutStr1, inputLayoutStr1, kOutputLayout, ""))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
for (GLuint j = i + 1; j < kInputPrimitives.size(); ++j)
{
const std::string &inputLayoutStr2 =
GetGeometryShaderLayout("in", kInputPrimitives[j], -1, -1);
if (compileGeometryShader(inputLayoutStr1, inputLayoutStr2, kOutputLayout, ""))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
}
}
TEST_F(GeometryShaderTest, DeclareDifferentInputPrimitivesInOneLayout)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points, triangles) in;
layout (points, max_vertices = 1) out;
void main()
{
})";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, InvocationsLessThanOne)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points, invocations = 0) in;
layout (points, max_vertices = 1) out;
void main()
{
})";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, InvocationsEqualsOne)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points, invocations = 1) in;
layout (points, max_vertices = 1) out;
void main()
{
})";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, InvocationsEqualsOneInSeparatedLayout)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points) in;
layout (invocations = 1) in;
layout (points, max_vertices = 1) out;
void main()
{
})";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, TooLargeInvocations)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points, invocations = 9989899) in;
layout (points, max_vertices = 1) out;
void main()
{
})";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, InvocationsDeclaredWithInputPrimitives)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points, invocations = 3) in;
layout (points, max_vertices = 1) out;
void main()
{
})";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, InvocationsBeforeInputPrimitives)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (invocations = 3, points) in;
layout (points, max_vertices = 1) out;
void main()
{
})";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, InvocationsInIndividualLayout)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points) in;
layout (invocations = 3) in;
layout (points, max_vertices = 1) out;
void main()
{
})";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, DuplicatedInvocations)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points, invocations = 3) in;
layout (invocations = 3) in;
layout (points, max_vertices = 1) out;
void main()
{
})";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, RedeclareDifferentInvocations)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points, invocations = 3) in;
layout (invocations = 5) in;
layout (points, max_vertices = 1) out;
void main()
{
})";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, RedeclareDifferentInvocationsAfterInvocationEqualsOne)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points, invocations = 1) in;
layout (invocations = 5) in;
layout (points, max_vertices = 1) out;
void main()
{
})";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, RedeclareDifferentInvocationsInOneLayout)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points, invocations = 3, invocations = 5) in;
layout (points, max_vertices = 1) out;
void main()
{
})";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, DeclareInvocationsInOutLayout)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points) in;
layout (points, invocations = 3, max_vertices = 1) out;
void main()
{
})";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, DeclareInvocationsInLayoutNoQualifier)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points) in;
layout (invocations = 3);
layout (points, max_vertices = 1) out;
void main()
{
})";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, DeclareOutputPrimitiveBeforeInputPrimitiveDeclare)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points, max_vertices = 1) out;
layout (points) in;
void main()
{
})";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, DeclareMaxVerticesBeforeOutputPrimitive)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points) in;
layout (max_vertices = 1, points) out;
void main()
{
})";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, NoOutputPrimitives)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points) in;
layout (max_vertices = 1) out;
void main()
{
})";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, ValidateOutputPrimitives)
{
const std::string outputPrimitives[] = {"line_strip", "triangle_strip"};
for (const std::string &outPrimitive : outputPrimitives)
{
if (!compileGeometryShader(kInputLayout,
GetGeometryShaderLayout("out", outPrimitive, -1, 6)))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
if (compileGeometryShader(GetGeometryShaderLayout("in", outPrimitive, -1, -1),
kOutputLayout))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
}
TEST_F(GeometryShaderTest, RedeclareOutputPrimitives)
{
const std::array<std::string, 3> outPrimitives = {{"points", "line_strip", "triangle_strip"}};
for (GLuint i = 0; i < outPrimitives.size(); i++)
{
constexpr int maxVertices = 1;
const std::string &outputLayoutStr1 =
GetGeometryShaderLayout("out", outPrimitives[i], -1, maxVertices);
const std::string &outputLayoutStr2 =
GetGeometryShaderLayout("out", outPrimitives[i], -1, -1);
if (!compileGeometryShader(kInputLayout, outputLayoutStr1, outputLayoutStr2, ""))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
for (GLuint j = i + 1; j < outPrimitives.size(); j++)
{
const std::string &outputLayoutStr3 =
GetGeometryShaderLayout("out", outPrimitives[j], -1, -1);
if (compileGeometryShader(kInputLayout, outputLayoutStr1, outputLayoutStr3, ""))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
}
}
TEST_F(GeometryShaderTest, RedeclareDifferentOutputPrimitivesInOneLayout)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points) in;
layout (points, max_vertices = 3, line_strip) out;
void main()
{
})";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, NoOutLayouts)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points) in;
void main()
{
})";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, NoMaxVertices)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points) in;
layout (points) out;
void main()
{
})";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, NegativeMaxVertices)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points) in;
layout (points, max_vertices = -1) out;
void main()
{
})";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, ZeroMaxVertices)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points) in;
layout (points, max_vertices = 0) out;
void main()
{
})";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, TooLargeMaxVertices)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points) in;
layout (points, max_vertices = 257) out;
void main()
{
})";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, MaxVerticesInIndividualLayout)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points) in;
layout (points) out;
layout (max_vertices = 1) out;
void main()
{
})";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, DuplicatedMaxVertices)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points) in;
layout (points, max_vertices = 1) out;
layout (max_vertices = 1) out;
void main()
{
})";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, RedeclareDifferentMaxVertices)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points) in;
layout (points, max_vertices = 1) out;
layout (max_vertices = 2) out;
void main()
{
})";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, RedeclareDifferentMaxVerticesInOneLayout)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points) in;
layout (points, max_vertices = 2, max_vertices = 1) out;
void main()
{
})";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, InvalidLocation)
{
const std::string &shaderString1 =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points, location = 1) in;
layout (points, max_vertices = 2) out;
void main()
{
})";
const std::string &shaderString2 =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points) in;
layout (invocations = 2, location = 1) in;
layout (points, max_vertices = 2) out;
void main()
{
})";
const std::string &shaderString3 =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points) in;
layout (points, location = 3, max_vertices = 2) out;
void main()
{
})";
const std::string &shaderString4 =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points) in;
layout (points) out;
layout (max_vertices = 2, location = 3) out;
void main()
{
})";
if (compile(shaderString1) || compile(shaderString2) || compile(shaderString3) ||
compile(shaderString4))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, InvalidLayoutQualifiers)
{
const std::string &shaderString1 =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points, abc) in;
layout (points, max_vertices = 2) out;
void main()
{
})";
const std::string &shaderString2 =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points) in;
layout (points, abc, max_vertices = 2) out;
void main()
{
})";
const std::string &shaderString3 =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points, xyz = 2) in;
layout (points, max_vertices = 2) out;
void main()
{
})";
const std::string &shaderString4 =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points) in;
layout (points) out;
layout (max_vertices = 2, xyz = 3) out;
void main()
{
})";
if (compile(shaderString1) || compile(shaderString2) || compile(shaderString3) ||
compile(shaderString4))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, IndexGLInByConstantInteger)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points) in;
layout (points, max_vertices = 2) out;
void main()
{
vec4 position;
position = gl_in[0].gl_Position;
})";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, IndexGLInByVariable)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (lines) in;
layout (points, max_vertices = 2) out;
void main()
{
vec4 position;
for (int i = 0; i < 2; i++)
{
position = gl_in[i].gl_Position;
}
})";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, IndexGLInWithoutInputPrimitive)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points, max_vertices = 2) out;
void main()
{
vec4 position = gl_in[0].gl_Position;
})";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, UseGLInLengthWithoutInputPrimitive)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points, max_vertices = 2) out;
void main()
{
int length = gl_in.length();
})";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, UseGLInLengthWithInputPrimitive)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points) in;
layout (points, max_vertices = 2) out;
void main()
{
gl_Position = vec4(gl_in.length());
EmitVertex();
})";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, AssignValueToGLIn)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points) in;
layout (points, max_vertices = 2) out;
void main()
{
gl_in[0].gl_Position = vec4(0, 0, 0, 1);
})";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, BuiltInVariables)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points, invocations = 2) in;
layout (points, max_vertices = 2) out;
void main()
{
gl_Position = gl_in[gl_InvocationID].gl_Position;
int invocation = gl_InvocationID;
gl_Layer = invocation;
int primitiveIn = gl_PrimitiveIDIn;
gl_PrimitiveID = primitiveIn;
})";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, AssignValueToGLPrimitiveIn)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points, invocations = 2) in;
layout (points, max_vertices = 2) out;
void main()
{
gl_PrimitiveIDIn = 1;
})";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, AssignValueToGLInvocations)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points, invocations = 2) in;
layout (points, max_vertices = 2) out;
void main()
{
gl_InvocationID = 1;
})";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, GeometryShaderBuiltInFunctions)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points) in;
layout (points, max_vertices = 2) out;
void main()
{
gl_Position = gl_in[0].gl_Position;
EmitVertex();
EndPrimitive();
})";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, GeometryShaderBuiltInFunctionsWithoutExtension)
{
const std::string &shaderString1 =
R"(#version 310 es
void main()
{
EmitVertex();
})";
const std::string &shaderString2 =
R"(#version 310 es
void main()
{
EndPrimitive();
})";
if (compile(shaderString1) || compile(shaderString2))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, GeometryShaderBuiltInConstants)
{
const std::string &kShaderHeader =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points) in;
layout (points, max_vertices = 2) out;
void main()
{
gl_Position.x = float()";
const std::array<std::string, 9> kGeometryShaderBuiltinConstants = {{
"gl_MaxGeometryInputComponents",
"gl_MaxGeometryOutputComponents",
"gl_MaxGeometryImageUniforms",
"gl_MaxGeometryTextureImageUnits",
"gl_MaxGeometryOutputVertices",
"gl_MaxGeometryTotalOutputComponents",
"gl_MaxGeometryUniformComponents",
"gl_MaxGeometryAtomicCounters",
"gl_MaxGeometryAtomicCounterBuffers",
}};
const std::string &kShaderTail =
R"();
EmitVertex();
})";
for (const std::string &kGSBuiltinConstant : kGeometryShaderBuiltinConstants)
{
std::ostringstream ostream;
ostream << kShaderHeader << kGSBuiltinConstant << kShaderTail;
if (!compile(ostream.str()))
{
FAIL() << "Shader compilation failed, expecting success: \n" << mInfoLog;
}
}
}
TEST_F(GeometryShaderTest, GeometryShaderBuiltInConstantsWithoutExtension)
{
const std::string &kShaderHeader =
"#version 310 es\n"
"void main()\n"
"{\n"
" int val = ";
const std::array<std::string, 9> kGeometryShaderBuiltinConstants = {{
"gl_MaxGeometryInputComponents",
"gl_MaxGeometryOutputComponents",
"gl_MaxGeometryImageUniforms",
"gl_MaxGeometryTextureImageUnits",
"gl_MaxGeometryOutputVertices",
"gl_MaxGeometryTotalOutputComponents",
"gl_MaxGeometryUniformComponents",
"gl_MaxGeometryAtomicCounters",
"gl_MaxGeometryAtomicCounterBuffers",
}};
const std::string &kShaderTail =
";\n"
"}\n";
for (const std::string &kGSBuiltinConstant : kGeometryShaderBuiltinConstants)
{
std::ostringstream ostream;
ostream << kShaderHeader << kGSBuiltinConstant << kShaderTail;
if (compile(ostream.str()))
{
FAIL() << "Shader compilation succeeded, expecting failure: \n" << mInfoLog;
}
}
}
TEST_F(GeometryShaderTest, NonArrayInput)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points) in;
layout (points, max_vertices = 1) out;
in vec4 texcoord;
void main()
{
})";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, DeclareUnsizedInputBeforeInputPrimitive)
{
const std::string &shaderString1 =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
in vec4 texcoord[];
layout (points) in;
layout (points, max_vertices = 1) out;
void main()
{
vec4 coord = texcoord[0];
int length = texcoord.length();
})";
const std::string &shaderString2 =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
in vec4 texcoord1[1];
in vec4 texcoord2[];
layout (points) in;
layout (points, max_vertices = 1) out;
void main()
{
vec4 coord = texcoord2[0];
int length = texcoord2.length();
})";
if (!compile(shaderString1) || !compile(shaderString2))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, DeclareUnsizedInputWithoutInputPrimitive)
{
const std::string &shaderString1 =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points, max_vertices = 1) out;
in vec4 texcoord[];
void main()
{
})";
const std::string &shaderString2 =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points, max_vertices = 1) out;
in vec4 texcoord1[1];
in vec4 texcoord2[];
void main()
{
})";
if (compile(shaderString1) || compile(shaderString2))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, IndexingUnsizedInputDeclaredAfterInputPrimitive)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points) in;
layout (points, max_vertices = 1) out;
in vec4 texcoord[], texcoord2[];
in vec4[] texcoord3, texcoord4;
void main()
{
gl_Position = texcoord[0] + texcoord2[0] + texcoord3[0] + texcoord4[0];
EmitVertex();
})";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, CallingLengthOnUnsizedInputDeclaredAfterInputPrimitive)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points) in;
layout (points, max_vertices = 1) out;
in vec4 texcoord[];
void main()
{
gl_Position = vec4(texcoord.length());
EmitVertex();
})";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, AssignValueToInput)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points) in;
layout (points, max_vertices = 1) out;
in vec4 texcoord[];
void main()
{
texcoord[0] = vec4(1.0, 0.0, 0.0, 1.0);
})";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, InputWithLocations)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (triangles) in;
layout (points, max_vertices = 1) out;
layout (location = 0) in vec4 texcoord1[];
layout (location = 1) in vec4 texcoord2[];
void main()
{
int index = 0;
vec4 coord1 = texcoord1[0];
vec4 coord2 = texcoord2[index];
gl_Position = coord1 + coord2;
})";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, InputWithSizeBeforeInputPrimitive)
{
for (auto &primitiveAndArraySize : kInputPrimitivesAndInputArraySizeMap)
{
const std::string &inputLayoutStr =
GetGeometryShaderLayout("in", primitiveAndArraySize.first, -1, -1);
const int inputSize = primitiveAndArraySize.second;
const std::string &inputDeclaration1 = GetInputDeclaration("vec4 input1", inputSize);
if (!compileGeometryShader(inputDeclaration1, "", inputLayoutStr, kOutputLayout))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
const std::string &inputDeclaration2 = GetInputDeclaration("vec4 input2", inputSize + 1);
if (compileGeometryShader(inputDeclaration2, "", inputLayoutStr, kOutputLayout) ||
compileGeometryShader(inputDeclaration1, inputDeclaration2, inputLayoutStr,
kOutputLayout))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
}
TEST_F(GeometryShaderTest, InputWithSizeAfterInputPrimitive)
{
for (auto &primitiveAndArraySize : kInputPrimitivesAndInputArraySizeMap)
{
const std::string &inputLayoutStr =
GetGeometryShaderLayout("in", primitiveAndArraySize.first, -1, -1);
const int inputSize = primitiveAndArraySize.second;
const std::string &inputDeclaration1 = GetInputDeclaration("vec4 input1", inputSize);
if (!compileGeometryShader(inputLayoutStr, kOutputLayout, inputDeclaration1, ""))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
const std::string &inputDeclaration2 = GetInputDeclaration("vec4 input2", inputSize + 1);
if (compileGeometryShader(inputLayoutStr, kOutputLayout, inputDeclaration2, ""))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
}
TEST_F(GeometryShaderTest, NonArrayOutputs)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points) in;
layout (points, max_vertices = 1) out;
out vec4 color;
void main()
{
})";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, OutputsWithLocation)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (triangles) in;
layout (points, max_vertices = 1) out;
layout (location = 0) out vec4 color1;
layout (location = 1) out vec4 color2;
void main()
{
color1 = vec4(0.0, 1.0, 0.0, 1.0);
color2 = vec4(1.0, 0.0, 0.0, 1.0);
})";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, SizedArrayOutputs)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (triangles) in;
layout (points, max_vertices = 1) out;
out vec4 color[2];
void main()
{
color[0] = vec4(0.0, 1.0, 0.0, 1.0);
color[1] = vec4(1.0, 0.0, 0.0, 1.0);
})";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, UnsizedArrayOutputs)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (triangles) in;
layout (points, max_vertices = 1) out;
out vec4 color[];
void main()
{
})";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, InputWithInterpolationQualifiers)
{
for (const std::string &qualifier : kInterpolationQualifiers)
{
std::ostringstream stream;
stream << kHeader << kInputLayout << kOutputLayout << qualifier << " in vec4 texcoord[];\n"
<< kEmptyBody;
if (!compile(stream.str()))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
}
TEST_F(GeometryShaderTest, OutputWithInterpolationQualifiers)
{
for (const std::string &qualifier : kInterpolationQualifiers)
{
std::ostringstream stream;
stream << kHeader << kInputLayout << kOutputLayout << qualifier << " out vec4 color;\n"
<< kEmptyBody;
if (!compile(stream.str()))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
}
TEST_F(GeometryShaderTest, InvariantOutput)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points) in;
layout (points, max_vertices = 2) out;
invariant out vec4 gs_output;
void main()
{
gl_Position = gl_in[0].gl_Position;
})";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderOutputCodeTest, ValidateGLInMembersInOutputShaderString)
{
const std::string &shaderString1 =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (lines) in;
layout (points, max_vertices = 2) out;
void main()
{
vec4 position;
for (int i = 0; i < 2; i++)
{
position = gl_in[i].gl_Position;
}
})";
compile(shaderString1);
EXPECT_TRUE(foundInESSLCode("].gl_Position"));
const std::string &shaderString2 =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points) in;
layout (points, max_vertices = 2) out;
void main()
{
vec4 position;
position = gl_in[0].gl_Position;
})";
compile(shaderString2);
EXPECT_TRUE(foundInESSLCode("].gl_Position"));
}
TEST_F(GeometryShaderTest, StructArrayInput)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points) in;
layout (points, max_vertices = 2) out;
struct S
{
float value1;
vec4 value2;
};
in S gs_input[];
out S gs_output;
void main()
{
gs_output = gs_input[0];
})";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
TEST_F(GeometryShaderTest, StructArrayOutput)
{
const std::string &shaderString =
R"(#version 310 es
#extension GL_EXT_geometry_shader : require
layout (points) in;
layout (points, max_vertices = 2) out;
struct S
{
float value1;
vec4 value2;
};
out S gs_output[1];
void main()
{
gs_output[0].value1 = 1.0;
gs_output[0].value2 = vec4(1.0, 0.0, 0.0, 1.0);
})";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}