xref: /aosp_15_r20/external/angle/src/tests/gl_tests/AtomicCounterBufferTest.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 // AtomicCounterBufferTest:
7*8975f5c5SAndroid Build Coastguard Worker //   Various tests related for atomic counter buffers.
8*8975f5c5SAndroid Build Coastguard Worker //
9*8975f5c5SAndroid Build Coastguard Worker 
10*8975f5c5SAndroid Build Coastguard Worker #include "test_utils/ANGLETest.h"
11*8975f5c5SAndroid Build Coastguard Worker #include "test_utils/gl_raii.h"
12*8975f5c5SAndroid Build Coastguard Worker 
13*8975f5c5SAndroid Build Coastguard Worker using namespace angle;
14*8975f5c5SAndroid Build Coastguard Worker 
15*8975f5c5SAndroid Build Coastguard Worker namespace
16*8975f5c5SAndroid Build Coastguard Worker {
17*8975f5c5SAndroid Build Coastguard Worker 
18*8975f5c5SAndroid Build Coastguard Worker class AtomicCounterBufferTest : public ANGLETest<>
19*8975f5c5SAndroid Build Coastguard Worker {
20*8975f5c5SAndroid Build Coastguard Worker   protected:
AtomicCounterBufferTest()21*8975f5c5SAndroid Build Coastguard Worker     AtomicCounterBufferTest()
22*8975f5c5SAndroid Build Coastguard Worker     {
23*8975f5c5SAndroid Build Coastguard Worker         setWindowWidth(128);
24*8975f5c5SAndroid Build Coastguard Worker         setWindowHeight(128);
25*8975f5c5SAndroid Build Coastguard Worker         setConfigRedBits(8);
26*8975f5c5SAndroid Build Coastguard Worker         setConfigGreenBits(8);
27*8975f5c5SAndroid Build Coastguard Worker         setConfigBlueBits(8);
28*8975f5c5SAndroid Build Coastguard Worker         setConfigAlphaBits(8);
29*8975f5c5SAndroid Build Coastguard Worker     }
30*8975f5c5SAndroid Build Coastguard Worker };
31*8975f5c5SAndroid Build Coastguard Worker 
32*8975f5c5SAndroid Build Coastguard Worker // Test GL_ATOMIC_COUNTER_BUFFER is not supported with version lower than ES31.
TEST_P(AtomicCounterBufferTest,AtomicCounterBufferBindings)33*8975f5c5SAndroid Build Coastguard Worker TEST_P(AtomicCounterBufferTest, AtomicCounterBufferBindings)
34*8975f5c5SAndroid Build Coastguard Worker {
35*8975f5c5SAndroid Build Coastguard Worker     ASSERT_EQ(3, getClientMajorVersion());
36*8975f5c5SAndroid Build Coastguard Worker     GLBuffer atomicCounterBuffer;
37*8975f5c5SAndroid Build Coastguard Worker     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
38*8975f5c5SAndroid Build Coastguard Worker     if (getClientMinorVersion() < 1)
39*8975f5c5SAndroid Build Coastguard Worker     {
40*8975f5c5SAndroid Build Coastguard Worker         EXPECT_GL_ERROR(GL_INVALID_ENUM);
41*8975f5c5SAndroid Build Coastguard Worker     }
42*8975f5c5SAndroid Build Coastguard Worker     else
43*8975f5c5SAndroid Build Coastguard Worker     {
44*8975f5c5SAndroid Build Coastguard Worker         EXPECT_GL_NO_ERROR();
45*8975f5c5SAndroid Build Coastguard Worker     }
46*8975f5c5SAndroid Build Coastguard Worker }
47*8975f5c5SAndroid Build Coastguard Worker 
48*8975f5c5SAndroid Build Coastguard Worker class AtomicCounterBufferTest31 : public AtomicCounterBufferTest
49*8975f5c5SAndroid Build Coastguard Worker {};
50*8975f5c5SAndroid Build Coastguard Worker 
51*8975f5c5SAndroid Build Coastguard Worker // Linking should fail if counters in vertex shader exceed gl_MaxVertexAtomicCounters.
TEST_P(AtomicCounterBufferTest31,ExceedMaxVertexAtomicCounters)52*8975f5c5SAndroid Build Coastguard Worker TEST_P(AtomicCounterBufferTest31, ExceedMaxVertexAtomicCounters)
53*8975f5c5SAndroid Build Coastguard Worker {
54*8975f5c5SAndroid Build Coastguard Worker     constexpr char kVS[] =
55*8975f5c5SAndroid Build Coastguard Worker         "#version 310 es\n"
56*8975f5c5SAndroid Build Coastguard Worker         "layout(binding = 0) uniform atomic_uint foo[gl_MaxVertexAtomicCounters + 1];\n"
57*8975f5c5SAndroid Build Coastguard Worker         "void main()\n"
58*8975f5c5SAndroid Build Coastguard Worker         "{\n"
59*8975f5c5SAndroid Build Coastguard Worker         "    atomicCounterIncrement(foo[0]);\n"
60*8975f5c5SAndroid Build Coastguard Worker         "}\n";
61*8975f5c5SAndroid Build Coastguard Worker     constexpr char kFS[] =
62*8975f5c5SAndroid Build Coastguard Worker         "#version 310 es\n"
63*8975f5c5SAndroid Build Coastguard Worker         "void main()\n"
64*8975f5c5SAndroid Build Coastguard Worker         "{\n"
65*8975f5c5SAndroid Build Coastguard Worker         "}\n";
66*8975f5c5SAndroid Build Coastguard Worker 
67*8975f5c5SAndroid Build Coastguard Worker     GLuint program = CompileProgram(kVS, kFS);
68*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(0u, program);
69*8975f5c5SAndroid Build Coastguard Worker }
70*8975f5c5SAndroid Build Coastguard Worker 
71*8975f5c5SAndroid Build Coastguard Worker // Test that Tessellation Control Shader Can Read/Write to atomic counter buffers
TEST_P(AtomicCounterBufferTest31,TessellationControlShaderMaxAtomicCounterTests)72*8975f5c5SAndroid Build Coastguard Worker TEST_P(AtomicCounterBufferTest31, TessellationControlShaderMaxAtomicCounterTests)
73*8975f5c5SAndroid Build Coastguard Worker {
74*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
75*8975f5c5SAndroid Build Coastguard Worker     GLint maxTessellationControlAtomicCounters = 0;
76*8975f5c5SAndroid Build Coastguard Worker     glGetIntegerv(GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS, &maxTessellationControlAtomicCounters);
77*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(maxTessellationControlAtomicCounters <= 0);
78*8975f5c5SAndroid Build Coastguard Worker 
79*8975f5c5SAndroid Build Coastguard Worker     // Cap the atomic counters to an arbitrary value 16 in case we do not have a limit for
80*8975f5c5SAndroid Build Coastguard Worker     // GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS on certain devices
81*8975f5c5SAndroid Build Coastguard Worker     GLint maxTessellationControlAtomicCountersCap = 16u;
82*8975f5c5SAndroid Build Coastguard Worker     maxTessellationControlAtomicCounters =
83*8975f5c5SAndroid Build Coastguard Worker         std::min(maxTessellationControlAtomicCounters, maxTessellationControlAtomicCountersCap);
84*8975f5c5SAndroid Build Coastguard Worker 
85*8975f5c5SAndroid Build Coastguard Worker     const unsigned int tessellationControlPointsCount = 3;
86*8975f5c5SAndroid Build Coastguard Worker 
87*8975f5c5SAndroid Build Coastguard Worker     // Vertex Shader Code
88*8975f5c5SAndroid Build Coastguard Worker     const char *kVS =
89*8975f5c5SAndroid Build Coastguard Worker         "#version 310 es\n"
90*8975f5c5SAndroid Build Coastguard Worker         "\n"
91*8975f5c5SAndroid Build Coastguard Worker         "in vec4 a_position;\n"
92*8975f5c5SAndroid Build Coastguard Worker         "flat out int vertex_id;\n"
93*8975f5c5SAndroid Build Coastguard Worker         "\n"
94*8975f5c5SAndroid Build Coastguard Worker         "void main()\n"
95*8975f5c5SAndroid Build Coastguard Worker         "{\n"
96*8975f5c5SAndroid Build Coastguard Worker         "    gl_Position  = a_position;\n"
97*8975f5c5SAndroid Build Coastguard Worker         "}\n";
98*8975f5c5SAndroid Build Coastguard Worker 
99*8975f5c5SAndroid Build Coastguard Worker     // Tessellation Control Shader Code
100*8975f5c5SAndroid Build Coastguard Worker     // gl_InvocationID = 0: increment all elements in atomic counters acs[].
101*8975f5c5SAndroid Build Coastguard Worker     // gl_InvocationID = 1: increment acs[index] where index==0
102*8975f5c5SAndroid Build Coastguard Worker     // gl_InvocationID = 2: increment acs[index] where index==0,1
103*8975f5c5SAndroid Build Coastguard Worker     // We have tessellationControlPointsCount=3 vertices output from the Tessellation Control
104*8975f5c5SAndroid Build Coastguard Worker     // Shader Stage, meaning we have three tessellation shader code running in parallel, each with a
105*8975f5c5SAndroid Build Coastguard Worker     // unique gl_InvocationID.
106*8975f5c5SAndroid Build Coastguard Worker     std::stringstream tcs_code_sstream;
107*8975f5c5SAndroid Build Coastguard Worker     tcs_code_sstream
108*8975f5c5SAndroid Build Coastguard Worker         << "#version 310 es\n"
109*8975f5c5SAndroid Build Coastguard Worker            "#extension GL_EXT_tessellation_shader : require\n"
110*8975f5c5SAndroid Build Coastguard Worker            "layout(vertices ="
111*8975f5c5SAndroid Build Coastguard Worker         << tessellationControlPointsCount
112*8975f5c5SAndroid Build Coastguard Worker         << ") out;\n"
113*8975f5c5SAndroid Build Coastguard Worker            "uniform int nLoopIterations;\n"
114*8975f5c5SAndroid Build Coastguard Worker            "layout(binding = 0) uniform atomic_uint acs["
115*8975f5c5SAndroid Build Coastguard Worker         << maxTessellationControlAtomicCounters
116*8975f5c5SAndroid Build Coastguard Worker         << "];\n"
117*8975f5c5SAndroid Build Coastguard Worker            "void main()\n"
118*8975f5c5SAndroid Build Coastguard Worker            "{\n"
119*8975f5c5SAndroid Build Coastguard Worker            "for (int counter_id = 1;\n"
120*8975f5c5SAndroid Build Coastguard Worker            "counter_id <= nLoopIterations;\n"
121*8975f5c5SAndroid Build Coastguard Worker            "++counter_id)\n"
122*8975f5c5SAndroid Build Coastguard Worker            "{\n"
123*8975f5c5SAndroid Build Coastguard Worker            "if ((gl_InvocationID % counter_id) == 0)\n"
124*8975f5c5SAndroid Build Coastguard Worker            "{\n"
125*8975f5c5SAndroid Build Coastguard Worker            "   atomicCounterIncrement(acs[counter_id - 1]);\n"
126*8975f5c5SAndroid Build Coastguard Worker            "}\n"
127*8975f5c5SAndroid Build Coastguard Worker            "}\n"
128*8975f5c5SAndroid Build Coastguard Worker            "\n"
129*8975f5c5SAndroid Build Coastguard Worker            "       gl_out [gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
130*8975f5c5SAndroid Build Coastguard Worker            "       gl_TessLevelInner[0] = 1.0;\n"
131*8975f5c5SAndroid Build Coastguard Worker            "       gl_TessLevelOuter[0] = 1.0;\n"
132*8975f5c5SAndroid Build Coastguard Worker            "       gl_TessLevelOuter[1] = 1.0;\n"
133*8975f5c5SAndroid Build Coastguard Worker            "       gl_TessLevelOuter[2] = 1.0;\n"
134*8975f5c5SAndroid Build Coastguard Worker            "}\n";
135*8975f5c5SAndroid Build Coastguard Worker     std::string tcs_code = tcs_code_sstream.str();
136*8975f5c5SAndroid Build Coastguard Worker     const char *kTC      = tcs_code.c_str();
137*8975f5c5SAndroid Build Coastguard Worker 
138*8975f5c5SAndroid Build Coastguard Worker     // Tessellation Evaluation Shader Code
139*8975f5c5SAndroid Build Coastguard Worker     constexpr char kTES[] =
140*8975f5c5SAndroid Build Coastguard Worker         "#version 310 es\n"
141*8975f5c5SAndroid Build Coastguard Worker         "#extension GL_EXT_tessellation_shader : require\n"
142*8975f5c5SAndroid Build Coastguard Worker         "layout (triangles) in;\n"
143*8975f5c5SAndroid Build Coastguard Worker         "void main()\n"
144*8975f5c5SAndroid Build Coastguard Worker         "{\n"
145*8975f5c5SAndroid Build Coastguard Worker         "   gl_Position = gl_TessCoord[0] * gl_in[0].gl_Position +"
146*8975f5c5SAndroid Build Coastguard Worker         "                 gl_TessCoord[1] * gl_in[1].gl_Position +"
147*8975f5c5SAndroid Build Coastguard Worker         "                 gl_TessCoord[2] * gl_in[2].gl_Position;\n"
148*8975f5c5SAndroid Build Coastguard Worker         "}\n";
149*8975f5c5SAndroid Build Coastguard Worker 
150*8975f5c5SAndroid Build Coastguard Worker     // Fragment Shader Code
151*8975f5c5SAndroid Build Coastguard Worker     const char *kFS =
152*8975f5c5SAndroid Build Coastguard Worker         "#version 310 es\n"
153*8975f5c5SAndroid Build Coastguard Worker         "\n"
154*8975f5c5SAndroid Build Coastguard Worker         "precision highp float;\n"
155*8975f5c5SAndroid Build Coastguard Worker         "\n"
156*8975f5c5SAndroid Build Coastguard Worker         "out vec4 result;\n"
157*8975f5c5SAndroid Build Coastguard Worker         "\n"
158*8975f5c5SAndroid Build Coastguard Worker         "void main()\n"
159*8975f5c5SAndroid Build Coastguard Worker         "{\n"
160*8975f5c5SAndroid Build Coastguard Worker         "    result = vec4(1.0);\n"
161*8975f5c5SAndroid Build Coastguard Worker         "}\n";
162*8975f5c5SAndroid Build Coastguard Worker     GLuint program = CompileProgramWithTESS(kVS, kTC, kTES, kFS);
163*8975f5c5SAndroid Build Coastguard Worker     EXPECT_NE(0u, program);
164*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(program);
165*8975f5c5SAndroid Build Coastguard Worker 
166*8975f5c5SAndroid Build Coastguard Worker     // Create and Bind Atomic Counter Buffer Object
167*8975f5c5SAndroid Build Coastguard Worker     GLuint atomicBufferID;
168*8975f5c5SAndroid Build Coastguard Worker     glGenBuffers(1, &atomicBufferID);
169*8975f5c5SAndroid Build Coastguard Worker     GLuint *atomicBufferData = new GLuint[maxTessellationControlAtomicCounters];
170*8975f5c5SAndroid Build Coastguard Worker     memset(atomicBufferData, 0, sizeof(GLuint) * maxTessellationControlAtomicCounters);
171*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicBufferID);
172*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint) * maxTessellationControlAtomicCounters,
173*8975f5c5SAndroid Build Coastguard Worker                  NULL, GL_DYNAMIC_COPY);
174*8975f5c5SAndroid Build Coastguard Worker     glBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0,
175*8975f5c5SAndroid Build Coastguard Worker                     sizeof(GLuint) * maxTessellationControlAtomicCounters, atomicBufferData);
176*8975f5c5SAndroid Build Coastguard Worker     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicBufferID);
177*8975f5c5SAndroid Build Coastguard Worker 
178*8975f5c5SAndroid Build Coastguard Worker     // Bind nLoopIterationsUniformLocation uniform
179*8975f5c5SAndroid Build Coastguard Worker     GLint nLoopIterationsUniformLocation = -1;
180*8975f5c5SAndroid Build Coastguard Worker     nLoopIterationsUniformLocation       = glGetUniformLocation(program, "nLoopIterations");
181*8975f5c5SAndroid Build Coastguard Worker     EXPECT_NE(-1, nLoopIterationsUniformLocation);
182*8975f5c5SAndroid Build Coastguard Worker     glUniform1i(nLoopIterationsUniformLocation, maxTessellationControlAtomicCounters);
183*8975f5c5SAndroid Build Coastguard Worker 
184*8975f5c5SAndroid Build Coastguard Worker     // Issue a Drawcall
185*8975f5c5SAndroid Build Coastguard Worker     std::array<Vector3, 3> triangleVertices = {
186*8975f5c5SAndroid Build Coastguard Worker         Vector3(-1.0f, 1.0f, 0.5f), Vector3(-1.0f, -1.0f, 0.5f), Vector3(1.0f, -1.0f, 0.5f)};
187*8975f5c5SAndroid Build Coastguard Worker     GLint positionLocation = glGetAttribLocation(program, "a_position");
188*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, triangleVertices.data());
189*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(positionLocation);
190*8975f5c5SAndroid Build Coastguard Worker     glDrawArrays(GL_PATCHES, 0, 3);
191*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
192*8975f5c5SAndroid Build Coastguard Worker 
193*8975f5c5SAndroid Build Coastguard Worker     // Check the value of atomic counter buffer
194*8975f5c5SAndroid Build Coastguard Worker     GLuint *atomicBufferResult = (GLuint *)glMapBufferRange(
195*8975f5c5SAndroid Build Coastguard Worker         GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint) * maxTessellationControlAtomicCounters,
196*8975f5c5SAndroid Build Coastguard Worker         GL_MAP_READ_BIT);
197*8975f5c5SAndroid Build Coastguard Worker 
198*8975f5c5SAndroid Build Coastguard Worker     for (GLint n_ac = 1; n_ac <= maxTessellationControlAtomicCounters; ++n_ac)
199*8975f5c5SAndroid Build Coastguard Worker     {
200*8975f5c5SAndroid Build Coastguard Worker         unsigned int expected_value = 0;
201*8975f5c5SAndroid Build Coastguard Worker         for (unsigned int n_draw_call_vertex = 0;
202*8975f5c5SAndroid Build Coastguard Worker              n_draw_call_vertex < tessellationControlPointsCount; ++n_draw_call_vertex)
203*8975f5c5SAndroid Build Coastguard Worker         {
204*8975f5c5SAndroid Build Coastguard Worker             if ((n_draw_call_vertex % n_ac) == 0)
205*8975f5c5SAndroid Build Coastguard Worker             {
206*8975f5c5SAndroid Build Coastguard Worker                 expected_value++;
207*8975f5c5SAndroid Build Coastguard Worker             }
208*8975f5c5SAndroid Build Coastguard Worker         }
209*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EQ(atomicBufferResult[n_ac - 1], expected_value);
210*8975f5c5SAndroid Build Coastguard Worker     }
211*8975f5c5SAndroid Build Coastguard Worker 
212*8975f5c5SAndroid Build Coastguard Worker     glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
213*8975f5c5SAndroid Build Coastguard Worker     glDisableVertexAttribArray(positionLocation);
214*8975f5c5SAndroid Build Coastguard Worker     glDeleteBuffers(1, &atomicBufferID);
215*8975f5c5SAndroid Build Coastguard Worker     glDeleteProgram(program);
216*8975f5c5SAndroid Build Coastguard Worker }
217*8975f5c5SAndroid Build Coastguard Worker 
218*8975f5c5SAndroid Build Coastguard Worker // Test that Tessellation Evaluation Shader Can Read/Write to atomic counter buffers
TEST_P(AtomicCounterBufferTest31,TessellationEvaluationShaderMaxAtomicCounterTests)219*8975f5c5SAndroid Build Coastguard Worker TEST_P(AtomicCounterBufferTest31, TessellationEvaluationShaderMaxAtomicCounterTests)
220*8975f5c5SAndroid Build Coastguard Worker {
221*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
222*8975f5c5SAndroid Build Coastguard Worker     GLint maxTessellationEvaluationAtomicCounters = 0;
223*8975f5c5SAndroid Build Coastguard Worker     glGetIntegerv(GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS, &maxTessellationEvaluationAtomicCounters);
224*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(maxTessellationEvaluationAtomicCounters <= 0);
225*8975f5c5SAndroid Build Coastguard Worker 
226*8975f5c5SAndroid Build Coastguard Worker     // Cap the atomic counters to an arbitrary value 16 in case we do not have a limit for
227*8975f5c5SAndroid Build Coastguard Worker     // GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS on certain devices
228*8975f5c5SAndroid Build Coastguard Worker     GLint maxTessellationEvaluationAtomicCountersCap = 16u;
229*8975f5c5SAndroid Build Coastguard Worker     maxTessellationEvaluationAtomicCounters = std::min(maxTessellationEvaluationAtomicCounters,
230*8975f5c5SAndroid Build Coastguard Worker                                                        maxTessellationEvaluationAtomicCountersCap);
231*8975f5c5SAndroid Build Coastguard Worker 
232*8975f5c5SAndroid Build Coastguard Worker     const unsigned int tessellationControlPointsCount = 3;
233*8975f5c5SAndroid Build Coastguard Worker 
234*8975f5c5SAndroid Build Coastguard Worker     // Vertex Shader Code
235*8975f5c5SAndroid Build Coastguard Worker     const char *kVS =
236*8975f5c5SAndroid Build Coastguard Worker         "#version 310 es\n"
237*8975f5c5SAndroid Build Coastguard Worker         "\n"
238*8975f5c5SAndroid Build Coastguard Worker         "in vec4 a_position;\n"
239*8975f5c5SAndroid Build Coastguard Worker         "\n"
240*8975f5c5SAndroid Build Coastguard Worker         "void main()\n"
241*8975f5c5SAndroid Build Coastguard Worker         "{\n"
242*8975f5c5SAndroid Build Coastguard Worker         "    gl_Position  = a_position;\n"
243*8975f5c5SAndroid Build Coastguard Worker         "}\n";
244*8975f5c5SAndroid Build Coastguard Worker 
245*8975f5c5SAndroid Build Coastguard Worker     // Tessellation Control Shader Code
246*8975f5c5SAndroid Build Coastguard Worker     std::stringstream tcs_code_sstream;
247*8975f5c5SAndroid Build Coastguard Worker     tcs_code_sstream
248*8975f5c5SAndroid Build Coastguard Worker         << "#version 310 es\n"
249*8975f5c5SAndroid Build Coastguard Worker            "#extension GL_EXT_tessellation_shader : require\n"
250*8975f5c5SAndroid Build Coastguard Worker            "layout(vertices = "
251*8975f5c5SAndroid Build Coastguard Worker         << tessellationControlPointsCount
252*8975f5c5SAndroid Build Coastguard Worker         << ") out;\n"
253*8975f5c5SAndroid Build Coastguard Worker            "void main()\n"
254*8975f5c5SAndroid Build Coastguard Worker            "{\n"
255*8975f5c5SAndroid Build Coastguard Worker            "       gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
256*8975f5c5SAndroid Build Coastguard Worker            "       gl_TessLevelInner[0] = 1.0;\n"
257*8975f5c5SAndroid Build Coastguard Worker            "       gl_TessLevelOuter[0] = 1.0;\n"
258*8975f5c5SAndroid Build Coastguard Worker            "       gl_TessLevelOuter[1] = 1.0;\n"
259*8975f5c5SAndroid Build Coastguard Worker            "       gl_TessLevelOuter[2] = 1.0;\n"
260*8975f5c5SAndroid Build Coastguard Worker            "}\n";
261*8975f5c5SAndroid Build Coastguard Worker     std::string tcs_code = tcs_code_sstream.str();
262*8975f5c5SAndroid Build Coastguard Worker     const char *kTC      = tcs_code.c_str();
263*8975f5c5SAndroid Build Coastguard Worker 
264*8975f5c5SAndroid Build Coastguard Worker     // Tessellation Evaluation Shader Code
265*8975f5c5SAndroid Build Coastguard Worker     // The gl_TessLevelInner and gl_TessLevelOuter values in tessellation control shader (tcs) code
266*8975f5c5SAndroid Build Coastguard Worker     // are set to 1, meaning we do not subdivide the patch and create more vertices. The number of
267*8975f5c5SAndroid Build Coastguard Worker     // tessellation evaluation shader (tes) invocations is the same as number of vertex output from
268*8975f5c5SAndroid Build Coastguard Worker     // tcs (e.g. tessellationControlPointsCount).
269*8975f5c5SAndroid Build Coastguard Worker     // Increment all elements in atomic counters acs[] in every tes invocation.
270*8975f5c5SAndroid Build Coastguard Worker     // Final value in atomic counters acs[] should be the same as the number of
271*8975f5c5SAndroid Build Coastguard Worker     // tes invocations (e.g. tessellationControlPointsCount).
272*8975f5c5SAndroid Build Coastguard Worker     std::stringstream tes_code_sstream;
273*8975f5c5SAndroid Build Coastguard Worker     tes_code_sstream << "#version 310 es\n"
274*8975f5c5SAndroid Build Coastguard Worker                         "#extension GL_EXT_tessellation_shader : require\n"
275*8975f5c5SAndroid Build Coastguard Worker                         "layout (triangles) in;\n"
276*8975f5c5SAndroid Build Coastguard Worker                         "uniform int nLoopIterations;\n"
277*8975f5c5SAndroid Build Coastguard Worker                         "layout(binding = 0) uniform atomic_uint acs["
278*8975f5c5SAndroid Build Coastguard Worker                      << maxTessellationEvaluationAtomicCounters
279*8975f5c5SAndroid Build Coastguard Worker                      << "];\n"
280*8975f5c5SAndroid Build Coastguard Worker                         "void main()\n"
281*8975f5c5SAndroid Build Coastguard Worker                         "{\n"
282*8975f5c5SAndroid Build Coastguard Worker                         "for (int counter_id = 0;\n"
283*8975f5c5SAndroid Build Coastguard Worker                         "counter_id < nLoopIterations;\n"
284*8975f5c5SAndroid Build Coastguard Worker                         "++counter_id)\n"
285*8975f5c5SAndroid Build Coastguard Worker                         "{\n"
286*8975f5c5SAndroid Build Coastguard Worker                         "   atomicCounterIncrement(acs[counter_id]);\n"
287*8975f5c5SAndroid Build Coastguard Worker                         "}\n"
288*8975f5c5SAndroid Build Coastguard Worker                         "\n"
289*8975f5c5SAndroid Build Coastguard Worker                         "   gl_Position = gl_TessCoord[0] * gl_in[0].gl_Position +"
290*8975f5c5SAndroid Build Coastguard Worker                         "                 gl_TessCoord[1] * gl_in[1].gl_Position +"
291*8975f5c5SAndroid Build Coastguard Worker                         "                 gl_TessCoord[2] * gl_in[2].gl_Position;\n"
292*8975f5c5SAndroid Build Coastguard Worker                         "}\n";
293*8975f5c5SAndroid Build Coastguard Worker     std::string tes_code = tes_code_sstream.str();
294*8975f5c5SAndroid Build Coastguard Worker     const char *kTES     = tes_code.c_str();
295*8975f5c5SAndroid Build Coastguard Worker 
296*8975f5c5SAndroid Build Coastguard Worker     // Fragment Shader Code
297*8975f5c5SAndroid Build Coastguard Worker     const char *kFS =
298*8975f5c5SAndroid Build Coastguard Worker         "#version 310 es\n"
299*8975f5c5SAndroid Build Coastguard Worker         "\n"
300*8975f5c5SAndroid Build Coastguard Worker         "precision highp float;\n"
301*8975f5c5SAndroid Build Coastguard Worker         "\n"
302*8975f5c5SAndroid Build Coastguard Worker         "out vec4 result;\n"
303*8975f5c5SAndroid Build Coastguard Worker         "\n"
304*8975f5c5SAndroid Build Coastguard Worker         "void main()\n"
305*8975f5c5SAndroid Build Coastguard Worker         "{\n"
306*8975f5c5SAndroid Build Coastguard Worker         "    result = vec4(1.0);\n"
307*8975f5c5SAndroid Build Coastguard Worker         "}\n";
308*8975f5c5SAndroid Build Coastguard Worker     GLuint program = CompileProgramWithTESS(kVS, kTC, kTES, kFS);
309*8975f5c5SAndroid Build Coastguard Worker     EXPECT_NE(0u, program);
310*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(program);
311*8975f5c5SAndroid Build Coastguard Worker 
312*8975f5c5SAndroid Build Coastguard Worker     // Create and Bind Atomic Counter Buffer Object
313*8975f5c5SAndroid Build Coastguard Worker     GLuint atomicBufferID;
314*8975f5c5SAndroid Build Coastguard Worker     glGenBuffers(1, &atomicBufferID);
315*8975f5c5SAndroid Build Coastguard Worker     GLuint *atomicBufferData = new GLuint[maxTessellationEvaluationAtomicCounters];
316*8975f5c5SAndroid Build Coastguard Worker     memset(atomicBufferData, 0, sizeof(GLuint) * maxTessellationEvaluationAtomicCounters);
317*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicBufferID);
318*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint) * maxTessellationEvaluationAtomicCounters,
319*8975f5c5SAndroid Build Coastguard Worker                  NULL, GL_DYNAMIC_COPY);
320*8975f5c5SAndroid Build Coastguard Worker     glBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0,
321*8975f5c5SAndroid Build Coastguard Worker                     sizeof(GLuint) * maxTessellationEvaluationAtomicCounters, atomicBufferData);
322*8975f5c5SAndroid Build Coastguard Worker     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicBufferID);
323*8975f5c5SAndroid Build Coastguard Worker 
324*8975f5c5SAndroid Build Coastguard Worker     // Bind nLoopIterationsUniformLocation uniform
325*8975f5c5SAndroid Build Coastguard Worker     GLint nLoopIterationsUniformLocation = -1;
326*8975f5c5SAndroid Build Coastguard Worker     nLoopIterationsUniformLocation       = glGetUniformLocation(program, "nLoopIterations");
327*8975f5c5SAndroid Build Coastguard Worker     EXPECT_NE(-1, nLoopIterationsUniformLocation);
328*8975f5c5SAndroid Build Coastguard Worker     glUniform1i(nLoopIterationsUniformLocation, maxTessellationEvaluationAtomicCounters);
329*8975f5c5SAndroid Build Coastguard Worker 
330*8975f5c5SAndroid Build Coastguard Worker     // Issue Drawcall
331*8975f5c5SAndroid Build Coastguard Worker     std::array<Vector3, 3> triangleVertices = {
332*8975f5c5SAndroid Build Coastguard Worker         Vector3(-1.0f, 1.0f, 0.5f), Vector3(-1.0f, -1.0f, 0.5f), Vector3(1.0f, -1.0f, 0.5f)};
333*8975f5c5SAndroid Build Coastguard Worker     GLint positionLocation = glGetAttribLocation(program, "a_position");
334*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, triangleVertices.data());
335*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(positionLocation);
336*8975f5c5SAndroid Build Coastguard Worker     glDrawArrays(GL_PATCHES, 0, 3);
337*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
338*8975f5c5SAndroid Build Coastguard Worker 
339*8975f5c5SAndroid Build Coastguard Worker     // Check the value of atomic counter buffer
340*8975f5c5SAndroid Build Coastguard Worker     GLuint *atomicBufferResult = (GLuint *)glMapBufferRange(
341*8975f5c5SAndroid Build Coastguard Worker         GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint) * maxTessellationEvaluationAtomicCounters,
342*8975f5c5SAndroid Build Coastguard Worker         GL_MAP_READ_BIT);
343*8975f5c5SAndroid Build Coastguard Worker     unsigned int expected_value = tessellationControlPointsCount;
344*8975f5c5SAndroid Build Coastguard Worker     for (GLint n_ac = 0; n_ac < maxTessellationEvaluationAtomicCounters; ++n_ac)
345*8975f5c5SAndroid Build Coastguard Worker     {
346*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EQ(atomicBufferResult[n_ac], expected_value);
347*8975f5c5SAndroid Build Coastguard Worker     }
348*8975f5c5SAndroid Build Coastguard Worker 
349*8975f5c5SAndroid Build Coastguard Worker     glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
350*8975f5c5SAndroid Build Coastguard Worker     glDisableVertexAttribArray(positionLocation);
351*8975f5c5SAndroid Build Coastguard Worker     glDeleteBuffers(1, &atomicBufferID);
352*8975f5c5SAndroid Build Coastguard Worker     glDeleteProgram(program);
353*8975f5c5SAndroid Build Coastguard Worker }
354*8975f5c5SAndroid Build Coastguard Worker 
355*8975f5c5SAndroid Build Coastguard Worker // Counters matching across shader stages should fail if offsets aren't all specified.
356*8975f5c5SAndroid Build Coastguard Worker // GLSL ES Spec 3.10.4, section 9.2.1.
TEST_P(AtomicCounterBufferTest31,OffsetNotAllSpecified)357*8975f5c5SAndroid Build Coastguard Worker TEST_P(AtomicCounterBufferTest31, OffsetNotAllSpecified)
358*8975f5c5SAndroid Build Coastguard Worker {
359*8975f5c5SAndroid Build Coastguard Worker     constexpr char kVS[] =
360*8975f5c5SAndroid Build Coastguard Worker         "#version 310 es\n"
361*8975f5c5SAndroid Build Coastguard Worker         "layout(binding = 0, offset = 4) uniform atomic_uint foo;\n"
362*8975f5c5SAndroid Build Coastguard Worker         "void main()\n"
363*8975f5c5SAndroid Build Coastguard Worker         "{\n"
364*8975f5c5SAndroid Build Coastguard Worker         "    atomicCounterIncrement(foo);\n"
365*8975f5c5SAndroid Build Coastguard Worker         "}\n";
366*8975f5c5SAndroid Build Coastguard Worker     constexpr char kFS[] =
367*8975f5c5SAndroid Build Coastguard Worker         "#version 310 es\n"
368*8975f5c5SAndroid Build Coastguard Worker         "layout(binding = 0) uniform atomic_uint foo;\n"
369*8975f5c5SAndroid Build Coastguard Worker         "void main()\n"
370*8975f5c5SAndroid Build Coastguard Worker         "{\n"
371*8975f5c5SAndroid Build Coastguard Worker         "}\n";
372*8975f5c5SAndroid Build Coastguard Worker 
373*8975f5c5SAndroid Build Coastguard Worker     GLuint program = CompileProgram(kVS, kFS);
374*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(0u, program);
375*8975f5c5SAndroid Build Coastguard Worker }
376*8975f5c5SAndroid Build Coastguard Worker 
377*8975f5c5SAndroid Build Coastguard Worker // Counters matching across shader stages should fail if offsets aren't all specified with same
378*8975f5c5SAndroid Build Coastguard Worker // value.
TEST_P(AtomicCounterBufferTest31,OffsetNotAllSpecifiedWithSameValue)379*8975f5c5SAndroid Build Coastguard Worker TEST_P(AtomicCounterBufferTest31, OffsetNotAllSpecifiedWithSameValue)
380*8975f5c5SAndroid Build Coastguard Worker {
381*8975f5c5SAndroid Build Coastguard Worker     constexpr char kVS[] =
382*8975f5c5SAndroid Build Coastguard Worker         "#version 310 es\n"
383*8975f5c5SAndroid Build Coastguard Worker         "layout(binding = 0, offset = 4) uniform atomic_uint foo;\n"
384*8975f5c5SAndroid Build Coastguard Worker         "void main()\n"
385*8975f5c5SAndroid Build Coastguard Worker         "{\n"
386*8975f5c5SAndroid Build Coastguard Worker         "    atomicCounterIncrement(foo);\n"
387*8975f5c5SAndroid Build Coastguard Worker         "}\n";
388*8975f5c5SAndroid Build Coastguard Worker     constexpr char kFS[] =
389*8975f5c5SAndroid Build Coastguard Worker         "#version 310 es\n"
390*8975f5c5SAndroid Build Coastguard Worker         "layout(binding = 0, offset = 8) uniform atomic_uint foo;\n"
391*8975f5c5SAndroid Build Coastguard Worker         "void main()\n"
392*8975f5c5SAndroid Build Coastguard Worker         "{\n"
393*8975f5c5SAndroid Build Coastguard Worker         "}\n";
394*8975f5c5SAndroid Build Coastguard Worker 
395*8975f5c5SAndroid Build Coastguard Worker     GLuint program = CompileProgram(kVS, kFS);
396*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(0u, program);
397*8975f5c5SAndroid Build Coastguard Worker }
398*8975f5c5SAndroid Build Coastguard Worker 
399*8975f5c5SAndroid Build Coastguard Worker // Tests atomic counter reads using compute shaders. Used as a confidence check for the translator.
TEST_P(AtomicCounterBufferTest31,AtomicCounterReadCompute)400*8975f5c5SAndroid Build Coastguard Worker TEST_P(AtomicCounterBufferTest31, AtomicCounterReadCompute)
401*8975f5c5SAndroid Build Coastguard Worker {
402*8975f5c5SAndroid Build Coastguard Worker     // Skipping due to a bug on the Adreno OpenGLES Android driver.
403*8975f5c5SAndroid Build Coastguard Worker     // http://anglebug.com/42261624
404*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
405*8975f5c5SAndroid Build Coastguard Worker 
406*8975f5c5SAndroid Build Coastguard Worker     constexpr char kComputeShaderSource[] = R"(#version 310 es
407*8975f5c5SAndroid Build Coastguard Worker layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
408*8975f5c5SAndroid Build Coastguard Worker 
409*8975f5c5SAndroid Build Coastguard Worker void atomicCounterInFunction(in atomic_uint counter[3]);
410*8975f5c5SAndroid Build Coastguard Worker 
411*8975f5c5SAndroid Build Coastguard Worker layout(binding = 0, offset = 8) uniform atomic_uint ac[3];
412*8975f5c5SAndroid Build Coastguard Worker 
413*8975f5c5SAndroid Build Coastguard Worker void atomicCounterInFunction(in atomic_uint counter[3])
414*8975f5c5SAndroid Build Coastguard Worker {
415*8975f5c5SAndroid Build Coastguard Worker     atomicCounter(counter[0]);
416*8975f5c5SAndroid Build Coastguard Worker }
417*8975f5c5SAndroid Build Coastguard Worker 
418*8975f5c5SAndroid Build Coastguard Worker void main()
419*8975f5c5SAndroid Build Coastguard Worker {
420*8975f5c5SAndroid Build Coastguard Worker     atomicCounterInFunction(ac);
421*8975f5c5SAndroid Build Coastguard Worker     atomicCounter(ac[gl_LocalInvocationIndex + 1u]);
422*8975f5c5SAndroid Build Coastguard Worker })";
423*8975f5c5SAndroid Build Coastguard Worker 
424*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
425*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
426*8975f5c5SAndroid Build Coastguard Worker }
427*8975f5c5SAndroid Build Coastguard Worker 
428*8975f5c5SAndroid Build Coastguard Worker // Test atomic counter read.
TEST_P(AtomicCounterBufferTest31,AtomicCounterRead)429*8975f5c5SAndroid Build Coastguard Worker TEST_P(AtomicCounterBufferTest31, AtomicCounterRead)
430*8975f5c5SAndroid Build Coastguard Worker {
431*8975f5c5SAndroid Build Coastguard Worker     // Skipping test while we work on enabling atomic counter buffer support in th D3D renderer.
432*8975f5c5SAndroid Build Coastguard Worker     // http://anglebug.com/42260658
433*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(IsD3D11());
434*8975f5c5SAndroid Build Coastguard Worker 
435*8975f5c5SAndroid Build Coastguard Worker     constexpr char kFS[] =
436*8975f5c5SAndroid Build Coastguard Worker         "#version 310 es\n"
437*8975f5c5SAndroid Build Coastguard Worker         "precision highp float;\n"
438*8975f5c5SAndroid Build Coastguard Worker         "layout(binding = 0, offset = 4) uniform atomic_uint ac;\n"
439*8975f5c5SAndroid Build Coastguard Worker         "out highp vec4 my_color;\n"
440*8975f5c5SAndroid Build Coastguard Worker         "void main()\n"
441*8975f5c5SAndroid Build Coastguard Worker         "{\n"
442*8975f5c5SAndroid Build Coastguard Worker         "    my_color = vec4(0.0);\n"
443*8975f5c5SAndroid Build Coastguard Worker         "    uint a1 = atomicCounter(ac);\n"
444*8975f5c5SAndroid Build Coastguard Worker         "    if (a1 == 3u) my_color = vec4(1.0);\n"
445*8975f5c5SAndroid Build Coastguard Worker         "}\n";
446*8975f5c5SAndroid Build Coastguard Worker 
447*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
448*8975f5c5SAndroid Build Coastguard Worker 
449*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(program);
450*8975f5c5SAndroid Build Coastguard Worker 
451*8975f5c5SAndroid Build Coastguard Worker     // The initial value of counter 'ac' is 3u.
452*8975f5c5SAndroid Build Coastguard Worker     unsigned int bufferData[3] = {11u, 3u, 1u};
453*8975f5c5SAndroid Build Coastguard Worker     GLBuffer atomicCounterBuffer;
454*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
455*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(bufferData), bufferData, GL_STATIC_DRAW);
456*8975f5c5SAndroid Build Coastguard Worker 
457*8975f5c5SAndroid Build Coastguard Worker     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
458*8975f5c5SAndroid Build Coastguard Worker 
459*8975f5c5SAndroid Build Coastguard Worker     drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
460*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
461*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
462*8975f5c5SAndroid Build Coastguard Worker }
463*8975f5c5SAndroid Build Coastguard Worker 
464*8975f5c5SAndroid Build Coastguard Worker // Test a bug in vulkan back-end where recreating the atomic counter storage should trigger state
465*8975f5c5SAndroid Build Coastguard Worker // update in the context
TEST_P(AtomicCounterBufferTest31,DependentAtomicCounterBufferChange)466*8975f5c5SAndroid Build Coastguard Worker TEST_P(AtomicCounterBufferTest31, DependentAtomicCounterBufferChange)
467*8975f5c5SAndroid Build Coastguard Worker {
468*8975f5c5SAndroid Build Coastguard Worker     // Skipping test while we work on enabling atomic counter buffer support in th D3D renderer.
469*8975f5c5SAndroid Build Coastguard Worker     // http://anglebug.com/42260658
470*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(IsD3D11());
471*8975f5c5SAndroid Build Coastguard Worker 
472*8975f5c5SAndroid Build Coastguard Worker     constexpr char kFS[] =
473*8975f5c5SAndroid Build Coastguard Worker         "#version 310 es\n"
474*8975f5c5SAndroid Build Coastguard Worker         "precision highp float;\n"
475*8975f5c5SAndroid Build Coastguard Worker         "layout(binding = 0, offset = 4) uniform atomic_uint ac;\n"
476*8975f5c5SAndroid Build Coastguard Worker         "out highp vec4 my_color;\n"
477*8975f5c5SAndroid Build Coastguard Worker         "void main()\n"
478*8975f5c5SAndroid Build Coastguard Worker         "{\n"
479*8975f5c5SAndroid Build Coastguard Worker         "    my_color = vec4(0.0);\n"
480*8975f5c5SAndroid Build Coastguard Worker         "    uint a1 = atomicCounter(ac);\n"
481*8975f5c5SAndroid Build Coastguard Worker         "    if (a1 == 3u) my_color = vec4(1.0);\n"
482*8975f5c5SAndroid Build Coastguard Worker         "    if (a1 == 19u) my_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
483*8975f5c5SAndroid Build Coastguard Worker         "}\n";
484*8975f5c5SAndroid Build Coastguard Worker 
485*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
486*8975f5c5SAndroid Build Coastguard Worker 
487*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(program);
488*8975f5c5SAndroid Build Coastguard Worker 
489*8975f5c5SAndroid Build Coastguard Worker     // The initial value of counter 'ac' is 3u.
490*8975f5c5SAndroid Build Coastguard Worker     unsigned int bufferDataLeft[3] = {11u, 3u, 1u};
491*8975f5c5SAndroid Build Coastguard Worker     GLBuffer atomicCounterBuffer;
492*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
493*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(bufferDataLeft), bufferDataLeft, GL_STATIC_DRAW);
494*8975f5c5SAndroid Build Coastguard Worker 
495*8975f5c5SAndroid Build Coastguard Worker     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
496*8975f5c5SAndroid Build Coastguard Worker     // Draw left quad
497*8975f5c5SAndroid Build Coastguard Worker     glViewport(0, 0, getWindowWidth() / 2, getWindowHeight());
498*8975f5c5SAndroid Build Coastguard Worker     drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
499*8975f5c5SAndroid Build Coastguard Worker     // Draw right quad
500*8975f5c5SAndroid Build Coastguard Worker     unsigned int bufferDataRight[3] = {11u, 19u, 1u};
501*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(bufferDataRight), bufferDataRight,
502*8975f5c5SAndroid Build Coastguard Worker                  GL_STATIC_DRAW);
503*8975f5c5SAndroid Build Coastguard Worker     glViewport(getWindowWidth() / 2, 0, getWindowWidth() / 2, getWindowHeight());
504*8975f5c5SAndroid Build Coastguard Worker     drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
505*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
506*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
507*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, 0, GLColor::red);
508*8975f5c5SAndroid Build Coastguard Worker }
509*8975f5c5SAndroid Build Coastguard Worker 
510*8975f5c5SAndroid Build Coastguard Worker // Updating atomic counter buffer's offsets was optimized based on a count of valid bindings.
511*8975f5c5SAndroid Build Coastguard Worker // This test will fail if there are bugs in how we count valid bindings.
TEST_P(AtomicCounterBufferTest31,AtomicCounterBufferRangeRead)512*8975f5c5SAndroid Build Coastguard Worker TEST_P(AtomicCounterBufferTest31, AtomicCounterBufferRangeRead)
513*8975f5c5SAndroid Build Coastguard Worker {
514*8975f5c5SAndroid Build Coastguard Worker     // Skipping due to a bug on the Qualcomm driver.
515*8975f5c5SAndroid Build Coastguard Worker     // http://anglebug.com/42262383
516*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
517*8975f5c5SAndroid Build Coastguard Worker 
518*8975f5c5SAndroid Build Coastguard Worker     // Skipping test while we work on enabling atomic counter buffer support in th D3D renderer.
519*8975f5c5SAndroid Build Coastguard Worker     // http://anglebug.com/42260658
520*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(IsD3D11());
521*8975f5c5SAndroid Build Coastguard Worker 
522*8975f5c5SAndroid Build Coastguard Worker     constexpr char kFS[] =
523*8975f5c5SAndroid Build Coastguard Worker         "#version 310 es\n"
524*8975f5c5SAndroid Build Coastguard Worker         "precision highp float;\n"
525*8975f5c5SAndroid Build Coastguard Worker         "layout(binding = 0, offset = 4) uniform atomic_uint ac;\n"
526*8975f5c5SAndroid Build Coastguard Worker         "out highp vec4 my_color;\n"
527*8975f5c5SAndroid Build Coastguard Worker         "void main()\n"
528*8975f5c5SAndroid Build Coastguard Worker         "{\n"
529*8975f5c5SAndroid Build Coastguard Worker         "    my_color = vec4(0.0);\n"
530*8975f5c5SAndroid Build Coastguard Worker         "    uint a1 = atomicCounter(ac);\n"
531*8975f5c5SAndroid Build Coastguard Worker         "    if (a1 == 3u) my_color = vec4(1.0);\n"
532*8975f5c5SAndroid Build Coastguard Worker         "}\n";
533*8975f5c5SAndroid Build Coastguard Worker 
534*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
535*8975f5c5SAndroid Build Coastguard Worker 
536*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(program);
537*8975f5c5SAndroid Build Coastguard Worker 
538*8975f5c5SAndroid Build Coastguard Worker     // The initial value of counter 'ac' is 3u.
539*8975f5c5SAndroid Build Coastguard Worker     unsigned int bufferData[]     = {0u, 0u, 0u, 0u, 0u, 11u, 3u, 1u};
540*8975f5c5SAndroid Build Coastguard Worker     constexpr GLintptr kOffset    = 20;
541*8975f5c5SAndroid Build Coastguard Worker     GLint maxAtomicCounterBuffers = 0;
542*8975f5c5SAndroid Build Coastguard Worker     GLBuffer atomicCounterBuffer;
543*8975f5c5SAndroid Build Coastguard Worker 
544*8975f5c5SAndroid Build Coastguard Worker     glGetIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS, &maxAtomicCounterBuffers);
545*8975f5c5SAndroid Build Coastguard Worker     // Repeatedly bind the same buffer (GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS + 1) times
546*8975f5c5SAndroid Build Coastguard Worker     // A bug in counting valid atomic counter buffers will cause a crash when we
547*8975f5c5SAndroid Build Coastguard Worker     // exceed GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS
548*8975f5c5SAndroid Build Coastguard Worker     for (int32_t i = 0; i < maxAtomicCounterBuffers + 1; i++)
549*8975f5c5SAndroid Build Coastguard Worker     {
550*8975f5c5SAndroid Build Coastguard Worker         glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
551*8975f5c5SAndroid Build Coastguard Worker         glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(bufferData), bufferData, GL_STATIC_DRAW);
552*8975f5c5SAndroid Build Coastguard Worker         glBindBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer, kOffset,
553*8975f5c5SAndroid Build Coastguard Worker                           sizeof(bufferData) - kOffset);
554*8975f5c5SAndroid Build Coastguard Worker     }
555*8975f5c5SAndroid Build Coastguard Worker 
556*8975f5c5SAndroid Build Coastguard Worker     drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
557*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
558*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
559*8975f5c5SAndroid Build Coastguard Worker }
560*8975f5c5SAndroid Build Coastguard Worker 
561*8975f5c5SAndroid Build Coastguard Worker // Updating atomic counter buffer's offsets was optimized based on a count of valid bindings.
562*8975f5c5SAndroid Build Coastguard Worker // Repeatedly bind/unbind buffers across available binding points. The test will fail if
563*8975f5c5SAndroid Build Coastguard Worker // there are bugs in how we count valid bindings.
TEST_P(AtomicCounterBufferTest31,AtomicCounterBufferRepeatedBindUnbind)564*8975f5c5SAndroid Build Coastguard Worker TEST_P(AtomicCounterBufferTest31, AtomicCounterBufferRepeatedBindUnbind)
565*8975f5c5SAndroid Build Coastguard Worker {
566*8975f5c5SAndroid Build Coastguard Worker     // Skipping test while we work on enabling atomic counter buffer support in th D3D renderer.
567*8975f5c5SAndroid Build Coastguard Worker     // http://anglebug.com/42260658
568*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(IsD3D11());
569*8975f5c5SAndroid Build Coastguard Worker 
570*8975f5c5SAndroid Build Coastguard Worker     constexpr char kFS[] =
571*8975f5c5SAndroid Build Coastguard Worker         "#version 310 es\n"
572*8975f5c5SAndroid Build Coastguard Worker         "precision highp float;\n"
573*8975f5c5SAndroid Build Coastguard Worker         "layout(binding = 0, offset = 4) uniform atomic_uint ac;\n"
574*8975f5c5SAndroid Build Coastguard Worker         "out highp vec4 my_color;\n"
575*8975f5c5SAndroid Build Coastguard Worker         "void main()\n"
576*8975f5c5SAndroid Build Coastguard Worker         "{\n"
577*8975f5c5SAndroid Build Coastguard Worker         "    my_color = vec4(0.0);\n"
578*8975f5c5SAndroid Build Coastguard Worker         "    uint a1 = atomicCounter(ac);\n"
579*8975f5c5SAndroid Build Coastguard Worker         "    if (a1 == 3u) my_color = vec4(1.0);\n"
580*8975f5c5SAndroid Build Coastguard Worker         "}\n";
581*8975f5c5SAndroid Build Coastguard Worker 
582*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
583*8975f5c5SAndroid Build Coastguard Worker 
584*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(program);
585*8975f5c5SAndroid Build Coastguard Worker 
586*8975f5c5SAndroid Build Coastguard Worker     constexpr int32_t kBufferCount = 16;
587*8975f5c5SAndroid Build Coastguard Worker     // The initial value of counter 'ac' is 3u.
588*8975f5c5SAndroid Build Coastguard Worker     unsigned int bufferData[3] = {11u, 3u, 1u};
589*8975f5c5SAndroid Build Coastguard Worker     GLBuffer atomicCounterBuffer[kBufferCount];
590*8975f5c5SAndroid Build Coastguard Worker     // Populate atomicCounterBuffer[0] with valid data and the rest with nullptr
591*8975f5c5SAndroid Build Coastguard Worker     for (int32_t bufferIndex = 0; bufferIndex < kBufferCount; bufferIndex++)
592*8975f5c5SAndroid Build Coastguard Worker     {
593*8975f5c5SAndroid Build Coastguard Worker         glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer[bufferIndex]);
594*8975f5c5SAndroid Build Coastguard Worker         glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(bufferData),
595*8975f5c5SAndroid Build Coastguard Worker                      (bufferIndex == 0) ? bufferData : nullptr, GL_STATIC_DRAW);
596*8975f5c5SAndroid Build Coastguard Worker     }
597*8975f5c5SAndroid Build Coastguard Worker 
598*8975f5c5SAndroid Build Coastguard Worker     GLint maxAtomicCounterBuffers = 0;
599*8975f5c5SAndroid Build Coastguard Worker     glGetIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS, &maxAtomicCounterBuffers);
600*8975f5c5SAndroid Build Coastguard Worker 
601*8975f5c5SAndroid Build Coastguard Worker     // Cycle through multiple buffers
602*8975f5c5SAndroid Build Coastguard Worker     for (int32_t i = 0; i < kBufferCount; i++)
603*8975f5c5SAndroid Build Coastguard Worker     {
604*8975f5c5SAndroid Build Coastguard Worker         constexpr int32_t kBufferIndices[kBufferCount] = {7, 12, 15, 5, 13, 14, 1, 2,
605*8975f5c5SAndroid Build Coastguard Worker                                                           0, 6,  4,  9, 8,  11, 3, 10};
606*8975f5c5SAndroid Build Coastguard Worker         int32_t bufferIndex                            = kBufferIndices[i];
607*8975f5c5SAndroid Build Coastguard Worker 
608*8975f5c5SAndroid Build Coastguard Worker         // Randomly bind/unbind buffers to/from different binding points,
609*8975f5c5SAndroid Build Coastguard Worker         // capped by GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS
610*8975f5c5SAndroid Build Coastguard Worker         for (int32_t bufferCount = 0; bufferCount < maxAtomicCounterBuffers; bufferCount++)
611*8975f5c5SAndroid Build Coastguard Worker         {
612*8975f5c5SAndroid Build Coastguard Worker             constexpr uint32_t kBindingSlotsSize                = kBufferCount;
613*8975f5c5SAndroid Build Coastguard Worker             constexpr uint32_t kBindingSlots[kBindingSlotsSize] = {1,  3,  4, 14, 15, 9, 0, 6,
614*8975f5c5SAndroid Build Coastguard Worker                                                                    12, 11, 8, 5,  10, 2, 7, 13};
615*8975f5c5SAndroid Build Coastguard Worker 
616*8975f5c5SAndroid Build Coastguard Worker             uint32_t bindingSlotIndex = bufferCount % kBindingSlotsSize;
617*8975f5c5SAndroid Build Coastguard Worker             uint32_t bindingSlot      = kBindingSlots[bindingSlotIndex];
618*8975f5c5SAndroid Build Coastguard Worker             uint32_t bindingPoint     = bindingSlot % maxAtomicCounterBuffers;
619*8975f5c5SAndroid Build Coastguard Worker             bool even                 = (bufferCount % 2 == 0);
620*8975f5c5SAndroid Build Coastguard Worker             int32_t bufferId          = (even) ? 0 : atomicCounterBuffer[bufferIndex];
621*8975f5c5SAndroid Build Coastguard Worker 
622*8975f5c5SAndroid Build Coastguard Worker             glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, bindingPoint, bufferId);
623*8975f5c5SAndroid Build Coastguard Worker         }
624*8975f5c5SAndroid Build Coastguard Worker     }
625*8975f5c5SAndroid Build Coastguard Worker 
626*8975f5c5SAndroid Build Coastguard Worker     // Bind atomicCounterBuffer[0] to slot 0 and verify result
627*8975f5c5SAndroid Build Coastguard Worker     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer[0]);
628*8975f5c5SAndroid Build Coastguard Worker     drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
629*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
630*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
631*8975f5c5SAndroid Build Coastguard Worker }
632*8975f5c5SAndroid Build Coastguard Worker 
633*8975f5c5SAndroid Build Coastguard Worker // Test atomic counter increment and decrement.
TEST_P(AtomicCounterBufferTest31,AtomicCounterIncrementAndDecrement)634*8975f5c5SAndroid Build Coastguard Worker TEST_P(AtomicCounterBufferTest31, AtomicCounterIncrementAndDecrement)
635*8975f5c5SAndroid Build Coastguard Worker {
636*8975f5c5SAndroid Build Coastguard Worker     constexpr char kCS[] =
637*8975f5c5SAndroid Build Coastguard Worker         "#version 310 es\n"
638*8975f5c5SAndroid Build Coastguard Worker         "layout(local_size_x=1, local_size_y=1, local_size_z=1) in;\n"
639*8975f5c5SAndroid Build Coastguard Worker         "layout(binding = 0, offset = 4) uniform atomic_uint ac[2];\n"
640*8975f5c5SAndroid Build Coastguard Worker         "void main()\n"
641*8975f5c5SAndroid Build Coastguard Worker         "{\n"
642*8975f5c5SAndroid Build Coastguard Worker         "    atomicCounterIncrement(ac[0]);\n"
643*8975f5c5SAndroid Build Coastguard Worker         "    atomicCounterDecrement(ac[1]);\n"
644*8975f5c5SAndroid Build Coastguard Worker         "}\n";
645*8975f5c5SAndroid Build Coastguard Worker 
646*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
647*8975f5c5SAndroid Build Coastguard Worker 
648*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(program);
649*8975f5c5SAndroid Build Coastguard Worker 
650*8975f5c5SAndroid Build Coastguard Worker     // The initial value of 'ac[0]' is 3u, 'ac[1]' is 1u.
651*8975f5c5SAndroid Build Coastguard Worker     unsigned int bufferData[3] = {11u, 3u, 1u};
652*8975f5c5SAndroid Build Coastguard Worker     GLBuffer atomicCounterBuffer;
653*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
654*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(bufferData), bufferData, GL_STATIC_DRAW);
655*8975f5c5SAndroid Build Coastguard Worker 
656*8975f5c5SAndroid Build Coastguard Worker     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
657*8975f5c5SAndroid Build Coastguard Worker 
658*8975f5c5SAndroid Build Coastguard Worker     glDispatchCompute(1, 1, 1);
659*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
660*8975f5c5SAndroid Build Coastguard Worker 
661*8975f5c5SAndroid Build Coastguard Worker     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
662*8975f5c5SAndroid Build Coastguard Worker 
663*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
664*8975f5c5SAndroid Build Coastguard Worker     void *mappedBuffer =
665*8975f5c5SAndroid Build Coastguard Worker         glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint) * 3, GL_MAP_READ_BIT);
666*8975f5c5SAndroid Build Coastguard Worker     memcpy(bufferData, mappedBuffer, sizeof(bufferData));
667*8975f5c5SAndroid Build Coastguard Worker     glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
668*8975f5c5SAndroid Build Coastguard Worker 
669*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(11u, bufferData[0]);
670*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(4u, bufferData[1]);
671*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(0u, bufferData[2]);
672*8975f5c5SAndroid Build Coastguard Worker }
673*8975f5c5SAndroid Build Coastguard Worker 
674*8975f5c5SAndroid Build Coastguard Worker // Tests multiple atomic counter buffers.
TEST_P(AtomicCounterBufferTest31,AtomicCounterMultipleBuffers)675*8975f5c5SAndroid Build Coastguard Worker TEST_P(AtomicCounterBufferTest31, AtomicCounterMultipleBuffers)
676*8975f5c5SAndroid Build Coastguard Worker {
677*8975f5c5SAndroid Build Coastguard Worker     GLint maxAtomicCounterBuffers = 0;
678*8975f5c5SAndroid Build Coastguard Worker     glGetIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS, &maxAtomicCounterBuffers);
679*8975f5c5SAndroid Build Coastguard Worker     constexpr unsigned int kBufferCount = 3;
680*8975f5c5SAndroid Build Coastguard Worker     // ES 3.1 table 20.45 only guarantees 1 atomic counter buffer
681*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(maxAtomicCounterBuffers < static_cast<int>(kBufferCount));
682*8975f5c5SAndroid Build Coastguard Worker 
683*8975f5c5SAndroid Build Coastguard Worker     constexpr char kComputeShaderSource[] = R"(#version 310 es
684*8975f5c5SAndroid Build Coastguard Worker layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
685*8975f5c5SAndroid Build Coastguard Worker layout(binding = 0) uniform atomic_uint ac1;
686*8975f5c5SAndroid Build Coastguard Worker layout(binding = 1) uniform atomic_uint ac2;
687*8975f5c5SAndroid Build Coastguard Worker layout(binding = 2) uniform atomic_uint ac3;
688*8975f5c5SAndroid Build Coastguard Worker 
689*8975f5c5SAndroid Build Coastguard Worker void main()
690*8975f5c5SAndroid Build Coastguard Worker {
691*8975f5c5SAndroid Build Coastguard Worker     atomicCounterIncrement(ac1);
692*8975f5c5SAndroid Build Coastguard Worker     atomicCounterIncrement(ac2);
693*8975f5c5SAndroid Build Coastguard Worker     atomicCounterIncrement(ac3);
694*8975f5c5SAndroid Build Coastguard Worker })";
695*8975f5c5SAndroid Build Coastguard Worker 
696*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
697*8975f5c5SAndroid Build Coastguard Worker 
698*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(program);
699*8975f5c5SAndroid Build Coastguard Worker 
700*8975f5c5SAndroid Build Coastguard Worker     GLBuffer atomicCounterBuffers[kBufferCount];
701*8975f5c5SAndroid Build Coastguard Worker 
702*8975f5c5SAndroid Build Coastguard Worker     for (unsigned int ii = 0; ii < kBufferCount; ++ii)
703*8975f5c5SAndroid Build Coastguard Worker     {
704*8975f5c5SAndroid Build Coastguard Worker         GLuint initialData[1] = {ii};
705*8975f5c5SAndroid Build Coastguard Worker         glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffers[ii]);
706*8975f5c5SAndroid Build Coastguard Worker         glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(initialData), initialData, GL_STATIC_DRAW);
707*8975f5c5SAndroid Build Coastguard Worker 
708*8975f5c5SAndroid Build Coastguard Worker         glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, ii, atomicCounterBuffers[ii]);
709*8975f5c5SAndroid Build Coastguard Worker     }
710*8975f5c5SAndroid Build Coastguard Worker 
711*8975f5c5SAndroid Build Coastguard Worker     glDispatchCompute(1, 1, 1);
712*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
713*8975f5c5SAndroid Build Coastguard Worker 
714*8975f5c5SAndroid Build Coastguard Worker     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
715*8975f5c5SAndroid Build Coastguard Worker 
716*8975f5c5SAndroid Build Coastguard Worker     for (unsigned int ii = 0; ii < kBufferCount; ++ii)
717*8975f5c5SAndroid Build Coastguard Worker     {
718*8975f5c5SAndroid Build Coastguard Worker         glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffers[ii]);
719*8975f5c5SAndroid Build Coastguard Worker         GLuint *mappedBuffer = static_cast<GLuint *>(
720*8975f5c5SAndroid Build Coastguard Worker             glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint), GL_MAP_READ_BIT));
721*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EQ(ii + 1, mappedBuffer[0]);
722*8975f5c5SAndroid Build Coastguard Worker         glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
723*8975f5c5SAndroid Build Coastguard Worker     }
724*8975f5c5SAndroid Build Coastguard Worker }
725*8975f5c5SAndroid Build Coastguard Worker 
726*8975f5c5SAndroid Build Coastguard Worker // Test atomic counter array of array.
TEST_P(AtomicCounterBufferTest31,AtomicCounterArrayOfArray)727*8975f5c5SAndroid Build Coastguard Worker TEST_P(AtomicCounterBufferTest31, AtomicCounterArrayOfArray)
728*8975f5c5SAndroid Build Coastguard Worker {
729*8975f5c5SAndroid Build Coastguard Worker     // Fails on D3D.  Some counters are double-incremented while some are untouched, hinting at a
730*8975f5c5SAndroid Build Coastguard Worker     // bug in index translation.  http://anglebug.com/42262427
731*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(IsD3D11());
732*8975f5c5SAndroid Build Coastguard Worker 
733*8975f5c5SAndroid Build Coastguard Worker     // Nvidia's OpenGL driver fails to compile the shader.  http://anglebug.com/42262434
734*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(IsOpenGL() && IsNVIDIA());
735*8975f5c5SAndroid Build Coastguard Worker 
736*8975f5c5SAndroid Build Coastguard Worker     // Intel's Windows OpenGL driver crashes in this test.  http://anglebug.com/42262434
737*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(IsOpenGL() && IsIntel() && IsWindows());
738*8975f5c5SAndroid Build Coastguard Worker 
739*8975f5c5SAndroid Build Coastguard Worker     constexpr char kCS[] = R"(#version 310 es
740*8975f5c5SAndroid Build Coastguard Worker layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
741*8975f5c5SAndroid Build Coastguard Worker layout(binding = 0) uniform atomic_uint ac[7][5][3];
742*8975f5c5SAndroid Build Coastguard Worker 
743*8975f5c5SAndroid Build Coastguard Worker void f0(in atomic_uint ac)
744*8975f5c5SAndroid Build Coastguard Worker {
745*8975f5c5SAndroid Build Coastguard Worker     atomicCounterIncrement(ac);
746*8975f5c5SAndroid Build Coastguard Worker }
747*8975f5c5SAndroid Build Coastguard Worker 
748*8975f5c5SAndroid Build Coastguard Worker void f1(in atomic_uint ac[3])
749*8975f5c5SAndroid Build Coastguard Worker {
750*8975f5c5SAndroid Build Coastguard Worker     atomicCounterIncrement(ac[0]);
751*8975f5c5SAndroid Build Coastguard Worker     f0(ac[1]);
752*8975f5c5SAndroid Build Coastguard Worker     int index = 2;
753*8975f5c5SAndroid Build Coastguard Worker     f0(ac[index]);
754*8975f5c5SAndroid Build Coastguard Worker }
755*8975f5c5SAndroid Build Coastguard Worker 
756*8975f5c5SAndroid Build Coastguard Worker void f2(in atomic_uint ac[5][3])
757*8975f5c5SAndroid Build Coastguard Worker {
758*8975f5c5SAndroid Build Coastguard Worker     // Increment all in ac[0], ac[1] and ac[2]
759*8975f5c5SAndroid Build Coastguard Worker     for (int i = 0; i < 3; ++i)
760*8975f5c5SAndroid Build Coastguard Worker     {
761*8975f5c5SAndroid Build Coastguard Worker         for (int j = 0; j < 2; ++j)
762*8975f5c5SAndroid Build Coastguard Worker         {
763*8975f5c5SAndroid Build Coastguard Worker             f0(ac[i][j]);
764*8975f5c5SAndroid Build Coastguard Worker         }
765*8975f5c5SAndroid Build Coastguard Worker         f0(ac[i][2]);
766*8975f5c5SAndroid Build Coastguard Worker     }
767*8975f5c5SAndroid Build Coastguard Worker 
768*8975f5c5SAndroid Build Coastguard Worker     // Increment all in ac[3]
769*8975f5c5SAndroid Build Coastguard Worker     f1(ac[3]);
770*8975f5c5SAndroid Build Coastguard Worker 
771*8975f5c5SAndroid Build Coastguard Worker     // Increment all in ac[4]
772*8975f5c5SAndroid Build Coastguard Worker     for (int i = 0; i < 2; ++i)
773*8975f5c5SAndroid Build Coastguard Worker     {
774*8975f5c5SAndroid Build Coastguard Worker         atomicCounterIncrement(ac[4][i]);
775*8975f5c5SAndroid Build Coastguard Worker     }
776*8975f5c5SAndroid Build Coastguard Worker     f0(ac[4][2]);
777*8975f5c5SAndroid Build Coastguard Worker }
778*8975f5c5SAndroid Build Coastguard Worker 
779*8975f5c5SAndroid Build Coastguard Worker void f3(in atomic_uint ac[7][5][3])
780*8975f5c5SAndroid Build Coastguard Worker {
781*8975f5c5SAndroid Build Coastguard Worker     // Increment all in ac[0], ac[1], ac[2] and ac[3]
782*8975f5c5SAndroid Build Coastguard Worker     f2(ac[0]);
783*8975f5c5SAndroid Build Coastguard Worker     for (int i = 1; i < 4; ++i)
784*8975f5c5SAndroid Build Coastguard Worker     {
785*8975f5c5SAndroid Build Coastguard Worker         f2(ac[i]);
786*8975f5c5SAndroid Build Coastguard Worker     }
787*8975f5c5SAndroid Build Coastguard Worker 
788*8975f5c5SAndroid Build Coastguard Worker     // Increment all in ac[5][0], ac[5][1], ac[5][2] and ac[5][3]
789*8975f5c5SAndroid Build Coastguard Worker     for (int i = 0; i < 4; ++i)
790*8975f5c5SAndroid Build Coastguard Worker     {
791*8975f5c5SAndroid Build Coastguard Worker         f1(ac[5][i]);
792*8975f5c5SAndroid Build Coastguard Worker     }
793*8975f5c5SAndroid Build Coastguard Worker 
794*8975f5c5SAndroid Build Coastguard Worker     // Increment all in ac[5][4][0], ac[5][4][1] and ac[5][4][2]
795*8975f5c5SAndroid Build Coastguard Worker     f0(ac[5][4][0]);
796*8975f5c5SAndroid Build Coastguard Worker     for (int i = 1; i < 3; ++i)
797*8975f5c5SAndroid Build Coastguard Worker     {
798*8975f5c5SAndroid Build Coastguard Worker         f0(ac[5][4][i]);
799*8975f5c5SAndroid Build Coastguard Worker     }
800*8975f5c5SAndroid Build Coastguard Worker 
801*8975f5c5SAndroid Build Coastguard Worker     // Increment all in ac[6]
802*8975f5c5SAndroid Build Coastguard Worker     for (int i = 0; i < 5; ++i)
803*8975f5c5SAndroid Build Coastguard Worker     {
804*8975f5c5SAndroid Build Coastguard Worker         for (int j = 0; j < 2; ++j)
805*8975f5c5SAndroid Build Coastguard Worker         {
806*8975f5c5SAndroid Build Coastguard Worker             atomicCounterIncrement(ac[6][i][j]);
807*8975f5c5SAndroid Build Coastguard Worker         }
808*8975f5c5SAndroid Build Coastguard Worker         atomicCounterIncrement(ac[6][i][2]);
809*8975f5c5SAndroid Build Coastguard Worker     }
810*8975f5c5SAndroid Build Coastguard Worker }
811*8975f5c5SAndroid Build Coastguard Worker 
812*8975f5c5SAndroid Build Coastguard Worker void main()
813*8975f5c5SAndroid Build Coastguard Worker {
814*8975f5c5SAndroid Build Coastguard Worker     // Increment all in ac except ac[4]
815*8975f5c5SAndroid Build Coastguard Worker     f3(ac);
816*8975f5c5SAndroid Build Coastguard Worker 
817*8975f5c5SAndroid Build Coastguard Worker     // Increment all in ac[4]
818*8975f5c5SAndroid Build Coastguard Worker     f2(ac[4]);
819*8975f5c5SAndroid Build Coastguard Worker })";
820*8975f5c5SAndroid Build Coastguard Worker 
821*8975f5c5SAndroid Build Coastguard Worker     constexpr uint32_t kAtomicCounterRows  = 7;
822*8975f5c5SAndroid Build Coastguard Worker     constexpr uint32_t kAtomicCounterCols  = 5;
823*8975f5c5SAndroid Build Coastguard Worker     constexpr uint32_t kAtomicCounterDepth = 3;
824*8975f5c5SAndroid Build Coastguard Worker     constexpr uint32_t kAtomicCounterCount =
825*8975f5c5SAndroid Build Coastguard Worker         kAtomicCounterRows * kAtomicCounterCols * kAtomicCounterDepth;
826*8975f5c5SAndroid Build Coastguard Worker 
827*8975f5c5SAndroid Build Coastguard Worker     GLint maxAtomicCounters = 0;
828*8975f5c5SAndroid Build Coastguard Worker     glGetIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTERS, &maxAtomicCounters);
829*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
830*8975f5c5SAndroid Build Coastguard Worker 
831*8975f5c5SAndroid Build Coastguard Worker     // Required minimum is 8 by the spec
832*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GE(maxAtomicCounters, 8);
833*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(static_cast<uint32_t>(maxAtomicCounters) < kAtomicCounterCount);
834*8975f5c5SAndroid Build Coastguard Worker 
835*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
836*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(program);
837*8975f5c5SAndroid Build Coastguard Worker 
838*8975f5c5SAndroid Build Coastguard Worker     // The initial value of atomic counters is 0, 1, 2, ...
839*8975f5c5SAndroid Build Coastguard Worker     unsigned int bufferData[kAtomicCounterCount] = {};
840*8975f5c5SAndroid Build Coastguard Worker     for (uint32_t index = 0; index < kAtomicCounterCount; ++index)
841*8975f5c5SAndroid Build Coastguard Worker     {
842*8975f5c5SAndroid Build Coastguard Worker         bufferData[index] = index;
843*8975f5c5SAndroid Build Coastguard Worker     }
844*8975f5c5SAndroid Build Coastguard Worker 
845*8975f5c5SAndroid Build Coastguard Worker     GLBuffer atomicCounterBuffer;
846*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
847*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(bufferData), bufferData, GL_STATIC_DRAW);
848*8975f5c5SAndroid Build Coastguard Worker 
849*8975f5c5SAndroid Build Coastguard Worker     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
850*8975f5c5SAndroid Build Coastguard Worker 
851*8975f5c5SAndroid Build Coastguard Worker     glDispatchCompute(1, 1, 1);
852*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
853*8975f5c5SAndroid Build Coastguard Worker 
854*8975f5c5SAndroid Build Coastguard Worker     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
855*8975f5c5SAndroid Build Coastguard Worker 
856*8975f5c5SAndroid Build Coastguard Worker     unsigned int result[kAtomicCounterCount] = {};
857*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
858*8975f5c5SAndroid Build Coastguard Worker     void *mappedBuffer =
859*8975f5c5SAndroid Build Coastguard Worker         glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(bufferData), GL_MAP_READ_BIT);
860*8975f5c5SAndroid Build Coastguard Worker     memcpy(result, mappedBuffer, sizeof(bufferData));
861*8975f5c5SAndroid Build Coastguard Worker     glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
862*8975f5c5SAndroid Build Coastguard Worker 
863*8975f5c5SAndroid Build Coastguard Worker     for (uint32_t index = 0; index < kAtomicCounterCount; ++index)
864*8975f5c5SAndroid Build Coastguard Worker     {
865*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EQ(result[index], bufferData[index] + 1) << "index " << index;
866*8975f5c5SAndroid Build Coastguard Worker     }
867*8975f5c5SAndroid Build Coastguard Worker }
868*8975f5c5SAndroid Build Coastguard Worker 
869*8975f5c5SAndroid Build Coastguard Worker // Test inactive atomic counter
TEST_P(AtomicCounterBufferTest31,AtomicCounterInactive)870*8975f5c5SAndroid Build Coastguard Worker TEST_P(AtomicCounterBufferTest31, AtomicCounterInactive)
871*8975f5c5SAndroid Build Coastguard Worker {
872*8975f5c5SAndroid Build Coastguard Worker     constexpr char kFS[] =
873*8975f5c5SAndroid Build Coastguard Worker         "#version 310 es\n"
874*8975f5c5SAndroid Build Coastguard Worker         "precision highp float;\n"
875*8975f5c5SAndroid Build Coastguard Worker 
876*8975f5c5SAndroid Build Coastguard Worker         // This inactive atomic counter should be removed by RemoveInactiveInterfaceVariables
877*8975f5c5SAndroid Build Coastguard Worker         "layout(binding = 0) uniform atomic_uint inactive;\n"
878*8975f5c5SAndroid Build Coastguard Worker 
879*8975f5c5SAndroid Build Coastguard Worker         "out highp vec4 my_color;\n"
880*8975f5c5SAndroid Build Coastguard Worker         "void main()\n"
881*8975f5c5SAndroid Build Coastguard Worker         "{\n"
882*8975f5c5SAndroid Build Coastguard Worker         "    my_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
883*8975f5c5SAndroid Build Coastguard Worker         "}\n";
884*8975f5c5SAndroid Build Coastguard Worker 
885*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
886*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(program);
887*8975f5c5SAndroid Build Coastguard Worker 
888*8975f5c5SAndroid Build Coastguard Worker     drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
889*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
890*8975f5c5SAndroid Build Coastguard Worker 
891*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
892*8975f5c5SAndroid Build Coastguard Worker }
893*8975f5c5SAndroid Build Coastguard Worker 
894*8975f5c5SAndroid Build Coastguard Worker // Test inactive memoryBarrierAtomicCounter
TEST_P(AtomicCounterBufferTest31,AtomicCounterMemoryBarrier)895*8975f5c5SAndroid Build Coastguard Worker TEST_P(AtomicCounterBufferTest31, AtomicCounterMemoryBarrier)
896*8975f5c5SAndroid Build Coastguard Worker {
897*8975f5c5SAndroid Build Coastguard Worker     constexpr char kFS[] =
898*8975f5c5SAndroid Build Coastguard Worker         "#version 310 es\n"
899*8975f5c5SAndroid Build Coastguard Worker         "precision highp float;\n"
900*8975f5c5SAndroid Build Coastguard Worker         // This inactive atomic counter should be removed by RemoveInactiveInterfaceVariables
901*8975f5c5SAndroid Build Coastguard Worker         "layout(binding = 0) uniform atomic_uint inactive;\n"
902*8975f5c5SAndroid Build Coastguard Worker         "out highp vec4 my_color;\n"
903*8975f5c5SAndroid Build Coastguard Worker         "void main()\n"
904*8975f5c5SAndroid Build Coastguard Worker         "{\n"
905*8975f5c5SAndroid Build Coastguard Worker         "    my_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
906*8975f5c5SAndroid Build Coastguard Worker         // This barrier should be removed by RemoveAtomicCounterBuiltins because
907*8975f5c5SAndroid Build Coastguard Worker         // there are no active atomic counters
908*8975f5c5SAndroid Build Coastguard Worker         "    memoryBarrierAtomicCounter();\n"
909*8975f5c5SAndroid Build Coastguard Worker         "}\n";
910*8975f5c5SAndroid Build Coastguard Worker 
911*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
912*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(program);
913*8975f5c5SAndroid Build Coastguard Worker 
914*8975f5c5SAndroid Build Coastguard Worker     drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
915*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
916*8975f5c5SAndroid Build Coastguard Worker 
917*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
918*8975f5c5SAndroid Build Coastguard Worker }
919*8975f5c5SAndroid Build Coastguard Worker 
920*8975f5c5SAndroid Build Coastguard Worker GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AtomicCounterBufferTest);
921*8975f5c5SAndroid Build Coastguard Worker GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AtomicCounterBufferTest31);
922*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST_ES3_AND_ES31(AtomicCounterBufferTest);
923*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST_ES31(AtomicCounterBufferTest31);
924*8975f5c5SAndroid Build Coastguard Worker 
925*8975f5c5SAndroid Build Coastguard Worker }  // namespace
926