Merge Vulkan CTS 1.0.2.5 into aosp/master
[platform/upstream/VK-GL-CTS.git] / modules / gles31 / functional / es31fNegativeSSBOBlockTests.cpp
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
63         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
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
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
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
171 bool SsboArgs::getMemberReorder (void) const
172 {
173         return m_memberReorder;
174 }
175
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
182 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
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
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
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
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
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
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