xref: /aosp_15_r20/external/deqp/modules/gles31/functional/es31fIndirectComputeDispatchTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker  * drawElements Quality Program OpenGL ES 3.1 Module
3*35238bceSAndroid Build Coastguard Worker  * -------------------------------------------------
4*35238bceSAndroid Build Coastguard Worker  *
5*35238bceSAndroid Build Coastguard Worker  * Copyright 2014 The Android Open Source Project
6*35238bceSAndroid Build Coastguard Worker  *
7*35238bceSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
8*35238bceSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
9*35238bceSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
10*35238bceSAndroid Build Coastguard Worker  *
11*35238bceSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
12*35238bceSAndroid Build Coastguard Worker  *
13*35238bceSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
14*35238bceSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
15*35238bceSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16*35238bceSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
17*35238bceSAndroid Build Coastguard Worker  * limitations under the License.
18*35238bceSAndroid Build Coastguard Worker  *
19*35238bceSAndroid Build Coastguard Worker  *//*!
20*35238bceSAndroid Build Coastguard Worker  * \file
21*35238bceSAndroid Build Coastguard Worker  * \brief Indirect compute dispatch tests.
22*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker 
24*35238bceSAndroid Build Coastguard Worker #include "es31fIndirectComputeDispatchTests.hpp"
25*35238bceSAndroid Build Coastguard Worker #include "gluObjectWrapper.hpp"
26*35238bceSAndroid Build Coastguard Worker #include "gluRenderContext.hpp"
27*35238bceSAndroid Build Coastguard Worker #include "gluShaderProgram.hpp"
28*35238bceSAndroid Build Coastguard Worker #include "glwFunctions.hpp"
29*35238bceSAndroid Build Coastguard Worker #include "glwEnums.hpp"
30*35238bceSAndroid Build Coastguard Worker #include "tcuVector.hpp"
31*35238bceSAndroid Build Coastguard Worker #include "tcuStringTemplate.hpp"
32*35238bceSAndroid Build Coastguard Worker #include "tcuTestLog.hpp"
33*35238bceSAndroid Build Coastguard Worker #include "deStringUtil.hpp"
34*35238bceSAndroid Build Coastguard Worker 
35*35238bceSAndroid Build Coastguard Worker #include <vector>
36*35238bceSAndroid Build Coastguard Worker #include <string>
37*35238bceSAndroid Build Coastguard Worker #include <map>
38*35238bceSAndroid Build Coastguard Worker 
39*35238bceSAndroid Build Coastguard Worker namespace deqp
40*35238bceSAndroid Build Coastguard Worker {
41*35238bceSAndroid Build Coastguard Worker namespace gles31
42*35238bceSAndroid Build Coastguard Worker {
43*35238bceSAndroid Build Coastguard Worker namespace Functional
44*35238bceSAndroid Build Coastguard Worker {
45*35238bceSAndroid Build Coastguard Worker 
46*35238bceSAndroid Build Coastguard Worker using std::map;
47*35238bceSAndroid Build Coastguard Worker using std::string;
48*35238bceSAndroid Build Coastguard Worker using std::vector;
49*35238bceSAndroid Build Coastguard Worker using tcu::TestLog;
50*35238bceSAndroid Build Coastguard Worker using tcu::UVec3;
51*35238bceSAndroid Build Coastguard Worker 
52*35238bceSAndroid Build Coastguard Worker // \todo [2014-02-17 pyry] Should be extended with following:
53*35238bceSAndroid Build Coastguard Worker 
54*35238bceSAndroid Build Coastguard Worker // Negative:
55*35238bceSAndroid Build Coastguard Worker //  - no active shader program
56*35238bceSAndroid Build Coastguard Worker //  - indirect negative or not aligned
57*35238bceSAndroid Build Coastguard Worker //  - indirect + size outside buffer bounds
58*35238bceSAndroid Build Coastguard Worker //  - no buffer bound to DRAW_INDIRECT_BUFFER
59*35238bceSAndroid Build Coastguard Worker //  - (implict) buffer mapped
60*35238bceSAndroid Build Coastguard Worker 
61*35238bceSAndroid Build Coastguard Worker // Robustness:
62*35238bceSAndroid Build Coastguard Worker //  - lot of small work group launches
63*35238bceSAndroid Build Coastguard Worker //  - very large work group size
64*35238bceSAndroid Build Coastguard Worker //  - no synchronization, touched by gpu
65*35238bceSAndroid Build Coastguard Worker //  - compute program overwiting buffer
66*35238bceSAndroid Build Coastguard Worker 
67*35238bceSAndroid Build Coastguard Worker namespace
68*35238bceSAndroid Build Coastguard Worker {
69*35238bceSAndroid Build Coastguard Worker 
70*35238bceSAndroid Build Coastguard Worker enum
71*35238bceSAndroid Build Coastguard Worker {
72*35238bceSAndroid Build Coastguard Worker     RESULT_BLOCK_BASE_SIZE             = (3 + 1) * (int)sizeof(uint32_t), // uvec3 + uint
73*35238bceSAndroid Build Coastguard Worker     RESULT_BLOCK_EXPECTED_COUNT_OFFSET = 0,
74*35238bceSAndroid Build Coastguard Worker     RESULT_BLOCK_NUM_PASSED_OFFSET     = 3 * (int)sizeof(uint32_t),
75*35238bceSAndroid Build Coastguard Worker 
76*35238bceSAndroid Build Coastguard Worker     INDIRECT_COMMAND_SIZE = 3 * (int)sizeof(uint32_t)
77*35238bceSAndroid Build Coastguard Worker };
78*35238bceSAndroid Build Coastguard Worker 
79*35238bceSAndroid Build Coastguard Worker enum GenBuffer
80*35238bceSAndroid Build Coastguard Worker {
81*35238bceSAndroid Build Coastguard Worker     GEN_BUFFER_UPLOAD = 0,
82*35238bceSAndroid Build Coastguard Worker     GEN_BUFFER_COMPUTE,
83*35238bceSAndroid Build Coastguard Worker 
84*35238bceSAndroid Build Coastguard Worker     GEN_BUFFER_LAST
85*35238bceSAndroid Build Coastguard Worker };
86*35238bceSAndroid Build Coastguard Worker 
genVerifySources(const UVec3 & workGroupSize)87*35238bceSAndroid Build Coastguard Worker glu::ProgramSources genVerifySources(const UVec3 &workGroupSize)
88*35238bceSAndroid Build Coastguard Worker {
89*35238bceSAndroid Build Coastguard Worker     static const char *s_verifyDispatchTmpl =
90*35238bceSAndroid Build Coastguard Worker         "#version 310 es\n"
91*35238bceSAndroid Build Coastguard Worker         "layout(local_size_x = ${LOCAL_SIZE_X}, local_size_y = ${LOCAL_SIZE_Y}, local_size_z = ${LOCAL_SIZE_Z}) in;\n"
92*35238bceSAndroid Build Coastguard Worker         "layout(binding = 0, std430) buffer Result\n"
93*35238bceSAndroid Build Coastguard Worker         "{\n"
94*35238bceSAndroid Build Coastguard Worker         "    uvec3           expectedGroupCount;\n"
95*35238bceSAndroid Build Coastguard Worker         "    coherent uint   numPassed;\n"
96*35238bceSAndroid Build Coastguard Worker         "} result;\n"
97*35238bceSAndroid Build Coastguard Worker         "void main (void)\n"
98*35238bceSAndroid Build Coastguard Worker         "{\n"
99*35238bceSAndroid Build Coastguard Worker         "    if (all(equal(result.expectedGroupCount, gl_NumWorkGroups)))\n"
100*35238bceSAndroid Build Coastguard Worker         "        atomicAdd(result.numPassed, 1u);\n"
101*35238bceSAndroid Build Coastguard Worker         "}\n";
102*35238bceSAndroid Build Coastguard Worker 
103*35238bceSAndroid Build Coastguard Worker     map<string, string> args;
104*35238bceSAndroid Build Coastguard Worker 
105*35238bceSAndroid Build Coastguard Worker     args["LOCAL_SIZE_X"] = de::toString(workGroupSize.x());
106*35238bceSAndroid Build Coastguard Worker     args["LOCAL_SIZE_Y"] = de::toString(workGroupSize.y());
107*35238bceSAndroid Build Coastguard Worker     args["LOCAL_SIZE_Z"] = de::toString(workGroupSize.z());
108*35238bceSAndroid Build Coastguard Worker 
109*35238bceSAndroid Build Coastguard Worker     return glu::ProgramSources() << glu::ComputeSource(tcu::StringTemplate(s_verifyDispatchTmpl).specialize(args));
110*35238bceSAndroid Build Coastguard Worker }
111*35238bceSAndroid Build Coastguard Worker 
112*35238bceSAndroid Build Coastguard Worker class IndirectDispatchCase : public TestCase
113*35238bceSAndroid Build Coastguard Worker {
114*35238bceSAndroid Build Coastguard Worker public:
115*35238bceSAndroid Build Coastguard Worker     IndirectDispatchCase(Context &context, const char *name, const char *description, GenBuffer genBuffer);
116*35238bceSAndroid Build Coastguard Worker     ~IndirectDispatchCase(void);
117*35238bceSAndroid Build Coastguard Worker 
118*35238bceSAndroid Build Coastguard Worker     IterateResult iterate(void);
119*35238bceSAndroid Build Coastguard Worker 
120*35238bceSAndroid Build Coastguard Worker protected:
121*35238bceSAndroid Build Coastguard Worker     struct DispatchCommand
122*35238bceSAndroid Build Coastguard Worker     {
123*35238bceSAndroid Build Coastguard Worker         intptr_t offset;
124*35238bceSAndroid Build Coastguard Worker         UVec3 numWorkGroups;
125*35238bceSAndroid Build Coastguard Worker 
DispatchCommanddeqp::gles31::Functional::__anonacebb5ad0111::IndirectDispatchCase::DispatchCommand126*35238bceSAndroid Build Coastguard Worker         DispatchCommand(void) : offset(0)
127*35238bceSAndroid Build Coastguard Worker         {
128*35238bceSAndroid Build Coastguard Worker         }
DispatchCommanddeqp::gles31::Functional::__anonacebb5ad0111::IndirectDispatchCase::DispatchCommand129*35238bceSAndroid Build Coastguard Worker         DispatchCommand(intptr_t offset_, const UVec3 &numWorkGroups_) : offset(offset_), numWorkGroups(numWorkGroups_)
130*35238bceSAndroid Build Coastguard Worker         {
131*35238bceSAndroid Build Coastguard Worker         }
132*35238bceSAndroid Build Coastguard Worker     };
133*35238bceSAndroid Build Coastguard Worker 
134*35238bceSAndroid Build Coastguard Worker     GenBuffer m_genBuffer;
135*35238bceSAndroid Build Coastguard Worker     uintptr_t m_bufferSize;
136*35238bceSAndroid Build Coastguard Worker     UVec3 m_workGroupSize;
137*35238bceSAndroid Build Coastguard Worker     vector<DispatchCommand> m_commands;
138*35238bceSAndroid Build Coastguard Worker 
139*35238bceSAndroid Build Coastguard Worker     void createCommandBuffer(uint32_t buffer) const;
140*35238bceSAndroid Build Coastguard Worker     void createResultBuffer(uint32_t buffer) const;
141*35238bceSAndroid Build Coastguard Worker 
142*35238bceSAndroid Build Coastguard Worker     bool verifyResultBuffer(uint32_t buffer);
143*35238bceSAndroid Build Coastguard Worker 
144*35238bceSAndroid Build Coastguard Worker     void createCmdBufferUpload(uint32_t buffer) const;
145*35238bceSAndroid Build Coastguard Worker     void createCmdBufferCompute(uint32_t buffer) const;
146*35238bceSAndroid Build Coastguard Worker 
147*35238bceSAndroid Build Coastguard Worker private:
148*35238bceSAndroid Build Coastguard Worker     IndirectDispatchCase(const IndirectDispatchCase &);
149*35238bceSAndroid Build Coastguard Worker     IndirectDispatchCase &operator=(const IndirectDispatchCase &);
150*35238bceSAndroid Build Coastguard Worker };
151*35238bceSAndroid Build Coastguard Worker 
IndirectDispatchCase(Context & context,const char * name,const char * description,GenBuffer genBuffer)152*35238bceSAndroid Build Coastguard Worker IndirectDispatchCase::IndirectDispatchCase(Context &context, const char *name, const char *description,
153*35238bceSAndroid Build Coastguard Worker                                            GenBuffer genBuffer)
154*35238bceSAndroid Build Coastguard Worker     : TestCase(context, name, description)
155*35238bceSAndroid Build Coastguard Worker     , m_genBuffer(genBuffer)
156*35238bceSAndroid Build Coastguard Worker     , m_bufferSize(0)
157*35238bceSAndroid Build Coastguard Worker {
158*35238bceSAndroid Build Coastguard Worker }
159*35238bceSAndroid Build Coastguard Worker 
~IndirectDispatchCase(void)160*35238bceSAndroid Build Coastguard Worker IndirectDispatchCase::~IndirectDispatchCase(void)
161*35238bceSAndroid Build Coastguard Worker {
162*35238bceSAndroid Build Coastguard Worker }
163*35238bceSAndroid Build Coastguard Worker 
getResultBlockAlignedSize(const glw::Functions & gl)164*35238bceSAndroid Build Coastguard Worker static int getResultBlockAlignedSize(const glw::Functions &gl)
165*35238bceSAndroid Build Coastguard Worker {
166*35238bceSAndroid Build Coastguard Worker     const int baseSize = RESULT_BLOCK_BASE_SIZE;
167*35238bceSAndroid Build Coastguard Worker     int alignment      = 0;
168*35238bceSAndroid Build Coastguard Worker     gl.getIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &alignment);
169*35238bceSAndroid Build Coastguard Worker 
170*35238bceSAndroid Build Coastguard Worker     if (alignment == 0 || (baseSize % alignment == 0))
171*35238bceSAndroid Build Coastguard Worker         return baseSize;
172*35238bceSAndroid Build Coastguard Worker     else
173*35238bceSAndroid Build Coastguard Worker         return (baseSize / alignment + 1) * alignment;
174*35238bceSAndroid Build Coastguard Worker }
175*35238bceSAndroid Build Coastguard Worker 
createCommandBuffer(uint32_t buffer) const176*35238bceSAndroid Build Coastguard Worker void IndirectDispatchCase::createCommandBuffer(uint32_t buffer) const
177*35238bceSAndroid Build Coastguard Worker {
178*35238bceSAndroid Build Coastguard Worker     switch (m_genBuffer)
179*35238bceSAndroid Build Coastguard Worker     {
180*35238bceSAndroid Build Coastguard Worker     case GEN_BUFFER_UPLOAD:
181*35238bceSAndroid Build Coastguard Worker         createCmdBufferUpload(buffer);
182*35238bceSAndroid Build Coastguard Worker         break;
183*35238bceSAndroid Build Coastguard Worker     case GEN_BUFFER_COMPUTE:
184*35238bceSAndroid Build Coastguard Worker         createCmdBufferCompute(buffer);
185*35238bceSAndroid Build Coastguard Worker         break;
186*35238bceSAndroid Build Coastguard Worker     default:
187*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
188*35238bceSAndroid Build Coastguard Worker     }
189*35238bceSAndroid Build Coastguard Worker }
190*35238bceSAndroid Build Coastguard Worker 
createCmdBufferUpload(uint32_t buffer) const191*35238bceSAndroid Build Coastguard Worker void IndirectDispatchCase::createCmdBufferUpload(uint32_t buffer) const
192*35238bceSAndroid Build Coastguard Worker {
193*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
194*35238bceSAndroid Build Coastguard Worker     vector<uint8_t> data(m_bufferSize);
195*35238bceSAndroid Build Coastguard Worker 
196*35238bceSAndroid Build Coastguard Worker     for (vector<DispatchCommand>::const_iterator cmdIter = m_commands.begin(); cmdIter != m_commands.end(); ++cmdIter)
197*35238bceSAndroid Build Coastguard Worker     {
198*35238bceSAndroid Build Coastguard Worker         DE_STATIC_ASSERT(INDIRECT_COMMAND_SIZE >= sizeof(uint32_t) * 3);
199*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(cmdIter->offset >= 0);
200*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(cmdIter->offset % sizeof(uint32_t) == 0);
201*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(cmdIter->offset + INDIRECT_COMMAND_SIZE <= (intptr_t)m_bufferSize);
202*35238bceSAndroid Build Coastguard Worker 
203*35238bceSAndroid Build Coastguard Worker         uint32_t *const dstPtr = (uint32_t *)&data[cmdIter->offset];
204*35238bceSAndroid Build Coastguard Worker 
205*35238bceSAndroid Build Coastguard Worker         dstPtr[0] = cmdIter->numWorkGroups[0];
206*35238bceSAndroid Build Coastguard Worker         dstPtr[1] = cmdIter->numWorkGroups[1];
207*35238bceSAndroid Build Coastguard Worker         dstPtr[2] = cmdIter->numWorkGroups[2];
208*35238bceSAndroid Build Coastguard Worker     }
209*35238bceSAndroid Build Coastguard Worker 
210*35238bceSAndroid Build Coastguard Worker     gl.bindBuffer(GL_DISPATCH_INDIRECT_BUFFER, buffer);
211*35238bceSAndroid Build Coastguard Worker     gl.bufferData(GL_DISPATCH_INDIRECT_BUFFER, (glw::GLsizeiptr)data.size(), &data[0], GL_STATIC_DRAW);
212*35238bceSAndroid Build Coastguard Worker }
213*35238bceSAndroid Build Coastguard Worker 
createCmdBufferCompute(uint32_t buffer) const214*35238bceSAndroid Build Coastguard Worker void IndirectDispatchCase::createCmdBufferCompute(uint32_t buffer) const
215*35238bceSAndroid Build Coastguard Worker {
216*35238bceSAndroid Build Coastguard Worker     std::ostringstream src;
217*35238bceSAndroid Build Coastguard Worker 
218*35238bceSAndroid Build Coastguard Worker     // Header
219*35238bceSAndroid Build Coastguard Worker     src << "#version 310 es\n"
220*35238bceSAndroid Build Coastguard Worker            "layout(local_size_x = 1) in;\n"
221*35238bceSAndroid Build Coastguard Worker            "layout(std430, binding = 1) buffer Out\n"
222*35238bceSAndroid Build Coastguard Worker            "{\n"
223*35238bceSAndroid Build Coastguard Worker            "    highp uint data[];\n"
224*35238bceSAndroid Build Coastguard Worker            "};\n"
225*35238bceSAndroid Build Coastguard Worker            "void writeCmd (uint offset, uvec3 numWorkGroups)\n"
226*35238bceSAndroid Build Coastguard Worker            "{\n"
227*35238bceSAndroid Build Coastguard Worker            "    data[offset+0u] = numWorkGroups.x;\n"
228*35238bceSAndroid Build Coastguard Worker            "    data[offset+1u] = numWorkGroups.y;\n"
229*35238bceSAndroid Build Coastguard Worker            "    data[offset+2u] = numWorkGroups.z;\n"
230*35238bceSAndroid Build Coastguard Worker            "}\n"
231*35238bceSAndroid Build Coastguard Worker            "void main (void)\n"
232*35238bceSAndroid Build Coastguard Worker            "{\n";
233*35238bceSAndroid Build Coastguard Worker 
234*35238bceSAndroid Build Coastguard Worker     // Commands
235*35238bceSAndroid Build Coastguard Worker     for (vector<DispatchCommand>::const_iterator cmdIter = m_commands.begin(); cmdIter != m_commands.end(); ++cmdIter)
236*35238bceSAndroid Build Coastguard Worker     {
237*35238bceSAndroid Build Coastguard Worker         const uint32_t offs = (uint32_t)(cmdIter->offset / 4);
238*35238bceSAndroid Build Coastguard Worker         DE_ASSERT((intptr_t)offs * 4 == cmdIter->offset);
239*35238bceSAndroid Build Coastguard Worker 
240*35238bceSAndroid Build Coastguard Worker         src << "\twriteCmd(" << offs << "u, uvec3(" << cmdIter->numWorkGroups.x() << "u, " << cmdIter->numWorkGroups.y()
241*35238bceSAndroid Build Coastguard Worker             << "u, " << cmdIter->numWorkGroups.z() << "u));\n";
242*35238bceSAndroid Build Coastguard Worker     }
243*35238bceSAndroid Build Coastguard Worker 
244*35238bceSAndroid Build Coastguard Worker     src << "}\n";
245*35238bceSAndroid Build Coastguard Worker 
246*35238bceSAndroid Build Coastguard Worker     {
247*35238bceSAndroid Build Coastguard Worker         const glw::Functions &gl = m_context.getRenderContext().getFunctions();
248*35238bceSAndroid Build Coastguard Worker         glu::ShaderProgram program(m_context.getRenderContext(), glu::ProgramSources()
249*35238bceSAndroid Build Coastguard Worker                                                                      << glu::ComputeSource(src.str()));
250*35238bceSAndroid Build Coastguard Worker 
251*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << program;
252*35238bceSAndroid Build Coastguard Worker         if (!program.isOk())
253*35238bceSAndroid Build Coastguard Worker             TCU_FAIL("Compile failed");
254*35238bceSAndroid Build Coastguard Worker 
255*35238bceSAndroid Build Coastguard Worker         gl.useProgram(program.getProgram());
256*35238bceSAndroid Build Coastguard Worker 
257*35238bceSAndroid Build Coastguard Worker         gl.bindBuffer(GL_DISPATCH_INDIRECT_BUFFER, buffer);
258*35238bceSAndroid Build Coastguard Worker         gl.bufferData(GL_DISPATCH_INDIRECT_BUFFER, (glw::GLsizeiptr)m_bufferSize, DE_NULL, GL_STATIC_DRAW);
259*35238bceSAndroid Build Coastguard Worker         gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, buffer);
260*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.getError(), "Buffer setup failed");
261*35238bceSAndroid Build Coastguard Worker 
262*35238bceSAndroid Build Coastguard Worker         gl.dispatchCompute(1, 1, 1);
263*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.getError(), "glDispatchCompute() failed");
264*35238bceSAndroid Build Coastguard Worker 
265*35238bceSAndroid Build Coastguard Worker         gl.memoryBarrier(GL_COMMAND_BARRIER_BIT);
266*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.getError(), "glMemoryBarrier(GL_COMMAND_BARRIER_BIT) failed");
267*35238bceSAndroid Build Coastguard Worker     }
268*35238bceSAndroid Build Coastguard Worker }
269*35238bceSAndroid Build Coastguard Worker 
createResultBuffer(uint32_t buffer) const270*35238bceSAndroid Build Coastguard Worker void IndirectDispatchCase::createResultBuffer(uint32_t buffer) const
271*35238bceSAndroid Build Coastguard Worker {
272*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl   = m_context.getRenderContext().getFunctions();
273*35238bceSAndroid Build Coastguard Worker     const int resultBlockSize  = getResultBlockAlignedSize(gl);
274*35238bceSAndroid Build Coastguard Worker     const int resultBufferSize = resultBlockSize * (int)m_commands.size();
275*35238bceSAndroid Build Coastguard Worker     vector<uint8_t> data(resultBufferSize);
276*35238bceSAndroid Build Coastguard Worker 
277*35238bceSAndroid Build Coastguard Worker     for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
278*35238bceSAndroid Build Coastguard Worker     {
279*35238bceSAndroid Build Coastguard Worker         uint8_t *const dstPtr = &data[resultBlockSize * cmdNdx];
280*35238bceSAndroid Build Coastguard Worker 
281*35238bceSAndroid Build Coastguard Worker         *(uint32_t *)(dstPtr + RESULT_BLOCK_EXPECTED_COUNT_OFFSET + 0 * 4) = m_commands[cmdNdx].numWorkGroups[0];
282*35238bceSAndroid Build Coastguard Worker         *(uint32_t *)(dstPtr + RESULT_BLOCK_EXPECTED_COUNT_OFFSET + 1 * 4) = m_commands[cmdNdx].numWorkGroups[1];
283*35238bceSAndroid Build Coastguard Worker         *(uint32_t *)(dstPtr + RESULT_BLOCK_EXPECTED_COUNT_OFFSET + 2 * 4) = m_commands[cmdNdx].numWorkGroups[2];
284*35238bceSAndroid Build Coastguard Worker         *(uint32_t *)(dstPtr + RESULT_BLOCK_NUM_PASSED_OFFSET)             = 0;
285*35238bceSAndroid Build Coastguard Worker     }
286*35238bceSAndroid Build Coastguard Worker 
287*35238bceSAndroid Build Coastguard Worker     gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
288*35238bceSAndroid Build Coastguard Worker     gl.bufferData(GL_SHADER_STORAGE_BUFFER, (glw::GLsizei)data.size(), &data[0], GL_STATIC_READ);
289*35238bceSAndroid Build Coastguard Worker }
290*35238bceSAndroid Build Coastguard Worker 
computeInvocationCount(const UVec3 & workGroupSize,const UVec3 & numWorkGroups)291*35238bceSAndroid Build Coastguard Worker uint32_t computeInvocationCount(const UVec3 &workGroupSize, const UVec3 &numWorkGroups)
292*35238bceSAndroid Build Coastguard Worker {
293*35238bceSAndroid Build Coastguard Worker     const int numInvocationsPerGroup = workGroupSize[0] * workGroupSize[1] * workGroupSize[2];
294*35238bceSAndroid Build Coastguard Worker     const int numGroups              = numWorkGroups[0] * numWorkGroups[1] * numWorkGroups[2];
295*35238bceSAndroid Build Coastguard Worker 
296*35238bceSAndroid Build Coastguard Worker     return numInvocationsPerGroup * numGroups;
297*35238bceSAndroid Build Coastguard Worker }
298*35238bceSAndroid Build Coastguard Worker 
verifyResultBuffer(uint32_t buffer)299*35238bceSAndroid Build Coastguard Worker bool IndirectDispatchCase::verifyResultBuffer(uint32_t buffer)
300*35238bceSAndroid Build Coastguard Worker {
301*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
302*35238bceSAndroid Build Coastguard Worker 
303*35238bceSAndroid Build Coastguard Worker     const int resultBlockSize  = getResultBlockAlignedSize(gl);
304*35238bceSAndroid Build Coastguard Worker     const int resultBufferSize = resultBlockSize * (int)m_commands.size();
305*35238bceSAndroid Build Coastguard Worker 
306*35238bceSAndroid Build Coastguard Worker     void *mapPtr = DE_NULL;
307*35238bceSAndroid Build Coastguard Worker     bool allOk   = true;
308*35238bceSAndroid Build Coastguard Worker 
309*35238bceSAndroid Build Coastguard Worker     try
310*35238bceSAndroid Build Coastguard Worker     {
311*35238bceSAndroid Build Coastguard Worker         gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
312*35238bceSAndroid Build Coastguard Worker         mapPtr = gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, resultBufferSize, GL_MAP_READ_BIT);
313*35238bceSAndroid Build Coastguard Worker 
314*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() failed");
315*35238bceSAndroid Build Coastguard Worker         TCU_CHECK(mapPtr);
316*35238bceSAndroid Build Coastguard Worker 
317*35238bceSAndroid Build Coastguard Worker         for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
318*35238bceSAndroid Build Coastguard Worker         {
319*35238bceSAndroid Build Coastguard Worker             const DispatchCommand &cmd   = m_commands[cmdNdx];
320*35238bceSAndroid Build Coastguard Worker             const uint8_t *const srcPtr  = (const uint8_t *)mapPtr + cmdNdx * resultBlockSize;
321*35238bceSAndroid Build Coastguard Worker             const uint32_t numPassed     = *(const uint32_t *)(srcPtr + RESULT_BLOCK_NUM_PASSED_OFFSET);
322*35238bceSAndroid Build Coastguard Worker             const uint32_t expectedCount = computeInvocationCount(m_workGroupSize, cmd.numWorkGroups);
323*35238bceSAndroid Build Coastguard Worker 
324*35238bceSAndroid Build Coastguard Worker             // Verify numPassed.
325*35238bceSAndroid Build Coastguard Worker             if (numPassed != expectedCount)
326*35238bceSAndroid Build Coastguard Worker             {
327*35238bceSAndroid Build Coastguard Worker                 m_testCtx.getLog() << TestLog::Message << "ERROR: got invalid result for invocation " << cmdNdx
328*35238bceSAndroid Build Coastguard Worker                                    << ": got numPassed = " << numPassed << ", expected " << expectedCount
329*35238bceSAndroid Build Coastguard Worker                                    << TestLog::EndMessage;
330*35238bceSAndroid Build Coastguard Worker                 allOk = false;
331*35238bceSAndroid Build Coastguard Worker             }
332*35238bceSAndroid Build Coastguard Worker         }
333*35238bceSAndroid Build Coastguard Worker     }
334*35238bceSAndroid Build Coastguard Worker     catch (...)
335*35238bceSAndroid Build Coastguard Worker     {
336*35238bceSAndroid Build Coastguard Worker         if (mapPtr)
337*35238bceSAndroid Build Coastguard Worker             gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
338*35238bceSAndroid Build Coastguard Worker     }
339*35238bceSAndroid Build Coastguard Worker 
340*35238bceSAndroid Build Coastguard Worker     gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
341*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() failed");
342*35238bceSAndroid Build Coastguard Worker 
343*35238bceSAndroid Build Coastguard Worker     return allOk;
344*35238bceSAndroid Build Coastguard Worker }
345*35238bceSAndroid Build Coastguard Worker 
iterate(void)346*35238bceSAndroid Build Coastguard Worker IndirectDispatchCase::IterateResult IndirectDispatchCase::iterate(void)
347*35238bceSAndroid Build Coastguard Worker {
348*35238bceSAndroid Build Coastguard Worker     const glu::RenderContext &renderCtx = m_context.getRenderContext();
349*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl            = renderCtx.getFunctions();
350*35238bceSAndroid Build Coastguard Worker 
351*35238bceSAndroid Build Coastguard Worker     const glu::ShaderProgram program(renderCtx, genVerifySources(m_workGroupSize));
352*35238bceSAndroid Build Coastguard Worker 
353*35238bceSAndroid Build Coastguard Worker     glu::Buffer cmdBuffer(renderCtx);
354*35238bceSAndroid Build Coastguard Worker     glu::Buffer resultBuffer(renderCtx);
355*35238bceSAndroid Build Coastguard Worker 
356*35238bceSAndroid Build Coastguard Worker     m_testCtx.getLog() << program;
357*35238bceSAndroid Build Coastguard Worker     TCU_CHECK_MSG(program.isOk(), "Compile failed");
358*35238bceSAndroid Build Coastguard Worker 
359*35238bceSAndroid Build Coastguard Worker     m_testCtx.getLog() << TestLog::Message << "GL_DISPATCH_INDIRECT_BUFFER size = " << m_bufferSize
360*35238bceSAndroid Build Coastguard Worker                        << TestLog::EndMessage;
361*35238bceSAndroid Build Coastguard Worker     {
362*35238bceSAndroid Build Coastguard Worker         tcu::ScopedLogSection section(m_testCtx.getLog(), "Commands",
363*35238bceSAndroid Build Coastguard Worker                                       "Indirect Dispatch Commands (" + de::toString(m_commands.size()) + " in total)");
364*35238bceSAndroid Build Coastguard Worker 
365*35238bceSAndroid Build Coastguard Worker         for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
366*35238bceSAndroid Build Coastguard Worker             m_testCtx.getLog() << TestLog::Message << cmdNdx << ": "
367*35238bceSAndroid Build Coastguard Worker                                << "offset = " << m_commands[cmdNdx].offset
368*35238bceSAndroid Build Coastguard Worker                                << ", numWorkGroups = " << m_commands[cmdNdx].numWorkGroups << TestLog::EndMessage;
369*35238bceSAndroid Build Coastguard Worker     }
370*35238bceSAndroid Build Coastguard Worker 
371*35238bceSAndroid Build Coastguard Worker     createResultBuffer(*resultBuffer);
372*35238bceSAndroid Build Coastguard Worker     createCommandBuffer(*cmdBuffer);
373*35238bceSAndroid Build Coastguard Worker 
374*35238bceSAndroid Build Coastguard Worker     gl.useProgram(program.getProgram());
375*35238bceSAndroid Build Coastguard Worker     gl.bindBuffer(GL_DISPATCH_INDIRECT_BUFFER, *cmdBuffer);
376*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.getError(), "State setup failed");
377*35238bceSAndroid Build Coastguard Worker 
378*35238bceSAndroid Build Coastguard Worker     {
379*35238bceSAndroid Build Coastguard Worker         const int resultBlockAlignedSize = getResultBlockAlignedSize(gl);
380*35238bceSAndroid Build Coastguard Worker         intptr_t curOffset               = 0;
381*35238bceSAndroid Build Coastguard Worker 
382*35238bceSAndroid Build Coastguard Worker         for (vector<DispatchCommand>::const_iterator cmdIter = m_commands.begin(); cmdIter != m_commands.end();
383*35238bceSAndroid Build Coastguard Worker              ++cmdIter)
384*35238bceSAndroid Build Coastguard Worker         {
385*35238bceSAndroid Build Coastguard Worker             gl.bindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, *resultBuffer, (glw::GLintptr)curOffset,
386*35238bceSAndroid Build Coastguard Worker                                resultBlockAlignedSize);
387*35238bceSAndroid Build Coastguard Worker             gl.dispatchComputeIndirect((glw::GLintptr)cmdIter->offset);
388*35238bceSAndroid Build Coastguard Worker 
389*35238bceSAndroid Build Coastguard Worker             curOffset += resultBlockAlignedSize;
390*35238bceSAndroid Build Coastguard Worker         }
391*35238bceSAndroid Build Coastguard Worker     }
392*35238bceSAndroid Build Coastguard Worker 
393*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.getError(), "glDispatchComputeIndirect() failed");
394*35238bceSAndroid Build Coastguard Worker 
395*35238bceSAndroid Build Coastguard Worker     if (verifyResultBuffer(*resultBuffer))
396*35238bceSAndroid Build Coastguard Worker         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
397*35238bceSAndroid Build Coastguard Worker     else
398*35238bceSAndroid Build Coastguard Worker         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid values in result buffer");
399*35238bceSAndroid Build Coastguard Worker 
400*35238bceSAndroid Build Coastguard Worker     return STOP;
401*35238bceSAndroid Build Coastguard Worker }
402*35238bceSAndroid Build Coastguard Worker 
403*35238bceSAndroid Build Coastguard Worker class SingleDispatchCase : public IndirectDispatchCase
404*35238bceSAndroid Build Coastguard Worker {
405*35238bceSAndroid Build Coastguard Worker public:
SingleDispatchCase(Context & context,const char * name,const char * description,GenBuffer genBuffer,uintptr_t bufferSize,uintptr_t offset,const UVec3 & workGroupSize,const UVec3 & numWorkGroups)406*35238bceSAndroid Build Coastguard Worker     SingleDispatchCase(Context &context, const char *name, const char *description, GenBuffer genBuffer,
407*35238bceSAndroid Build Coastguard Worker                        uintptr_t bufferSize, uintptr_t offset, const UVec3 &workGroupSize, const UVec3 &numWorkGroups)
408*35238bceSAndroid Build Coastguard Worker         : IndirectDispatchCase(context, name, description, genBuffer)
409*35238bceSAndroid Build Coastguard Worker     {
410*35238bceSAndroid Build Coastguard Worker         m_bufferSize    = bufferSize;
411*35238bceSAndroid Build Coastguard Worker         m_workGroupSize = workGroupSize;
412*35238bceSAndroid Build Coastguard Worker         m_commands.push_back(DispatchCommand(offset, numWorkGroups));
413*35238bceSAndroid Build Coastguard Worker     }
414*35238bceSAndroid Build Coastguard Worker };
415*35238bceSAndroid Build Coastguard Worker 
416*35238bceSAndroid Build Coastguard Worker class MultiDispatchCase : public IndirectDispatchCase
417*35238bceSAndroid Build Coastguard Worker {
418*35238bceSAndroid Build Coastguard Worker public:
MultiDispatchCase(Context & context,GenBuffer genBuffer)419*35238bceSAndroid Build Coastguard Worker     MultiDispatchCase(Context &context, GenBuffer genBuffer)
420*35238bceSAndroid Build Coastguard Worker         : IndirectDispatchCase(context, "multi_dispatch", "Dispatch multiple compute commands from single buffer",
421*35238bceSAndroid Build Coastguard Worker                                genBuffer)
422*35238bceSAndroid Build Coastguard Worker     {
423*35238bceSAndroid Build Coastguard Worker         m_bufferSize    = 1 << 10;
424*35238bceSAndroid Build Coastguard Worker         m_workGroupSize = UVec3(3, 1, 2);
425*35238bceSAndroid Build Coastguard Worker 
426*35238bceSAndroid Build Coastguard Worker         m_commands.push_back(DispatchCommand(0, UVec3(1, 1, 1)));
427*35238bceSAndroid Build Coastguard Worker         m_commands.push_back(DispatchCommand(INDIRECT_COMMAND_SIZE, UVec3(2, 1, 1)));
428*35238bceSAndroid Build Coastguard Worker         m_commands.push_back(DispatchCommand(104, UVec3(1, 3, 1)));
429*35238bceSAndroid Build Coastguard Worker         m_commands.push_back(DispatchCommand(40, UVec3(1, 1, 7)));
430*35238bceSAndroid Build Coastguard Worker         m_commands.push_back(DispatchCommand(52, UVec3(1, 1, 4)));
431*35238bceSAndroid Build Coastguard Worker     }
432*35238bceSAndroid Build Coastguard Worker };
433*35238bceSAndroid Build Coastguard Worker 
434*35238bceSAndroid Build Coastguard Worker class MultiDispatchReuseCommandCase : public IndirectDispatchCase
435*35238bceSAndroid Build Coastguard Worker {
436*35238bceSAndroid Build Coastguard Worker public:
MultiDispatchReuseCommandCase(Context & context,GenBuffer genBuffer)437*35238bceSAndroid Build Coastguard Worker     MultiDispatchReuseCommandCase(Context &context, GenBuffer genBuffer)
438*35238bceSAndroid Build Coastguard Worker         : IndirectDispatchCase(context, "multi_dispatch_reuse_command",
439*35238bceSAndroid Build Coastguard Worker                                "Dispatch multiple compute commands from single buffer", genBuffer)
440*35238bceSAndroid Build Coastguard Worker     {
441*35238bceSAndroid Build Coastguard Worker         m_bufferSize    = 1 << 10;
442*35238bceSAndroid Build Coastguard Worker         m_workGroupSize = UVec3(3, 1, 2);
443*35238bceSAndroid Build Coastguard Worker 
444*35238bceSAndroid Build Coastguard Worker         m_commands.push_back(DispatchCommand(0, UVec3(1, 1, 1)));
445*35238bceSAndroid Build Coastguard Worker         m_commands.push_back(DispatchCommand(0, UVec3(1, 1, 1)));
446*35238bceSAndroid Build Coastguard Worker         m_commands.push_back(DispatchCommand(0, UVec3(1, 1, 1)));
447*35238bceSAndroid Build Coastguard Worker         m_commands.push_back(DispatchCommand(104, UVec3(1, 3, 1)));
448*35238bceSAndroid Build Coastguard Worker         m_commands.push_back(DispatchCommand(104, UVec3(1, 3, 1)));
449*35238bceSAndroid Build Coastguard Worker         m_commands.push_back(DispatchCommand(52, UVec3(1, 1, 4)));
450*35238bceSAndroid Build Coastguard Worker         m_commands.push_back(DispatchCommand(52, UVec3(1, 1, 4)));
451*35238bceSAndroid Build Coastguard Worker     }
452*35238bceSAndroid Build Coastguard Worker };
453*35238bceSAndroid Build Coastguard Worker 
454*35238bceSAndroid Build Coastguard Worker } // namespace
455*35238bceSAndroid Build Coastguard Worker 
IndirectComputeDispatchTests(Context & context)456*35238bceSAndroid Build Coastguard Worker IndirectComputeDispatchTests::IndirectComputeDispatchTests(Context &context)
457*35238bceSAndroid Build Coastguard Worker     : TestCaseGroup(context, "indirect_dispatch", "Indirect dispatch tests")
458*35238bceSAndroid Build Coastguard Worker {
459*35238bceSAndroid Build Coastguard Worker }
460*35238bceSAndroid Build Coastguard Worker 
~IndirectComputeDispatchTests(void)461*35238bceSAndroid Build Coastguard Worker IndirectComputeDispatchTests::~IndirectComputeDispatchTests(void)
462*35238bceSAndroid Build Coastguard Worker {
463*35238bceSAndroid Build Coastguard Worker }
464*35238bceSAndroid Build Coastguard Worker 
init(void)465*35238bceSAndroid Build Coastguard Worker void IndirectComputeDispatchTests::init(void)
466*35238bceSAndroid Build Coastguard Worker {
467*35238bceSAndroid Build Coastguard Worker     static const struct
468*35238bceSAndroid Build Coastguard Worker     {
469*35238bceSAndroid Build Coastguard Worker         const char *name;
470*35238bceSAndroid Build Coastguard Worker         GenBuffer gen;
471*35238bceSAndroid Build Coastguard Worker     } s_genBuffer[] = {{"upload_buffer", GEN_BUFFER_UPLOAD}, {"gen_in_compute", GEN_BUFFER_COMPUTE}};
472*35238bceSAndroid Build Coastguard Worker 
473*35238bceSAndroid Build Coastguard Worker     static const struct
474*35238bceSAndroid Build Coastguard Worker     {
475*35238bceSAndroid Build Coastguard Worker         const char *name;
476*35238bceSAndroid Build Coastguard Worker         const char *description;
477*35238bceSAndroid Build Coastguard Worker         uintptr_t bufferSize;
478*35238bceSAndroid Build Coastguard Worker         uintptr_t offset;
479*35238bceSAndroid Build Coastguard Worker         UVec3 workGroupSize;
480*35238bceSAndroid Build Coastguard Worker         UVec3 numWorkGroups;
481*35238bceSAndroid Build Coastguard Worker     } s_singleDispatchCases[] = {
482*35238bceSAndroid Build Coastguard Worker         //    Name                                        Desc                                            BufferSize                    Offs            WorkGroupSize    NumWorkGroups
483*35238bceSAndroid Build Coastguard Worker         {"single_invocation", "Single invocation only from offset 0", INDIRECT_COMMAND_SIZE, 0, UVec3(1, 1, 1),
484*35238bceSAndroid Build Coastguard Worker          UVec3(1, 1, 1)},
485*35238bceSAndroid Build Coastguard Worker         {"multiple_groups", "Multiple groups dispatched from offset 0", INDIRECT_COMMAND_SIZE, 0, UVec3(1, 1, 1),
486*35238bceSAndroid Build Coastguard Worker          UVec3(2, 3, 5)},
487*35238bceSAndroid Build Coastguard Worker         {"multiple_groups_multiple_invocations", "Multiple groups of size 2x3x1 from offset 0", INDIRECT_COMMAND_SIZE,
488*35238bceSAndroid Build Coastguard Worker          0, UVec3(2, 3, 1), UVec3(1, 2, 3)},
489*35238bceSAndroid Build Coastguard Worker         {"small_offset", "Small offset", 16 + INDIRECT_COMMAND_SIZE, 16, UVec3(1, 1, 1), UVec3(1, 1, 1)},
490*35238bceSAndroid Build Coastguard Worker         {"large_offset", "Large offset", (2 << 20), (1 << 20) + 12, UVec3(1, 1, 1), UVec3(1, 1, 1)},
491*35238bceSAndroid Build Coastguard Worker         {"large_offset_multiple_invocations", "Large offset, multiple invocations", (2 << 20), (1 << 20) + 12,
492*35238bceSAndroid Build Coastguard Worker          UVec3(2, 3, 1), UVec3(1, 2, 3)},
493*35238bceSAndroid Build Coastguard Worker         {"empty_command", "Empty command", INDIRECT_COMMAND_SIZE, 0, UVec3(1, 1, 1), UVec3(0, 0, 0)},
494*35238bceSAndroid Build Coastguard Worker     };
495*35238bceSAndroid Build Coastguard Worker 
496*35238bceSAndroid Build Coastguard Worker     for (int genNdx = 0; genNdx < DE_LENGTH_OF_ARRAY(s_genBuffer); genNdx++)
497*35238bceSAndroid Build Coastguard Worker     {
498*35238bceSAndroid Build Coastguard Worker         const GenBuffer genBuf             = s_genBuffer[genNdx].gen;
499*35238bceSAndroid Build Coastguard Worker         tcu::TestCaseGroup *const genGroup = new tcu::TestCaseGroup(m_testCtx, s_genBuffer[genNdx].name, "");
500*35238bceSAndroid Build Coastguard Worker         addChild(genGroup);
501*35238bceSAndroid Build Coastguard Worker 
502*35238bceSAndroid Build Coastguard Worker         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_singleDispatchCases); ndx++)
503*35238bceSAndroid Build Coastguard Worker             genGroup->addChild(new SingleDispatchCase(
504*35238bceSAndroid Build Coastguard Worker                 m_context, s_singleDispatchCases[ndx].name, s_singleDispatchCases[ndx].description, genBuf,
505*35238bceSAndroid Build Coastguard Worker                 s_singleDispatchCases[ndx].bufferSize, s_singleDispatchCases[ndx].offset,
506*35238bceSAndroid Build Coastguard Worker                 s_singleDispatchCases[ndx].workGroupSize, s_singleDispatchCases[ndx].numWorkGroups));
507*35238bceSAndroid Build Coastguard Worker 
508*35238bceSAndroid Build Coastguard Worker         genGroup->addChild(new MultiDispatchCase(m_context, genBuf));
509*35238bceSAndroid Build Coastguard Worker         genGroup->addChild(new MultiDispatchReuseCommandCase(m_context, genBuf));
510*35238bceSAndroid Build Coastguard Worker     }
511*35238bceSAndroid Build Coastguard Worker }
512*35238bceSAndroid Build Coastguard Worker 
513*35238bceSAndroid Build Coastguard Worker } // namespace Functional
514*35238bceSAndroid Build Coastguard Worker } // namespace gles31
515*35238bceSAndroid Build Coastguard Worker } // namespace deqp
516