• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.1 Module
3 * -------------------------------------------------
4 *
5 * Copyright 2016 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Negative Shader Storage Buffer Object (SSBO) tests.
22 *//*--------------------------------------------------------------------*/
23 #include "es31fNegativeSSBOBlockTests.hpp"
24 #include "glwDefs.hpp"
25 #include "glwEnums.hpp"
26 #include "tcuStringTemplate.hpp"
27 #include "gluShaderProgram.hpp"
28 #include <map>
29 
30 namespace deqp
31 {
32 namespace gles31
33 {
34 namespace Functional
35 {
36 namespace NegativeTestShared
37 {
38 namespace
39 {
40 using tcu::TestLog;
41 using glu::CallLogWrapper;
42 using namespace glw;
43 namespace args
44 {
45 enum ArgMember
46 {
47 	ARGMEMBER_FORMAT			=	0,
48 	ARGMEMBER_BINDING_POINT,
49 	ARGMEMBER_MATRIX_ORDER,
50 	ARGMEMBER_MEMBER_TYPE,
51 	ARGMEMBER_NAME,
52 	ARGMEMBER_FIXED_ARRAY,
53 	ARGMEMBER_VARIABLE_ARRAY,
54 	ARGMEMBER_REORDER
55 };
56 
57 // key pair ssbo arg data
58 struct SsboArgData
59 {
60 	ArgMember	member;
61 	std::string	data;
62 
SsboArgDatadeqp::gles31::Functional::NegativeTestShared::__anonbf4fef340111::args::SsboArgData63 	SsboArgData(const ArgMember& member_, const std::string& data_)
64 	{
65 		member	=	member_;
66 		data	=	data_;
67 	}
68 };
69 
70 // class which manages string based argument used to build varying ssbo interface blocks and members
71 class SsboArgs
72 {
73 public:
74 					SsboArgs(const std::string version, tcu::TestLog& log);
75 
76 	void			setSingleValue						(const SsboArgData argData);
77 	bool			setAllValues						(const std::vector<SsboArgData> argDataList);
78 
79 	bool				getMemberReorder				(void) const;
80 
81 	void				resetValues						(void);
82 
83 	std::map<std::string, std::string>	populateArgsMap	(void) const;
84 
85 private:
86 	std::string		m_negativeContextVersion;
87 	std::string		m_stdFormat;
88 	std::string		m_bindingPoint;
89 	std::string		m_matrixOrder;
90 	std::string		m_memberType;
91 	std::string		m_memberName;
92 	std::string		m_memberFixedArrayerName;
93 	std::string		m_memberVariableArray;
94 	bool			m_memberReorder;
95 	int				m_numberMembers;
96 	tcu::TestLog&	m_testLog;
97 
98 	void			setDefaultValues					(void);
99 };
100 
101 //constructor which ensure a proper context is passed into the struct
SsboArgs(const std::string version,tcu::TestLog & log)102 SsboArgs::SsboArgs(const std::string version, tcu::TestLog& log)
103 	: m_negativeContextVersion	(version)
104 	, m_numberMembers			(8)
105 	, m_testLog					(log)
106 {
107 	setDefaultValues();
108 }
109 
setSingleValue(const SsboArgData argData)110 void SsboArgs::setSingleValue (const SsboArgData argData)
111 {
112 	std::string message;
113 
114 	switch (argData.member)
115 	{
116 		case ARGMEMBER_FORMAT:
117 			m_stdFormat					=	argData.data;
118 			return;
119 		case ARGMEMBER_BINDING_POINT:
120 			m_bindingPoint				=	argData.data;
121 			return;
122 		case ARGMEMBER_MATRIX_ORDER:
123 			m_matrixOrder				=	argData.data;
124 			return;
125 		case ARGMEMBER_MEMBER_TYPE:
126 			m_memberType				=	argData.data;
127 			return;
128 		case ARGMEMBER_NAME:
129 			m_memberName				=	argData.data;
130 			return;
131 		case ARGMEMBER_FIXED_ARRAY:
132 			m_memberFixedArrayerName	=	argData.data;
133 			return;
134 		case ARGMEMBER_VARIABLE_ARRAY:
135 			m_memberVariableArray		=	argData.data;
136 			return;
137 		case ARGMEMBER_REORDER:
138 			if (argData.data == "true")
139 			{
140 				m_memberReorder			=	true;
141 			}
142 			return;
143 		default:
144 			message = "auto loop argument data member not recognised.";
145 			m_testLog << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
146 	}
147 }
148 
setAllValues(const std::vector<SsboArgData> argDataList)149 bool SsboArgs::setAllValues (const std::vector<SsboArgData> argDataList)
150 {
151 	std::string	message;
152 
153 	if ((argDataList.size() == 0) || (argDataList.size() > (size_t)m_numberMembers))
154 	{
155 		message = "set of args does not match the number of args struct changeable members.";
156 		m_testLog << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
157 
158 		return false;
159 	}
160 	else
161 	{
162 		for (unsigned int idx = 0; idx < argDataList.size(); idx++)
163 		{
164 			setSingleValue(argDataList[idx]);
165 		}
166 	}
167 
168 	return true;
169 }
170 
getMemberReorder(void) const171 bool SsboArgs::getMemberReorder (void) const
172 {
173 	return m_memberReorder;
174 }
175 
resetValues(void)176 void SsboArgs::resetValues (void)
177 {
178 	setDefaultValues();
179 }
180 
181 //converts SsboArgs member variable into a map object to be used by tcu::StringTemplate
populateArgsMap(void) const182 std::map<std::string, std::string> SsboArgs::populateArgsMap (void) const
183 {
184 	std::map<std::string, std::string> argsMap;
185 
186 	// key placeholders located at specific points in the ssbo block
187 	argsMap["NEGATIVE_CONTEXT_VERSION"]	=	m_negativeContextVersion;
188 	argsMap["STD_FORMAT"]				=	m_stdFormat;
189 	argsMap["BINDING_POINT"]			=	m_bindingPoint;
190 	argsMap["MATRIX_ORDER"]				=	m_matrixOrder;
191 	argsMap["MEMBER_TYPE"]				=	m_memberType;
192 	argsMap["MEMBER_NAME"]				=	m_memberName;
193 	argsMap["MEMBER_FIXED_ARRAY"]		=	m_memberFixedArrayerName;
194 	argsMap["MEMBER_VARIABLE_ARRAY"]	=	m_memberVariableArray;
195 
196 	return argsMap;
197 }
198 
199 // default values i.e. same shader template
setDefaultValues(void)200 void SsboArgs::setDefaultValues (void)
201 {
202 	m_stdFormat					=	"std430";
203 	m_bindingPoint				=	"0";
204 	m_matrixOrder				=	"column_major";
205 	m_memberType				=	"int";
206 	m_memberName				=	"matrix";
207 	m_memberFixedArrayerName	=	"10";
208 	m_memberVariableArray		=	"";
209 	m_memberReorder				=	false;
210 }
211 } // args
212 
generateVaryingSSBOShader(const glw::GLenum shaderType,const args::SsboArgs & args,tcu::TestLog & log)213 std::string generateVaryingSSBOShader(const glw::GLenum shaderType, const args::SsboArgs& args, tcu::TestLog& log)
214 {
215 	std::map<std::string, std::string>	argsMap;
216 	std::ostringstream					source;
217 	std::string							sourceString;
218 	std::stringstream					ssboString;
219 	std::string							message;
220 
221 	if (args.getMemberReorder())
222 	{
223 		ssboString	<< "	mediump vec4 array_1[${MEMBER_FIXED_ARRAY}];\n"
224 					<< "	highp mat4 ${MEMBER_NAME};\n"
225 					<< "	lowp ${MEMBER_TYPE} data;\n"
226 					<< "	mediump float array_2[${MEMBER_VARIABLE_ARRAY}];\n";
227 	}
228 	else
229 	{
230 		ssboString	<< "	lowp ${MEMBER_TYPE} data;\n"
231 					<< "	highp mat4 ${MEMBER_NAME};\n"
232 					<< "	mediump vec4 array_1[${MEMBER_FIXED_ARRAY}];\n"
233 					<< "	mediump float array_2[${MEMBER_VARIABLE_ARRAY}];\n";
234 	}
235 
236 	argsMap = args.populateArgsMap();
237 
238 	switch (shaderType)
239 	{
240 		case GL_VERTEX_SHADER:
241 		{
242 			source	<< "${NEGATIVE_CONTEXT_VERSION}\n"
243 					<< "layout (location = 0) in highp vec4 position;\n"
244 					<< "layout (location = 1) in mediump vec4 colour;\n"
245 					<< "out mediump vec4 vertex_colour;\n"
246 					<< "layout (${STD_FORMAT}, binding = ${BINDING_POINT}, ${MATRIX_ORDER}) buffer ssbo_block\n"
247 					<< "{\n";
248 
249 			source << ssboString.str();
250 
251 			source	<< "} ssbo;\n"
252 					<< "void main()\n"
253 					<< "{\n"
254 					<< "	mediump vec4 variable;\n"
255 					<< "	gl_Position = ssbo.${MEMBER_NAME} * position;\n"
256 					<< "	for (int idx = 0; idx < ${MEMBER_FIXED_ARRAY}; idx++)\n"
257 					<< "	{\n"
258 					<< "		variable += ssbo.array_1[idx];\n"
259 					<< "	}\n"
260 					<< "	vertex_colour = colour + variable;\n"
261 					<< "}\n";
262 
263 			sourceString = source.str();
264 			sourceString = tcu::StringTemplate(sourceString).specialize(argsMap);
265 
266 			return sourceString;
267 		}
268 
269 		case GL_FRAGMENT_SHADER:
270 		{
271 			source	<< "${NEGATIVE_CONTEXT_VERSION}\n"
272 					<< "in mediump vec4 vertex_colour;\n"
273 					<< "layout (location = 0) out mediump vec4 fragment_colour;\n"
274 					<< "layout (${STD_FORMAT}, binding = ${BINDING_POINT}, ${MATRIX_ORDER}) buffer ssbo_block\n"
275 					<< "{\n";
276 
277 			source << ssboString.str();
278 
279 			source	<< "} ssbo;\n"
280 					<< "void main()\n"
281 					<< "{\n"
282 					<< "	mediump vec4 variable;\n"
283 					<< "	variable * ssbo.${MEMBER_NAME};\n"
284 					<< "	for (int idx = 0; idx < ${MEMBER_FIXED_ARRAY}; idx++)\n"
285 					<< "	{\n"
286 					<< "		variable += ssbo.array_1[idx];\n"
287 					<< "	}\n"
288 					<< "	fragment_colour = vertex_colour + variable;\n"
289 					<< "}\n";
290 
291 			sourceString = source.str();
292 			sourceString = tcu::StringTemplate(sourceString).specialize(argsMap);
293 
294 			return sourceString;
295 		}
296 
297 		case GL_GEOMETRY_SHADER:
298 		{
299 			// TODO:
300 			return sourceString;
301 		}
302 
303 		case GL_TESS_CONTROL_SHADER:
304 		{
305 			// TODO:
306 			return sourceString;
307 		}
308 
309 		case GL_TESS_EVALUATION_SHADER:
310 		{
311 			// TODO:
312 			return sourceString;
313 		}
314 
315 		case GL_COMPUTE_SHADER:
316 		{
317 			// TODO:
318 			return sourceString;
319 		}
320 
321 		default:
322 		{
323 			message = "shader type not recognised.";
324 			log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
325 		}
326 	}
327 
328 	return std::string();
329 }
330 
logProgramInfo(NegativeTestContext & ctx,GLint program)331 void logProgramInfo(NegativeTestContext& ctx, GLint program)
332 {
333 	GLint			maxLength	=	0;
334 	std::string		message;
335 	tcu::TestLog&	log			=	ctx.getLog();
336 
337 	ctx.glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
338 
339 	message = "Program log:";
340 	log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
341 
342 	if (maxLength == 0)
343 	{
344 		message = "No available info log.";
345 		log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
346 		return;
347 	}
348 
349 	std::vector<GLchar> infoLog(maxLength);
350 	ctx.glGetProgramInfoLog(program, maxLength, &maxLength, &infoLog[0]);
351 
352 	std::string programLogMessage(&infoLog[0], maxLength);
353 	log << tcu::TestLog::Message << programLogMessage << tcu::TestLog::EndMessage;
354 }
355 
ssbo_block_matching(NegativeTestContext & ctx)356 void ssbo_block_matching(NegativeTestContext& ctx)
357 {
358 	const bool				isES32													=	contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
359 	const glu::GLSLVersion	version													=	isES32 ? glu::GLSL_VERSION_320_ES : glu::GLSL_VERSION_310_ES;
360 	tcu::TestLog&			log														=	ctx.getLog();
361 	std::string				message;
362 	std::string				versionString(glu::getGLSLVersionDeclaration(version));
363 	args::SsboArgs			ssboArgs(versionString, log);
364 	GLint					shaderVertexGL;
365 	std::string				shaderVertexString;
366 	const char*				shaderVertexCharPtr;
367 
368 	// List of arguments used to create varying ssbo objects in the fragment shader
369 	const args::SsboArgData argDataArrayFrag[] = {	args::SsboArgData(args::ARGMEMBER_FORMAT,			"std140"),
370 													args::SsboArgData(args::ARGMEMBER_BINDING_POINT,	"10"),
371 													args::SsboArgData(args::ARGMEMBER_MATRIX_ORDER,		"row_major"),
372 													args::SsboArgData(args::ARGMEMBER_MEMBER_TYPE,		"vec2"),
373 													args::SsboArgData(args::ARGMEMBER_NAME,				"name_changed"),
374 													args::SsboArgData(args::ARGMEMBER_FIXED_ARRAY,		"20"),
375 													args::SsboArgData(args::ARGMEMBER_VARIABLE_ARRAY,	"5"),
376 													args::SsboArgData(args::ARGMEMBER_REORDER,			"true") };
377 	std::vector<args::SsboArgData> argDataVectorFrag(argDataArrayFrag, argDataArrayFrag + sizeof(argDataArrayFrag) / sizeof(argDataArrayFrag[0]));
378 
379 	// create default vertex shader
380 	shaderVertexString = generateVaryingSSBOShader(GL_VERTEX_SHADER, ssboArgs, log);
381 	shaderVertexCharPtr = shaderVertexString.c_str();
382 	shaderVertexGL = ctx.glCreateShader(GL_VERTEX_SHADER);
383 
384 	// log
385 	message = shaderVertexString;
386 	log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
387 
388 	// compile
389 	ctx.glShaderSource(shaderVertexGL, 1, &shaderVertexCharPtr, DE_NULL);
390 	ctx.glCompileShader(shaderVertexGL);
391 
392 	for (std::size_t idx = 0; idx < argDataVectorFrag.size(); ++idx)
393 	{
394 		GLint			linkStatus				=	-1;
395 		GLint			program;
396 		GLint			shaderFragmentGL;
397 		std::string		shaderFragmentString;
398 		const char*		shaderFragmentCharPtr;
399 
400 		ctx.beginSection("Multiple shaders created using SSBO's sharing the same name but not matching layouts");
401 
402 		program = ctx.glCreateProgram();
403 
404 		// reset args to default and make a single change
405 		ssboArgs.resetValues();
406 		ssboArgs.setSingleValue(argDataVectorFrag[idx]);
407 
408 		// create fragment shader
409 		shaderFragmentString = generateVaryingSSBOShader(GL_FRAGMENT_SHADER, ssboArgs, log);
410 		shaderFragmentCharPtr = shaderFragmentString.c_str();
411 		shaderFragmentGL = ctx.glCreateShader(GL_FRAGMENT_SHADER);
412 
413 		// log
414 		message = shaderFragmentString;
415 		log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
416 
417 		// compile
418 		ctx.glShaderSource(shaderFragmentGL, 1, &shaderFragmentCharPtr, DE_NULL);
419 		ctx.glCompileShader(shaderFragmentGL);
420 
421 		// attach shaders to program and attempt to link
422 		ctx.glAttachShader(program, shaderVertexGL);
423 		ctx.glAttachShader(program, shaderFragmentGL);
424 		ctx.glLinkProgram(program);
425 		ctx.glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
426 
427 		logProgramInfo(ctx, program);
428 
429 		if (linkStatus == GL_TRUE)
430 		{
431 			ctx.fail("Program should not have linked");
432 		}
433 
434 		// clean up resources
435 		ctx.glDeleteShader(shaderFragmentGL);
436 		ctx.glDeleteProgram(program);
437 
438 		ctx.endSection();
439 	}
440 
441 	// clean up default resources
442 	ctx.glDeleteShader(shaderVertexGL);
443 }
444 
ssbo_block_shared_qualifier(NegativeTestContext & ctx)445 void ssbo_block_shared_qualifier(NegativeTestContext& ctx)
446 {
447 	const bool				isES32													=	contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
448 	const glu::GLSLVersion	version													=	isES32 ? glu::GLSL_VERSION_320_ES : glu::GLSL_VERSION_310_ES;
449 	tcu::TestLog&			log														=	ctx.getLog();
450 	std::string				message;
451 	std::string				versionString(glu::getGLSLVersionDeclaration(version));
452 	args::SsboArgs			ssboArgs(versionString, log);
453 	bool					result;
454 	GLint					shaderVertexGL;
455 	std::string				shaderVertexString;
456 	const char*				shaderVertexCharPtr;
457 
458 	// default args used in vertex shader ssbo
459 	const args::SsboArgData argDataArrayVert[] = {	args::SsboArgData(args::ARGMEMBER_FORMAT,			"shared"),
460 													args::SsboArgData(args::ARGMEMBER_BINDING_POINT,	"0"),
461 													args::SsboArgData(args::ARGMEMBER_MATRIX_ORDER,		"column_major"),
462 													args::SsboArgData(args::ARGMEMBER_FIXED_ARRAY,		"10"),
463 													args::SsboArgData(args::ARGMEMBER_VARIABLE_ARRAY,	"10"),
464 													args::SsboArgData(args::ARGMEMBER_REORDER,			"false") };
465 	std::vector<args::SsboArgData> argDataVectorVert(argDataArrayVert, argDataArrayVert + sizeof(argDataArrayVert) / sizeof(argDataArrayVert[0]));
466 
467 	// args changed in fragment shader ssbo
468 	const args::SsboArgData argDataArrayFrag[] = {	args::SsboArgData(args::ARGMEMBER_MATRIX_ORDER,		"row_major"),
469 													args::SsboArgData(args::ARGMEMBER_VARIABLE_ARRAY,	""),
470 													args::SsboArgData(args::ARGMEMBER_FIXED_ARRAY,		"20") };
471 	std::vector<args::SsboArgData> argDataVectorFrag(argDataArrayFrag, argDataArrayFrag + sizeof(argDataArrayFrag) / sizeof(argDataArrayFrag[0]));
472 
473 	// set default vertex ssbo args
474 	result = ssboArgs.setAllValues(argDataVectorVert);
475 
476 	if (result == false)
477 	{
478 		message = "Invalid use of args.setAllValues()";
479 		log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
480 		return;
481 	}
482 
483 	// create default vertex shader
484 	shaderVertexString = generateVaryingSSBOShader(GL_VERTEX_SHADER, ssboArgs, log);
485 	shaderVertexCharPtr = shaderVertexString.c_str();
486 	shaderVertexGL = ctx.glCreateShader(GL_VERTEX_SHADER);
487 
488 	// log
489 	message = shaderVertexString;
490 	log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
491 
492 	// compile
493 	ctx.glShaderSource(shaderVertexGL, 1, &shaderVertexCharPtr, DE_NULL);
494 	ctx.glCompileShader(shaderVertexGL);
495 
496 	for (std::size_t idx = 0; idx < argDataVectorFrag.size(); idx++)
497 	{
498 		GLint		linkStatus				=	-1;
499 		GLint		program;
500 		GLint		shaderFragmentGL;
501 		std::string	shaderFragmentString;
502 		const char*	shaderFragmentCharPtr;
503 
504 		ctx.beginSection("Multiple shaders created using SSBO's sharing the same name but not matching layouts");
505 
506 		program = ctx.glCreateProgram();
507 
508 		// reset args to default and make a single change
509 		ssboArgs.setAllValues(argDataVectorVert);
510 		ssboArgs.setSingleValue(argDataVectorFrag[idx]);
511 
512 		// create fragment shader
513 		shaderFragmentString = generateVaryingSSBOShader(GL_FRAGMENT_SHADER, ssboArgs, log);
514 		shaderFragmentCharPtr = shaderFragmentString.c_str();
515 		shaderFragmentGL = ctx.glCreateShader(GL_FRAGMENT_SHADER);
516 
517 		// log
518 		message = shaderFragmentString;
519 		log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
520 
521 		// compile
522 		ctx.glShaderSource(shaderFragmentGL, 1, &shaderFragmentCharPtr, DE_NULL);
523 		ctx.glCompileShader(shaderFragmentGL);
524 
525 		// attach shaders to the program and attempt to link
526 		ctx.glAttachShader(program, shaderVertexGL);
527 		ctx.glAttachShader(program, shaderFragmentGL);
528 		ctx.glLinkProgram(program);
529 		ctx.glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
530 
531 		logProgramInfo(ctx, program);
532 
533 		if (linkStatus == GL_TRUE)
534 		{
535 			ctx.fail("Program should not have linked");
536 		}
537 
538 		// clean up resources
539 		ctx.glDeleteShader(shaderFragmentGL);
540 		ctx.glDeleteProgram(program);
541 
542 		ctx.endSection();
543 	}
544 
545 	// clean up default resources
546 	ctx.glDeleteShader(shaderVertexGL);
547 }
548 } // anonymous
549 
getNegativeSSBOBlockTestFunctions(void)550 std::vector<FunctionContainer> getNegativeSSBOBlockTestFunctions (void)
551 {
552 	const FunctionContainer funcs[] =
553 	{
554 		{ ssbo_block_matching,			"ssbo_block_interface_matching_tests",	"Invalid Shader Linkage" },
555 		{ ssbo_block_shared_qualifier,	"ssbo_using_shared_qualifier_tests",	"Invalid Shader Linkage" },
556 	};
557 
558 	return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
559 }
560 } // NegativeTestShared
561 } //Functional
562 } //gles31
563 } //deqp
564