1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.1 Module
3 * -------------------------------------------------
5 * Copyright 2016 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
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"
36 namespace NegativeTestShared
41 using glu::CallLogWrapper;
48 ARGMEMBER_BINDING_POINT,
49 ARGMEMBER_MATRIX_ORDER,
50 ARGMEMBER_MEMBER_TYPE,
52 ARGMEMBER_FIXED_ARRAY,
53 ARGMEMBER_VARIABLE_ARRAY,
57 // key pair ssbo arg data
63 SsboArgData(const ArgMember& member_, const std::string& data_)
70 // class which manages string based argument used to build varying ssbo interface blocks and members
74 SsboArgs(const std::string version, tcu::TestLog& log);
76 void setSingleValue (const SsboArgData argData);
77 bool setAllValues (const std::vector<SsboArgData> argDataList);
79 bool getMemberReorder (void) const;
81 void resetValues (void);
83 std::map<std::string, std::string> populateArgsMap (void) const;
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;
96 tcu::TestLog& m_testLog;
98 void setDefaultValues (void);
101 //constructor which ensure a proper context is passed into the struct
102 SsboArgs::SsboArgs(const std::string version, tcu::TestLog& log)
103 : m_negativeContextVersion (version)
104 , m_numberMembers (8)
110 void SsboArgs::setSingleValue (const SsboArgData argData)
114 switch (argData.member)
116 case ARGMEMBER_FORMAT:
117 m_stdFormat = argData.data;
119 case ARGMEMBER_BINDING_POINT:
120 m_bindingPoint = argData.data;
122 case ARGMEMBER_MATRIX_ORDER:
123 m_matrixOrder = argData.data;
125 case ARGMEMBER_MEMBER_TYPE:
126 m_memberType = argData.data;
129 m_memberName = argData.data;
131 case ARGMEMBER_FIXED_ARRAY:
132 m_memberFixedArrayerName = argData.data;
134 case ARGMEMBER_VARIABLE_ARRAY:
135 m_memberVariableArray = argData.data;
137 case ARGMEMBER_REORDER:
138 if (argData.data == "true")
140 m_memberReorder = true;
144 message = "auto loop argument data member not recognised.";
145 m_testLog << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
149 bool SsboArgs::setAllValues (const std::vector<SsboArgData> argDataList)
153 if ((argDataList.size() == 0) || (argDataList.size() > (size_t)m_numberMembers))
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;
162 for (unsigned int idx = 0; idx < argDataList.size(); idx++)
164 setSingleValue(argDataList[idx]);
171 bool SsboArgs::getMemberReorder (void) const
173 return m_memberReorder;
176 void SsboArgs::resetValues (void)
181 //converts SsboArgs member variable into a map object to be used by tcu::StringTemplate
182 std::map<std::string, std::string> SsboArgs::populateArgsMap (void) const
184 std::map<std::string, std::string> argsMap;
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;
199 // default values i.e. same shader template
200 void SsboArgs::setDefaultValues (void)
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;
213 std::string generateVaryingSSBOShader(const glw::GLenum shaderType, const args::SsboArgs& args, tcu::TestLog& log)
215 std::map<std::string, std::string> argsMap;
216 std::ostringstream source;
217 std::string sourceString;
218 std::stringstream ssboString;
221 if (args.getMemberReorder())
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";
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";
236 argsMap = args.populateArgsMap();
240 case GL_VERTEX_SHADER:
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"
249 source << ssboString.str();
251 source << "} ssbo;\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"
258 << " variable += ssbo.array_1[idx];\n"
260 << " vertex_colour = colour + variable;\n"
263 sourceString = source.str();
264 sourceString = tcu::StringTemplate(sourceString).specialize(argsMap);
269 case GL_FRAGMENT_SHADER:
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"
277 source << ssboString.str();
279 source << "} ssbo;\n"
282 << " mediump vec4 variable;\n"
283 << " variable * ssbo.${MEMBER_NAME};\n"
284 << " for (int idx = 0; idx < ${MEMBER_FIXED_ARRAY}; idx++)\n"
286 << " variable += ssbo.array_1[idx];\n"
288 << " fragment_colour = vertex_colour + variable;\n"
291 sourceString = source.str();
292 sourceString = tcu::StringTemplate(sourceString).specialize(argsMap);
297 case GL_GEOMETRY_SHADER:
303 case GL_TESS_CONTROL_SHADER:
309 case GL_TESS_EVALUATION_SHADER:
315 case GL_COMPUTE_SHADER:
323 message = "shader type not recognised.";
324 log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
328 return std::string();
331 void logProgramInfo(NegativeTestContext& ctx, GLint program)
335 tcu::TestLog& log = ctx.getLog();
337 ctx.glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
339 message = "Program log:";
340 log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
344 message = "No available info log.";
345 log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
349 std::vector<GLchar> infoLog(maxLength);
350 ctx.glGetProgramInfoLog(program, maxLength, &maxLength, &infoLog[0]);
352 std::string programLogMessage(&infoLog[0], maxLength);
353 log << tcu::TestLog::Message << programLogMessage << tcu::TestLog::EndMessage;
356 void ssbo_block_matching(NegativeTestContext& ctx)
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();
362 std::string versionString(glu::getGLSLVersionDeclaration(version));
363 args::SsboArgs ssboArgs(versionString, log);
364 GLint shaderVertexGL;
365 std::string shaderVertexString;
366 const char* shaderVertexCharPtr;
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]));
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);
385 message = shaderVertexString;
386 log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
389 ctx.glShaderSource(shaderVertexGL, 1, &shaderVertexCharPtr, DE_NULL);
390 ctx.glCompileShader(shaderVertexGL);
392 for (std::size_t idx = 0; idx < argDataVectorFrag.size(); ++idx)
394 GLint linkStatus = -1;
396 GLint shaderFragmentGL;
397 std::string shaderFragmentString;
398 const char* shaderFragmentCharPtr;
400 ctx.beginSection("Multiple shaders created using SSBO's sharing the same name but not matching layouts");
402 program = ctx.glCreateProgram();
404 // reset args to default and make a single change
405 ssboArgs.resetValues();
406 ssboArgs.setSingleValue(argDataVectorFrag[idx]);
408 // create fragment shader
409 shaderFragmentString = generateVaryingSSBOShader(GL_FRAGMENT_SHADER, ssboArgs, log);
410 shaderFragmentCharPtr = shaderFragmentString.c_str();
411 shaderFragmentGL = ctx.glCreateShader(GL_FRAGMENT_SHADER);
414 message = shaderFragmentString;
415 log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
418 ctx.glShaderSource(shaderFragmentGL, 1, &shaderFragmentCharPtr, DE_NULL);
419 ctx.glCompileShader(shaderFragmentGL);
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);
427 logProgramInfo(ctx, program);
429 if (linkStatus == GL_TRUE)
431 ctx.fail("Program should not have linked");
434 // clean up resources
435 ctx.glDeleteShader(shaderFragmentGL);
436 ctx.glDeleteProgram(program);
441 // clean up default resources
442 ctx.glDeleteShader(shaderVertexGL);
445 void ssbo_block_shared_qualifier(NegativeTestContext& ctx)
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();
451 std::string versionString(glu::getGLSLVersionDeclaration(version));
452 args::SsboArgs ssboArgs(versionString, log);
454 GLint shaderVertexGL;
455 std::string shaderVertexString;
456 const char* shaderVertexCharPtr;
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]));
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]));
473 // set default vertex ssbo args
474 result = ssboArgs.setAllValues(argDataVectorVert);
478 message = "Invalid use of args.setAllValues()";
479 log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
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);
489 message = shaderVertexString;
490 log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
493 ctx.glShaderSource(shaderVertexGL, 1, &shaderVertexCharPtr, DE_NULL);
494 ctx.glCompileShader(shaderVertexGL);
496 for (std::size_t idx = 0; idx < argDataVectorFrag.size(); idx++)
498 GLint linkStatus = -1;
500 GLint shaderFragmentGL;
501 std::string shaderFragmentString;
502 const char* shaderFragmentCharPtr;
504 ctx.beginSection("Multiple shaders created using SSBO's sharing the same name but not matching layouts");
506 program = ctx.glCreateProgram();
508 // reset args to default and make a single change
509 ssboArgs.setAllValues(argDataVectorVert);
510 ssboArgs.setSingleValue(argDataVectorFrag[idx]);
512 // create fragment shader
513 shaderFragmentString = generateVaryingSSBOShader(GL_FRAGMENT_SHADER, ssboArgs, log);
514 shaderFragmentCharPtr = shaderFragmentString.c_str();
515 shaderFragmentGL = ctx.glCreateShader(GL_FRAGMENT_SHADER);
518 message = shaderFragmentString;
519 log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
522 ctx.glShaderSource(shaderFragmentGL, 1, &shaderFragmentCharPtr, DE_NULL);
523 ctx.glCompileShader(shaderFragmentGL);
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);
531 logProgramInfo(ctx, program);
533 if (linkStatus == GL_TRUE)
535 ctx.fail("Program should not have linked");
538 // clean up resources
539 ctx.glDeleteShader(shaderFragmentGL);
540 ctx.glDeleteProgram(program);
545 // clean up default resources
546 ctx.glDeleteShader(shaderVertexGL);
550 std::vector<FunctionContainer> getNegativeSSBOBlockTestFunctions (void)
552 const FunctionContainer funcs[] =
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" },
558 return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
560 } // NegativeTestShared