1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2015 Mobica Ltd.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and/or associated documentation files (the
9 * "Materials"), to deal in the Materials without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sublicense, and/or sell copies of the Materials, and to
12 * permit persons to whom the Materials are furnished to do so, subject to
13 * the following conditions:
15 * The above copyright notice(s) and this permission notice shall be included
16 * in all copies or substantial portions of the Materials.
18 * The Materials are Confidential Information as defined by the
19 * Khronos Membership Agreement until designated non-confidential by Khronos,
20 * at which point this condition clause shall be removed.
22 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
26 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28 * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
32 * \brief Compute Shader Built-in variable tests.
33 *//*--------------------------------------------------------------------*/
35 #include "vktComputeShaderBuiltinVarTests.hpp"
36 #include "vktTestCaseUtil.hpp"
37 #include "vktComputeTestsUtil.hpp"
40 #include "vkPlatform.hpp"
42 #include "vkPrograms.hpp"
43 #include "vkStrUtil.hpp"
44 #include "vkRefUtil.hpp"
45 #include "vkQueryUtil.hpp"
46 #include "vkMemUtil.hpp"
47 #include "vkDeviceUtil.hpp"
48 #include "vkTypeUtil.hpp"
49 #include "vkBuilderUtil.hpp"
51 #include "tcuTestLog.hpp"
52 #include "tcuFormatUtil.hpp"
53 #include "tcuVectorUtil.hpp"
55 #include "gluShaderUtil.hpp"
57 #include "deUniquePtr.hpp"
58 #include "deSharedPtr.hpp"
79 class ComputeBuiltinVarInstance;
80 class ComputeBuiltinVarCase;
82 static const string s_prefixProgramName ="compute_";
84 static inline bool compareNumComponents (const UVec3& a, const UVec3& b,const int numComps)
86 DE_ASSERT(numComps == 1 || numComps == 3);
87 return numComps == 3 ? tcu::allEqual(a, b) : a.x() == b.x();
90 static inline UVec3 readResultVec (const deUint32* ptr, const int numComps)
93 for (int ndx = 0; ndx < numComps; ndx++)
103 LogComps (const UVec3 &v_, int numComps_) : v(v_), numComps(numComps_) {}
106 static inline std::ostream& operator<< (std::ostream& str, const LogComps& c)
108 DE_ASSERT(c.numComps == 1 || c.numComps == 3);
109 return c.numComps == 3 ? str << c.v : str << c.v.x();
115 // Use getters instead of public const members, because SubCase must be assignable
116 // in order to be stored in a vector.
118 const UVec3& localSize (void) const { return m_localSize; }
119 const UVec3& numWorkGroups (void) const { return m_numWorkGroups; }
122 SubCase (const UVec3& localSize_, const UVec3& numWorkGroups_)
123 : m_localSize (localSize_)
124 , m_numWorkGroups (numWorkGroups_) {}
128 UVec3 m_numWorkGroups;
132 class ComputeBuiltinVarInstance : public vkt::TestInstance
135 ComputeBuiltinVarInstance (Context& context,
136 const vector<SubCase>& subCases,
137 const glu::DataType varType,
138 const ComputeBuiltinVarCase* builtinVarCase);
140 virtual tcu::TestStatus iterate (void);
143 const VkDevice m_device;
144 const DeviceInterface& m_vki;
145 const VkQueue m_queue;
146 const deUint32 m_queueFamilyIndex;
147 vector<SubCase> m_subCases;
148 const ComputeBuiltinVarCase* m_builtin_var_case;
150 const glu::DataType m_varType;
153 class ComputeBuiltinVarCase : public vkt::TestCase
156 ComputeBuiltinVarCase (tcu::TestContext& context, const char* name, const char* varName, glu::DataType varType);
157 ~ComputeBuiltinVarCase (void);
159 TestInstance* createInstance (Context& context) const
161 return new ComputeBuiltinVarInstance(context, m_subCases, m_varType, this);
164 virtual void initPrograms (SourceCollections& programCollection) const;
165 virtual UVec3 computeReference (const UVec3& numWorkGroups, const UVec3& workGroupSize, const UVec3& workGroupID, const UVec3& localInvocationID) const = 0;
168 string genBuiltinVarSource (const string& varName, glu::DataType varType, const UVec3& localSize) const;
169 vector<SubCase> m_subCases;
172 deUint32 getProgram (const tcu::UVec3& localSize);
174 const string m_varName;
175 const glu::DataType m_varType;
178 ComputeBuiltinVarCase (const ComputeBuiltinVarCase& other);
179 ComputeBuiltinVarCase& operator= (const ComputeBuiltinVarCase& other);
182 ComputeBuiltinVarCase::ComputeBuiltinVarCase (tcu::TestContext& context, const char* name, const char* varName, glu::DataType varType)
183 : TestCase (context, name, varName)
184 , m_varName (varName)
185 , m_varType (varType)
190 ComputeBuiltinVarCase::~ComputeBuiltinVarCase (void)
192 ComputeBuiltinVarCase::deinit();
195 void ComputeBuiltinVarCase::initPrograms (SourceCollections& programCollection) const
197 for (std::size_t i = 0; i < m_subCases.size(); i++)
199 const SubCase& subCase = m_subCases[i];
200 std::ostringstream name;
201 name << s_prefixProgramName << i;
202 programCollection.glslSources.add(name.str()) << glu::ComputeSource(genBuiltinVarSource(m_varName, m_varType, subCase.localSize()).c_str());
206 string ComputeBuiltinVarCase::genBuiltinVarSource (const string& varName, glu::DataType varType, const UVec3& localSize) const
208 std::ostringstream src;
210 src << "#version 310 es\n"
211 << "layout (local_size_x = " << localSize.x() << ", local_size_y = " << localSize.y() << ", local_size_z = " << localSize.z() << ") in;\n"
212 << "layout(set = 0, binding = 0) uniform Stride\n"
214 << " uvec2 u_stride;\n"
216 << "layout(set = 0, binding = 1, std430) buffer Output\n"
218 << " " << glu::getDataTypeName(varType) << " result[];\n"
221 << "void main (void)\n"
223 << " highp uint offset = stride.u_stride.x*gl_GlobalInvocationID.z + stride.u_stride.y*gl_GlobalInvocationID.y + gl_GlobalInvocationID.x;\n"
224 << " sb_out.result[offset] = " << varName << ";\n"
230 class NumWorkGroupsCase : public ComputeBuiltinVarCase
233 NumWorkGroupsCase (tcu::TestContext& context)
234 : ComputeBuiltinVarCase(context, "num_work_groups", "gl_NumWorkGroups", glu::TYPE_UINT_VEC3)
236 m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(1, 1, 1)));
237 m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(52, 1, 1)));
238 m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(1, 39, 1)));
239 m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(1, 1, 78)));
240 m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(4, 7, 11)));
241 m_subCases.push_back(SubCase(UVec3(2, 3, 4), UVec3(4, 7, 11)));
244 UVec3 computeReference (const UVec3& numWorkGroups, const UVec3& workGroupSize, const UVec3& workGroupID, const UVec3& localInvocationID) const
246 DE_UNREF(numWorkGroups);
247 DE_UNREF(workGroupSize);
248 DE_UNREF(workGroupID);
249 DE_UNREF(localInvocationID);
250 return numWorkGroups;
254 class WorkGroupSizeCase : public ComputeBuiltinVarCase
257 WorkGroupSizeCase (tcu::TestContext& context)
258 : ComputeBuiltinVarCase(context, "work_group_size", "gl_WorkGroupSize", glu::TYPE_UINT_VEC3)
260 m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(1, 1, 1)));
261 m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(2, 7, 3)));
262 m_subCases.push_back(SubCase(UVec3(2, 1, 1), UVec3(1, 1, 1)));
263 m_subCases.push_back(SubCase(UVec3(2, 1, 1), UVec3(1, 3, 5)));
264 m_subCases.push_back(SubCase(UVec3(1, 3, 1), UVec3(1, 1, 1)));
265 m_subCases.push_back(SubCase(UVec3(1, 1, 7), UVec3(1, 1, 1)));
266 m_subCases.push_back(SubCase(UVec3(1, 1, 7), UVec3(3, 3, 1)));
267 m_subCases.push_back(SubCase(UVec3(10, 3, 4), UVec3(1, 1, 1)));
268 m_subCases.push_back(SubCase(UVec3(10, 3, 4), UVec3(3, 1, 2)));
271 UVec3 computeReference (const UVec3& numWorkGroups, const UVec3& workGroupSize, const UVec3& workGroupID, const UVec3& localInvocationID) const
273 DE_UNREF(numWorkGroups);
274 DE_UNREF(workGroupID);
275 DE_UNREF(localInvocationID);
276 return workGroupSize;
280 //-----------------------------------------------------------------------
281 class WorkGroupIDCase : public ComputeBuiltinVarCase
284 WorkGroupIDCase (tcu::TestContext& context)
285 : ComputeBuiltinVarCase(context, "work_group_id", "gl_WorkGroupID", glu::TYPE_UINT_VEC3)
287 m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(1, 1, 1)));
288 m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(52, 1, 1)));
289 m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(1, 39, 1)));
290 m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(1, 1, 78)));
291 m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(4, 7, 11)));
292 m_subCases.push_back(SubCase(UVec3(2, 3, 4), UVec3(4, 7, 11)));
295 UVec3 computeReference (const UVec3& numWorkGroups, const UVec3& workGroupSize, const UVec3& workGroupID, const UVec3& localInvocationID) const
297 DE_UNREF(numWorkGroups);
298 DE_UNREF(workGroupSize);
299 DE_UNREF(localInvocationID);
304 class LocalInvocationIDCase : public ComputeBuiltinVarCase
307 LocalInvocationIDCase (tcu::TestContext& context)
308 : ComputeBuiltinVarCase(context, "local_invocation_id", "gl_LocalInvocationID", glu::TYPE_UINT_VEC3)
310 m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(1, 1, 1)));
311 m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(2, 7, 3)));
312 m_subCases.push_back(SubCase(UVec3(2, 1, 1), UVec3(1, 1, 1)));
313 m_subCases.push_back(SubCase(UVec3(2, 1, 1), UVec3(1, 3, 5)));
314 m_subCases.push_back(SubCase(UVec3(1, 3, 1), UVec3(1, 1, 1)));
315 m_subCases.push_back(SubCase(UVec3(1, 1, 7), UVec3(1, 1, 1)));
316 m_subCases.push_back(SubCase(UVec3(1, 1, 7), UVec3(3, 3, 1)));
317 m_subCases.push_back(SubCase(UVec3(10, 3, 4), UVec3(1, 1, 1)));
318 m_subCases.push_back(SubCase(UVec3(10, 3, 4), UVec3(3, 1, 2)));
321 UVec3 computeReference (const UVec3& numWorkGroups, const UVec3& workGroupSize, const UVec3& workGroupID, const UVec3& localInvocationID) const
323 DE_UNREF(numWorkGroups);
324 DE_UNREF(workGroupSize);
325 DE_UNREF(workGroupID);
326 return localInvocationID;
330 class GlobalInvocationIDCase : public ComputeBuiltinVarCase
333 GlobalInvocationIDCase (tcu::TestContext& context)
334 : ComputeBuiltinVarCase(context, "global_invocation_id", "gl_GlobalInvocationID", glu::TYPE_UINT_VEC3)
336 m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(1, 1, 1)));
337 m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(52, 1, 1)));
338 m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(1, 39, 1)));
339 m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(1, 1, 78)));
340 m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(4, 7, 11)));
341 m_subCases.push_back(SubCase(UVec3(2, 3, 4), UVec3(4, 7, 11)));
342 m_subCases.push_back(SubCase(UVec3(10, 3, 4), UVec3(1, 1, 1)));
343 m_subCases.push_back(SubCase(UVec3(10, 3, 4), UVec3(3, 1, 2)));
346 UVec3 computeReference (const UVec3& numWorkGroups, const UVec3& workGroupSize, const UVec3& workGroupID, const UVec3& localInvocationID) const
348 DE_UNREF(numWorkGroups);
349 return workGroupID * workGroupSize + localInvocationID;
353 class LocalInvocationIndexCase : public ComputeBuiltinVarCase
356 LocalInvocationIndexCase (tcu::TestContext& context)
357 : ComputeBuiltinVarCase(context, "local_invocation_index", "gl_LocalInvocationIndex", glu::TYPE_UINT)
359 m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(1, 1, 1)));
360 m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(1, 39, 1)));
361 m_subCases.push_back(SubCase(UVec3(1, 1, 1), UVec3(4, 7, 11)));
362 m_subCases.push_back(SubCase(UVec3(2, 3, 4), UVec3(4, 7, 11)));
363 m_subCases.push_back(SubCase(UVec3(10, 3, 4), UVec3(1, 1, 1)));
364 m_subCases.push_back(SubCase(UVec3(10, 3, 4), UVec3(3, 1, 2)));
367 UVec3 computeReference (const UVec3& numWorkGroups, const UVec3& workGroupSize, const UVec3& workGroupID, const UVec3& localInvocationID) const
369 DE_UNREF(workGroupID);
370 DE_UNREF(numWorkGroups);
371 return UVec3(localInvocationID.z()*workGroupSize.x()*workGroupSize.y() + localInvocationID.y()*workGroupSize.x() + localInvocationID.x(), 0, 0);
375 ComputeBuiltinVarInstance::ComputeBuiltinVarInstance (Context& context,
376 const vector<SubCase>& subCases,
377 const glu::DataType varType,
378 const ComputeBuiltinVarCase* builtinVarCase)
379 : vkt::TestInstance (context)
380 , m_device (m_context.getDevice())
381 , m_vki (m_context.getDeviceInterface())
382 , m_queue (context.getUniversalQueue())
383 , m_queueFamilyIndex (context.getUniversalQueueFamilyIndex())
384 , m_subCases (subCases)
385 , m_builtin_var_case (builtinVarCase)
387 , m_varType (varType)
391 tcu::TestStatus ComputeBuiltinVarInstance::iterate (void)
393 std::ostringstream program_name;
394 program_name << s_prefixProgramName << m_subCaseNdx;
396 const SubCase& subCase = m_subCases[m_subCaseNdx];
397 const tcu::UVec3 globalSize = subCase.localSize()*subCase.numWorkGroups();
398 const tcu::UVec2 stride (globalSize[0] * globalSize[1], globalSize[0]);
399 const deUint32 sizeOfUniformBuffer = sizeof(stride);
400 const int numScalars = glu::getDataTypeScalarSize(m_varType);
401 const deUint32 numInvocations = subCase.localSize()[0] * subCase.localSize()[1] * subCase.localSize()[2] * subCase.numWorkGroups()[0] * subCase.numWorkGroups()[1] * subCase.numWorkGroups()[2];
403 deUint32 resultBufferStride = 0;
407 resultBufferStride = sizeof(deUint32);
409 case glu::TYPE_UINT_VEC2:
410 resultBufferStride = sizeof(tcu::UVec2);
412 case glu::TYPE_UINT_VEC3:
413 case glu::TYPE_UINT_VEC4:
414 resultBufferStride = sizeof(tcu::UVec4);
417 DE_ASSERT("Illegal data type");
420 const deUint32 resultBufferSize = numInvocations * resultBufferStride;
422 // Create result buffer
423 Buffer uniformBuffer(m_vki, m_device, m_context.getDefaultAllocator(), makeBufferCreateInfo(sizeOfUniformBuffer, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT), MemoryRequirement::HostVisible);
424 Buffer resultBuffer(m_vki, m_device, m_context.getDefaultAllocator(), makeBufferCreateInfo(resultBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), MemoryRequirement::HostVisible);
427 const Allocation& alloc = uniformBuffer.getAllocation();
428 memcpy(alloc.getHostPtr(), &stride, sizeOfUniformBuffer);
429 flushMappedMemoryRange(m_vki, m_device, alloc.getMemory(), alloc.getOffset(), sizeOfUniformBuffer);
432 // Create descriptorSetLayout
433 const Unique<VkDescriptorSetLayout> descriptorSetLayout(
434 DescriptorSetLayoutBuilder()
435 .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
436 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
437 .build(m_vki, m_device));
439 const Unique<VkShaderModule> shaderModule(createShaderModule(m_vki, m_device, m_context.getBinaryCollection().get(program_name.str()), 0u));
440 const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(m_vki, m_device, *descriptorSetLayout));
441 const Unique<VkPipeline> pipeline(makeComputePipeline(m_vki, m_device, *pipelineLayout, *shaderModule));
443 const Unique<VkDescriptorPool> descriptorPool(
444 DescriptorPoolBuilder()
445 .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
446 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
447 .build(m_vki, m_device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
449 const VkBufferMemoryBarrier bufferBarrier = makeBufferMemoryBarrier(
450 VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *resultBuffer, 0ull, resultBufferSize);
452 const void* const postBarrier[] = { &bufferBarrier };
454 const Unique<VkCommandPool> cmdPool(makeCommandPool(m_vki, m_device, m_queueFamilyIndex));
455 const Unique<VkCommandBuffer> cmdBuffer(makeCommandBuffer(m_vki, m_device, *cmdPool));
457 // Start recording commands
458 beginCommandBuffer(m_vki, *cmdBuffer);
460 m_vki.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
462 // Create descriptor set
463 const Unique<VkDescriptorSet> descriptorSet(makeDescriptorSet(m_vki, m_device, *descriptorPool, *descriptorSetLayout));
465 const VkDescriptorBufferInfo resultDescriptorInfo = makeDescriptorBufferInfo(*resultBuffer, 0ull, resultBufferSize);
466 const VkDescriptorBufferInfo uniformDescriptorInfo = makeDescriptorBufferInfo(*uniformBuffer, 0ull, sizeOfUniformBuffer);
468 DescriptorSetUpdateBuilder()
469 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &uniformDescriptorInfo)
470 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultDescriptorInfo)
471 .update(m_vki, m_device);
473 m_vki.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
475 // Dispatch indirect compute command
476 m_vki.cmdDispatch(*cmdBuffer, subCase.numWorkGroups()[0], subCase.numWorkGroups()[1], subCase.numWorkGroups()[2]);
478 m_vki.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, VK_FALSE, 1, postBarrier);
480 // End recording commands
481 endCommandBuffer(m_vki, *cmdBuffer);
483 // Wait for command buffer execution finish
484 submitCommandsAndWait(m_vki, m_device, m_queue, *cmdBuffer);
486 const Allocation& resultAlloc = resultBuffer.getAllocation();
487 invalidateMappedMemoryRange(m_vki, m_device, resultAlloc.getMemory(), resultAlloc.getOffset(), resultBufferSize);
489 const deUint8* ptr = reinterpret_cast<deUint8*>(resultAlloc.getHostPtr());
492 const int maxLogPrints = 10;
494 tcu::TestContext& testCtx = m_context.getTestContext();
496 for (deUint32 groupZ = 0; groupZ < subCase.numWorkGroups().z(); groupZ++)
497 for (deUint32 groupY = 0; groupY < subCase.numWorkGroups().y(); groupY++)
498 for (deUint32 groupX = 0; groupX < subCase.numWorkGroups().x(); groupX++)
499 for (deUint32 localZ = 0; localZ < subCase.localSize().z(); localZ++)
500 for (deUint32 localY = 0; localY < subCase.localSize().y(); localY++)
501 for (deUint32 localX = 0; localX < subCase.localSize().x(); localX++)
503 const UVec3 refGroupID(groupX, groupY, groupZ);
504 const UVec3 refLocalID(localX, localY, localZ);
505 const UVec3 refGlobalID = refGroupID * subCase.localSize() + refLocalID;
507 const deUint32 refOffset = stride.x()*refGlobalID.z() + stride.y()*refGlobalID.y() + refGlobalID.x();
509 const UVec3 refValue = m_builtin_var_case->computeReference(subCase.numWorkGroups(), subCase.localSize(), refGroupID, refLocalID);
511 const deUint32* resPtr = (const deUint32*)(ptr + refOffset * resultBufferStride);
512 const UVec3 resValue = readResultVec(resPtr, numScalars);
514 if (!compareNumComponents(refValue, resValue, numScalars))
516 if (numFailed < maxLogPrints)
519 << "ERROR: comparison failed at offset " << refOffset
520 << ": expected " << LogComps(refValue, numScalars)
521 << ", got " << LogComps(resValue, numScalars)
522 << TestLog::EndMessage;
523 else if (numFailed == maxLogPrints)
524 testCtx.getLog() << TestLog::Message << "..." << TestLog::EndMessage;
530 testCtx.getLog() << TestLog::Message << (numInvocations - numFailed) << " / " << numInvocations << " values passed" << TestLog::EndMessage;
533 return tcu::TestStatus::fail("Comparison failed");
536 return (m_subCaseNdx < (int)m_subCases.size()) ? tcu::TestStatus::incomplete() :tcu::TestStatus::pass("Comparison succeeded");
539 class ComputeShaderBuiltinVarTests : public tcu::TestCaseGroup
542 ComputeShaderBuiltinVarTests (tcu::TestContext& context);
547 ComputeShaderBuiltinVarTests (const ComputeShaderBuiltinVarTests& other);
548 ComputeShaderBuiltinVarTests& operator= (const ComputeShaderBuiltinVarTests& other);
551 ComputeShaderBuiltinVarTests::ComputeShaderBuiltinVarTests (tcu::TestContext& context)
552 : TestCaseGroup(context, "builtin_var", "Shader builtin var tests")
556 void ComputeShaderBuiltinVarTests::init (void)
558 addChild(new NumWorkGroupsCase(this->getTestContext()));
559 addChild(new WorkGroupSizeCase(this->getTestContext()));
560 addChild(new WorkGroupIDCase(this->getTestContext()));
561 addChild(new LocalInvocationIDCase(this->getTestContext()));
562 addChild(new GlobalInvocationIDCase(this->getTestContext()));
563 addChild(new LocalInvocationIndexCase(this->getTestContext()));
568 tcu::TestCaseGroup* createComputeShaderBuiltinVarTests (tcu::TestContext& testCtx)
570 return new ComputeShaderBuiltinVarTests(testCtx);