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