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 
operator ++(void)85 		Iterator&			operator++	(void)			{ ++m_impl; return *this;	}
operator *(void) const86 		const Program&		operator*	(void) const	{ return getProgram();		}
87 
getName(void) const88 		const std::string&	getName		(void) const	{ return m_impl->first;		}
getProgram(void) const89 		const Program&		getProgram	(void) const	{ return *m_impl->second;	}
90 
operator ==(const Iterator & other) const91 		bool				operator==	(const Iterator& other) const	{ return m_impl == other.m_impl;	}
operator !=(const Iterator & other) const92 		bool				operator!=	(const Iterator& other) const	{ return m_impl != other.m_impl;	}
93 
94 	private:
95 
96 		IteratorImpl	m_impl;
97 	};
98 
begin(void) const99 	Iterator					begin				(void) const { return Iterator(m_programs.begin());	}
end(void) const100 	Iterator					end					(void) const { return Iterator(m_programs.end());	}
101 
empty(void) const102 	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>
ProgramCollection(void)111 ProgramCollection<Program>::ProgramCollection (void)
112 {
113 }
114 
115 template<typename Program>
~ProgramCollection(void)116 ProgramCollection<Program>::~ProgramCollection (void)
117 {
118 	clear();
119 }
120 
121 template<typename Program>
clear(void)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>
add(const std::string & name)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>
add(const std::string & name,de::MovePtr<Program> & 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>
contains(const std::string & name) const148 bool ProgramCollection<Program>::contains (const std::string& name) const
149 {
150 	return de::contains(m_programs, name);
151 }
152 
153 template<typename Program>
get(const std::string & name) const154 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 
operator <<glc::GlslSource164 	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:
Context(deqp::Context & deqpCtx)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 		{}
~Context(void)183 	~Context (void) {}
getDeqpContext(void) const184 	deqp::Context&			getDeqpContext		(void) const { return m_deqpCtx; }
getSourceCollection(void)185 	SourceCollections&		getSourceCollection (void) { return m_sourceCollection; }
getGLSLVersion(void)186 	glu::GLSLVersion		getGLSLVersion		(void) { return m_glslVersion; }
getShaderType(void)187 	ShaderType				getShaderType		(void) { return m_shaderType; }
setShaderType(ShaderType type)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 */
SubgroupFactory(deqp::Context & context,tcu::TestNodeType type,const std::string & name,const std::string & desc,SupportFunction suppFunc,InitFunction initFunc,TestFunction testFunc,Arg0 arg0)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 
init()222 	void init()
223 	{
224 		m_supportedFunc(m_glcContext, m_arg0);
225 
226 		m_initFunc(m_glcContext.getSourceCollection(), m_arg0);
227 	}
228 
deinit()229 	void deinit()
230 	{
231 		// nothing to do
232 	}
233 
iterate()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 
addFunctionCaseWithPrograms(deqp::TestCaseGroup * group,const std::string & name,const std::string & desc,SupportFunction suppFunc,InitFunction initFunc,TestFunction testFunc,Arg0 arg0)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 {
SSBODataglc::subgroups::SSBOData369 	SSBOData() :
370 		initializeType	(InitializeNone),
371 		layout			(LayoutStd140),
372 		format			(FORMAT_UNDEFINED),
373 		numElements		(0),
374 		isImage			(false),
375 		binding			(0u),
376 		stages			((ShaderStageFlags)0u)
377 	{}
378 
379 	enum InputDataInitializeType
380 	{
381 		InitializeNone = 0,
382 		InitializeNonZero,
383 		InitializeZero,
384 	} initializeType;
385 
386 	enum InputDataLayoutType
387 	{
388 		LayoutStd140 = 0,
389 		LayoutStd430,
390 		LayoutPacked,
391 	} layout;
392 
393 	Format						format;
394 	deUint64					numElements;
395 	bool						isImage;
396 	deUint32					binding;
397 	ShaderStageFlags			stages;
398 };
399 
400 std::string getSharedMemoryBallotHelper();
401 
402 deUint32 getSubgroupSize(Context& context);
403 
404 deUint32 maxSupportedSubgroupSize();
405 
406 std::string getShaderStageName(ShaderStageFlags stage);
407 
408 std::string getSubgroupFeatureName(SubgroupFeatureFlags bit);
409 
410 void addNoSubgroupShader (SourceCollections& programCollection);
411 
412 std::string getVertShaderForStage(ShaderStageFlags stage);
413 
414 bool isSubgroupSupported(Context& context);
415 
416 bool areSubgroupOperationsSupportedForStage(
417 	Context& context, ShaderStageFlags stage);
418 
419 bool areSubgroupOperationsRequiredForStage(ShaderStageFlags stage);
420 
421 bool isSubgroupFeatureSupportedForDevice(Context& context, SubgroupFeatureFlags bit);
422 
423 bool isFragmentSSBOSupportedForDevice(Context& context);
424 
425 bool isVertexSSBOSupportedForDevice(Context& context);
426 
427 bool isImageSupportedForStageOnDevice(Context& context, const ShaderStageFlags stage);
428 
429 bool isDoubleSupportedForDevice(Context& context);
430 
431 bool isDoubleFormat(Format format);
432 
433 std::string getFormatNameForGLSL(Format format);
434 
435 void addGeometryShadersFromTemplate (const std::string& glslTemplate, SourceCollections& collection);
436 
437 void setVertexShaderFrameBuffer (SourceCollections& programCollection);
438 
439 void setFragmentShaderFrameBuffer (SourceCollections& programCollection);
440 
441 void setFragmentShaderFrameBuffer (SourceCollections& programCollection);
442 
443 void setTesCtrlShaderFrameBuffer (SourceCollections& programCollection);
444 
445 void setTesEvalShaderFrameBuffer (SourceCollections& programCollection);
446 
447 bool check(std::vector<const void*> datas,
448 	deUint32 width, deUint32 ref);
449 
450 bool checkCompute(std::vector<const void*> datas,
451 	const deUint32 numWorkgroups[3], const deUint32 localSize[3],
452 	deUint32 ref);
453 
454 tcu::TestStatus makeTessellationEvaluationFrameBufferTest(Context& context, Format format,
455 	SSBOData* extraData, deUint32 extraDataCount,
456 	bool (*checkResult)(std::vector<const void*> datas, deUint32 width, deUint32 subgroupSize),
457 	const ShaderStageFlags shaderStage = SHADER_STAGE_ALL_GRAPHICS);
458 
459 tcu::TestStatus makeGeometryFrameBufferTest(Context& context, Format format, SSBOData* extraData,
460 	deUint32 extraDataCount,
461 	bool (*checkResult)(std::vector<const void*> datas, deUint32 width, deUint32 subgroupSize));
462 
463 tcu::TestStatus allStages(Context& context, Format format,
464 	SSBOData* extraData, deUint32 extraDataCount,
465 	bool (*checkResult)(std::vector<const void*> datas, deUint32 width, deUint32 subgroupSize),
466 	const ShaderStageFlags shaderStage);
467 
468 tcu::TestStatus makeVertexFrameBufferTest(Context& context, Format format,
469 	SSBOData* extraData, deUint32 extraDataCount,
470 	bool (*checkResult)(std::vector<const void*> datas, deUint32 width, deUint32 subgroupSize));
471 
472 tcu::TestStatus makeFragmentFrameBufferTest(Context& context, Format format,
473 	SSBOData* extraData, deUint32 extraDataCount,
474 	bool (*checkResult)(std::vector<const void*> datas, deUint32 width,
475 									 deUint32 height, deUint32 subgroupSize));
476 
477 tcu::TestStatus makeComputeTest(
478 	Context& context, Format format, SSBOData* inputs,
479 	deUint32 inputsCount,
480 	bool (*checkResult)(std::vector<const void*> datas,
481 		const deUint32 numWorkgroups[3], const deUint32 localSize[3],
482 		deUint32 subgroupSize));
483 } // subgroups
484 } // glc
485 
486 #endif // _GLCSUBGROUPSTESTSUTILS_HPP
487