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
39 using namespace glu;
40 using namespace glw;
41
42 namespace glcts
43 {
44
45 static const char* shaderVersionES = "#version 300 es\n";
46 static const char* shaderVersionGL = "#version 450\n";
47 static 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
54 static 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 */
SimpleQueriesTest(deqp::Context & context)67 SimpleQueriesTest::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 */
iterate()78 tcu::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 */
MaxShaderCompileThreadsTest(deqp::Context & context)157 MaxShaderCompileThreadsTest::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 */
iterate()168 tcu::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 */
CompilationCompletionParallelTest(deqp::Context & context)220 CompilationCompletionParallelTest::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 */
iterate()231 tcu::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 */
ParallelShaderCompileTests(deqp::Context & context)364 ParallelShaderCompileTests::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. */
init()371 void 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