porting changes for OpenGL Subgroup tests
[platform/upstream/VK-GL-CTS.git] / external / openglcts / modules / common / subgroups / glcSubgroupsTestsUtils.cpp
1 /*------------------------------------------------------------------------
2  * OpenGL Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2017-2019 The Khronos Group Inc.
6  * Copyright (c) 2017 Codeplay Software Ltd.
7  * Copyright (c) 2019 NVIDIA Corporation.
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  */ /*!
22  * \file
23  * \brief Subgroups Tests Utils
24  */ /*--------------------------------------------------------------------*/
25
26 #include "glcSubgroupsTestsUtils.hpp"
27 #include "deRandom.hpp"
28 #include "tcuCommandLine.hpp"
29 #include "tcuStringTemplate.hpp"
30 #include "gluContextInfo.hpp"
31 #include "gluShaderUtil.hpp"
32
33 using namespace deqp;
34 using namespace std;
35 using namespace glc;
36 using namespace glw;
37
38 namespace
39 {
40 // debug callback function
41 // To use:
42 //        gl.enable(GL_DEBUG_OUTPUT);
43 //        gl.debugMessageCallback(debugCallback, &context);
44 //
45 void debugCallback(GLenum source, GLenum type, GLuint id, GLenum severity,
46                                         GLsizei length, const char * message, const void * userParam)
47 {
48         glc::Context *context = (glc::Context *)userParam;
49
50         tcu::TestLog& log       = context->getDeqpContext().getTestContext().getLog();
51
52         log << tcu::TestLog::Message
53                 << "DEBUG: source = " << source << ", type= " << type << ", id = " << id << ", severity = " << severity
54                 << ", length = " << length << "\n"
55                 << "DEBUG: `" << message << "`"
56                 << tcu::TestLog::EndMessage;
57
58 }
59
60 // getFormatReadInfo
61 // returns the stride in bytes
62 deUint32 getFormatReadInfo(const subgroups::Format format, GLenum &readFormat, GLenum &readType)
63 {
64         using namespace subgroups;
65         switch (format)
66         {
67                 default:
68                         DE_FATAL("Unhandled format!");
69                         // fall-through
70                 case FORMAT_R32G32B32A32_SFLOAT:
71                         readFormat = GL_RGBA;
72                         readType = GL_FLOAT;
73                         return 4u;
74                 case FORMAT_R32G32_SFLOAT:
75                         readFormat = GL_RG;
76                         readType = GL_FLOAT;
77                         return 2u;
78                 case FORMAT_R32_UINT:
79                         readFormat = GL_RED_INTEGER;
80                         readType = GL_UNSIGNED_INT;
81                         return 1u;
82                 case FORMAT_R32G32B32A32_UINT:
83                         readFormat = GL_RGBA_INTEGER;
84                         readType = GL_UNSIGNED_INT;
85                         return 4u;
86         }
87 }
88 deUint32 getFormatSizeInBytes(const subgroups::Format format)
89 {
90         using namespace subgroups;
91         switch (format)
92         {
93                 default:
94                         DE_FATAL("Unhandled format!");
95                         return 0;
96                 case FORMAT_R32_SINT:
97                 case FORMAT_R32_UINT:
98                         return sizeof(deInt32);
99                 case FORMAT_R32G32_SINT:
100                 case FORMAT_R32G32_UINT:
101                         return static_cast<deUint32>(sizeof(deInt32) * 2);
102                 case FORMAT_R32G32B32_SINT:
103                 case FORMAT_R32G32B32_UINT:
104                 case FORMAT_R32G32B32A32_SINT:
105                 case FORMAT_R32G32B32A32_UINT:
106                         return static_cast<deUint32>(sizeof(deInt32) * 4);
107                 case FORMAT_R32_SFLOAT:
108                         return 4;
109                 case FORMAT_R32G32_SFLOAT:
110                         return 8;
111                 case FORMAT_R32G32B32_SFLOAT:
112                         return 16;
113                 case FORMAT_R32G32B32A32_SFLOAT:
114                         return 16;
115                 case FORMAT_R64_SFLOAT:
116                         return 8;
117                 case FORMAT_R64G64_SFLOAT:
118                         return 16;
119                 case FORMAT_R64G64B64_SFLOAT:
120                         return 32;
121                 case FORMAT_R64G64B64A64_SFLOAT:
122                         return 32;
123                 // The below formats are used to represent bool and bvec* types. These
124                 // types are passed to the shader as int and ivec* types, before the
125                 // calculations are done as booleans. We need a distinct type here so
126                 // that the shader generators can switch on it and generate the correct
127                 // shader source for testing.
128                 case FORMAT_R32_BOOL:
129                         return sizeof(deInt32);
130                 case FORMAT_R32G32_BOOL:
131                         return static_cast<deUint32>(sizeof(deInt32) * 2);
132                 case FORMAT_R32G32B32_BOOL:
133                 case FORMAT_R32G32B32A32_BOOL:
134                         return static_cast<deUint32>(sizeof(deInt32) * 4);
135         }
136 }
137
138 de::MovePtr<glu::ShaderProgram> makeGraphicsPipeline(glc::Context&                              context,
139                                                                           const subgroups::ShaderStageFlags                     stages,
140                                                                           const GlslSource *                                            vshader,
141                                                                           const GlslSource *                                            fshader,
142                                                                           const GlslSource *                                            gshader,
143                                                                           const GlslSource *                                            tcshader,
144                                                                           const GlslSource *                                            teshader)
145 {
146         tcu::TestLog&   log                     = context.getDeqpContext().getTestContext().getLog();
147         const bool              doShaderLog     = log.isShaderLoggingEnabled();
148         DE_UNREF(stages);                       // only used for asserts
149
150         map<string, string>             templateArgs;
151 //      string                                  versionDecl(getGLSLVersionDeclaration(context.getGLSLVersion()));
152 //      templateArgs.insert(pair<string, string>("VERSION_DECL", versionDecl));
153
154         string vertSource, tescSource, teseSource, geomSource, fragSource;
155         if (vshader)
156         {
157                 DE_ASSERT(stages & subgroups::SHADER_STAGE_VERTEX_BIT);
158                 tcu::StringTemplate shaderTemplate(vshader->sources[glu::SHADERTYPE_VERTEX][0]);
159                 string shaderSource(shaderTemplate.specialize(templateArgs));
160                 if (doShaderLog)
161                 {
162                         log << tcu::TestLog::Message << "vertex shader:\n"
163                                 << shaderSource << "\n:end:" << tcu::TestLog::EndMessage;
164                 }
165                 vertSource = shaderSource;
166         }
167         if (tcshader)
168         {
169                 DE_ASSERT(stages & subgroups::SHADER_STAGE_TESS_CONTROL_BIT);
170                 tcu::StringTemplate shaderTemplate(tcshader->sources[glu::SHADERTYPE_TESSELLATION_CONTROL][0]);
171                 string shaderSource(shaderTemplate.specialize(templateArgs));
172                 if (doShaderLog)
173                 {
174                         log << tcu::TestLog::Message << "tess control shader:\n"
175                                 << shaderSource << "\n:end:" << tcu::TestLog::EndMessage;
176                 }
177                 tescSource = shaderSource;
178         }
179         if (teshader)
180         {
181                 DE_ASSERT(stages & subgroups::SHADER_STAGE_TESS_EVALUATION_BIT);
182                 tcu::StringTemplate shaderTemplate(teshader->sources[glu::SHADERTYPE_TESSELLATION_EVALUATION][0]);
183                 string shaderSource(shaderTemplate.specialize(templateArgs));
184                 if (doShaderLog)
185                 {
186                         log << tcu::TestLog::Message << "tess eval shader:\n"
187                                 << shaderSource << "\n:end:" << tcu::TestLog::EndMessage;
188                 }
189                 teseSource = shaderSource;
190         }
191         if (gshader)
192         {
193                 DE_ASSERT(stages & subgroups::SHADER_STAGE_GEOMETRY_BIT);
194                 tcu::StringTemplate shaderTemplate(gshader->sources[glu::SHADERTYPE_GEOMETRY][0]);
195                 string shaderSource(shaderTemplate.specialize(templateArgs));
196                 if (doShaderLog)
197                 {
198                         log << tcu::TestLog::Message << "geometry shader:\n"
199                                 << shaderSource << "\n:end:" << tcu::TestLog::EndMessage;
200                 }
201                 geomSource = shaderSource;
202         }
203         if (fshader)
204         {
205                 DE_ASSERT(stages & subgroups::SHADER_STAGE_FRAGMENT_BIT);
206                 tcu::StringTemplate shaderTemplate(fshader->sources[glu::SHADERTYPE_FRAGMENT][0]);
207                 string shaderSource(shaderTemplate.specialize(templateArgs));
208                 if (doShaderLog)
209                 {
210                         log << tcu::TestLog::Message << "fragment shader:\n"
211                                 << shaderSource << "\n:end:" << tcu::TestLog::EndMessage;
212                 }
213                 fragSource = shaderSource;
214         }
215
216         glu::ShaderProgram *program = DE_NULL;
217         if(context.getShaderType() == SHADER_TYPE_GLSL)
218         {
219                 glu::ProgramSources sources;
220                 if (vshader)
221                         sources << glu::VertexSource(vertSource);
222                 if (tcshader)
223                         sources << glu::TessellationControlSource(tescSource);
224                 if (teshader)
225                         sources << glu::TessellationEvaluationSource(teseSource);
226                 if (gshader)
227                         sources << glu::GeometrySource(geomSource);
228                 if (fshader)
229                         sources << glu::FragmentSource(fragSource);
230
231                 program = new glu::ShaderProgram(context.getDeqpContext().getRenderContext().getFunctions(), sources);
232         } else {
233                 DE_ASSERT(context.getShaderType() == SHADER_TYPE_SPIRV);
234
235                 glu::ProgramBinaries binaries;
236                 if (vshader)
237                         binaries << spirvUtils::makeSpirV(log, glu::VertexSource(vertSource), spirvUtils::SPIRV_VERSION_1_3);
238                 if (tcshader)
239                         binaries << spirvUtils::makeSpirV(log, glu::TessellationControlSource(tescSource), spirvUtils::SPIRV_VERSION_1_3);
240                 if (teshader)
241                         binaries << spirvUtils::makeSpirV(log, glu::TessellationEvaluationSource(teseSource), spirvUtils::SPIRV_VERSION_1_3);
242                 if (gshader)
243                         binaries << spirvUtils::makeSpirV(log, glu::GeometrySource(geomSource), spirvUtils::SPIRV_VERSION_1_3);
244                 if (fshader)
245                         binaries << spirvUtils::makeSpirV(log, glu::FragmentSource(fragSource), spirvUtils::SPIRV_VERSION_1_3);
246
247                 program = new glu::ShaderProgram(context.getDeqpContext().getRenderContext().getFunctions(), binaries);
248         }
249
250         if (!program->isOk())
251         {
252                 log << tcu::TestLog::Message << "Shader build failed.\n"
253                         << "Vertex: " << (vshader ? program->getShaderInfo(glu::SHADERTYPE_VERTEX).infoLog : "n/a") << "\n"
254                         << "Tess Cont: " << (tcshader ? program->getShaderInfo(glu::SHADERTYPE_TESSELLATION_CONTROL).infoLog : "n/a") << "\n"
255                         << "Tess Eval: " << (teshader ? program->getShaderInfo(glu::SHADERTYPE_TESSELLATION_EVALUATION).infoLog : "n/a") << "\n"
256                         << "Geometry: " << (gshader ? program->getShaderInfo(glu::SHADERTYPE_GEOMETRY).infoLog : "n/a") << "\n"
257                         << "Fragment: " << (fshader ? program->getShaderInfo(glu::SHADERTYPE_FRAGMENT).infoLog : "n/a") << "\n"
258                         << "Program: " << program->getProgramInfo().infoLog << tcu::TestLog::EndMessage;
259         }
260         return de::MovePtr<glu::ShaderProgram>(program);
261 }
262
263 de::MovePtr<glu::ShaderProgram> makeComputePipeline(glc::Context& context, const GlslSource &glslTemplate,
264                                                                          deUint32 localSizeX, deUint32 localSizeY, deUint32 localSizeZ)
265 {
266
267         tcu::TestLog&   log                     = context.getDeqpContext().getTestContext().getLog();
268         const bool              doShaderLog     = log.isShaderLoggingEnabled();
269
270         tcu::StringTemplate computeTemplate(glslTemplate.sources[glu::SHADERTYPE_COMPUTE][0]);
271
272         map<string, string>             localSizeParams;
273         {
274                 stringstream localSize;
275                 localSize << "local_size_x = " << localSizeX;
276                 localSizeParams.insert(pair<string, string>("LOCAL_SIZE_X", localSize.str()));
277         }
278         {
279                 stringstream localSize;
280                 localSize << "local_size_y = " << localSizeY;
281                 localSizeParams.insert(pair<string, string>("LOCAL_SIZE_Y", localSize.str()));
282         }
283         {
284                 stringstream localSize;
285                 localSize << "local_size_z = " << localSizeZ;
286                 localSizeParams.insert(pair<string, string>("LOCAL_SIZE_Z", localSize.str()));
287         }
288
289         glu::ComputeSource cshader(glu::ComputeSource(computeTemplate.specialize(localSizeParams)));
290
291         if (doShaderLog)
292         {
293                 log << tcu::TestLog::Message << "compute shader specialized source:\n"
294                         << cshader.source << "\n:end:" << tcu::TestLog::EndMessage;
295         }
296
297         glu::ShaderProgram *program = DE_NULL;
298         if(context.getShaderType() == SHADER_TYPE_GLSL)
299         {
300                 glu::ProgramSources sources;
301                 sources << cshader;
302                 program = new glu::ShaderProgram(context.getDeqpContext().getRenderContext().getFunctions(), sources);
303         } else {
304                 DE_ASSERT(context.getShaderType() == SHADER_TYPE_SPIRV);
305
306                 glu::ProgramBinaries binaries;
307                 binaries << spirvUtils::makeSpirV(log, cshader, spirvUtils::SPIRV_VERSION_1_3);
308
309                 program = new glu::ShaderProgram(context.getDeqpContext().getRenderContext().getFunctions(), binaries);
310         }
311
312         if (!program->isOk())
313         {
314                 log << tcu::TestLog::Message << "Shader build failed.\n"
315                         << "Compute: " << program->getShaderInfo(glu::SHADERTYPE_COMPUTE).infoLog << "\n"
316                         << "Program: " << program->getProgramInfo().infoLog << tcu::TestLog::EndMessage;
317         }
318         return de::MovePtr<glu::ShaderProgram>(program);
319 }
320
321 struct Buffer;
322 struct Image;
323
324 struct BufferOrImage
325 {
326         bool isImage() const
327         {
328                 return m_isImage;
329         }
330
331         Buffer* getAsBuffer()
332         {
333                 if (m_isImage) DE_FATAL("Trying to get a buffer as an image!");
334                 return reinterpret_cast<Buffer* >(this);
335         }
336
337         Image* getAsImage()
338         {
339                 if (!m_isImage) DE_FATAL("Trying to get an image as a buffer!");
340                 return reinterpret_cast<Image*>(this);
341         }
342
343         virtual subgroups::DescriptorType getType() const
344         {
345                 if (m_isImage)
346                 {
347                         return subgroups::DESCRIPTOR_TYPE_STORAGE_IMAGE;
348                 }
349                 else
350                 {
351                         return subgroups::DESCRIPTOR_TYPE_STORAGE_BUFFER;
352                 }
353         }
354
355         GLuint getId()
356         {
357                 return m_objectId;
358         }
359
360         virtual ~BufferOrImage() {}
361
362 protected:
363         explicit BufferOrImage(glc::Context& context, bool image)
364                 : m_gl(context.getDeqpContext().getRenderContext().getFunctions())
365                 , m_isImage(image)
366                 , m_objectId(0) {}
367
368         const glw::Functions &  m_gl;
369         bool                                    m_isImage;
370         GLuint                                  m_objectId;
371 };
372
373 struct Buffer : public BufferOrImage
374 {
375         explicit Buffer(
376                 glc::Context& context, deUint64 sizeInBytes, GLenum target = GL_SHADER_STORAGE_BUFFER)
377                 : BufferOrImage         (context, false)
378                 // HACK overpad to account for the size for std140 UBOs
379                 , m_sizeInBytes         (sizeInBytes * 4)
380                 , m_target                      (target)
381         {
382                 m_gl.genBuffers(1, &m_objectId);
383                 GLU_EXPECT_NO_ERROR(m_gl.getError(), "genBuffers");
384                 m_gl.bindBuffer(m_target, m_objectId);
385                 GLU_EXPECT_NO_ERROR(m_gl.getError(), "bindBuffer");
386                 m_gl.bufferData(m_target, m_sizeInBytes, NULL, GL_DYNAMIC_DRAW);
387                 GLU_EXPECT_NO_ERROR(m_gl.getError(), "bufferData");
388                 m_gl.bindBuffer(m_target, 0);
389                 GLU_EXPECT_NO_ERROR(m_gl.getError(), "bindBuffer(0)");
390         }
391
392         virtual ~Buffer()
393         {
394                 if (m_objectId != 0)
395                 {
396                         m_gl.deleteBuffers(1, &m_objectId);
397                         GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDeleteBuffers");
398                 }
399         }
400
401         virtual subgroups::DescriptorType getType() const
402         {
403                 if (GL_UNIFORM_BUFFER == m_target)
404                 {
405                         return subgroups::DESCRIPTOR_TYPE_UNIFORM_BUFFER;
406                 }
407                 return subgroups::DESCRIPTOR_TYPE_STORAGE_BUFFER;
408         }
409
410         glw::GLvoid* mapBufferPtr() {
411                 glw::GLvoid *ptr;
412
413                 m_gl.bindBuffer(m_target, m_objectId);
414                 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer");
415
416                 ptr = m_gl.mapBuffer(m_target, GL_READ_WRITE);
417                 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glMapBuffer");
418
419                 m_gl.bindBuffer(m_target, 0);
420                 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer(0)");
421
422                 return ptr;
423         }
424
425         void unmapBufferPtr() {
426                 m_gl.bindBuffer(m_target, m_objectId);
427                 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer");
428
429                 m_gl.unmapBuffer(m_target);
430                 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glUnmapBuffer");
431
432                 m_gl.bindBuffer(m_target, 0);
433                 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindBuffer(0)");
434         }
435
436         deUint64 getSize() const {
437                 return m_sizeInBytes;
438         }
439
440 private:
441         deUint64                                        m_sizeInBytes;
442         const GLenum                            m_target;
443 };
444
445 struct Image : public BufferOrImage
446 {
447         explicit Image(glc::Context& context, deUint32 width, deUint32 height,
448                                    subgroups::Format format)
449                 : BufferOrImage(context, true)
450         {
451                 m_gl.genTextures(1, &m_objectId);
452                 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenTextures");
453                 m_gl.bindTexture(GL_TEXTURE_2D, m_objectId);
454                 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindTexture");
455                 m_gl.texStorage2D(GL_TEXTURE_2D, 1, format, width, height);
456                 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glTexStorage2D");
457         }
458
459         virtual ~Image()
460         {
461                 if (m_objectId != 0)
462                 {
463                         m_gl.deleteTextures(1, &m_objectId);
464                         GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDeleteTextures");
465                 }
466         }
467
468 private:
469 };
470
471 struct Vao
472 {
473         explicit Vao(glc::Context& context)
474                 : m_gl(context.getDeqpContext().getRenderContext().getFunctions())
475                 , m_objectId(0)
476         {
477                 m_gl.genVertexArrays(1, &m_objectId);
478                 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenVertexArrays");
479                 m_gl.bindVertexArray(m_objectId);
480                 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindVertexArray");
481         }
482
483         ~Vao()
484         {
485                 if (m_objectId != 0)
486                 {
487                         m_gl.deleteVertexArrays(1, &m_objectId);
488                         GLU_EXPECT_NO_ERROR(m_gl.getError(), "glDeleteVertexArrays");
489                 }
490         }
491
492 private:
493         const glw::Functions &  m_gl;
494         GLuint                                  m_objectId;
495 };
496
497 struct Fbo
498 {
499         explicit Fbo(glc::Context& context)
500                 : m_gl(context.getDeqpContext().getRenderContext().getFunctions())
501                 , m_objectId(0)
502         {
503                 m_gl.genFramebuffers(1, &m_objectId);
504                 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGenFramebuffers");
505                 m_gl.bindFramebuffer(GL_FRAMEBUFFER, m_objectId);
506                 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glBindFramebuffer");
507         }
508
509         ~Fbo()
510         {
511                 if (m_objectId != 0)
512                 {
513                         m_gl.deleteFramebuffers(1, &m_objectId);
514                         GLU_EXPECT_NO_ERROR(m_gl.getError(), "deleteFramebuffers");
515                 }
516         }
517
518         void bind2D(Image &img)
519         {
520                 m_gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, img.getId(), 0);
521                 GLU_EXPECT_NO_ERROR(m_gl.getError(), "glFramebufferTexture2D");
522         }
523
524 private:
525         const glw::Functions &  m_gl;
526         GLuint                                  m_objectId;
527
528 };
529 }
530
531 std::string glc::subgroups::getSharedMemoryBallotHelper()
532 {
533         return  "shared uvec4 superSecretComputeShaderHelper[gl_WorkGroupSize.x * gl_WorkGroupSize.y * gl_WorkGroupSize.z];\n"
534                         "uvec4 sharedMemoryBallot(bool vote)\n"
535                         "{\n"
536                         "  uint groupOffset = gl_SubgroupID;\n"
537                         "  // One invocation in the group 0's the whole group's data\n"
538                         "  if (subgroupElect())\n"
539                         "  {\n"
540                         "    superSecretComputeShaderHelper[groupOffset] = uvec4(0);\n"
541                         "  }\n"
542                         "  subgroupMemoryBarrierShared();\n"
543                         "  if (vote)\n"
544                         "  {\n"
545                         "    const highp uint invocationId = gl_SubgroupInvocationID % 32;\n"
546                         "    const highp uint bitToSet = 1u << invocationId;\n"
547                         "    switch (gl_SubgroupInvocationID / 32)\n"
548                         "    {\n"
549                         "    case 0: atomicOr(superSecretComputeShaderHelper[groupOffset].x, bitToSet); break;\n"
550                         "    case 1: atomicOr(superSecretComputeShaderHelper[groupOffset].y, bitToSet); break;\n"
551                         "    case 2: atomicOr(superSecretComputeShaderHelper[groupOffset].z, bitToSet); break;\n"
552                         "    case 3: atomicOr(superSecretComputeShaderHelper[groupOffset].w, bitToSet); break;\n"
553                         "    }\n"
554                         "  }\n"
555                         "  subgroupMemoryBarrierShared();\n"
556                         "  return superSecretComputeShaderHelper[groupOffset];\n"
557                         "}\n";
558 }
559
560 deUint32 glc::subgroups::getSubgroupSize(Context& context)
561 {
562         int subgroupSize = context.getDeqpContext().getContextInfo().getInt(GL_SUBGROUP_SIZE_KHR);
563
564         return subgroupSize;
565 }
566
567 deUint32 glc::subgroups::maxSupportedSubgroupSize() {
568         return 128u;
569 }
570
571 std::string glc::subgroups::getShaderStageName(ShaderStageFlags stage)
572 {
573         DE_ASSERT(stage & SHADER_STAGE_ALL_VALID);
574         switch (stage)
575         {
576                 default:
577                         DE_FATAL("Unhandled stage!");
578                         return "";
579                 case SHADER_STAGE_COMPUTE_BIT:
580                         return "compute";
581                 case SHADER_STAGE_FRAGMENT_BIT:
582                         return "fragment";
583                 case SHADER_STAGE_VERTEX_BIT:
584                         return "vertex";
585                 case SHADER_STAGE_GEOMETRY_BIT:
586                         return "geometry";
587                 case SHADER_STAGE_TESS_CONTROL_BIT:
588                         return "tess_control";
589                 case SHADER_STAGE_TESS_EVALUATION_BIT:
590                         return "tess_eval";
591         }
592 }
593
594 std::string glc::subgroups::getSubgroupFeatureName(SubgroupFeatureFlags bit)
595 {
596         DE_ASSERT(bit & SUBGROUP_FEATURE_ALL_VALID);
597         switch (bit)
598         {
599                 default:
600                         DE_FATAL("Unknown subgroup feature category!");
601                         return "";
602                 case SUBGROUP_FEATURE_BASIC_BIT:
603                         return "GL_SUBGROUP_FEATURE_BASIC_BIT_KHR";
604                 case SUBGROUP_FEATURE_VOTE_BIT:
605                         return "GL_SUBGROUP_FEATURE_VOTE_BIT_KHR";
606                 case SUBGROUP_FEATURE_ARITHMETIC_BIT:
607                         return "GL_SUBGROUP_FEATURE_ARITHMETIC_BIT_KHR";
608                 case SUBGROUP_FEATURE_BALLOT_BIT:
609                         return "GL_SUBGROUP_FEATURE_BALLOT_BIT_KHR";
610                 case SUBGROUP_FEATURE_SHUFFLE_BIT:
611                         return "GL_SUBGROUP_FEATURE_SHUFFLE_BIT_KHR";
612                 case SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT:
613                         return "GL_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT_KHR";
614                 case SUBGROUP_FEATURE_CLUSTERED_BIT:
615                         return "GL_SUBGROUP_FEATURE_CLUSTERED_BIT_KHR";
616                 case SUBGROUP_FEATURE_QUAD_BIT:
617                         return "GL_SUBGROUP_FEATURE_QUAD_BIT_KHR";
618                 case SUBGROUP_FEATURE_PARTITIONED_BIT_NV:
619                         return "GL_SUBGROUP_FEATURE_PARTITIONED_BIT_NV";
620         }
621 }
622
623 void glc::subgroups::addNoSubgroupShader (SourceCollections& programCollection)
624 {
625         {
626                 const std::string vertNoSubgroupGLSL =
627                         "#version 450\n"
628                         "void main (void)\n"
629                         "{\n"
630                         "  float pixelSize = 2.0f/1024.0f;\n"
631                         "   float pixelPosition = pixelSize/2.0f - 1.0f;\n"
632                         "  gl_Position = vec4(float(gl_VertexID) * pixelSize + pixelPosition, 0.0f, 0.0f, 1.0f);\n"
633                         "  gl_PointSize = 1.0f;\n"
634                         "}\n";
635                 programCollection.add("vert_noSubgroup") << glu::VertexSource(vertNoSubgroupGLSL);
636         }
637
638         {
639                 const std::string tescNoSubgroupGLSL =
640                         "#version 450\n"
641                         "layout(vertices=1) out;\n"
642                         "\n"
643                         "void main (void)\n"
644                         "{\n"
645                         "  if (gl_InvocationID == 0)\n"
646                         "  {\n"
647                         "    gl_TessLevelOuter[0] = 1.0f;\n"
648                         "    gl_TessLevelOuter[1] = 1.0f;\n"
649                         "  }\n"
650                         "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
651                         "}\n";
652                 programCollection.add("tesc_noSubgroup") << glu::TessellationControlSource(tescNoSubgroupGLSL);
653         }
654
655         {
656                 const std::string teseNoSubgroupGLSL =
657                         "#version 450\n"
658                         "layout(isolines) in;\n"
659                         "\n"
660                         "void main (void)\n"
661                         "{\n"
662                         "  float pixelSize = 2.0f/1024.0f;\n"
663                         "  gl_Position = gl_in[0].gl_Position + gl_TessCoord.x * pixelSize / 2.0f;\n"
664                         "}\n";
665                 programCollection.add("tese_noSubgroup") << glu::TessellationEvaluationSource(teseNoSubgroupGLSL);
666         }
667
668 }
669
670 std::string glc::subgroups::getVertShaderForStage(const ShaderStageFlags stage)
671 {
672         DE_ASSERT(stage & SHADER_STAGE_ALL_VALID);
673         switch (stage)
674         {
675                 default:
676                         DE_FATAL("Unhandled stage!");
677                         return "";
678                 case SHADER_STAGE_FRAGMENT_BIT:
679                         return
680                                 "#version 450\n"
681                                 "void main (void)\n"
682                                 "{\n"
683                                 "  float pixelSize = 2.0f/1024.0f;\n"
684                                 "   float pixelPosition = pixelSize/2.0f - 1.0f;\n"
685                                 "  gl_Position = vec4(float(gl_VertexID) * pixelSize + pixelPosition, 0.0f, 0.0f, 1.0f);\n"
686                                 "}\n";
687                 case SHADER_STAGE_GEOMETRY_BIT:
688                         return
689                                 "#version 450\n"
690                                 "void main (void)\n"
691                                 "{\n"
692                                 "}\n";
693                 case SHADER_STAGE_TESS_CONTROL_BIT:
694                 case SHADER_STAGE_TESS_EVALUATION_BIT:
695                         return
696                                 "#version 450\n"
697                                 "void main (void)\n"
698                                 "{\n"
699                                 "}\n";
700         }
701 }
702
703 bool glc::subgroups::isSubgroupSupported(Context& context)
704 {
705         return context.getDeqpContext().getContextInfo().isExtensionSupported("GL_KHR_shader_subgroup");
706 }
707
708 bool glc::subgroups::areSubgroupOperationsSupportedForStage(
709         Context& context, const ShaderStageFlags stage)
710 {
711         DE_ASSERT(stage & SHADER_STAGE_ALL_VALID);
712         int supportedStages = context.getDeqpContext().getContextInfo().getInt(GL_SUBGROUP_SUPPORTED_STAGES_KHR);
713
714         return (stage & supportedStages) ? true : false;
715 }
716
717 bool glc::subgroups::areSubgroupOperationsRequiredForStage(
718         const ShaderStageFlags stage)
719 {
720         DE_ASSERT(stage & SHADER_STAGE_ALL_VALID);
721         switch (stage)
722         {
723                 default:
724                         return false;
725                 case SHADER_STAGE_COMPUTE_BIT:
726                         return true;
727         }
728 }
729
730 bool glc::subgroups::isSubgroupFeatureSupportedForDevice(
731         Context& context,
732         const SubgroupFeatureFlags bit)
733 {
734         DE_ASSERT(bit & SUBGROUP_FEATURE_ALL_VALID);
735
736         int supportedOperations = context.getDeqpContext().getContextInfo().getInt(GL_SUBGROUP_SUPPORTED_FEATURES_KHR);
737
738         return (bit & supportedOperations) ? true : false;
739 }
740
741 bool glc::subgroups::isFragmentSSBOSupportedForDevice(Context& context)
742 {
743         int numFragmentSSBOs = context.getDeqpContext().getContextInfo().getInt(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS);
744
745         return (numFragmentSSBOs > 0) ? true : false;
746 }
747
748 bool glc::subgroups::isVertexSSBOSupportedForDevice(Context& context)
749 {
750         int numVertexSSBOs = context.getDeqpContext().getContextInfo().getInt(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS);
751
752         return (numVertexSSBOs > 0) ? true : false;
753 }
754
755 bool glc::subgroups::isDoubleSupportedForDevice(Context& context)
756 {
757         glu::ContextType contextType = context.getDeqpContext().getRenderContext().getType();
758         return (glu::contextSupports(contextType, glu::ApiType::core(4, 0)) ||
759                         context.getDeqpContext().getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"));
760 }
761
762 bool glc::subgroups::isDoubleFormat(Format format)
763 {
764         switch (format)
765         {
766                 default:
767                         return false;
768                 case FORMAT_R64_SFLOAT:
769                 case FORMAT_R64G64_SFLOAT:
770                 case FORMAT_R64G64B64_SFLOAT:
771                 case FORMAT_R64G64B64A64_SFLOAT:
772                         return true;
773         }
774 }
775
776 std::string glc::subgroups::getFormatNameForGLSL (Format format)
777 {
778         switch (format)
779         {
780                 default:
781                         DE_FATAL("Unhandled format!");
782                         return "";
783                 case FORMAT_R32_SINT:
784                         return "int";
785                 case FORMAT_R32G32_SINT:
786                         return "ivec2";
787                 case FORMAT_R32G32B32_SINT:
788                         return "ivec3";
789                 case FORMAT_R32G32B32A32_SINT:
790                         return "ivec4";
791                 case FORMAT_R32_UINT:
792                         return "uint";
793                 case FORMAT_R32G32_UINT:
794                         return "uvec2";
795                 case FORMAT_R32G32B32_UINT:
796                         return "uvec3";
797                 case FORMAT_R32G32B32A32_UINT:
798                         return "uvec4";
799                 case FORMAT_R32_SFLOAT:
800                         return "float";
801                 case FORMAT_R32G32_SFLOAT:
802                         return "vec2";
803                 case FORMAT_R32G32B32_SFLOAT:
804                         return "vec3";
805                 case FORMAT_R32G32B32A32_SFLOAT:
806                         return "vec4";
807                 case FORMAT_R64_SFLOAT:
808                         return "double";
809                 case FORMAT_R64G64_SFLOAT:
810                         return "dvec2";
811                 case FORMAT_R64G64B64_SFLOAT:
812                         return "dvec3";
813                 case FORMAT_R64G64B64A64_SFLOAT:
814                         return "dvec4";
815                 case FORMAT_R32_BOOL:
816                         return "bool";
817                 case FORMAT_R32G32_BOOL:
818                         return "bvec2";
819                 case FORMAT_R32G32B32_BOOL:
820                         return "bvec3";
821                 case FORMAT_R32G32B32A32_BOOL:
822                         return "bvec4";
823         }
824 }
825
826 void glc::subgroups::setVertexShaderFrameBuffer (SourceCollections& programCollection)
827 {
828         programCollection.add("vert") << glu::VertexSource(
829                 "#version 450\n"
830                 "layout(location = 0) in highp vec4 in_position;\n"
831                 "void main (void)\n"
832                 "{\n"
833                 "  gl_Position = in_position;\n"
834                 "}\n");
835 }
836
837 void glc::subgroups::setFragmentShaderFrameBuffer (SourceCollections& programCollection)
838 {
839         programCollection.add("fragment") << glu::FragmentSource(
840                 "#version 450\n"
841                 "layout(location = 0) in float in_color;\n"
842                 "layout(location = 0) out uint out_color;\n"
843                 "void main()\n"
844                 "{\n"
845                 "       out_color = uint(in_color);\n"
846                 "}\n");
847 }
848
849 void glc::subgroups::setTesCtrlShaderFrameBuffer (SourceCollections& programCollection)
850 {
851         programCollection.add("tesc") << glu::TessellationControlSource(
852                 "#version 450\n"
853                 "#extension GL_KHR_shader_subgroup_basic: enable\n"
854                 "#extension GL_EXT_tessellation_shader : require\n"
855                 "layout(vertices = 2) out;\n"
856                 "void main (void)\n"
857                 "{\n"
858                 "  if (gl_InvocationID == 0)\n"
859                 "  {\n"
860                 "    gl_TessLevelOuter[0] = 1.0f;\n"
861                 "    gl_TessLevelOuter[1] = 1.0f;\n"
862                 "  }\n"
863                 "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
864                 "}\n");
865 }
866
867 void glc::subgroups::setTesEvalShaderFrameBuffer (SourceCollections& programCollection)
868 {
869         programCollection.add("tese") << glu::TessellationEvaluationSource(
870                 "#version 450\n"
871                 "#extension GL_KHR_shader_subgroup_ballot: enable\n"
872                 "#extension GL_EXT_tessellation_shader : require\n"
873                 "layout(isolines, equal_spacing, ccw ) in;\n"
874                 "layout(location = 0) in float in_color[];\n"
875                 "layout(location = 0) out float out_color;\n"
876                 "\n"
877                 "void main (void)\n"
878                 "{\n"
879                 "  gl_Position = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);\n"
880                 "  out_color = in_color[0];\n"
881                 "}\n");
882 }
883
884 void glc::subgroups::addGeometryShadersFromTemplate (const std::string& glslTemplate, SourceCollections& collection)
885 {
886         tcu::StringTemplate geometryTemplate(glslTemplate);
887
888         map<string, string>             linesParams;
889         linesParams.insert(pair<string, string>("TOPOLOGY", "lines"));
890
891         map<string, string>             pointsParams;
892         pointsParams.insert(pair<string, string>("TOPOLOGY", "points"));
893
894         collection.add("geometry_lines")        << glu::GeometrySource(geometryTemplate.specialize(linesParams));
895         collection.add("geometry_points")       << glu::GeometrySource(geometryTemplate.specialize(pointsParams));
896 }
897
898 void initializeMemory(deqp::Context& context, glw::GLvoid *hostPtr, subgroups::SSBOData& data)
899 {
900         using namespace subgroups;
901         const Format format = data.format;
902         const deUint64 size = getFormatSizeInBytes(format) * data.numElements;
903         if (subgroups::SSBOData::InitializeNonZero == data.initializeType)
904         {
905                 de::Random rnd(context.getTestContext().getCommandLine().getBaseSeed());
906                 switch (format)
907                 {
908                         default:
909                                 DE_FATAL("Illegal buffer format");
910                                 break;
911                         case FORMAT_R32_BOOL:
912                         case FORMAT_R32G32_BOOL:
913                         case FORMAT_R32G32B32_BOOL:
914                         case FORMAT_R32G32B32A32_BOOL:
915                         case FORMAT_R32_SINT:
916                         case FORMAT_R32G32_SINT:
917                         case FORMAT_R32G32B32_SINT:
918                         case FORMAT_R32G32B32A32_SINT:
919                         case FORMAT_R32_UINT:
920                         case FORMAT_R32G32_UINT:
921                         case FORMAT_R32G32B32_UINT:
922                         case FORMAT_R32G32B32A32_UINT:
923                         {
924                                 deUint32* ptr = reinterpret_cast<deUint32*>(hostPtr);
925
926                                 for (deUint64 k = 0; k < (size / sizeof(deUint32)); k++)
927                                 {
928                                         ptr[k] = rnd.getUint32();
929                                 }
930                         }
931                         break;
932                         case FORMAT_R32_SFLOAT:
933                         case FORMAT_R32G32_SFLOAT:
934                         case FORMAT_R32G32B32_SFLOAT:
935                         case FORMAT_R32G32B32A32_SFLOAT:
936                         {
937                                 float* ptr = reinterpret_cast<float*>(hostPtr);
938
939                                 for (deUint64 k = 0; k < (size / sizeof(float)); k++)
940                                 {
941                                         ptr[k] = rnd.getFloat();
942                                 }
943                         }
944                         break;
945                         case FORMAT_R64_SFLOAT:
946                         case FORMAT_R64G64_SFLOAT:
947                         case FORMAT_R64G64B64_SFLOAT:
948                         case FORMAT_R64G64B64A64_SFLOAT:
949                         {
950                                 double* ptr = reinterpret_cast<double*>(hostPtr);
951
952                                 for (deUint64 k = 0; k < (size / sizeof(double)); k++)
953                                 {
954                                         ptr[k] = rnd.getDouble();
955                                 }
956                         }
957                         break;
958                 }
959         }
960         else if (subgroups::SSBOData::InitializeZero == data.initializeType)
961         {
962                 deUint32* ptr = reinterpret_cast<deUint32*>(hostPtr);
963
964                 for (deUint64 k = 0; k < size / 4; k++)
965                 {
966                         ptr[k] = 0;
967                 }
968         }
969
970         if (subgroups::SSBOData::InitializeNone != data.initializeType)
971         {
972                 // nothing to do for GL
973         }
974 }
975
976 deUint32 getResultBinding (const glc::subgroups::ShaderStageFlags shaderStage)
977 {
978         using namespace glc::subgroups;
979         switch(shaderStage)
980         {
981                 case SHADER_STAGE_VERTEX_BIT:
982                         return 0u;
983                         break;
984                 case SHADER_STAGE_TESS_CONTROL_BIT:
985                         return 1u;
986                         break;
987                 case SHADER_STAGE_TESS_EVALUATION_BIT:
988                         return 2u;
989                         break;
990                 case SHADER_STAGE_GEOMETRY_BIT:
991                         return 3u;
992                         break;
993                 default:
994                         DE_ASSERT(0);
995                         return -1;
996         }
997         DE_ASSERT(0);
998         return -1;
999 }
1000
1001 tcu::TestStatus glc::subgroups::makeTessellationEvaluationFrameBufferTest(
1002         Context& context, Format format, SSBOData* extraData,
1003         deUint32 extraDataCount,
1004         bool (*checkResult)(std::vector<const void*> datas, deUint32 width, deUint32 subgroupSize),
1005         const ShaderStageFlags shaderStage)
1006 {
1007         tcu::TestLog& log       = context.getDeqpContext().getTestContext().getLog();
1008         const glw::Functions& gl = context.getDeqpContext().getRenderContext().getFunctions();
1009
1010         const deUint32                                                  maxWidth                                = 1024u;
1011         vector<de::SharedPtr<BufferOrImage> >   inputBuffers                    (extraDataCount);
1012
1013         const GlslSource& vshader = context.getSourceCollection().get("vert");
1014         const GlslSource& tcshader = context.getSourceCollection().get("tesc");
1015         const GlslSource& teshader = context.getSourceCollection().get("tese");
1016         const GlslSource& fshader = context.getSourceCollection().get("fragment");
1017
1018         for (deUint32 i = 0u; i < extraDataCount; i++)
1019         {
1020                 if (extraData[i].isImage)
1021                 {
1022                         inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Image(context, static_cast<deUint32>(extraData[i].numElements), 1u, extraData[i].format));
1023                         // haven't implemented init for images yet
1024                         DE_ASSERT(extraData[i].initializeType == subgroups::SSBOData::InitializeNone);
1025                 }
1026                 else
1027                 {
1028                         deUint64 size = getFormatSizeInBytes(extraData[i].format) * extraData[i].numElements;
1029                         inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Buffer(context, size, GL_UNIFORM_BUFFER));
1030
1031                         glw::GLvoid *ptr = inputBuffers[i]->getAsBuffer()->mapBufferPtr();
1032                         initializeMemory(context.getDeqpContext(), ptr, extraData[i]);
1033                         inputBuffers[i]->getAsBuffer()->unmapBufferPtr();
1034                 }
1035         }
1036
1037         for (deUint32 ndx = 0u; ndx < extraDataCount; ndx++)
1038         {
1039                 log << tcu::TestLog::Message
1040                         << "binding inputBuffers[" << ndx << "](" << inputBuffers[ndx]->getType() << ", " << inputBuffers[ndx]->getId() << " ), "
1041                         << "stage = " << shaderStage << " , binding = " << extraData[ndx].binding << "\n"
1042                         << tcu::TestLog::EndMessage;
1043
1044                 if (inputBuffers[ndx]->isImage())
1045                 {
1046                         gl.bindImageTexture(extraData[ndx].binding, inputBuffers[ndx]->getId(),
1047                                                                 0, GL_FALSE, 0, GL_READ_ONLY, extraData[ndx].format);
1048                         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture()");
1049                 } else
1050                 {
1051                         gl.bindBufferBase(inputBuffers[ndx]->getType(), extraData[ndx].binding, inputBuffers[ndx]->getId());
1052                         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase()");
1053                 }
1054         }
1055
1056         de::MovePtr<glu::ShaderProgram> pipeline(
1057                         makeGraphicsPipeline(context, (ShaderStageFlags)(SHADER_STAGE_VERTEX_BIT | SHADER_STAGE_FRAGMENT_BIT | SHADER_STAGE_TESS_CONTROL_BIT | SHADER_STAGE_TESS_EVALUATION_BIT),
1058                                                                  &vshader, &fshader, DE_NULL, &tcshader, &teshader));
1059         if (!pipeline->isOk())
1060         {
1061                 return tcu::TestStatus::fail("tese graphics program build failed");
1062         }
1063
1064         const deUint32                                                  subgroupSize                    = getSubgroupSize(context);
1065         const deUint64                                                  vertexBufferSize                = 2ull * maxWidth * sizeof(tcu::Vec4);
1066         Buffer                                                                  vertexBuffer                    (context, vertexBufferSize, GL_ARRAY_BUFFER);
1067         unsigned                                                                totalIterations                 = 0u;
1068         unsigned                                                                failedIterations                = 0u;
1069         Image                                                                   discardableImage                (context, maxWidth, 1u, format);
1070
1071         {
1072                 glw::GLvoid *                   bufferPtr                       = vertexBuffer.mapBufferPtr();
1073                 std::vector<tcu::Vec4>  data                            (2u * maxWidth, tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f));
1074                 const float                             pixelSize                       = 2.0f / static_cast<float>(maxWidth);
1075                 float                                   leftHandPosition        = -1.0f;
1076
1077                 for(deUint32 ndx = 0u; ndx < data.size(); ndx+=2u)
1078                 {
1079                         data[ndx][0] = leftHandPosition;
1080                         leftHandPosition += pixelSize;
1081                         data[ndx+1][0] = leftHandPosition;
1082                 }
1083
1084                 deMemcpy(bufferPtr, &data[0], data.size() * sizeof(tcu::Vec4));
1085                 vertexBuffer.unmapBufferPtr();
1086         }
1087
1088         Vao vao(context);
1089         Fbo fbo(context);
1090         fbo.bind2D(discardableImage);
1091
1092         gl.viewport(0, 0, maxWidth, 1u);
1093         GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport");
1094
1095         for (deUint32 width = 1u; width < maxWidth; ++width)
1096         {
1097                 const deUint64                          imageResultSize         = getFormatSizeInBytes(format) * maxWidth;
1098                 vector<glw::GLubyte>            imageBufferResult(imageResultSize);
1099                 const deUint64                          vertexBufferOffset      = 0u;
1100
1101                 totalIterations++;
1102
1103                 {
1104                         gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
1105                         GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor");
1106                         gl.clear(GL_COLOR_BUFFER_BIT);
1107                         GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
1108
1109                         gl.useProgram(pipeline->getProgram());
1110                         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
1111
1112                         gl.enableVertexAttribArray(0);
1113                         GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
1114
1115                         gl.bindBuffer(GL_ARRAY_BUFFER, vertexBuffer.getId());
1116                         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
1117
1118                         gl.vertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(tcu::Vec4), vertexBufferOffset);
1119                         GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
1120
1121                         gl.patchParameteri(GL_PATCH_VERTICES, 2u);
1122                         GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameter(PATCH_VERTICES)");
1123
1124                         gl.drawArrays(GL_PATCHES, 0, 2 * width);
1125                         GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays");
1126
1127                         gl.disableVertexAttribArray(0);
1128
1129                         GLenum readFormat;
1130                         GLenum readType;
1131                         getFormatReadInfo(format, readFormat, readType);
1132
1133                         gl.readPixels(0, 0, width, 1, readFormat, readType, (GLvoid*)&imageBufferResult[0]);
1134                         GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
1135                 }
1136
1137                 {
1138                         std::vector<const void*> datas;
1139                         datas.push_back(&imageBufferResult[0]);
1140                         if (!checkResult(datas, width/2u, subgroupSize))
1141                                 failedIterations++;
1142                 }
1143         }
1144
1145         if (0 < failedIterations)
1146         {
1147                 log             << tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
1148                                 << totalIterations << " values passed" << tcu::TestLog::EndMessage;
1149                 return tcu::TestStatus::fail("Failed!");
1150         } else
1151         {
1152                 log     << tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
1153                                 <<totalIterations << " values passed" << tcu::TestLog::EndMessage;
1154         }
1155
1156         return tcu::TestStatus::pass("OK");
1157 }
1158
1159 bool glc::subgroups::check(std::vector<const void*> datas,
1160         deUint32 width, deUint32 ref)
1161 {
1162         const deUint32* data = reinterpret_cast<const deUint32*>(datas[0]);
1163
1164         for (deUint32 n = 0; n < width; ++n)
1165         {
1166                 if (data[n] != ref)
1167                 {
1168                         return false;
1169                 }
1170         }
1171
1172         return true;
1173 }
1174
1175 bool glc::subgroups::checkCompute(std::vector<const void*> datas,
1176         const deUint32 numWorkgroups[3], const deUint32 localSize[3],
1177         deUint32 ref)
1178 {
1179         const deUint32 globalSizeX = numWorkgroups[0] * localSize[0];
1180         const deUint32 globalSizeY = numWorkgroups[1] * localSize[1];
1181         const deUint32 globalSizeZ = numWorkgroups[2] * localSize[2];
1182
1183         return check(datas, globalSizeX * globalSizeY * globalSizeZ, ref);
1184 }
1185
1186
1187 tcu::TestStatus glc::subgroups::makeGeometryFrameBufferTest(
1188         Context& context, Format format, SSBOData* extraData,
1189         deUint32 extraDataCount,
1190         bool (*checkResult)(std::vector<const void*> datas, deUint32 width, deUint32 subgroupSize))
1191 {
1192         tcu::TestLog& log       = context.getDeqpContext().getTestContext().getLog();
1193         const glw::Functions& gl = context.getDeqpContext().getRenderContext().getFunctions();
1194
1195         const deUint32                                                  maxWidth                                = 1024u;
1196         vector<de::SharedPtr<BufferOrImage> >   inputBuffers                    (extraDataCount);
1197
1198         const GlslSource& vshader = context.getSourceCollection().get("vert");
1199         const GlslSource& gshader = context.getSourceCollection().get("geometry");
1200         const GlslSource& fshader = context.getSourceCollection().get("fragment");
1201
1202         for (deUint32 i = 0u; i < extraDataCount; i++)
1203         {
1204                 if (extraData[i].isImage)
1205                 {
1206                         inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Image(context, static_cast<deUint32>(extraData[i].numElements), 1u, extraData[i].format));
1207                         // haven't implemented init for images yet
1208                         DE_ASSERT(extraData[i].initializeType == subgroups::SSBOData::InitializeNone);
1209                 }
1210                 else
1211                 {
1212                         deUint64 size = getFormatSizeInBytes(extraData[i].format) * extraData[i].numElements;
1213                         inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Buffer(context, size, GL_UNIFORM_BUFFER));
1214
1215                         glw::GLvoid *ptr = inputBuffers[i]->getAsBuffer()->mapBufferPtr();
1216                         initializeMemory(context.getDeqpContext(), ptr, extraData[i]);
1217                         inputBuffers[i]->getAsBuffer()->unmapBufferPtr();
1218                 }
1219         }
1220
1221         for (deUint32 ndx = 0u; ndx < extraDataCount; ndx++)
1222         {
1223                 log << tcu::TestLog::Message
1224                         << "binding inputBuffers[" << ndx << "](" << inputBuffers[ndx]->getType() << ", " << inputBuffers[ndx]->getId() << " ), "
1225                         << "GEOMETRY, binding = " << extraData[ndx].binding << "\n"
1226                         << tcu::TestLog::EndMessage;
1227
1228                 if (inputBuffers[ndx]->isImage())
1229                 {
1230                         gl.bindImageTexture(extraData[ndx].binding, inputBuffers[ndx]->getId(),
1231                                                                 0, GL_FALSE, 0, GL_READ_ONLY, extraData[ndx].format);
1232                         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture()");
1233                 } else
1234                 {
1235                         gl.bindBufferBase(inputBuffers[ndx]->getType(), extraData[ndx].binding, inputBuffers[ndx]->getId());
1236                         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase()");
1237                 }
1238         }
1239
1240         de::MovePtr<glu::ShaderProgram> pipeline(
1241                         makeGraphicsPipeline(context, (ShaderStageFlags)(SHADER_STAGE_VERTEX_BIT | SHADER_STAGE_FRAGMENT_BIT | SHADER_STAGE_GEOMETRY_BIT),
1242                                                                  &vshader, &fshader, &gshader, DE_NULL, DE_NULL));
1243         if (!pipeline->isOk())
1244         {
1245                 return tcu::TestStatus::fail("geom graphics program build failed");
1246         }
1247
1248         const deUint32                                                  subgroupSize                    = getSubgroupSize(context);
1249         const deUint64                                                  vertexBufferSize                = maxWidth * sizeof(tcu::Vec4);
1250         Buffer                                                                  vertexBuffer                    (context, vertexBufferSize, GL_ARRAY_BUFFER);
1251         unsigned                                                                totalIterations                 = 0u;
1252         unsigned                                                                failedIterations                = 0u;
1253         Image                                                                   discardableImage                (context, maxWidth, 1u, format);
1254
1255         {
1256                 glw::GLvoid *                   bufferPtr                       = vertexBuffer.mapBufferPtr();
1257                 std::vector<tcu::Vec4>  data                            (maxWidth, tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
1258                 const float                             pixelSize                       = 2.0f / static_cast<float>(maxWidth);
1259                 float                                   leftHandPosition        = -1.0f;
1260
1261                 for(deUint32 ndx = 0u; ndx < maxWidth; ++ndx)
1262                 {
1263                         data[ndx][0] = leftHandPosition + pixelSize / 2.0f;
1264                         leftHandPosition += pixelSize;
1265                 }
1266
1267                 deMemcpy(bufferPtr, &data[0], maxWidth * sizeof(tcu::Vec4));
1268                 vertexBuffer.unmapBufferPtr();
1269         }
1270
1271         Vao vao(context);
1272         Fbo fbo(context);
1273         fbo.bind2D(discardableImage);
1274
1275         gl.viewport(0, 0, maxWidth, 1u);
1276         GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport");
1277
1278         for (deUint32 width = 1u; width < maxWidth; width++)
1279         {
1280                 totalIterations++;
1281                 const deUint64                          imageResultSize         = getFormatSizeInBytes(format) * maxWidth;
1282                 vector<glw::GLubyte>            imageBufferResult(imageResultSize);
1283                 const deUint64                          vertexBufferOffset      = 0u;
1284
1285                 for (deUint32 ndx = 0u; ndx < inputBuffers.size(); ndx++)
1286                 {
1287                         if (inputBuffers[ndx]->isImage())
1288                         {
1289                                 DE_ASSERT(extraData[ndx].initializeType == subgroups::SSBOData::InitializeNone);
1290                         } else
1291                         {
1292                                 glw::GLvoid *ptr = inputBuffers[ndx]->getAsBuffer()->mapBufferPtr();
1293                                 initializeMemory(context.getDeqpContext(), ptr, extraData[ndx]);
1294                                 inputBuffers[ndx]->getAsBuffer()->unmapBufferPtr();
1295                         }
1296                 }
1297
1298                 {
1299                         gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
1300                         GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor");
1301                         gl.clear(GL_COLOR_BUFFER_BIT);
1302                         GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
1303
1304                         gl.useProgram(pipeline->getProgram());
1305                         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
1306
1307                         gl.enableVertexAttribArray(0);
1308                         GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
1309
1310                         gl.bindBuffer(GL_ARRAY_BUFFER, vertexBuffer.getId());
1311                         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
1312
1313                         gl.vertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(tcu::Vec4), vertexBufferOffset);
1314                         GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
1315
1316                         gl.drawArrays(GL_POINTS, 0, width);
1317                         GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays");
1318
1319                         gl.disableVertexAttribArray(0);
1320                         GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray");
1321
1322                         GLenum readFormat;
1323                         GLenum readType;
1324                         getFormatReadInfo(format, readFormat, readType);
1325
1326                         gl.readPixels(0, 0, width, 1, readFormat, readType, (GLvoid*)&imageBufferResult[0]);
1327                         GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
1328                 }
1329
1330                 {
1331                         std::vector<const void*> datas;
1332                         datas.push_back(&imageBufferResult[0]);
1333                         if (!checkResult(datas, width, subgroupSize))
1334                                 failedIterations++;
1335                 }
1336         }
1337
1338         if (0 < failedIterations)
1339         {
1340                 log     << tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
1341                                 << totalIterations << " values passed" << tcu::TestLog::EndMessage;
1342                 return tcu::TestStatus::fail("Failed!");
1343         } else
1344         {
1345                 log     << tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
1346                                 <<totalIterations << " values passed" << tcu::TestLog::EndMessage;
1347         }
1348
1349         return tcu::TestStatus::pass("OK");
1350 }
1351
1352 tcu::TestStatus glc::subgroups::allStages(
1353         Context& context, Format format, SSBOData* extraDatas,
1354         deUint32 extraDatasCount,
1355         bool (*checkResult)(std::vector<const void*> datas, deUint32 width, deUint32 subgroupSize),
1356         const ShaderStageFlags shaderStageTested)
1357 {
1358         const deUint32                                  maxWidth                        = 1024u;
1359         vector<ShaderStageFlags>                stagesVector;
1360         ShaderStageFlags                                shaderStageRequired     = (ShaderStageFlags)0ull;
1361         tcu::TestLog&                                   log                                     = context.getDeqpContext().getTestContext().getLog();
1362         const glw::Functions&                   gl                                      = context.getDeqpContext().getRenderContext().getFunctions();
1363
1364         if (shaderStageTested & SHADER_STAGE_VERTEX_BIT)
1365         {
1366                 stagesVector.push_back(SHADER_STAGE_VERTEX_BIT);
1367         }
1368         if (shaderStageTested & SHADER_STAGE_TESS_CONTROL_BIT)
1369         {
1370                 stagesVector.push_back(SHADER_STAGE_TESS_CONTROL_BIT);
1371                 shaderStageRequired = (ShaderStageFlags)((deUint32)shaderStageRequired | ((deUint32)(shaderStageTested & SHADER_STAGE_TESS_EVALUATION_BIT) ? 0u : (deUint32)SHADER_STAGE_TESS_EVALUATION_BIT));
1372                 shaderStageRequired = (ShaderStageFlags)((deUint32)shaderStageRequired | ((deUint32)(shaderStageTested & SHADER_STAGE_VERTEX_BIT) ? 0u : (deUint32)SHADER_STAGE_VERTEX_BIT));
1373         }
1374         if (shaderStageTested & SHADER_STAGE_TESS_EVALUATION_BIT)
1375         {
1376                 stagesVector.push_back(SHADER_STAGE_TESS_EVALUATION_BIT);
1377                 shaderStageRequired = (ShaderStageFlags)((deUint32)shaderStageRequired | ((deUint32)(shaderStageTested & SHADER_STAGE_VERTEX_BIT) ? 0u : (deUint32)SHADER_STAGE_VERTEX_BIT));
1378                 shaderStageRequired = (ShaderStageFlags)((deUint32)shaderStageRequired | ((deUint32)(shaderStageTested & SHADER_STAGE_TESS_CONTROL_BIT) ? 0u : (deUint32)SHADER_STAGE_TESS_CONTROL_BIT));
1379         }
1380         if (shaderStageTested & SHADER_STAGE_GEOMETRY_BIT)
1381         {
1382                 stagesVector.push_back(SHADER_STAGE_GEOMETRY_BIT);
1383                 const ShaderStageFlags required = SHADER_STAGE_VERTEX_BIT;
1384                 shaderStageRequired = (ShaderStageFlags)((deUint32)shaderStageRequired | ((deUint32)(shaderStageTested & required) ? 0u : (deUint32)required));
1385         }
1386         if (shaderStageTested & SHADER_STAGE_FRAGMENT_BIT)
1387         {
1388                 const ShaderStageFlags required = SHADER_STAGE_VERTEX_BIT;
1389                 shaderStageRequired = (ShaderStageFlags)((deUint32)shaderStageRequired | ((deUint32)(shaderStageTested & required) ? 0u : (deUint32)required));
1390         }
1391
1392         const deUint32  stagesCount     = static_cast<deUint32>(stagesVector.size());
1393         const string    vert            = (shaderStageRequired & SHADER_STAGE_VERTEX_BIT)                       ? "vert_noSubgroup"             : "vert";
1394         const string    tesc            = (shaderStageRequired & SHADER_STAGE_TESS_CONTROL_BIT)         ? "tesc_noSubgroup"             : "tesc";
1395         const string    tese            = (shaderStageRequired & SHADER_STAGE_TESS_EVALUATION_BIT)      ? "tese_noSubgroup"             : "tese";
1396
1397         shaderStageRequired = (ShaderStageFlags)(shaderStageTested | shaderStageRequired);
1398
1399         const GlslSource *vshader = &context.getSourceCollection().get(vert);
1400         const GlslSource *fshader = DE_NULL;
1401         const GlslSource *gshader = DE_NULL;
1402         const GlslSource *tcshader = DE_NULL;
1403         const GlslSource *teshader = DE_NULL;
1404
1405         if (shaderStageRequired & SHADER_STAGE_TESS_CONTROL_BIT)
1406         {
1407                 tcshader = &context.getSourceCollection().get(tesc);
1408                 teshader = &context.getSourceCollection().get(tese);
1409         }
1410         if (shaderStageRequired & SHADER_STAGE_GEOMETRY_BIT)
1411         {
1412                 if (shaderStageRequired & SHADER_STAGE_TESS_EVALUATION_BIT)
1413                 {
1414                         // tessellation shaders output line primitives
1415                         gshader = &context.getSourceCollection().get("geometry_lines");
1416                 }
1417                 else
1418                 {
1419                         // otherwise points are processed by geometry shader
1420                         gshader = &context.getSourceCollection().get("geometry_points");
1421                 }
1422         }
1423         if (shaderStageRequired & SHADER_STAGE_FRAGMENT_BIT)
1424         {
1425                 fshader = &context.getSourceCollection().get("fragment");
1426         }
1427
1428         std::vector< de::SharedPtr<BufferOrImage> > inputBuffers(stagesCount + extraDatasCount);
1429
1430         // The implicit result SSBO we use to store our outputs from the shader
1431         for (deUint32 ndx = 0u; ndx < stagesCount; ++ndx)
1432         {
1433                 const deUint64 shaderSize = (stagesVector[ndx] == SHADER_STAGE_TESS_EVALUATION_BIT) ? maxWidth * 2 : maxWidth;
1434                 const deUint64 size = getFormatSizeInBytes(format) * shaderSize;
1435                 inputBuffers[ndx] = de::SharedPtr<BufferOrImage>(new Buffer(context, size));
1436
1437                 log << tcu::TestLog::Message
1438                         << "binding inputBuffers[" << ndx << "](" << inputBuffers[ndx]->getType() << ", " << inputBuffers[ndx]->getId() << " ), "
1439                         << "inputstage[" << ndx << "] = " << stagesVector[ndx] << " binding = " << getResultBinding(stagesVector[ndx])
1440                         << tcu::TestLog::EndMessage;
1441
1442                 gl.bindBufferBase(inputBuffers[ndx]->getType(), getResultBinding(stagesVector[ndx]), inputBuffers[ndx]->getId());
1443                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase(ndx, inputBuffers[ndx])");
1444         }
1445
1446         for (deUint32 ndx = stagesCount; ndx < stagesCount + extraDatasCount; ++ndx)
1447         {
1448                 const deUint32 datasNdx = ndx - stagesCount;
1449                 if (extraDatas[datasNdx].isImage)
1450                 {
1451                         inputBuffers[ndx] = de::SharedPtr<BufferOrImage>(new Image(context, static_cast<deUint32>(extraDatas[datasNdx].numElements), 1, extraDatas[datasNdx].format));
1452
1453                         // haven't implemented init for images yet
1454                         DE_ASSERT(extraDatas[datasNdx].initializeType == subgroups::SSBOData::InitializeNone);
1455                 }
1456                 else
1457                 {
1458                         const deUint64 size = getFormatSizeInBytes(extraDatas[datasNdx].format) * extraDatas[datasNdx].numElements;
1459                         inputBuffers[ndx] = de::SharedPtr<BufferOrImage>(new Buffer(context, size));
1460
1461                         glw::GLvoid *ptr = inputBuffers[ndx]->getAsBuffer()->mapBufferPtr();
1462                         initializeMemory(context.getDeqpContext(), ptr, extraDatas[datasNdx]);
1463                         inputBuffers[ndx]->getAsBuffer()->unmapBufferPtr();
1464                 }
1465
1466                 log << tcu::TestLog::Message
1467                         << "binding inputBuffers[" << ndx << "](" << inputBuffers[ndx]->getType() << ", " << inputBuffers[ndx]->getId() << " ), "
1468                         << "extrastage[" << datasNdx << "] = " << extraDatas[datasNdx].stages << " binding = " << extraDatas[datasNdx].binding
1469                         << tcu::TestLog::EndMessage;
1470
1471                 if (inputBuffers[ndx]->isImage())
1472                 {
1473                         gl.bindImageTexture(extraDatas[datasNdx].binding, inputBuffers[ndx]->getId(),
1474                                                                 0, GL_FALSE, 0, GL_READ_WRITE, extraDatas[datasNdx].format);
1475                         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture(extraDatas[datasNdx])");
1476                 } else
1477                 {
1478                         gl.bindBufferBase(inputBuffers[ndx]->getType(), extraDatas[datasNdx].binding, inputBuffers[ndx]->getId());
1479                         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase(extraDatas[datasNdx])");
1480                 }
1481         }
1482
1483         de::MovePtr<glu::ShaderProgram> pipeline(
1484                         makeGraphicsPipeline(context, shaderStageRequired, vshader, fshader, gshader, tcshader, teshader));
1485
1486         if (!pipeline->isOk())
1487         {
1488                 return tcu::TestStatus::fail("allstages graphics program build failed");
1489         }
1490
1491         {
1492                 const deUint32                                  subgroupSize                    = getSubgroupSize(context);
1493                 unsigned                                                totalIterations                 = 0u;
1494                 unsigned                                                failedIterations                = 0u;
1495                 Image                                                   resultImage                             (context, maxWidth, 1, format);
1496                 const deUint64                                  imageResultSize                 = getFormatSizeInBytes(format) * maxWidth;
1497                 vector<glw::GLubyte>                    imageBufferResult(imageResultSize);
1498
1499                 Vao vao(context);
1500                 Fbo fbo(context);
1501                 fbo.bind2D(resultImage);
1502
1503                 gl.viewport(0, 0, maxWidth, 1u);
1504                 GLU_EXPECT_NO_ERROR(gl.getError(), "viewport");
1505
1506                 for (deUint32 width = 1u; width < maxWidth; width++)
1507                 {
1508                         for (deUint32 ndx = stagesCount; ndx < stagesCount + extraDatasCount; ++ndx)
1509                         {
1510                                 // re-init the data
1511                                 if (extraDatas[ndx - stagesCount].isImage)
1512                                 {
1513                                         // haven't implemented init for images yet
1514                                         DE_ASSERT(extraDatas[ndx - stagesCount].initializeType == subgroups::SSBOData::InitializeNone);
1515                                 } else
1516                                 {
1517                                         glw::GLvoid *ptr = inputBuffers[ndx]->getAsBuffer()->mapBufferPtr();
1518                                         initializeMemory(context.getDeqpContext(), ptr, extraDatas[ndx - stagesCount]);
1519                                         inputBuffers[ndx]->getAsBuffer()->unmapBufferPtr();
1520                                 }
1521                         }
1522
1523                         totalIterations++;
1524
1525                         gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
1526                         GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor");
1527                         gl.clear(GL_COLOR_BUFFER_BIT);
1528                         GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
1529
1530                         gl.useProgram(pipeline->getProgram());
1531                         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
1532
1533                         glw::GLenum drawType;
1534                         if (shaderStageRequired & SHADER_STAGE_TESS_CONTROL_BIT)
1535                         {
1536                                 drawType = GL_PATCHES;
1537                                 gl.patchParameteri(GL_PATCH_VERTICES, 1u);
1538                                 GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameter(PATCH_VERTICES)");
1539                         } else
1540                         {
1541                                 drawType = GL_POINTS;
1542                         }
1543
1544                         gl.drawArrays(drawType, 0, width);
1545                         GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays");
1546
1547                         GLenum readFormat;
1548                         GLenum readType;
1549                         getFormatReadInfo(format, readFormat, readType);
1550
1551                         gl.readPixels(0, 0, width, 1, readFormat, readType, (GLvoid*)&imageBufferResult[0]);
1552                         GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
1553
1554                         for (deUint32 ndx = 0u; ndx < stagesCount; ++ndx)
1555                         {
1556                                 std::vector<const void*> datas;
1557                                 std::vector<Buffer *> buffersToUnmap;
1558
1559                                 if (!inputBuffers[ndx]->isImage())
1560                                 {
1561                                         glw::GLvoid * resultData = inputBuffers[ndx]->getAsBuffer()->mapBufferPtr();
1562                                         buffersToUnmap.push_back(inputBuffers[ndx]->getAsBuffer());
1563                                         // we always have our result data first
1564                                         datas.push_back(resultData);
1565                                 }
1566
1567                                 for (deUint32 index = stagesCount; index < stagesCount + extraDatasCount; ++index)
1568                                 {
1569                                         const deUint32 datasNdx = index - stagesCount;
1570                                         if ((stagesVector[ndx] & extraDatas[datasNdx].stages) && (!inputBuffers[index]->isImage()))
1571                                         {
1572                                                 glw::GLvoid * resultData = inputBuffers[index]->getAsBuffer()->mapBufferPtr();
1573                                                 buffersToUnmap.push_back(inputBuffers[index]->getAsBuffer());
1574                                                 // we always have our result data first
1575                                                 datas.push_back(resultData);
1576                                         }
1577                                 }
1578
1579                                 if (!checkResult(datas, (stagesVector[ndx] == SHADER_STAGE_TESS_EVALUATION_BIT) ? width * 2 : width , subgroupSize))
1580                                         failedIterations++;
1581
1582                                 while( !buffersToUnmap.empty() )
1583                                 {
1584                                         Buffer * buf = buffersToUnmap.back();
1585                                         buf->unmapBufferPtr();
1586                                         buffersToUnmap.pop_back();
1587                                 }
1588                         }
1589                         if (shaderStageTested & SHADER_STAGE_FRAGMENT_BIT)
1590                         {
1591                                 std::vector<const void*> datas;
1592                                 std::vector<Buffer *> buffersToUnmap;
1593
1594                                 // we always have our result data first
1595                                 datas.push_back(&imageBufferResult[0]);
1596
1597                                 for (deUint32 index = stagesCount; index < stagesCount + extraDatasCount; ++index)
1598                                 {
1599                                         const deUint32 datasNdx = index - stagesCount;
1600                                         if (SHADER_STAGE_FRAGMENT_BIT & extraDatas[datasNdx].stages && (!inputBuffers[index]->isImage()))
1601                                         {
1602                                                 glw::GLvoid * resultData = inputBuffers[index]->getAsBuffer()->mapBufferPtr();
1603                                                 buffersToUnmap.push_back(inputBuffers[index]->getAsBuffer());
1604                                                 // we always have our result data first
1605                                                 datas.push_back(resultData);
1606                                         }
1607                                 }
1608
1609                                 if (!checkResult(datas, width , subgroupSize))
1610                                         failedIterations++;
1611
1612                                 while( !buffersToUnmap.empty() )
1613                                 {
1614                                         Buffer * buf = buffersToUnmap.back();
1615                                         buf->unmapBufferPtr();
1616                                         buffersToUnmap.pop_back();
1617                                 }
1618                         }
1619
1620                 }
1621
1622                 if (0 < failedIterations)
1623                 {
1624                         log             << tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
1625                                         << totalIterations << " values passed" << tcu::TestLog::EndMessage;
1626                         return tcu::TestStatus::fail("Failed!");
1627                 } else
1628                 {
1629                         log             << tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
1630                                         << totalIterations << " values passed" << tcu::TestLog::EndMessage;
1631                 }
1632         }
1633         return tcu::TestStatus::pass("OK");
1634 }
1635
1636 tcu::TestStatus glc::subgroups::makeVertexFrameBufferTest(Context& context, Format format,
1637         SSBOData* extraData, deUint32 extraDataCount,
1638         bool (*checkResult)(std::vector<const void*> datas, deUint32 width, deUint32 subgroupSize))
1639 {
1640         tcu::TestLog& log       = context.getDeqpContext().getTestContext().getLog();
1641         const glw::Functions& gl = context.getDeqpContext().getRenderContext().getFunctions();
1642
1643         const deUint32                                                  maxWidth                                = 1024u;
1644         vector<de::SharedPtr<BufferOrImage> >   inputBuffers                    (extraDataCount);
1645
1646         const GlslSource& vshader = context.getSourceCollection().get("vert");
1647         const GlslSource& fshader = context.getSourceCollection().get("fragment");
1648
1649         for (deUint32 i = 0u; i < extraDataCount; i++)
1650         {
1651                 if (extraData[i].isImage)
1652                 {
1653                         inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Image(context, static_cast<deUint32>(extraData[i].numElements), 1u, extraData[i].format));
1654
1655                         // haven't implemented init for images yet
1656                         DE_ASSERT(extraData[i].initializeType == subgroups::SSBOData::InitializeNone);
1657                 }
1658                 else
1659                 {
1660                         deUint64 size = getFormatSizeInBytes(extraData[i].format) * extraData[i].numElements;
1661                         inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Buffer(context, size, GL_UNIFORM_BUFFER));
1662
1663                         glw::GLvoid *ptr = inputBuffers[i]->getAsBuffer()->mapBufferPtr();
1664                         initializeMemory(context.getDeqpContext(), ptr, extraData[i]);
1665                         inputBuffers[i]->getAsBuffer()->unmapBufferPtr();
1666                 }
1667         }
1668
1669         for (deUint32 ndx = 0u; ndx < extraDataCount; ndx++)
1670         {
1671                 log << tcu::TestLog::Message
1672                         << "binding inputBuffers[" << ndx << "](" << inputBuffers[ndx]->getType() << ", " << inputBuffers[ndx]->getId() << " ), "
1673                         << "VERTEX, binding = " << extraData[ndx].binding << "\n"
1674                         << tcu::TestLog::EndMessage;
1675
1676                 if (inputBuffers[ndx]->isImage())
1677                 {
1678                         gl.bindImageTexture(extraData[ndx].binding, inputBuffers[ndx]->getId(),
1679                                                                 0, GL_FALSE, 0, GL_READ_ONLY, extraData[ndx].format);
1680                         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture()");
1681                 } else
1682                 {
1683                         gl.bindBufferBase(inputBuffers[ndx]->getType(), extraData[ndx].binding, inputBuffers[ndx]->getId());
1684                         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase()");
1685                 }
1686         }
1687
1688         de::MovePtr<glu::ShaderProgram> pipeline(
1689                         makeGraphicsPipeline(context, (ShaderStageFlags)(SHADER_STAGE_VERTEX_BIT | SHADER_STAGE_FRAGMENT_BIT),
1690                                                                  &vshader, &fshader, DE_NULL, DE_NULL, DE_NULL));
1691
1692         if (!pipeline->isOk())
1693         {
1694                 return tcu::TestStatus::fail("vert graphics program build failed");
1695         }
1696
1697         const deUint32                                                  subgroupSize                    = getSubgroupSize(context);
1698
1699         const deUint64                                                  vertexBufferSize                = maxWidth * sizeof(tcu::Vec4);
1700         Buffer                                                                  vertexBuffer                    (context, vertexBufferSize, GL_ARRAY_BUFFER);
1701
1702         unsigned                                                                totalIterations                 = 0u;
1703         unsigned                                                                failedIterations                = 0u;
1704
1705         Image                                                                   discardableImage                (context, maxWidth, 1u, format);
1706
1707         {
1708                 glw::GLvoid *                   bufferPtr                       = vertexBuffer.mapBufferPtr();
1709                 std::vector<tcu::Vec4>  data                            (maxWidth, tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
1710                 const float                             pixelSize                       = 2.0f / static_cast<float>(maxWidth);
1711                 float                                   leftHandPosition        = -1.0f;
1712
1713                 for(deUint32 ndx = 0u; ndx < maxWidth; ++ndx)
1714                 {
1715                         data[ndx][0] = leftHandPosition + pixelSize / 2.0f;
1716                         leftHandPosition += pixelSize;
1717                 }
1718
1719                 deMemcpy(bufferPtr, &data[0], maxWidth * sizeof(tcu::Vec4));
1720                 vertexBuffer.unmapBufferPtr();
1721         }
1722
1723         Vao vao(context);
1724         Fbo fbo(context);
1725         fbo.bind2D(discardableImage);
1726
1727         gl.viewport(0, 0, maxWidth, 1u);
1728         GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport");
1729
1730         for (deUint32 width = 1u; width < maxWidth; width++)
1731         {
1732                 totalIterations++;
1733                 const deUint64                          imageResultSize         = getFormatSizeInBytes(format) * maxWidth;
1734                 vector<glw::GLubyte>            imageBufferResult(imageResultSize);
1735                 const deUint64                          vertexBufferOffset      = 0u;
1736
1737                 for (deUint32 ndx = 0u; ndx < inputBuffers.size(); ndx++)
1738                 {
1739                         if (inputBuffers[ndx]->isImage())
1740                         {
1741                                 DE_ASSERT(extraData[ndx].initializeType == subgroups::SSBOData::InitializeNone);
1742                         } else
1743                         {
1744                                 glw::GLvoid *ptr = inputBuffers[ndx]->getAsBuffer()->mapBufferPtr();
1745                                 initializeMemory(context.getDeqpContext(), ptr, extraData[ndx]);
1746                                 inputBuffers[ndx]->getAsBuffer()->unmapBufferPtr();
1747                         }
1748                 }
1749
1750                 {
1751                         gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
1752                         GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor");
1753                         gl.clear(GL_COLOR_BUFFER_BIT);
1754                         GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
1755
1756                         gl.useProgram(pipeline->getProgram());
1757                         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
1758
1759                         gl.enableVertexAttribArray(0);
1760                         GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
1761
1762                         gl.bindBuffer(GL_ARRAY_BUFFER, vertexBuffer.getId());
1763                         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
1764
1765                         gl.vertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(tcu::Vec4), vertexBufferOffset);
1766                         GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
1767
1768                         gl.drawArrays(GL_POINTS, 0, width);
1769                         GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays");
1770
1771                         gl.disableVertexAttribArray(0);
1772                         GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray");
1773
1774                         GLenum readFormat;
1775                         GLenum readType;
1776                         getFormatReadInfo(format, readFormat, readType);
1777
1778                         gl.readPixels(0, 0, width, 1, readFormat, readType, (GLvoid*)&imageBufferResult[0]);
1779                         GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
1780                 }
1781
1782                 {
1783                         std::vector<const void*> datas;
1784                         datas.push_back(&imageBufferResult[0]);
1785                         if (!checkResult(datas, width, subgroupSize))
1786                                 failedIterations++;
1787                 }
1788         }
1789
1790         if (0 < failedIterations)
1791         {
1792                 log     << tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
1793                         << totalIterations << " values passed" << tcu::TestLog::EndMessage;
1794                 return tcu::TestStatus::fail("Failed!");
1795         } else
1796         {
1797                 log     << tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
1798                                 <<totalIterations << " values passed" << tcu::TestLog::EndMessage;
1799         }
1800
1801         return tcu::TestStatus::pass("OK");
1802 }
1803
1804
1805 tcu::TestStatus glc::subgroups::makeFragmentFrameBufferTest     (Context& context, Format format, SSBOData* extraDatas,
1806         deUint32 extraDatasCount,
1807         bool (*checkResult)(std::vector<const void*> datas, deUint32 width,
1808                                                 deUint32 height, deUint32 subgroupSize))
1809 {
1810         tcu::TestLog& log       = context.getDeqpContext().getTestContext().getLog();
1811         const glw::Functions& gl = context.getDeqpContext().getRenderContext().getFunctions();
1812
1813         const GlslSource& vshader = context.getSourceCollection().get("vert");
1814         const GlslSource& fshader = context.getSourceCollection().get("fragment");
1815
1816         std::vector< de::SharedPtr<BufferOrImage> > inputBuffers(extraDatasCount);
1817
1818         for (deUint32 i = 0; i < extraDatasCount; i++)
1819         {
1820                 if (extraDatas[i].isImage)
1821                 {
1822                         inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Image(context,
1823                                                                                 static_cast<deUint32>(extraDatas[i].numElements), 1, extraDatas[i].format));
1824
1825                         // haven't implemented init for images yet
1826                         DE_ASSERT(extraDatas[i].initializeType == subgroups::SSBOData::InitializeNone);
1827                 }
1828                 else
1829                 {
1830                         deUint64 size =
1831                                 getFormatSizeInBytes(extraDatas[i].format) * extraDatas[i].numElements;
1832                         inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Buffer(context, size, GL_UNIFORM_BUFFER));
1833
1834                         glw::GLvoid *ptr = inputBuffers[i]->getAsBuffer()->mapBufferPtr();
1835                         initializeMemory(context.getDeqpContext(), ptr, extraDatas[i]);
1836                         inputBuffers[i]->getAsBuffer()->unmapBufferPtr();
1837                 }
1838         }
1839
1840         for (deUint32 i = 0; i < extraDatasCount; i++)
1841         {
1842                 log << tcu::TestLog::Message
1843                         << "binding inputBuffers[" << i << "](" << inputBuffers[i]->getType() << ", " << inputBuffers[i]->getId() << " ), "
1844                         << "FRAGMENT, binding = " << extraDatas[i].binding << "\n"
1845                         << tcu::TestLog::EndMessage;
1846
1847                 if (inputBuffers[i]->isImage())
1848                 {
1849                         gl.bindImageTexture(extraDatas[i].binding, inputBuffers[i]->getId(),
1850                                                                 0, GL_FALSE, 0, GL_READ_ONLY, extraDatas[i].format);
1851                         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture()");
1852                 } else
1853                 {
1854                         gl.bindBufferBase(inputBuffers[i]->getType(), extraDatas[i].binding, inputBuffers[i]->getId());
1855                         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase()");
1856                 }
1857         }
1858
1859         de::MovePtr<glu::ShaderProgram> pipeline(
1860                         makeGraphicsPipeline(context, (ShaderStageFlags)(SHADER_STAGE_VERTEX_BIT | SHADER_STAGE_FRAGMENT_BIT),
1861                                                                  &vshader, &fshader, DE_NULL, DE_NULL, DE_NULL));
1862
1863         if (!pipeline->isOk())
1864         {
1865                 return tcu::TestStatus::fail("frag graphics program build failed");
1866         }
1867
1868         const deUint32 subgroupSize = getSubgroupSize(context);
1869
1870         unsigned totalIterations = 0;
1871         unsigned failedIterations = 0;
1872
1873         Vao vao(context);
1874         Fbo fbo(context);
1875
1876         for (deUint32 width = 8; width <= subgroupSize; width *= 2)
1877         {
1878                 for (deUint32 height = 8; height <= subgroupSize; height *= 2)
1879                 {
1880                         totalIterations++;
1881
1882                         // re-init the data
1883                         for (deUint32 i = 0; i < extraDatasCount; i++)
1884                         {
1885                                 if (inputBuffers[i]->isImage())
1886                                 {
1887                                         DE_ASSERT(extraDatas[i].initializeType == subgroups::SSBOData::InitializeNone);
1888                                 } else
1889                                 {
1890                                         glw::GLvoid *ptr = inputBuffers[i]->getAsBuffer()->mapBufferPtr();
1891                                         initializeMemory(context.getDeqpContext(), ptr, extraDatas[i]);
1892                                         inputBuffers[i]->getAsBuffer()->unmapBufferPtr();
1893                                 }
1894                         }
1895
1896                         deUint64 formatSize = getFormatSizeInBytes(format);
1897                         const deUint64 resultImageSizeInBytes =
1898                                 width * height * formatSize;
1899
1900                         Image resultImage(context, width, height, format);
1901
1902                         vector<glw::GLubyte>  resultBuffer(resultImageSizeInBytes);
1903
1904                         fbo.bind2D(resultImage);
1905
1906                         gl.viewport(0, 0, width, height);
1907                         GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport");
1908
1909                         gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
1910                         GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor");
1911                         gl.clear(GL_COLOR_BUFFER_BIT);
1912                         GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
1913
1914                         gl.useProgram(pipeline->getProgram());
1915                         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
1916
1917                         gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
1918                         GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays");
1919
1920                         GLenum readFormat;
1921                         GLenum readType;
1922                         getFormatReadInfo(format, readFormat, readType);
1923
1924                         gl.readPixels(0, 0, width, height, readFormat, readType, (GLvoid*)&resultBuffer[0]);
1925                         GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
1926
1927                         std::vector<const void*> datas;
1928                         {
1929                                 // we always have our result data first
1930                                 datas.push_back(&resultBuffer[0]);
1931                         }
1932
1933                         if (!checkResult(datas, width, height, subgroupSize))
1934                         {
1935                                 failedIterations++;
1936                         }
1937                 }
1938         }
1939
1940         if (0 < failedIterations)
1941         {
1942                 log             << tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
1943                                 << totalIterations << " values passed" << tcu::TestLog::EndMessage;
1944                 return tcu::TestStatus::fail("Failed!");
1945         } else
1946         {
1947                 log             << tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
1948                                 <<totalIterations << " values passed" << tcu::TestLog::EndMessage;
1949         }
1950         return tcu::TestStatus::pass("OK");
1951 }
1952
1953 tcu::TestStatus glc::subgroups::makeComputeTest(
1954         Context& context, Format format, SSBOData* inputs, deUint32 inputsCount,
1955         bool (*checkResult)(std::vector<const void*> datas,
1956                                                 const deUint32 numWorkgroups[3], const deUint32 localSize[3],
1957                                                 deUint32 subgroupSize))
1958 {
1959         const glw::Functions& gl = context.getDeqpContext().getRenderContext().getFunctions();
1960         deUint64 elementSize = getFormatSizeInBytes(format);
1961
1962         const deUint64 resultBufferSize = maxSupportedSubgroupSize() *
1963                                                                                   maxSupportedSubgroupSize() *
1964                                                                                   maxSupportedSubgroupSize();
1965         const deUint64 resultBufferSizeInBytes = resultBufferSize * elementSize;
1966
1967         Buffer resultBuffer(
1968                 context, resultBufferSizeInBytes);
1969
1970         std::vector< de::SharedPtr<BufferOrImage> > inputBuffers(inputsCount);
1971
1972         for (deUint32 i = 0; i < inputsCount; i++)
1973         {
1974                 if (inputs[i].isImage)
1975                 {
1976                         inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Image(context,
1977                                                                                 static_cast<deUint32>(inputs[i].numElements), 1, inputs[i].format));
1978                         // haven't implemented init for images yet
1979                         DE_ASSERT(inputs[i].initializeType == subgroups::SSBOData::InitializeNone);
1980                 }
1981                 else
1982                 {
1983                         deUint64 size =
1984                                 getFormatSizeInBytes(inputs[i].format) * inputs[i].numElements;
1985                         inputBuffers[i] = de::SharedPtr<BufferOrImage>(new Buffer(context, size));
1986
1987                         glw::GLvoid *ptr = inputBuffers[i]->getAsBuffer()->mapBufferPtr();
1988                         initializeMemory(context.getDeqpContext(), ptr, inputs[i]);
1989                         inputBuffers[i]->getAsBuffer()->unmapBufferPtr();
1990                 }
1991
1992         }
1993
1994         tcu::TestLog& log       = context.getDeqpContext().getTestContext().getLog();
1995         log << tcu::TestLog::Message
1996                 << "binding resultbuffer(type=" << resultBuffer.getType()
1997                 << ", id=" << resultBuffer.getId() << ", binding=0), COMPUTE"
1998                 << tcu::TestLog::EndMessage;
1999
2000         gl.bindBufferBase(resultBuffer.getType(), 0, resultBuffer.getId());
2001         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase(0, resultBuffer)");
2002
2003         for (deUint32 i = 0; i < inputsCount; i++)
2004         {
2005                 log << tcu::TestLog::Message
2006                         << "binding inputBuffers[" << i << "](type=" << inputBuffers[i]->getType()
2007                         << ", id=" << inputBuffers[i]->getId() << ", binding="
2008                         << inputs[i].binding << "), 1, COMPUTE"
2009                         << tcu::TestLog::EndMessage;
2010
2011                 if (inputBuffers[i]->isImage())
2012                 {
2013                         gl.bindImageTexture(inputs[i].binding, inputBuffers[i]->getId(),
2014                                                                 0, GL_FALSE, 0, GL_READ_WRITE, inputs[i].format);
2015                         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture(inputBuffer[i]");
2016                 } else
2017                 {
2018                         gl.bindBufferBase(inputBuffers[i]->getType(), inputs[i].binding, inputBuffers[i]->getId());
2019                         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase(inputBuffer[i])");
2020                 }
2021         }
2022
2023         const GlslSource &cshader = context.getSourceCollection().get("comp");
2024
2025         unsigned totalIterations = 0;
2026         unsigned failedIterations = 0;
2027
2028         const deUint32 subgroupSize = getSubgroupSize(context);
2029
2030         const deUint32 numWorkgroups[3] = {4, 2, 2};
2031
2032         const deUint32 localSizesToTestCount = 15;
2033         deUint32 localSizesToTest[localSizesToTestCount][3] =
2034         {
2035                 {1, 1, 1},
2036                 {32, 4, 1},
2037                 {32, 1, 4},
2038                 {1, 32, 4},
2039                 {1, 4, 32},
2040                 {4, 1, 32},
2041                 {4, 32, 1},
2042                 {subgroupSize, 1, 1},
2043                 {1, subgroupSize, 1},
2044                 {1, 1, subgroupSize},
2045                 {3, 5, 7},
2046                 {128, 1, 1},
2047                 {1, 128, 1},
2048                 {1, 1, 64},
2049                 {1, 1, 1} // Isn't used, just here to make double buffering checks easier
2050         };
2051
2052
2053         de::MovePtr<glu::ShaderProgram> lastPipeline(
2054                 makeComputePipeline(context, cshader,
2055                                                         localSizesToTest[0][0], localSizesToTest[0][1], localSizesToTest[0][2]));
2056
2057         for (deUint32 index = 0; index < (localSizesToTestCount - 1); index++)
2058         {
2059                 const deUint32 nextX = localSizesToTest[index + 1][0];
2060                 const deUint32 nextY = localSizesToTest[index + 1][1];
2061                 const deUint32 nextZ = localSizesToTest[index + 1][2];
2062
2063                 // we are running one test
2064                 totalIterations++;
2065
2066                 if (!lastPipeline->isOk())
2067                 {
2068                         return tcu::TestStatus::fail("compute shaders build failed");
2069                 }
2070
2071                 gl.useProgram(lastPipeline->getProgram());
2072                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
2073
2074                 gl.dispatchCompute(numWorkgroups[0], numWorkgroups[1], numWorkgroups[2]);
2075                 GLU_EXPECT_NO_ERROR(gl.getError(), "glDispatchCompute");
2076
2077                 de::MovePtr<glu::ShaderProgram> nextPipeline(
2078                         makeComputePipeline(context, cshader, nextX, nextY, nextZ));
2079
2080                 std::vector<const void*> datas;
2081
2082                 {
2083                         glw::GLvoid * resultData = resultBuffer.mapBufferPtr();
2084
2085                         // we always have our result data first
2086                         datas.push_back(resultData);
2087                 }
2088
2089                 for (deUint32 i = 0; i < inputsCount; i++)
2090                 {
2091                         if (!inputBuffers[i]->isImage())
2092                         {
2093                                 glw::GLvoid *resultData = inputBuffers[i]->getAsBuffer()->mapBufferPtr();
2094
2095                                 // we always have our result data first
2096                                 datas.push_back(resultData);
2097                         }
2098                 }
2099
2100                 if (!checkResult(datas, numWorkgroups, localSizesToTest[index], subgroupSize))
2101                 {
2102                         failedIterations++;
2103                 }
2104
2105                 resultBuffer.unmapBufferPtr();
2106                 for (deUint32 i = 0; i < inputsCount; i++)
2107                 {
2108                         if (!inputBuffers[i]->isImage())
2109                         {
2110                                 inputBuffers[i]->getAsBuffer()->unmapBufferPtr();
2111                         }
2112                 }
2113
2114                 lastPipeline = nextPipeline;
2115         }
2116
2117         if (0 < failedIterations)
2118         {
2119                 log             << tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
2120                                 << totalIterations << " values passed" << tcu::TestLog::EndMessage;
2121                 return tcu::TestStatus::fail("Failed!");
2122         } else
2123         {
2124                 log             << tcu::TestLog::Message << (totalIterations - failedIterations) << " / "
2125                                 << totalIterations << " values passed" << tcu::TestLog::EndMessage;
2126         }
2127
2128         return tcu::TestStatus::pass("OK");
2129 }