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