xref: /aosp_15_r20/external/angle/src/tests/gl_tests/GeometryShaderTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2017 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker 
7*8975f5c5SAndroid Build Coastguard Worker // GeometryShaderTest.cpp : Tests of the implementation of geometry shader
8*8975f5c5SAndroid Build Coastguard Worker 
9*8975f5c5SAndroid Build Coastguard Worker #include "test_utils/ANGLETest.h"
10*8975f5c5SAndroid Build Coastguard Worker #include "test_utils/gl_raii.h"
11*8975f5c5SAndroid Build Coastguard Worker 
12*8975f5c5SAndroid Build Coastguard Worker using namespace angle;
13*8975f5c5SAndroid Build Coastguard Worker 
14*8975f5c5SAndroid Build Coastguard Worker namespace
15*8975f5c5SAndroid Build Coastguard Worker {
16*8975f5c5SAndroid Build Coastguard Worker 
17*8975f5c5SAndroid Build Coastguard Worker class GeometryShaderTest : public ANGLETest<>
18*8975f5c5SAndroid Build Coastguard Worker {
19*8975f5c5SAndroid Build Coastguard Worker   protected:
GeometryShaderTest()20*8975f5c5SAndroid Build Coastguard Worker     GeometryShaderTest()
21*8975f5c5SAndroid Build Coastguard Worker     {
22*8975f5c5SAndroid Build Coastguard Worker         setWindowWidth(64);
23*8975f5c5SAndroid Build Coastguard Worker         setWindowHeight(32);
24*8975f5c5SAndroid Build Coastguard Worker         setConfigRedBits(8);
25*8975f5c5SAndroid Build Coastguard Worker         setConfigGreenBits(8);
26*8975f5c5SAndroid Build Coastguard Worker         setConfigBlueBits(8);
27*8975f5c5SAndroid Build Coastguard Worker         setConfigAlphaBits(8);
28*8975f5c5SAndroid Build Coastguard Worker         setConfigDepthBits(24);
29*8975f5c5SAndroid Build Coastguard Worker         setConfigStencilBits(8);
30*8975f5c5SAndroid Build Coastguard Worker     }
31*8975f5c5SAndroid Build Coastguard Worker 
CreateEmptyGeometryShader(const std::string & inputPrimitive,const std::string & outputPrimitive,int invocations,int maxVertices)32*8975f5c5SAndroid Build Coastguard Worker     static std::string CreateEmptyGeometryShader(const std::string &inputPrimitive,
33*8975f5c5SAndroid Build Coastguard Worker                                                  const std::string &outputPrimitive,
34*8975f5c5SAndroid Build Coastguard Worker                                                  int invocations,
35*8975f5c5SAndroid Build Coastguard Worker                                                  int maxVertices)
36*8975f5c5SAndroid Build Coastguard Worker     {
37*8975f5c5SAndroid Build Coastguard Worker         std::ostringstream ostream;
38*8975f5c5SAndroid Build Coastguard Worker         ostream << "#version 310 es\n"
39*8975f5c5SAndroid Build Coastguard Worker                    "#extension GL_EXT_geometry_shader : require\n";
40*8975f5c5SAndroid Build Coastguard Worker         if (!inputPrimitive.empty())
41*8975f5c5SAndroid Build Coastguard Worker         {
42*8975f5c5SAndroid Build Coastguard Worker             ostream << "layout (" << inputPrimitive << ") in;\n";
43*8975f5c5SAndroid Build Coastguard Worker         }
44*8975f5c5SAndroid Build Coastguard Worker         if (!outputPrimitive.empty())
45*8975f5c5SAndroid Build Coastguard Worker         {
46*8975f5c5SAndroid Build Coastguard Worker             ostream << "layout (" << outputPrimitive << ") out;\n";
47*8975f5c5SAndroid Build Coastguard Worker         }
48*8975f5c5SAndroid Build Coastguard Worker         if (invocations > 0)
49*8975f5c5SAndroid Build Coastguard Worker         {
50*8975f5c5SAndroid Build Coastguard Worker             ostream << "layout (invocations = " << invocations << ") in;\n";
51*8975f5c5SAndroid Build Coastguard Worker         }
52*8975f5c5SAndroid Build Coastguard Worker         if (maxVertices >= 0)
53*8975f5c5SAndroid Build Coastguard Worker         {
54*8975f5c5SAndroid Build Coastguard Worker             ostream << "layout (max_vertices = " << maxVertices << ") out;\n";
55*8975f5c5SAndroid Build Coastguard Worker         }
56*8975f5c5SAndroid Build Coastguard Worker         ostream << "void main()\n"
57*8975f5c5SAndroid Build Coastguard Worker                    "{\n"
58*8975f5c5SAndroid Build Coastguard Worker                    "}";
59*8975f5c5SAndroid Build Coastguard Worker         return ostream.str();
60*8975f5c5SAndroid Build Coastguard Worker     }
61*8975f5c5SAndroid Build Coastguard Worker 
62*8975f5c5SAndroid Build Coastguard Worker     void setupLayeredFramebuffer(GLuint framebuffer,
63*8975f5c5SAndroid Build Coastguard Worker                                  GLuint color0,
64*8975f5c5SAndroid Build Coastguard Worker                                  GLuint color1,
65*8975f5c5SAndroid Build Coastguard Worker                                  GLuint depthStencil,
66*8975f5c5SAndroid Build Coastguard Worker                                  GLenum colorTarget,
67*8975f5c5SAndroid Build Coastguard Worker                                  const GLColor &color0InitialColor,
68*8975f5c5SAndroid Build Coastguard Worker                                  const GLColor &color1InitialColor,
69*8975f5c5SAndroid Build Coastguard Worker                                  float depthInitialValue,
70*8975f5c5SAndroid Build Coastguard Worker                                  GLint stencilInitialValue);
71*8975f5c5SAndroid Build Coastguard Worker     void setupLayeredFramebufferProgram(GLProgram *program);
72*8975f5c5SAndroid Build Coastguard Worker     void verifyLayeredFramebufferColor(GLuint colorTexture,
73*8975f5c5SAndroid Build Coastguard Worker                                        GLenum colorTarget,
74*8975f5c5SAndroid Build Coastguard Worker                                        const GLColor expected[],
75*8975f5c5SAndroid Build Coastguard Worker                                        GLsizei layerCount);
76*8975f5c5SAndroid Build Coastguard Worker     void verifyLayeredFramebufferDepthStencil(GLuint depthStencilTexture,
77*8975f5c5SAndroid Build Coastguard Worker                                               const float expectedDepth[],
78*8975f5c5SAndroid Build Coastguard Worker                                               const GLint expectedStencil[],
79*8975f5c5SAndroid Build Coastguard Worker                                               GLsizei layerCount);
80*8975f5c5SAndroid Build Coastguard Worker 
81*8975f5c5SAndroid Build Coastguard Worker     void layeredFramebufferClearTest(GLenum colorTarget);
82*8975f5c5SAndroid Build Coastguard Worker     void layeredFramebufferPreRenderClearTest(GLenum colorTarget, bool doubleClear);
83*8975f5c5SAndroid Build Coastguard Worker     void layeredFramebufferMidRenderClearTest(GLenum colorTarget);
84*8975f5c5SAndroid Build Coastguard Worker     void callFramebufferTextureAPI(APIExtensionVersion usedExtension,
85*8975f5c5SAndroid Build Coastguard Worker                                    GLenum target,
86*8975f5c5SAndroid Build Coastguard Worker                                    GLenum attachment,
87*8975f5c5SAndroid Build Coastguard Worker                                    GLuint texture,
88*8975f5c5SAndroid Build Coastguard Worker                                    GLint level);
89*8975f5c5SAndroid Build Coastguard Worker     void testNegativeFramebufferTexture(APIExtensionVersion usedExtension);
90*8975f5c5SAndroid Build Coastguard Worker     void testCreateAndAttachGeometryShader(APIExtensionVersion usedExtension);
91*8975f5c5SAndroid Build Coastguard Worker 
92*8975f5c5SAndroid Build Coastguard Worker     static constexpr GLsizei kWidth              = 16;
93*8975f5c5SAndroid Build Coastguard Worker     static constexpr GLsizei kHeight             = 16;
94*8975f5c5SAndroid Build Coastguard Worker     static constexpr GLsizei kColor0Layers       = 4;
95*8975f5c5SAndroid Build Coastguard Worker     static constexpr GLsizei kColor1Layers       = 3;
96*8975f5c5SAndroid Build Coastguard Worker     static constexpr GLsizei kDepthStencilLayers = 5;
97*8975f5c5SAndroid Build Coastguard Worker     static constexpr GLsizei kFramebufferLayers =
98*8975f5c5SAndroid Build Coastguard Worker         std::min({kColor0Layers, kColor1Layers, kDepthStencilLayers});
99*8975f5c5SAndroid Build Coastguard Worker };
100*8975f5c5SAndroid Build Coastguard Worker 
101*8975f5c5SAndroid Build Coastguard Worker class GeometryShaderTestES3 : public ANGLETest<>
102*8975f5c5SAndroid Build Coastguard Worker {};
103*8975f5c5SAndroid Build Coastguard Worker 
104*8975f5c5SAndroid Build Coastguard Worker class GeometryShaderTestES32 : public GeometryShaderTest
105*8975f5c5SAndroid Build Coastguard Worker {};
106*8975f5c5SAndroid Build Coastguard Worker 
107*8975f5c5SAndroid Build Coastguard Worker // Verify that a geometry shader cannot be created in an OpenGL ES 3.0 context, since at least
108*8975f5c5SAndroid Build Coastguard Worker // ES 3.1 is required.
TEST_P(GeometryShaderTestES3,CreateGeometryShaderInES3)109*8975f5c5SAndroid Build Coastguard Worker TEST_P(GeometryShaderTestES3, CreateGeometryShaderInES3)
110*8975f5c5SAndroid Build Coastguard Worker {
111*8975f5c5SAndroid Build Coastguard Worker     EXPECT_TRUE(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
112*8975f5c5SAndroid Build Coastguard Worker     GLuint geometryShader = glCreateShader(GL_GEOMETRY_SHADER_EXT);
113*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(0u, geometryShader);
114*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_ENUM);
115*8975f5c5SAndroid Build Coastguard Worker }
116*8975f5c5SAndroid Build Coastguard Worker 
testCreateAndAttachGeometryShader(APIExtensionVersion usedExtension)117*8975f5c5SAndroid Build Coastguard Worker void GeometryShaderTest::testCreateAndAttachGeometryShader(APIExtensionVersion usedExtension)
118*8975f5c5SAndroid Build Coastguard Worker {
119*8975f5c5SAndroid Build Coastguard Worker     ASSERT(usedExtension == APIExtensionVersion::EXT || usedExtension == APIExtensionVersion::OES ||
120*8975f5c5SAndroid Build Coastguard Worker            usedExtension == APIExtensionVersion::Core);
121*8975f5c5SAndroid Build Coastguard Worker 
122*8975f5c5SAndroid Build Coastguard Worker     std::string gs;
123*8975f5c5SAndroid Build Coastguard Worker 
124*8975f5c5SAndroid Build Coastguard Worker     constexpr char kGLSLVersion31[] = R"(#version 310 es
125*8975f5c5SAndroid Build Coastguard Worker )";
126*8975f5c5SAndroid Build Coastguard Worker     constexpr char kGLSLVersion32[] = R"(#version 320 es
127*8975f5c5SAndroid Build Coastguard Worker )";
128*8975f5c5SAndroid Build Coastguard Worker     constexpr char kGeometryEXT[]   = R"(#extension GL_EXT_geometry_shader : require
129*8975f5c5SAndroid Build Coastguard Worker )";
130*8975f5c5SAndroid Build Coastguard Worker     constexpr char kGeometryOES[]   = R"(#extension GL_OES_geometry_shader : require
131*8975f5c5SAndroid Build Coastguard Worker )";
132*8975f5c5SAndroid Build Coastguard Worker 
133*8975f5c5SAndroid Build Coastguard Worker     if (usedExtension == APIExtensionVersion::EXT)
134*8975f5c5SAndroid Build Coastguard Worker     {
135*8975f5c5SAndroid Build Coastguard Worker         gs.append(kGLSLVersion31);
136*8975f5c5SAndroid Build Coastguard Worker         gs.append(kGeometryEXT);
137*8975f5c5SAndroid Build Coastguard Worker     }
138*8975f5c5SAndroid Build Coastguard Worker     else if (usedExtension == APIExtensionVersion::OES)
139*8975f5c5SAndroid Build Coastguard Worker     {
140*8975f5c5SAndroid Build Coastguard Worker         gs.append(kGLSLVersion31);
141*8975f5c5SAndroid Build Coastguard Worker         gs.append(kGeometryOES);
142*8975f5c5SAndroid Build Coastguard Worker     }
143*8975f5c5SAndroid Build Coastguard Worker     else
144*8975f5c5SAndroid Build Coastguard Worker     {
145*8975f5c5SAndroid Build Coastguard Worker         gs.append(kGLSLVersion32);
146*8975f5c5SAndroid Build Coastguard Worker     }
147*8975f5c5SAndroid Build Coastguard Worker 
148*8975f5c5SAndroid Build Coastguard Worker     constexpr char kGSBody[] = R"(
149*8975f5c5SAndroid Build Coastguard Worker layout (invocations = 3, triangles) in;
150*8975f5c5SAndroid Build Coastguard Worker layout (triangle_strip, max_vertices = 3) out;
151*8975f5c5SAndroid Build Coastguard Worker in vec4 texcoord[];
152*8975f5c5SAndroid Build Coastguard Worker out vec4 o_texcoord;
153*8975f5c5SAndroid Build Coastguard Worker void main()
154*8975f5c5SAndroid Build Coastguard Worker {
155*8975f5c5SAndroid Build Coastguard Worker     int n;
156*8975f5c5SAndroid Build Coastguard Worker     for (n = 0; n < gl_in.length(); n++)
157*8975f5c5SAndroid Build Coastguard Worker     {
158*8975f5c5SAndroid Build Coastguard Worker         gl_Position = gl_in[n].gl_Position;
159*8975f5c5SAndroid Build Coastguard Worker         gl_Layer   = gl_InvocationID;
160*8975f5c5SAndroid Build Coastguard Worker         o_texcoord = texcoord[n];
161*8975f5c5SAndroid Build Coastguard Worker         EmitVertex();
162*8975f5c5SAndroid Build Coastguard Worker     }
163*8975f5c5SAndroid Build Coastguard Worker     EndPrimitive();
164*8975f5c5SAndroid Build Coastguard Worker })";
165*8975f5c5SAndroid Build Coastguard Worker     gs.append(kGSBody);
166*8975f5c5SAndroid Build Coastguard Worker 
167*8975f5c5SAndroid Build Coastguard Worker     GLuint geometryShader = CompileShader(GL_GEOMETRY_SHADER_EXT, gs.c_str());
168*8975f5c5SAndroid Build Coastguard Worker     EXPECT_NE(0u, geometryShader);
169*8975f5c5SAndroid Build Coastguard Worker 
170*8975f5c5SAndroid Build Coastguard Worker     GLuint programID = glCreateProgram();
171*8975f5c5SAndroid Build Coastguard Worker     glAttachShader(programID, geometryShader);
172*8975f5c5SAndroid Build Coastguard Worker 
173*8975f5c5SAndroid Build Coastguard Worker     glDetachShader(programID, geometryShader);
174*8975f5c5SAndroid Build Coastguard Worker     glDeleteShader(geometryShader);
175*8975f5c5SAndroid Build Coastguard Worker     glDeleteProgram(programID);
176*8975f5c5SAndroid Build Coastguard Worker 
177*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
178*8975f5c5SAndroid Build Coastguard Worker }
179*8975f5c5SAndroid Build Coastguard Worker 
180*8975f5c5SAndroid Build Coastguard Worker // Verify that a geometry shader can be created and attached to a program using the EXT extension.
TEST_P(GeometryShaderTest,CreateAndAttachGeometryShaderEXT)181*8975f5c5SAndroid Build Coastguard Worker TEST_P(GeometryShaderTest, CreateAndAttachGeometryShaderEXT)
182*8975f5c5SAndroid Build Coastguard Worker {
183*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
184*8975f5c5SAndroid Build Coastguard Worker     testCreateAndAttachGeometryShader(APIExtensionVersion::EXT);
185*8975f5c5SAndroid Build Coastguard Worker }
186*8975f5c5SAndroid Build Coastguard Worker 
187*8975f5c5SAndroid Build Coastguard Worker // Verify that a geometry shader can be created and attached to a program using the OES extension.
TEST_P(GeometryShaderTest,CreateAndAttachGeometryShaderOES)188*8975f5c5SAndroid Build Coastguard Worker TEST_P(GeometryShaderTest, CreateAndAttachGeometryShaderOES)
189*8975f5c5SAndroid Build Coastguard Worker {
190*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_geometry_shader"));
191*8975f5c5SAndroid Build Coastguard Worker     testCreateAndAttachGeometryShader(APIExtensionVersion::OES);
192*8975f5c5SAndroid Build Coastguard Worker }
193*8975f5c5SAndroid Build Coastguard Worker 
194*8975f5c5SAndroid Build Coastguard Worker // Verify that a geometry shader can be created and attached to a program in GLES 3.2.
TEST_P(GeometryShaderTestES32,CreateAndAttachGeometryShader)195*8975f5c5SAndroid Build Coastguard Worker TEST_P(GeometryShaderTestES32, CreateAndAttachGeometryShader)
196*8975f5c5SAndroid Build Coastguard Worker {
197*8975f5c5SAndroid Build Coastguard Worker     testCreateAndAttachGeometryShader(APIExtensionVersion::Core);
198*8975f5c5SAndroid Build Coastguard Worker }
199*8975f5c5SAndroid Build Coastguard Worker 
200*8975f5c5SAndroid Build Coastguard Worker // Verify that Geometry Shader can be compiled when geometry shader array input size
201*8975f5c5SAndroid Build Coastguard Worker // is set after shader input variables.
202*8975f5c5SAndroid Build Coastguard Worker // http://anglebug.com/42265598 GFXBench Car Chase uses this pattern
TEST_P(GeometryShaderTest,DeferredSetOfArrayInputSize)203*8975f5c5SAndroid Build Coastguard Worker TEST_P(GeometryShaderTest, DeferredSetOfArrayInputSize)
204*8975f5c5SAndroid Build Coastguard Worker {
205*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
206*8975f5c5SAndroid Build Coastguard Worker     // "layout (invocations = 3, triangles) in;" should be declared before "in vec4 texcoord [];",
207*8975f5c5SAndroid Build Coastguard Worker     // but here it is declared later.
208*8975f5c5SAndroid Build Coastguard Worker     constexpr char kGS[]  = R"(#version 310 es
209*8975f5c5SAndroid Build Coastguard Worker #extension GL_EXT_geometry_shader : require
210*8975f5c5SAndroid Build Coastguard Worker in vec4 texcoord[];
211*8975f5c5SAndroid Build Coastguard Worker out vec4 o_texcoord;
212*8975f5c5SAndroid Build Coastguard Worker layout (invocations = 3, triangles_adjacency) in;
213*8975f5c5SAndroid Build Coastguard Worker layout (triangle_strip, max_vertices = 3) out;
214*8975f5c5SAndroid Build Coastguard Worker void main()
215*8975f5c5SAndroid Build Coastguard Worker {
216*8975f5c5SAndroid Build Coastguard Worker     int n;
217*8975f5c5SAndroid Build Coastguard Worker     for (n = 0; n < gl_in.length(); n++)
218*8975f5c5SAndroid Build Coastguard Worker     {
219*8975f5c5SAndroid Build Coastguard Worker         gl_Position = gl_in[n].gl_Position;
220*8975f5c5SAndroid Build Coastguard Worker         gl_Layer   = gl_InvocationID;
221*8975f5c5SAndroid Build Coastguard Worker         o_texcoord = texcoord[n];
222*8975f5c5SAndroid Build Coastguard Worker         EmitVertex();
223*8975f5c5SAndroid Build Coastguard Worker     }
224*8975f5c5SAndroid Build Coastguard Worker     EndPrimitive();
225*8975f5c5SAndroid Build Coastguard Worker })";
226*8975f5c5SAndroid Build Coastguard Worker     GLuint geometryShader = CompileShader(GL_GEOMETRY_SHADER_EXT, kGS);
227*8975f5c5SAndroid Build Coastguard Worker     EXPECT_NE(0u, geometryShader);
228*8975f5c5SAndroid Build Coastguard Worker     GLuint programID = glCreateProgram();
229*8975f5c5SAndroid Build Coastguard Worker     glAttachShader(programID, geometryShader);
230*8975f5c5SAndroid Build Coastguard Worker     glDetachShader(programID, geometryShader);
231*8975f5c5SAndroid Build Coastguard Worker     glDeleteShader(geometryShader);
232*8975f5c5SAndroid Build Coastguard Worker     glDeleteProgram(programID);
233*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
234*8975f5c5SAndroid Build Coastguard Worker }
235*8975f5c5SAndroid Build Coastguard Worker 
236*8975f5c5SAndroid Build Coastguard Worker // Verify that all the implementation dependent geometry shader related resource limits meet the
237*8975f5c5SAndroid Build Coastguard Worker // requirement of GL_EXT_geometry_shader SPEC.
TEST_P(GeometryShaderTest,GeometryShaderImplementationDependentLimits)238*8975f5c5SAndroid Build Coastguard Worker TEST_P(GeometryShaderTest, GeometryShaderImplementationDependentLimits)
239*8975f5c5SAndroid Build Coastguard Worker {
240*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
241*8975f5c5SAndroid Build Coastguard Worker 
242*8975f5c5SAndroid Build Coastguard Worker     // http://anglebug.com/42264048
243*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(IsIntel() && IsVulkan() && IsLinux());
244*8975f5c5SAndroid Build Coastguard Worker 
245*8975f5c5SAndroid Build Coastguard Worker     const std::map<GLenum, int> limits = {{GL_MAX_FRAMEBUFFER_LAYERS_EXT, 256},
246*8975f5c5SAndroid Build Coastguard Worker                                           {GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT, 1024},
247*8975f5c5SAndroid Build Coastguard Worker                                           {GL_MAX_GEOMETRY_UNIFORM_BLOCKS_EXT, 12},
248*8975f5c5SAndroid Build Coastguard Worker                                           {GL_MAX_GEOMETRY_INPUT_COMPONENTS_EXT, 64},
249*8975f5c5SAndroid Build Coastguard Worker                                           {GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_EXT, 64},
250*8975f5c5SAndroid Build Coastguard Worker                                           {GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT, 256},
251*8975f5c5SAndroid Build Coastguard Worker                                           {GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT, 1024},
252*8975f5c5SAndroid Build Coastguard Worker                                           {GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT, 16},
253*8975f5c5SAndroid Build Coastguard Worker                                           {GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT, 0},
254*8975f5c5SAndroid Build Coastguard Worker                                           {GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT, 0},
255*8975f5c5SAndroid Build Coastguard Worker                                           {GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT, 0},
256*8975f5c5SAndroid Build Coastguard Worker                                           {GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT, 0},
257*8975f5c5SAndroid Build Coastguard Worker                                           {GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT, 32}};
258*8975f5c5SAndroid Build Coastguard Worker 
259*8975f5c5SAndroid Build Coastguard Worker     GLint value;
260*8975f5c5SAndroid Build Coastguard Worker     for (const auto &limit : limits)
261*8975f5c5SAndroid Build Coastguard Worker     {
262*8975f5c5SAndroid Build Coastguard Worker         value = 0;
263*8975f5c5SAndroid Build Coastguard Worker         glGetIntegerv(limit.first, &value);
264*8975f5c5SAndroid Build Coastguard Worker         EXPECT_GL_NO_ERROR();
265*8975f5c5SAndroid Build Coastguard Worker         EXPECT_GE(value, limit.second);
266*8975f5c5SAndroid Build Coastguard Worker     }
267*8975f5c5SAndroid Build Coastguard Worker 
268*8975f5c5SAndroid Build Coastguard Worker     value = 0;
269*8975f5c5SAndroid Build Coastguard Worker     glGetIntegerv(GL_LAYER_PROVOKING_VERTEX_EXT, &value);
270*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
271*8975f5c5SAndroid Build Coastguard Worker     EXPECT_TRUE(value == GL_FIRST_VERTEX_CONVENTION_EXT || value == GL_LAST_VERTEX_CONVENTION_EXT ||
272*8975f5c5SAndroid Build Coastguard Worker                 value == GL_UNDEFINED_VERTEX_EXT);
273*8975f5c5SAndroid Build Coastguard Worker }
274*8975f5c5SAndroid Build Coastguard Worker 
275*8975f5c5SAndroid Build Coastguard Worker // Verify that all the combined resource limits meet the requirement of GL_EXT_geometry_shader SPEC.
TEST_P(GeometryShaderTest,CombinedResourceLimits)276*8975f5c5SAndroid Build Coastguard Worker TEST_P(GeometryShaderTest, CombinedResourceLimits)
277*8975f5c5SAndroid Build Coastguard Worker {
278*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
279*8975f5c5SAndroid Build Coastguard Worker 
280*8975f5c5SAndroid Build Coastguard Worker     // See http://anglebug.com/42260977.
281*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(IsAndroid());
282*8975f5c5SAndroid Build Coastguard Worker 
283*8975f5c5SAndroid Build Coastguard Worker     const std::map<GLenum, int> limits = {{GL_MAX_UNIFORM_BUFFER_BINDINGS, 48},
284*8975f5c5SAndroid Build Coastguard Worker                                           {GL_MAX_COMBINED_UNIFORM_BLOCKS, 36},
285*8975f5c5SAndroid Build Coastguard Worker                                           {GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, 64}};
286*8975f5c5SAndroid Build Coastguard Worker 
287*8975f5c5SAndroid Build Coastguard Worker     GLint value;
288*8975f5c5SAndroid Build Coastguard Worker     for (const auto &limit : limits)
289*8975f5c5SAndroid Build Coastguard Worker     {
290*8975f5c5SAndroid Build Coastguard Worker         value = 0;
291*8975f5c5SAndroid Build Coastguard Worker         glGetIntegerv(limit.first, &value);
292*8975f5c5SAndroid Build Coastguard Worker         EXPECT_GL_NO_ERROR();
293*8975f5c5SAndroid Build Coastguard Worker         EXPECT_GE(value, limit.second);
294*8975f5c5SAndroid Build Coastguard Worker     }
295*8975f5c5SAndroid Build Coastguard Worker }
296*8975f5c5SAndroid Build Coastguard Worker 
297*8975f5c5SAndroid Build Coastguard Worker // Verify that linking a program with an uncompiled geometry shader causes a link failure.
TEST_P(GeometryShaderTest,LinkWithUncompiledGeometryShader)298*8975f5c5SAndroid Build Coastguard Worker TEST_P(GeometryShaderTest, LinkWithUncompiledGeometryShader)
299*8975f5c5SAndroid Build Coastguard Worker {
300*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
301*8975f5c5SAndroid Build Coastguard Worker 
302*8975f5c5SAndroid Build Coastguard Worker     GLuint vertexShader   = CompileShader(GL_VERTEX_SHADER, essl31_shaders::vs::Simple());
303*8975f5c5SAndroid Build Coastguard Worker     GLuint fragmentShader = CompileShader(GL_FRAGMENT_SHADER, essl31_shaders::fs::Red());
304*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(0u, vertexShader);
305*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(0u, fragmentShader);
306*8975f5c5SAndroid Build Coastguard Worker 
307*8975f5c5SAndroid Build Coastguard Worker     GLuint geometryShader = glCreateShader(GL_GEOMETRY_SHADER_EXT);
308*8975f5c5SAndroid Build Coastguard Worker 
309*8975f5c5SAndroid Build Coastguard Worker     GLuint program = glCreateProgram();
310*8975f5c5SAndroid Build Coastguard Worker     glAttachShader(program, vertexShader);
311*8975f5c5SAndroid Build Coastguard Worker     glAttachShader(program, fragmentShader);
312*8975f5c5SAndroid Build Coastguard Worker     glAttachShader(program, geometryShader);
313*8975f5c5SAndroid Build Coastguard Worker     glDeleteShader(vertexShader);
314*8975f5c5SAndroid Build Coastguard Worker     glDeleteShader(fragmentShader);
315*8975f5c5SAndroid Build Coastguard Worker     glDeleteShader(geometryShader);
316*8975f5c5SAndroid Build Coastguard Worker 
317*8975f5c5SAndroid Build Coastguard Worker     glLinkProgram(program);
318*8975f5c5SAndroid Build Coastguard Worker 
319*8975f5c5SAndroid Build Coastguard Worker     GLint linkStatus;
320*8975f5c5SAndroid Build Coastguard Worker     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
321*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(0, linkStatus);
322*8975f5c5SAndroid Build Coastguard Worker 
323*8975f5c5SAndroid Build Coastguard Worker     glDeleteProgram(program);
324*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
325*8975f5c5SAndroid Build Coastguard Worker }
326*8975f5c5SAndroid Build Coastguard Worker 
327*8975f5c5SAndroid Build Coastguard Worker // Verify that linking a program with geometry shader whose version is different from other shaders
328*8975f5c5SAndroid Build Coastguard Worker // in this program causes a link error.
TEST_P(GeometryShaderTest,LinkWhenShaderVersionMismatch)329*8975f5c5SAndroid Build Coastguard Worker TEST_P(GeometryShaderTest, LinkWhenShaderVersionMismatch)
330*8975f5c5SAndroid Build Coastguard Worker {
331*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
332*8975f5c5SAndroid Build Coastguard Worker 
333*8975f5c5SAndroid Build Coastguard Worker     const std::string &emptyGeometryShader = CreateEmptyGeometryShader("points", "points", 2, 1);
334*8975f5c5SAndroid Build Coastguard Worker 
335*8975f5c5SAndroid Build Coastguard Worker     GLuint program = CompileProgramWithGS(essl3_shaders::vs::Simple(), emptyGeometryShader.c_str(),
336*8975f5c5SAndroid Build Coastguard Worker                                           essl3_shaders::fs::Red());
337*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(0u, program);
338*8975f5c5SAndroid Build Coastguard Worker }
339*8975f5c5SAndroid Build Coastguard Worker 
340*8975f5c5SAndroid Build Coastguard Worker // Verify that linking a program with geometry shader that lacks input primitive,
341*8975f5c5SAndroid Build Coastguard Worker // output primitive, or declaration on 'max_vertices' causes a link failure.
TEST_P(GeometryShaderTest,LinkValidationOnGeometryShaderLayouts)342*8975f5c5SAndroid Build Coastguard Worker TEST_P(GeometryShaderTest, LinkValidationOnGeometryShaderLayouts)
343*8975f5c5SAndroid Build Coastguard Worker {
344*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
345*8975f5c5SAndroid Build Coastguard Worker 
346*8975f5c5SAndroid Build Coastguard Worker     const std::string gsWithoutInputPrimitive  = CreateEmptyGeometryShader("", "points", 2, 1);
347*8975f5c5SAndroid Build Coastguard Worker     const std::string gsWithoutOutputPrimitive = CreateEmptyGeometryShader("points", "", 2, 1);
348*8975f5c5SAndroid Build Coastguard Worker     const std::string gsWithoutInvocations = CreateEmptyGeometryShader("points", "points", -1, 1);
349*8975f5c5SAndroid Build Coastguard Worker     const std::string gsWithoutMaxVertices = CreateEmptyGeometryShader("points", "points", 2, -1);
350*8975f5c5SAndroid Build Coastguard Worker 
351*8975f5c5SAndroid Build Coastguard Worker     // Linking a program with a geometry shader that only lacks 'invocations' should not cause a
352*8975f5c5SAndroid Build Coastguard Worker     // link failure.
353*8975f5c5SAndroid Build Coastguard Worker     GLuint program = CompileProgramWithGS(essl31_shaders::vs::Simple(),
354*8975f5c5SAndroid Build Coastguard Worker                                           gsWithoutInvocations.c_str(), essl31_shaders::fs::Red());
355*8975f5c5SAndroid Build Coastguard Worker     EXPECT_NE(0u, program);
356*8975f5c5SAndroid Build Coastguard Worker 
357*8975f5c5SAndroid Build Coastguard Worker     glDeleteProgram(program);
358*8975f5c5SAndroid Build Coastguard Worker 
359*8975f5c5SAndroid Build Coastguard Worker     // Linking a program with a geometry shader that lacks input primitive, output primitive or
360*8975f5c5SAndroid Build Coastguard Worker     // 'max_vertices' causes a link failure.
361*8975f5c5SAndroid Build Coastguard Worker     program = CompileProgramWithGS(essl31_shaders::vs::Simple(), gsWithoutInputPrimitive.c_str(),
362*8975f5c5SAndroid Build Coastguard Worker                                    essl31_shaders::fs::Red());
363*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(0u, program);
364*8975f5c5SAndroid Build Coastguard Worker 
365*8975f5c5SAndroid Build Coastguard Worker     program = CompileProgramWithGS(essl31_shaders::vs::Simple(), gsWithoutOutputPrimitive.c_str(),
366*8975f5c5SAndroid Build Coastguard Worker                                    essl31_shaders::fs::Red());
367*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(0u, program);
368*8975f5c5SAndroid Build Coastguard Worker 
369*8975f5c5SAndroid Build Coastguard Worker     program = CompileProgramWithGS(essl31_shaders::vs::Simple(), gsWithoutMaxVertices.c_str(),
370*8975f5c5SAndroid Build Coastguard Worker                                    essl31_shaders::fs::Red());
371*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(0u, program);
372*8975f5c5SAndroid Build Coastguard Worker 
373*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
374*8975f5c5SAndroid Build Coastguard Worker }
375*8975f5c5SAndroid Build Coastguard Worker 
376*8975f5c5SAndroid Build Coastguard Worker // Verify that an link error occurs when the vertex shader has an array output and there is a
377*8975f5c5SAndroid Build Coastguard Worker // geometry shader in the program.
TEST_P(GeometryShaderTest,VertexShaderArrayOutput)378*8975f5c5SAndroid Build Coastguard Worker TEST_P(GeometryShaderTest, VertexShaderArrayOutput)
379*8975f5c5SAndroid Build Coastguard Worker {
380*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
381*8975f5c5SAndroid Build Coastguard Worker 
382*8975f5c5SAndroid Build Coastguard Worker     constexpr char kVS[] = R"(#version 310 es
383*8975f5c5SAndroid Build Coastguard Worker in vec4 vertex_in;
384*8975f5c5SAndroid Build Coastguard Worker out vec4 vertex_out[3];
385*8975f5c5SAndroid Build Coastguard Worker void main()
386*8975f5c5SAndroid Build Coastguard Worker {
387*8975f5c5SAndroid Build Coastguard Worker     gl_Position = vertex_in;
388*8975f5c5SAndroid Build Coastguard Worker     vertex_out[0] = vec4(1.0, 0.0, 0.0, 1.0);
389*8975f5c5SAndroid Build Coastguard Worker     vertex_out[1] = vec4(0.0, 1.0, 0.0, 1.0);
390*8975f5c5SAndroid Build Coastguard Worker     vertex_out[2] = vec4(0.0, 0.0, 1.0, 1.0);
391*8975f5c5SAndroid Build Coastguard Worker })";
392*8975f5c5SAndroid Build Coastguard Worker 
393*8975f5c5SAndroid Build Coastguard Worker     constexpr char kGS[] = R"(#version 310 es
394*8975f5c5SAndroid Build Coastguard Worker #extension GL_EXT_geometry_shader : require
395*8975f5c5SAndroid Build Coastguard Worker layout (invocations = 3, triangles) in;
396*8975f5c5SAndroid Build Coastguard Worker layout (points, max_vertices = 3) out;
397*8975f5c5SAndroid Build Coastguard Worker in vec4 vertex_out[];
398*8975f5c5SAndroid Build Coastguard Worker out vec4 geometry_color;
399*8975f5c5SAndroid Build Coastguard Worker void main()
400*8975f5c5SAndroid Build Coastguard Worker {
401*8975f5c5SAndroid Build Coastguard Worker     gl_Position = gl_in[0].gl_Position;
402*8975f5c5SAndroid Build Coastguard Worker     geometry_color = vertex_out[0];
403*8975f5c5SAndroid Build Coastguard Worker     EmitVertex();
404*8975f5c5SAndroid Build Coastguard Worker })";
405*8975f5c5SAndroid Build Coastguard Worker 
406*8975f5c5SAndroid Build Coastguard Worker     constexpr char kFS[] = R"(#version 310 es
407*8975f5c5SAndroid Build Coastguard Worker precision mediump float;
408*8975f5c5SAndroid Build Coastguard Worker in vec4 geometry_color;
409*8975f5c5SAndroid Build Coastguard Worker layout (location = 0) out vec4 output_color;
410*8975f5c5SAndroid Build Coastguard Worker void main()
411*8975f5c5SAndroid Build Coastguard Worker {
412*8975f5c5SAndroid Build Coastguard Worker     output_color = geometry_color;
413*8975f5c5SAndroid Build Coastguard Worker })";
414*8975f5c5SAndroid Build Coastguard Worker 
415*8975f5c5SAndroid Build Coastguard Worker     GLuint program = CompileProgramWithGS(kVS, kGS, kFS);
416*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(0u, program);
417*8975f5c5SAndroid Build Coastguard Worker 
418*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
419*8975f5c5SAndroid Build Coastguard Worker }
420*8975f5c5SAndroid Build Coastguard Worker 
421*8975f5c5SAndroid Build Coastguard Worker // Verify that an link error occurs when the definition of a unform in fragment shader is different
422*8975f5c5SAndroid Build Coastguard Worker // from those in a geometry shader.
TEST_P(GeometryShaderTest,UniformMismatchBetweenGeometryAndFragmentShader)423*8975f5c5SAndroid Build Coastguard Worker TEST_P(GeometryShaderTest, UniformMismatchBetweenGeometryAndFragmentShader)
424*8975f5c5SAndroid Build Coastguard Worker {
425*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
426*8975f5c5SAndroid Build Coastguard Worker 
427*8975f5c5SAndroid Build Coastguard Worker     constexpr char kVS[] = R"(#version 310 es
428*8975f5c5SAndroid Build Coastguard Worker uniform highp vec4 uniform_value_vert;
429*8975f5c5SAndroid Build Coastguard Worker in vec4 vertex_in;
430*8975f5c5SAndroid Build Coastguard Worker out vec4 vertex_out;
431*8975f5c5SAndroid Build Coastguard Worker void main()
432*8975f5c5SAndroid Build Coastguard Worker {
433*8975f5c5SAndroid Build Coastguard Worker     gl_Position = vertex_in;
434*8975f5c5SAndroid Build Coastguard Worker     vertex_out = uniform_value_vert;
435*8975f5c5SAndroid Build Coastguard Worker })";
436*8975f5c5SAndroid Build Coastguard Worker 
437*8975f5c5SAndroid Build Coastguard Worker     constexpr char kGS[] = R"(#version 310 es
438*8975f5c5SAndroid Build Coastguard Worker #extension GL_EXT_geometry_shader : require
439*8975f5c5SAndroid Build Coastguard Worker uniform vec4 uniform_value;
440*8975f5c5SAndroid Build Coastguard Worker layout (invocations = 3, triangles) in;
441*8975f5c5SAndroid Build Coastguard Worker layout (points, max_vertices = 3) out;
442*8975f5c5SAndroid Build Coastguard Worker in vec4 vertex_out[];
443*8975f5c5SAndroid Build Coastguard Worker out vec4 geometry_color;
444*8975f5c5SAndroid Build Coastguard Worker void main()
445*8975f5c5SAndroid Build Coastguard Worker {
446*8975f5c5SAndroid Build Coastguard Worker     gl_Position = gl_in[0].gl_Position;
447*8975f5c5SAndroid Build Coastguard Worker     geometry_color = vertex_out[0] + uniform_value;
448*8975f5c5SAndroid Build Coastguard Worker     EmitVertex();
449*8975f5c5SAndroid Build Coastguard Worker })";
450*8975f5c5SAndroid Build Coastguard Worker 
451*8975f5c5SAndroid Build Coastguard Worker     constexpr char kFS[] = R"(#version 310 es
452*8975f5c5SAndroid Build Coastguard Worker precision highp float;
453*8975f5c5SAndroid Build Coastguard Worker uniform float uniform_value;
454*8975f5c5SAndroid Build Coastguard Worker in vec4 geometry_color;
455*8975f5c5SAndroid Build Coastguard Worker layout (location = 0) out vec4 output_color;
456*8975f5c5SAndroid Build Coastguard Worker void main()
457*8975f5c5SAndroid Build Coastguard Worker {
458*8975f5c5SAndroid Build Coastguard Worker     output_color = vec4(geometry_color.rgb, uniform_value);
459*8975f5c5SAndroid Build Coastguard Worker })";
460*8975f5c5SAndroid Build Coastguard Worker 
461*8975f5c5SAndroid Build Coastguard Worker     GLuint program = CompileProgramWithGS(kVS, kGS, kFS);
462*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(0u, program);
463*8975f5c5SAndroid Build Coastguard Worker 
464*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
465*8975f5c5SAndroid Build Coastguard Worker }
466*8975f5c5SAndroid Build Coastguard Worker 
467*8975f5c5SAndroid Build Coastguard Worker // Verify that an link error occurs when the number of uniform blocks in a geometry shader exceeds
468*8975f5c5SAndroid Build Coastguard Worker // MAX_GEOMETRY_UNIFORM_BLOCKS_EXT.
TEST_P(GeometryShaderTest,TooManyUniformBlocks)469*8975f5c5SAndroid Build Coastguard Worker TEST_P(GeometryShaderTest, TooManyUniformBlocks)
470*8975f5c5SAndroid Build Coastguard Worker {
471*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
472*8975f5c5SAndroid Build Coastguard Worker 
473*8975f5c5SAndroid Build Coastguard Worker     GLint maxGeometryUniformBlocks = 0;
474*8975f5c5SAndroid Build Coastguard Worker     glGetIntegerv(GL_MAX_GEOMETRY_UNIFORM_BLOCKS_EXT, &maxGeometryUniformBlocks);
475*8975f5c5SAndroid Build Coastguard Worker 
476*8975f5c5SAndroid Build Coastguard Worker     GLint numUniformBlocks = maxGeometryUniformBlocks + 1;
477*8975f5c5SAndroid Build Coastguard Worker     std::ostringstream stream;
478*8975f5c5SAndroid Build Coastguard Worker     stream << "#version 310 es\n"
479*8975f5c5SAndroid Build Coastguard Worker               "#extension GL_EXT_geometry_shader : require\n"
480*8975f5c5SAndroid Build Coastguard Worker               "uniform ubo\n"
481*8975f5c5SAndroid Build Coastguard Worker               "{\n"
482*8975f5c5SAndroid Build Coastguard Worker               "    vec4 value1;\n"
483*8975f5c5SAndroid Build Coastguard Worker               "} block0["
484*8975f5c5SAndroid Build Coastguard Worker            << numUniformBlocks
485*8975f5c5SAndroid Build Coastguard Worker            << "];\n"
486*8975f5c5SAndroid Build Coastguard Worker               "layout (triangles) in;\n"
487*8975f5c5SAndroid Build Coastguard Worker               "layout (points, max_vertices = 1) out;\n"
488*8975f5c5SAndroid Build Coastguard Worker               "void main()\n"
489*8975f5c5SAndroid Build Coastguard Worker               "{\n"
490*8975f5c5SAndroid Build Coastguard Worker               "    gl_Position = gl_in[0].gl_Position;\n";
491*8975f5c5SAndroid Build Coastguard Worker 
492*8975f5c5SAndroid Build Coastguard Worker     for (GLint i = 0; i < numUniformBlocks; ++i)
493*8975f5c5SAndroid Build Coastguard Worker     {
494*8975f5c5SAndroid Build Coastguard Worker         stream << "    gl_Position += block0[" << i << "].value1;\n";
495*8975f5c5SAndroid Build Coastguard Worker     }
496*8975f5c5SAndroid Build Coastguard Worker     stream << "    EmitVertex();\n"
497*8975f5c5SAndroid Build Coastguard Worker               "}\n";
498*8975f5c5SAndroid Build Coastguard Worker 
499*8975f5c5SAndroid Build Coastguard Worker     GLuint program = CompileProgramWithGS(essl31_shaders::vs::Simple(), stream.str().c_str(),
500*8975f5c5SAndroid Build Coastguard Worker                                           essl31_shaders::fs::Red());
501*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(0u, program);
502*8975f5c5SAndroid Build Coastguard Worker 
503*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
504*8975f5c5SAndroid Build Coastguard Worker }
505*8975f5c5SAndroid Build Coastguard Worker 
506*8975f5c5SAndroid Build Coastguard Worker // Verify that an link error occurs when the number of shader storage blocks in a geometry shader
507*8975f5c5SAndroid Build Coastguard Worker // exceeds MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT.
TEST_P(GeometryShaderTest,TooManyShaderStorageBlocks)508*8975f5c5SAndroid Build Coastguard Worker TEST_P(GeometryShaderTest, TooManyShaderStorageBlocks)
509*8975f5c5SAndroid Build Coastguard Worker {
510*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
511*8975f5c5SAndroid Build Coastguard Worker 
512*8975f5c5SAndroid Build Coastguard Worker     GLint maxGeometryShaderStorageBlocks = 0;
513*8975f5c5SAndroid Build Coastguard Worker     glGetIntegerv(GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT, &maxGeometryShaderStorageBlocks);
514*8975f5c5SAndroid Build Coastguard Worker 
515*8975f5c5SAndroid Build Coastguard Worker     GLint numSSBOs = maxGeometryShaderStorageBlocks + 1;
516*8975f5c5SAndroid Build Coastguard Worker     std::ostringstream stream;
517*8975f5c5SAndroid Build Coastguard Worker     stream << "#version 310 es\n"
518*8975f5c5SAndroid Build Coastguard Worker               "#extension GL_EXT_geometry_shader : require\n"
519*8975f5c5SAndroid Build Coastguard Worker               "buffer ssbo\n"
520*8975f5c5SAndroid Build Coastguard Worker               "{\n"
521*8975f5c5SAndroid Build Coastguard Worker               "    vec4 value1;\n"
522*8975f5c5SAndroid Build Coastguard Worker               "} block0["
523*8975f5c5SAndroid Build Coastguard Worker            << numSSBOs
524*8975f5c5SAndroid Build Coastguard Worker            << "];\n"
525*8975f5c5SAndroid Build Coastguard Worker               "layout (triangles) in;\n"
526*8975f5c5SAndroid Build Coastguard Worker               "layout (points, max_vertices = 1) out;\n"
527*8975f5c5SAndroid Build Coastguard Worker               "void main()\n"
528*8975f5c5SAndroid Build Coastguard Worker               "{\n"
529*8975f5c5SAndroid Build Coastguard Worker               "    gl_Position = gl_in[0].gl_Position;\n";
530*8975f5c5SAndroid Build Coastguard Worker 
531*8975f5c5SAndroid Build Coastguard Worker     for (GLint i = 0; i < numSSBOs; ++i)
532*8975f5c5SAndroid Build Coastguard Worker     {
533*8975f5c5SAndroid Build Coastguard Worker         stream << "    gl_Position += block0[" << i << "].value1;\n";
534*8975f5c5SAndroid Build Coastguard Worker     }
535*8975f5c5SAndroid Build Coastguard Worker     stream << "    EmitVertex();\n"
536*8975f5c5SAndroid Build Coastguard Worker               "}\n";
537*8975f5c5SAndroid Build Coastguard Worker 
538*8975f5c5SAndroid Build Coastguard Worker     GLuint program = CompileProgramWithGS(essl31_shaders::vs::Simple(), stream.str().c_str(),
539*8975f5c5SAndroid Build Coastguard Worker                                           essl31_shaders::fs::Red());
540*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(0u, program);
541*8975f5c5SAndroid Build Coastguard Worker 
542*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
543*8975f5c5SAndroid Build Coastguard Worker }
544*8975f5c5SAndroid Build Coastguard Worker 
545*8975f5c5SAndroid Build Coastguard Worker // Verify that an link error occurs when the definition of a unform block in the vertex shader is
546*8975f5c5SAndroid Build Coastguard Worker // different from that in a geometry shader.
TEST_P(GeometryShaderTest,UniformBlockMismatchBetweenVertexAndGeometryShader)547*8975f5c5SAndroid Build Coastguard Worker TEST_P(GeometryShaderTest, UniformBlockMismatchBetweenVertexAndGeometryShader)
548*8975f5c5SAndroid Build Coastguard Worker {
549*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
550*8975f5c5SAndroid Build Coastguard Worker 
551*8975f5c5SAndroid Build Coastguard Worker     constexpr char kVS[] = R"(#version 310 es
552*8975f5c5SAndroid Build Coastguard Worker uniform ubo
553*8975f5c5SAndroid Build Coastguard Worker {
554*8975f5c5SAndroid Build Coastguard Worker     vec4 uniform_value_vert;
555*8975f5c5SAndroid Build Coastguard Worker } block0;
556*8975f5c5SAndroid Build Coastguard Worker in vec4 vertex_in;
557*8975f5c5SAndroid Build Coastguard Worker out vec4 vertex_out;
558*8975f5c5SAndroid Build Coastguard Worker void main()
559*8975f5c5SAndroid Build Coastguard Worker {
560*8975f5c5SAndroid Build Coastguard Worker     gl_Position = vertex_in;
561*8975f5c5SAndroid Build Coastguard Worker     vertex_out = block0.uniform_value_vert;
562*8975f5c5SAndroid Build Coastguard Worker })";
563*8975f5c5SAndroid Build Coastguard Worker 
564*8975f5c5SAndroid Build Coastguard Worker     constexpr char kGS[] = R"(#version 310 es
565*8975f5c5SAndroid Build Coastguard Worker #extension GL_EXT_geometry_shader : require
566*8975f5c5SAndroid Build Coastguard Worker uniform ubo
567*8975f5c5SAndroid Build Coastguard Worker {
568*8975f5c5SAndroid Build Coastguard Worker     vec4 uniform_value_geom;
569*8975f5c5SAndroid Build Coastguard Worker } block0;
570*8975f5c5SAndroid Build Coastguard Worker layout (triangles) in;
571*8975f5c5SAndroid Build Coastguard Worker layout (points, max_vertices = 1) out;
572*8975f5c5SAndroid Build Coastguard Worker in vec4 vertex_out[];
573*8975f5c5SAndroid Build Coastguard Worker void main()
574*8975f5c5SAndroid Build Coastguard Worker {
575*8975f5c5SAndroid Build Coastguard Worker     gl_Position = gl_in[0].gl_Position + vertex_out[0];
576*8975f5c5SAndroid Build Coastguard Worker     gl_Position += block0.uniform_value_geom;
577*8975f5c5SAndroid Build Coastguard Worker     EmitVertex();
578*8975f5c5SAndroid Build Coastguard Worker })";
579*8975f5c5SAndroid Build Coastguard Worker 
580*8975f5c5SAndroid Build Coastguard Worker     GLuint program = CompileProgramWithGS(kVS, kGS, essl31_shaders::fs::Red());
581*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(0u, program);
582*8975f5c5SAndroid Build Coastguard Worker 
583*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
584*8975f5c5SAndroid Build Coastguard Worker }
585*8975f5c5SAndroid Build Coastguard Worker 
586*8975f5c5SAndroid Build Coastguard Worker // Verify that an link error occurs when the definition of a shader storage block in the geometry
587*8975f5c5SAndroid Build Coastguard Worker // shader is different from that in a fragment shader.
TEST_P(GeometryShaderTest,ShaderStorageBlockMismatchBetweenGeometryAndFragmentShader)588*8975f5c5SAndroid Build Coastguard Worker TEST_P(GeometryShaderTest, ShaderStorageBlockMismatchBetweenGeometryAndFragmentShader)
589*8975f5c5SAndroid Build Coastguard Worker {
590*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
591*8975f5c5SAndroid Build Coastguard Worker 
592*8975f5c5SAndroid Build Coastguard Worker     GLint maxGeometryShaderStorageBlocks = 0;
593*8975f5c5SAndroid Build Coastguard Worker     glGetIntegerv(GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT, &maxGeometryShaderStorageBlocks);
594*8975f5c5SAndroid Build Coastguard Worker 
595*8975f5c5SAndroid Build Coastguard Worker     // The minimun value of MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT can be 0.
596*8975f5c5SAndroid Build Coastguard Worker     // [EXT_geometry_shader] Table 20.43gs
597*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(maxGeometryShaderStorageBlocks == 0);
598*8975f5c5SAndroid Build Coastguard Worker 
599*8975f5c5SAndroid Build Coastguard Worker     GLint maxFragmentShaderStorageBlocks = 0;
600*8975f5c5SAndroid Build Coastguard Worker     glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &maxFragmentShaderStorageBlocks);
601*8975f5c5SAndroid Build Coastguard Worker 
602*8975f5c5SAndroid Build Coastguard Worker     // The minimun value of MAX_FRAGMENT_SHADER_STORAGE_BLOCKS can be 0.
603*8975f5c5SAndroid Build Coastguard Worker     // [OpenGL ES 3.1] Table 20.44
604*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(maxFragmentShaderStorageBlocks == 0);
605*8975f5c5SAndroid Build Coastguard Worker 
606*8975f5c5SAndroid Build Coastguard Worker     constexpr char kGS[] = R"(#version 310 es
607*8975f5c5SAndroid Build Coastguard Worker #extension GL_EXT_geometry_shader : require
608*8975f5c5SAndroid Build Coastguard Worker buffer ssbo
609*8975f5c5SAndroid Build Coastguard Worker {
610*8975f5c5SAndroid Build Coastguard Worker     vec4 ssbo_value;
611*8975f5c5SAndroid Build Coastguard Worker } block0;
612*8975f5c5SAndroid Build Coastguard Worker layout (triangles) in;
613*8975f5c5SAndroid Build Coastguard Worker layout (points, max_vertices = 1) out;
614*8975f5c5SAndroid Build Coastguard Worker void main()
615*8975f5c5SAndroid Build Coastguard Worker {
616*8975f5c5SAndroid Build Coastguard Worker     gl_Position = gl_in[0].gl_Position + block0.ssbo_value;
617*8975f5c5SAndroid Build Coastguard Worker     EmitVertex();
618*8975f5c5SAndroid Build Coastguard Worker })";
619*8975f5c5SAndroid Build Coastguard Worker 
620*8975f5c5SAndroid Build Coastguard Worker     constexpr char kFS[] = R"(#version 310 es
621*8975f5c5SAndroid Build Coastguard Worker precision highp float;
622*8975f5c5SAndroid Build Coastguard Worker buffer ssbo
623*8975f5c5SAndroid Build Coastguard Worker {
624*8975f5c5SAndroid Build Coastguard Worker     vec3 ssbo_value;
625*8975f5c5SAndroid Build Coastguard Worker } block0;
626*8975f5c5SAndroid Build Coastguard Worker layout (location = 0) out vec4 output_color;
627*8975f5c5SAndroid Build Coastguard Worker void main()
628*8975f5c5SAndroid Build Coastguard Worker {
629*8975f5c5SAndroid Build Coastguard Worker     output_color = vec4(block0.ssbo_value, 1);
630*8975f5c5SAndroid Build Coastguard Worker })";
631*8975f5c5SAndroid Build Coastguard Worker 
632*8975f5c5SAndroid Build Coastguard Worker     GLuint program = CompileProgramWithGS(essl31_shaders::vs::Simple(), kGS, kFS);
633*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(0u, program);
634*8975f5c5SAndroid Build Coastguard Worker 
635*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
636*8975f5c5SAndroid Build Coastguard Worker }
637*8975f5c5SAndroid Build Coastguard Worker 
638*8975f5c5SAndroid Build Coastguard Worker // Verify GL_REFERENCED_BY_GEOMETRY_SHADER_EXT cannot be used on platforms that don't support
639*8975f5c5SAndroid Build Coastguard Worker // EXT_geometry_shader, or we will get an INVALID_ENUM error.
TEST_P(GeometryShaderTest,ReferencedByGeometryShaderWithoutExtensionEnabled)640*8975f5c5SAndroid Build Coastguard Worker TEST_P(GeometryShaderTest, ReferencedByGeometryShaderWithoutExtensionEnabled)
641*8975f5c5SAndroid Build Coastguard Worker {
642*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_EXT_geometry_shader"));
643*8975f5c5SAndroid Build Coastguard Worker 
644*8975f5c5SAndroid Build Coastguard Worker     constexpr char kFS[] = R"(#version 310 es
645*8975f5c5SAndroid Build Coastguard Worker precision highp float;
646*8975f5c5SAndroid Build Coastguard Worker uniform vec4 color;
647*8975f5c5SAndroid Build Coastguard Worker layout(location = 0) out vec4 oColor;
648*8975f5c5SAndroid Build Coastguard Worker void main()
649*8975f5c5SAndroid Build Coastguard Worker {
650*8975f5c5SAndroid Build Coastguard Worker     oColor = color;
651*8975f5c5SAndroid Build Coastguard Worker })";
652*8975f5c5SAndroid Build Coastguard Worker 
653*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
654*8975f5c5SAndroid Build Coastguard Worker 
655*8975f5c5SAndroid Build Coastguard Worker     const GLuint index = glGetProgramResourceIndex(program, GL_UNIFORM, "color");
656*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
657*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(GL_INVALID_INDEX, index);
658*8975f5c5SAndroid Build Coastguard Worker 
659*8975f5c5SAndroid Build Coastguard Worker     constexpr GLenum kProps[]    = {GL_REFERENCED_BY_GEOMETRY_SHADER_EXT};
660*8975f5c5SAndroid Build Coastguard Worker     constexpr GLsizei kPropCount = static_cast<GLsizei>(ArraySize(kProps));
661*8975f5c5SAndroid Build Coastguard Worker     GLint params[ArraySize(kProps)];
662*8975f5c5SAndroid Build Coastguard Worker     GLsizei length;
663*8975f5c5SAndroid Build Coastguard Worker 
664*8975f5c5SAndroid Build Coastguard Worker     glGetProgramResourceiv(program, GL_UNIFORM, index, kPropCount, kProps, kPropCount, &length,
665*8975f5c5SAndroid Build Coastguard Worker                            params);
666*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_ENUM);
667*8975f5c5SAndroid Build Coastguard Worker }
668*8975f5c5SAndroid Build Coastguard Worker 
669*8975f5c5SAndroid Build Coastguard Worker // Verify GL_REFERENCED_BY_GEOMETRY_SHADER_EXT can work correctly on platforms that support
670*8975f5c5SAndroid Build Coastguard Worker // EXT_geometry_shader.
TEST_P(GeometryShaderTest,ReferencedByGeometryShader)671*8975f5c5SAndroid Build Coastguard Worker TEST_P(GeometryShaderTest, ReferencedByGeometryShader)
672*8975f5c5SAndroid Build Coastguard Worker {
673*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
674*8975f5c5SAndroid Build Coastguard Worker 
675*8975f5c5SAndroid Build Coastguard Worker     constexpr char kVS[] = R"(#version 310 es
676*8975f5c5SAndroid Build Coastguard Worker precision highp float;
677*8975f5c5SAndroid Build Coastguard Worker layout(location = 0) in highp vec4 position;
678*8975f5c5SAndroid Build Coastguard Worker void main()
679*8975f5c5SAndroid Build Coastguard Worker {
680*8975f5c5SAndroid Build Coastguard Worker     gl_Position = position;
681*8975f5c5SAndroid Build Coastguard Worker })";
682*8975f5c5SAndroid Build Coastguard Worker 
683*8975f5c5SAndroid Build Coastguard Worker     constexpr char kGS[] = R"(#version 310 es
684*8975f5c5SAndroid Build Coastguard Worker #extension GL_EXT_geometry_shader : require
685*8975f5c5SAndroid Build Coastguard Worker layout (binding = 3) uniform ubo0
686*8975f5c5SAndroid Build Coastguard Worker {
687*8975f5c5SAndroid Build Coastguard Worker     vec4 ubo0_location;
688*8975f5c5SAndroid Build Coastguard Worker } block0;
689*8975f5c5SAndroid Build Coastguard Worker layout (binding = 4) uniform ubo1
690*8975f5c5SAndroid Build Coastguard Worker {
691*8975f5c5SAndroid Build Coastguard Worker     vec4 ubo1_location;
692*8975f5c5SAndroid Build Coastguard Worker } block1;
693*8975f5c5SAndroid Build Coastguard Worker uniform vec4 u_color;
694*8975f5c5SAndroid Build Coastguard Worker layout (triangles) in;
695*8975f5c5SAndroid Build Coastguard Worker layout (points, max_vertices = 1) out;
696*8975f5c5SAndroid Build Coastguard Worker out vec4 gs_out;
697*8975f5c5SAndroid Build Coastguard Worker void main()
698*8975f5c5SAndroid Build Coastguard Worker {
699*8975f5c5SAndroid Build Coastguard Worker     gl_Position = gl_in[0].gl_Position;
700*8975f5c5SAndroid Build Coastguard Worker     gl_Position += block0.ubo0_location + block1.ubo1_location;
701*8975f5c5SAndroid Build Coastguard Worker     gs_out = u_color;
702*8975f5c5SAndroid Build Coastguard Worker     EmitVertex();
703*8975f5c5SAndroid Build Coastguard Worker })";
704*8975f5c5SAndroid Build Coastguard Worker 
705*8975f5c5SAndroid Build Coastguard Worker     constexpr char kFS[] = R"(#version 310 es
706*8975f5c5SAndroid Build Coastguard Worker precision highp float;
707*8975f5c5SAndroid Build Coastguard Worker in vec4 gs_out;
708*8975f5c5SAndroid Build Coastguard Worker layout(location = 0) out vec4 oColor;
709*8975f5c5SAndroid Build Coastguard Worker void main()
710*8975f5c5SAndroid Build Coastguard Worker {
711*8975f5c5SAndroid Build Coastguard Worker     oColor = gs_out;
712*8975f5c5SAndroid Build Coastguard Worker })";
713*8975f5c5SAndroid Build Coastguard Worker 
714*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_PROGRAM_WITH_GS(program, kVS, kGS, kFS);
715*8975f5c5SAndroid Build Coastguard Worker 
716*8975f5c5SAndroid Build Coastguard Worker     constexpr GLenum kProps[]    = {GL_REFERENCED_BY_GEOMETRY_SHADER_EXT};
717*8975f5c5SAndroid Build Coastguard Worker     constexpr GLsizei kPropCount = static_cast<GLsizei>(ArraySize(kProps));
718*8975f5c5SAndroid Build Coastguard Worker     std::array<GLint, ArraySize(kProps)> params;
719*8975f5c5SAndroid Build Coastguard Worker     GLsizei length;
720*8975f5c5SAndroid Build Coastguard Worker 
721*8975f5c5SAndroid Build Coastguard Worker     params.fill(1);
722*8975f5c5SAndroid Build Coastguard Worker     GLuint index = glGetProgramResourceIndex(program, GL_PROGRAM_INPUT, "position");
723*8975f5c5SAndroid Build Coastguard Worker     glGetProgramResourceiv(program, GL_PROGRAM_INPUT, index, kPropCount, kProps, kPropCount,
724*8975f5c5SAndroid Build Coastguard Worker                            &length, params.data());
725*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
726*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(0, params[0]);
727*8975f5c5SAndroid Build Coastguard Worker 
728*8975f5c5SAndroid Build Coastguard Worker     params.fill(1);
729*8975f5c5SAndroid Build Coastguard Worker     index = glGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, "oColor");
730*8975f5c5SAndroid Build Coastguard Worker     glGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, index, kPropCount, kProps, kPropCount,
731*8975f5c5SAndroid Build Coastguard Worker                            &length, params.data());
732*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
733*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(0, params[0]);
734*8975f5c5SAndroid Build Coastguard Worker 
735*8975f5c5SAndroid Build Coastguard Worker     index = glGetProgramResourceIndex(program, GL_UNIFORM, "u_color");
736*8975f5c5SAndroid Build Coastguard Worker     glGetProgramResourceiv(program, GL_UNIFORM, index, kPropCount, kProps, kPropCount, &length,
737*8975f5c5SAndroid Build Coastguard Worker                            params.data());
738*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
739*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(1, params[0]);
740*8975f5c5SAndroid Build Coastguard Worker 
741*8975f5c5SAndroid Build Coastguard Worker     params.fill(0);
742*8975f5c5SAndroid Build Coastguard Worker     index = glGetProgramResourceIndex(program, GL_UNIFORM_BLOCK, "ubo1");
743*8975f5c5SAndroid Build Coastguard Worker     glGetProgramResourceiv(program, GL_UNIFORM_BLOCK, index, kPropCount, kProps, kPropCount,
744*8975f5c5SAndroid Build Coastguard Worker                            &length, params.data());
745*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
746*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(1, params[0]);
747*8975f5c5SAndroid Build Coastguard Worker 
748*8975f5c5SAndroid Build Coastguard Worker     GLint maxGeometryShaderStorageBlocks = 0;
749*8975f5c5SAndroid Build Coastguard Worker     glGetIntegerv(GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT, &maxGeometryShaderStorageBlocks);
750*8975f5c5SAndroid Build Coastguard Worker     // The maximum number of shader storage blocks in a geometry shader can be 0.
751*8975f5c5SAndroid Build Coastguard Worker     // [EXT_geometry_shader] Table 20.43gs
752*8975f5c5SAndroid Build Coastguard Worker     if (maxGeometryShaderStorageBlocks > 0)
753*8975f5c5SAndroid Build Coastguard Worker     {
754*8975f5c5SAndroid Build Coastguard Worker         constexpr char kGSWithSSBO[] = R"(#version 310 es
755*8975f5c5SAndroid Build Coastguard Worker #extension GL_EXT_geometry_shader : require
756*8975f5c5SAndroid Build Coastguard Worker layout (binding = 2) buffer ssbo
757*8975f5c5SAndroid Build Coastguard Worker {
758*8975f5c5SAndroid Build Coastguard Worker     vec4 ssbo_value;
759*8975f5c5SAndroid Build Coastguard Worker } block0;
760*8975f5c5SAndroid Build Coastguard Worker layout (triangles) in;
761*8975f5c5SAndroid Build Coastguard Worker layout (points, max_vertices = 1) out;
762*8975f5c5SAndroid Build Coastguard Worker out vec4 gs_out;
763*8975f5c5SAndroid Build Coastguard Worker void main()
764*8975f5c5SAndroid Build Coastguard Worker {
765*8975f5c5SAndroid Build Coastguard Worker     gl_Position = gl_in[0].gl_Position + block0.ssbo_value;
766*8975f5c5SAndroid Build Coastguard Worker     gs_out = block0.ssbo_value;
767*8975f5c5SAndroid Build Coastguard Worker     EmitVertex();
768*8975f5c5SAndroid Build Coastguard Worker })";
769*8975f5c5SAndroid Build Coastguard Worker 
770*8975f5c5SAndroid Build Coastguard Worker         ANGLE_GL_PROGRAM_WITH_GS(programWithSSBO, kVS, kGSWithSSBO, kFS);
771*8975f5c5SAndroid Build Coastguard Worker 
772*8975f5c5SAndroid Build Coastguard Worker         params.fill(0);
773*8975f5c5SAndroid Build Coastguard Worker         index = glGetProgramResourceIndex(programWithSSBO, GL_SHADER_STORAGE_BLOCK, "ssbo");
774*8975f5c5SAndroid Build Coastguard Worker         glGetProgramResourceiv(programWithSSBO, GL_SHADER_STORAGE_BLOCK, index, kPropCount, kProps,
775*8975f5c5SAndroid Build Coastguard Worker                                kPropCount, &length, params.data());
776*8975f5c5SAndroid Build Coastguard Worker         EXPECT_GL_NO_ERROR();
777*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EQ(1, params[0]);
778*8975f5c5SAndroid Build Coastguard Worker 
779*8975f5c5SAndroid Build Coastguard Worker         params.fill(0);
780*8975f5c5SAndroid Build Coastguard Worker         index = glGetProgramResourceIndex(programWithSSBO, GL_BUFFER_VARIABLE, "ssbo.ssbo_value");
781*8975f5c5SAndroid Build Coastguard Worker         glGetProgramResourceiv(programWithSSBO, GL_BUFFER_VARIABLE, index, kPropCount, kProps,
782*8975f5c5SAndroid Build Coastguard Worker                                kPropCount, &length, params.data());
783*8975f5c5SAndroid Build Coastguard Worker         EXPECT_GL_NO_ERROR();
784*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EQ(1, params[0]);
785*8975f5c5SAndroid Build Coastguard Worker     }
786*8975f5c5SAndroid Build Coastguard Worker 
787*8975f5c5SAndroid Build Coastguard Worker     GLint maxGeometryAtomicCounterBuffers = 0;
788*8975f5c5SAndroid Build Coastguard Worker     glGetIntegerv(GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT, &maxGeometryAtomicCounterBuffers);
789*8975f5c5SAndroid Build Coastguard Worker     // The maximum number of atomic counter buffers in a geometry shader can be 0.
790*8975f5c5SAndroid Build Coastguard Worker     // [EXT_geometry_shader] Table 20.43gs
791*8975f5c5SAndroid Build Coastguard Worker     if (maxGeometryAtomicCounterBuffers > 0)
792*8975f5c5SAndroid Build Coastguard Worker     {
793*8975f5c5SAndroid Build Coastguard Worker         constexpr char kGSWithAtomicCounters[] = R"(#version 310 es
794*8975f5c5SAndroid Build Coastguard Worker #extension GL_EXT_geometry_shader : require
795*8975f5c5SAndroid Build Coastguard Worker layout(binding = 1, offset = 0) uniform atomic_uint gs_counter;
796*8975f5c5SAndroid Build Coastguard Worker layout (triangles) in;
797*8975f5c5SAndroid Build Coastguard Worker layout (points, max_vertices = 1) out;
798*8975f5c5SAndroid Build Coastguard Worker out vec4 gs_out;
799*8975f5c5SAndroid Build Coastguard Worker void main()
800*8975f5c5SAndroid Build Coastguard Worker {
801*8975f5c5SAndroid Build Coastguard Worker     atomicCounterIncrement(gs_counter);
802*8975f5c5SAndroid Build Coastguard Worker     gl_Position = gl_in[0].gl_Position;
803*8975f5c5SAndroid Build Coastguard Worker     gs_out = vec4(1.0, 0.0, 0.0, 1.0);
804*8975f5c5SAndroid Build Coastguard Worker     EmitVertex();
805*8975f5c5SAndroid Build Coastguard Worker })";
806*8975f5c5SAndroid Build Coastguard Worker 
807*8975f5c5SAndroid Build Coastguard Worker         ANGLE_GL_PROGRAM_WITH_GS(programWithAtomicCounter, kVS, kGSWithAtomicCounters, kFS);
808*8975f5c5SAndroid Build Coastguard Worker 
809*8975f5c5SAndroid Build Coastguard Worker         params.fill(0);
810*8975f5c5SAndroid Build Coastguard Worker         index = glGetProgramResourceIndex(programWithAtomicCounter, GL_UNIFORM, "gs_counter");
811*8975f5c5SAndroid Build Coastguard Worker         EXPECT_GL_NO_ERROR();
812*8975f5c5SAndroid Build Coastguard Worker         glGetProgramResourceiv(programWithAtomicCounter, GL_ATOMIC_COUNTER_BUFFER, index,
813*8975f5c5SAndroid Build Coastguard Worker                                kPropCount, kProps, kPropCount, &length, params.data());
814*8975f5c5SAndroid Build Coastguard Worker         EXPECT_GL_NO_ERROR();
815*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EQ(1, params[0]);
816*8975f5c5SAndroid Build Coastguard Worker     }
817*8975f5c5SAndroid Build Coastguard Worker }
818*8975f5c5SAndroid Build Coastguard Worker 
callFramebufferTextureAPI(APIExtensionVersion usedExtension,GLenum target,GLenum attachment,GLuint texture,GLint level)819*8975f5c5SAndroid Build Coastguard Worker void GeometryShaderTest::callFramebufferTextureAPI(APIExtensionVersion usedExtension,
820*8975f5c5SAndroid Build Coastguard Worker                                                    GLenum target,
821*8975f5c5SAndroid Build Coastguard Worker                                                    GLenum attachment,
822*8975f5c5SAndroid Build Coastguard Worker                                                    GLuint texture,
823*8975f5c5SAndroid Build Coastguard Worker                                                    GLint level)
824*8975f5c5SAndroid Build Coastguard Worker {
825*8975f5c5SAndroid Build Coastguard Worker     ASSERT(usedExtension == APIExtensionVersion::EXT || usedExtension == APIExtensionVersion::OES ||
826*8975f5c5SAndroid Build Coastguard Worker            usedExtension == APIExtensionVersion::Core);
827*8975f5c5SAndroid Build Coastguard Worker     if (usedExtension == APIExtensionVersion::EXT)
828*8975f5c5SAndroid Build Coastguard Worker     {
829*8975f5c5SAndroid Build Coastguard Worker         glFramebufferTextureEXT(target, attachment, texture, level);
830*8975f5c5SAndroid Build Coastguard Worker     }
831*8975f5c5SAndroid Build Coastguard Worker     else if (usedExtension == APIExtensionVersion::OES)
832*8975f5c5SAndroid Build Coastguard Worker     {
833*8975f5c5SAndroid Build Coastguard Worker         glFramebufferTextureOES(target, attachment, texture, level);
834*8975f5c5SAndroid Build Coastguard Worker     }
835*8975f5c5SAndroid Build Coastguard Worker     else
836*8975f5c5SAndroid Build Coastguard Worker     {
837*8975f5c5SAndroid Build Coastguard Worker         glFramebufferTexture(target, attachment, texture, level);
838*8975f5c5SAndroid Build Coastguard Worker     }
839*8975f5c5SAndroid Build Coastguard Worker }
840*8975f5c5SAndroid Build Coastguard Worker 
testNegativeFramebufferTexture(APIExtensionVersion usedExtension)841*8975f5c5SAndroid Build Coastguard Worker void GeometryShaderTest::testNegativeFramebufferTexture(APIExtensionVersion usedExtension)
842*8975f5c5SAndroid Build Coastguard Worker {
843*8975f5c5SAndroid Build Coastguard Worker     ASSERT(usedExtension == APIExtensionVersion::EXT || usedExtension == APIExtensionVersion::OES ||
844*8975f5c5SAndroid Build Coastguard Worker            usedExtension == APIExtensionVersion::Core);
845*8975f5c5SAndroid Build Coastguard Worker 
846*8975f5c5SAndroid Build Coastguard Worker     GLFramebuffer fbo;
847*8975f5c5SAndroid Build Coastguard Worker     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
848*8975f5c5SAndroid Build Coastguard Worker 
849*8975f5c5SAndroid Build Coastguard Worker     GLTexture tex;
850*8975f5c5SAndroid Build Coastguard Worker     glBindTexture(GL_TEXTURE_3D, tex);
851*8975f5c5SAndroid Build Coastguard Worker     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 32, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
852*8975f5c5SAndroid Build Coastguard Worker 
853*8975f5c5SAndroid Build Coastguard Worker     // [EXT_geometry_shader] Section 9.2.8, "Attaching Texture Images to a Framebuffer"
854*8975f5c5SAndroid Build Coastguard Worker     // An INVALID_ENUM error is generated if <target> is not DRAW_FRAMEBUFFER, READ_FRAMEBUFFER, or
855*8975f5c5SAndroid Build Coastguard Worker     // FRAMEBUFFER.
856*8975f5c5SAndroid Build Coastguard Worker     callFramebufferTextureAPI(usedExtension, GL_TEXTURE_2D, GL_COLOR_ATTACHMENT0, tex, 0);
857*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_ENUM);
858*8975f5c5SAndroid Build Coastguard Worker 
859*8975f5c5SAndroid Build Coastguard Worker     // An INVALID_ENUM error is generated if <attachment> is not one of the attachments in Table
860*8975f5c5SAndroid Build Coastguard Worker     // 9.1.
861*8975f5c5SAndroid Build Coastguard Worker     callFramebufferTextureAPI(usedExtension, GL_FRAMEBUFFER, GL_TEXTURE_2D, tex, 0);
862*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_ENUM);
863*8975f5c5SAndroid Build Coastguard Worker 
864*8975f5c5SAndroid Build Coastguard Worker     // An INVALID_OPERATION error is generated if zero is bound to <target>.
865*8975f5c5SAndroid Build Coastguard Worker     glBindFramebuffer(GL_FRAMEBUFFER, 0);
866*8975f5c5SAndroid Build Coastguard Worker     callFramebufferTextureAPI(usedExtension, GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0);
867*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
868*8975f5c5SAndroid Build Coastguard Worker 
869*8975f5c5SAndroid Build Coastguard Worker     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
870*8975f5c5SAndroid Build Coastguard Worker 
871*8975f5c5SAndroid Build Coastguard Worker     // An INVALID_VALUE error is generated if <texture> is not the name of a texture object, or if
872*8975f5c5SAndroid Build Coastguard Worker     // <level> is not a supported texture level for <texture>.
873*8975f5c5SAndroid Build Coastguard Worker     GLuint tex2;
874*8975f5c5SAndroid Build Coastguard Worker     glGenTextures(1, &tex2);
875*8975f5c5SAndroid Build Coastguard Worker     glDeleteTextures(1, &tex2);
876*8975f5c5SAndroid Build Coastguard Worker     ASSERT_FALSE(glIsTexture(tex2));
877*8975f5c5SAndroid Build Coastguard Worker     callFramebufferTextureAPI(usedExtension, GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex2, 0);
878*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_VALUE);
879*8975f5c5SAndroid Build Coastguard Worker 
880*8975f5c5SAndroid Build Coastguard Worker     GLint max3DSize;
881*8975f5c5SAndroid Build Coastguard Worker     glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &max3DSize);
882*8975f5c5SAndroid Build Coastguard Worker     GLint max3DLevel = static_cast<GLint>(std::log2(max3DSize));
883*8975f5c5SAndroid Build Coastguard Worker     callFramebufferTextureAPI(usedExtension, GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex,
884*8975f5c5SAndroid Build Coastguard Worker                               max3DLevel + 1);
885*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_VALUE);
886*8975f5c5SAndroid Build Coastguard Worker }
887*8975f5c5SAndroid Build Coastguard Worker 
888*8975f5c5SAndroid Build Coastguard Worker // Verify that correct errors are reported when we use illegal parameters in FramebufferTextureEXT.
TEST_P(GeometryShaderTest,NegativeFramebufferTextureEXT)889*8975f5c5SAndroid Build Coastguard Worker TEST_P(GeometryShaderTest, NegativeFramebufferTextureEXT)
890*8975f5c5SAndroid Build Coastguard Worker {
891*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
892*8975f5c5SAndroid Build Coastguard Worker     testNegativeFramebufferTexture(APIExtensionVersion::EXT);
893*8975f5c5SAndroid Build Coastguard Worker }
894*8975f5c5SAndroid Build Coastguard Worker 
895*8975f5c5SAndroid Build Coastguard Worker // Verify that correct errors are reported when we use illegal parameters in FramebufferTextureOES.
TEST_P(GeometryShaderTest,NegativeFramebufferTextureOES)896*8975f5c5SAndroid Build Coastguard Worker TEST_P(GeometryShaderTest, NegativeFramebufferTextureOES)
897*8975f5c5SAndroid Build Coastguard Worker {
898*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_geometry_shader"));
899*8975f5c5SAndroid Build Coastguard Worker     testNegativeFramebufferTexture(APIExtensionVersion::OES);
900*8975f5c5SAndroid Build Coastguard Worker }
901*8975f5c5SAndroid Build Coastguard Worker 
902*8975f5c5SAndroid Build Coastguard Worker // Verify CheckFramebufferStatus can work correctly on layered depth and stencil attachments.
TEST_P(GeometryShaderTest,LayeredFramebufferCompletenessWithDepthAttachment)903*8975f5c5SAndroid Build Coastguard Worker TEST_P(GeometryShaderTest, LayeredFramebufferCompletenessWithDepthAttachment)
904*8975f5c5SAndroid Build Coastguard Worker {
905*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
906*8975f5c5SAndroid Build Coastguard Worker 
907*8975f5c5SAndroid Build Coastguard Worker     GLint maxFramebufferLayers;
908*8975f5c5SAndroid Build Coastguard Worker     glGetIntegerv(GL_MAX_FRAMEBUFFER_LAYERS_EXT, &maxFramebufferLayers);
909*8975f5c5SAndroid Build Coastguard Worker 
910*8975f5c5SAndroid Build Coastguard Worker     constexpr GLint kTexLayers = 2;
911*8975f5c5SAndroid Build Coastguard Worker     ASSERT_LT(kTexLayers, maxFramebufferLayers);
912*8975f5c5SAndroid Build Coastguard Worker 
913*8975f5c5SAndroid Build Coastguard Worker     GLTexture layeredColorTex;
914*8975f5c5SAndroid Build Coastguard Worker     glBindTexture(GL_TEXTURE_3D, layeredColorTex);
915*8975f5c5SAndroid Build Coastguard Worker     glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 32, 32, kTexLayers, 0, GL_RGBA, GL_UNSIGNED_BYTE,
916*8975f5c5SAndroid Build Coastguard Worker                  nullptr);
917*8975f5c5SAndroid Build Coastguard Worker 
918*8975f5c5SAndroid Build Coastguard Worker     // [EXT_geometry_shader] section 9.4.1, "Framebuffer Completeness"
919*8975f5c5SAndroid Build Coastguard Worker     // If any framebuffer attachment is layered, all populated attachments must be layered.
920*8975f5c5SAndroid Build Coastguard Worker     // {FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT }
921*8975f5c5SAndroid Build Coastguard Worker     GLTexture layeredDepthStencilTex;
922*8975f5c5SAndroid Build Coastguard Worker     glBindTexture(GL_TEXTURE_2D_ARRAY, layeredDepthStencilTex);
923*8975f5c5SAndroid Build Coastguard Worker     glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH24_STENCIL8, 32, 32, kTexLayers, 0,
924*8975f5c5SAndroid Build Coastguard Worker                  GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, nullptr);
925*8975f5c5SAndroid Build Coastguard Worker 
926*8975f5c5SAndroid Build Coastguard Worker     // 1. Color attachment is layered, while depth attachment is not layered.
927*8975f5c5SAndroid Build Coastguard Worker     GLFramebuffer fbo1;
928*8975f5c5SAndroid Build Coastguard Worker     glBindFramebuffer(GL_FRAMEBUFFER, fbo1);
929*8975f5c5SAndroid Build Coastguard Worker     glFramebufferTextureEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, layeredColorTex, 0);
930*8975f5c5SAndroid Build Coastguard Worker     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, layeredDepthStencilTex, 0, 0);
931*8975f5c5SAndroid Build Coastguard Worker     GLenum status1 = glCheckFramebufferStatus(GL_FRAMEBUFFER);
932*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
933*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT, status1);
934*8975f5c5SAndroid Build Coastguard Worker 
935*8975f5c5SAndroid Build Coastguard Worker     // 2. Color attachment is not layered, while depth attachment is layered.
936*8975f5c5SAndroid Build Coastguard Worker     GLFramebuffer fbo2;
937*8975f5c5SAndroid Build Coastguard Worker     glBindFramebuffer(GL_FRAMEBUFFER, fbo2);
938*8975f5c5SAndroid Build Coastguard Worker     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, layeredColorTex, 0, 0);
939*8975f5c5SAndroid Build Coastguard Worker     glFramebufferTextureEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, layeredDepthStencilTex, 0);
940*8975f5c5SAndroid Build Coastguard Worker     GLenum status2 = glCheckFramebufferStatus(GL_FRAMEBUFFER);
941*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
942*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT, status2);
943*8975f5c5SAndroid Build Coastguard Worker 
944*8975f5c5SAndroid Build Coastguard Worker     // 3. Color attachment is not layered, while stencil attachment is layered.
945*8975f5c5SAndroid Build Coastguard Worker     GLFramebuffer fbo3;
946*8975f5c5SAndroid Build Coastguard Worker     glBindFramebuffer(GL_FRAMEBUFFER, fbo3);
947*8975f5c5SAndroid Build Coastguard Worker     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, layeredColorTex, 0, 0);
948*8975f5c5SAndroid Build Coastguard Worker     glFramebufferTextureEXT(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, layeredDepthStencilTex, 0);
949*8975f5c5SAndroid Build Coastguard Worker     GLenum status3 = glCheckFramebufferStatus(GL_FRAMEBUFFER);
950*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
951*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT, status3);
952*8975f5c5SAndroid Build Coastguard Worker 
953*8975f5c5SAndroid Build Coastguard Worker     // [EXT_geometry_shader] section 9.4.1, "Framebuffer Completeness"
954*8975f5c5SAndroid Build Coastguard Worker     // If <image> is a three-dimensional texture or a two-dimensional array texture and the
955*8975f5c5SAndroid Build Coastguard Worker     // attachment is layered, the depth or layer count, respectively, of the texture is less than or
956*8975f5c5SAndroid Build Coastguard Worker     // equal to the value of MAX_FRAMEBUFFER_LAYERS_EXT.
957*8975f5c5SAndroid Build Coastguard Worker     GLint maxArrayTextureLayers;
958*8975f5c5SAndroid Build Coastguard Worker     glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &maxArrayTextureLayers);
959*8975f5c5SAndroid Build Coastguard Worker     GLint depthTexLayer4 = maxFramebufferLayers + 1;
960*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(maxArrayTextureLayers < depthTexLayer4);
961*8975f5c5SAndroid Build Coastguard Worker 
962*8975f5c5SAndroid Build Coastguard Worker     // Use a depth attachment whose layer count exceeds MAX_FRAMEBUFFER_LAYERS
963*8975f5c5SAndroid Build Coastguard Worker     GLTexture depthTex4;
964*8975f5c5SAndroid Build Coastguard Worker     glBindTexture(GL_TEXTURE_2D_ARRAY, depthTex4);
965*8975f5c5SAndroid Build Coastguard Worker     glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH24_STENCIL8, 32, 32, depthTexLayer4, 0,
966*8975f5c5SAndroid Build Coastguard Worker                  GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, nullptr);
967*8975f5c5SAndroid Build Coastguard Worker     GLFramebuffer fbo4;
968*8975f5c5SAndroid Build Coastguard Worker     glBindFramebuffer(GL_FRAMEBUFFER, fbo4);
969*8975f5c5SAndroid Build Coastguard Worker     glFramebufferTextureEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTex4, 0);
970*8975f5c5SAndroid Build Coastguard Worker     GLenum status4 = glCheckFramebufferStatus(GL_FRAMEBUFFER);
971*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
972*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT, status4);
973*8975f5c5SAndroid Build Coastguard Worker }
974*8975f5c5SAndroid Build Coastguard Worker 
975*8975f5c5SAndroid Build Coastguard Worker // Verify correct errors can be reported when we use layered cube map attachments on a framebuffer.
TEST_P(GeometryShaderTest,NegativeLayeredFramebufferCompletenessWithCubeMapTextures)976*8975f5c5SAndroid Build Coastguard Worker TEST_P(GeometryShaderTest, NegativeLayeredFramebufferCompletenessWithCubeMapTextures)
977*8975f5c5SAndroid Build Coastguard Worker {
978*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
979*8975f5c5SAndroid Build Coastguard Worker 
980*8975f5c5SAndroid Build Coastguard Worker     GLTexture tex;
981*8975f5c5SAndroid Build Coastguard Worker     glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
982*8975f5c5SAndroid Build Coastguard Worker 
983*8975f5c5SAndroid Build Coastguard Worker     GLFramebuffer fbo;
984*8975f5c5SAndroid Build Coastguard Worker     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
985*8975f5c5SAndroid Build Coastguard Worker     glFramebufferTextureEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0);
986*8975f5c5SAndroid Build Coastguard Worker     GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
987*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
988*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT, status);
989*8975f5c5SAndroid Build Coastguard Worker 
990*8975f5c5SAndroid Build Coastguard Worker     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA8, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE,
991*8975f5c5SAndroid Build Coastguard Worker                  nullptr);
992*8975f5c5SAndroid Build Coastguard Worker     glFramebufferTextureEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0);
993*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
994*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT, status);
995*8975f5c5SAndroid Build Coastguard Worker }
996*8975f5c5SAndroid Build Coastguard Worker 
997*8975f5c5SAndroid Build Coastguard Worker // Verify that we can use default interpolation in the GS.
TEST_P(GeometryShaderTest,FlatQualifierNotRequired)998*8975f5c5SAndroid Build Coastguard Worker TEST_P(GeometryShaderTest, FlatQualifierNotRequired)
999*8975f5c5SAndroid Build Coastguard Worker {
1000*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
1001*8975f5c5SAndroid Build Coastguard Worker 
1002*8975f5c5SAndroid Build Coastguard Worker     constexpr char kGS[] = R"(#version 310 es
1003*8975f5c5SAndroid Build Coastguard Worker #extension GL_EXT_geometry_shader : require
1004*8975f5c5SAndroid Build Coastguard Worker layout(points) in;
1005*8975f5c5SAndroid Build Coastguard Worker layout(points, max_vertices=1) out;
1006*8975f5c5SAndroid Build Coastguard Worker 
1007*8975f5c5SAndroid Build Coastguard Worker in highp int target[];
1008*8975f5c5SAndroid Build Coastguard Worker highp uniform vec4 dummyZero; // Default value is vec4(0.0).
1009*8975f5c5SAndroid Build Coastguard Worker 
1010*8975f5c5SAndroid Build Coastguard Worker void main()
1011*8975f5c5SAndroid Build Coastguard Worker {
1012*8975f5c5SAndroid Build Coastguard Worker     highp vec4 retValue = dummyZero;
1013*8975f5c5SAndroid Build Coastguard Worker     retValue += vec4(float(target[0]));
1014*8975f5c5SAndroid Build Coastguard Worker     retValue += gl_in[0].gl_Position;
1015*8975f5c5SAndroid Build Coastguard Worker     gl_Position = retValue;
1016*8975f5c5SAndroid Build Coastguard Worker     EmitVertex();
1017*8975f5c5SAndroid Build Coastguard Worker })";
1018*8975f5c5SAndroid Build Coastguard Worker 
1019*8975f5c5SAndroid Build Coastguard Worker     GLuint geometryShader = CompileShader(GL_GEOMETRY_SHADER_EXT, kGS);
1020*8975f5c5SAndroid Build Coastguard Worker 
1021*8975f5c5SAndroid Build Coastguard Worker     EXPECT_NE(0u, geometryShader);
1022*8975f5c5SAndroid Build Coastguard Worker 
1023*8975f5c5SAndroid Build Coastguard Worker     GLuint programID = glCreateProgram();
1024*8975f5c5SAndroid Build Coastguard Worker     glAttachShader(programID, geometryShader);
1025*8975f5c5SAndroid Build Coastguard Worker 
1026*8975f5c5SAndroid Build Coastguard Worker     glDetachShader(programID, geometryShader);
1027*8975f5c5SAndroid Build Coastguard Worker     glDeleteShader(geometryShader);
1028*8975f5c5SAndroid Build Coastguard Worker     glDeleteProgram(programID);
1029*8975f5c5SAndroid Build Coastguard Worker 
1030*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1031*8975f5c5SAndroid Build Coastguard Worker }
1032*8975f5c5SAndroid Build Coastguard Worker 
setupLayeredFramebuffer(GLuint framebuffer,GLuint color0,GLuint color1,GLuint depthStencil,GLenum colorTarget,const GLColor & color0InitialColor,const GLColor & color1InitialColor,float depthInitialValue,GLint stencilInitialValue)1033*8975f5c5SAndroid Build Coastguard Worker void GeometryShaderTest::setupLayeredFramebuffer(GLuint framebuffer,
1034*8975f5c5SAndroid Build Coastguard Worker                                                  GLuint color0,
1035*8975f5c5SAndroid Build Coastguard Worker                                                  GLuint color1,
1036*8975f5c5SAndroid Build Coastguard Worker                                                  GLuint depthStencil,
1037*8975f5c5SAndroid Build Coastguard Worker                                                  GLenum colorTarget,
1038*8975f5c5SAndroid Build Coastguard Worker                                                  const GLColor &color0InitialColor,
1039*8975f5c5SAndroid Build Coastguard Worker                                                  const GLColor &color1InitialColor,
1040*8975f5c5SAndroid Build Coastguard Worker                                                  float depthInitialValue,
1041*8975f5c5SAndroid Build Coastguard Worker                                                  GLint stencilInitialValue)
1042*8975f5c5SAndroid Build Coastguard Worker {
1043*8975f5c5SAndroid Build Coastguard Worker     const uint32_t depthInitialValueUnorm   = static_cast<uint32_t>(depthInitialValue * 0xFFFFFF);
1044*8975f5c5SAndroid Build Coastguard Worker     const uint32_t depthStencilInitialValue = depthInitialValueUnorm << 8 | stencilInitialValue;
1045*8975f5c5SAndroid Build Coastguard Worker 
1046*8975f5c5SAndroid Build Coastguard Worker     const std::vector<GLColor> kColor0InitData(kWidth * kHeight * kColor0Layers,
1047*8975f5c5SAndroid Build Coastguard Worker                                                color0InitialColor);
1048*8975f5c5SAndroid Build Coastguard Worker     const std::vector<GLColor> kColor1InitData(kWidth * kHeight * kColor1Layers,
1049*8975f5c5SAndroid Build Coastguard Worker                                                color1InitialColor);
1050*8975f5c5SAndroid Build Coastguard Worker     const std::vector<uint32_t> kDepthStencilInitData(kWidth * kHeight * kDepthStencilLayers,
1051*8975f5c5SAndroid Build Coastguard Worker                                                       depthStencilInitialValue);
1052*8975f5c5SAndroid Build Coastguard Worker 
1053*8975f5c5SAndroid Build Coastguard Worker     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1054*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1055*8975f5c5SAndroid Build Coastguard Worker 
1056*8975f5c5SAndroid Build Coastguard Worker     glBindTexture(colorTarget, color0);
1057*8975f5c5SAndroid Build Coastguard Worker     glTexStorage3D(colorTarget, 1, GL_RGBA8, kWidth, kHeight, kColor0Layers);
1058*8975f5c5SAndroid Build Coastguard Worker     glTexSubImage3D(colorTarget, 0, 0, 0, 0, kWidth, kHeight, kColor0Layers, GL_RGBA,
1059*8975f5c5SAndroid Build Coastguard Worker                     GL_UNSIGNED_BYTE, kColor0InitData.data());
1060*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1061*8975f5c5SAndroid Build Coastguard Worker 
1062*8975f5c5SAndroid Build Coastguard Worker     glBindTexture(colorTarget, color1);
1063*8975f5c5SAndroid Build Coastguard Worker     glTexStorage3D(colorTarget, 1, GL_RGBA8, kWidth, kHeight, kColor1Layers);
1064*8975f5c5SAndroid Build Coastguard Worker     glTexSubImage3D(colorTarget, 0, 0, 0, 0, kWidth, kHeight, kColor1Layers, GL_RGBA,
1065*8975f5c5SAndroid Build Coastguard Worker                     GL_UNSIGNED_BYTE, kColor1InitData.data());
1066*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1067*8975f5c5SAndroid Build Coastguard Worker 
1068*8975f5c5SAndroid Build Coastguard Worker     glBindTexture(GL_TEXTURE_2D_ARRAY, depthStencil);
1069*8975f5c5SAndroid Build Coastguard Worker     glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_DEPTH24_STENCIL8, kWidth, kHeight,
1070*8975f5c5SAndroid Build Coastguard Worker                    kDepthStencilLayers);
1071*8975f5c5SAndroid Build Coastguard Worker     glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepthStencilLayers,
1072*8975f5c5SAndroid Build Coastguard Worker                     GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, kDepthStencilInitData.data());
1073*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1074*8975f5c5SAndroid Build Coastguard Worker 
1075*8975f5c5SAndroid Build Coastguard Worker     glFramebufferTextureEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, color0, 0);
1076*8975f5c5SAndroid Build Coastguard Worker     glFramebufferTextureEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, color1, 0);
1077*8975f5c5SAndroid Build Coastguard Worker     glFramebufferTextureEXT(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, depthStencil, 0);
1078*8975f5c5SAndroid Build Coastguard Worker 
1079*8975f5c5SAndroid Build Coastguard Worker     constexpr GLenum kDrawBuffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
1080*8975f5c5SAndroid Build Coastguard Worker     glDrawBuffers(2, kDrawBuffers);
1081*8975f5c5SAndroid Build Coastguard Worker 
1082*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1083*8975f5c5SAndroid Build Coastguard Worker }
1084*8975f5c5SAndroid Build Coastguard Worker 
setupLayeredFramebufferProgram(GLProgram * program)1085*8975f5c5SAndroid Build Coastguard Worker void GeometryShaderTest::setupLayeredFramebufferProgram(GLProgram *program)
1086*8975f5c5SAndroid Build Coastguard Worker {
1087*8975f5c5SAndroid Build Coastguard Worker     constexpr char kVS[] = R"(#version 310 es
1088*8975f5c5SAndroid Build Coastguard Worker 
1089*8975f5c5SAndroid Build Coastguard Worker in highp vec4 position;
1090*8975f5c5SAndroid Build Coastguard Worker 
1091*8975f5c5SAndroid Build Coastguard Worker void main()
1092*8975f5c5SAndroid Build Coastguard Worker {
1093*8975f5c5SAndroid Build Coastguard Worker     gl_Position = position;
1094*8975f5c5SAndroid Build Coastguard Worker })";
1095*8975f5c5SAndroid Build Coastguard Worker 
1096*8975f5c5SAndroid Build Coastguard Worker     static_assert(kFramebufferLayers == 3,
1097*8975f5c5SAndroid Build Coastguard Worker                   "Adjust the invocations parameter in the geometry shader, and color arrays in "
1098*8975f5c5SAndroid Build Coastguard Worker                   "fragment shader");
1099*8975f5c5SAndroid Build Coastguard Worker 
1100*8975f5c5SAndroid Build Coastguard Worker     constexpr char kGS[] = R"(#version 310 es
1101*8975f5c5SAndroid Build Coastguard Worker #extension GL_EXT_geometry_shader : require
1102*8975f5c5SAndroid Build Coastguard Worker layout (invocations = 3, triangles) in;
1103*8975f5c5SAndroid Build Coastguard Worker layout (triangle_strip, max_vertices = 3) out;
1104*8975f5c5SAndroid Build Coastguard Worker 
1105*8975f5c5SAndroid Build Coastguard Worker void main()
1106*8975f5c5SAndroid Build Coastguard Worker {
1107*8975f5c5SAndroid Build Coastguard Worker     for (int n = 0; n < gl_in.length(); n++)
1108*8975f5c5SAndroid Build Coastguard Worker     {
1109*8975f5c5SAndroid Build Coastguard Worker         gl_Position = gl_in[n].gl_Position;
1110*8975f5c5SAndroid Build Coastguard Worker         gl_Layer = gl_InvocationID;
1111*8975f5c5SAndroid Build Coastguard Worker         EmitVertex();
1112*8975f5c5SAndroid Build Coastguard Worker     }
1113*8975f5c5SAndroid Build Coastguard Worker     EndPrimitive();
1114*8975f5c5SAndroid Build Coastguard Worker })";
1115*8975f5c5SAndroid Build Coastguard Worker 
1116*8975f5c5SAndroid Build Coastguard Worker     constexpr char kFS[] = R"(#version 310 es
1117*8975f5c5SAndroid Build Coastguard Worker #extension GL_EXT_geometry_shader : require
1118*8975f5c5SAndroid Build Coastguard Worker precision mediump float;
1119*8975f5c5SAndroid Build Coastguard Worker 
1120*8975f5c5SAndroid Build Coastguard Worker layout(location = 0) out mediump vec4 color0;
1121*8975f5c5SAndroid Build Coastguard Worker layout(location = 1) out mediump vec4 color1;
1122*8975f5c5SAndroid Build Coastguard Worker 
1123*8975f5c5SAndroid Build Coastguard Worker const vec4 color0Layers[3] = vec4[](
1124*8975f5c5SAndroid Build Coastguard Worker     vec4(1, 0, 0, 1),
1125*8975f5c5SAndroid Build Coastguard Worker     vec4(0, 1, 0, 1),
1126*8975f5c5SAndroid Build Coastguard Worker     vec4(0, 0, 1, 1)
1127*8975f5c5SAndroid Build Coastguard Worker );
1128*8975f5c5SAndroid Build Coastguard Worker 
1129*8975f5c5SAndroid Build Coastguard Worker const vec4 color1Layers[3] = vec4[](
1130*8975f5c5SAndroid Build Coastguard Worker     vec4(1, 1, 0, 1),
1131*8975f5c5SAndroid Build Coastguard Worker     vec4(0, 1, 1, 1),
1132*8975f5c5SAndroid Build Coastguard Worker     vec4(1, 0, 1, 1)
1133*8975f5c5SAndroid Build Coastguard Worker );
1134*8975f5c5SAndroid Build Coastguard Worker 
1135*8975f5c5SAndroid Build Coastguard Worker void main()
1136*8975f5c5SAndroid Build Coastguard Worker {
1137*8975f5c5SAndroid Build Coastguard Worker     color0 = color0Layers[gl_Layer];
1138*8975f5c5SAndroid Build Coastguard Worker     color1 = color1Layers[gl_Layer];
1139*8975f5c5SAndroid Build Coastguard Worker })";
1140*8975f5c5SAndroid Build Coastguard Worker 
1141*8975f5c5SAndroid Build Coastguard Worker     program->makeRaster(kVS, kGS, kFS);
1142*8975f5c5SAndroid Build Coastguard Worker     ASSERT_TRUE(program->valid());
1143*8975f5c5SAndroid Build Coastguard Worker }
1144*8975f5c5SAndroid Build Coastguard Worker 
verifyLayeredFramebufferColor(GLuint colorTexture,GLenum colorTarget,const GLColor expected[],GLsizei layerCount)1145*8975f5c5SAndroid Build Coastguard Worker void GeometryShaderTest::verifyLayeredFramebufferColor(GLuint colorTexture,
1146*8975f5c5SAndroid Build Coastguard Worker                                                        GLenum colorTarget,
1147*8975f5c5SAndroid Build Coastguard Worker                                                        const GLColor expected[],
1148*8975f5c5SAndroid Build Coastguard Worker                                                        GLsizei layerCount)
1149*8975f5c5SAndroid Build Coastguard Worker {
1150*8975f5c5SAndroid Build Coastguard Worker     // Note: the OpenGL and Vulkan specs are unclear regarding whether clear should affect all
1151*8975f5c5SAndroid Build Coastguard Worker     // layers of the framebuffer or the attachment.  The GL spec says:
1152*8975f5c5SAndroid Build Coastguard Worker     //
1153*8975f5c5SAndroid Build Coastguard Worker     // > When the Clear or ClearBuffer* commands described in section 15.2.3 are
1154*8975f5c5SAndroid Build Coastguard Worker     // > used to clear a layered framebuffer attachment, all layers of the attachment are
1155*8975f5c5SAndroid Build Coastguard Worker     // > cleared.
1156*8975f5c5SAndroid Build Coastguard Worker     //
1157*8975f5c5SAndroid Build Coastguard Worker     // Which implies that all layers are cleared.  However, it's common among vendors to consider
1158*8975f5c5SAndroid Build Coastguard Worker     // only the attachments accessible to a draw call to be affected by clear (otherwise
1159*8975f5c5SAndroid Build Coastguard Worker     // clear-through-draw cannot be done).
1160*8975f5c5SAndroid Build Coastguard Worker     //
1161*8975f5c5SAndroid Build Coastguard Worker     // There is inconsistency between implementations in both the OpenGL and Vulkan implementations
1162*8975f5c5SAndroid Build Coastguard Worker     // in this regard.  In OpenGL, Qualcomm and Intel drivers clear all layers while Nvidia drivers
1163*8975f5c5SAndroid Build Coastguard Worker     // clear only the framebuffer layers.  In Vulkan, Intel and AMD windows drivers clear all layers
1164*8975f5c5SAndroid Build Coastguard Worker     // with loadOp=CLEAR, while the other implementations (including Intel mesa) only clear the
1165*8975f5c5SAndroid Build Coastguard Worker     // framebuffer layers.
1166*8975f5c5SAndroid Build Coastguard Worker     //
1167*8975f5c5SAndroid Build Coastguard Worker     // Due to this inconsistency, only the framebuffer layers are verified.  The other layers, if
1168*8975f5c5SAndroid Build Coastguard Worker     // the texture has them will either contain the initial or the cleared color, but is not
1169*8975f5c5SAndroid Build Coastguard Worker     // verified by these tests.
1170*8975f5c5SAndroid Build Coastguard Worker     layerCount = kFramebufferLayers;
1171*8975f5c5SAndroid Build Coastguard Worker 
1172*8975f5c5SAndroid Build Coastguard Worker     GLFramebuffer fbo;
1173*8975f5c5SAndroid Build Coastguard Worker     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1174*8975f5c5SAndroid Build Coastguard Worker 
1175*8975f5c5SAndroid Build Coastguard Worker     glBindTexture(colorTarget, colorTexture);
1176*8975f5c5SAndroid Build Coastguard Worker 
1177*8975f5c5SAndroid Build Coastguard Worker     for (GLsizei layer = 0; layer < layerCount; ++layer)
1178*8975f5c5SAndroid Build Coastguard Worker     {
1179*8975f5c5SAndroid Build Coastguard Worker         glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorTexture, 0, layer);
1180*8975f5c5SAndroid Build Coastguard Worker         EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1181*8975f5c5SAndroid Build Coastguard Worker 
1182*8975f5c5SAndroid Build Coastguard Worker         EXPECT_PIXEL_COLOR_NEAR(0, 0, expected[layer], 1);
1183*8975f5c5SAndroid Build Coastguard Worker         EXPECT_PIXEL_COLOR_NEAR(kWidth - 1, 0, expected[layer], 1);
1184*8975f5c5SAndroid Build Coastguard Worker         EXPECT_PIXEL_COLOR_NEAR(0, kHeight - 1, expected[layer], 1);
1185*8975f5c5SAndroid Build Coastguard Worker         EXPECT_PIXEL_COLOR_NEAR(kWidth - 1, kHeight - 1, expected[layer], 1);
1186*8975f5c5SAndroid Build Coastguard Worker     }
1187*8975f5c5SAndroid Build Coastguard Worker }
1188*8975f5c5SAndroid Build Coastguard Worker 
verifyLayeredFramebufferDepthStencil(GLuint depthStencilTexture,const float expectedDepth[],const GLint expectedStencil[],GLsizei layerCount)1189*8975f5c5SAndroid Build Coastguard Worker void GeometryShaderTest::verifyLayeredFramebufferDepthStencil(GLuint depthStencilTexture,
1190*8975f5c5SAndroid Build Coastguard Worker                                                               const float expectedDepth[],
1191*8975f5c5SAndroid Build Coastguard Worker                                                               const GLint expectedStencil[],
1192*8975f5c5SAndroid Build Coastguard Worker                                                               GLsizei layerCount)
1193*8975f5c5SAndroid Build Coastguard Worker {
1194*8975f5c5SAndroid Build Coastguard Worker     // See comment in verifyLayeredFramebufferColor
1195*8975f5c5SAndroid Build Coastguard Worker     layerCount = kFramebufferLayers;
1196*8975f5c5SAndroid Build Coastguard Worker 
1197*8975f5c5SAndroid Build Coastguard Worker     // Setup program
1198*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
1199*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(drawColor);
1200*8975f5c5SAndroid Build Coastguard Worker     GLint colorUniformLocation =
1201*8975f5c5SAndroid Build Coastguard Worker         glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
1202*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(colorUniformLocation, -1);
1203*8975f5c5SAndroid Build Coastguard Worker 
1204*8975f5c5SAndroid Build Coastguard Worker     // Set up state to validate depth and stencil
1205*8975f5c5SAndroid Build Coastguard Worker     glEnable(GL_DEPTH_TEST);
1206*8975f5c5SAndroid Build Coastguard Worker     glEnable(GL_STENCIL_TEST);
1207*8975f5c5SAndroid Build Coastguard Worker     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
1208*8975f5c5SAndroid Build Coastguard Worker     glStencilMask(0xFF);
1209*8975f5c5SAndroid Build Coastguard Worker     glClearColor(0, 0, 0, 0);
1210*8975f5c5SAndroid Build Coastguard Worker 
1211*8975f5c5SAndroid Build Coastguard Worker     // Set up framebuffer
1212*8975f5c5SAndroid Build Coastguard Worker     GLFramebuffer fbo;
1213*8975f5c5SAndroid Build Coastguard Worker     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1214*8975f5c5SAndroid Build Coastguard Worker 
1215*8975f5c5SAndroid Build Coastguard Worker     GLTexture color;
1216*8975f5c5SAndroid Build Coastguard Worker     glBindTexture(GL_TEXTURE_2D, color);
1217*8975f5c5SAndroid Build Coastguard Worker     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kWidth, kHeight);
1218*8975f5c5SAndroid Build Coastguard Worker 
1219*8975f5c5SAndroid Build Coastguard Worker     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
1220*8975f5c5SAndroid Build Coastguard Worker 
1221*8975f5c5SAndroid Build Coastguard Worker     glBindTexture(GL_TEXTURE_2D_ARRAY, depthStencilTexture);
1222*8975f5c5SAndroid Build Coastguard Worker 
1223*8975f5c5SAndroid Build Coastguard Worker     for (GLsizei layer = 0; layer < layerCount; ++layer)
1224*8975f5c5SAndroid Build Coastguard Worker     {
1225*8975f5c5SAndroid Build Coastguard Worker         glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, depthStencilTexture,
1226*8975f5c5SAndroid Build Coastguard Worker                                   0, layer);
1227*8975f5c5SAndroid Build Coastguard Worker         EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1228*8975f5c5SAndroid Build Coastguard Worker 
1229*8975f5c5SAndroid Build Coastguard Worker         glClear(GL_COLOR_BUFFER_BIT);
1230*8975f5c5SAndroid Build Coastguard Worker 
1231*8975f5c5SAndroid Build Coastguard Worker         glStencilFunc(GL_EQUAL, expectedStencil[layer], 0xFF);
1232*8975f5c5SAndroid Build Coastguard Worker 
1233*8975f5c5SAndroid Build Coastguard Worker         // Pass depth slightly less than expected
1234*8975f5c5SAndroid Build Coastguard Worker         glDepthFunc(GL_LESS);
1235*8975f5c5SAndroid Build Coastguard Worker         glUniform4f(colorUniformLocation, 0.1f, 0.2f, 0.3f, 0.4f);
1236*8975f5c5SAndroid Build Coastguard Worker         drawQuad(drawColor, essl1_shaders::PositionAttrib(), expectedDepth[layer] * 2 - 1 - 0.01f);
1237*8975f5c5SAndroid Build Coastguard Worker 
1238*8975f5c5SAndroid Build Coastguard Worker         // Fail depth slightly greater than expected
1239*8975f5c5SAndroid Build Coastguard Worker         glUniform4f(colorUniformLocation, 0.5f, 0.6f, 0.7f, 0.8f);
1240*8975f5c5SAndroid Build Coastguard Worker         drawQuad(drawColor, essl1_shaders::PositionAttrib(), expectedDepth[layer] * 2 - 1 + 0.01f);
1241*8975f5c5SAndroid Build Coastguard Worker 
1242*8975f5c5SAndroid Build Coastguard Worker         ASSERT_GL_NO_ERROR();
1243*8975f5c5SAndroid Build Coastguard Worker 
1244*8975f5c5SAndroid Build Coastguard Worker         // Verify results
1245*8975f5c5SAndroid Build Coastguard Worker         const GLColor kExpected(25, 51, 76, 102);
1246*8975f5c5SAndroid Build Coastguard Worker 
1247*8975f5c5SAndroid Build Coastguard Worker         EXPECT_PIXEL_COLOR_NEAR(0, 0, kExpected, 1);
1248*8975f5c5SAndroid Build Coastguard Worker         EXPECT_PIXEL_COLOR_NEAR(kWidth - 1, 0, kExpected, 1);
1249*8975f5c5SAndroid Build Coastguard Worker         EXPECT_PIXEL_COLOR_NEAR(0, kHeight - 1, kExpected, 1);
1250*8975f5c5SAndroid Build Coastguard Worker         EXPECT_PIXEL_COLOR_NEAR(kWidth - 1, kHeight - 1, kExpected, 1);
1251*8975f5c5SAndroid Build Coastguard Worker     }
1252*8975f5c5SAndroid Build Coastguard Worker }
1253*8975f5c5SAndroid Build Coastguard Worker 
layeredFramebufferClearTest(GLenum colorTarget)1254*8975f5c5SAndroid Build Coastguard Worker void GeometryShaderTest::layeredFramebufferClearTest(GLenum colorTarget)
1255*8975f5c5SAndroid Build Coastguard Worker {
1256*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
1257*8975f5c5SAndroid Build Coastguard Worker 
1258*8975f5c5SAndroid Build Coastguard Worker     const GLColor kColor0InitColor(10, 20, 30, 40);
1259*8975f5c5SAndroid Build Coastguard Worker     const GLColor kColor1InitColor(200, 210, 220, 230);
1260*8975f5c5SAndroid Build Coastguard Worker     constexpr float kDepthInitValue   = 0.35f;
1261*8975f5c5SAndroid Build Coastguard Worker     constexpr GLint kStencilInitValue = 0x33;
1262*8975f5c5SAndroid Build Coastguard Worker 
1263*8975f5c5SAndroid Build Coastguard Worker     GLFramebuffer framebuffer;
1264*8975f5c5SAndroid Build Coastguard Worker     GLTexture color0;
1265*8975f5c5SAndroid Build Coastguard Worker     GLTexture color1;
1266*8975f5c5SAndroid Build Coastguard Worker     GLTexture depthStencil;
1267*8975f5c5SAndroid Build Coastguard Worker     GLProgram program;
1268*8975f5c5SAndroid Build Coastguard Worker 
1269*8975f5c5SAndroid Build Coastguard Worker     setupLayeredFramebuffer(framebuffer, color0, color1, depthStencil, colorTarget,
1270*8975f5c5SAndroid Build Coastguard Worker                             kColor0InitColor, kColor1InitColor, kDepthInitValue, kStencilInitValue);
1271*8975f5c5SAndroid Build Coastguard Worker     setupLayeredFramebufferProgram(&program);
1272*8975f5c5SAndroid Build Coastguard Worker 
1273*8975f5c5SAndroid Build Coastguard Worker     glClearColor(0.5, 0.5, 0.5, 0.5);
1274*8975f5c5SAndroid Build Coastguard Worker     glClearDepthf(1.0f);
1275*8975f5c5SAndroid Build Coastguard Worker     glClearStencil(0x55);
1276*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1277*8975f5c5SAndroid Build Coastguard Worker 
1278*8975f5c5SAndroid Build Coastguard Worker     const GLColor kClearColor(127, 127, 127, 127);
1279*8975f5c5SAndroid Build Coastguard Worker     const GLColor kExpectedColor0[kColor0Layers] = {
1280*8975f5c5SAndroid Build Coastguard Worker         kClearColor,
1281*8975f5c5SAndroid Build Coastguard Worker         kClearColor,
1282*8975f5c5SAndroid Build Coastguard Worker         kClearColor,
1283*8975f5c5SAndroid Build Coastguard Worker         kColor0InitColor,
1284*8975f5c5SAndroid Build Coastguard Worker     };
1285*8975f5c5SAndroid Build Coastguard Worker     const GLColor kExpectedColor1[kColor1Layers] = {
1286*8975f5c5SAndroid Build Coastguard Worker         kClearColor,
1287*8975f5c5SAndroid Build Coastguard Worker         kClearColor,
1288*8975f5c5SAndroid Build Coastguard Worker         kClearColor,
1289*8975f5c5SAndroid Build Coastguard Worker     };
1290*8975f5c5SAndroid Build Coastguard Worker     const float kExpectedDepth[kDepthStencilLayers] = {
1291*8975f5c5SAndroid Build Coastguard Worker         1.0f, 1.0f, 1.0f, kDepthInitValue, kDepthInitValue,
1292*8975f5c5SAndroid Build Coastguard Worker     };
1293*8975f5c5SAndroid Build Coastguard Worker     const GLint kExpectedStencil[kDepthStencilLayers] = {
1294*8975f5c5SAndroid Build Coastguard Worker         0x55, 0x55, 0x55, kStencilInitValue, kStencilInitValue,
1295*8975f5c5SAndroid Build Coastguard Worker     };
1296*8975f5c5SAndroid Build Coastguard Worker 
1297*8975f5c5SAndroid Build Coastguard Worker     verifyLayeredFramebufferColor(color0, colorTarget, kExpectedColor0, kColor0Layers);
1298*8975f5c5SAndroid Build Coastguard Worker     verifyLayeredFramebufferColor(color1, colorTarget, kExpectedColor1, kColor1Layers);
1299*8975f5c5SAndroid Build Coastguard Worker     verifyLayeredFramebufferDepthStencil(depthStencil, kExpectedDepth, kExpectedStencil,
1300*8975f5c5SAndroid Build Coastguard Worker                                          kDepthStencilLayers);
1301*8975f5c5SAndroid Build Coastguard Worker }
1302*8975f5c5SAndroid Build Coastguard Worker 
1303*8975f5c5SAndroid Build Coastguard Worker // Verify clear of layered attachments.  Uses 3D color textures.
TEST_P(GeometryShaderTest,LayeredFramebufferClear3DColor)1304*8975f5c5SAndroid Build Coastguard Worker TEST_P(GeometryShaderTest, LayeredFramebufferClear3DColor)
1305*8975f5c5SAndroid Build Coastguard Worker {
1306*8975f5c5SAndroid Build Coastguard Worker     // Mesa considers the framebuffer with mixed 3D and 2D array attachments to be incomplete.
1307*8975f5c5SAndroid Build Coastguard Worker     // http://anglebug.com/42264003
1308*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF((IsAMD() || IsIntel()) && IsOpenGL() && IsLinux());
1309*8975f5c5SAndroid Build Coastguard Worker 
1310*8975f5c5SAndroid Build Coastguard Worker     layeredFramebufferClearTest(GL_TEXTURE_3D);
1311*8975f5c5SAndroid Build Coastguard Worker }
1312*8975f5c5SAndroid Build Coastguard Worker 
1313*8975f5c5SAndroid Build Coastguard Worker // Verify clear of layered attachments.  Uses 2D array color textures.
TEST_P(GeometryShaderTest,LayeredFramebufferClear2DArrayColor)1314*8975f5c5SAndroid Build Coastguard Worker TEST_P(GeometryShaderTest, LayeredFramebufferClear2DArrayColor)
1315*8975f5c5SAndroid Build Coastguard Worker {
1316*8975f5c5SAndroid Build Coastguard Worker     layeredFramebufferClearTest(GL_TEXTURE_2D_ARRAY);
1317*8975f5c5SAndroid Build Coastguard Worker }
1318*8975f5c5SAndroid Build Coastguard Worker 
layeredFramebufferPreRenderClearTest(GLenum colorTarget,bool doubleClear)1319*8975f5c5SAndroid Build Coastguard Worker void GeometryShaderTest::layeredFramebufferPreRenderClearTest(GLenum colorTarget, bool doubleClear)
1320*8975f5c5SAndroid Build Coastguard Worker {
1321*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
1322*8975f5c5SAndroid Build Coastguard Worker 
1323*8975f5c5SAndroid Build Coastguard Worker     const GLColor kColor0InitColor(10, 20, 30, 40);
1324*8975f5c5SAndroid Build Coastguard Worker     const GLColor kColor1InitColor(200, 210, 220, 230);
1325*8975f5c5SAndroid Build Coastguard Worker     constexpr float kDepthInitValue   = 0.35f;
1326*8975f5c5SAndroid Build Coastguard Worker     constexpr GLint kStencilInitValue = 0x33;
1327*8975f5c5SAndroid Build Coastguard Worker 
1328*8975f5c5SAndroid Build Coastguard Worker     GLFramebuffer framebuffer;
1329*8975f5c5SAndroid Build Coastguard Worker     GLTexture color0;
1330*8975f5c5SAndroid Build Coastguard Worker     GLTexture color1;
1331*8975f5c5SAndroid Build Coastguard Worker     GLTexture depthStencil;
1332*8975f5c5SAndroid Build Coastguard Worker     GLProgram program;
1333*8975f5c5SAndroid Build Coastguard Worker 
1334*8975f5c5SAndroid Build Coastguard Worker     setupLayeredFramebuffer(framebuffer, color0, color1, depthStencil, colorTarget,
1335*8975f5c5SAndroid Build Coastguard Worker                             kColor0InitColor, kColor1InitColor, kDepthInitValue, kStencilInitValue);
1336*8975f5c5SAndroid Build Coastguard Worker     setupLayeredFramebufferProgram(&program);
1337*8975f5c5SAndroid Build Coastguard Worker 
1338*8975f5c5SAndroid Build Coastguard Worker     if (doubleClear)
1339*8975f5c5SAndroid Build Coastguard Worker     {
1340*8975f5c5SAndroid Build Coastguard Worker         glClearColor(0.1, 0.2, 0.8, 0.9);
1341*8975f5c5SAndroid Build Coastguard Worker         glClearDepthf(0.2f);
1342*8975f5c5SAndroid Build Coastguard Worker         glClearStencil(0x99);
1343*8975f5c5SAndroid Build Coastguard Worker         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1344*8975f5c5SAndroid Build Coastguard Worker     }
1345*8975f5c5SAndroid Build Coastguard Worker 
1346*8975f5c5SAndroid Build Coastguard Worker     glClearColor(0.5, 0.5, 0.5, 0.5);
1347*8975f5c5SAndroid Build Coastguard Worker     glClearDepthf(1.0f);
1348*8975f5c5SAndroid Build Coastguard Worker     glClearStencil(0x55);
1349*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1350*8975f5c5SAndroid Build Coastguard Worker 
1351*8975f5c5SAndroid Build Coastguard Worker     glEnable(GL_DEPTH_TEST);
1352*8975f5c5SAndroid Build Coastguard Worker     glDepthFunc(GL_LESS);
1353*8975f5c5SAndroid Build Coastguard Worker 
1354*8975f5c5SAndroid Build Coastguard Worker     glEnable(GL_STENCIL_TEST);
1355*8975f5c5SAndroid Build Coastguard Worker     glStencilFunc(GL_EQUAL, 0x5A, 0xF0);
1356*8975f5c5SAndroid Build Coastguard Worker     glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
1357*8975f5c5SAndroid Build Coastguard Worker     glStencilMask(0xFF);
1358*8975f5c5SAndroid Build Coastguard Worker 
1359*8975f5c5SAndroid Build Coastguard Worker     drawQuad(program, "position", 0.9f);
1360*8975f5c5SAndroid Build Coastguard Worker 
1361*8975f5c5SAndroid Build Coastguard Worker     const GLColor kExpectedColor0[kColor0Layers] = {
1362*8975f5c5SAndroid Build Coastguard Worker         GLColor::red,
1363*8975f5c5SAndroid Build Coastguard Worker         GLColor::green,
1364*8975f5c5SAndroid Build Coastguard Worker         GLColor::blue,
1365*8975f5c5SAndroid Build Coastguard Worker         kColor0InitColor,
1366*8975f5c5SAndroid Build Coastguard Worker     };
1367*8975f5c5SAndroid Build Coastguard Worker     const GLColor kExpectedColor1[kColor1Layers] = {
1368*8975f5c5SAndroid Build Coastguard Worker         GLColor::yellow,
1369*8975f5c5SAndroid Build Coastguard Worker         GLColor::cyan,
1370*8975f5c5SAndroid Build Coastguard Worker         GLColor::magenta,
1371*8975f5c5SAndroid Build Coastguard Worker     };
1372*8975f5c5SAndroid Build Coastguard Worker     const float kExpectedDepth[kDepthStencilLayers] = {
1373*8975f5c5SAndroid Build Coastguard Worker         0.95f, 0.95f, 0.95f, kDepthInitValue, kDepthInitValue,
1374*8975f5c5SAndroid Build Coastguard Worker     };
1375*8975f5c5SAndroid Build Coastguard Worker     const GLint kExpectedStencil[kDepthStencilLayers] = {
1376*8975f5c5SAndroid Build Coastguard Worker         0x5A, 0x5A, 0x5A, kStencilInitValue, kStencilInitValue,
1377*8975f5c5SAndroid Build Coastguard Worker     };
1378*8975f5c5SAndroid Build Coastguard Worker 
1379*8975f5c5SAndroid Build Coastguard Worker     verifyLayeredFramebufferColor(color0, colorTarget, kExpectedColor0, kColor0Layers);
1380*8975f5c5SAndroid Build Coastguard Worker     verifyLayeredFramebufferColor(color1, colorTarget, kExpectedColor1, kColor1Layers);
1381*8975f5c5SAndroid Build Coastguard Worker     verifyLayeredFramebufferDepthStencil(depthStencil, kExpectedDepth, kExpectedStencil,
1382*8975f5c5SAndroid Build Coastguard Worker                                          kDepthStencilLayers);
1383*8975f5c5SAndroid Build Coastguard Worker }
1384*8975f5c5SAndroid Build Coastguard Worker 
1385*8975f5c5SAndroid Build Coastguard Worker // Verify pre-render clear of layered attachments.  Uses 3D color textures.
TEST_P(GeometryShaderTest,LayeredFramebufferPreRenderClear3DColor)1386*8975f5c5SAndroid Build Coastguard Worker TEST_P(GeometryShaderTest, LayeredFramebufferPreRenderClear3DColor)
1387*8975f5c5SAndroid Build Coastguard Worker {
1388*8975f5c5SAndroid Build Coastguard Worker     // Mesa considers the framebuffer with mixed 3D and 2D array attachments to be incomplete.
1389*8975f5c5SAndroid Build Coastguard Worker     // http://anglebug.com/42264003
1390*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF((IsAMD() || IsIntel()) && IsOpenGL() && IsLinux());
1391*8975f5c5SAndroid Build Coastguard Worker 
1392*8975f5c5SAndroid Build Coastguard Worker     layeredFramebufferPreRenderClearTest(GL_TEXTURE_3D, false);
1393*8975f5c5SAndroid Build Coastguard Worker }
1394*8975f5c5SAndroid Build Coastguard Worker 
1395*8975f5c5SAndroid Build Coastguard Worker // Same as LayeredFramebufferPreRenderClear3DColor, but clears twice.
TEST_P(GeometryShaderTest,LayeredFramebufferPreRenderDoubleClear3DColor)1396*8975f5c5SAndroid Build Coastguard Worker TEST_P(GeometryShaderTest, LayeredFramebufferPreRenderDoubleClear3DColor)
1397*8975f5c5SAndroid Build Coastguard Worker {
1398*8975f5c5SAndroid Build Coastguard Worker     // Mesa considers the framebuffer with mixed 3D and 2D array attachments to be incomplete.
1399*8975f5c5SAndroid Build Coastguard Worker     // http://anglebug.com/42264003
1400*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF((IsAMD() || IsIntel()) && IsOpenGL() && IsLinux());
1401*8975f5c5SAndroid Build Coastguard Worker 
1402*8975f5c5SAndroid Build Coastguard Worker     layeredFramebufferPreRenderClearTest(GL_TEXTURE_3D, true);
1403*8975f5c5SAndroid Build Coastguard Worker }
1404*8975f5c5SAndroid Build Coastguard Worker 
1405*8975f5c5SAndroid Build Coastguard Worker // Verify pre-render clear of layered attachments.  Uses 2D array color textures.
TEST_P(GeometryShaderTest,LayeredFramebufferPreRenderClear2DArrayColor)1406*8975f5c5SAndroid Build Coastguard Worker TEST_P(GeometryShaderTest, LayeredFramebufferPreRenderClear2DArrayColor)
1407*8975f5c5SAndroid Build Coastguard Worker {
1408*8975f5c5SAndroid Build Coastguard Worker     layeredFramebufferPreRenderClearTest(GL_TEXTURE_2D_ARRAY, false);
1409*8975f5c5SAndroid Build Coastguard Worker }
1410*8975f5c5SAndroid Build Coastguard Worker 
1411*8975f5c5SAndroid Build Coastguard Worker // Same as LayeredFramebufferPreRenderClear2DArrayColor, but clears twice.
TEST_P(GeometryShaderTest,LayeredFramebufferPreRenderDoubleClear2DArrayColor)1412*8975f5c5SAndroid Build Coastguard Worker TEST_P(GeometryShaderTest, LayeredFramebufferPreRenderDoubleClear2DArrayColor)
1413*8975f5c5SAndroid Build Coastguard Worker {
1414*8975f5c5SAndroid Build Coastguard Worker     layeredFramebufferPreRenderClearTest(GL_TEXTURE_2D_ARRAY, true);
1415*8975f5c5SAndroid Build Coastguard Worker }
1416*8975f5c5SAndroid Build Coastguard Worker 
layeredFramebufferMidRenderClearTest(GLenum colorTarget)1417*8975f5c5SAndroid Build Coastguard Worker void GeometryShaderTest::layeredFramebufferMidRenderClearTest(GLenum colorTarget)
1418*8975f5c5SAndroid Build Coastguard Worker {
1419*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
1420*8975f5c5SAndroid Build Coastguard Worker 
1421*8975f5c5SAndroid Build Coastguard Worker     // Vulkan's draw path for clear doesn't support layered framebuffers.
1422*8975f5c5SAndroid Build Coastguard Worker     // http://anglebug.com/42263992
1423*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(IsVulkan());
1424*8975f5c5SAndroid Build Coastguard Worker 
1425*8975f5c5SAndroid Build Coastguard Worker     const GLColor kColor0InitColor(10, 20, 30, 40);
1426*8975f5c5SAndroid Build Coastguard Worker     const GLColor kColor1InitColor(200, 210, 220, 230);
1427*8975f5c5SAndroid Build Coastguard Worker     constexpr float kDepthInitValue   = 0.35f;
1428*8975f5c5SAndroid Build Coastguard Worker     constexpr GLint kStencilInitValue = 0x33;
1429*8975f5c5SAndroid Build Coastguard Worker 
1430*8975f5c5SAndroid Build Coastguard Worker     GLFramebuffer framebuffer;
1431*8975f5c5SAndroid Build Coastguard Worker     GLTexture color0;
1432*8975f5c5SAndroid Build Coastguard Worker     GLTexture color1;
1433*8975f5c5SAndroid Build Coastguard Worker     GLTexture depthStencil;
1434*8975f5c5SAndroid Build Coastguard Worker     GLProgram program;
1435*8975f5c5SAndroid Build Coastguard Worker 
1436*8975f5c5SAndroid Build Coastguard Worker     setupLayeredFramebuffer(framebuffer, color0, color1, depthStencil, colorTarget,
1437*8975f5c5SAndroid Build Coastguard Worker                             kColor0InitColor, kColor1InitColor, kDepthInitValue, kStencilInitValue);
1438*8975f5c5SAndroid Build Coastguard Worker     setupLayeredFramebufferProgram(&program);
1439*8975f5c5SAndroid Build Coastguard Worker 
1440*8975f5c5SAndroid Build Coastguard Worker     glEnable(GL_DEPTH_TEST);
1441*8975f5c5SAndroid Build Coastguard Worker     glDepthFunc(GL_ALWAYS);
1442*8975f5c5SAndroid Build Coastguard Worker 
1443*8975f5c5SAndroid Build Coastguard Worker     glEnable(GL_STENCIL_TEST);
1444*8975f5c5SAndroid Build Coastguard Worker     glStencilFunc(GL_ALWAYS, 0x55, 0xF0);
1445*8975f5c5SAndroid Build Coastguard Worker     glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
1446*8975f5c5SAndroid Build Coastguard Worker     glStencilMask(0xFF);
1447*8975f5c5SAndroid Build Coastguard Worker 
1448*8975f5c5SAndroid Build Coastguard Worker     drawQuad(program, "position", 0.3f);
1449*8975f5c5SAndroid Build Coastguard Worker 
1450*8975f5c5SAndroid Build Coastguard Worker     glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_TRUE);
1451*8975f5c5SAndroid Build Coastguard Worker     glClearColor(0.5, 0.5, 0.5, 0.5);
1452*8975f5c5SAndroid Build Coastguard Worker     glClearDepthf(0.8f);
1453*8975f5c5SAndroid Build Coastguard Worker     glStencilMask(0xF0);
1454*8975f5c5SAndroid Build Coastguard Worker     glClearStencil(0xAA);
1455*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1456*8975f5c5SAndroid Build Coastguard Worker 
1457*8975f5c5SAndroid Build Coastguard Worker     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1458*8975f5c5SAndroid Build Coastguard Worker     glStencilMask(0xFF);
1459*8975f5c5SAndroid Build Coastguard Worker 
1460*8975f5c5SAndroid Build Coastguard Worker     const GLColor kExpectedColor0[kColor0Layers] = {
1461*8975f5c5SAndroid Build Coastguard Worker         GLColor(255, 0, 127, 127),
1462*8975f5c5SAndroid Build Coastguard Worker         GLColor(0, 255, 127, 127),
1463*8975f5c5SAndroid Build Coastguard Worker         GLColor(0, 0, 127, 127),
1464*8975f5c5SAndroid Build Coastguard Worker         kColor0InitColor,
1465*8975f5c5SAndroid Build Coastguard Worker     };
1466*8975f5c5SAndroid Build Coastguard Worker     const GLColor kExpectedColor1[kColor1Layers] = {
1467*8975f5c5SAndroid Build Coastguard Worker         GLColor(255, 255, 127, 127),
1468*8975f5c5SAndroid Build Coastguard Worker         GLColor(0, 255, 127, 127),
1469*8975f5c5SAndroid Build Coastguard Worker         GLColor(255, 0, 127, 127),
1470*8975f5c5SAndroid Build Coastguard Worker     };
1471*8975f5c5SAndroid Build Coastguard Worker     const float kExpectedDepth[kDepthStencilLayers] = {
1472*8975f5c5SAndroid Build Coastguard Worker         0.6f, 0.6f, 0.6f, kDepthInitValue, kDepthInitValue,
1473*8975f5c5SAndroid Build Coastguard Worker     };
1474*8975f5c5SAndroid Build Coastguard Worker     const GLint kExpectedStencil[kDepthStencilLayers] = {
1475*8975f5c5SAndroid Build Coastguard Worker         0xA5, 0xA5, 0xA5, kStencilInitValue, kStencilInitValue,
1476*8975f5c5SAndroid Build Coastguard Worker     };
1477*8975f5c5SAndroid Build Coastguard Worker 
1478*8975f5c5SAndroid Build Coastguard Worker     verifyLayeredFramebufferColor(color0, colorTarget, kExpectedColor0, kColor0Layers);
1479*8975f5c5SAndroid Build Coastguard Worker     verifyLayeredFramebufferColor(color1, colorTarget, kExpectedColor1, kColor1Layers);
1480*8975f5c5SAndroid Build Coastguard Worker     verifyLayeredFramebufferDepthStencil(depthStencil, kExpectedDepth, kExpectedStencil,
1481*8975f5c5SAndroid Build Coastguard Worker                                          kDepthStencilLayers);
1482*8975f5c5SAndroid Build Coastguard Worker }
1483*8975f5c5SAndroid Build Coastguard Worker 
1484*8975f5c5SAndroid Build Coastguard Worker // Verify that Geometry Shader's gl_Layer is ineffective when the framebuffer is not layered.
TEST_P(GeometryShaderTest,GLLayerIneffectiveWithoutLayeredFramebuffer)1485*8975f5c5SAndroid Build Coastguard Worker TEST_P(GeometryShaderTest, GLLayerIneffectiveWithoutLayeredFramebuffer)
1486*8975f5c5SAndroid Build Coastguard Worker {
1487*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
1488*8975f5c5SAndroid Build Coastguard Worker 
1489*8975f5c5SAndroid Build Coastguard Worker     constexpr char kVS[] = R"(#version 310 es
1490*8975f5c5SAndroid Build Coastguard Worker in highp vec4 position;
1491*8975f5c5SAndroid Build Coastguard Worker void main()
1492*8975f5c5SAndroid Build Coastguard Worker {
1493*8975f5c5SAndroid Build Coastguard Worker     gl_Position = position;
1494*8975f5c5SAndroid Build Coastguard Worker })";
1495*8975f5c5SAndroid Build Coastguard Worker 
1496*8975f5c5SAndroid Build Coastguard Worker     constexpr char kGS[] = R"(#version 310 es
1497*8975f5c5SAndroid Build Coastguard Worker #extension GL_EXT_geometry_shader : require
1498*8975f5c5SAndroid Build Coastguard Worker layout (invocations = 3, triangles) in;
1499*8975f5c5SAndroid Build Coastguard Worker layout (triangle_strip, max_vertices = 3) out;
1500*8975f5c5SAndroid Build Coastguard Worker 
1501*8975f5c5SAndroid Build Coastguard Worker void main()
1502*8975f5c5SAndroid Build Coastguard Worker {
1503*8975f5c5SAndroid Build Coastguard Worker     for (int n = 0; n < gl_in.length(); n++)
1504*8975f5c5SAndroid Build Coastguard Worker     {
1505*8975f5c5SAndroid Build Coastguard Worker         gl_Position = gl_in[n].gl_Position;
1506*8975f5c5SAndroid Build Coastguard Worker         gl_Layer = gl_InvocationID;
1507*8975f5c5SAndroid Build Coastguard Worker         EmitVertex();
1508*8975f5c5SAndroid Build Coastguard Worker     }
1509*8975f5c5SAndroid Build Coastguard Worker     EndPrimitive();
1510*8975f5c5SAndroid Build Coastguard Worker })";
1511*8975f5c5SAndroid Build Coastguard Worker 
1512*8975f5c5SAndroid Build Coastguard Worker     constexpr char kFS[] = R"(#version 310 es
1513*8975f5c5SAndroid Build Coastguard Worker #extension GL_EXT_geometry_shader : require
1514*8975f5c5SAndroid Build Coastguard Worker precision mediump float;
1515*8975f5c5SAndroid Build Coastguard Worker 
1516*8975f5c5SAndroid Build Coastguard Worker layout(location = 0) out mediump vec4 color;
1517*8975f5c5SAndroid Build Coastguard Worker 
1518*8975f5c5SAndroid Build Coastguard Worker void main()
1519*8975f5c5SAndroid Build Coastguard Worker {
1520*8975f5c5SAndroid Build Coastguard Worker     if (gl_Layer == 0)
1521*8975f5c5SAndroid Build Coastguard Worker         color = vec4(0, 1, 0, 1);
1522*8975f5c5SAndroid Build Coastguard Worker     else
1523*8975f5c5SAndroid Build Coastguard Worker         color = vec4(1, 0, 0, 1);
1524*8975f5c5SAndroid Build Coastguard Worker })";
1525*8975f5c5SAndroid Build Coastguard Worker 
1526*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_PROGRAM_WITH_GS(program, kVS, kGS, kFS);
1527*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1528*8975f5c5SAndroid Build Coastguard Worker 
1529*8975f5c5SAndroid Build Coastguard Worker     GLFramebuffer fbo;
1530*8975f5c5SAndroid Build Coastguard Worker     GLTexture color;
1531*8975f5c5SAndroid Build Coastguard Worker 
1532*8975f5c5SAndroid Build Coastguard Worker     glBindTexture(GL_TEXTURE_2D_ARRAY, color);
1533*8975f5c5SAndroid Build Coastguard Worker     glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, kWidth, kHeight, 4);
1534*8975f5c5SAndroid Build Coastguard Worker 
1535*8975f5c5SAndroid Build Coastguard Worker     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1536*8975f5c5SAndroid Build Coastguard Worker     glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, color, 0, 1);
1537*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1538*8975f5c5SAndroid Build Coastguard Worker 
1539*8975f5c5SAndroid Build Coastguard Worker     drawQuad(program, "position", 0.3f);
1540*8975f5c5SAndroid Build Coastguard Worker 
1541*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green);
1542*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1543*8975f5c5SAndroid Build Coastguard Worker }
1544*8975f5c5SAndroid Build Coastguard Worker 
1545*8975f5c5SAndroid Build Coastguard Worker // Verify mid-render clear of layered attachments.  Uses 3D color textures.
TEST_P(GeometryShaderTest,LayeredFramebufferMidRenderClear3DColor)1546*8975f5c5SAndroid Build Coastguard Worker TEST_P(GeometryShaderTest, LayeredFramebufferMidRenderClear3DColor)
1547*8975f5c5SAndroid Build Coastguard Worker {
1548*8975f5c5SAndroid Build Coastguard Worker     // Mesa considers the framebuffer with mixed 3D and 2D array attachments to be incomplete.
1549*8975f5c5SAndroid Build Coastguard Worker     // http://anglebug.com/42264003
1550*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF((IsAMD() || IsIntel()) && IsOpenGL() && IsLinux());
1551*8975f5c5SAndroid Build Coastguard Worker 
1552*8975f5c5SAndroid Build Coastguard Worker     layeredFramebufferMidRenderClearTest(GL_TEXTURE_3D);
1553*8975f5c5SAndroid Build Coastguard Worker }
1554*8975f5c5SAndroid Build Coastguard Worker 
1555*8975f5c5SAndroid Build Coastguard Worker // Verify mid-render clear of layered attachments.  Uses 2D array color textures.
TEST_P(GeometryShaderTest,LayeredFramebufferMidRenderClear2DArrayColor)1556*8975f5c5SAndroid Build Coastguard Worker TEST_P(GeometryShaderTest, LayeredFramebufferMidRenderClear2DArrayColor)
1557*8975f5c5SAndroid Build Coastguard Worker {
1558*8975f5c5SAndroid Build Coastguard Worker     layeredFramebufferMidRenderClearTest(GL_TEXTURE_2D_ARRAY);
1559*8975f5c5SAndroid Build Coastguard Worker }
1560*8975f5c5SAndroid Build Coastguard Worker 
1561*8975f5c5SAndroid Build Coastguard Worker // Verify that prerotation applies to the geometry shader stage if present.
TEST_P(GeometryShaderTest,Prerotation)1562*8975f5c5SAndroid Build Coastguard Worker TEST_P(GeometryShaderTest, Prerotation)
1563*8975f5c5SAndroid Build Coastguard Worker {
1564*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
1565*8975f5c5SAndroid Build Coastguard Worker 
1566*8975f5c5SAndroid Build Coastguard Worker     constexpr char kVS[] = R"(#version 310 es
1567*8975f5c5SAndroid Build Coastguard Worker void main()
1568*8975f5c5SAndroid Build Coastguard Worker {
1569*8975f5c5SAndroid Build Coastguard Worker     // Geometry shader will output fixed positions, so this is ignored.
1570*8975f5c5SAndroid Build Coastguard Worker     gl_Position = vec4(0);
1571*8975f5c5SAndroid Build Coastguard Worker })";
1572*8975f5c5SAndroid Build Coastguard Worker 
1573*8975f5c5SAndroid Build Coastguard Worker     constexpr char kGS[] = R"(#version 310 es
1574*8975f5c5SAndroid Build Coastguard Worker #extension GL_EXT_geometry_shader : require
1575*8975f5c5SAndroid Build Coastguard Worker layout (triangles) in;
1576*8975f5c5SAndroid Build Coastguard Worker layout (triangle_strip, max_vertices = 4) out;
1577*8975f5c5SAndroid Build Coastguard Worker 
1578*8975f5c5SAndroid Build Coastguard Worker void main()
1579*8975f5c5SAndroid Build Coastguard Worker {
1580*8975f5c5SAndroid Build Coastguard Worker     // Generate two triangles to cover the lower-left quarter of the screen.
1581*8975f5c5SAndroid Build Coastguard Worker     gl_Position = vec4(0, -1, 0, 1);
1582*8975f5c5SAndroid Build Coastguard Worker     EmitVertex();
1583*8975f5c5SAndroid Build Coastguard Worker 
1584*8975f5c5SAndroid Build Coastguard Worker     gl_Position = vec4(0, 0, 0, 1);
1585*8975f5c5SAndroid Build Coastguard Worker     EmitVertex();
1586*8975f5c5SAndroid Build Coastguard Worker 
1587*8975f5c5SAndroid Build Coastguard Worker     gl_Position = vec4(-1, -1, 0, 1);
1588*8975f5c5SAndroid Build Coastguard Worker     EmitVertex();
1589*8975f5c5SAndroid Build Coastguard Worker 
1590*8975f5c5SAndroid Build Coastguard Worker     gl_Position = vec4(-1, 0, 0, 1);
1591*8975f5c5SAndroid Build Coastguard Worker     EmitVertex();
1592*8975f5c5SAndroid Build Coastguard Worker 
1593*8975f5c5SAndroid Build Coastguard Worker     EndPrimitive();
1594*8975f5c5SAndroid Build Coastguard Worker })";
1595*8975f5c5SAndroid Build Coastguard Worker 
1596*8975f5c5SAndroid Build Coastguard Worker     constexpr char kFS[] = R"(#version 310 es
1597*8975f5c5SAndroid Build Coastguard Worker #extension GL_EXT_shader_io_blocks : require
1598*8975f5c5SAndroid Build Coastguard Worker precision mediump float;
1599*8975f5c5SAndroid Build Coastguard Worker 
1600*8975f5c5SAndroid Build Coastguard Worker layout(location = 0) out mediump vec4 color;
1601*8975f5c5SAndroid Build Coastguard Worker 
1602*8975f5c5SAndroid Build Coastguard Worker void main()
1603*8975f5c5SAndroid Build Coastguard Worker {
1604*8975f5c5SAndroid Build Coastguard Worker     // Output solid green
1605*8975f5c5SAndroid Build Coastguard Worker     color = vec4(0, 1.0, 0, 1.0);
1606*8975f5c5SAndroid Build Coastguard Worker })";
1607*8975f5c5SAndroid Build Coastguard Worker 
1608*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_PROGRAM_WITH_GS(program, kVS, kGS, kFS);
1609*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1610*8975f5c5SAndroid Build Coastguard Worker 
1611*8975f5c5SAndroid Build Coastguard Worker     glClearColor(1.0, 0, 0, 1.0);
1612*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT);
1613*8975f5c5SAndroid Build Coastguard Worker 
1614*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(program);
1615*8975f5c5SAndroid Build Coastguard Worker     glDrawArrays(GL_TRIANGLES, 0, 3);
1616*8975f5c5SAndroid Build Coastguard Worker 
1617*8975f5c5SAndroid Build Coastguard Worker     const int w = getWindowWidth();
1618*8975f5c5SAndroid Build Coastguard Worker     const int h = getWindowHeight();
1619*8975f5c5SAndroid Build Coastguard Worker 
1620*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::green);
1621*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_RECT_EQ(0, h / 2, w, h / 2, GLColor::red);
1622*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::red);
1623*8975f5c5SAndroid Build Coastguard Worker }
1624*8975f5c5SAndroid Build Coastguard Worker 
1625*8975f5c5SAndroid Build Coastguard Worker // Verify that correct errors are reported when we use illegal parameters in FramebufferTexture.
TEST_P(GeometryShaderTestES32,NegativeFramebufferTexture)1626*8975f5c5SAndroid Build Coastguard Worker TEST_P(GeometryShaderTestES32, NegativeFramebufferTexture)
1627*8975f5c5SAndroid Build Coastguard Worker {
1628*8975f5c5SAndroid Build Coastguard Worker     testNegativeFramebufferTexture(APIExtensionVersion::Core);
1629*8975f5c5SAndroid Build Coastguard Worker }
1630*8975f5c5SAndroid Build Coastguard Worker 
1631*8975f5c5SAndroid Build Coastguard Worker // Verify that we can have the max amount of uniforms with a geometry shader.
TEST_P(GeometryShaderTestES32,MaxGeometryImageUniforms)1632*8975f5c5SAndroid Build Coastguard Worker TEST_P(GeometryShaderTestES32, MaxGeometryImageUniforms)
1633*8975f5c5SAndroid Build Coastguard Worker {
1634*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
1635*8975f5c5SAndroid Build Coastguard Worker 
1636*8975f5c5SAndroid Build Coastguard Worker     GLint maxGeometryImageUnits;
1637*8975f5c5SAndroid Build Coastguard Worker     glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT, &maxGeometryImageUnits);
1638*8975f5c5SAndroid Build Coastguard Worker 
1639*8975f5c5SAndroid Build Coastguard Worker     const GLchar *vertString = essl31_shaders::vs::Simple();
1640*8975f5c5SAndroid Build Coastguard Worker     const GLchar *fragString = R"(#version 310 es
1641*8975f5c5SAndroid Build Coastguard Worker precision highp float;
1642*8975f5c5SAndroid Build Coastguard Worker out vec4 my_FragColor;
1643*8975f5c5SAndroid Build Coastguard Worker void main()
1644*8975f5c5SAndroid Build Coastguard Worker {
1645*8975f5c5SAndroid Build Coastguard Worker     my_FragColor = vec4(1.0);
1646*8975f5c5SAndroid Build Coastguard Worker })";
1647*8975f5c5SAndroid Build Coastguard Worker 
1648*8975f5c5SAndroid Build Coastguard Worker     std::stringstream geomStringStream;
1649*8975f5c5SAndroid Build Coastguard Worker 
1650*8975f5c5SAndroid Build Coastguard Worker     geomStringStream << R"(#version 310 es
1651*8975f5c5SAndroid Build Coastguard Worker #extension GL_OES_geometry_shader : require
1652*8975f5c5SAndroid Build Coastguard Worker layout (points)                   in;
1653*8975f5c5SAndroid Build Coastguard Worker layout (points, max_vertices = 1) out;
1654*8975f5c5SAndroid Build Coastguard Worker 
1655*8975f5c5SAndroid Build Coastguard Worker precision highp iimage2D;
1656*8975f5c5SAndroid Build Coastguard Worker 
1657*8975f5c5SAndroid Build Coastguard Worker ivec4 counter = ivec4(0);
1658*8975f5c5SAndroid Build Coastguard Worker )";
1659*8975f5c5SAndroid Build Coastguard Worker 
1660*8975f5c5SAndroid Build Coastguard Worker     for (GLint index = 0; index < maxGeometryImageUnits; ++index)
1661*8975f5c5SAndroid Build Coastguard Worker     {
1662*8975f5c5SAndroid Build Coastguard Worker         geomStringStream << "layout(binding = " << index << ", r32i) uniform iimage2D img" << index
1663*8975f5c5SAndroid Build Coastguard Worker                          << ";" << std::endl;
1664*8975f5c5SAndroid Build Coastguard Worker     }
1665*8975f5c5SAndroid Build Coastguard Worker 
1666*8975f5c5SAndroid Build Coastguard Worker     geomStringStream << R"(
1667*8975f5c5SAndroid Build Coastguard Worker void main()
1668*8975f5c5SAndroid Build Coastguard Worker {
1669*8975f5c5SAndroid Build Coastguard Worker )";
1670*8975f5c5SAndroid Build Coastguard Worker 
1671*8975f5c5SAndroid Build Coastguard Worker     for (GLint index = 0; index < maxGeometryImageUnits; ++index)
1672*8975f5c5SAndroid Build Coastguard Worker     {
1673*8975f5c5SAndroid Build Coastguard Worker         geomStringStream << "counter += imageLoad(img" << index << ", ivec2(0, 0));" << std::endl;
1674*8975f5c5SAndroid Build Coastguard Worker     }
1675*8975f5c5SAndroid Build Coastguard Worker 
1676*8975f5c5SAndroid Build Coastguard Worker     geomStringStream << R"(
1677*8975f5c5SAndroid Build Coastguard Worker     gl_Position = vec4(float(counter.x), 0.0, 0.0, 1.0);
1678*8975f5c5SAndroid Build Coastguard Worker     EmitVertex();
1679*8975f5c5SAndroid Build Coastguard Worker }
1680*8975f5c5SAndroid Build Coastguard Worker )";
1681*8975f5c5SAndroid Build Coastguard Worker 
1682*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_PROGRAM_WITH_GS(program, vertString, geomStringStream.str().c_str(), fragString);
1683*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1684*8975f5c5SAndroid Build Coastguard Worker 
1685*8975f5c5SAndroid Build Coastguard Worker     glClearColor(1.0, 0, 0, 1.0);
1686*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT);
1687*8975f5c5SAndroid Build Coastguard Worker 
1688*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(program);
1689*8975f5c5SAndroid Build Coastguard Worker 
1690*8975f5c5SAndroid Build Coastguard Worker     std::vector<GLTexture> textures(maxGeometryImageUnits);
1691*8975f5c5SAndroid Build Coastguard Worker     for (GLint index = 0; index < maxGeometryImageUnits; ++index)
1692*8975f5c5SAndroid Build Coastguard Worker     {
1693*8975f5c5SAndroid Build Coastguard Worker         GLint value = index + 1;
1694*8975f5c5SAndroid Build Coastguard Worker 
1695*8975f5c5SAndroid Build Coastguard Worker         glBindTexture(GL_TEXTURE_2D, textures[index]);
1696*8975f5c5SAndroid Build Coastguard Worker 
1697*8975f5c5SAndroid Build Coastguard Worker         glTexStorage2D(GL_TEXTURE_2D, 1 /*levels*/, GL_R32I, 1 /*width*/, 1 /*height*/);
1698*8975f5c5SAndroid Build Coastguard Worker 
1699*8975f5c5SAndroid Build Coastguard Worker         glTexSubImage2D(GL_TEXTURE_2D, 0 /*level*/, 0 /*xoffset*/, 0 /*yoffset*/, 1 /*width*/,
1700*8975f5c5SAndroid Build Coastguard Worker                         1 /*height*/, GL_RED_INTEGER, GL_INT, &value);
1701*8975f5c5SAndroid Build Coastguard Worker 
1702*8975f5c5SAndroid Build Coastguard Worker         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1703*8975f5c5SAndroid Build Coastguard Worker 
1704*8975f5c5SAndroid Build Coastguard Worker         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1705*8975f5c5SAndroid Build Coastguard Worker 
1706*8975f5c5SAndroid Build Coastguard Worker         glBindImageTexture(index, textures[index], 0 /*level*/, GL_FALSE /*is layered?*/,
1707*8975f5c5SAndroid Build Coastguard Worker                            0 /*layer*/, GL_READ_ONLY, GL_R32I);
1708*8975f5c5SAndroid Build Coastguard Worker     }
1709*8975f5c5SAndroid Build Coastguard Worker 
1710*8975f5c5SAndroid Build Coastguard Worker     glDrawArrays(GL_POINTS, 0, 3);
1711*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1712*8975f5c5SAndroid Build Coastguard Worker }
1713*8975f5c5SAndroid Build Coastguard Worker 
1714*8975f5c5SAndroid Build Coastguard Worker // Verify that depth viewport transform applies to the geometry shader stage if present.
TEST_P(GeometryShaderTest,DepthViewportTransform)1715*8975f5c5SAndroid Build Coastguard Worker TEST_P(GeometryShaderTest, DepthViewportTransform)
1716*8975f5c5SAndroid Build Coastguard Worker {
1717*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
1718*8975f5c5SAndroid Build Coastguard Worker 
1719*8975f5c5SAndroid Build Coastguard Worker     constexpr char kVS[] = R"(#version 310 es
1720*8975f5c5SAndroid Build Coastguard Worker void main()
1721*8975f5c5SAndroid Build Coastguard Worker {
1722*8975f5c5SAndroid Build Coastguard Worker     // Geometry shader will output fixed positions, so this is ignored.
1723*8975f5c5SAndroid Build Coastguard Worker     gl_Position = vec4(0);
1724*8975f5c5SAndroid Build Coastguard Worker })";
1725*8975f5c5SAndroid Build Coastguard Worker 
1726*8975f5c5SAndroid Build Coastguard Worker     constexpr char kGS[] = R"(#version 310 es
1727*8975f5c5SAndroid Build Coastguard Worker #extension GL_EXT_geometry_shader : require
1728*8975f5c5SAndroid Build Coastguard Worker layout (triangles) in;
1729*8975f5c5SAndroid Build Coastguard Worker layout (triangle_strip, max_vertices = 4) out;
1730*8975f5c5SAndroid Build Coastguard Worker 
1731*8975f5c5SAndroid Build Coastguard Worker void main()
1732*8975f5c5SAndroid Build Coastguard Worker {
1733*8975f5c5SAndroid Build Coastguard Worker     // Generate two triangles to cover the whole screen, with depth at -0.5.  After viewport
1734*8975f5c5SAndroid Build Coastguard Worker     // transformation, the depth buffer should contain 0.25.
1735*8975f5c5SAndroid Build Coastguard Worker     gl_Position = vec4(1, -1, -0.5, 1);
1736*8975f5c5SAndroid Build Coastguard Worker     EmitVertex();
1737*8975f5c5SAndroid Build Coastguard Worker 
1738*8975f5c5SAndroid Build Coastguard Worker     gl_Position = vec4(1, 1, -0.5, 1);
1739*8975f5c5SAndroid Build Coastguard Worker     EmitVertex();
1740*8975f5c5SAndroid Build Coastguard Worker 
1741*8975f5c5SAndroid Build Coastguard Worker     gl_Position = vec4(-1, -1, -0.5, 1);
1742*8975f5c5SAndroid Build Coastguard Worker     EmitVertex();
1743*8975f5c5SAndroid Build Coastguard Worker 
1744*8975f5c5SAndroid Build Coastguard Worker     gl_Position = vec4(-1, 1, -0.5, 1);
1745*8975f5c5SAndroid Build Coastguard Worker     EmitVertex();
1746*8975f5c5SAndroid Build Coastguard Worker 
1747*8975f5c5SAndroid Build Coastguard Worker     EndPrimitive();
1748*8975f5c5SAndroid Build Coastguard Worker })";
1749*8975f5c5SAndroid Build Coastguard Worker 
1750*8975f5c5SAndroid Build Coastguard Worker     constexpr char kFS[] = R"(#version 310 es
1751*8975f5c5SAndroid Build Coastguard Worker #extension GL_EXT_shader_io_blocks : require
1752*8975f5c5SAndroid Build Coastguard Worker precision mediump float;
1753*8975f5c5SAndroid Build Coastguard Worker 
1754*8975f5c5SAndroid Build Coastguard Worker layout(location = 0) out mediump vec4 color;
1755*8975f5c5SAndroid Build Coastguard Worker 
1756*8975f5c5SAndroid Build Coastguard Worker void main()
1757*8975f5c5SAndroid Build Coastguard Worker {
1758*8975f5c5SAndroid Build Coastguard Worker     // Output solid green
1759*8975f5c5SAndroid Build Coastguard Worker     color = vec4(0, 1.0, 0, 1.0);
1760*8975f5c5SAndroid Build Coastguard Worker })";
1761*8975f5c5SAndroid Build Coastguard Worker 
1762*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_PROGRAM_WITH_GS(program, kVS, kGS, kFS);
1763*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1764*8975f5c5SAndroid Build Coastguard Worker 
1765*8975f5c5SAndroid Build Coastguard Worker     glClearColor(1.0, 0, 0, 1.0);
1766*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT);
1767*8975f5c5SAndroid Build Coastguard Worker 
1768*8975f5c5SAndroid Build Coastguard Worker     glEnable(GL_DEPTH_TEST);
1769*8975f5c5SAndroid Build Coastguard Worker     glDepthFunc(GL_ALWAYS);
1770*8975f5c5SAndroid Build Coastguard Worker 
1771*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(program);
1772*8975f5c5SAndroid Build Coastguard Worker     glDrawArrays(GL_TRIANGLES, 0, 3);
1773*8975f5c5SAndroid Build Coastguard Worker 
1774*8975f5c5SAndroid Build Coastguard Worker     const int w = getWindowWidth();
1775*8975f5c5SAndroid Build Coastguard Worker     const int h = getWindowHeight();
1776*8975f5c5SAndroid Build Coastguard Worker 
1777*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::green);
1778*8975f5c5SAndroid Build Coastguard Worker 
1779*8975f5c5SAndroid Build Coastguard Worker     // Verify depth
1780*8975f5c5SAndroid Build Coastguard Worker     glDepthFunc(GL_LESS);
1781*8975f5c5SAndroid Build Coastguard Worker 
1782*8975f5c5SAndroid Build Coastguard Worker     // An epsilon below the depth value should pass the depth test
1783*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_PROGRAM(drawBlue, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
1784*8975f5c5SAndroid Build Coastguard Worker     drawQuad(drawBlue, essl1_shaders::PositionAttrib(), -0.5f - 0.01f);
1785*8975f5c5SAndroid Build Coastguard Worker 
1786*8975f5c5SAndroid Build Coastguard Worker     // An epsilon above the depth value should fail the depth test
1787*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1788*8975f5c5SAndroid Build Coastguard Worker     drawQuad(drawRed, essl1_shaders::PositionAttrib(), -0.5f + 0.01f);
1789*8975f5c5SAndroid Build Coastguard Worker 
1790*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_RECT_EQ(0, 0, w, h, GLColor::blue);
1791*8975f5c5SAndroid Build Coastguard Worker }
1792*8975f5c5SAndroid Build Coastguard Worker 
1793*8975f5c5SAndroid Build Coastguard Worker // Tests separating the VS from the GS/FS and then modifying the shader.
TEST_P(GeometryShaderTest,RecompileSeparableVSWithVaryings)1794*8975f5c5SAndroid Build Coastguard Worker TEST_P(GeometryShaderTest, RecompileSeparableVSWithVaryings)
1795*8975f5c5SAndroid Build Coastguard Worker {
1796*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
1797*8975f5c5SAndroid Build Coastguard Worker 
1798*8975f5c5SAndroid Build Coastguard Worker     // Errors in D3D11/GL. No plans to fix this.
1799*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan());
1800*8975f5c5SAndroid Build Coastguard Worker 
1801*8975f5c5SAndroid Build Coastguard Worker     const char *kVS = R"(#version 310 es
1802*8975f5c5SAndroid Build Coastguard Worker precision mediump float;
1803*8975f5c5SAndroid Build Coastguard Worker in vec4 position;
1804*8975f5c5SAndroid Build Coastguard Worker out vec4 vgVarying;
1805*8975f5c5SAndroid Build Coastguard Worker uniform vec4 uniVec;
1806*8975f5c5SAndroid Build Coastguard Worker void main()
1807*8975f5c5SAndroid Build Coastguard Worker {
1808*8975f5c5SAndroid Build Coastguard Worker    vgVarying = uniVec;
1809*8975f5c5SAndroid Build Coastguard Worker    gl_Position = position;
1810*8975f5c5SAndroid Build Coastguard Worker })";
1811*8975f5c5SAndroid Build Coastguard Worker 
1812*8975f5c5SAndroid Build Coastguard Worker     const char *kGS = R"(#version 310 es
1813*8975f5c5SAndroid Build Coastguard Worker #extension GL_EXT_geometry_shader : require
1814*8975f5c5SAndroid Build Coastguard Worker 
1815*8975f5c5SAndroid Build Coastguard Worker precision mediump float;
1816*8975f5c5SAndroid Build Coastguard Worker 
1817*8975f5c5SAndroid Build Coastguard Worker layout (triangles) in;
1818*8975f5c5SAndroid Build Coastguard Worker layout (triangle_strip, max_vertices = 4) out;
1819*8975f5c5SAndroid Build Coastguard Worker 
1820*8975f5c5SAndroid Build Coastguard Worker in vec4 vgVarying[];
1821*8975f5c5SAndroid Build Coastguard Worker layout(location = 5) out vec4 gfVarying;
1822*8975f5c5SAndroid Build Coastguard Worker 
1823*8975f5c5SAndroid Build Coastguard Worker void main()
1824*8975f5c5SAndroid Build Coastguard Worker {
1825*8975f5c5SAndroid Build Coastguard Worker     for (int n = 0; n < gl_in.length(); n++)
1826*8975f5c5SAndroid Build Coastguard Worker     {
1827*8975f5c5SAndroid Build Coastguard Worker         gl_Position = gl_in[n].gl_Position;
1828*8975f5c5SAndroid Build Coastguard Worker         gfVarying = vgVarying[n];
1829*8975f5c5SAndroid Build Coastguard Worker         EmitVertex();
1830*8975f5c5SAndroid Build Coastguard Worker     }
1831*8975f5c5SAndroid Build Coastguard Worker     EndPrimitive();
1832*8975f5c5SAndroid Build Coastguard Worker })";
1833*8975f5c5SAndroid Build Coastguard Worker 
1834*8975f5c5SAndroid Build Coastguard Worker     const char *kFS = R"(#version 310 es
1835*8975f5c5SAndroid Build Coastguard Worker precision mediump float;
1836*8975f5c5SAndroid Build Coastguard Worker 
1837*8975f5c5SAndroid Build Coastguard Worker layout(location = 5) in vec4 gfVarying;
1838*8975f5c5SAndroid Build Coastguard Worker out vec4 fOut;
1839*8975f5c5SAndroid Build Coastguard Worker 
1840*8975f5c5SAndroid Build Coastguard Worker void main()
1841*8975f5c5SAndroid Build Coastguard Worker {
1842*8975f5c5SAndroid Build Coastguard Worker     fOut = gfVarying;
1843*8975f5c5SAndroid Build Coastguard Worker })";
1844*8975f5c5SAndroid Build Coastguard Worker 
1845*8975f5c5SAndroid Build Coastguard Worker     GLShader vertShader(GL_VERTEX_SHADER);
1846*8975f5c5SAndroid Build Coastguard Worker     glShaderSource(vertShader, 1, &kVS, nullptr);
1847*8975f5c5SAndroid Build Coastguard Worker     glCompileShader(vertShader);
1848*8975f5c5SAndroid Build Coastguard Worker 
1849*8975f5c5SAndroid Build Coastguard Worker     GLProgram vertProg;
1850*8975f5c5SAndroid Build Coastguard Worker     glProgramParameteri(vertProg, GL_PROGRAM_SEPARABLE, GL_TRUE);
1851*8975f5c5SAndroid Build Coastguard Worker     glAttachShader(vertProg, vertShader);
1852*8975f5c5SAndroid Build Coastguard Worker     glLinkProgram(vertProg);
1853*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1854*8975f5c5SAndroid Build Coastguard Worker 
1855*8975f5c5SAndroid Build Coastguard Worker     GLShader geomShader(GL_GEOMETRY_SHADER);
1856*8975f5c5SAndroid Build Coastguard Worker     glShaderSource(geomShader, 1, &kGS, nullptr);
1857*8975f5c5SAndroid Build Coastguard Worker     glCompileShader(geomShader);
1858*8975f5c5SAndroid Build Coastguard Worker 
1859*8975f5c5SAndroid Build Coastguard Worker     GLShader fragShader(GL_FRAGMENT_SHADER);
1860*8975f5c5SAndroid Build Coastguard Worker     glShaderSource(fragShader, 1, &kFS, nullptr);
1861*8975f5c5SAndroid Build Coastguard Worker     glCompileShader(fragShader);
1862*8975f5c5SAndroid Build Coastguard Worker 
1863*8975f5c5SAndroid Build Coastguard Worker     GLProgram geomFragProg;
1864*8975f5c5SAndroid Build Coastguard Worker     glProgramParameteri(geomFragProg, GL_PROGRAM_SEPARABLE, GL_TRUE);
1865*8975f5c5SAndroid Build Coastguard Worker     glAttachShader(geomFragProg, geomShader);
1866*8975f5c5SAndroid Build Coastguard Worker     glAttachShader(geomFragProg, fragShader);
1867*8975f5c5SAndroid Build Coastguard Worker     glLinkProgram(geomFragProg);
1868*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1869*8975f5c5SAndroid Build Coastguard Worker 
1870*8975f5c5SAndroid Build Coastguard Worker     GLProgramPipeline pipeline;
1871*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(pipeline, GL_VERTEX_SHADER_BIT, vertProg);
1872*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(pipeline, GL_GEOMETRY_SHADER_BIT, geomFragProg);
1873*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, geomFragProg);
1874*8975f5c5SAndroid Build Coastguard Worker     glBindProgramPipeline(pipeline);
1875*8975f5c5SAndroid Build Coastguard Worker 
1876*8975f5c5SAndroid Build Coastguard Worker     glActiveShaderProgram(pipeline, vertProg);
1877*8975f5c5SAndroid Build Coastguard Worker     GLint uniLoc = glGetUniformLocation(vertProg, "uniVec");
1878*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(-1, uniLoc);
1879*8975f5c5SAndroid Build Coastguard Worker     glUniform4f(uniLoc, 0, 1, 0, 1);
1880*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1881*8975f5c5SAndroid Build Coastguard Worker 
1882*8975f5c5SAndroid Build Coastguard Worker     drawQuadPPO(vertProg, "position", 0.5f, 1.0f);
1883*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1884*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1885*8975f5c5SAndroid Build Coastguard Worker 
1886*8975f5c5SAndroid Build Coastguard Worker     // Do it again with deleted shaders.
1887*8975f5c5SAndroid Build Coastguard Worker     vertProg.reset();
1888*8975f5c5SAndroid Build Coastguard Worker     geomFragProg.reset();
1889*8975f5c5SAndroid Build Coastguard Worker     pipeline.reset();
1890*8975f5c5SAndroid Build Coastguard Worker 
1891*8975f5c5SAndroid Build Coastguard Worker     glProgramParameteri(vertProg, GL_PROGRAM_SEPARABLE, GL_TRUE);
1892*8975f5c5SAndroid Build Coastguard Worker     glAttachShader(vertProg, vertShader);
1893*8975f5c5SAndroid Build Coastguard Worker     glLinkProgram(vertProg);
1894*8975f5c5SAndroid Build Coastguard Worker 
1895*8975f5c5SAndroid Build Coastguard Worker     // Mess up the VS.
1896*8975f5c5SAndroid Build Coastguard Worker     const char *otherVS = essl1_shaders::vs::Texture2D();
1897*8975f5c5SAndroid Build Coastguard Worker     glShaderSource(vertShader, 1, &otherVS, nullptr);
1898*8975f5c5SAndroid Build Coastguard Worker     glCompileShader(vertShader);
1899*8975f5c5SAndroid Build Coastguard Worker 
1900*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1901*8975f5c5SAndroid Build Coastguard Worker 
1902*8975f5c5SAndroid Build Coastguard Worker     glProgramParameteri(geomFragProg, GL_PROGRAM_SEPARABLE, GL_TRUE);
1903*8975f5c5SAndroid Build Coastguard Worker     glAttachShader(geomFragProg, geomShader);
1904*8975f5c5SAndroid Build Coastguard Worker     glAttachShader(geomFragProg, fragShader);
1905*8975f5c5SAndroid Build Coastguard Worker     glLinkProgram(geomFragProg);
1906*8975f5c5SAndroid Build Coastguard Worker 
1907*8975f5c5SAndroid Build Coastguard Worker     // Mess up the FS.
1908*8975f5c5SAndroid Build Coastguard Worker     const char *otherFS = essl1_shaders::fs::Texture2D();
1909*8975f5c5SAndroid Build Coastguard Worker     glShaderSource(fragShader, 1, &otherFS, nullptr);
1910*8975f5c5SAndroid Build Coastguard Worker     glCompileShader(fragShader);
1911*8975f5c5SAndroid Build Coastguard Worker 
1912*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1913*8975f5c5SAndroid Build Coastguard Worker 
1914*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(pipeline, GL_VERTEX_SHADER_BIT, vertProg);
1915*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(pipeline, GL_GEOMETRY_SHADER_BIT, geomFragProg);
1916*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, geomFragProg);
1917*8975f5c5SAndroid Build Coastguard Worker     glBindProgramPipeline(pipeline);
1918*8975f5c5SAndroid Build Coastguard Worker 
1919*8975f5c5SAndroid Build Coastguard Worker     glActiveShaderProgram(pipeline, vertProg);
1920*8975f5c5SAndroid Build Coastguard Worker     uniLoc = glGetUniformLocation(vertProg, "uniVec");
1921*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(-1, uniLoc);
1922*8975f5c5SAndroid Build Coastguard Worker     glUniform4f(uniLoc, 0, 1, 0, 1);
1923*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1924*8975f5c5SAndroid Build Coastguard Worker 
1925*8975f5c5SAndroid Build Coastguard Worker     drawQuadPPO(vertProg, "position", 0.5f, 1.0f);
1926*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1927*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1928*8975f5c5SAndroid Build Coastguard Worker }
1929*8975f5c5SAndroid Build Coastguard Worker 
1930*8975f5c5SAndroid Build Coastguard Worker // Tests that varying limits work as expected with geometry shaders.
TEST_P(GeometryShaderTest,MaxVaryings)1931*8975f5c5SAndroid Build Coastguard Worker TEST_P(GeometryShaderTest, MaxVaryings)
1932*8975f5c5SAndroid Build Coastguard Worker {
1933*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
1934*8975f5c5SAndroid Build Coastguard Worker 
1935*8975f5c5SAndroid Build Coastguard Worker     // Get appropriate limitations.
1936*8975f5c5SAndroid Build Coastguard Worker     GLint maxVertexOutputComponents = 0;
1937*8975f5c5SAndroid Build Coastguard Worker     glGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS, &maxVertexOutputComponents);
1938*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GT(maxVertexOutputComponents, 0);
1939*8975f5c5SAndroid Build Coastguard Worker 
1940*8975f5c5SAndroid Build Coastguard Worker     GLint maxGeometryInputComponents = 0;
1941*8975f5c5SAndroid Build Coastguard Worker     glGetIntegerv(GL_MAX_GEOMETRY_INPUT_COMPONENTS, &maxGeometryInputComponents);
1942*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GT(maxGeometryInputComponents, 0);
1943*8975f5c5SAndroid Build Coastguard Worker 
1944*8975f5c5SAndroid Build Coastguard Worker     GLint maxGeometryOutputComponents = 0;
1945*8975f5c5SAndroid Build Coastguard Worker     glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_COMPONENTS, &maxGeometryOutputComponents);
1946*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GT(maxGeometryOutputComponents, 0);
1947*8975f5c5SAndroid Build Coastguard Worker 
1948*8975f5c5SAndroid Build Coastguard Worker     GLint maxFragmentInputComponents = 0;
1949*8975f5c5SAndroid Build Coastguard Worker     glGetIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS, &maxFragmentInputComponents);
1950*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GT(maxFragmentInputComponents, 0);
1951*8975f5c5SAndroid Build Coastguard Worker 
1952*8975f5c5SAndroid Build Coastguard Worker     GLint vertexToGeometryVaryings =
1953*8975f5c5SAndroid Build Coastguard Worker         std::min(maxVertexOutputComponents, maxGeometryInputComponents) / 4;
1954*8975f5c5SAndroid Build Coastguard Worker     GLint geometryToFragmentVaryings =
1955*8975f5c5SAndroid Build Coastguard Worker         std::min(maxGeometryOutputComponents, maxFragmentInputComponents) / 4;
1956*8975f5c5SAndroid Build Coastguard Worker 
1957*8975f5c5SAndroid Build Coastguard Worker     GLint varyingCount = std::min(vertexToGeometryVaryings, geometryToFragmentVaryings);
1958*8975f5c5SAndroid Build Coastguard Worker 
1959*8975f5c5SAndroid Build Coastguard Worker     // Reserve gl_Position;
1960*8975f5c5SAndroid Build Coastguard Worker     varyingCount--;
1961*8975f5c5SAndroid Build Coastguard Worker 
1962*8975f5c5SAndroid Build Coastguard Worker     // Create a vertex shader with "varyingCount" outputs.
1963*8975f5c5SAndroid Build Coastguard Worker     std::stringstream vsStream;
1964*8975f5c5SAndroid Build Coastguard Worker     vsStream << R"(#version 310 es
1965*8975f5c5SAndroid Build Coastguard Worker uniform vec4 uniOne;
1966*8975f5c5SAndroid Build Coastguard Worker in vec4 position;
1967*8975f5c5SAndroid Build Coastguard Worker )";
1968*8975f5c5SAndroid Build Coastguard Worker 
1969*8975f5c5SAndroid Build Coastguard Worker     for (GLint varyingIndex = 0; varyingIndex < varyingCount; ++varyingIndex)
1970*8975f5c5SAndroid Build Coastguard Worker     {
1971*8975f5c5SAndroid Build Coastguard Worker         vsStream << "out vec4 v" << varyingIndex << ";\n";
1972*8975f5c5SAndroid Build Coastguard Worker     }
1973*8975f5c5SAndroid Build Coastguard Worker 
1974*8975f5c5SAndroid Build Coastguard Worker     vsStream << R"(
1975*8975f5c5SAndroid Build Coastguard Worker void main()
1976*8975f5c5SAndroid Build Coastguard Worker {
1977*8975f5c5SAndroid Build Coastguard Worker     gl_Position = position;
1978*8975f5c5SAndroid Build Coastguard Worker )";
1979*8975f5c5SAndroid Build Coastguard Worker 
1980*8975f5c5SAndroid Build Coastguard Worker     for (GLint varyingIndex = 0; varyingIndex < varyingCount; ++varyingIndex)
1981*8975f5c5SAndroid Build Coastguard Worker     {
1982*8975f5c5SAndroid Build Coastguard Worker         vsStream << "    v" << varyingIndex << " = uniOne * " << varyingIndex << ".0;\n";
1983*8975f5c5SAndroid Build Coastguard Worker     }
1984*8975f5c5SAndroid Build Coastguard Worker 
1985*8975f5c5SAndroid Build Coastguard Worker     vsStream << "}";
1986*8975f5c5SAndroid Build Coastguard Worker 
1987*8975f5c5SAndroid Build Coastguard Worker     // Create a GS with "varyingCount" inputs and "varyingCount" outputs.
1988*8975f5c5SAndroid Build Coastguard Worker     std::stringstream gsStream;
1989*8975f5c5SAndroid Build Coastguard Worker     gsStream << R"(#version 310 es
1990*8975f5c5SAndroid Build Coastguard Worker #extension GL_EXT_geometry_shader : require
1991*8975f5c5SAndroid Build Coastguard Worker layout (triangles) in;
1992*8975f5c5SAndroid Build Coastguard Worker layout (triangle_strip, max_vertices = 4) out;
1993*8975f5c5SAndroid Build Coastguard Worker )";
1994*8975f5c5SAndroid Build Coastguard Worker 
1995*8975f5c5SAndroid Build Coastguard Worker     for (GLint varyingIndex = 0; varyingIndex < varyingCount; ++varyingIndex)
1996*8975f5c5SAndroid Build Coastguard Worker     {
1997*8975f5c5SAndroid Build Coastguard Worker         gsStream << "in vec4 v" << varyingIndex << "[];\n";
1998*8975f5c5SAndroid Build Coastguard Worker     }
1999*8975f5c5SAndroid Build Coastguard Worker 
2000*8975f5c5SAndroid Build Coastguard Worker     for (GLint varyingIndex = 0; varyingIndex < varyingCount; ++varyingIndex)
2001*8975f5c5SAndroid Build Coastguard Worker     {
2002*8975f5c5SAndroid Build Coastguard Worker         gsStream << "out vec4 o" << varyingIndex << ";\n";
2003*8975f5c5SAndroid Build Coastguard Worker     }
2004*8975f5c5SAndroid Build Coastguard Worker 
2005*8975f5c5SAndroid Build Coastguard Worker     gsStream << R"(
2006*8975f5c5SAndroid Build Coastguard Worker void main()
2007*8975f5c5SAndroid Build Coastguard Worker {
2008*8975f5c5SAndroid Build Coastguard Worker     for (int n = 0; n < gl_in.length(); n++)
2009*8975f5c5SAndroid Build Coastguard Worker     {
2010*8975f5c5SAndroid Build Coastguard Worker         gl_Position = gl_in[n].gl_Position;
2011*8975f5c5SAndroid Build Coastguard Worker )";
2012*8975f5c5SAndroid Build Coastguard Worker 
2013*8975f5c5SAndroid Build Coastguard Worker     for (GLint varyingIndex = 0; varyingIndex < varyingCount; ++varyingIndex)
2014*8975f5c5SAndroid Build Coastguard Worker     {
2015*8975f5c5SAndroid Build Coastguard Worker         gsStream << "        o" << varyingIndex << " = v" << varyingIndex << "[n];\n";
2016*8975f5c5SAndroid Build Coastguard Worker     }
2017*8975f5c5SAndroid Build Coastguard Worker 
2018*8975f5c5SAndroid Build Coastguard Worker     gsStream << R"(
2019*8975f5c5SAndroid Build Coastguard Worker         EmitVertex();
2020*8975f5c5SAndroid Build Coastguard Worker     }
2021*8975f5c5SAndroid Build Coastguard Worker     EndPrimitive();
2022*8975f5c5SAndroid Build Coastguard Worker }
2023*8975f5c5SAndroid Build Coastguard Worker )";
2024*8975f5c5SAndroid Build Coastguard Worker 
2025*8975f5c5SAndroid Build Coastguard Worker     // Create a FS with "varyingCount" inputs.
2026*8975f5c5SAndroid Build Coastguard Worker     std::stringstream fsStream;
2027*8975f5c5SAndroid Build Coastguard Worker     fsStream << R"(#version 310 es
2028*8975f5c5SAndroid Build Coastguard Worker precision mediump float;
2029*8975f5c5SAndroid Build Coastguard Worker out vec4 color;
2030*8975f5c5SAndroid Build Coastguard Worker )";
2031*8975f5c5SAndroid Build Coastguard Worker 
2032*8975f5c5SAndroid Build Coastguard Worker     for (GLint varyingIndex = 0; varyingIndex < varyingCount; ++varyingIndex)
2033*8975f5c5SAndroid Build Coastguard Worker     {
2034*8975f5c5SAndroid Build Coastguard Worker         fsStream << "in vec4 o" << varyingIndex << ";\n";
2035*8975f5c5SAndroid Build Coastguard Worker     }
2036*8975f5c5SAndroid Build Coastguard Worker 
2037*8975f5c5SAndroid Build Coastguard Worker     fsStream << R"(
2038*8975f5c5SAndroid Build Coastguard Worker void main()
2039*8975f5c5SAndroid Build Coastguard Worker {
2040*8975f5c5SAndroid Build Coastguard Worker     color = vec4(0, 1, 0, 1);
2041*8975f5c5SAndroid Build Coastguard Worker )";
2042*8975f5c5SAndroid Build Coastguard Worker 
2043*8975f5c5SAndroid Build Coastguard Worker     for (GLint varyingIndex = 0; varyingIndex < varyingCount; ++varyingIndex)
2044*8975f5c5SAndroid Build Coastguard Worker     {
2045*8975f5c5SAndroid Build Coastguard Worker         fsStream << "    if (o" << varyingIndex << " != vec4(" << varyingIndex << ".0))\n"
2046*8975f5c5SAndroid Build Coastguard Worker                  << "        color = vec4(1, 0, 0, 1);\n";
2047*8975f5c5SAndroid Build Coastguard Worker     }
2048*8975f5c5SAndroid Build Coastguard Worker 
2049*8975f5c5SAndroid Build Coastguard Worker     fsStream << "}";
2050*8975f5c5SAndroid Build Coastguard Worker 
2051*8975f5c5SAndroid Build Coastguard Worker     const std::string vs = vsStream.str();
2052*8975f5c5SAndroid Build Coastguard Worker     const std::string gs = gsStream.str();
2053*8975f5c5SAndroid Build Coastguard Worker     const std::string fs = fsStream.str();
2054*8975f5c5SAndroid Build Coastguard Worker 
2055*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_PROGRAM_WITH_GS(program, vs.c_str(), gs.c_str(), fs.c_str());
2056*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(program);
2057*8975f5c5SAndroid Build Coastguard Worker 
2058*8975f5c5SAndroid Build Coastguard Worker     GLint uniLoc = glGetUniformLocation(program, "uniOne");
2059*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(-1, uniLoc);
2060*8975f5c5SAndroid Build Coastguard Worker     glUniform4f(uniLoc, 1.0f, 1.0f, 1.0f, 1.0f);
2061*8975f5c5SAndroid Build Coastguard Worker 
2062*8975f5c5SAndroid Build Coastguard Worker     drawQuad(program, "position", 0.5f, 1.0f, true);
2063*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
2064*8975f5c5SAndroid Build Coastguard Worker 
2065*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2066*8975f5c5SAndroid Build Coastguard Worker }
2067*8975f5c5SAndroid Build Coastguard Worker 
2068*8975f5c5SAndroid Build Coastguard Worker GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GeometryShaderTestES3);
2069*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST_ES3(GeometryShaderTestES3);
2070*8975f5c5SAndroid Build Coastguard Worker 
2071*8975f5c5SAndroid Build Coastguard Worker GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GeometryShaderTest);
2072*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST_ES31_AND(GeometryShaderTest,
2073*8975f5c5SAndroid Build Coastguard Worker                                 ES31_VULKAN().enable(Feature::EmulatedPrerotation90),
2074*8975f5c5SAndroid Build Coastguard Worker                                 ES31_VULKAN().enable(Feature::EmulatedPrerotation180),
2075*8975f5c5SAndroid Build Coastguard Worker                                 ES31_VULKAN().enable(Feature::EmulatedPrerotation270));
2076*8975f5c5SAndroid Build Coastguard Worker 
2077*8975f5c5SAndroid Build Coastguard Worker GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GeometryShaderTestES32);
2078*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST_ES32(GeometryShaderTestES32);
2079*8975f5c5SAndroid Build Coastguard Worker }  // namespace
2080