Merge branch 'jekstrand_renderpass_transfer_bit_fix' into 'master'
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / compute / vktComputeShaderBuiltinVarTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 Mobica Ltd.
6  *
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:
14  *
15  * The above copyright notice(s) and this permission notice shall be included
16  * in all copies or substantial portions of the Materials.
17  *
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.
21  *
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.
29  *
30  *//*!
31  * \file
32  * \brief Compute Shader Built-in variable tests.
33  *//*--------------------------------------------------------------------*/
34
35 #include "vktComputeShaderBuiltinVarTests.hpp"
36 #include "vktTestCaseUtil.hpp"
37 #include "vktComputeTestsUtil.hpp"
38
39 #include "vkDefs.hpp"
40 #include "vkPlatform.hpp"
41 #include "vkRef.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"
50
51 #include "tcuTestLog.hpp"
52 #include "tcuFormatUtil.hpp"
53 #include "tcuVectorUtil.hpp"
54
55 #include "gluShaderUtil.hpp"
56
57 #include "deUniquePtr.hpp"
58 #include "deSharedPtr.hpp"
59
60 #include <map>
61 #include <string>
62 #include <vector>
63
64 namespace vkt
65 {
66 namespace compute
67 {
68 namespace
69 {
70
71 using namespace vk;
72 using std::string;
73 using std::vector;
74 using std::map;
75 using tcu::TestLog;
76 using tcu::UVec3;
77 using tcu::IVec3;
78
79 class ComputeBuiltinVarInstance;
80 class ComputeBuiltinVarCase;
81
82 static const string s_prefixProgramName ="compute_";
83
84 static inline bool compareNumComponents (const UVec3& a, const UVec3& b,const int numComps)
85 {
86         DE_ASSERT(numComps == 1 || numComps == 3);
87         return numComps == 3 ? tcu::allEqual(a, b) : a.x() == b.x();
88 }
89
90 static inline UVec3 readResultVec (const deUint32* ptr, const int numComps)
91 {
92         UVec3 res;
93         for (int ndx = 0; ndx < numComps; ndx++)
94                 res[ndx] = ptr[ndx];
95         return res;
96 }
97
98 struct LogComps
99 {
100         const UVec3&    v;
101         int                             numComps;
102
103                                         LogComps        (const UVec3 &v_, int numComps_) : v(v_), numComps(numComps_) {}
104 };
105
106 static inline std::ostream& operator<< (std::ostream& str, const LogComps& c)
107 {
108         DE_ASSERT(c.numComps == 1 || c.numComps == 3);
109         return c.numComps == 3 ? str << c.v : str << c.v.x();
110 }
111
112 class SubCase
113 {
114 public:
115         // Use getters instead of public const members, because SubCase must be assignable
116         // in order to be stored in a vector.
117
118         const UVec3&    localSize               (void) const { return m_localSize; }
119         const UVec3&    numWorkGroups   (void) const { return m_numWorkGroups; }
120
121                                         SubCase                 (void) {}
122                                         SubCase                 (const UVec3& localSize_, const UVec3& numWorkGroups_)
123                                                 : m_localSize           (localSize_)
124                                                 , m_numWorkGroups       (numWorkGroups_) {}
125
126 private:
127         UVec3   m_localSize;
128         UVec3   m_numWorkGroups;
129 };
130
131
132 class ComputeBuiltinVarInstance : public vkt::TestInstance
133 {
134 public:
135                                                                         ComputeBuiltinVarInstance       (Context&                                               context,
136                                                                                                                                  const vector<SubCase>&                 subCases,
137                                                                                                                                  const glu::DataType                    varType,
138                                                                                                                                  const ComputeBuiltinVarCase*   builtinVarCase);
139
140         virtual tcu::TestStatus                 iterate                                         (void);
141
142 private:
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;
149         int                                                             m_subCaseNdx;
150         const glu::DataType                             m_varType;
151 };
152
153 class ComputeBuiltinVarCase : public vkt::TestCase
154 {
155 public:
156                                                         ComputeBuiltinVarCase   (tcu::TestContext& context, const char* name, const char* varName, glu::DataType varType);
157                                                         ~ComputeBuiltinVarCase  (void);
158
159         TestInstance*                   createInstance                  (Context& context) const
160         {
161                 return new ComputeBuiltinVarInstance(context, m_subCases, m_varType, this);
162         };
163
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;
166
167 protected:
168         string                                  genBuiltinVarSource             (const string& varName, glu::DataType varType, const UVec3& localSize) const;
169         vector<SubCase>                 m_subCases;
170
171 private:
172         deUint32                                getProgram                              (const tcu::UVec3& localSize);
173
174         const string                    m_varName;
175         const glu::DataType             m_varType;
176         int                                             m_subCaseNdx;
177
178         ComputeBuiltinVarCase (const ComputeBuiltinVarCase& other);
179         ComputeBuiltinVarCase& operator= (const ComputeBuiltinVarCase& other);
180 };
181
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)
186         , m_subCaseNdx  (0)
187 {
188 }
189
190 ComputeBuiltinVarCase::~ComputeBuiltinVarCase (void)
191 {
192         ComputeBuiltinVarCase::deinit();
193 }
194
195 void ComputeBuiltinVarCase::initPrograms (SourceCollections& programCollection) const
196 {
197         for (std::size_t i = 0; i < m_subCases.size(); i++)
198         {
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());
203         }
204 }
205
206 string ComputeBuiltinVarCase::genBuiltinVarSource (const string& varName, glu::DataType varType, const UVec3& localSize) const
207 {
208         std::ostringstream src;
209
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"
213                 << "{\n"
214                 << "    uvec2 u_stride;\n"
215                 << "}stride;\n"
216                 << "layout(set = 0, binding = 1, std430) buffer Output\n"
217                 << "{\n"
218                 << "    " << glu::getDataTypeName(varType) << " result[];\n"
219                 << "} sb_out;\n"
220                 << "\n"
221                 << "void main (void)\n"
222                 << "{\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"
225                 << "}\n";
226
227         return src.str();
228 }
229
230 class NumWorkGroupsCase : public ComputeBuiltinVarCase
231 {
232 public:
233         NumWorkGroupsCase (tcu::TestContext& context)
234                 : ComputeBuiltinVarCase(context, "num_work_groups", "gl_NumWorkGroups", glu::TYPE_UINT_VEC3)
235         {
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)));
242         }
243
244         UVec3 computeReference (const UVec3& numWorkGroups, const UVec3& workGroupSize, const UVec3& workGroupID, const UVec3& localInvocationID) const
245         {
246                 DE_UNREF(numWorkGroups);
247                 DE_UNREF(workGroupSize);
248                 DE_UNREF(workGroupID);
249                 DE_UNREF(localInvocationID);
250                 return numWorkGroups;
251         }
252 };
253
254 class WorkGroupSizeCase : public ComputeBuiltinVarCase
255 {
256 public:
257         WorkGroupSizeCase (tcu::TestContext& context)
258                 : ComputeBuiltinVarCase(context, "work_group_size", "gl_WorkGroupSize", glu::TYPE_UINT_VEC3)
259         {
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)));
269         }
270
271         UVec3 computeReference (const UVec3& numWorkGroups, const UVec3& workGroupSize, const UVec3& workGroupID, const UVec3& localInvocationID) const
272         {
273                 DE_UNREF(numWorkGroups);
274                 DE_UNREF(workGroupID);
275                 DE_UNREF(localInvocationID);
276                 return workGroupSize;
277         }
278 };
279
280 //-----------------------------------------------------------------------
281 class WorkGroupIDCase : public ComputeBuiltinVarCase
282 {
283 public:
284         WorkGroupIDCase (tcu::TestContext& context)
285                 : ComputeBuiltinVarCase(context, "work_group_id", "gl_WorkGroupID", glu::TYPE_UINT_VEC3)
286         {
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)));
293         }
294
295         UVec3 computeReference (const UVec3& numWorkGroups, const UVec3& workGroupSize, const UVec3& workGroupID, const UVec3& localInvocationID) const
296         {
297                 DE_UNREF(numWorkGroups);
298                 DE_UNREF(workGroupSize);
299                 DE_UNREF(localInvocationID);
300                 return workGroupID;
301         }
302 };
303
304 class LocalInvocationIDCase : public ComputeBuiltinVarCase
305 {
306 public:
307         LocalInvocationIDCase (tcu::TestContext& context)
308                 : ComputeBuiltinVarCase(context, "local_invocation_id", "gl_LocalInvocationID", glu::TYPE_UINT_VEC3)
309         {
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)));
319         }
320
321         UVec3 computeReference (const UVec3& numWorkGroups, const UVec3& workGroupSize, const UVec3& workGroupID, const UVec3& localInvocationID) const
322         {
323                 DE_UNREF(numWorkGroups);
324                 DE_UNREF(workGroupSize);
325                 DE_UNREF(workGroupID);
326                 return localInvocationID;
327         }
328 };
329
330 class GlobalInvocationIDCase : public ComputeBuiltinVarCase
331 {
332 public:
333         GlobalInvocationIDCase (tcu::TestContext& context)
334                 : ComputeBuiltinVarCase(context, "global_invocation_id", "gl_GlobalInvocationID", glu::TYPE_UINT_VEC3)
335         {
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)));
344         }
345
346         UVec3 computeReference (const UVec3& numWorkGroups, const UVec3& workGroupSize, const UVec3& workGroupID, const UVec3& localInvocationID) const
347         {
348                 DE_UNREF(numWorkGroups);
349                 return workGroupID * workGroupSize + localInvocationID;
350         }
351 };
352
353 class LocalInvocationIndexCase : public ComputeBuiltinVarCase
354 {
355 public:
356         LocalInvocationIndexCase (tcu::TestContext& context)
357                 : ComputeBuiltinVarCase(context, "local_invocation_index", "gl_LocalInvocationIndex", glu::TYPE_UINT)
358         {
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)));
365         }
366
367         UVec3 computeReference (const UVec3& numWorkGroups, const UVec3& workGroupSize, const UVec3& workGroupID, const UVec3& localInvocationID) const
368         {
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);
372         }
373 };
374
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)
386         , m_subCaseNdx                  (0)
387         , m_varType                             (varType)
388 {
389 }
390
391 tcu::TestStatus ComputeBuiltinVarInstance::iterate (void)
392 {
393         std::ostringstream program_name;
394         program_name << s_prefixProgramName << m_subCaseNdx;
395
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];
402
403         deUint32                                        resultBufferStride = 0;
404         switch (m_varType)
405         {
406                 case glu::TYPE_UINT:
407                         resultBufferStride = sizeof(deUint32);
408                         break;
409                 case glu::TYPE_UINT_VEC2:
410                         resultBufferStride = sizeof(tcu::UVec2);
411                         break;
412                 case glu::TYPE_UINT_VEC3:
413                 case glu::TYPE_UINT_VEC4:
414                         resultBufferStride = sizeof(tcu::UVec4);
415                         break;
416                 default:
417                         DE_ASSERT("Illegal data type");
418         }
419
420         const deUint32                          resultBufferSize        = numInvocations * resultBufferStride;
421
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);
425
426         {
427                 const Allocation& alloc = uniformBuffer.getAllocation();
428                 memcpy(alloc.getHostPtr(), &stride, sizeOfUniformBuffer);
429                 flushMappedMemoryRange(m_vki, m_device, alloc.getMemory(), alloc.getOffset(), sizeOfUniformBuffer);
430         }
431
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));
438
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));
442
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));
448
449         const VkBufferMemoryBarrier bufferBarrier = makeBufferMemoryBarrier(
450                 VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *resultBuffer, 0ull, resultBufferSize);
451
452         const Unique<VkCommandPool> cmdPool(makeCommandPool(m_vki, m_device, m_queueFamilyIndex));
453         const Unique<VkCommandBuffer> cmdBuffer(makeCommandBuffer(m_vki, m_device, *cmdPool));
454
455         // Start recording commands
456         beginCommandBuffer(m_vki, *cmdBuffer);
457
458         m_vki.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
459
460         // Create descriptor set
461         const Unique<VkDescriptorSet> descriptorSet(makeDescriptorSet(m_vki, m_device, *descriptorPool, *descriptorSetLayout));
462
463         const VkDescriptorBufferInfo resultDescriptorInfo = makeDescriptorBufferInfo(*resultBuffer, 0ull, resultBufferSize);
464         const VkDescriptorBufferInfo uniformDescriptorInfo = makeDescriptorBufferInfo(*uniformBuffer, 0ull, sizeOfUniformBuffer);
465
466         DescriptorSetUpdateBuilder()
467                 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &uniformDescriptorInfo)
468                 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultDescriptorInfo)
469                 .update(m_vki, m_device);
470
471         m_vki.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
472
473         // Dispatch indirect compute command
474         m_vki.cmdDispatch(*cmdBuffer, subCase.numWorkGroups()[0], subCase.numWorkGroups()[1], subCase.numWorkGroups()[2]);
475
476         m_vki.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0,
477                                                          0, (const VkMemoryBarrier*)DE_NULL,
478                                                          1, &bufferBarrier,
479                                                          0, (const VkImageMemoryBarrier*)DE_NULL);
480
481         // End recording commands
482         endCommandBuffer(m_vki, *cmdBuffer);
483
484         // Wait for command buffer execution finish
485         submitCommandsAndWait(m_vki, m_device, m_queue, *cmdBuffer);
486
487         const Allocation& resultAlloc = resultBuffer.getAllocation();
488         invalidateMappedMemoryRange(m_vki, m_device, resultAlloc.getMemory(), resultAlloc.getOffset(), resultBufferSize);
489
490         const deUint8*   ptr = reinterpret_cast<deUint8*>(resultAlloc.getHostPtr());
491
492         int                     numFailed               = 0;
493         const int       maxLogPrints    = 10;
494
495         tcu::TestContext& testCtx       = m_context.getTestContext();
496
497         for (deUint32 groupZ = 0; groupZ < subCase.numWorkGroups().z(); groupZ++)
498         for (deUint32 groupY = 0; groupY < subCase.numWorkGroups().y(); groupY++)
499         for (deUint32 groupX = 0; groupX < subCase.numWorkGroups().x(); groupX++)
500         for (deUint32 localZ = 0; localZ < subCase.localSize().z(); localZ++)
501         for (deUint32 localY = 0; localY < subCase.localSize().y(); localY++)
502         for (deUint32 localX = 0; localX < subCase.localSize().x(); localX++)
503         {
504                 const UVec3                     refGroupID(groupX, groupY, groupZ);
505                 const UVec3                     refLocalID(localX, localY, localZ);
506                 const UVec3                     refGlobalID = refGroupID * subCase.localSize() + refLocalID;
507
508                 const deUint32          refOffset = stride.x()*refGlobalID.z() + stride.y()*refGlobalID.y() + refGlobalID.x();
509
510                 const UVec3                     refValue = m_builtin_var_case->computeReference(subCase.numWorkGroups(), subCase.localSize(), refGroupID, refLocalID);
511
512                 const deUint32*         resPtr = (const deUint32*)(ptr + refOffset * resultBufferStride);
513                 const UVec3                     resValue = readResultVec(resPtr, numScalars);
514
515                 if (!compareNumComponents(refValue, resValue, numScalars))
516                 {
517                         if (numFailed < maxLogPrints)
518                                 testCtx.getLog()
519                                 << TestLog::Message
520                                 << "ERROR: comparison failed at offset " << refOffset
521                                 << ": expected " << LogComps(refValue, numScalars)
522                                 << ", got " << LogComps(resValue, numScalars)
523                                 << TestLog::EndMessage;
524                         else if (numFailed == maxLogPrints)
525                                 testCtx.getLog() << TestLog::Message << "..." << TestLog::EndMessage;
526
527                         numFailed += 1;
528                 }
529         }
530
531         testCtx.getLog() << TestLog::Message << (numInvocations - numFailed) << " / " << numInvocations << " values passed" << TestLog::EndMessage;
532
533         if (numFailed > 0)
534                 return tcu::TestStatus::fail("Comparison failed");
535
536         m_subCaseNdx += 1;
537         return (m_subCaseNdx < (int)m_subCases.size()) ? tcu::TestStatus::incomplete() :tcu::TestStatus::pass("Comparison succeeded");
538 }
539
540 class ComputeShaderBuiltinVarTests : public tcu::TestCaseGroup
541 {
542 public:
543                         ComputeShaderBuiltinVarTests    (tcu::TestContext& context);
544
545         void    init                                                    (void);
546
547 private:
548         ComputeShaderBuiltinVarTests (const ComputeShaderBuiltinVarTests& other);
549         ComputeShaderBuiltinVarTests& operator= (const ComputeShaderBuiltinVarTests& other);
550 };
551
552 ComputeShaderBuiltinVarTests::ComputeShaderBuiltinVarTests (tcu::TestContext& context)
553         : TestCaseGroup(context, "builtin_var", "Shader builtin var tests")
554 {
555 }
556
557 void ComputeShaderBuiltinVarTests::init (void)
558 {
559         addChild(new NumWorkGroupsCase(this->getTestContext()));
560         addChild(new WorkGroupSizeCase(this->getTestContext()));
561         addChild(new WorkGroupIDCase(this->getTestContext()));
562         addChild(new LocalInvocationIDCase(this->getTestContext()));
563         addChild(new GlobalInvocationIDCase(this->getTestContext()));
564         addChild(new LocalInvocationIndexCase(this->getTestContext()));
565 }
566
567 } // anonymous
568
569 tcu::TestCaseGroup* createComputeShaderBuiltinVarTests (tcu::TestContext& testCtx)
570 {
571         return new ComputeShaderBuiltinVarTests(testCtx);
572 }
573
574 } // compute
575 } // vkt