xref: /aosp_15_r20/external/deqp/modules/gles31/functional/es31fComputeShaderBuiltinVarTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.1 Module
3  * -------------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Compute Shader Built-in variable tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es31fComputeShaderBuiltinVarTests.hpp"
25 #include "gluShaderProgram.hpp"
26 #include "gluShaderUtil.hpp"
27 #include "gluRenderContext.hpp"
28 #include "gluObjectWrapper.hpp"
29 #include "gluProgramInterfaceQuery.hpp"
30 #include "tcuVector.hpp"
31 #include "tcuTestLog.hpp"
32 #include "tcuVectorUtil.hpp"
33 #include "deSharedPtr.hpp"
34 #include "deStringUtil.hpp"
35 #include "glwFunctions.hpp"
36 #include "glwEnums.hpp"
37 
38 #include <map>
39 
40 namespace deqp
41 {
42 namespace gles31
43 {
44 namespace Functional
45 {
46 
47 using std::map;
48 using std::string;
49 using std::vector;
50 using tcu::IVec3;
51 using tcu::TestLog;
52 using tcu::UVec3;
53 
54 using namespace glu;
55 
56 template <typename T, int Size>
57 struct LexicalCompareVec
58 {
operator ()deqp::gles31::Functional::LexicalCompareVec59     inline bool operator()(const tcu::Vector<T, Size> &a, const tcu::Vector<T, Size> &b) const
60     {
61         for (int ndx = 0; ndx < Size; ndx++)
62         {
63             if (a[ndx] < b[ndx])
64                 return true;
65             else if (a[ndx] > b[ndx])
66                 return false;
67         }
68         return false;
69     }
70 };
71 
72 typedef de::SharedPtr<glu::ShaderProgram> ShaderProgramSp;
73 typedef std::map<tcu::UVec3, ShaderProgramSp, LexicalCompareVec<uint32_t, 3>> LocalSizeProgramMap;
74 
75 class ComputeBuiltinVarCase : public TestCase
76 {
77 public:
78     ComputeBuiltinVarCase(Context &context, const char *name, const char *varName, DataType varType);
79     ~ComputeBuiltinVarCase(void);
80 
81     void init(void);
82     void deinit(void);
83     IterateResult iterate(void);
84 
85     virtual UVec3 computeReference(const UVec3 &numWorkGroups, const UVec3 &workGroupSize, const UVec3 &workGroupID,
86                                    const UVec3 &localInvocationID) const = 0;
87 
88 protected:
89     struct SubCase
90     {
91         UVec3 localSize;
92         UVec3 numWorkGroups;
93 
SubCasedeqp::gles31::Functional::ComputeBuiltinVarCase::SubCase94         SubCase(void)
95         {
96         }
SubCasedeqp::gles31::Functional::ComputeBuiltinVarCase::SubCase97         SubCase(const UVec3 &localSize_, const UVec3 &numWorkGroups_)
98             : localSize(localSize_)
99             , numWorkGroups(numWorkGroups_)
100         {
101         }
102     };
103 
104     vector<SubCase> m_subCases;
105 
106 private:
107     ComputeBuiltinVarCase(const ComputeBuiltinVarCase &other);
108     ComputeBuiltinVarCase &operator=(const ComputeBuiltinVarCase &other);
109 
110     uint32_t getProgram(const UVec3 &localSize);
111 
112     const string m_varName;
113     const DataType m_varType;
114 
115     LocalSizeProgramMap m_progMap;
116     int m_subCaseNdx;
117 };
118 
ComputeBuiltinVarCase(Context & context,const char * name,const char * varName,DataType varType)119 ComputeBuiltinVarCase::ComputeBuiltinVarCase(Context &context, const char *name, const char *varName, DataType varType)
120     : TestCase(context, name, varName)
121     , m_varName(varName)
122     , m_varType(varType)
123     , m_subCaseNdx(0)
124 {
125 }
126 
~ComputeBuiltinVarCase(void)127 ComputeBuiltinVarCase::~ComputeBuiltinVarCase(void)
128 {
129     ComputeBuiltinVarCase::deinit();
130 }
131 
init(void)132 void ComputeBuiltinVarCase::init(void)
133 {
134     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
135     m_subCaseNdx = 0;
136 }
137 
deinit(void)138 void ComputeBuiltinVarCase::deinit(void)
139 {
140     m_progMap.clear();
141 }
142 
genBuiltinVarSource(const string & varName,DataType varType,const UVec3 & localSize)143 static string genBuiltinVarSource(const string &varName, DataType varType, const UVec3 &localSize)
144 {
145     std::ostringstream src;
146 
147     src << "#version 310 es\n"
148         << "layout (local_size_x = " << localSize.x() << ", local_size_y = " << localSize.y()
149         << ", local_size_z = " << localSize.z() << ") in;\n"
150         << "uniform highp uvec2 u_stride;\n"
151         << "layout(binding = 0) buffer Output\n"
152         << "{\n"
153         << "    " << glu::getDataTypeName(varType) << " result[];\n"
154         << "} sb_out;\n"
155         << "\n"
156         << "void main (void)\n"
157         << "{\n"
158         << "    highp uint offset = u_stride.x*gl_GlobalInvocationID.z + u_stride.y*gl_GlobalInvocationID.y + "
159            "gl_GlobalInvocationID.x;\n"
160         << "    sb_out.result[offset] = " << varName << ";\n"
161         << "}\n";
162 
163     return src.str();
164 }
165 
getProgram(const UVec3 & localSize)166 uint32_t ComputeBuiltinVarCase::getProgram(const UVec3 &localSize)
167 {
168     LocalSizeProgramMap::const_iterator cachePos = m_progMap.find(localSize);
169     if (cachePos != m_progMap.end())
170         return cachePos->second->getProgram();
171     else
172     {
173         ShaderProgramSp program(
174             new ShaderProgram(m_context.getRenderContext(),
175                               ProgramSources() << ComputeSource(genBuiltinVarSource(m_varName, m_varType, localSize))));
176 
177         // Log all compiled programs.
178         m_testCtx.getLog() << *program;
179         if (!program->isOk())
180             throw tcu::TestError("Compile failed");
181 
182         m_progMap[localSize] = program;
183         return program->getProgram();
184     }
185 }
186 
readResultVec(const uint32_t * ptr,int numComps)187 static inline UVec3 readResultVec(const uint32_t *ptr, int numComps)
188 {
189     UVec3 res;
190     for (int ndx = 0; ndx < numComps; ndx++)
191         res[ndx] = ptr[ndx];
192     return res;
193 }
194 
compareComps(const UVec3 & a,const UVec3 & b,int numComps)195 static inline bool compareComps(const UVec3 &a, const UVec3 &b, int numComps)
196 {
197     DE_ASSERT(numComps == 1 || numComps == 3);
198     return numComps == 3 ? tcu::allEqual(a, b) : a.x() == b.x();
199 }
200 
201 struct LogComps
202 {
203     const UVec3 &v;
204     int numComps;
205 
LogCompsdeqp::gles31::Functional::LogComps206     LogComps(const UVec3 &v_, int numComps_) : v(v_), numComps(numComps_)
207     {
208     }
209 };
210 
operator <<(std::ostream & str,const LogComps & c)211 static inline std::ostream &operator<<(std::ostream &str, const LogComps &c)
212 {
213     DE_ASSERT(c.numComps == 1 || c.numComps == 3);
214     return c.numComps == 3 ? str << c.v : str << c.v.x();
215 }
216 
iterate(void)217 ComputeBuiltinVarCase::IterateResult ComputeBuiltinVarCase::iterate(void)
218 {
219     const tcu::ScopedLogSection section(m_testCtx.getLog(), string("Iteration") + de::toString(m_subCaseNdx),
220                                         string("Iteration ") + de::toString(m_subCaseNdx));
221     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
222     const SubCase &subCase   = m_subCases[m_subCaseNdx];
223     const uint32_t program   = getProgram(subCase.localSize);
224 
225     const tcu::UVec3 globalSize = subCase.localSize * subCase.numWorkGroups;
226     const tcu::UVec2 stride(globalSize[0] * globalSize[1], globalSize[0]);
227     const uint32_t numInvocations = subCase.localSize[0] * subCase.localSize[1] * subCase.localSize[2] *
228                                     subCase.numWorkGroups[0] * subCase.numWorkGroups[1] * subCase.numWorkGroups[2];
229 
230     const uint32_t outVarIndex = gl.getProgramResourceIndex(program, GL_BUFFER_VARIABLE, "Output.result");
231     const InterfaceVariableInfo outVarInfo =
232         getProgramInterfaceVariableInfo(gl, program, GL_BUFFER_VARIABLE, outVarIndex);
233     const uint32_t bufferSize = numInvocations * outVarInfo.arrayStride;
234     Buffer outputBuffer(m_context.getRenderContext());
235 
236     TCU_CHECK(outVarInfo.arraySize == 0); // Unsized variable.
237 
238     m_testCtx.getLog() << TestLog::Message << "Number of work groups = " << subCase.numWorkGroups << TestLog::EndMessage
239                        << TestLog::Message << "Work group size = " << subCase.localSize << TestLog::EndMessage;
240 
241     gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, *outputBuffer);
242     gl.bufferData(GL_SHADER_STORAGE_BUFFER, (glw::GLsizeiptr)bufferSize, DE_NULL, GL_STREAM_READ);
243     gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, *outputBuffer);
244     GLU_EXPECT_NO_ERROR(gl.getError(), "Buffer setup failed");
245 
246     gl.useProgram(program);
247     gl.uniform2uiv(gl.getUniformLocation(program, "u_stride"), 1, stride.getPtr());
248     GLU_EXPECT_NO_ERROR(gl.getError(), "Program setup failed");
249 
250     gl.dispatchCompute(subCase.numWorkGroups[0], subCase.numWorkGroups[1], subCase.numWorkGroups[2]);
251     GLU_EXPECT_NO_ERROR(gl.getError(), "glDispatchCompute() failed");
252 
253     {
254         const void *ptr        = gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, bufferSize, GL_MAP_READ_BIT);
255         int numFailed          = 0;
256         const int numScalars   = getDataTypeScalarSize(m_varType);
257         const int maxLogPrints = 10;
258 
259         GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() failed");
260         TCU_CHECK(ptr);
261 
262         for (uint32_t groupZ = 0; groupZ < subCase.numWorkGroups.z(); groupZ++)
263             for (uint32_t groupY = 0; groupY < subCase.numWorkGroups.y(); groupY++)
264                 for (uint32_t groupX = 0; groupX < subCase.numWorkGroups.x(); groupX++)
265                     for (uint32_t localZ = 0; localZ < subCase.localSize.z(); localZ++)
266                         for (uint32_t localY = 0; localY < subCase.localSize.y(); localY++)
267                             for (uint32_t localX = 0; localX < subCase.localSize.x(); localX++)
268                             {
269                                 const UVec3 refGroupID(groupX, groupY, groupZ);
270                                 const UVec3 refLocalID(localX, localY, localZ);
271                                 const UVec3 refGlobalID = refGroupID * subCase.localSize + refLocalID;
272                                 const uint32_t refOffset =
273                                     stride.x() * refGlobalID.z() + stride.y() * refGlobalID.y() + refGlobalID.x();
274                                 const UVec3 refValue =
275                                     computeReference(subCase.numWorkGroups, subCase.localSize, refGroupID, refLocalID);
276 
277                                 const uint32_t *resPtr =
278                                     (const uint32_t *)((const uint8_t *)ptr + refOffset * outVarInfo.arrayStride);
279                                 const UVec3 resValue = readResultVec(resPtr, numScalars);
280 
281                                 if (!compareComps(refValue, resValue, numScalars))
282                                 {
283                                     if (numFailed < maxLogPrints)
284                                         m_testCtx.getLog()
285                                             << TestLog::Message << "ERROR: comparison failed at offset " << refOffset
286                                             << ": expected " << LogComps(refValue, numScalars) << ", got "
287                                             << LogComps(resValue, numScalars) << TestLog::EndMessage;
288                                     else if (numFailed == maxLogPrints)
289                                         m_testCtx.getLog() << TestLog::Message << "..." << TestLog::EndMessage;
290 
291                                     numFailed += 1;
292                                 }
293                             }
294 
295         m_testCtx.getLog() << TestLog::Message << (numInvocations - numFailed) << " / " << numInvocations
296                            << " values passed" << TestLog::EndMessage;
297 
298         if (numFailed > 0)
299             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Comparison failed");
300 
301         gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
302     }
303 
304     m_subCaseNdx += 1;
305     return (m_subCaseNdx < (int)m_subCases.size() && m_testCtx.getTestResult() == QP_TEST_RESULT_PASS) ? CONTINUE :
306                                                                                                          STOP;
307 }
308 
309 // Test cases
310 
311 class NumWorkGroupsCase : public ComputeBuiltinVarCase
312 {
313 public:
NumWorkGroupsCase(Context & context)314     NumWorkGroupsCase(Context &context)
315         : ComputeBuiltinVarCase(context, "num_work_groups", "gl_NumWorkGroups", TYPE_UINT_VEC3)
316     {
317         m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(1, 1, 1)));
318         m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(52, 1, 1)));
319         m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(1, 39, 1)));
320         m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(1, 1, 78)));
321         m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(4, 7, 11)));
322         m_subCases.push_back(SubCase(UVec3(2, 3, 4), UVec3(4, 7, 11)));
323     }
324 
computeReference(const UVec3 & numWorkGroups,const UVec3 & workGroupSize,const UVec3 & workGroupID,const UVec3 & localInvocationID) const325     UVec3 computeReference(const UVec3 &numWorkGroups, const UVec3 &workGroupSize, const UVec3 &workGroupID,
326                            const UVec3 &localInvocationID) const
327     {
328         DE_UNREF(numWorkGroups);
329         DE_UNREF(workGroupSize);
330         DE_UNREF(workGroupID);
331         DE_UNREF(localInvocationID);
332         return numWorkGroups;
333     }
334 };
335 
336 class WorkGroupSizeCase : public ComputeBuiltinVarCase
337 {
338 public:
WorkGroupSizeCase(Context & context)339     WorkGroupSizeCase(Context &context)
340         : ComputeBuiltinVarCase(context, "work_group_size", "gl_WorkGroupSize", TYPE_UINT_VEC3)
341     {
342         m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(1, 1, 1)));
343         m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(2, 7, 3)));
344         m_subCases.push_back(SubCase(UVec3(2, 1, 1), UVec3(1, 1, 1)));
345         m_subCases.push_back(SubCase(UVec3(2, 1, 1), UVec3(1, 3, 5)));
346         m_subCases.push_back(SubCase(UVec3(1, 3, 1), UVec3(1, 1, 1)));
347         m_subCases.push_back(SubCase(UVec3(1, 1, 7), UVec3(1, 1, 1)));
348         m_subCases.push_back(SubCase(UVec3(1, 1, 7), UVec3(3, 3, 1)));
349         m_subCases.push_back(SubCase(UVec3(10, 3, 4), UVec3(1, 1, 1)));
350         m_subCases.push_back(SubCase(UVec3(10, 3, 4), UVec3(3, 1, 2)));
351     }
352 
computeReference(const UVec3 & numWorkGroups,const UVec3 & workGroupSize,const UVec3 & workGroupID,const UVec3 & localInvocationID) const353     UVec3 computeReference(const UVec3 &numWorkGroups, const UVec3 &workGroupSize, const UVec3 &workGroupID,
354                            const UVec3 &localInvocationID) const
355     {
356         DE_UNREF(numWorkGroups);
357         DE_UNREF(workGroupID);
358         DE_UNREF(localInvocationID);
359         return workGroupSize;
360     }
361 };
362 
363 class WorkGroupIDCase : public ComputeBuiltinVarCase
364 {
365 public:
WorkGroupIDCase(Context & context)366     WorkGroupIDCase(Context &context)
367         : ComputeBuiltinVarCase(context, "work_group_id", "gl_WorkGroupID", TYPE_UINT_VEC3)
368     {
369         m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(1, 1, 1)));
370         m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(52, 1, 1)));
371         m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(1, 39, 1)));
372         m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(1, 1, 78)));
373         m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(4, 7, 11)));
374         m_subCases.push_back(SubCase(UVec3(2, 3, 4), UVec3(4, 7, 11)));
375     }
376 
computeReference(const UVec3 & numWorkGroups,const UVec3 & workGroupSize,const UVec3 & workGroupID,const UVec3 & localInvocationID) const377     UVec3 computeReference(const UVec3 &numWorkGroups, const UVec3 &workGroupSize, const UVec3 &workGroupID,
378                            const UVec3 &localInvocationID) const
379     {
380         DE_UNREF(numWorkGroups);
381         DE_UNREF(workGroupSize);
382         DE_UNREF(localInvocationID);
383         return workGroupID;
384     }
385 };
386 
387 class LocalInvocationIDCase : public ComputeBuiltinVarCase
388 {
389 public:
LocalInvocationIDCase(Context & context)390     LocalInvocationIDCase(Context &context)
391         : ComputeBuiltinVarCase(context, "local_invocation_id", "gl_LocalInvocationID", TYPE_UINT_VEC3)
392     {
393         m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(1, 1, 1)));
394         m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(2, 7, 3)));
395         m_subCases.push_back(SubCase(UVec3(2, 1, 1), UVec3(1, 1, 1)));
396         m_subCases.push_back(SubCase(UVec3(2, 1, 1), UVec3(1, 3, 5)));
397         m_subCases.push_back(SubCase(UVec3(1, 3, 1), UVec3(1, 1, 1)));
398         m_subCases.push_back(SubCase(UVec3(1, 1, 7), UVec3(1, 1, 1)));
399         m_subCases.push_back(SubCase(UVec3(1, 1, 7), UVec3(3, 3, 1)));
400         m_subCases.push_back(SubCase(UVec3(10, 3, 4), UVec3(1, 1, 1)));
401         m_subCases.push_back(SubCase(UVec3(10, 3, 4), UVec3(3, 1, 2)));
402     }
403 
computeReference(const UVec3 & numWorkGroups,const UVec3 & workGroupSize,const UVec3 & workGroupID,const UVec3 & localInvocationID) const404     UVec3 computeReference(const UVec3 &numWorkGroups, const UVec3 &workGroupSize, const UVec3 &workGroupID,
405                            const UVec3 &localInvocationID) const
406     {
407         DE_UNREF(numWorkGroups);
408         DE_UNREF(workGroupSize);
409         DE_UNREF(workGroupID);
410         return localInvocationID;
411     }
412 };
413 
414 class GlobalInvocationIDCase : public ComputeBuiltinVarCase
415 {
416 public:
GlobalInvocationIDCase(Context & context)417     GlobalInvocationIDCase(Context &context)
418         : ComputeBuiltinVarCase(context, "global_invocation_id", "gl_GlobalInvocationID", TYPE_UINT_VEC3)
419     {
420         m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(1, 1, 1)));
421         m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(52, 1, 1)));
422         m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(1, 39, 1)));
423         m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(1, 1, 78)));
424         m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(4, 7, 11)));
425         m_subCases.push_back(SubCase(UVec3(2, 3, 4), UVec3(4, 7, 11)));
426         m_subCases.push_back(SubCase(UVec3(10, 3, 4), UVec3(1, 1, 1)));
427         m_subCases.push_back(SubCase(UVec3(10, 3, 4), UVec3(3, 1, 2)));
428     }
429 
computeReference(const UVec3 & numWorkGroups,const UVec3 & workGroupSize,const UVec3 & workGroupID,const UVec3 & localInvocationID) const430     UVec3 computeReference(const UVec3 &numWorkGroups, const UVec3 &workGroupSize, const UVec3 &workGroupID,
431                            const UVec3 &localInvocationID) const
432     {
433         DE_UNREF(numWorkGroups);
434         return workGroupID * workGroupSize + localInvocationID;
435     }
436 };
437 
438 class LocalInvocationIndexCase : public ComputeBuiltinVarCase
439 {
440 public:
LocalInvocationIndexCase(Context & context)441     LocalInvocationIndexCase(Context &context)
442         : ComputeBuiltinVarCase(context, "local_invocation_index", "gl_LocalInvocationIndex", TYPE_UINT)
443     {
444         m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(1, 1, 1)));
445         m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(1, 39, 1)));
446         m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(4, 7, 11)));
447         m_subCases.push_back(SubCase(UVec3(2, 3, 4), UVec3(4, 7, 11)));
448         m_subCases.push_back(SubCase(UVec3(10, 3, 4), UVec3(1, 1, 1)));
449         m_subCases.push_back(SubCase(UVec3(10, 3, 4), UVec3(3, 1, 2)));
450     }
451 
computeReference(const UVec3 & numWorkGroups,const UVec3 & workGroupSize,const UVec3 & workGroupID,const UVec3 & localInvocationID) const452     UVec3 computeReference(const UVec3 &numWorkGroups, const UVec3 &workGroupSize, const UVec3 &workGroupID,
453                            const UVec3 &localInvocationID) const
454     {
455         DE_UNREF(workGroupID);
456         DE_UNREF(numWorkGroups);
457         return UVec3(localInvocationID.z() * workGroupSize.x() * workGroupSize.y() +
458                          localInvocationID.y() * workGroupSize.x() + localInvocationID.x(),
459                      0, 0);
460     }
461 };
462 
ComputeShaderBuiltinVarTests(Context & context)463 ComputeShaderBuiltinVarTests::ComputeShaderBuiltinVarTests(Context &context)
464     : TestCaseGroup(context, "compute", "Compute Shader Builtin Variables")
465 {
466 }
467 
~ComputeShaderBuiltinVarTests(void)468 ComputeShaderBuiltinVarTests::~ComputeShaderBuiltinVarTests(void)
469 {
470 }
471 
init(void)472 void ComputeShaderBuiltinVarTests::init(void)
473 {
474     addChild(new NumWorkGroupsCase(m_context));
475     addChild(new WorkGroupSizeCase(m_context));
476     addChild(new WorkGroupIDCase(m_context));
477     addChild(new LocalInvocationIDCase(m_context));
478     addChild(new GlobalInvocationIDCase(m_context));
479     addChild(new LocalInvocationIndexCase(m_context));
480 }
481 
482 } // namespace Functional
483 } // namespace gles31
484 } // namespace deqp
485