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::isDataTypeBoolOrBVec(DataType(basicType))) 371 { 372 const tcu::UVec3 workGroupSize (2,1,3); 373 basicTypeGroup->addChild(new SharedBasicVarCase(m_context, getDataTypeName(DataType(basicType)), DataType(basicType), PRECISION_LAST, workGroupSize)); 374 } 375 else 376 { 377 for (int precision = 0; precision < PRECISION_LAST; precision++) 378 { 379 const tcu::UVec3 workGroupSize (2,1,3); 380 const string name = string(getDataTypeName(DataType(basicType))) + "_" + getPrecisionName(Precision(precision)); 381 382 basicTypeGroup->addChild(new SharedBasicVarCase(m_context, name.c_str(), DataType(basicType), Precision(precision), workGroupSize)); 383 } 384 } 385 } 386 } 387 388 // .work_group_size 389 { 390 tcu::TestCaseGroup *const workGroupSizeGroup = new tcu::TestCaseGroup(m_testCtx, "work_group_size", "Shared Variables with Various Work Group Sizes"); 391 addChild(workGroupSizeGroup); 392 393 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "float_1_1_1", TYPE_FLOAT, PRECISION_HIGHP, tcu::UVec3(1,1,1))); 394 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "float_64_1_1", TYPE_FLOAT, PRECISION_HIGHP, tcu::UVec3(64,1,1))); 395 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "float_1_64_1", TYPE_FLOAT, PRECISION_HIGHP, tcu::UVec3(1,64,1))); 396 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "float_1_1_64", TYPE_FLOAT, PRECISION_HIGHP, tcu::UVec3(1,1,64))); 397 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "float_128_1_1", TYPE_FLOAT, PRECISION_HIGHP, tcu::UVec3(128,1,1))); 398 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "float_1_128_1", TYPE_FLOAT, PRECISION_HIGHP, tcu::UVec3(1,128,1))); 399 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "float_13_2_4", TYPE_FLOAT, PRECISION_HIGHP, tcu::UVec3(13,2,4))); 400 401 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "vec4_1_1_1", TYPE_FLOAT_VEC4, PRECISION_HIGHP, tcu::UVec3(1,1,1))); 402 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "vec4_64_1_1", TYPE_FLOAT_VEC4, PRECISION_HIGHP, tcu::UVec3(64,1,1))); 403 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "vec4_1_64_1", TYPE_FLOAT_VEC4, PRECISION_HIGHP, tcu::UVec3(1,64,1))); 404 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "vec4_1_1_64", TYPE_FLOAT_VEC4, PRECISION_HIGHP, tcu::UVec3(1,1,64))); 405 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "vec4_128_1_1", TYPE_FLOAT_VEC4, PRECISION_HIGHP, tcu::UVec3(128,1,1))); 406 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "vec4_1_128_1", TYPE_FLOAT_VEC4, PRECISION_HIGHP, tcu::UVec3(1,128,1))); 407 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "vec4_13_2_4", TYPE_FLOAT_VEC4, PRECISION_HIGHP, tcu::UVec3(13,2,4))); 408 409 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "mat4_1_1_1", TYPE_FLOAT_MAT4, PRECISION_HIGHP, tcu::UVec3(1,1,1))); 410 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "mat4_64_1_1", TYPE_FLOAT_MAT4, PRECISION_HIGHP, tcu::UVec3(64,1,1))); 411 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "mat4_1_64_1", TYPE_FLOAT_MAT4, PRECISION_HIGHP, tcu::UVec3(1,64,1))); 412 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "mat4_1_1_64", TYPE_FLOAT_MAT4, PRECISION_HIGHP, tcu::UVec3(1,1,64))); 413 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "mat4_128_1_1", TYPE_FLOAT_MAT4, PRECISION_HIGHP, tcu::UVec3(128,1,1))); 414 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "mat4_1_128_1", TYPE_FLOAT_MAT4, PRECISION_HIGHP, tcu::UVec3(1,128,1))); 415 workGroupSizeGroup->addChild(new SharedBasicVarCase(m_context, "mat4_13_2_4", TYPE_FLOAT_MAT4, PRECISION_HIGHP, tcu::UVec3(13,2,4))); 416 } 417 418 // .atomic 419 addChild(new ShaderAtomicOpTests(m_context, "atomic", ATOMIC_OPERAND_SHARED_VARIABLE)); 420 } 421 422 } // Functional 423 } // gles31 424 } // deqp 425