porting changes for OpenGL Subgroup tests
[platform/upstream/VK-GL-CTS.git] / external / openglcts / modules / common / subgroups / glcSubgroupsTestsUtils.hpp
1 #ifndef _GLCSUBGROUPSTESTSUTILS_HPP
2 #define _GLCSUBGROUPSTESTSUTILS_HPP
3 /*------------------------------------------------------------------------
4  * OpenGL Conformance Tests
5  * ------------------------
6  *
7  * Copyright (c) 2017-2019 The Khronos Group Inc.
8  * Copyright (c) 2017 Codeplay Software Ltd.
9  * Copyright (c) 2019 NVIDIA Corporation.
10  *
11  * Licensed under the Apache License, Version 2.0 (the "License");
12  * you may not use this file except in compliance with the License.
13  * You may obtain a copy of the License at
14  *
15  *      http://www.apache.org/licenses/LICENSE-2.0
16  *
17  * Unless required by applicable law or agreed to in writing, software
18  * distributed under the License is distributed on an "AS IS" BASIS,
19  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  * See the License for the specific language governing permissions and
21  * limitations under the License.
22  *
23  */ /*!
24  * \file
25  * \brief Subgroups tests utility classes
26  */ /*--------------------------------------------------------------------*/
27
28 #include "deDefs.hpp"
29 #include "deSTLUtil.hpp"
30 #include "deStringUtil.hpp"
31 #include "glwEnums.hpp"
32 #include "glwFunctions.hpp"
33 #include "glwDefs.hpp"
34 #include "tcuDefs.hpp"
35 #include "tcuTestCase.hpp"
36 #include "glcTestCase.hpp"
37 #include "glcSpirvUtils.hpp"
38
39 #include "tcuFormatUtil.hpp"
40 #include "tcuTestLog.hpp"
41 #include "tcuVectorUtil.hpp"
42
43 #include "gluShaderUtil.hpp"
44 #include "gluContextInfo.hpp"
45
46 #include "deSharedPtr.hpp"
47 #include "deUniquePtr.hpp"
48
49 #include <string>
50
51 namespace glc
52 {
53
54 enum ShaderType
55 {
56         SHADER_TYPE_GLSL = 0,
57         SHADER_TYPE_SPIRV,
58
59         SHADER_TYPE_LAST
60 };
61
62 template<typename Program>
63 class ProgramCollection
64 {
65 public:
66                                                                 ProgramCollection       (void);
67                                                                 ~ProgramCollection      (void);
68
69         void                                            clear                           (void);
70
71         Program&                                        add                                     (const std::string& name);
72         void                                            add                                     (const std::string& name, de::MovePtr<Program>& program);
73
74         bool                                            contains                        (const std::string& name) const;
75         const Program&                          get                                     (const std::string& name) const;
76
77         class Iterator
78         {
79         private:
80                 typedef typename std::map<std::string, Program*>::const_iterator        IteratorImpl;
81
82         public:
83                 explicit                        Iterator        (const IteratorImpl& i) : m_impl(i) {}
84
85                 Iterator&                       operator++      (void)                  { ++m_impl; return *this;       }
86                 const Program&          operator*       (void) const    { return getProgram();          }
87
88                 const std::string&      getName         (void) const    { return m_impl->first;         }
89                 const Program&          getProgram      (void) const    { return *m_impl->second;       }
90
91                 bool                            operator==      (const Iterator& other) const   { return m_impl == other.m_impl;        }
92                 bool                            operator!=      (const Iterator& other) const   { return m_impl != other.m_impl;        }
93
94         private:
95
96                 IteratorImpl    m_impl;
97         };
98
99         Iterator                                        begin                           (void) const { return Iterator(m_programs.begin());     }
100         Iterator                                        end                                     (void) const { return Iterator(m_programs.end());       }
101
102         bool                                            empty                           (void) const { return m_programs.empty();                       }
103
104 private:
105         typedef std::map<std::string, Program*> ProgramMap;
106
107         ProgramMap                                      m_programs;
108 };
109
110 template<typename Program>
111 ProgramCollection<Program>::ProgramCollection (void)
112 {
113 }
114
115 template<typename Program>
116 ProgramCollection<Program>::~ProgramCollection (void)
117 {
118         clear();
119 }
120
121 template<typename Program>
122 void ProgramCollection<Program>::clear (void)
123 {
124         for (typename ProgramMap::const_iterator i = m_programs.begin(); i != m_programs.end(); ++i)
125                 delete i->second;
126         m_programs.clear();
127 }
128
129 template<typename Program>
130 Program& ProgramCollection<Program>::add (const std::string& name)
131 {
132         DE_ASSERT(!contains(name));
133         de::MovePtr<Program> prog = de::newMovePtr<Program>();
134         m_programs[name] = prog.get();
135         prog.release();
136         return *m_programs[name];
137 }
138
139 template<typename Program>
140 void ProgramCollection<Program>::add (const std::string& name, de::MovePtr<Program>& program)
141 {
142         DE_ASSERT(!contains(name));
143         m_programs[name] = program.get();
144         program.release();
145 }
146
147 template<typename Program>
148 bool ProgramCollection<Program>::contains (const std::string& name) const
149 {
150         return de::contains(m_programs, name);
151 }
152
153 template<typename Program>
154 const Program& ProgramCollection<Program>::get (const std::string& name) const
155 {
156         DE_ASSERT(contains(name));
157         return *m_programs.find(name)->second;
158 }
159
160 struct GlslSource
161 {
162         std::vector<std::string>        sources[glu::SHADERTYPE_LAST];
163
164         GlslSource&                                     operator<< (const glu::ShaderSource& shaderSource)
165         {
166                 sources[shaderSource.shaderType].push_back(shaderSource.source);
167                 return *this;
168         }
169 };
170
171 typedef ProgramCollection<GlslSource>           SourceCollections;
172
173
174 class Context
175 {
176 public:
177         Context (deqp::Context& deqpCtx)
178                 : m_deqpCtx(deqpCtx)
179                 , m_sourceCollection()
180                 , m_glslVersion(glu::getContextTypeGLSLVersion(m_deqpCtx.getRenderContext().getType()))
181                 , m_shaderType(SHADER_TYPE_GLSL)
182                 {}
183         ~Context (void) {}
184         deqp::Context&                  getDeqpContext          (void) const { return m_deqpCtx; }
185         SourceCollections&              getSourceCollection (void) { return m_sourceCollection; }
186         glu::GLSLVersion                getGLSLVersion          (void) { return m_glslVersion; }
187         ShaderType                              getShaderType           (void) { return m_shaderType; }
188         void                                    setShaderType           (ShaderType type) { m_shaderType = type; }
189
190 protected:
191         deqp::Context&          m_deqpCtx;
192         SourceCollections       m_sourceCollection;
193         glu::GLSLVersion        m_glslVersion;
194         ShaderType                      m_shaderType;
195 };
196
197 namespace subgroups
198 {
199
200 template<typename Arg0>
201 class SubgroupFactory : public deqp::TestCase
202 {
203 public:
204         //void initPrograms(SourceCollections& programCollection, CaseDefinition caseDef)
205         typedef void (*InitFunction)(SourceCollections& programCollection, Arg0 arg0);
206         //void supportedCheck (Context& context, CaseDefinition caseDef)
207         typedef void (*SupportFunction)(Context& context, Arg0 arg0);
208         //tcu::TestStatus test(Context& context, const CaseDefinition caseDef)
209         typedef tcu::TestStatus (*TestFunction)(Context& context, const Arg0 arg0);
210
211         /* Public methods */
212         SubgroupFactory(deqp::Context& context, tcu::TestNodeType type, const std::string& name, const std::string& desc,
213                 SupportFunction suppFunc, InitFunction initFunc, TestFunction testFunc, Arg0 arg0)
214                 : TestCase(context, type, name.c_str(), desc.c_str())
215                 , m_supportedFunc(suppFunc)
216                 , m_initFunc(initFunc)
217                 , m_testFunc(testFunc)
218                 , m_arg0(arg0)
219                 , m_glcContext(m_context)
220         {}
221
222         void init()
223         {
224                 m_supportedFunc(m_glcContext, m_arg0);
225
226                 m_initFunc(m_glcContext.getSourceCollection(), m_arg0);
227         }
228
229         void deinit()
230         {
231                 // nothing to do
232         }
233
234         tcu::TestNode::IterateResult iterate()
235         {
236                 DE_ASSERT(m_testFunc);
237                 tcu::TestLog& log = m_testCtx.getLog();
238
239                 try {
240                         // do SPIRV version of tests if supported
241                         log << tcu::TestLog::Message << "SPIRV pass beginning..." << tcu::TestLog::EndMessage;
242                         spirvUtils::checkGlSpirvSupported(m_glcContext.getDeqpContext());
243
244                         m_glcContext.setShaderType(SHADER_TYPE_SPIRV);
245
246                         const tcu::TestStatus result = m_testFunc(m_glcContext, m_arg0);
247                         if (result.isComplete())
248                         {
249                                 DE_ASSERT(m_testCtx.getTestResult() == QP_TEST_RESULT_LAST);
250                                 if (result.getCode() == QP_TEST_RESULT_PASS)
251                                 {
252                                         log << tcu::TestLog::Message << "SPIRV pass completed successfully ("
253                                                 << result.getDescription() << ")." << tcu::TestLog::EndMessage;
254                                 } else {
255                                         // test failed - log result and stop
256                                         m_testCtx.setTestResult(result.getCode(), result.getDescription().c_str());
257                                         return tcu::TestNode::STOP;
258                                 }
259                         }
260                 } catch(tcu::NotSupportedError& e)
261                 {
262                         log << tcu::TestLog::Message << "SPIRV pass skipped ("
263                                                 << e.getMessage() << ")." << tcu::TestLog::EndMessage;
264                 }
265
266                 // do GLSL version of the tests
267                 log << tcu::TestLog::Message << "GLSL pass beginning..." << tcu::TestLog::EndMessage;
268                 m_glcContext.setShaderType(SHADER_TYPE_GLSL);
269                 const tcu::TestStatus result = m_testFunc(m_glcContext, m_arg0);
270
271                 if (result.isComplete())
272                 {
273                         DE_ASSERT(m_testCtx.getTestResult() == QP_TEST_RESULT_LAST);
274                         log << tcu::TestLog::Message << "GLSL pass completed successfully ("
275                                 << result.getDescription() << ")." << tcu::TestLog::EndMessage;
276                         m_testCtx.setTestResult(result.getCode(), result.getDescription().c_str());
277                         return tcu::TestNode::STOP;
278                 }
279
280                 return tcu::TestNode::CONTINUE;
281         }
282
283         static void addFunctionCaseWithPrograms (deqp::TestCaseGroup*                           group,
284                                                                   const std::string&                                                    name,
285                                                                   const std::string&                                                    desc,
286                                                                   SupportFunction                                                               suppFunc,
287                                                                   InitFunction                                                                  initFunc,
288                                                                   TestFunction                                                                  testFunc,
289                                                                   Arg0                                                                                  arg0)
290         {
291                 group->addChild(new SubgroupFactory(group->getContext(), tcu::NODETYPE_SELF_VALIDATE, name, desc, suppFunc, initFunc, testFunc, arg0));
292         }
293
294 private:
295         SupportFunction         m_supportedFunc;
296         InitFunction            m_initFunc;
297         TestFunction            m_testFunc;
298         Arg0                            m_arg0;
299
300         Context                         m_glcContext;
301 };
302
303
304 typedef enum ShaderStageFlags
305 {
306         SHADER_STAGE_VERTEX_BIT = GL_VERTEX_SHADER_BIT,
307         SHADER_STAGE_FRAGMENT_BIT = GL_FRAGMENT_SHADER_BIT,
308         SHADER_STAGE_GEOMETRY_BIT = GL_GEOMETRY_SHADER_BIT,
309         SHADER_STAGE_TESS_CONTROL_BIT = GL_TESS_CONTROL_SHADER_BIT,
310         SHADER_STAGE_TESS_EVALUATION_BIT = GL_TESS_EVALUATION_SHADER_BIT,
311         SHADER_STAGE_COMPUTE_BIT = GL_COMPUTE_SHADER_BIT,
312         SHADER_STAGE_ALL_GRAPHICS = (SHADER_STAGE_VERTEX_BIT | SHADER_STAGE_FRAGMENT_BIT | SHADER_STAGE_GEOMETRY_BIT |
313                                                                  SHADER_STAGE_TESS_CONTROL_BIT | SHADER_STAGE_TESS_EVALUATION_BIT ),
314         SHADER_STAGE_ALL_VALID = (SHADER_STAGE_ALL_GRAPHICS | SHADER_STAGE_COMPUTE_BIT),
315 } ShaderStageFlags;
316
317 typedef enum SubgroupFeatureFlags
318 {
319     SUBGROUP_FEATURE_BASIC_BIT = GL_SUBGROUP_FEATURE_BASIC_BIT_KHR,
320     SUBGROUP_FEATURE_VOTE_BIT = GL_SUBGROUP_FEATURE_VOTE_BIT_KHR,
321     SUBGROUP_FEATURE_ARITHMETIC_BIT = GL_SUBGROUP_FEATURE_ARITHMETIC_BIT_KHR,
322     SUBGROUP_FEATURE_BALLOT_BIT = GL_SUBGROUP_FEATURE_BALLOT_BIT_KHR,
323     SUBGROUP_FEATURE_SHUFFLE_BIT = GL_SUBGROUP_FEATURE_SHUFFLE_BIT_KHR,
324     SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT = GL_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT_KHR,
325     SUBGROUP_FEATURE_CLUSTERED_BIT = GL_SUBGROUP_FEATURE_CLUSTERED_BIT_KHR,
326     SUBGROUP_FEATURE_QUAD_BIT = GL_SUBGROUP_FEATURE_QUAD_BIT_KHR,
327     SUBGROUP_FEATURE_PARTITIONED_BIT_NV = GL_SUBGROUP_FEATURE_PARTITIONED_BIT_NV,
328         SUBGROUP_FEATURE_ALL_VALID = (SUBGROUP_FEATURE_BASIC_BIT | SUBGROUP_FEATURE_VOTE_BIT | SUBGROUP_FEATURE_ARITHMETIC_BIT |
329                                                                   SUBGROUP_FEATURE_BALLOT_BIT | SUBGROUP_FEATURE_SHUFFLE_BIT | SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT |
330                                                                   SUBGROUP_FEATURE_CLUSTERED_BIT | SUBGROUP_FEATURE_QUAD_BIT | SUBGROUP_FEATURE_QUAD_BIT |
331                                                                   SUBGROUP_FEATURE_PARTITIONED_BIT_NV),
332 } SubgroupFeatureFlags;
333
334 typedef enum Format
335 {
336         FORMAT_UNDEFINED = 0,
337         FORMAT_R32_SINT = GL_R32I,
338         FORMAT_R32_UINT = GL_R32UI,
339         FORMAT_R32G32_SINT = GL_RG32I,
340         FORMAT_R32G32_UINT = GL_RG32UI,
341         FORMAT_R32G32B32_SINT = GL_RGB32I,
342         FORMAT_R32G32B32_UINT = GL_RGB32UI,
343         FORMAT_R32G32B32A32_SINT = GL_RGBA32I,
344         FORMAT_R32G32B32A32_UINT = GL_RGBA32UI,
345         FORMAT_R32_SFLOAT = GL_R32F,
346         FORMAT_R32G32_SFLOAT = GL_RG32F,
347         FORMAT_R32G32B32_SFLOAT = GL_RGB32F,
348         FORMAT_R32G32B32A32_SFLOAT = GL_RGBA32F,
349         FORMAT_R64_SFLOAT = 0x6000,
350         FORMAT_R64G64_SFLOAT,
351         FORMAT_R64G64B64_SFLOAT,
352         FORMAT_R64G64B64A64_SFLOAT,
353         FORMAT_R32_BOOL = 0x6100,
354         FORMAT_R32G32_BOOL,
355         FORMAT_R32G32B32_BOOL,
356         FORMAT_R32G32B32A32_BOOL,
357 } Format;
358
359 typedef enum DescriptorType
360 {
361         DESCRIPTOR_TYPE_UNIFORM_BUFFER = GL_UNIFORM_BUFFER,
362         DESCRIPTOR_TYPE_STORAGE_BUFFER = GL_SHADER_STORAGE_BUFFER,
363         DESCRIPTOR_TYPE_STORAGE_IMAGE  = GL_TEXTURE_2D,
364 } DescriptorType;
365
366 // A struct to represent input data to a shader
367 struct SSBOData
368 {
369         SSBOData() :
370                 initializeType  (InitializeNone),
371                 format                  (FORMAT_UNDEFINED),
372                 numElements             (0),
373                 isImage                 (false),
374                 binding                 (0u),
375                 stages                  ((ShaderStageFlags)0u)
376         {}
377
378         enum InputDataInitializeType
379         {
380                 InitializeNone = 0,
381                 InitializeNonZero,
382                 InitializeZero,
383         } initializeType;
384
385         Format                                          format;
386         deUint64                                        numElements;
387         bool                                            isImage;
388         deUint32                                        binding;
389         ShaderStageFlags                        stages;
390 };
391
392 std::string getSharedMemoryBallotHelper();
393
394 deUint32 getSubgroupSize(Context& context);
395
396 deUint32 maxSupportedSubgroupSize();
397
398 std::string getShaderStageName(ShaderStageFlags stage);
399
400 std::string getSubgroupFeatureName(SubgroupFeatureFlags bit);
401
402 void addNoSubgroupShader (SourceCollections& programCollection);
403
404 std::string getVertShaderForStage(ShaderStageFlags stage);
405
406 bool isSubgroupSupported(Context& context);
407
408 bool areSubgroupOperationsSupportedForStage(
409         Context& context, ShaderStageFlags stage);
410
411 bool areSubgroupOperationsRequiredForStage(ShaderStageFlags stage);
412
413 bool isSubgroupFeatureSupportedForDevice(Context& context, SubgroupFeatureFlags bit);
414
415 bool isFragmentSSBOSupportedForDevice(Context& context);
416
417 bool isVertexSSBOSupportedForDevice(Context& context);
418
419 bool isDoubleSupportedForDevice(Context& context);
420
421 bool isDoubleFormat(Format format);
422
423 std::string getFormatNameForGLSL(Format format);
424
425 void addGeometryShadersFromTemplate (const std::string& glslTemplate, SourceCollections& collection);
426
427 void setVertexShaderFrameBuffer (SourceCollections& programCollection);
428
429 void setFragmentShaderFrameBuffer (SourceCollections& programCollection);
430
431 void setFragmentShaderFrameBuffer (SourceCollections& programCollection);
432
433 void setTesCtrlShaderFrameBuffer (SourceCollections& programCollection);
434
435 void setTesEvalShaderFrameBuffer (SourceCollections& programCollection);
436
437 bool check(std::vector<const void*> datas,
438         deUint32 width, deUint32 ref);
439
440 bool checkCompute(std::vector<const void*> datas,
441         const deUint32 numWorkgroups[3], const deUint32 localSize[3],
442         deUint32 ref);
443
444 tcu::TestStatus makeTessellationEvaluationFrameBufferTest(Context& context, Format format,
445         SSBOData* extraData, deUint32 extraDataCount,
446         bool (*checkResult)(std::vector<const void*> datas, deUint32 width, deUint32 subgroupSize),
447         const ShaderStageFlags shaderStage = SHADER_STAGE_ALL_GRAPHICS);
448
449 tcu::TestStatus makeGeometryFrameBufferTest(Context& context, Format format, SSBOData* extraData,
450         deUint32 extraDataCount,
451         bool (*checkResult)(std::vector<const void*> datas, deUint32 width, deUint32 subgroupSize));
452
453 tcu::TestStatus allStages(Context& context, Format format,
454         SSBOData* extraData, deUint32 extraDataCount,
455         bool (*checkResult)(std::vector<const void*> datas, deUint32 width, deUint32 subgroupSize),
456         const ShaderStageFlags shaderStage);
457
458 tcu::TestStatus makeVertexFrameBufferTest(Context& context, Format format,
459         SSBOData* extraData, deUint32 extraDataCount,
460         bool (*checkResult)(std::vector<const void*> datas, deUint32 width, deUint32 subgroupSize));
461
462 tcu::TestStatus makeFragmentFrameBufferTest(Context& context, Format format,
463         SSBOData* extraData, deUint32 extraDataCount,
464         bool (*checkResult)(std::vector<const void*> datas, deUint32 width,
465                                                                          deUint32 height, deUint32 subgroupSize));
466
467 tcu::TestStatus makeComputeTest(
468         Context& context, Format format, SSBOData* inputs,
469         deUint32 inputsCount,
470         bool (*checkResult)(std::vector<const void*> datas,
471                 const deUint32 numWorkgroups[3], const deUint32 localSize[3],
472                 deUint32 subgroupSize));
473 } // subgroups
474 } // glc
475
476 #endif // _GLCSUBGROUPSTESTSUTILS_HPP