xref: /aosp_15_r20/external/deqp/modules/gles31/functional/es31fShaderSharedVarTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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::set;
51 using std::string;
52 using std::vector;
53 using tcu::TestLog;
54 using tcu::UVec3;
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>
product(const tcu::Vector<T,Size> & v)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,
75                        const tcu::UVec3 &workGroupSize);
76     ~SharedBasicVarCase(void);
77 
78     void init(void);
79     void deinit(void);
80     IterateResult iterate(void);
81 
82 private:
83     SharedBasicVarCase(const SharedBasicVarCase &other);
84     SharedBasicVarCase &operator=(const SharedBasicVarCase &other);
85 
86     const DataType m_basicType;
87     const Precision m_precision;
88     const tcu::UVec3 m_workGroupSize;
89 
90     ShaderProgram *m_program;
91 };
92 
getBasicCaseDescription(DataType basicType,Precision precision,const tcu::UVec3 & workGroupSize)93 static std::string getBasicCaseDescription(DataType basicType, Precision precision, const tcu::UVec3 &workGroupSize)
94 {
95     std::ostringstream str;
96     if (precision != PRECISION_LAST)
97         str << getPrecisionName(precision) << " ";
98     str << getDataTypeName(basicType) << ", work group size = " << workGroupSize;
99     return str.str();
100 }
101 
SharedBasicVarCase(Context & context,const char * name,DataType basicType,Precision precision,const tcu::UVec3 & workGroupSize)102 SharedBasicVarCase::SharedBasicVarCase(Context &context, const char *name, DataType basicType, Precision precision,
103                                        const tcu::UVec3 &workGroupSize)
104     : TestCase(context, name, getBasicCaseDescription(basicType, precision, workGroupSize).c_str())
105     , m_basicType(basicType)
106     , m_precision(precision)
107     , m_workGroupSize(workGroupSize)
108     , m_program(DE_NULL)
109 {
110 }
111 
~SharedBasicVarCase(void)112 SharedBasicVarCase::~SharedBasicVarCase(void)
113 {
114     SharedBasicVarCase::deinit();
115 }
116 
init(void)117 void SharedBasicVarCase::init(void)
118 {
119     const int valArrayLength = de::min<int>(MAX_VALUE_ARRAY_LENGTH, product(m_workGroupSize));
120     const char *precName     = m_precision != glu::PRECISION_LAST ? getPrecisionName(m_precision) : "";
121     const char *typeName     = getDataTypeName(m_basicType);
122     std::ostringstream src;
123 
124     src << "#version 310 es\n"
125         << "layout (local_size_x = " << m_workGroupSize[0] << ", local_size_y = " << m_workGroupSize[1]
126         << ", local_size_z = " << m_workGroupSize[2] << ") 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 
deinit(void)169 void SharedBasicVarCase::deinit(void)
170 {
171     delete m_program;
172     m_program = DE_NULL;
173 }
174 
iterate(void)175 SharedBasicVarCase::IterateResult SharedBasicVarCase::iterate(void)
176 {
177     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
178     const uint32_t program   = m_program->getProgram();
179     Buffer outputBuffer(m_context.getRenderContext());
180     const uint32_t outBlockNdx = gl.getProgramResourceIndex(program, GL_SHADER_STORAGE_BLOCK, "Result");
181     const InterfaceBlockInfo outBlockInfo =
182         getProgramInterfaceBlockInfo(gl, program, GL_SHADER_STORAGE_BLOCK, outBlockNdx);
183 
184     gl.useProgram(program);
185 
186     // Setup input values.
187     {
188         const int numValues    = (int)product(m_workGroupSize);
189         const int valLoc       = gl.getUniformLocation(program, "u_val[0]");
190         const int refLoc       = gl.getUniformLocation(program, "u_ref[0]");
191         const int iterCountLoc = gl.getUniformLocation(program, "u_numIters");
192         const int scalarSize   = getDataTypeScalarSize(m_basicType);
193 
194         if (isDataTypeFloatOrVec(m_basicType))
195         {
196             const int maxInt = m_precision == glu::PRECISION_LOWP ? 2 : 1024;
197             const int minInt = -de::min(numValues / 2, maxInt);
198             vector<float> values(numValues * scalarSize);
199 
200             for (int ndx = 0; ndx < (int)values.size(); ndx++)
201                 values[ndx] = float(minInt + (ndx % (maxInt - minInt + 1)));
202 
203             for (int uNdx = 0; uNdx < 2; uNdx++)
204             {
205                 const int location = uNdx == 1 ? refLoc : valLoc;
206 
207                 if (scalarSize == 1)
208                     gl.uniform1fv(location, numValues, &values[0]);
209                 else if (scalarSize == 2)
210                     gl.uniform2fv(location, numValues, &values[0]);
211                 else if (scalarSize == 3)
212                     gl.uniform3fv(location, numValues, &values[0]);
213                 else if (scalarSize == 4)
214                     gl.uniform4fv(location, numValues, &values[0]);
215             }
216         }
217         else if (isDataTypeIntOrIVec(m_basicType))
218         {
219             const int maxInt = m_precision == glu::PRECISION_LOWP ? 64 : 1024;
220             const int minInt = -de::min(numValues / 2, maxInt);
221             vector<int> values(numValues * scalarSize);
222 
223             for (int ndx = 0; ndx < (int)values.size(); ndx++)
224                 values[ndx] = minInt + (ndx % (maxInt - minInt + 1));
225 
226             for (int uNdx = 0; uNdx < 2; uNdx++)
227             {
228                 const int location = uNdx == 1 ? refLoc : valLoc;
229 
230                 if (scalarSize == 1)
231                     gl.uniform1iv(location, numValues, &values[0]);
232                 else if (scalarSize == 2)
233                     gl.uniform2iv(location, numValues, &values[0]);
234                 else if (scalarSize == 3)
235                     gl.uniform3iv(location, numValues, &values[0]);
236                 else if (scalarSize == 4)
237                     gl.uniform4iv(location, numValues, &values[0]);
238             }
239         }
240         else if (isDataTypeUintOrUVec(m_basicType))
241         {
242             const uint32_t maxInt = m_precision == glu::PRECISION_LOWP ? 128 : 1024;
243             vector<uint32_t> values(numValues * scalarSize);
244 
245             for (int ndx = 0; ndx < (int)values.size(); ndx++)
246                 values[ndx] = ndx % (maxInt + 1);
247 
248             for (int uNdx = 0; uNdx < 2; uNdx++)
249             {
250                 const int location = uNdx == 1 ? refLoc : valLoc;
251 
252                 if (scalarSize == 1)
253                     gl.uniform1uiv(location, numValues, &values[0]);
254                 else if (scalarSize == 2)
255                     gl.uniform2uiv(location, numValues, &values[0]);
256                 else if (scalarSize == 3)
257                     gl.uniform3uiv(location, numValues, &values[0]);
258                 else if (scalarSize == 4)
259                     gl.uniform4uiv(location, numValues, &values[0]);
260             }
261         }
262         else if (isDataTypeBoolOrBVec(m_basicType))
263         {
264             de::Random rnd(0x324f);
265             vector<int> values(numValues * scalarSize);
266 
267             for (int ndx = 0; ndx < (int)values.size(); ndx++)
268                 values[ndx] = rnd.getBool() ? 1 : 0;
269 
270             for (int uNdx = 0; uNdx < 2; uNdx++)
271             {
272                 const int location = uNdx == 1 ? refLoc : valLoc;
273 
274                 if (scalarSize == 1)
275                     gl.uniform1iv(location, numValues, &values[0]);
276                 else if (scalarSize == 2)
277                     gl.uniform2iv(location, numValues, &values[0]);
278                 else if (scalarSize == 3)
279                     gl.uniform3iv(location, numValues, &values[0]);
280                 else if (scalarSize == 4)
281                     gl.uniform4iv(location, numValues, &values[0]);
282             }
283         }
284         else if (isDataTypeMatrix(m_basicType))
285         {
286             const int maxInt = m_precision == glu::PRECISION_LOWP ? 2 : 1024;
287             const int minInt = -de::min(numValues / 2, maxInt);
288             vector<float> values(numValues * scalarSize);
289 
290             for (int ndx = 0; ndx < (int)values.size(); ndx++)
291                 values[ndx] = float(minInt + (ndx % (maxInt - minInt + 1)));
292 
293             for (int uNdx = 0; uNdx < 2; uNdx++)
294             {
295                 const int location = uNdx == 1 ? refLoc : valLoc;
296 
297                 switch (m_basicType)
298                 {
299                 case TYPE_FLOAT_MAT2:
300                     gl.uniformMatrix2fv(location, numValues, false, &values[0]);
301                     break;
302                 case TYPE_FLOAT_MAT2X3:
303                     gl.uniformMatrix2x3fv(location, numValues, false, &values[0]);
304                     break;
305                 case TYPE_FLOAT_MAT2X4:
306                     gl.uniformMatrix2x4fv(location, numValues, false, &values[0]);
307                     break;
308                 case TYPE_FLOAT_MAT3X2:
309                     gl.uniformMatrix3x2fv(location, numValues, false, &values[0]);
310                     break;
311                 case TYPE_FLOAT_MAT3:
312                     gl.uniformMatrix3fv(location, numValues, false, &values[0]);
313                     break;
314                 case TYPE_FLOAT_MAT3X4:
315                     gl.uniformMatrix3x4fv(location, numValues, false, &values[0]);
316                     break;
317                 case TYPE_FLOAT_MAT4X2:
318                     gl.uniformMatrix4x2fv(location, numValues, false, &values[0]);
319                     break;
320                 case TYPE_FLOAT_MAT4X3:
321                     gl.uniformMatrix4x3fv(location, numValues, false, &values[0]);
322                     break;
323                 case TYPE_FLOAT_MAT4:
324                     gl.uniformMatrix4fv(location, numValues, false, &values[0]);
325                     break;
326                 default:
327                     DE_ASSERT(false);
328                 }
329             }
330         }
331 
332         gl.uniform1ui(iterCountLoc, product(m_workGroupSize));
333         GLU_EXPECT_NO_ERROR(gl.getError(), "Input value setup failed");
334     }
335 
336     // Setup output buffer.
337     {
338         vector<uint8_t> emptyData(outBlockInfo.dataSize);
339         std::fill(emptyData.begin(), emptyData.end(), 0);
340 
341         gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, *outputBuffer);
342         gl.bufferData(GL_SHADER_STORAGE_BUFFER, outBlockInfo.dataSize, &emptyData[0], GL_STATIC_READ);
343         gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, *outputBuffer);
344         GLU_EXPECT_NO_ERROR(gl.getError(), "Output buffer setup failed");
345     }
346 
347     gl.dispatchCompute(1, 1, 1);
348 
349     // Read back and compare
350     {
351         const uint32_t numValues = product(m_workGroupSize);
352         const InterfaceVariableInfo outVarInfo =
353             getProgramInterfaceVariableInfo(gl, program, GL_BUFFER_VARIABLE, outBlockInfo.activeVariables[0]);
354         const void *resPtr  = gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, outBlockInfo.dataSize, GL_MAP_READ_BIT);
355         const int maxErrMsg = 10;
356         int numFailed       = 0;
357 
358         GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange()");
359         TCU_CHECK(resPtr);
360 
361         for (uint32_t ndx = 0; ndx < numValues; ndx++)
362         {
363             const int resVal =
364                 *((const int *)((const uint8_t *)resPtr + outVarInfo.offset + outVarInfo.arrayStride * ndx));
365 
366             if (resVal == 0)
367             {
368                 if (numFailed < maxErrMsg)
369                     m_testCtx.getLog() << TestLog::Message << "ERROR: isOk[" << ndx << "] = " << resVal << " != true"
370                                        << TestLog::EndMessage;
371                 else if (numFailed == maxErrMsg)
372                     m_testCtx.getLog() << TestLog::Message << "..." << TestLog::EndMessage;
373 
374                 numFailed += 1;
375             }
376         }
377 
378         gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
379         GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer()");
380 
381         m_testCtx.getLog() << TestLog::Message << (numValues - numFailed) << " / " << numValues << " values passed"
382                            << TestLog::EndMessage;
383 
384         m_testCtx.setTestResult(numFailed == 0 ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
385                                 numFailed == 0 ? "Pass" : "Comparison failed");
386     }
387 
388     return STOP;
389 }
390 
ShaderSharedVarTests(Context & context)391 ShaderSharedVarTests::ShaderSharedVarTests(Context &context)
392     : TestCaseGroup(context, "shared_var", "Shared Variable Tests")
393 {
394 }
395 
~ShaderSharedVarTests(void)396 ShaderSharedVarTests::~ShaderSharedVarTests(void)
397 {
398 }
399 
init(void)400 void ShaderSharedVarTests::init(void)
401 {
402     // .basic_type
403     {
404         tcu::TestCaseGroup *const basicTypeGroup = new tcu::TestCaseGroup(m_testCtx, "basic_type", "Basic Types");
405         addChild(basicTypeGroup);
406 
407         for (int basicType = TYPE_FLOAT; basicType <= TYPE_BOOL_VEC4; basicType++)
408         {
409             if (glu::getDataTypeScalarType(DataType(basicType)) == glu::TYPE_DOUBLE)
410                 continue;
411 
412             if (glu::isDataTypeBoolOrBVec(DataType(basicType)))
413             {
414                 const tcu::UVec3 workGroupSize(2, 1, 3);
415                 basicTypeGroup->addChild(new SharedBasicVarCase(m_context, getDataTypeName(DataType(basicType)),
416                                                                 DataType(basicType), PRECISION_LAST, workGroupSize));
417             }
418             else
419             {
420                 for (int precision = 0; precision < PRECISION_LAST; precision++)
421                 {
422                     const tcu::UVec3 workGroupSize(2, 1, 3);
423                     const string name =
424                         string(getDataTypeName(DataType(basicType))) + "_" + getPrecisionName(Precision(precision));
425 
426                     basicTypeGroup->addChild(new SharedBasicVarCase(m_context, name.c_str(), DataType(basicType),
427                                                                     Precision(precision), workGroupSize));
428                 }
429             }
430         }
431     }
432 
433     // .work_group_size
434     {
435         tcu::TestCaseGroup *const workGroupSizeGroup =
436             new tcu::TestCaseGroup(m_testCtx, "work_group_size", "Shared Variables with Various Work Group Sizes");
437         addChild(workGroupSizeGroup);
438 
439         workGroupSizeGroup->addChild(
440             new SharedBasicVarCase(m_context, "float_1_1_1", TYPE_FLOAT, PRECISION_HIGHP, tcu::UVec3(1, 1, 1)));
441         workGroupSizeGroup->addChild(
442             new SharedBasicVarCase(m_context, "float_64_1_1", TYPE_FLOAT, PRECISION_HIGHP, tcu::UVec3(64, 1, 1)));
443         workGroupSizeGroup->addChild(
444             new SharedBasicVarCase(m_context, "float_1_64_1", TYPE_FLOAT, PRECISION_HIGHP, tcu::UVec3(1, 64, 1)));
445         workGroupSizeGroup->addChild(
446             new SharedBasicVarCase(m_context, "float_1_1_64", TYPE_FLOAT, PRECISION_HIGHP, tcu::UVec3(1, 1, 64)));
447         workGroupSizeGroup->addChild(
448             new SharedBasicVarCase(m_context, "float_128_1_1", TYPE_FLOAT, PRECISION_HIGHP, tcu::UVec3(128, 1, 1)));
449         workGroupSizeGroup->addChild(
450             new SharedBasicVarCase(m_context, "float_1_128_1", TYPE_FLOAT, PRECISION_HIGHP, tcu::UVec3(1, 128, 1)));
451         workGroupSizeGroup->addChild(
452             new SharedBasicVarCase(m_context, "float_13_2_4", TYPE_FLOAT, PRECISION_HIGHP, tcu::UVec3(13, 2, 4)));
453 
454         workGroupSizeGroup->addChild(
455             new SharedBasicVarCase(m_context, "vec4_1_1_1", TYPE_FLOAT_VEC4, PRECISION_HIGHP, tcu::UVec3(1, 1, 1)));
456         workGroupSizeGroup->addChild(
457             new SharedBasicVarCase(m_context, "vec4_64_1_1", TYPE_FLOAT_VEC4, PRECISION_HIGHP, tcu::UVec3(64, 1, 1)));
458         workGroupSizeGroup->addChild(
459             new SharedBasicVarCase(m_context, "vec4_1_64_1", TYPE_FLOAT_VEC4, PRECISION_HIGHP, tcu::UVec3(1, 64, 1)));
460         workGroupSizeGroup->addChild(
461             new SharedBasicVarCase(m_context, "vec4_1_1_64", TYPE_FLOAT_VEC4, PRECISION_HIGHP, tcu::UVec3(1, 1, 64)));
462         workGroupSizeGroup->addChild(
463             new SharedBasicVarCase(m_context, "vec4_128_1_1", TYPE_FLOAT_VEC4, PRECISION_HIGHP, tcu::UVec3(128, 1, 1)));
464         workGroupSizeGroup->addChild(
465             new SharedBasicVarCase(m_context, "vec4_1_128_1", TYPE_FLOAT_VEC4, PRECISION_HIGHP, tcu::UVec3(1, 128, 1)));
466         workGroupSizeGroup->addChild(
467             new SharedBasicVarCase(m_context, "vec4_13_2_4", TYPE_FLOAT_VEC4, PRECISION_HIGHP, tcu::UVec3(13, 2, 4)));
468 
469         workGroupSizeGroup->addChild(
470             new SharedBasicVarCase(m_context, "mat4_1_1_1", TYPE_FLOAT_MAT4, PRECISION_HIGHP, tcu::UVec3(1, 1, 1)));
471         workGroupSizeGroup->addChild(
472             new SharedBasicVarCase(m_context, "mat4_64_1_1", TYPE_FLOAT_MAT4, PRECISION_HIGHP, tcu::UVec3(64, 1, 1)));
473         workGroupSizeGroup->addChild(
474             new SharedBasicVarCase(m_context, "mat4_1_64_1", TYPE_FLOAT_MAT4, PRECISION_HIGHP, tcu::UVec3(1, 64, 1)));
475         workGroupSizeGroup->addChild(
476             new SharedBasicVarCase(m_context, "mat4_1_1_64", TYPE_FLOAT_MAT4, PRECISION_HIGHP, tcu::UVec3(1, 1, 64)));
477         workGroupSizeGroup->addChild(
478             new SharedBasicVarCase(m_context, "mat4_128_1_1", TYPE_FLOAT_MAT4, PRECISION_HIGHP, tcu::UVec3(128, 1, 1)));
479         workGroupSizeGroup->addChild(
480             new SharedBasicVarCase(m_context, "mat4_1_128_1", TYPE_FLOAT_MAT4, PRECISION_HIGHP, tcu::UVec3(1, 128, 1)));
481         workGroupSizeGroup->addChild(
482             new SharedBasicVarCase(m_context, "mat4_13_2_4", TYPE_FLOAT_MAT4, PRECISION_HIGHP, tcu::UVec3(13, 2, 4)));
483     }
484 
485     // .atomic
486     addChild(new ShaderAtomicOpTests(m_context, "atomic", ATOMIC_OPERAND_SHARED_VARIABLE));
487 }
488 
489 } // namespace Functional
490 } // namespace gles31
491 } // namespace deqp
492