xref: /aosp_15_r20/external/deqp/external/openglcts/modules/common/subgroups/glcSubgroupsTestsUtils.hpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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:
Iterator(const IteratorImpl & i)83         explicit Iterator(const IteratorImpl &i) : m_impl(i)
84         {
85         }
86 
operator ++(void)87         Iterator &operator++(void)
88         {
89             ++m_impl;
90             return *this;
91         }
operator *(void) const92         const Program &operator*(void) const
93         {
94             return getProgram();
95         }
96 
getName(void) const97         const std::string &getName(void) const
98         {
99             return m_impl->first;
100         }
getProgram(void) const101         const Program &getProgram(void) const
102         {
103             return *m_impl->second;
104         }
105 
operator ==(const Iterator & other) const106         bool operator==(const Iterator &other) const
107         {
108             return m_impl == other.m_impl;
109         }
operator !=(const Iterator & other) const110         bool operator!=(const Iterator &other) const
111         {
112             return m_impl != other.m_impl;
113         }
114 
115     private:
116         IteratorImpl m_impl;
117     };
118 
begin(void) const119     Iterator begin(void) const
120     {
121         return Iterator(m_programs.begin());
122     }
end(void) const123     Iterator end(void) const
124     {
125         return Iterator(m_programs.end());
126     }
127 
empty(void) const128     bool empty(void) const
129     {
130         return m_programs.empty();
131     }
132 
133 private:
134     typedef std::map<std::string, Program *> ProgramMap;
135 
136     ProgramMap m_programs;
137 };
138 
139 template <typename Program>
ProgramCollection(void)140 ProgramCollection<Program>::ProgramCollection(void)
141 {
142 }
143 
144 template <typename Program>
~ProgramCollection(void)145 ProgramCollection<Program>::~ProgramCollection(void)
146 {
147     clear();
148 }
149 
150 template <typename Program>
clear(void)151 void ProgramCollection<Program>::clear(void)
152 {
153     for (typename ProgramMap::const_iterator i = m_programs.begin(); i != m_programs.end(); ++i)
154         delete i->second;
155     m_programs.clear();
156 }
157 
158 template <typename Program>
add(const std::string & name)159 Program &ProgramCollection<Program>::add(const std::string &name)
160 {
161     DE_ASSERT(!contains(name));
162     de::MovePtr<Program> prog = de::newMovePtr<Program>();
163     m_programs[name]          = prog.get();
164     prog.release();
165     return *m_programs[name];
166 }
167 
168 template <typename Program>
add(const std::string & name,de::MovePtr<Program> & program)169 void ProgramCollection<Program>::add(const std::string &name, de::MovePtr<Program> &program)
170 {
171     DE_ASSERT(!contains(name));
172     m_programs[name] = program.get();
173     program.release();
174 }
175 
176 template <typename Program>
contains(const std::string & name) const177 bool ProgramCollection<Program>::contains(const std::string &name) const
178 {
179     return de::contains(m_programs, name);
180 }
181 
182 template <typename Program>
get(const std::string & name) const183 const Program &ProgramCollection<Program>::get(const std::string &name) const
184 {
185     DE_ASSERT(contains(name));
186     return *m_programs.find(name)->second;
187 }
188 
189 struct GlslSource
190 {
191     std::vector<std::string> sources[glu::SHADERTYPE_LAST];
192 
operator <<glc::GlslSource193     GlslSource &operator<<(const glu::ShaderSource &shaderSource)
194     {
195         sources[shaderSource.shaderType].push_back(shaderSource.source);
196         return *this;
197     }
198 };
199 
200 typedef ProgramCollection<GlslSource> SourceCollections;
201 
202 class Context
203 {
204 public:
Context(deqp::Context & deqpCtx)205     Context(deqp::Context &deqpCtx)
206         : m_deqpCtx(deqpCtx)
207         , m_sourceCollection()
208         , m_glslVersion(glu::getContextTypeGLSLVersion(m_deqpCtx.getRenderContext().getType()))
209         , m_shaderType(SHADER_TYPE_GLSL)
210     {
211     }
~Context(void)212     ~Context(void)
213     {
214     }
getDeqpContext(void) const215     deqp::Context &getDeqpContext(void) const
216     {
217         return m_deqpCtx;
218     }
getSourceCollection(void)219     SourceCollections &getSourceCollection(void)
220     {
221         return m_sourceCollection;
222     }
getGLSLVersion(void)223     glu::GLSLVersion getGLSLVersion(void)
224     {
225         return m_glslVersion;
226     }
getShaderType(void)227     ShaderType getShaderType(void)
228     {
229         return m_shaderType;
230     }
setShaderType(ShaderType type)231     void setShaderType(ShaderType type)
232     {
233         m_shaderType = type;
234     }
235 
236 protected:
237     deqp::Context &m_deqpCtx;
238     SourceCollections m_sourceCollection;
239     glu::GLSLVersion m_glslVersion;
240     ShaderType m_shaderType;
241 };
242 
243 namespace subgroups
244 {
245 
246 template <typename Arg0>
247 class SubgroupFactory : public deqp::TestCase
248 {
249 public:
250     //void initPrograms(SourceCollections& programCollection, CaseDefinition caseDef)
251     typedef void (*InitFunction)(SourceCollections &programCollection, Arg0 arg0);
252     //void supportedCheck (Context& context, CaseDefinition caseDef)
253     typedef void (*SupportFunction)(Context &context, Arg0 arg0);
254     //tcu::TestStatus test(Context& context, const CaseDefinition caseDef)
255     typedef tcu::TestStatus (*TestFunction)(Context &context, const Arg0 arg0);
256 
257     /* Public methods */
SubgroupFactory(deqp::Context & context,tcu::TestNodeType type,const std::string & name,const std::string & desc,SupportFunction suppFunc,InitFunction initFunc,TestFunction testFunc,Arg0 arg0)258     SubgroupFactory(deqp::Context &context, tcu::TestNodeType type, const std::string &name, const std::string &desc,
259                     SupportFunction suppFunc, InitFunction initFunc, TestFunction testFunc, Arg0 arg0)
260         : TestCase(context, type, name.c_str(), desc.c_str())
261         , m_supportedFunc(suppFunc)
262         , m_initFunc(initFunc)
263         , m_testFunc(testFunc)
264         , m_arg0(arg0)
265         , m_glcContext(m_context)
266     {
267     }
268 
init()269     void init()
270     {
271         m_supportedFunc(m_glcContext, m_arg0);
272 
273         m_initFunc(m_glcContext.getSourceCollection(), m_arg0);
274     }
275 
deinit()276     void deinit()
277     {
278         // nothing to do
279     }
280 
iterate()281     tcu::TestNode::IterateResult iterate()
282     {
283         DE_ASSERT(m_testFunc);
284         tcu::TestLog &log = m_testCtx.getLog();
285 
286         try
287         {
288             // do SPIRV version of tests if supported
289             log << tcu::TestLog::Message << "SPIRV pass beginning..." << tcu::TestLog::EndMessage;
290             spirvUtils::checkGlSpirvSupported(m_glcContext.getDeqpContext());
291 
292             m_glcContext.setShaderType(SHADER_TYPE_SPIRV);
293 
294             const tcu::TestStatus result = m_testFunc(m_glcContext, m_arg0);
295             if (result.isComplete())
296             {
297                 DE_ASSERT(m_testCtx.getTestResult() == QP_TEST_RESULT_LAST);
298                 if (result.getCode() == QP_TEST_RESULT_PASS)
299                 {
300                     log << tcu::TestLog::Message << "SPIRV pass completed successfully (" << result.getDescription()
301                         << ")." << tcu::TestLog::EndMessage;
302                 }
303                 else
304                 {
305                     // test failed - log result and stop
306                     m_testCtx.setTestResult(result.getCode(), result.getDescription().c_str());
307                     return tcu::TestNode::STOP;
308                 }
309             }
310         }
311         catch (tcu::NotSupportedError &e)
312         {
313             log << tcu::TestLog::Message << "SPIRV pass skipped (" << e.getMessage() << ")."
314                 << tcu::TestLog::EndMessage;
315         }
316 
317         // do GLSL version of the tests
318         log << tcu::TestLog::Message << "GLSL pass beginning..." << tcu::TestLog::EndMessage;
319         m_glcContext.setShaderType(SHADER_TYPE_GLSL);
320         const tcu::TestStatus result = m_testFunc(m_glcContext, m_arg0);
321 
322         if (result.isComplete())
323         {
324             DE_ASSERT(m_testCtx.getTestResult() == QP_TEST_RESULT_LAST);
325             log << tcu::TestLog::Message << "GLSL pass completed successfully (" << result.getDescription() << ")."
326                 << tcu::TestLog::EndMessage;
327             m_testCtx.setTestResult(result.getCode(), result.getDescription().c_str());
328             return tcu::TestNode::STOP;
329         }
330 
331         return tcu::TestNode::CONTINUE;
332     }
333 
addFunctionCaseWithPrograms(deqp::TestCaseGroup * group,const std::string & name,const std::string & desc,SupportFunction suppFunc,InitFunction initFunc,TestFunction testFunc,Arg0 arg0)334     static void addFunctionCaseWithPrograms(deqp::TestCaseGroup *group, const std::string &name,
335                                             const std::string &desc, SupportFunction suppFunc, InitFunction initFunc,
336                                             TestFunction testFunc, Arg0 arg0)
337     {
338         group->addChild(new SubgroupFactory(group->getContext(), tcu::NODETYPE_SELF_VALIDATE, name, desc, suppFunc,
339                                             initFunc, testFunc, arg0));
340     }
341 
342 private:
343     SupportFunction m_supportedFunc;
344     InitFunction m_initFunc;
345     TestFunction m_testFunc;
346     Arg0 m_arg0;
347 
348     Context m_glcContext;
349 };
350 
351 typedef enum ShaderStageFlags
352 {
353     SHADER_STAGE_VERTEX_BIT          = GL_VERTEX_SHADER_BIT,
354     SHADER_STAGE_FRAGMENT_BIT        = GL_FRAGMENT_SHADER_BIT,
355     SHADER_STAGE_GEOMETRY_BIT        = GL_GEOMETRY_SHADER_BIT,
356     SHADER_STAGE_TESS_CONTROL_BIT    = GL_TESS_CONTROL_SHADER_BIT,
357     SHADER_STAGE_TESS_EVALUATION_BIT = GL_TESS_EVALUATION_SHADER_BIT,
358     SHADER_STAGE_COMPUTE_BIT         = GL_COMPUTE_SHADER_BIT,
359     SHADER_STAGE_ALL_GRAPHICS = (SHADER_STAGE_VERTEX_BIT | SHADER_STAGE_FRAGMENT_BIT | SHADER_STAGE_GEOMETRY_BIT |
360                                  SHADER_STAGE_TESS_CONTROL_BIT | SHADER_STAGE_TESS_EVALUATION_BIT),
361     SHADER_STAGE_ALL_VALID    = (SHADER_STAGE_ALL_GRAPHICS | SHADER_STAGE_COMPUTE_BIT),
362 } ShaderStageFlags;
363 
364 typedef enum SubgroupFeatureFlags
365 {
366     SUBGROUP_FEATURE_BASIC_BIT            = GL_SUBGROUP_FEATURE_BASIC_BIT_KHR,
367     SUBGROUP_FEATURE_VOTE_BIT             = GL_SUBGROUP_FEATURE_VOTE_BIT_KHR,
368     SUBGROUP_FEATURE_ARITHMETIC_BIT       = GL_SUBGROUP_FEATURE_ARITHMETIC_BIT_KHR,
369     SUBGROUP_FEATURE_BALLOT_BIT           = GL_SUBGROUP_FEATURE_BALLOT_BIT_KHR,
370     SUBGROUP_FEATURE_SHUFFLE_BIT          = GL_SUBGROUP_FEATURE_SHUFFLE_BIT_KHR,
371     SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT = GL_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT_KHR,
372     SUBGROUP_FEATURE_CLUSTERED_BIT        = GL_SUBGROUP_FEATURE_CLUSTERED_BIT_KHR,
373     SUBGROUP_FEATURE_QUAD_BIT             = GL_SUBGROUP_FEATURE_QUAD_BIT_KHR,
374     SUBGROUP_FEATURE_PARTITIONED_BIT_NV   = GL_SUBGROUP_FEATURE_PARTITIONED_BIT_NV,
375     SUBGROUP_FEATURE_ALL_VALID =
376         (SUBGROUP_FEATURE_BASIC_BIT | SUBGROUP_FEATURE_VOTE_BIT | SUBGROUP_FEATURE_ARITHMETIC_BIT |
377          SUBGROUP_FEATURE_BALLOT_BIT | SUBGROUP_FEATURE_SHUFFLE_BIT | SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT |
378          SUBGROUP_FEATURE_CLUSTERED_BIT | SUBGROUP_FEATURE_QUAD_BIT | SUBGROUP_FEATURE_PARTITIONED_BIT_NV),
379 } SubgroupFeatureFlags;
380 
381 typedef enum Format
382 {
383     FORMAT_UNDEFINED           = 0,
384     FORMAT_R32_SINT            = GL_R32I,
385     FORMAT_R32_UINT            = GL_R32UI,
386     FORMAT_R32G32_SINT         = GL_RG32I,
387     FORMAT_R32G32_UINT         = GL_RG32UI,
388     FORMAT_R32G32B32_SINT      = GL_RGB32I,
389     FORMAT_R32G32B32_UINT      = GL_RGB32UI,
390     FORMAT_R32G32B32A32_SINT   = GL_RGBA32I,
391     FORMAT_R32G32B32A32_UINT   = GL_RGBA32UI,
392     FORMAT_R32_SFLOAT          = GL_R32F,
393     FORMAT_R32G32_SFLOAT       = GL_RG32F,
394     FORMAT_R32G32B32_SFLOAT    = GL_RGB32F,
395     FORMAT_R32G32B32A32_SFLOAT = GL_RGBA32F,
396     FORMAT_R64_SFLOAT          = 0x6000,
397     FORMAT_R64G64_SFLOAT,
398     FORMAT_R64G64B64_SFLOAT,
399     FORMAT_R64G64B64A64_SFLOAT,
400     FORMAT_R32_BOOL = 0x6100,
401     FORMAT_R32G32_BOOL,
402     FORMAT_R32G32B32_BOOL,
403     FORMAT_R32G32B32A32_BOOL,
404 } Format;
405 
406 typedef enum DescriptorType
407 {
408     DESCRIPTOR_TYPE_UNIFORM_BUFFER = GL_UNIFORM_BUFFER,
409     DESCRIPTOR_TYPE_STORAGE_BUFFER = GL_SHADER_STORAGE_BUFFER,
410     DESCRIPTOR_TYPE_STORAGE_IMAGE  = GL_TEXTURE_2D,
411 } DescriptorType;
412 
413 // A struct to represent input data to a shader
414 struct SSBOData
415 {
SSBODataglc::subgroups::SSBOData416     SSBOData()
417         : initializeType(InitializeNone)
418         , layout(LayoutStd140)
419         , format(FORMAT_UNDEFINED)
420         , numElements(0)
421         , isImage(false)
422         , binding(0u)
423         , stages((ShaderStageFlags)0u)
424     {
425     }
426 
427     enum InputDataInitializeType
428     {
429         InitializeNone = 0,
430         InitializeNonZero,
431         InitializeZero,
432     } initializeType;
433 
434     enum InputDataLayoutType
435     {
436         LayoutStd140 = 0,
437         LayoutStd430,
438         LayoutPacked,
439     } layout;
440 
441     Format format;
442     uint64_t numElements;
443     bool isImage;
444     uint32_t binding;
445     ShaderStageFlags stages;
446 };
447 
448 std::string getSharedMemoryBallotHelper();
449 
450 uint32_t getSubgroupSize(Context &context);
451 
452 uint32_t maxSupportedSubgroupSize();
453 
454 std::string getShaderStageName(ShaderStageFlags stage);
455 
456 std::string getSubgroupFeatureName(SubgroupFeatureFlags bit);
457 
458 void addNoSubgroupShader(SourceCollections &programCollection);
459 
460 std::string getVertShaderForStage(ShaderStageFlags stage);
461 
462 bool isSubgroupSupported(Context &context);
463 
464 bool areSubgroupOperationsSupportedForStage(Context &context, ShaderStageFlags stage);
465 
466 bool areSubgroupOperationsRequiredForStage(ShaderStageFlags stage);
467 
468 bool isSubgroupFeatureSupportedForDevice(Context &context, SubgroupFeatureFlags bit);
469 
470 bool isFragmentSSBOSupportedForDevice(Context &context);
471 
472 bool isVertexSSBOSupportedForDevice(Context &context);
473 
474 bool isImageSupportedForStageOnDevice(Context &context, const ShaderStageFlags stage);
475 
476 bool isDoubleSupportedForDevice(Context &context);
477 
478 bool isDoubleFormat(Format format);
479 
480 std::string getFormatNameForGLSL(Format format);
481 
482 void addGeometryShadersFromTemplate(const std::string &glslTemplate, SourceCollections &collection);
483 
484 void setVertexShaderFrameBuffer(SourceCollections &programCollection);
485 
486 void setFragmentShaderFrameBuffer(SourceCollections &programCollection);
487 
488 void setFragmentShaderFrameBuffer(SourceCollections &programCollection);
489 
490 void setTesCtrlShaderFrameBuffer(SourceCollections &programCollection);
491 
492 void setTesEvalShaderFrameBuffer(SourceCollections &programCollection);
493 
494 bool check(std::vector<const void *> datas, uint32_t width, uint32_t ref);
495 
496 bool checkCompute(std::vector<const void *> datas, const uint32_t numWorkgroups[3], const uint32_t localSize[3],
497                   uint32_t ref);
498 
499 tcu::TestStatus makeTessellationEvaluationFrameBufferTest(
500     Context &context, Format format, SSBOData *extraData, uint32_t extraDataCount,
501     bool (*checkResult)(std::vector<const void *> datas, uint32_t width, uint32_t subgroupSize),
502     const ShaderStageFlags shaderStage = SHADER_STAGE_ALL_GRAPHICS);
503 
504 tcu::TestStatus makeGeometryFrameBufferTest(Context &context, Format format, SSBOData *extraData,
505                                             uint32_t extraDataCount,
506                                             bool (*checkResult)(std::vector<const void *> datas, uint32_t width,
507                                                                 uint32_t subgroupSize));
508 
509 tcu::TestStatus allStages(Context &context, Format format, SSBOData *extraData, uint32_t extraDataCount,
510                           bool (*checkResult)(std::vector<const void *> datas, uint32_t width, uint32_t subgroupSize),
511                           const ShaderStageFlags shaderStage);
512 
513 tcu::TestStatus makeVertexFrameBufferTest(Context &context, Format format, SSBOData *extraData, uint32_t extraDataCount,
514                                           bool (*checkResult)(std::vector<const void *> datas, uint32_t width,
515                                                               uint32_t subgroupSize));
516 
517 tcu::TestStatus makeFragmentFrameBufferTest(Context &context, Format format, SSBOData *extraData,
518                                             uint32_t extraDataCount,
519                                             bool (*checkResult)(std::vector<const void *> datas, uint32_t width,
520                                                                 uint32_t height, uint32_t subgroupSize));
521 
522 tcu::TestStatus makeComputeTest(Context &context, Format format, SSBOData *inputs, uint32_t inputsCount,
523                                 bool (*checkResult)(std::vector<const void *> datas, const uint32_t numWorkgroups[3],
524                                                     const uint32_t localSize[3], uint32_t subgroupSize));
525 } // namespace subgroups
526 } // namespace glc
527 
528 #endif // _GLCSUBGROUPSTESTSUTILS_HPP
529