1/*------------------------------------------------------------------------- 2 * OpenGL Conformance Test Suite 3 * ----------------------------- 4 * 5 * Copyright (c) 2016-2017 The Khronos Group Inc. 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 22 */ /*-------------------------------------------------------------------*/ 23 24/** 25 */ /*! 26 * \file glcParallelShaderCompileTests.cpp 27 * \brief Conformance tests for the GL_KHR_parallel_shader_compile functionality. 28 */ /*-------------------------------------------------------------------*/ 29 30#include "glcParallelShaderCompileTests.hpp" 31#include "deClock.h" 32#include "gluContextInfo.hpp" 33#include "gluDefs.hpp" 34#include "gluShaderProgram.hpp" 35#include "glwEnums.hpp" 36#include "glwFunctions.hpp" 37#include "tcuTestLog.hpp" 38 39using namespace glu; 40using namespace glw; 41 42namespace glcts 43{ 44 45static const char* shaderVersionES = "#version 300 es\n"; 46static const char* shaderVersionGL = "#version 450\n"; 47static const char* vShader = "\n" 48 "in vec3 vertex;\n" 49 "\n" 50 "void main() {\n" 51 " gl_Position = vec4(vertex, 1);\n" 52 "}\n"; 53 54static const char* fShader = "\n" 55 "out vec4 fragColor;\n" 56 "\n" 57 "void main() {\n" 58 " fragColor = vec4(1, 1, 1, 1);\n" 59 "}\n"; 60 61/** Constructor. 62 * 63 * @param context Rendering context 64 * @param name Test name 65 * @param description Test description 66 */ 67SimpleQueriesTest::SimpleQueriesTest(deqp::Context& context) 68 : TestCase(context, "simple_queries", 69 "Tests verifies if simple queries works as expected for MAX_SHADER_COMPILER_THREADS_KHR <pname>") 70{ 71 /* Left blank intentionally */ 72} 73 74/** Executes test iteration. 75 * 76 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 77 */ 78tcu::TestNode::IterateResult SimpleQueriesTest::iterate() 79{ 80 const glu::ContextInfo& contextInfo = m_context.getContextInfo(); 81 const glu::ContextType& contextType = m_context.getRenderContext().getType(); 82 const bool isGL = glu::isContextTypeGLCore(contextType); 83 const bool supportParallel = (isGL && contextInfo.isExtensionSupported("GL_ARB_parallel_shader_compile")) || 84 contextInfo.isExtensionSupported("GL_KHR_parallel_shader_compile"); 85 86 if (!supportParallel) 87 { 88 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported"); 89 return STOP; 90 } 91 92 const Functions& gl = m_context.getRenderContext().getFunctions(); 93 94 GLboolean boolValue; 95 GLint intValue; 96 GLint64 int64Value; 97 GLfloat floatValue; 98 GLdouble doubleValue; 99 100 bool supportsInt64 = isGL || glu::contextSupports(contextType, glu::ApiType::es(3, 0)); 101 bool supportsDouble = isGL; 102 103 gl.getBooleanv(GL_MAX_SHADER_COMPILER_THREADS_KHR, &boolValue); 104 GLU_EXPECT_NO_ERROR(gl.getError(), "getBooleanv"); 105 106 gl.getIntegerv(GL_MAX_SHADER_COMPILER_THREADS_KHR, &intValue); 107 GLU_EXPECT_NO_ERROR(gl.getError(), "getIntegerv"); 108 109 if (supportsInt64) 110 { 111 gl.getInteger64v(GL_MAX_SHADER_COMPILER_THREADS_KHR, &int64Value); 112 GLU_EXPECT_NO_ERROR(gl.getError(), "getInteger64v"); 113 } 114 115 gl.getFloatv(GL_MAX_SHADER_COMPILER_THREADS_KHR, &floatValue); 116 GLU_EXPECT_NO_ERROR(gl.getError(), "getFloatv"); 117 118 if (supportsDouble) 119 { 120 gl.getDoublev(GL_MAX_SHADER_COMPILER_THREADS_KHR, &doubleValue); 121 GLU_EXPECT_NO_ERROR(gl.getError(), "getDoublev"); 122 } 123 124 if (boolValue != (intValue != 0) || intValue != (GLint)floatValue || 125 (supportsInt64 && intValue != (GLint)int64Value) || (supportsDouble && intValue != (GLint)doubleValue)) 126 { 127 tcu::MessageBuilder message = m_testCtx.getLog() << tcu::TestLog::Message; 128 129 message << "Simple queries returned different values: " 130 << "bool(" << (int)boolValue << "), " 131 << "int(" << intValue << "), "; 132 133 if (supportsInt64) 134 message << "int64(" << int64Value << "), "; 135 136 message << "float(" << floatValue << ")"; 137 138 if (supportsDouble) 139 message << ", double(" << doubleValue << ")"; 140 141 message << tcu::TestLog::EndMessage; 142 143 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 144 return STOP; 145 } 146 147 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 148 return STOP; 149} 150 151/** Constructor. 152 * 153 * @param context Rendering context 154 * @param name Test name 155 * @param description Test description 156 */ 157MaxShaderCompileThreadsTest::MaxShaderCompileThreadsTest(deqp::Context& context) 158 : TestCase(context, "max_shader_compile_threads", 159 "Tests verifies if MaxShaderCompileThreadsKHR function works as expected") 160{ 161 /* Left blank intentionally */ 162} 163 164/** Executes test iteration. 165 * 166 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 167 */ 168tcu::TestNode::IterateResult MaxShaderCompileThreadsTest::iterate() 169{ 170 const glu::ContextInfo& contextInfo = m_context.getContextInfo(); 171 const glu::ContextType& contextType = m_context.getRenderContext().getType(); 172 const bool isGL = glu::isContextTypeGLCore(contextType); 173 const bool supportParallel = (isGL && contextInfo.isExtensionSupported("GL_ARB_parallel_shader_compile")) || 174 contextInfo.isExtensionSupported("GL_KHR_parallel_shader_compile"); 175 176 if (!supportParallel) 177 { 178 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported"); 179 return STOP; 180 } 181 182 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 183 184 GLint intValue; 185 186 gl.maxShaderCompilerThreadsKHR(0); 187 GLU_EXPECT_NO_ERROR(gl.getError(), "maxShaderCompilerThreadsKHR"); 188 189 gl.getIntegerv(GL_MAX_SHADER_COMPILER_THREADS_KHR, &intValue); 190 GLU_EXPECT_NO_ERROR(gl.getError(), "getIntegerv"); 191 192 if (intValue != 0) 193 { 194 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Failed to disable parallel shader compilation."); 195 return STOP; 196 } 197 198 gl.maxShaderCompilerThreadsKHR(0xFFFFFFFF); 199 GLU_EXPECT_NO_ERROR(gl.getError(), "maxShaderCompilerThreadsKHR"); 200 201 gl.getIntegerv(GL_MAX_SHADER_COMPILER_THREADS_KHR, &intValue); 202 GLU_EXPECT_NO_ERROR(gl.getError(), "getIntegerv"); 203 204 if (intValue != GLint(0xFFFFFFFF)) 205 { 206 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Failed to set maximum shader compiler threads."); 207 return STOP; 208 } 209 210 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 211 return STOP; 212} 213 214/** Constructor. 215 * 216 * @param context Rendering context 217 * @param name Test name 218 * @param description Test description 219 */ 220CompilationCompletionParallelTest::CompilationCompletionParallelTest(deqp::Context& context) 221 : TestCase(context, "compilation_completion_parallel", 222 "Tests verifies if shader COMPLETION_STATUS query works as expected for parallel compilation") 223{ 224 /* Left blank intentionally */ 225} 226 227/** Executes test iteration. 228 * 229 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. 230 */ 231tcu::TestNode::IterateResult CompilationCompletionParallelTest::iterate() 232{ 233 const glu::ContextInfo& contextInfo = m_context.getContextInfo(); 234 const glu::ContextType& contextType = m_context.getRenderContext().getType(); 235 const bool isGL = glu::isContextTypeGLCore(contextType); 236 const bool supportParallel = (isGL && contextInfo.isExtensionSupported("GL_ARB_parallel_shader_compile")) || 237 contextInfo.isExtensionSupported("GL_KHR_parallel_shader_compile"); 238 239 if (!supportParallel) 240 { 241 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported"); 242 return STOP; 243 } 244 245 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 246 247 GLint completionStatus; 248 249 gl.maxShaderCompilerThreadsKHR(8); 250 GLU_EXPECT_NO_ERROR(gl.getError(), "maxShaderCompilerThreadsKHR"); 251 252 { 253 Shader vertexShader(gl, SHADERTYPE_VERTEX); 254 deUint32 fragmentShader[8]; 255 deUint32 program[8]; 256 257 bool isContextES = (glu::isContextTypeES(m_context.getRenderContext().getType())); 258 const char* shaderVersion = isContextES ? shaderVersionES : shaderVersionGL; 259 260 for (int i = 0; i < 8; ++i) 261 { 262 fragmentShader[i] = gl.createShader(GL_FRAGMENT_SHADER); 263 program[i] = gl.createProgram(); 264 } 265 266 const char* vSources[] = { shaderVersion, vShader }; 267 const int vLengths[] = { int(strlen(shaderVersion)), int(strlen(vShader)) }; 268 vertexShader.setSources(2, vSources, vLengths); 269 270 //Compilation test 271 for (int i = 0; i < 8; ++i) 272 { 273 const char* fSources[] = { shaderVersion, fShader }; 274 const int fLengths[] = { int(strlen(shaderVersion)), int(strlen(fShader)) }; 275 gl.shaderSource(fragmentShader[i], 2, fSources, fLengths); 276 } 277 278 gl.compileShader(vertexShader.getShader()); 279 GLU_EXPECT_NO_ERROR(gl.getError(), "compileShader"); 280 for (int i = 0; i < 8; ++i) 281 { 282 gl.compileShader(fragmentShader[i]); 283 GLU_EXPECT_NO_ERROR(gl.getError(), "compileShader"); 284 } 285 286 { 287 int completion = 0; 288 deUint64 shLoopStart = deGetMicroseconds(); 289 while (completion != 8 && deGetMicroseconds() < shLoopStart + 1000000) 290 { 291 completion = 0; 292 for (int i = 0; i < 8; ++i) 293 { 294 gl.getShaderiv(fragmentShader[i], GL_COMPLETION_STATUS_KHR, &completionStatus); 295 GLU_EXPECT_NO_ERROR(gl.getError(), "getShaderiv"); 296 if (completionStatus) 297 completion++; 298 } 299 } 300 if (completion != 8) 301 { 302 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, 303 "Failed reading completion status for parallel shader compiling"); 304 for (int i = 0; i < 8; ++i) 305 { 306 gl.deleteProgram(program[i]); 307 gl.deleteShader(fragmentShader[i]); 308 } 309 return STOP; 310 } 311 } 312 313 for (int i = 0; i < 8; ++i) 314 { 315 gl.attachShader(program[i], vertexShader.getShader()); 316 GLU_EXPECT_NO_ERROR(gl.getError(), "attachShader"); 317 gl.attachShader(program[i], fragmentShader[i]); 318 GLU_EXPECT_NO_ERROR(gl.getError(), "attachShader"); 319 } 320 321 //Linking test 322 for (int i = 0; i < 8; ++i) 323 { 324 gl.linkProgram(program[i]); 325 GLU_EXPECT_NO_ERROR(gl.getError(), "linkProgram"); 326 } 327 328 { 329 int completion = 0; 330 deUint64 prLoopStart = deGetMicroseconds(); 331 while (completion != 8 && deGetMicroseconds() < prLoopStart + 1000000) 332 { 333 completion = 0; 334 for (int i = 0; i < 8; ++i) 335 { 336 gl.getProgramiv(program[i], GL_COMPLETION_STATUS_KHR, &completionStatus); 337 GLU_EXPECT_NO_ERROR(gl.getError(), "getProgramiv"); 338 if (completionStatus) 339 completion++; 340 } 341 } 342 if (completion != 8) 343 { 344 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, 345 "Failed reading completion status for parallel program linking"); 346 for (int i = 0; i < 8; ++i) 347 { 348 gl.deleteProgram(program[i]); 349 gl.deleteShader(fragmentShader[i]); 350 } 351 return STOP; 352 } 353 } 354 } 355 356 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 357 return STOP; 358} 359 360/** Constructor. 361 * 362 * @param context Rendering context. 363 */ 364ParallelShaderCompileTests::ParallelShaderCompileTests(deqp::Context& context) 365 : TestCaseGroup(context, "parallel_shader_compile", 366 "Verify conformance of KHR_parallel_shader_compile implementation") 367{ 368} 369 370/** Initializes the test group contents. */ 371void ParallelShaderCompileTests::init() 372{ 373 addChild(new SimpleQueriesTest(m_context)); 374 addChild(new MaxShaderCompileThreadsTest(m_context)); 375 addChild(new CompilationCompletionParallelTest(m_context)); 376} 377 378} /* glcts namespace */ 379