Fix PIPELINE_STAGE_TOP_OF_PIPE_BIT usage in api tests
[platform/upstream/VK-GL-CTS.git] / modules / gles31 / functional / es31fShaderSharedVarTests.cpp
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.1 Module
3  * -------------------------------------------------
4  *
5  * Copyright 2014 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 GLSL Shared variable tests.
22  *//*--------------------------------------------------------------------*/
23
24 #include "es31fShaderSharedVarTests.hpp"
25 #include "es31fShaderAtomicOpTests.hpp"
26 #include "gluShaderProgram.hpp"
27 #include "gluShaderUtil.hpp"
28 #include "gluRenderContext.hpp"
29 #include "gluObjectWrapper.hpp"
30 #include "gluProgramInterfaceQuery.hpp"
31 #include "tcuVector.hpp"
32 #include "tcuTestLog.hpp"
33 #include "tcuVectorUtil.hpp"
34 #include "tcuFormatUtil.hpp"
35 #include "deRandom.hpp"
36 #include "deArrayUtil.hpp"
37 #include "glwFunctions.hpp"
38 #include "glwEnums.hpp"
39
40 #include <algorithm>
41 #include <set>
42
43 namespace deqp
44 {
45 namespace gles31
46 {
47 namespace Functional
48 {
49
50 using std::string;
51 using std::vector;
52 using tcu::TestLog;
53 using tcu::UVec3;
54 using std::set;
55 using namespace glu;
56
57 enum
58 {
59         MAX_VALUE_ARRAY_LENGTH  = 15    // * 2 * sizeof(mat4) + sizeof(int) = 481 uniform components (limit 512)
60 };
61
62 template<typename T, int Size>
63 static inline T product (const tcu::Vector<T, Size>& v)
64 {
65         T res = v[0];
66         for (int ndx = 1; ndx < Size; ndx++)
67                 res *= v[ndx];
68         return res;
69 }
70
71 class SharedBasicVarCase : public TestCase
72 {
73 public:
74                                                         SharedBasicVarCase              (Context& context, const char* name, DataType basicType, Precision precision, const tcu::UVec3& workGroupSize);
75                                                         ~SharedBasicVarCase             (void);
76
77         void                                    init                                    (void);
78         void                                    deinit                                  (void);
79         IterateResult                   iterate                                 (void);
80
81 private:
82                                                         SharedBasicVarCase              (const SharedBasicVarCase& other);
83         SharedBasicVarCase&             operator=                               (const SharedBasicVarCase& other);
84
85         const DataType                  m_basicType;
86         const Precision                 m_precision;
87         const tcu::UVec3                m_workGroupSize;
88
89         ShaderProgram*                  m_program;
90 };
91
92 static std::string getBasicCaseDescription (DataType basicType, Precision precision, const tcu::UVec3& workGroupSize)
93 {
94         std::ostringstream str;
95         if (precision != PRECISION_LAST)
96                 str << getPrecisionName(precision) << " ";
97         str << getDataTypeName(basicType) << ", work group size = " << workGroupSize;
98         return str.str();
99 }
100
101 SharedBasicVarCase::SharedBasicVarCase (Context& context, const char* name, DataType basicType, Precision precision, const tcu::UVec3& workGroupSize)
102         : TestCase                      (context, name, getBasicCaseDescription(basicType, precision, workGroupSize).c_str())
103         , m_basicType           (basicType)
104         , m_precision           (precision)
105         , m_workGroupSize       (workGroupSize)
106         , m_program                     (DE_NULL)
107 {
108 }
109
110 SharedBasicVarCase::~SharedBasicVarCase (void)
111 {
112         SharedBasicVarCase::deinit();
113 }
114
115 void SharedBasicVarCase::init (void)
116 {
117         const int                       valArrayLength  = de::min<int>(MAX_VALUE_ARRAY_LENGTH, product(m_workGroupSize));
118         const char*                     precName                = m_precision != glu::PRECISION_LAST ? getPrecisionName(m_precision) : "";
119         const char*                     typeName                = getDataTypeName(m_basicType);
120         std::ostringstream      src;
121
122         src << "#version 310 es\n"
123                 << "layout (local_size_x = " << m_workGroupSize[0]
124                 << ", local_size_y = " << m_workGroupSize[1]
125                 << ", local_size_z = " << m_workGroupSize[2]
126                 << ") in;\n"
127                 << "const uint LOCAL_SIZE = gl_WorkGroupSize.x*gl_WorkGroupSize.y*gl_WorkGroupSize.z;\n"
128                 << "shared " << precName << " " << typeName << " s_var;\n"
129                 << "uniform " << precName << " " << typeName << " u_val[" << valArrayLength << "];\n"
130                 << "uniform " << precName << " " << typeName << " u_ref[" << valArrayLength << "];\n"
131                 << "uniform uint u_numIters;\n"
132                 << "layout(binding = 0) buffer Result\n"
133                 << "{\n"
134                 << "    bool isOk[LOCAL_SIZE];\n"
135                 << "};\n"
136                 << "\n"
137                 << "void main (void)\n"
138                 << "{\n"
139                 << "    bool allOk = true;\n"
140                 << "    for (uint ndx = 0u; ndx < u_numIters; ndx++)\n"
141                 << "    {\n"
142                 << "            if (ndx == gl_LocalInvocationIndex)\n"
143                 << "                    s_var = u_val[ndx%uint(u_val.length())];\n"
144                 << "\n"
145                 << "            barrier();\n"
146                 << "\n"
147                 << "            if (s_var != u_ref[ndx%uint(u_ref.length())])\n"
148                 << "                    allOk = false;\n"
149                 << "\n"
150                 << "            barrier();\n"
151                 << "    }\n"
152                 << "\n"
153                 << "    isOk[gl_LocalInvocationIndex] = allOk;\n"
154                 << "}\n";
155
156         DE_ASSERT(!m_program);
157         m_program = new ShaderProgram(m_context.getRenderContext(), ProgramSources() << ComputeSource(src.str()));
158
159         m_testCtx.getLog() << *m_program;
160
161         if (!m_program->isOk())
162         {
163                 delete m_program;
164                 m_program = DE_NULL;
165                 throw tcu::TestError("Compile failed");
166         }
167 }
168
169 void SharedBasicVarCase::deinit (void)
170 {
171         delete m_program;
172         m_program = DE_NULL;
173 }
174
175 SharedBasicVarCase::IterateResult SharedBasicVarCase::iterate (void)
176 {
177         const glw::Functions&           gl                              = m_context.getRenderContext().getFunctions();
178         const deUint32                          program                 = m_program->getProgram();
179         Buffer                                          outputBuffer    (m_context.getRenderContext());
180         const deUint32                          outBlockNdx             = gl.getProgramResourceIndex(program, GL_SHADER_STORAGE_BLOCK, "Result");
181         const InterfaceBlockInfo        outBlockInfo    = getProgramInterfaceBlockInfo(gl, program, GL_SHADER_STORAGE_BLOCK, outBlockNdx);
182
183         gl.useProgram(program);
184
185         // Setup input values.
186         {
187                 const int               numValues               = (int)product(m_workGroupSize);
188                 const int               valLoc                  = gl.getUniformLocation(program, "u_val[0]");
189                 const int               refLoc                  = gl.getUniformLocation(program, "u_ref[0]");
190                 const int               iterCountLoc    = gl.getUniformLocation(program, "u_numIters");
191                 const int               scalarSize              = getDataTypeScalarSize(m_basicType);
192
193                 if (isDataTypeFloatOrVec(m_basicType))
194                 {
195                         const int               maxInt                  = m_precision == glu::PRECISION_LOWP ? 2 : 1024;
196                         const int               minInt                  = -de::min(numValues/2, maxInt);
197                         vector<float>   values                  (numValues*scalarSize);
198
199                         for (int ndx = 0; ndx < (int)values.size(); ndx++)
200                                 values[ndx] = float(minInt + (ndx % (maxInt-minInt+1)));
201
202                         for (int uNdx = 0; uNdx < 2; uNdx++)
203                         {
204                                 const int location = uNdx == 1 ? refLoc : valLoc;
205
206                                 if (scalarSize == 1)            gl.uniform1fv(location, numValues, &values[0]);
207                                 else if (scalarSize == 2)       gl.uniform2fv(location, numValues, &values[0]);
208                                 else if (scalarSize == 3)       gl.uniform3fv(location, numValues, &values[0]);
209                                 else if (scalarSize == 4)       gl.uniform4fv(location, numValues, &values[0]);
210                         }
211                 }
212                 else if (isDataTypeIntOrIVec(m_basicType))
213                 {
214                         const int               maxInt                  = m_precision == glu::PRECISION_LOWP ? 64 : 1024;
215                         const int               minInt                  = -de::min(numValues/2, maxInt);
216                         vector<int>             values                  (numValues*scalarSize);
217
218                         for (int ndx = 0; ndx < (int)values.size(); ndx++)
219                                 values[ndx] = minInt + (ndx % (maxInt-minInt+1));
220
221                         for (int uNdx = 0; uNdx < 2; uNdx++)
222                         {
223                                 const int location = uNdx == 1 ? refLoc : valLoc;
224
225                                 if (scalarSize == 1)            gl.uniform1iv(location, numValues, &values[0]);
226                                 else if (scalarSize == 2)       gl.uniform2iv(location, numValues, &values[0]);
227                                 else if (scalarSize == 3)       gl.uniform3iv(location, numValues, &values[0]);
228                                 else if (scalarSize == 4)       gl.uniform4iv(location, numValues, &values[0]);
229                         }
230                 }
231                 else if (isDataTypeUintOrUVec(m_basicType))
232                 {
233                         const deUint32          maxInt          = m_precision == glu::PRECISION_LOWP ? 128 : 1024;
234                         vector<deUint32>        values          (numValues*scalarSize);
235
236                         for (int ndx = 0; ndx < (int)values.size(); ndx++)
237                                 values[ndx] = ndx % (maxInt+1);
238
239                         for (int uNdx = 0; uNdx < 2; uNdx++)
240                         {
241                                 const int location = uNdx == 1 ? refLoc : valLoc;
242
243                                 if (scalarSize == 1)            gl.uniform1uiv(location, numValues, &values[0]);
244                                 else if (scalarSize == 2)       gl.uniform2uiv(location, numValues, &values[0]);
245                                 else if (scalarSize == 3)       gl.uniform3uiv(location, numValues, &values[0]);
246                                 else if (scalarSize == 4)       gl.uniform4uiv(location, numValues, &values[0]);
247                         }
248                 }
249                 else if (isDataTypeBoolOrBVec(m_basicType))
250                 {
251                         de::Random              rnd                             (0x324f);
252                         vector<int>             values                  (numValues*scalarSize);
253
254                         for (int ndx = 0; ndx < (int)values.size(); ndx++)
255                                 values[ndx] = rnd.getBool() ? 1 : 0;
256
257                         for (int uNdx = 0; uNdx < 2; uNdx++)
258                         {
259                                 const int location = uNdx == 1 ? refLoc : valLoc;
260
261                                 if (scalarSize == 1)            gl.uniform1iv(location, numValues, &values[0]);
262                                 else if (scalarSize == 2)       gl.uniform2iv(location, numValues, &values[0]);
263                                 else if (scalarSize == 3)       gl.uniform3iv(location, numValues, &values[0]);
264                                 else if (scalarSize == 4)       gl.uniform4iv(location, numValues, &values[0]);
265                         }
266                 }
267                 else if (isDataTypeMatrix(m_basicType))
268                 {
269                         const int               maxInt                  = m_precision == glu::PRECISION_LOWP ? 2 : 1024;
270                         const int               minInt                  = -de::min(numValues/2, maxInt);
271                         vector<float>   values                  (numValues*scalarSize);
272
273                         for (int ndx = 0; ndx < (int)values.size(); ndx++)
274                                 values[ndx] = float(minInt + (ndx % (maxInt-minInt+1)));
275
276                         for (int uNdx = 0; uNdx < 2; uNdx++)
277                         {
278                                 const int location = uNdx == 1 ? refLoc : valLoc;
279
280                                 switch (m_basicType)
281                                 {
282                                         case TYPE_FLOAT_MAT2:   gl.uniformMatrix2fv  (location, numValues, DE_FALSE, &values[0]);       break;
283                                         case TYPE_FLOAT_MAT2X3: gl.uniformMatrix2x3fv(location, numValues, DE_FALSE, &values[0]);       break;
284                                         case TYPE_FLOAT_MAT2X4: gl.uniformMatrix2x4fv(location, numValues, DE_FALSE, &values[0]);       break;
285                                         case TYPE_FLOAT_MAT3X2: gl.uniformMatrix3x2fv(location, numValues, DE_FALSE, &values[0]);       break;
286                                         case TYPE_FLOAT_MAT3:   gl.uniformMatrix3fv  (location, numValues, DE_FALSE, &values[0]);       break;
287                                         case TYPE_FLOAT_MAT3X4: gl.uniformMatrix3x4fv(location, numValues, DE_FALSE, &values[0]);       break;
288                                         case TYPE_FLOAT_MAT4X2: gl.uniformMatrix4x2fv(location, numValues, DE_FALSE, &values[0]);       break;
289                                         case TYPE_FLOAT_MAT4X3: gl.uniformMatrix4x3fv(location, numValues, DE_FALSE, &values[0]);       break;
290                                         case TYPE_FLOAT_MAT4:   gl.uniformMatrix4fv  (location, numValues, DE_FALSE, &values[0]);       break;
291                                         default:
292                                                 DE_ASSERT(false);
293                                 }
294                         }
295                 }
296
297                 gl.uniform1ui(iterCountLoc, product(m_workGroupSize));
298                 GLU_EXPECT_NO_ERROR(gl.getError(), "Input value setup failed");
299         }
300
301         // Setup output buffer.
302         {
303                 vector<deUint8> emptyData(outBlockInfo.dataSize);
304                 std::fill(emptyData.begin(), emptyData.end(), 0);
305
306                 gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, *outputBuffer);
307                 gl.bufferData(GL_SHADER_STORAGE_BUFFER, outBlockInfo.dataSize, &emptyData[0], GL_STATIC_READ);
308                 gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, *outputBuffer);
309                 GLU_EXPECT_NO_ERROR(gl.getError(), "Output buffer setup failed");
310         }
311
312         gl.dispatchCompute(1, 1, 1);
313
314         // Read back and compare
315         {
316                 const deUint32                          numValues       = product(m_workGroupSize);
317                 const InterfaceVariableInfo     outVarInfo      = getProgramInterfaceVariableInfo(gl, program, GL_BUFFER_VARIABLE, outBlockInfo.activeVariables[0]);
318                 const void*                                     resPtr          = gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, outBlockInfo.dataSize, GL_MAP_READ_BIT);
319                 const int                                       maxErrMsg       = 10;
320                 int                                                     numFailed       = 0;
321
322                 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange()");
323                 TCU_CHECK(resPtr);
324
325                 for (deUint32 ndx = 0; ndx < numValues; ndx++)
326                 {
327                         const int resVal = *((const int*)((const deUint8*)resPtr + outVarInfo.offset + outVarInfo.arrayStride*ndx));
328
329                         if (resVal == 0)
330                         {
331                                 if (numFailed < maxErrMsg)
332                                         m_testCtx.getLog() << TestLog::Message << "ERROR: isOk[" << ndx << "] = " << resVal << " != true" << TestLog::EndMessage;
333                                 else if (numFailed == maxErrMsg)
334                                         m_testCtx.getLog() << TestLog::Message << "..." << TestLog::EndMessage;
335
336                                 numFailed += 1;
337                         }
338                 }
339
340                 gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
341                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer()");
342
343                 m_testCtx.getLog() << TestLog::Message << (numValues-numFailed) << " / " << numValues << " values passed" << TestLog::EndMessage;
344
345                 m_testCtx.setTestResult(numFailed == 0 ? QP_TEST_RESULT_PASS    : QP_TEST_RESULT_FAIL,
346                                                                 numFailed == 0 ? "Pass"                                 : "Comparison failed");
347         }
348
349         return STOP;
350 }
351
352 ShaderSharedVarTests::ShaderSharedVarTests (Context& context)
353         : TestCaseGroup(context, "shared_var", "Shared Variable Tests")
354 {
355 }
356
357 ShaderSharedVarTests::~ShaderSharedVarTests (void)
358 {
359 }
360
361 void ShaderSharedVarTests::init (void)
362 {
363         // .basic_type
364         {
365                 tcu::TestCaseGroup *const basicTypeGroup = new tcu::TestCaseGroup(m_testCtx, "basic_type", "Basic Types");
366                 addChild(basicTypeGroup);
367
368                 for (int basicType = TYPE_FLOAT; basicType <= TYPE_BOOL_VEC4; basicType++)
369                 {
370                         if (glu::getDataTypeScalarType(DataType(basicType)) == glu::TYPE_DOUBLE)
371                                 continue;
372
373                         if (glu::isDataTypeBoolOrBVec(DataType(basicType)))
374                         {
375                                 const tcu::UVec3        workGroupSize   (2,1,3);
376                                 basicTypeGroup->addChild(new SharedBasicVarCase(m_context, getDataTypeName(DataType(basicType)), DataType(basicType), PRECISION_LAST, workGroupSize));
377                         }
378                         else
379                         {
380                                 for (int precision = 0; precision < PRECISION_LAST; precision++)
381                                 {
382                                         const tcu::UVec3        workGroupSize   (2,1,3);
383                                         const string            name                    = string(getDataTypeName(DataType(basicType))) + "_" + getPrecisionName(Precision(precision));
384
385                                         basicTypeGroup->addChild(new SharedBasicVarCase(m_context, name.c_str(), DataType(basicType), Precision(precision), workGroupSize));
386                                 }
387                         }
388                 }
389         }
390
391         // .work_group_size
392         {
393                 tcu::TestCaseGroup *const workGroupSizeGroup = new tcu::TestCaseGroup(m_testCtx, "work_group_size", "Shared Variables with Various Work Group Sizes");
394                 addChild(workGroupSizeGroup);
395
396                 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "float_1_1_1",           TYPE_FLOAT,                     PRECISION_HIGHP,        tcu::UVec3(1,1,1)));
397                 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "float_64_1_1",          TYPE_FLOAT,                     PRECISION_HIGHP,        tcu::UVec3(64,1,1)));
398                 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "float_1_64_1",          TYPE_FLOAT,                     PRECISION_HIGHP,        tcu::UVec3(1,64,1)));
399                 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "float_1_1_64",          TYPE_FLOAT,                     PRECISION_HIGHP,        tcu::UVec3(1,1,64)));
400                 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "float_128_1_1",         TYPE_FLOAT,                     PRECISION_HIGHP,        tcu::UVec3(128,1,1)));
401                 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "float_1_128_1",         TYPE_FLOAT,                     PRECISION_HIGHP,        tcu::UVec3(1,128,1)));
402                 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "float_13_2_4",          TYPE_FLOAT,                     PRECISION_HIGHP,        tcu::UVec3(13,2,4)));
403
404                 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "vec4_1_1_1",            TYPE_FLOAT_VEC4,        PRECISION_HIGHP,        tcu::UVec3(1,1,1)));
405                 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "vec4_64_1_1",           TYPE_FLOAT_VEC4,        PRECISION_HIGHP,        tcu::UVec3(64,1,1)));
406                 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "vec4_1_64_1",           TYPE_FLOAT_VEC4,        PRECISION_HIGHP,        tcu::UVec3(1,64,1)));
407                 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "vec4_1_1_64",           TYPE_FLOAT_VEC4,        PRECISION_HIGHP,        tcu::UVec3(1,1,64)));
408                 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "vec4_128_1_1",          TYPE_FLOAT_VEC4,        PRECISION_HIGHP,        tcu::UVec3(128,1,1)));
409                 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "vec4_1_128_1",          TYPE_FLOAT_VEC4,        PRECISION_HIGHP,        tcu::UVec3(1,128,1)));
410                 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "vec4_13_2_4",           TYPE_FLOAT_VEC4,        PRECISION_HIGHP,        tcu::UVec3(13,2,4)));
411
412                 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "mat4_1_1_1",            TYPE_FLOAT_MAT4,        PRECISION_HIGHP,        tcu::UVec3(1,1,1)));
413                 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "mat4_64_1_1",           TYPE_FLOAT_MAT4,        PRECISION_HIGHP,        tcu::UVec3(64,1,1)));
414                 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "mat4_1_64_1",           TYPE_FLOAT_MAT4,        PRECISION_HIGHP,        tcu::UVec3(1,64,1)));
415                 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "mat4_1_1_64",           TYPE_FLOAT_MAT4,        PRECISION_HIGHP,        tcu::UVec3(1,1,64)));
416                 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "mat4_128_1_1",          TYPE_FLOAT_MAT4,        PRECISION_HIGHP,        tcu::UVec3(128,1,1)));
417                 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "mat4_1_128_1",          TYPE_FLOAT_MAT4,        PRECISION_HIGHP,        tcu::UVec3(1,128,1)));
418                 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "mat4_13_2_4",           TYPE_FLOAT_MAT4,        PRECISION_HIGHP,        tcu::UVec3(13,2,4)));
419         }
420
421         // .atomic
422         addChild(new ShaderAtomicOpTests(m_context, "atomic", ATOMIC_OPERAND_SHARED_VARIABLE));
423 }
424
425 } // Functional
426 } // gles31
427 } // deqp