Path: blob/main_old/src/tests/compiler_tests/GeometryShader_test.cpp
1693 views
//1// Copyright 2017 The ANGLE Project Authors. All rights reserved.2// Use of this source code is governed by a BSD-style license that can be3// found in the LICENSE file.4//5// GeometryShader_test.cpp:6// tests for compiling a Geometry Shader7//89#include "GLSLANG/ShaderLang.h"10#include "angle_gl.h"11#include "compiler/translator/BaseTypes.h"12#include "gtest/gtest.h"13#include "tests/test_utils/ShaderCompileTreeTest.h"14#include "tests/test_utils/compiler_test.h"1516using namespace sh;1718class GeometryShaderTest : public ShaderCompileTreeTest19{20public:21GeometryShaderTest() {}2223protected:24void initResources(ShBuiltInResources *resources) override25{26resources->EXT_geometry_shader = 1;27}2829::GLenum getShaderType() const override { return GL_GEOMETRY_SHADER_EXT; }3031ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; }3233bool compileGeometryShader(const std::string &statement1, const std::string &statement2)34{35std::ostringstream sstream;36sstream << kHeader << statement1 << statement2 << kEmptyBody;37return compile(sstream.str());38}3940bool compileGeometryShader(const std::string &statement1,41const std::string &statement2,42const std::string &statement3,43const std::string &statement4)44{45std::ostringstream sstream;46sstream << kHeader << statement1 << statement2 << statement3 << statement4 << kEmptyBody;47return compile(sstream.str());48}4950static std::string GetGeometryShaderLayout(const std::string &layoutType,51const std::string &primitive,52int invocations,53int maxVertices)54{55std::ostringstream sstream;5657sstream << "layout (";58if (!primitive.empty())59{60sstream << primitive;61}62if (invocations > 0)63{64sstream << ", invocations = " << invocations;65}66if (maxVertices >= 0)67{68sstream << ", max_vertices = " << maxVertices;69}70sstream << ") " << layoutType << ";" << std::endl;7172return sstream.str();73}7475static std::string GetInputDeclaration(const std::string &var, int size)76{77std::ostringstream sstream;7879sstream << "in ";80if (size < 0)81{82sstream << var << "[];\n";83}84else85{86sstream << var << "[" << size << "];\n";87}8889return sstream.str();90}9192const std::string kVersion = "#version 310 es\n";93const std::string kHeader =94"#version 310 es\n"95"#extension GL_EXT_geometry_shader : require\n";96const std::string kInputLayout = "layout (points) in;\n";97const std::string kOutputLayout = "layout (points, max_vertices = 1) out;\n";9899const std::array<std::string, 4> kInterpolationQualifiers = {{"flat", "smooth", "centroid"}};100const std::map<std::string, int> kInputPrimitivesAndInputArraySizeMap = {101{"points", 1},102{"lines", 2},103{"lines_adjacency", 4},104{"triangles", 3},105{"triangles_adjacency", 6}};106107const std::string kEmptyBody =108"void main()\n"109"{\n"110"}\n";111};112113class GeometryShaderOutputCodeTest : public MatchOutputCodeTest114{115public:116GeometryShaderOutputCodeTest()117: MatchOutputCodeTest(GL_GEOMETRY_SHADER_EXT, SH_OBJECT_CODE, SH_ESSL_OUTPUT)118{119getResources()->EXT_geometry_shader = 1;120}121};122123// Geometry Shaders are not supported in GLSL ES shaders version lower than 310.124TEST_F(GeometryShaderTest, Version300)125{126const std::string &shaderString =127R"(#version 300 es128void main()129{130})";131132if (compile(shaderString))133{134FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;135}136}137138// Geometry Shaders are not supported in GLSL ES shaders version 310 without extension139// EXT_geometry_shader enabled.140TEST_F(GeometryShaderTest, Version310WithoutExtension)141{142const std::string &shaderString =143R"(#version 310 es144void main()145{146})";147148if (compile(shaderString))149{150FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;151}152}153154// Geometry Shaders are not supported in GLSL ES shaders version 310 with extension155// EXT_geometry_shader disabled.156TEST_F(GeometryShaderTest, Version310ExtensionDisabled)157{158const std::string &shaderString =159R"(#version 310 es160#extension GL_EXT_geometry_shader : disable161void main()162{163})";164165if (compile(shaderString))166{167FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;168}169}170171// Geometry Shaders are supported in GLSL ES shaders version 310 with EXT_geometry_shader enabled.172TEST_F(GeometryShaderTest, Version310WithEXTExtension)173{174const std::string &shaderString =175R"(#version 310 es176#extension GL_EXT_geometry_shader : require177layout(points) in;178layout(points, max_vertices = 1) out;179void main()180{181})";182183if (!compile(shaderString))184{185FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;186}187}188189// Missing the declaration of input primitive in a geometry shader should be a link error instead of190// a compile error.191TEST_F(GeometryShaderTest, NoInputPrimitives)192{193const std::string &shaderString =194R"(#version 310 es195#extension GL_EXT_geometry_shader : require196layout(points, max_vertices = 1) out;197void main()198{199})";200201if (!compile(shaderString))202{203FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;204}205}206207// Geometry Shaders can only support 5 kinds of input primitives, which cannot be used as output208// primitives except 'points'.209// Skip testing "points" as it can be used as both input and output primitives.210TEST_F(GeometryShaderTest, ValidInputPrimitives)211{212const std::array<std::string, 4> kInputPrimitives = {213{"lines", "lines_adjacency", "triangles", "triangles_adjacency"}};214215for (const std::string &inputPrimitive : kInputPrimitives)216{217if (!compileGeometryShader(GetGeometryShaderLayout("in", inputPrimitive, -1, -1),218kOutputLayout))219{220FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;221}222if (compileGeometryShader(kInputLayout,223GetGeometryShaderLayout("out", inputPrimitive, -1, 6)))224{225FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;226}227}228}229230// Geometry Shaders allow duplicated declaration of input primitive, but all of them must be same.231TEST_F(GeometryShaderTest, RedeclareInputPrimitives)232{233const std::array<std::string, 5> kInputPrimitives = {234{"points", "lines", "lines_adjacency", "triangles", "triangles_adjacency"}};235236for (GLuint i = 0; i < kInputPrimitives.size(); ++i)237{238const std::string &inputLayoutStr1 =239GetGeometryShaderLayout("in", kInputPrimitives[i], -1, -1);240if (!compileGeometryShader(inputLayoutStr1, inputLayoutStr1, kOutputLayout, ""))241{242FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;243}244245for (GLuint j = i + 1; j < kInputPrimitives.size(); ++j)246{247const std::string &inputLayoutStr2 =248GetGeometryShaderLayout("in", kInputPrimitives[j], -1, -1);249if (compileGeometryShader(inputLayoutStr1, inputLayoutStr2, kOutputLayout, ""))250{251FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;252}253}254}255}256257// Geometry Shaders don't allow declaring different input primitives in one layout.258TEST_F(GeometryShaderTest, DeclareDifferentInputPrimitivesInOneLayout)259{260const std::string &shaderString =261R"(#version 310 es262#extension GL_EXT_geometry_shader : require263layout (points, triangles) in;264layout (points, max_vertices = 1) out;265void main()266{267})";268269if (compile(shaderString))270{271FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;272}273}274275// Geometry Shaders don't allow 'invocations' < 1.276TEST_F(GeometryShaderTest, InvocationsLessThanOne)277{278const std::string &shaderString =279R"(#version 310 es280#extension GL_EXT_geometry_shader : require281layout (points, invocations = 0) in;282layout (points, max_vertices = 1) out;283void main()284{285})";286287if (compile(shaderString))288{289FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;290}291}292293// Geometry Shaders allow declaring 'invocations' == 1 together with input primitive declaration in294// one layout.295TEST_F(GeometryShaderTest, InvocationsEqualsOne)296{297const std::string &shaderString =298R"(#version 310 es299#extension GL_EXT_geometry_shader : require300layout (points, invocations = 1) in;301layout (points, max_vertices = 1) out;302void main()303{304})";305306if (!compile(shaderString))307{308FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;309}310}311312// Geometry Shaders allow declaring 'invocations' == 1 in an individual layout.313TEST_F(GeometryShaderTest, InvocationsEqualsOneInSeparatedLayout)314{315const std::string &shaderString =316R"(#version 310 es317#extension GL_EXT_geometry_shader : require318layout (points) in;319layout (invocations = 1) in;320layout (points, max_vertices = 1) out;321void main()322{323})";324325if (!compile(shaderString))326{327FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;328}329}330331// Geometry Shaders don't allow 'invocations' larger than the implementation-dependent maximum value332// (32 in this test).333TEST_F(GeometryShaderTest, TooLargeInvocations)334{335const std::string &shaderString =336R"(#version 310 es337#extension GL_EXT_geometry_shader : require338layout (points, invocations = 9989899) in;339layout (points, max_vertices = 1) out;340void main()341{342})";343344if (compile(shaderString))345{346FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;347}348}349350// Geometry Shaders allow 'invocations' declared together with input primitives in one layout.351TEST_F(GeometryShaderTest, InvocationsDeclaredWithInputPrimitives)352{353const std::string &shaderString =354R"(#version 310 es355#extension GL_EXT_geometry_shader : require356layout (points, invocations = 3) in;357layout (points, max_vertices = 1) out;358void main()359{360})";361362if (!compile(shaderString))363{364FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;365}366}367368// Geometry Shaders allow 'invocations' declared before input primitives in one input layout.369TEST_F(GeometryShaderTest, InvocationsBeforeInputPrimitives)370{371const std::string &shaderString =372R"(#version 310 es373#extension GL_EXT_geometry_shader : require374layout (invocations = 3, points) in;375layout (points, max_vertices = 1) out;376void main()377{378})";379380if (!compile(shaderString))381{382FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;383}384}385386// Geometry Shaders allow 'invocations' declared in an individual input layout.387TEST_F(GeometryShaderTest, InvocationsInIndividualLayout)388{389const std::string &shaderString =390R"(#version 310 es391#extension GL_EXT_geometry_shader : require392layout (points) in;393layout (invocations = 3) in;394layout (points, max_vertices = 1) out;395void main()396{397})";398399if (!compile(shaderString))400{401FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;402}403}404405// Geometry Shaders allow duplicated 'invocations' declarations.406TEST_F(GeometryShaderTest, DuplicatedInvocations)407{408const std::string &shaderString =409R"(#version 310 es410#extension GL_EXT_geometry_shader : require411layout (points, invocations = 3) in;412layout (invocations = 3) in;413layout (points, max_vertices = 1) out;414void main()415{416})";417418if (!compile(shaderString))419{420FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;421}422}423424// Geometry Shaders don't allow multiple different 'invocations' declarations in different425// layouts.426TEST_F(GeometryShaderTest, RedeclareDifferentInvocations)427{428const std::string &shaderString =429R"(#version 310 es430#extension GL_EXT_geometry_shader : require431layout (points, invocations = 3) in;432layout (invocations = 5) in;433layout (points, max_vertices = 1) out;434void main()435{436})";437438if (compile(shaderString))439{440FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;441}442}443444// Geometry Shaders don't allow multiple different 'invocations' declarations in different445// layouts.446TEST_F(GeometryShaderTest, RedeclareDifferentInvocationsAfterInvocationEqualsOne)447{448const std::string &shaderString =449R"(#version 310 es450#extension GL_EXT_geometry_shader : require451layout (points, invocations = 1) in;452layout (invocations = 5) in;453layout (points, max_vertices = 1) out;454void main()455{456})";457458if (compile(shaderString))459{460FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;461}462}463464// Geometry Shaders don't allow multiple different 'invocations' declarations in one layout.465TEST_F(GeometryShaderTest, RedeclareDifferentInvocationsInOneLayout)466{467const std::string &shaderString =468R"(#version 310 es469#extension GL_EXT_geometry_shader : require470layout (points, invocations = 3, invocations = 5) in;471layout (points, max_vertices = 1) out;472void main()473{474})";475476if (compile(shaderString))477{478FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;479}480}481482// Geometry Shaders don't allow 'invocations' in out layouts.483TEST_F(GeometryShaderTest, DeclareInvocationsInOutLayout)484{485const std::string &shaderString =486R"(#version 310 es487#extension GL_EXT_geometry_shader : require488layout (points) in;489layout (points, invocations = 3, max_vertices = 1) out;490void main()491{492})";493494if (compile(shaderString))495{496FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;497}498}499500// Geometry Shaders don't allow 'invocations' in layouts without 'in' qualifier.501TEST_F(GeometryShaderTest, DeclareInvocationsInLayoutNoQualifier)502{503const std::string &shaderString =504R"(#version 310 es505#extension GL_EXT_geometry_shader : require506layout (points) in;507layout (invocations = 3);508layout (points, max_vertices = 1) out;509void main()510{511})";512513if (compile(shaderString))514{515FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;516}517}518519// Geometry Shaders allow declaring output primitive before input primitive declaration.520TEST_F(GeometryShaderTest, DeclareOutputPrimitiveBeforeInputPrimitiveDeclare)521{522const std::string &shaderString =523R"(#version 310 es524#extension GL_EXT_geometry_shader : require525layout (points, max_vertices = 1) out;526layout (points) in;527void main()528{529})";530531if (!compile(shaderString))532{533FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;534}535}536537// Geometry Shaders allow declaring 'max_vertices' before output primitive in one output layout.538TEST_F(GeometryShaderTest, DeclareMaxVerticesBeforeOutputPrimitive)539{540const std::string &shaderString =541R"(#version 310 es542#extension GL_EXT_geometry_shader : require543layout (points) in;544layout (max_vertices = 1, points) out;545void main()546{547})";548549if (!compile(shaderString))550{551FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;552}553}554555// Missing the declaration of output primitive should be a link error instead of a compile error in556// a geometry shader.557TEST_F(GeometryShaderTest, NoOutputPrimitives)558{559const std::string &shaderString =560R"(#version 310 es561#extension GL_EXT_geometry_shader : require562layout (points) in;563layout (max_vertices = 1) out;564void main()565{566})";567568if (!compile(shaderString))569{570FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;571}572}573574// Geometry Shaders can only support 3 kinds of output primitives, which cannot be used as input575// primitives except 'points'.576// Skip testing "points" as it can be used as both input and output primitives.577TEST_F(GeometryShaderTest, ValidateOutputPrimitives)578{579const std::string outputPrimitives[] = {"line_strip", "triangle_strip"};580581for (const std::string &outPrimitive : outputPrimitives)582{583if (!compileGeometryShader(kInputLayout,584GetGeometryShaderLayout("out", outPrimitive, -1, 6)))585{586FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;587}588589if (compileGeometryShader(GetGeometryShaderLayout("in", outPrimitive, -1, -1),590kOutputLayout))591{592FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;593}594}595}596597// Geometry Shaders allow duplicated output primitive declarations, but all of them must be same.598TEST_F(GeometryShaderTest, RedeclareOutputPrimitives)599{600const std::array<std::string, 3> outPrimitives = {{"points", "line_strip", "triangle_strip"}};601602for (GLuint i = 0; i < outPrimitives.size(); i++)603{604constexpr int maxVertices = 1;605const std::string &outputLayoutStr1 =606GetGeometryShaderLayout("out", outPrimitives[i], -1, maxVertices);607const std::string &outputLayoutStr2 =608GetGeometryShaderLayout("out", outPrimitives[i], -1, -1);609if (!compileGeometryShader(kInputLayout, outputLayoutStr1, outputLayoutStr2, ""))610{611FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;612}613for (GLuint j = i + 1; j < outPrimitives.size(); j++)614{615const std::string &outputLayoutStr3 =616GetGeometryShaderLayout("out", outPrimitives[j], -1, -1);617if (compileGeometryShader(kInputLayout, outputLayoutStr1, outputLayoutStr3, ""))618{619FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;620}621}622}623}624625// Geometry Shaders don't allow declaring different output primitives in one layout.626TEST_F(GeometryShaderTest, RedeclareDifferentOutputPrimitivesInOneLayout)627{628const std::string &shaderString =629R"(#version 310 es630#extension GL_EXT_geometry_shader : require631layout (points) in;632layout (points, max_vertices = 3, line_strip) out;633void main()634{635})";636637if (compile(shaderString))638{639FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;640}641}642643// Missing the declarations of output primitives and 'max_vertices' in a geometry shader should644// be a link error instead of a compile error.645TEST_F(GeometryShaderTest, NoOutLayouts)646{647const std::string &shaderString =648R"(#version 310 es649#extension GL_EXT_geometry_shader : require650layout (points) in;651void main()652{653})";654655if (!compile(shaderString))656{657FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;658}659}660661// Missing the declarations of 'max_vertices' in a geometry shader should be a link error662// instead of a compile error.663TEST_F(GeometryShaderTest, NoMaxVertices)664{665const std::string &shaderString =666R"(#version 310 es667#extension GL_EXT_geometry_shader : require668layout (points) in;669layout (points) out;670void main()671{672})";673674if (!compile(shaderString))675{676FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;677}678}679680// Geometry Shaders cannot declare a negative 'max_vertices'.681TEST_F(GeometryShaderTest, NegativeMaxVertices)682{683const std::string &shaderString =684R"(#version 310 es685#extension GL_EXT_geometry_shader : require686layout (points) in;687layout (points, max_vertices = -1) out;688void main()689{690})";691692if (compile(shaderString))693{694FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;695}696}697698// Geometry Shaders allow max_vertices == 0.699TEST_F(GeometryShaderTest, ZeroMaxVertices)700{701const std::string &shaderString =702R"(#version 310 es703#extension GL_EXT_geometry_shader : require704layout (points) in;705layout (points, max_vertices = 0) out;706void main()707{708})";709710if (!compile(shaderString))711{712FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;713}714}715716// Geometry Shaders cannot declare a 'max_vertices' that is greater than717// MAX_GEOMETRY_OUTPUT_VERTICES_EXT (256 in this test).718TEST_F(GeometryShaderTest, TooLargeMaxVertices)719{720const std::string &shaderString =721R"(#version 310 es722#extension GL_EXT_geometry_shader : require723layout (points) in;724layout (points, max_vertices = 257) out;725void main()726{727})";728729if (compile(shaderString))730{731FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;732}733}734735// Geometry Shaders can declare 'max_vertices' in an individual out layout.736TEST_F(GeometryShaderTest, MaxVerticesInIndividualLayout)737{738const std::string &shaderString =739R"(#version 310 es740#extension GL_EXT_geometry_shader : require741layout (points) in;742layout (points) out;743layout (max_vertices = 1) out;744void main()745{746})";747748if (!compile(shaderString))749{750FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;751}752}753754// Geometry Shaders allow duplicated 'max_vertices' declarations.755TEST_F(GeometryShaderTest, DuplicatedMaxVertices)756{757const std::string &shaderString =758R"(#version 310 es759#extension GL_EXT_geometry_shader : require760layout (points) in;761layout (points, max_vertices = 1) out;762layout (max_vertices = 1) out;763void main()764{765})";766767if (!compile(shaderString))768{769FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;770}771}772773// Geometry Shaders don't allow declaring different 'max_vertices'.774TEST_F(GeometryShaderTest, RedeclareDifferentMaxVertices)775{776const std::string &shaderString =777R"(#version 310 es778#extension GL_EXT_geometry_shader : require779layout (points) in;780layout (points, max_vertices = 1) out;781layout (max_vertices = 2) out;782void main()783{784})";785786if (compile(shaderString))787{788FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;789}790}791792// Geometry Shaders don't allow declaring different 'max_vertices'.793TEST_F(GeometryShaderTest, RedeclareDifferentMaxVerticesInOneLayout)794{795const std::string &shaderString =796R"(#version 310 es797#extension GL_EXT_geometry_shader : require798layout (points) in;799layout (points, max_vertices = 2, max_vertices = 1) out;800void main()801{802})";803804if (compile(shaderString))805{806FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;807}808}809810// Geometry Shaders don't allow 'location' declared with input/output primitives in one layout.811TEST_F(GeometryShaderTest, InvalidLocation)812{813const std::string &shaderString1 =814R"(#version 310 es815#extension GL_EXT_geometry_shader : require816layout (points, location = 1) in;817layout (points, max_vertices = 2) out;818void main()819{820})";821822const std::string &shaderString2 =823R"(#version 310 es824#extension GL_EXT_geometry_shader : require825layout (points) in;826layout (invocations = 2, location = 1) in;827layout (points, max_vertices = 2) out;828void main()829{830})";831832const std::string &shaderString3 =833R"(#version 310 es834#extension GL_EXT_geometry_shader : require835layout (points) in;836layout (points, location = 3, max_vertices = 2) out;837void main()838{839})";840841const std::string &shaderString4 =842R"(#version 310 es843#extension GL_EXT_geometry_shader : require844layout (points) in;845layout (points) out;846layout (max_vertices = 2, location = 3) out;847void main()848{849})";850851if (compile(shaderString1) || compile(shaderString2) || compile(shaderString3) ||852compile(shaderString4))853{854FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;855}856}857858// Geometry Shaders don't allow invalid layout qualifier declarations.859TEST_F(GeometryShaderTest, InvalidLayoutQualifiers)860{861const std::string &shaderString1 =862R"(#version 310 es863#extension GL_EXT_geometry_shader : require864layout (points, abc) in;865layout (points, max_vertices = 2) out;866void main()867{868})";869870const std::string &shaderString2 =871R"(#version 310 es872#extension GL_EXT_geometry_shader : require873layout (points) in;874layout (points, abc, max_vertices = 2) out;875void main()876{877})";878879const std::string &shaderString3 =880R"(#version 310 es881#extension GL_EXT_geometry_shader : require882layout (points, xyz = 2) in;883layout (points, max_vertices = 2) out;884void main()885{886})";887888const std::string &shaderString4 =889R"(#version 310 es890#extension GL_EXT_geometry_shader : require891layout (points) in;892layout (points) out;893layout (max_vertices = 2, xyz = 3) out;894void main()895{896})";897898if (compile(shaderString1) || compile(shaderString2) || compile(shaderString3) ||899compile(shaderString4))900{901FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;902}903}904905// Verify that indexing an array with a constant integer on gl_in is legal.906TEST_F(GeometryShaderTest, IndexGLInByConstantInteger)907{908const std::string &shaderString =909R"(#version 310 es910#extension GL_EXT_geometry_shader : require911layout (points) in;912layout (points, max_vertices = 2) out;913void main()914{915vec4 position;916position = gl_in[0].gl_Position;917})";918919if (!compile(shaderString))920{921FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;922}923}924925// Verify that indexing an array with an integer variable on gl_in is legal.926TEST_F(GeometryShaderTest, IndexGLInByVariable)927{928const std::string &shaderString =929R"(#version 310 es930#extension GL_EXT_geometry_shader : require931layout (lines) in;932layout (points, max_vertices = 2) out;933void main()934{935vec4 position;936for (int i = 0; i < 2; i++)937{938position = gl_in[i].gl_Position;939}940})";941942if (!compile(shaderString))943{944FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;945}946}947948// Verify that indexing an array on gl_in without input primitive declaration causes a compile949// error.950TEST_F(GeometryShaderTest, IndexGLInWithoutInputPrimitive)951{952const std::string &shaderString =953R"(#version 310 es954#extension GL_EXT_geometry_shader : require955layout (points, max_vertices = 2) out;956void main()957{958vec4 position = gl_in[0].gl_Position;959})";960961if (compile(shaderString))962{963FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;964}965}966967// Verify that using gl_in.length() without input primitive declaration causes a compile error.968TEST_F(GeometryShaderTest, UseGLInLengthWithoutInputPrimitive)969{970const std::string &shaderString =971R"(#version 310 es972#extension GL_EXT_geometry_shader : require973layout (points, max_vertices = 2) out;974void main()975{976int length = gl_in.length();977})";978979if (compile(shaderString))980{981FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;982}983}984985// Verify that using gl_in.length() with input primitive declaration can compile.986TEST_F(GeometryShaderTest, UseGLInLengthWithInputPrimitive)987{988const std::string &shaderString =989R"(#version 310 es990#extension GL_EXT_geometry_shader : require991layout (points) in;992layout (points, max_vertices = 2) out;993void main()994{995gl_Position = vec4(gl_in.length());996EmitVertex();997})";998999if (!compile(shaderString))1000{1001FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;1002}1003}10041005// Verify that gl_in[].gl_Position cannot be l-value.1006TEST_F(GeometryShaderTest, AssignValueToGLIn)1007{1008const std::string &shaderString =1009R"(#version 310 es1010#extension GL_EXT_geometry_shader : require1011layout (points) in;1012layout (points, max_vertices = 2) out;1013void main()1014{1015gl_in[0].gl_Position = vec4(0, 0, 0, 1);1016})";1017if (compile(shaderString))1018{1019FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;1020}1021}10221023// Verify Geometry Shader supports all required built-in variables.1024TEST_F(GeometryShaderTest, BuiltInVariables)1025{1026const std::string &shaderString =1027R"(#version 310 es1028#extension GL_EXT_geometry_shader : require1029layout (points, invocations = 2) in;1030layout (points, max_vertices = 2) out;1031void main()1032{1033gl_Position = gl_in[gl_InvocationID].gl_Position;1034int invocation = gl_InvocationID;1035gl_Layer = invocation;1036int primitiveIn = gl_PrimitiveIDIn;1037gl_PrimitiveID = primitiveIn;1038})";1039if (!compile(shaderString))1040{1041FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;1042}1043}10441045// Verify that gl_PrimitiveIDIn cannot be l-value.1046TEST_F(GeometryShaderTest, AssignValueToGLPrimitiveIn)1047{1048const std::string &shaderString =1049R"(#version 310 es1050#extension GL_EXT_geometry_shader : require1051layout (points, invocations = 2) in;1052layout (points, max_vertices = 2) out;1053void main()1054{1055gl_PrimitiveIDIn = 1;1056})";1057if (compile(shaderString))1058{1059FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;1060}1061}10621063// Verify that gl_InvocationID cannot be l-value.1064TEST_F(GeometryShaderTest, AssignValueToGLInvocations)1065{1066const std::string &shaderString =1067R"(#version 310 es1068#extension GL_EXT_geometry_shader : require1069layout (points, invocations = 2) in;1070layout (points, max_vertices = 2) out;1071void main()1072{1073gl_InvocationID = 1;1074})";1075if (compile(shaderString))1076{1077FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;1078}1079}10801081// Verify that both EmitVertex() and EndPrimitive() are supported in Geometry Shader.1082TEST_F(GeometryShaderTest, GeometryShaderBuiltInFunctions)1083{1084const std::string &shaderString =1085R"(#version 310 es1086#extension GL_EXT_geometry_shader : require1087layout (points) in;1088layout (points, max_vertices = 2) out;1089void main()1090{1091gl_Position = gl_in[0].gl_Position;1092EmitVertex();1093EndPrimitive();1094})";10951096if (!compile(shaderString))1097{1098FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;1099}1100}11011102// Verify that using EmitVertex() or EndPrimitive() without GL_EXT_geometry_shader declared causes a1103// compile error.1104TEST_F(GeometryShaderTest, GeometryShaderBuiltInFunctionsWithoutExtension)1105{1106const std::string &shaderString1 =1107R"(#version 310 es1108void main()1109{1110EmitVertex();1111})";11121113const std::string &shaderString2 =1114R"(#version 310 es1115void main()1116{1117EndPrimitive();1118})";11191120if (compile(shaderString1) || compile(shaderString2))1121{1122FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;1123}1124}11251126// Verify that all required built-in constant values are supported in Geometry Shaders1127TEST_F(GeometryShaderTest, GeometryShaderBuiltInConstants)1128{1129const std::string &kShaderHeader =1130R"(#version 310 es1131#extension GL_EXT_geometry_shader : require1132layout (points) in;1133layout (points, max_vertices = 2) out;1134void main()1135{1136gl_Position.x = float()";11371138const std::array<std::string, 9> kGeometryShaderBuiltinConstants = {{1139"gl_MaxGeometryInputComponents",1140"gl_MaxGeometryOutputComponents",1141"gl_MaxGeometryImageUniforms",1142"gl_MaxGeometryTextureImageUnits",1143"gl_MaxGeometryOutputVertices",1144"gl_MaxGeometryTotalOutputComponents",1145"gl_MaxGeometryUniformComponents",1146"gl_MaxGeometryAtomicCounters",1147"gl_MaxGeometryAtomicCounterBuffers",1148}};11491150const std::string &kShaderTail =1151R"();1152EmitVertex();1153})";11541155for (const std::string &kGSBuiltinConstant : kGeometryShaderBuiltinConstants)1156{1157std::ostringstream ostream;1158ostream << kShaderHeader << kGSBuiltinConstant << kShaderTail;1159if (!compile(ostream.str()))1160{1161FAIL() << "Shader compilation failed, expecting success: \n" << mInfoLog;1162}1163}1164}11651166// Verify that using any Geometry Shader built-in constant values without GL_EXT_geometry_shader1167// declared causes a compile error.1168TEST_F(GeometryShaderTest, GeometryShaderBuiltInConstantsWithoutExtension)1169{1170const std::string &kShaderHeader =1171"#version 310 es\n"1172"void main()\n"1173"{\n"1174" int val = ";11751176const std::array<std::string, 9> kGeometryShaderBuiltinConstants = {{1177"gl_MaxGeometryInputComponents",1178"gl_MaxGeometryOutputComponents",1179"gl_MaxGeometryImageUniforms",1180"gl_MaxGeometryTextureImageUnits",1181"gl_MaxGeometryOutputVertices",1182"gl_MaxGeometryTotalOutputComponents",1183"gl_MaxGeometryUniformComponents",1184"gl_MaxGeometryAtomicCounters",1185"gl_MaxGeometryAtomicCounterBuffers",1186}};11871188const std::string &kShaderTail =1189";\n"1190"}\n";11911192for (const std::string &kGSBuiltinConstant : kGeometryShaderBuiltinConstants)1193{1194std::ostringstream ostream;1195ostream << kShaderHeader << kGSBuiltinConstant << kShaderTail;1196if (compile(ostream.str()))1197{1198FAIL() << "Shader compilation succeeded, expecting failure: \n" << mInfoLog;1199}1200}1201}12021203// Verify that Geometry Shaders cannot accept non-array inputs.1204TEST_F(GeometryShaderTest, NonArrayInput)1205{1206const std::string &shaderString =1207R"(#version 310 es1208#extension GL_EXT_geometry_shader : require1209layout (points) in;1210layout (points, max_vertices = 1) out;1211in vec4 texcoord;1212void main()1213{1214})";12151216if (compile(shaderString))1217{1218FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;1219}1220}12211222// Verify that it is a compile error to declare an unsized Geometry Shader input before a valid1223// input primitive declaration.1224TEST_F(GeometryShaderTest, DeclareUnsizedInputBeforeInputPrimitive)1225{1226const std::string &shaderString1 =1227R"(#version 310 es1228#extension GL_EXT_geometry_shader : require1229in vec4 texcoord[];1230layout (points) in;1231layout (points, max_vertices = 1) out;1232void main()1233{1234vec4 coord = texcoord[0];1235int length = texcoord.length();1236})";12371238const std::string &shaderString2 =1239R"(#version 310 es1240#extension GL_EXT_geometry_shader : require1241in vec4 texcoord1[1];1242in vec4 texcoord2[];1243layout (points) in;1244layout (points, max_vertices = 1) out;1245void main()1246{1247vec4 coord = texcoord2[0];1248int length = texcoord2.length();1249})";12501251if (compile(shaderString1) || compile(shaderString2))1252{1253FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;1254}1255}12561257// Verify that it is a compile error to declare an unsized Geometry Shader input without a valid1258// input primitive declaration.1259TEST_F(GeometryShaderTest, DeclareUnsizedInputWithoutInputPrimitive)1260{1261const std::string &shaderString1 =1262R"(#version 310 es1263#extension GL_EXT_geometry_shader : require1264layout (points, max_vertices = 1) out;1265in vec4 texcoord[];1266void main()1267{1268})";12691270const std::string &shaderString2 =1271R"(#version 310 es1272#extension GL_EXT_geometry_shader : require1273layout (points, max_vertices = 1) out;1274in vec4 texcoord1[1];1275in vec4 texcoord2[];1276void main()1277{1278})";12791280if (compile(shaderString1) || compile(shaderString2))1281{1282FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;1283}1284}12851286// Verify that indexing an unsized Geometry Shader input which is declared after a1287// valid input primitive declaration can compile.1288TEST_F(GeometryShaderTest, IndexingUnsizedInputDeclaredAfterInputPrimitive)1289{1290const std::string &shaderString =1291R"(#version 310 es1292#extension GL_EXT_geometry_shader : require1293layout (points) in;1294layout (points, max_vertices = 1) out;1295in vec4 texcoord[], texcoord2[];1296in vec4[] texcoord3, texcoord4;1297void main()1298{1299gl_Position = texcoord[0] + texcoord2[0] + texcoord3[0] + texcoord4[0];1300EmitVertex();1301})";13021303if (!compile(shaderString))1304{1305FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;1306}1307}13081309// Verify that calling length() function on an unsized Geometry Shader input which1310// is declared before a valid input primitive declaration can compile.1311TEST_F(GeometryShaderTest, CallingLengthOnUnsizedInputDeclaredAfterInputPrimitive)1312{1313const std::string &shaderString =1314R"(#version 310 es1315#extension GL_EXT_geometry_shader : require1316layout (points) in;1317layout (points, max_vertices = 1) out;1318in vec4 texcoord[];1319void main()1320{1321gl_Position = vec4(texcoord.length());1322EmitVertex();1323})";13241325if (!compile(shaderString))1326{1327FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;1328}1329}13301331// Verify that assigning a value to the input of a geometry shader causes a compile error.1332TEST_F(GeometryShaderTest, AssignValueToInput)1333{1334const std::string &shaderString =1335R"(#version 310 es1336#extension GL_EXT_geometry_shader : require1337layout (points) in;1338layout (points, max_vertices = 1) out;1339in vec4 texcoord[];1340void main()1341{1342texcoord[0] = vec4(1.0, 0.0, 0.0, 1.0);1343})";13441345if (compile(shaderString))1346{1347FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;1348}1349}13501351// Geometry Shaders allow inputs with location qualifier.1352TEST_F(GeometryShaderTest, InputWithLocations)1353{1354const std::string &shaderString =1355R"(#version 310 es1356#extension GL_EXT_geometry_shader : require1357layout (triangles) in;1358layout (points, max_vertices = 1) out;1359layout (location = 0) in vec4 texcoord1[];1360layout (location = 1) in vec4 texcoord2[];1361void main()1362{1363int index = 0;1364vec4 coord1 = texcoord1[0];1365vec4 coord2 = texcoord2[index];1366gl_Position = coord1 + coord2;1367})";13681369if (!compile(shaderString))1370{1371FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;1372}1373}13741375// Geometry Shaders allow inputs with explicit size declared before the declaration of the1376// input primitive, but they should have same size and match the declaration of the1377// following input primitive declarations.1378TEST_F(GeometryShaderTest, InputWithSizeBeforeInputPrimitive)1379{1380for (auto &primitiveAndArraySize : kInputPrimitivesAndInputArraySizeMap)1381{1382const std::string &inputLayoutStr =1383GetGeometryShaderLayout("in", primitiveAndArraySize.first, -1, -1);1384const int inputSize = primitiveAndArraySize.second;13851386const std::string &inputDeclaration1 = GetInputDeclaration("vec4 input1", inputSize);1387if (!compileGeometryShader(inputDeclaration1, "", inputLayoutStr, kOutputLayout))1388{1389FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;1390}13911392const std::string &inputDeclaration2 = GetInputDeclaration("vec4 input2", inputSize + 1);1393if (compileGeometryShader(inputDeclaration2, "", inputLayoutStr, kOutputLayout) ||1394compileGeometryShader(inputDeclaration1, inputDeclaration2, inputLayoutStr,1395kOutputLayout))1396{1397FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;1398}1399}1400}14011402// Geometry shaders allow inputs with explicit size declared after the declaration of the1403// input primitive, but their sizes should match the previous input primitive declaration.1404TEST_F(GeometryShaderTest, InputWithSizeAfterInputPrimitive)1405{1406for (auto &primitiveAndArraySize : kInputPrimitivesAndInputArraySizeMap)1407{1408const std::string &inputLayoutStr =1409GetGeometryShaderLayout("in", primitiveAndArraySize.first, -1, -1);1410const int inputSize = primitiveAndArraySize.second;14111412const std::string &inputDeclaration1 = GetInputDeclaration("vec4 input1", inputSize);1413if (!compileGeometryShader(inputLayoutStr, kOutputLayout, inputDeclaration1, ""))1414{1415FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;1416}14171418const std::string &inputDeclaration2 = GetInputDeclaration("vec4 input2", inputSize + 1);1419if (compileGeometryShader(inputLayoutStr, kOutputLayout, inputDeclaration2, ""))1420{1421FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;1422}1423}1424}14251426// Verify that Geometry Shaders accept non-array outputs.1427TEST_F(GeometryShaderTest, NonArrayOutputs)1428{1429const std::string &shaderString =1430R"(#version 310 es1431#extension GL_EXT_geometry_shader : require1432layout (points) in;1433layout (points, max_vertices = 1) out;1434out vec4 color;1435void main()1436{1437})";14381439if (!compile(shaderString))1440{1441FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;1442}1443}14441445// Verify that Geometry Shaders allow declaring outputs with 'location' layout qualifier.1446TEST_F(GeometryShaderTest, OutputsWithLocation)1447{1448const std::string &shaderString =1449R"(#version 310 es1450#extension GL_EXT_geometry_shader : require1451layout (triangles) in;1452layout (points, max_vertices = 1) out;1453layout (location = 0) out vec4 color1;1454layout (location = 1) out vec4 color2;1455void main()1456{1457color1 = vec4(0.0, 1.0, 0.0, 1.0);1458color2 = vec4(1.0, 0.0, 0.0, 1.0);1459})";14601461if (!compile(shaderString))1462{1463FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;1464}1465}14661467// Geometry Shaders allow declaring sized array outputs.1468TEST_F(GeometryShaderTest, SizedArrayOutputs)1469{1470const std::string &shaderString =1471R"(#version 310 es1472#extension GL_EXT_geometry_shader : require1473layout (triangles) in;1474layout (points, max_vertices = 1) out;1475out vec4 color[2];1476void main()1477{1478color[0] = vec4(0.0, 1.0, 0.0, 1.0);1479color[1] = vec4(1.0, 0.0, 0.0, 1.0);1480})";14811482if (!compile(shaderString))1483{1484FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;1485}1486}14871488// Verify that Geometry Shader outputs cannot be declared as an unsized array.1489TEST_F(GeometryShaderTest, UnsizedArrayOutputs)1490{1491const std::string &shaderString =1492R"(#version 310 es1493#extension GL_EXT_geometry_shader : require1494layout (triangles) in;1495layout (points, max_vertices = 1) out;1496out vec4 color[];1497void main()1498{1499})";15001501if (compile(shaderString))1502{1503FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;1504}1505}15061507// Verify that Geometry Shader inputs can use interpolation qualifiers.1508TEST_F(GeometryShaderTest, InputWithInterpolationQualifiers)1509{1510for (const std::string &qualifier : kInterpolationQualifiers)1511{1512std::ostringstream stream;1513stream << kHeader << kInputLayout << kOutputLayout << qualifier << " in vec4 texcoord[];\n"1514<< kEmptyBody;15151516if (!compile(stream.str()))1517{1518FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;1519}1520}1521}15221523// Verify that Geometry Shader outputs can use interpolation qualifiers.1524TEST_F(GeometryShaderTest, OutputWithInterpolationQualifiers)1525{1526for (const std::string &qualifier : kInterpolationQualifiers)1527{1528std::ostringstream stream;1529stream << kHeader << kInputLayout << kOutputLayout << qualifier << " out vec4 color;\n"1530<< kEmptyBody;15311532if (!compile(stream.str()))1533{1534FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;1535}1536}1537}15381539// Verify that Geometry Shader outputs can use 'invariant' qualifier.1540TEST_F(GeometryShaderTest, InvariantOutput)1541{1542const std::string &shaderString =1543R"(#version 310 es1544#extension GL_EXT_geometry_shader : require1545layout (points) in;1546layout (points, max_vertices = 2) out;1547invariant out vec4 gs_output;1548void main()1549{1550gl_Position = gl_in[0].gl_Position;1551})";15521553if (!compile(shaderString))1554{1555FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;1556}1557}15581559// Verify that the member of gl_in won't be incorrectly changed in the output shader string.1560TEST_F(GeometryShaderOutputCodeTest, ValidateGLInMembersInOutputShaderString)1561{1562const std::string &shaderString1 =1563R"(#version 310 es1564#extension GL_EXT_geometry_shader : require1565layout (lines) in;1566layout (points, max_vertices = 2) out;1567void main()1568{1569vec4 position;1570for (int i = 0; i < 2; i++)1571{1572position = gl_in[i].gl_Position;1573}1574})";15751576compile(shaderString1);1577EXPECT_TRUE(foundInESSLCode("].gl_Position"));15781579const std::string &shaderString2 =1580R"(#version 310 es1581#extension GL_EXT_geometry_shader : require1582layout (points) in;1583layout (points, max_vertices = 2) out;1584void main()1585{1586vec4 position;1587position = gl_in[0].gl_Position;1588})";15891590compile(shaderString2);1591EXPECT_TRUE(foundInESSLCode("].gl_Position"));1592}15931594// Verify that geometry shader inputs can be declared as struct arrays.1595TEST_F(GeometryShaderTest, StructArrayInput)1596{1597const std::string &shaderString =1598R"(#version 310 es1599#extension GL_EXT_geometry_shader : require1600layout (points) in;1601layout (points, max_vertices = 2) out;1602struct S1603{1604float value1;1605vec4 value2;1606};1607in S gs_input[];1608out S gs_output;1609void main()1610{1611gs_output = gs_input[0];1612})";16131614if (!compile(shaderString))1615{1616FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;1617}1618}16191620// Verify that geometry shader outputs cannot be declared as struct arrays.1621TEST_F(GeometryShaderTest, StructArrayOutput)1622{1623const std::string &shaderString =1624R"(#version 310 es1625#extension GL_EXT_geometry_shader : require1626layout (points) in;1627layout (points, max_vertices = 2) out;1628struct S1629{1630float value1;1631vec4 value2;1632};1633out S gs_output[1];1634void main()1635{1636gs_output[0].value1 = 1.0;1637gs_output[0].value2 = vec4(1.0, 0.0, 0.0, 1.0);1638})";16391640if (compile(shaderString))1641{1642FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;1643}1644}164516461647