1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 2.0 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 Rbo state query tests.
22 *//*--------------------------------------------------------------------*/
23
24 #include "es2fShaderStateQueryTests.hpp"
25 #include "glsStateQueryUtil.hpp"
26 #include "es2fApiCase.hpp"
27 #include "gluRenderContext.hpp"
28 #include "gluShaderProgram.hpp"
29 #include "glwEnums.hpp"
30 #include "glwFunctions.hpp"
31 #include "deRandom.hpp"
32 #include "deMath.h"
33 #include "deString.h"
34
35 using namespace glw; // GLint and other GL types
36 using deqp::gls::StateQueryUtil::StateQueryMemoryWriteGuard;
37
38 namespace deqp
39 {
40 namespace gles2
41 {
42 namespace Functional
43 {
44 namespace
45 {
46
47 static const char *commonTestVertSource = "void main (void)\n"
48 "{\n"
49 " gl_Position = vec4(0.0);\n"
50 "}\n";
51 static const char *commonTestFragSource = "void main (void)\n"
52 "{\n"
53 " gl_FragColor = vec4(0.0);\n"
54 "}\n";
55
56 static const char *brokenShader = "broken, this should not compile!\n"
57 "\n";
58
59 // rounds x.1 to x+1
60 template <typename T>
roundGLfloatToNearestIntegerUp(GLfloat val)61 T roundGLfloatToNearestIntegerUp(GLfloat val)
62 {
63 return (T)(ceil(val));
64 }
65
66 // rounds x.9 to x
67 template <typename T>
roundGLfloatToNearestIntegerDown(GLfloat val)68 T roundGLfloatToNearestIntegerDown(GLfloat val)
69 {
70 return (T)(floor(val));
71 }
72
checkIntEquals(tcu::TestContext & testCtx,GLint got,GLint expected)73 bool checkIntEquals(tcu::TestContext &testCtx, GLint got, GLint expected)
74 {
75 using tcu::TestLog;
76
77 if (got != expected)
78 {
79 testCtx.getLog() << TestLog::Message << "// ERROR: Expected " << expected << "; got " << got
80 << TestLog::EndMessage;
81 if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
82 testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid value");
83 return false;
84 }
85 return true;
86 }
87
checkPointerEquals(tcu::TestContext & testCtx,const void * got,const void * expected)88 void checkPointerEquals(tcu::TestContext &testCtx, const void *got, const void *expected)
89 {
90 using tcu::TestLog;
91
92 if (got != expected)
93 {
94 testCtx.getLog() << TestLog::Message << "// ERROR: Expected " << expected << "; got " << got
95 << TestLog::EndMessage;
96 if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
97 testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid value");
98 }
99 }
100
verifyShaderParam(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLuint shader,GLenum pname,GLenum reference)101 void verifyShaderParam(tcu::TestContext &testCtx, glu::CallLogWrapper &gl, GLuint shader, GLenum pname,
102 GLenum reference)
103 {
104 StateQueryMemoryWriteGuard<GLint> state;
105 gl.glGetShaderiv(shader, pname, &state);
106
107 if (state.verifyValidity(testCtx))
108 checkIntEquals(testCtx, state, reference);
109 }
110
verifyProgramParam(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLuint program,GLenum pname,GLenum reference)111 bool verifyProgramParam(tcu::TestContext &testCtx, glu::CallLogWrapper &gl, GLuint program, GLenum pname,
112 GLenum reference)
113 {
114 StateQueryMemoryWriteGuard<GLint> state;
115 gl.glGetProgramiv(program, pname, &state);
116
117 if (state.verifyValidity(testCtx))
118 return checkIntEquals(testCtx, state, reference);
119 return false;
120 }
121
verifyCurrentVertexAttribf(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLint index,GLfloat x,GLfloat y,GLfloat z,GLfloat w)122 void verifyCurrentVertexAttribf(tcu::TestContext &testCtx, glu::CallLogWrapper &gl, GLint index, GLfloat x, GLfloat y,
123 GLfloat z, GLfloat w)
124 {
125 using tcu::TestLog;
126
127 StateQueryMemoryWriteGuard<GLfloat[4]> attribValue;
128 gl.glGetVertexAttribfv(index, GL_CURRENT_VERTEX_ATTRIB, attribValue);
129
130 attribValue.verifyValidity(testCtx);
131
132 if (attribValue[0] != x || attribValue[1] != y || attribValue[2] != z || attribValue[3] != w)
133 {
134 testCtx.getLog() << TestLog::Message << "// ERROR: Expected [" << x << "," << y << "," << z << "," << w << "];"
135 << "got [" << attribValue[0] << "," << attribValue[1] << "," << attribValue[2] << ","
136 << attribValue[3] << "]" << TestLog::EndMessage;
137 if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
138 testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid attribute value");
139 }
140 }
141
verifyCurrentVertexAttribConversion(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLint index,GLfloat x,GLfloat y,GLfloat z,GLfloat w)142 void verifyCurrentVertexAttribConversion(tcu::TestContext &testCtx, glu::CallLogWrapper &gl, GLint index, GLfloat x,
143 GLfloat y, GLfloat z, GLfloat w)
144 {
145 using tcu::TestLog;
146
147 StateQueryMemoryWriteGuard<GLint[4]> attribValue;
148 gl.glGetVertexAttribiv(index, GL_CURRENT_VERTEX_ATTRIB, attribValue);
149
150 attribValue.verifyValidity(testCtx);
151
152 const GLint referenceAsGLintMin[] = {
153 roundGLfloatToNearestIntegerDown<GLint>(x), roundGLfloatToNearestIntegerDown<GLint>(y),
154 roundGLfloatToNearestIntegerDown<GLint>(z), roundGLfloatToNearestIntegerDown<GLint>(w)};
155 const GLint referenceAsGLintMax[] = {
156 roundGLfloatToNearestIntegerUp<GLint>(x), roundGLfloatToNearestIntegerUp<GLint>(y),
157 roundGLfloatToNearestIntegerUp<GLint>(z), roundGLfloatToNearestIntegerUp<GLint>(w)};
158
159 if (attribValue[0] < referenceAsGLintMin[0] || attribValue[0] > referenceAsGLintMax[0] ||
160 attribValue[1] < referenceAsGLintMin[1] || attribValue[1] > referenceAsGLintMax[1] ||
161 attribValue[2] < referenceAsGLintMin[2] || attribValue[2] > referenceAsGLintMax[2] ||
162 attribValue[3] < referenceAsGLintMin[3] || attribValue[3] > referenceAsGLintMax[3])
163 {
164 testCtx.getLog() << TestLog::Message << "// ERROR: expected in range "
165 << "[" << referenceAsGLintMin[0] << " " << referenceAsGLintMax[0] << "], "
166 << "[" << referenceAsGLintMin[1] << " " << referenceAsGLintMax[1] << "], "
167 << "[" << referenceAsGLintMin[2] << " " << referenceAsGLintMax[2] << "], "
168 << "[" << referenceAsGLintMin[3] << " " << referenceAsGLintMax[3] << "]"
169 << "; got " << attribValue[0] << ", " << attribValue[1] << ", " << attribValue[2] << ", "
170 << attribValue[3] << " "
171 << "; Input=" << x << "; " << y << "; " << z << "; " << w << " " << TestLog::EndMessage;
172
173 if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
174 testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid attribute value");
175 }
176 }
177
verifyVertexAttrib(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLint index,GLenum pname,GLenum reference)178 void verifyVertexAttrib(tcu::TestContext &testCtx, glu::CallLogWrapper &gl, GLint index, GLenum pname, GLenum reference)
179 {
180 StateQueryMemoryWriteGuard<GLint> state;
181 gl.glGetVertexAttribiv(index, pname, &state);
182
183 if (state.verifyValidity(testCtx))
184 checkIntEquals(testCtx, state, reference);
185 }
186
verifyUniformValue1f(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLuint program,GLint location,float x)187 void verifyUniformValue1f(tcu::TestContext &testCtx, glu::CallLogWrapper &gl, GLuint program, GLint location, float x)
188 {
189 using tcu::TestLog;
190
191 StateQueryMemoryWriteGuard<GLfloat[1]> state;
192 gl.glGetUniformfv(program, location, state);
193
194 if (!state.verifyValidity(testCtx))
195 return;
196
197 if (state[0] != x)
198 {
199 testCtx.getLog() << TestLog::Message << "// ERROR: expected [" << x << "]; got [" << state[0] << "]"
200 << TestLog::EndMessage;
201
202 if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
203 testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
204 }
205 }
206
verifyUniformValue2f(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLuint program,GLint location,float x,float y)207 void verifyUniformValue2f(tcu::TestContext &testCtx, glu::CallLogWrapper &gl, GLuint program, GLint location, float x,
208 float y)
209 {
210 using tcu::TestLog;
211
212 StateQueryMemoryWriteGuard<GLfloat[2]> state;
213 gl.glGetUniformfv(program, location, state);
214
215 if (!state.verifyValidity(testCtx))
216 return;
217
218 if (state[0] != x || state[1] != y)
219 {
220 testCtx.getLog() << TestLog::Message << "// ERROR: expected [" << x << ", " << y << "]; got [" << state[0]
221 << ", " << state[1] << "]" << TestLog::EndMessage;
222
223 if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
224 testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
225 }
226 }
227
verifyUniformValue3f(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLuint program,GLint location,float x,float y,float z)228 void verifyUniformValue3f(tcu::TestContext &testCtx, glu::CallLogWrapper &gl, GLuint program, GLint location, float x,
229 float y, float z)
230 {
231 using tcu::TestLog;
232
233 StateQueryMemoryWriteGuard<GLfloat[3]> state;
234 gl.glGetUniformfv(program, location, state);
235
236 if (!state.verifyValidity(testCtx))
237 return;
238
239 if (state[0] != x || state[1] != y || state[2] != z)
240 {
241 testCtx.getLog() << TestLog::Message << "// ERROR: expected [" << x << ", " << y << ", " << z << "]; got ["
242 << state[0] << ", " << state[1] << ", " << state[2] << "]" << TestLog::EndMessage;
243
244 if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
245 testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
246 }
247 }
248
verifyUniformValue4f(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLuint program,GLint location,float x,float y,float z,float w)249 void verifyUniformValue4f(tcu::TestContext &testCtx, glu::CallLogWrapper &gl, GLuint program, GLint location, float x,
250 float y, float z, float w)
251 {
252 using tcu::TestLog;
253
254 StateQueryMemoryWriteGuard<GLfloat[4]> state;
255 gl.glGetUniformfv(program, location, state);
256
257 if (!state.verifyValidity(testCtx))
258 return;
259
260 if (state[0] != x || state[1] != y || state[2] != z || state[3] != w)
261 {
262 testCtx.getLog() << TestLog::Message << "// ERROR: expected [" << x << ", " << y << ", " << z << ", " << w
263 << "]; got [" << state[0] << ", " << state[1] << ", " << state[2] << ", " << state[3] << "]"
264 << TestLog::EndMessage;
265
266 if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
267 testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
268 }
269 }
270
verifyUniformValue1i(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLuint program,GLint location,GLint x)271 void verifyUniformValue1i(tcu::TestContext &testCtx, glu::CallLogWrapper &gl, GLuint program, GLint location, GLint x)
272 {
273 using tcu::TestLog;
274
275 StateQueryMemoryWriteGuard<GLint[1]> state;
276 gl.glGetUniformiv(program, location, state);
277
278 if (!state.verifyValidity(testCtx))
279 return;
280
281 if (state[0] != x)
282 {
283 testCtx.getLog() << TestLog::Message << "// ERROR: expected [" << x << "]; got [" << state[0] << "]"
284 << TestLog::EndMessage;
285
286 if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
287 testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
288 }
289 }
290
verifyUniformValue2i(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLuint program,GLint location,GLint x,GLint y)291 void verifyUniformValue2i(tcu::TestContext &testCtx, glu::CallLogWrapper &gl, GLuint program, GLint location, GLint x,
292 GLint y)
293 {
294 using tcu::TestLog;
295
296 StateQueryMemoryWriteGuard<GLint[2]> state;
297 gl.glGetUniformiv(program, location, state);
298
299 if (!state.verifyValidity(testCtx))
300 return;
301
302 if (state[0] != x || state[1] != y)
303 {
304 testCtx.getLog() << TestLog::Message << "// ERROR: expected [" << x << ", " << y << "]; got [" << state[0]
305 << ", " << state[1] << "]" << TestLog::EndMessage;
306
307 if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
308 testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
309 }
310 }
311
verifyUniformValue3i(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLuint program,GLint location,GLint x,GLint y,GLint z)312 void verifyUniformValue3i(tcu::TestContext &testCtx, glu::CallLogWrapper &gl, GLuint program, GLint location, GLint x,
313 GLint y, GLint z)
314 {
315 using tcu::TestLog;
316
317 StateQueryMemoryWriteGuard<GLint[3]> state;
318 gl.glGetUniformiv(program, location, state);
319
320 if (!state.verifyValidity(testCtx))
321 return;
322
323 if (state[0] != x || state[1] != y || state[2] != z)
324 {
325 testCtx.getLog() << TestLog::Message << "// ERROR: expected [" << x << ", " << y << ", " << z << "]; got ["
326 << state[0] << ", " << state[1] << ", " << state[2] << "]" << TestLog::EndMessage;
327
328 if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
329 testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
330 }
331 }
332
verifyUniformValue4i(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLuint program,GLint location,GLint x,GLint y,GLint z,GLint w)333 void verifyUniformValue4i(tcu::TestContext &testCtx, glu::CallLogWrapper &gl, GLuint program, GLint location, GLint x,
334 GLint y, GLint z, GLint w)
335 {
336 using tcu::TestLog;
337
338 StateQueryMemoryWriteGuard<GLint[4]> state;
339 gl.glGetUniformiv(program, location, state);
340
341 if (!state.verifyValidity(testCtx))
342 return;
343
344 if (state[0] != x || state[1] != y || state[2] != z || state[3] != w)
345 {
346 testCtx.getLog() << TestLog::Message << "// ERROR: expected [" << x << ", " << y << ", " << z << ", " << w
347 << "]; got [" << state[0] << ", " << state[1] << ", " << state[2] << ", " << state[3] << "]"
348 << TestLog::EndMessage;
349
350 if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
351 testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
352 }
353 }
354
355 template <int Count>
verifyUniformValues(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLuint program,GLint location,const GLfloat * values)356 void verifyUniformValues(tcu::TestContext &testCtx, glu::CallLogWrapper &gl, GLuint program, GLint location,
357 const GLfloat *values)
358 {
359 using tcu::TestLog;
360
361 StateQueryMemoryWriteGuard<GLfloat[Count]> state;
362 gl.glGetUniformfv(program, location, state);
363
364 if (!state.verifyValidity(testCtx))
365 return;
366
367 for (int ndx = 0; ndx < Count; ++ndx)
368 {
369 if (values[ndx] != state[ndx])
370 {
371 testCtx.getLog() << TestLog::Message << "// ERROR: at index " << ndx << " expected " << values[ndx]
372 << "; got " << state[ndx] << TestLog::EndMessage;
373
374 if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
375 testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
376 }
377 }
378 }
379
380 template <int N>
verifyUniformMatrixValues(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLuint program,GLint location,const GLfloat * values,bool transpose)381 void verifyUniformMatrixValues(tcu::TestContext &testCtx, glu::CallLogWrapper &gl, GLuint program, GLint location,
382 const GLfloat *values, bool transpose)
383 {
384 using tcu::TestLog;
385
386 StateQueryMemoryWriteGuard<GLfloat[N * N]> state;
387 gl.glGetUniformfv(program, location, state);
388
389 if (!state.verifyValidity(testCtx))
390 return;
391
392 for (int y = 0; y < N; ++y)
393 for (int x = 0; x < N; ++x)
394 {
395 const int refIndex = y * N + x;
396 const int stateIndex = transpose ? (x * N + y) : (y * N + x);
397
398 if (values[refIndex] != state[stateIndex])
399 {
400 testCtx.getLog() << TestLog::Message << "// ERROR: at index [" << y << "][" << x << "] expected "
401 << values[refIndex] << "; got " << state[stateIndex] << TestLog::EndMessage;
402
403 if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
404 testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
405 }
406 }
407 }
408
requireShaderCompiler(tcu::TestContext & testCtx,glu::CallLogWrapper & gl)409 void requireShaderCompiler(tcu::TestContext &testCtx, glu::CallLogWrapper &gl)
410 {
411 StateQueryMemoryWriteGuard<GLboolean> state;
412 gl.glGetBooleanv(GL_SHADER_COMPILER, &state);
413
414 if (!state.verifyValidity(testCtx) || state != GL_TRUE)
415 throw tcu::NotSupportedError("Test requires SHADER_COMPILER = TRUE");
416 }
417
418 class ShaderTypeCase : public ApiCase
419 {
420 public:
ShaderTypeCase(Context & context,const char * name,const char * description)421 ShaderTypeCase(Context &context, const char *name, const char *description) : ApiCase(context, name, description)
422 {
423 }
424
test(void)425 void test(void)
426 {
427 const GLenum shaderTypes[] = {GL_VERTEX_SHADER, GL_FRAGMENT_SHADER};
428 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(shaderTypes); ++ndx)
429 {
430 const GLuint shader = glCreateShader(shaderTypes[ndx]);
431 verifyShaderParam(m_testCtx, *this, shader, GL_SHADER_TYPE, shaderTypes[ndx]);
432 glDeleteShader(shader);
433 }
434 }
435 };
436
437 class ShaderCompileStatusCase : public ApiCase
438 {
439 public:
ShaderCompileStatusCase(Context & context,const char * name,const char * description)440 ShaderCompileStatusCase(Context &context, const char *name, const char *description)
441 : ApiCase(context, name, description)
442 {
443 }
444
test(void)445 void test(void)
446 {
447 requireShaderCompiler(m_testCtx, *this);
448
449 GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
450 GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
451
452 verifyShaderParam(m_testCtx, *this, shaderVert, GL_COMPILE_STATUS, GL_FALSE);
453 verifyShaderParam(m_testCtx, *this, shaderFrag, GL_COMPILE_STATUS, GL_FALSE);
454
455 glShaderSource(shaderVert, 1, &commonTestVertSource, DE_NULL);
456 glShaderSource(shaderFrag, 1, &commonTestFragSource, DE_NULL);
457
458 glCompileShader(shaderVert);
459 glCompileShader(shaderFrag);
460 expectError(GL_NO_ERROR);
461
462 verifyShaderParam(m_testCtx, *this, shaderVert, GL_COMPILE_STATUS, GL_TRUE);
463 verifyShaderParam(m_testCtx, *this, shaderFrag, GL_COMPILE_STATUS, GL_TRUE);
464
465 glDeleteShader(shaderVert);
466 glDeleteShader(shaderFrag);
467 expectError(GL_NO_ERROR);
468 }
469 };
470
471 class ShaderInfoLogCase : public ApiCase
472 {
473 public:
ShaderInfoLogCase(Context & context,const char * name,const char * description)474 ShaderInfoLogCase(Context &context, const char *name, const char *description) : ApiCase(context, name, description)
475 {
476 }
477
test(void)478 void test(void)
479 {
480 requireShaderCompiler(m_testCtx, *this);
481
482 using tcu::TestLog;
483
484 // INFO_LOG_LENGTH is 0 by default and it includes null-terminator
485 const GLuint shader = glCreateShader(GL_VERTEX_SHADER);
486 verifyShaderParam(m_testCtx, *this, shader, GL_INFO_LOG_LENGTH, 0);
487
488 glShaderSource(shader, 1, &brokenShader, DE_NULL);
489 glCompileShader(shader);
490 expectError(GL_NO_ERROR);
491
492 // check the log length
493 StateQueryMemoryWriteGuard<GLint> logLength;
494 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength);
495 if (!logLength.verifyValidity(m_testCtx))
496 {
497 glDeleteShader(shader);
498 return;
499 }
500 if (logLength == 0)
501 {
502 glDeleteShader(shader);
503 return;
504 }
505
506 // check normal case
507 {
508 char buffer[2048] = {'x'}; // non-zero initialization
509
510 GLint written = 0; // written does not include null terminator
511 glGetShaderInfoLog(shader, DE_LENGTH_OF_ARRAY(buffer), &written, buffer);
512
513 // check lengths are consistent
514 if (logLength <= DE_LENGTH_OF_ARRAY(buffer))
515 {
516 if (written != logLength - 1)
517 {
518 m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected length " << logLength - 1 << "; got "
519 << written << TestLog::EndMessage;
520 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
521 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid log length");
522 }
523 }
524
525 // check null-terminator, either at end of buffer or at buffer[written]
526 const char *terminator = &buffer[DE_LENGTH_OF_ARRAY(buffer) - 1];
527 if (logLength < DE_LENGTH_OF_ARRAY(buffer))
528 terminator = &buffer[written];
529
530 if (*terminator != '\0')
531 {
532 m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected null terminator, got " << (int)*terminator
533 << TestLog::EndMessage;
534 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
535 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid log terminator");
536 }
537 }
538
539 // check with too small buffer
540 {
541 char buffer[2048] = {'x'}; // non-zero initialization
542
543 // check string always ends with \0, even with small buffers
544 GLint written = 0;
545 glGetShaderInfoLog(shader, 1, &written, buffer);
546 if (written != 0)
547 {
548 m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected length 0; got " << written
549 << TestLog::EndMessage;
550 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
551 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid log length");
552 }
553 if (buffer[0] != '\0')
554 {
555 m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected null terminator, got " << (int)buffer[0]
556 << TestLog::EndMessage;
557 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
558 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid log terminator");
559 }
560 }
561
562 glDeleteShader(shader);
563 expectError(GL_NO_ERROR);
564 }
565 };
566
567 class ShaderSourceCase : public ApiCase
568 {
569 public:
ShaderSourceCase(Context & context,const char * name,const char * description)570 ShaderSourceCase(Context &context, const char *name, const char *description) : ApiCase(context, name, description)
571 {
572 }
573
test(void)574 void test(void)
575 {
576 requireShaderCompiler(m_testCtx, *this);
577
578 using tcu::TestLog;
579
580 // SHADER_SOURCE_LENGTH does include 0-terminator
581 const GLuint shader = glCreateShader(GL_VERTEX_SHADER);
582 verifyShaderParam(m_testCtx, *this, shader, GL_SHADER_SOURCE_LENGTH, 0);
583
584 // check the SHADER_SOURCE_LENGTH
585 {
586 glShaderSource(shader, 1, &brokenShader, DE_NULL);
587 expectError(GL_NO_ERROR);
588
589 StateQueryMemoryWriteGuard<GLint> sourceLength;
590 glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &sourceLength);
591
592 sourceLength.verifyValidity(m_testCtx);
593
594 const GLint referenceLength =
595 (GLint)std::string(brokenShader).length() + 1; // including the null terminator
596 if (sourceLength != referenceLength)
597 {
598 m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected length " << referenceLength << "; got "
599 << sourceLength << TestLog::EndMessage;
600 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
601 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid source length");
602 }
603 }
604
605 // check the concat source SHADER_SOURCE_LENGTH
606 {
607 const char *shaders[] = {brokenShader, brokenShader};
608 glShaderSource(shader, 2, shaders, DE_NULL);
609 expectError(GL_NO_ERROR);
610
611 StateQueryMemoryWriteGuard<GLint> sourceLength;
612 glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &sourceLength);
613
614 sourceLength.verifyValidity(m_testCtx);
615
616 const GLint referenceLength =
617 2 * (GLint)std::string(brokenShader).length() + 1; // including the null terminator
618 if (sourceLength != referenceLength)
619 {
620 m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected length " << referenceLength << "; got "
621 << sourceLength << TestLog::EndMessage;
622 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
623 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid source length");
624 }
625 }
626
627 // check the string length
628 {
629 char buffer[2048] = {'x'};
630 DE_ASSERT(DE_LENGTH_OF_ARRAY(buffer) > 2 * (int)std::string(brokenShader).length());
631
632 GLint written = 0; // not inluding null-terminator
633 glGetShaderSource(shader, DE_LENGTH_OF_ARRAY(buffer), &written, buffer);
634
635 const GLint referenceLength = 2 * (GLint)std::string(brokenShader).length();
636 if (written != referenceLength)
637 {
638 m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected write length " << referenceLength
639 << "; got " << written << TestLog::EndMessage;
640 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
641 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid source length");
642 }
643 // check null pointer at
644 else
645 {
646 if (buffer[referenceLength] != '\0')
647 {
648 m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected null terminator at "
649 << referenceLength << TestLog::EndMessage;
650 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
651 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "did not get a null terminator");
652 }
653 }
654 }
655
656 // check with small buffer
657 {
658 char buffer[2048] = {'x'};
659
660 GLint written = 0;
661 glGetShaderSource(shader, 1, &written, buffer);
662
663 if (written != 0)
664 {
665 m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected write length 0; got " << written
666 << TestLog::EndMessage;
667 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
668 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid source length");
669 }
670 if (buffer[0] != '\0')
671 {
672 m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected null terminator; got=" << int(buffer[0])
673 << ", char=" << buffer[0] << TestLog::EndMessage;
674 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
675 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid terminator");
676 }
677 }
678
679 glDeleteShader(shader);
680 expectError(GL_NO_ERROR);
681 }
682 };
683
684 class DeleteStatusCase : public ApiCase
685 {
686 public:
DeleteStatusCase(Context & context,const char * name,const char * description)687 DeleteStatusCase(Context &context, const char *name, const char *description) : ApiCase(context, name, description)
688 {
689 }
690
test(void)691 void test(void)
692 {
693 GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
694 GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
695
696 glShaderSource(shaderVert, 1, &commonTestVertSource, DE_NULL);
697 glShaderSource(shaderFrag, 1, &commonTestFragSource, DE_NULL);
698
699 glCompileShader(shaderVert);
700 glCompileShader(shaderFrag);
701 expectError(GL_NO_ERROR);
702
703 verifyShaderParam(m_testCtx, *this, shaderVert, GL_COMPILE_STATUS, GL_TRUE);
704 verifyShaderParam(m_testCtx, *this, shaderFrag, GL_COMPILE_STATUS, GL_TRUE);
705
706 GLuint shaderProg = glCreateProgram();
707 glAttachShader(shaderProg, shaderVert);
708 glAttachShader(shaderProg, shaderFrag);
709 glLinkProgram(shaderProg);
710 expectError(GL_NO_ERROR);
711
712 verifyProgramParam(m_testCtx, *this, shaderProg, GL_LINK_STATUS, GL_TRUE);
713
714 verifyShaderParam(m_testCtx, *this, shaderVert, GL_DELETE_STATUS, GL_FALSE);
715 verifyShaderParam(m_testCtx, *this, shaderFrag, GL_DELETE_STATUS, GL_FALSE);
716 verifyProgramParam(m_testCtx, *this, shaderProg, GL_DELETE_STATUS, GL_FALSE);
717 expectError(GL_NO_ERROR);
718
719 glUseProgram(shaderProg);
720
721 glDeleteShader(shaderVert);
722 glDeleteShader(shaderFrag);
723 glDeleteProgram(shaderProg);
724 expectError(GL_NO_ERROR);
725
726 verifyShaderParam(m_testCtx, *this, shaderVert, GL_DELETE_STATUS, GL_TRUE);
727 verifyShaderParam(m_testCtx, *this, shaderFrag, GL_DELETE_STATUS, GL_TRUE);
728 verifyProgramParam(m_testCtx, *this, shaderProg, GL_DELETE_STATUS, GL_TRUE);
729 expectError(GL_NO_ERROR);
730
731 glUseProgram(0);
732 expectError(GL_NO_ERROR);
733 }
734 };
735
736 class CurrentVertexAttribInitialCase : public ApiCase
737 {
738 public:
CurrentVertexAttribInitialCase(Context & context,const char * name,const char * description)739 CurrentVertexAttribInitialCase(Context &context, const char *name, const char *description)
740 : ApiCase(context, name, description)
741 {
742 }
743
test(void)744 void test(void)
745 {
746 using tcu::TestLog;
747
748 int attribute_count = 16;
749 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &attribute_count);
750
751 // initial
752
753 for (int index = 0; index < attribute_count; ++index)
754 {
755 StateQueryMemoryWriteGuard<GLfloat[4]> attribValue;
756 glGetVertexAttribfv(index, GL_CURRENT_VERTEX_ATTRIB, attribValue);
757 attribValue.verifyValidity(m_testCtx);
758
759 if (attribValue[0] != 0.0f || attribValue[1] != 0.0f || attribValue[2] != 0.0f || attribValue[3] != 1.0f)
760 {
761 m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected [0, 0, 0, 1];"
762 << "got [" << attribValue[0] << "," << attribValue[1] << "," << attribValue[2] << ","
763 << attribValue[3] << "]" << TestLog::EndMessage;
764 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
765 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid attribute value");
766 }
767 }
768 }
769 };
770
771 class CurrentVertexAttribFloatCase : public ApiCase
772 {
773 public:
CurrentVertexAttribFloatCase(Context & context,const char * name,const char * description)774 CurrentVertexAttribFloatCase(Context &context, const char *name, const char *description)
775 : ApiCase(context, name, description)
776 {
777 }
778
test(void)779 void test(void)
780 {
781 using tcu::TestLog;
782
783 de::Random rnd(0xabcdef);
784
785 int attribute_count = 16;
786 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &attribute_count);
787
788 // test write float/read float
789
790 for (int index = 0; index < attribute_count; ++index)
791 {
792 const GLfloat x = rnd.getFloat(-64000, 64000);
793 const GLfloat y = rnd.getFloat(-64000, 64000);
794 const GLfloat z = rnd.getFloat(-64000, 64000);
795 const GLfloat w = rnd.getFloat(-64000, 64000);
796
797 glVertexAttrib4f(index, x, y, z, w);
798 verifyCurrentVertexAttribf(m_testCtx, *this, index, x, y, z, w);
799 }
800 for (int index = 0; index < attribute_count; ++index)
801 {
802 const GLfloat x = rnd.getFloat(-64000, 64000);
803 const GLfloat y = rnd.getFloat(-64000, 64000);
804 const GLfloat z = rnd.getFloat(-64000, 64000);
805 const GLfloat w = 1.0f;
806
807 glVertexAttrib3f(index, x, y, z);
808 verifyCurrentVertexAttribf(m_testCtx, *this, index, x, y, z, w);
809 }
810 for (int index = 0; index < attribute_count; ++index)
811 {
812 const GLfloat x = rnd.getFloat(-64000, 64000);
813 const GLfloat y = rnd.getFloat(-64000, 64000);
814 const GLfloat z = 0.0f;
815 const GLfloat w = 1.0f;
816
817 glVertexAttrib2f(index, x, y);
818 verifyCurrentVertexAttribf(m_testCtx, *this, index, x, y, z, w);
819 }
820 for (int index = 0; index < attribute_count; ++index)
821 {
822 const GLfloat x = rnd.getFloat(-64000, 64000);
823 const GLfloat y = 0.0f;
824 const GLfloat z = 0.0f;
825 const GLfloat w = 1.0f;
826
827 glVertexAttrib1f(index, x);
828 verifyCurrentVertexAttribf(m_testCtx, *this, index, x, y, z, w);
829 }
830 }
831 };
832
833 class CurrentVertexAttribConversionCase : public ApiCase
834 {
835 public:
CurrentVertexAttribConversionCase(Context & context,const char * name,const char * description)836 CurrentVertexAttribConversionCase(Context &context, const char *name, const char *description)
837 : ApiCase(context, name, description)
838 {
839 }
840
test(void)841 void test(void)
842 {
843 using tcu::TestLog;
844
845 de::Random rnd(0xabcdef);
846
847 int attribute_count = 16;
848 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &attribute_count);
849
850 // test write float/read float
851
852 for (int index = 0; index < attribute_count; ++index)
853 {
854 const GLfloat x = rnd.getFloat(-64000, 64000);
855 const GLfloat y = rnd.getFloat(-64000, 64000);
856 const GLfloat z = rnd.getFloat(-64000, 64000);
857 const GLfloat w = rnd.getFloat(-64000, 64000);
858
859 glVertexAttrib4f(index, x, y, z, w);
860 verifyCurrentVertexAttribConversion(m_testCtx, *this, index, x, y, z, w);
861 }
862 for (int index = 0; index < attribute_count; ++index)
863 {
864 const GLfloat x = rnd.getFloat(-64000, 64000);
865 const GLfloat y = rnd.getFloat(-64000, 64000);
866 const GLfloat z = rnd.getFloat(-64000, 64000);
867 const GLfloat w = 1.0f;
868
869 glVertexAttrib3f(index, x, y, z);
870 verifyCurrentVertexAttribConversion(m_testCtx, *this, index, x, y, z, w);
871 }
872 for (int index = 0; index < attribute_count; ++index)
873 {
874 const GLfloat x = rnd.getFloat(-64000, 64000);
875 const GLfloat y = rnd.getFloat(-64000, 64000);
876 const GLfloat z = 0.0f;
877 const GLfloat w = 1.0f;
878
879 glVertexAttrib2f(index, x, y);
880 verifyCurrentVertexAttribConversion(m_testCtx, *this, index, x, y, z, w);
881 }
882 for (int index = 0; index < attribute_count; ++index)
883 {
884 const GLfloat x = rnd.getFloat(-64000, 64000);
885 const GLfloat y = 0.0f;
886 const GLfloat z = 0.0f;
887 const GLfloat w = 1.0f;
888
889 glVertexAttrib1f(index, x);
890 verifyCurrentVertexAttribConversion(m_testCtx, *this, index, x, y, z, w);
891 }
892 }
893 };
894
895 class ProgramInfoLogCase : public ApiCase
896 {
897 public:
ProgramInfoLogCase(Context & context,const char * name,const char * description)898 ProgramInfoLogCase(Context &context, const char *name, const char *description)
899 : ApiCase(context, name, description)
900 {
901 }
902
test(void)903 void test(void)
904 {
905 using tcu::TestLog;
906
907 GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
908 GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
909
910 glShaderSource(shaderVert, 1, &brokenShader, DE_NULL);
911 glShaderSource(shaderFrag, 1, &brokenShader, DE_NULL);
912
913 glCompileShader(shaderVert);
914 glCompileShader(shaderFrag);
915 expectError(GL_NO_ERROR);
916
917 GLuint program = glCreateProgram();
918 glAttachShader(program, shaderVert);
919 glAttachShader(program, shaderFrag);
920 glLinkProgram(program);
921
922 // check INFO_LOG_LENGTH == GetProgramInfoLog len
923 {
924 char buffer[2048] = {'x'};
925
926 GLint written = 0;
927 glGetProgramInfoLog(program, DE_LENGTH_OF_ARRAY(buffer), &written, buffer);
928
929 StateQueryMemoryWriteGuard<GLint> logLength;
930 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
931 logLength.verifyValidity(m_testCtx);
932
933 if (logLength != 0 && written + 1 != logLength) // INFO_LOG_LENGTH contains 0-terminator
934 {
935 m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected INFO_LOG_LENGTH " << written + 1
936 << "; got " << logLength << TestLog::EndMessage;
937 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
938 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid log length");
939 }
940 }
941
942 // check GetProgramInfoLog works with too small buffer
943 {
944 char buffer[2048] = {'x'};
945
946 GLint written = 0;
947 glGetProgramInfoLog(program, 1, &written, buffer);
948
949 if (written != 0)
950 {
951 m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected write length 0; got " << written
952 << TestLog::EndMessage;
953 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
954 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid log length");
955 }
956 }
957
958 glDeleteShader(shaderVert);
959 glDeleteShader(shaderFrag);
960 glDeleteProgram(program);
961 expectError(GL_NO_ERROR);
962 }
963 };
964
965 class ProgramValidateStatusCase : public ApiCase
966 {
967 public:
ProgramValidateStatusCase(Context & context,const char * name,const char * description)968 ProgramValidateStatusCase(Context &context, const char *name, const char *description)
969 : ApiCase(context, name, description)
970 {
971 }
972
test(void)973 void test(void)
974 {
975 // test validate ok
976 {
977 GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
978 GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
979
980 glShaderSource(shaderVert, 1, &commonTestVertSource, DE_NULL);
981 glShaderSource(shaderFrag, 1, &commonTestFragSource, DE_NULL);
982
983 glCompileShader(shaderVert);
984 glCompileShader(shaderFrag);
985 expectError(GL_NO_ERROR);
986
987 GLuint program = glCreateProgram();
988 glAttachShader(program, shaderVert);
989 glAttachShader(program, shaderFrag);
990 glLinkProgram(program);
991 expectError(GL_NO_ERROR);
992
993 verifyShaderParam(m_testCtx, *this, shaderVert, GL_COMPILE_STATUS, GL_TRUE);
994 verifyShaderParam(m_testCtx, *this, shaderFrag, GL_COMPILE_STATUS, GL_TRUE);
995 verifyProgramParam(m_testCtx, *this, program, GL_LINK_STATUS, GL_TRUE);
996
997 glValidateProgram(program);
998 verifyProgramParam(m_testCtx, *this, program, GL_VALIDATE_STATUS, GL_TRUE);
999
1000 glDeleteShader(shaderVert);
1001 glDeleteShader(shaderFrag);
1002 glDeleteProgram(program);
1003 expectError(GL_NO_ERROR);
1004 }
1005
1006 // test with broken shader
1007 {
1008 GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
1009 GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
1010
1011 glShaderSource(shaderVert, 1, &commonTestVertSource, DE_NULL);
1012 glShaderSource(shaderFrag, 1, &brokenShader, DE_NULL);
1013
1014 glCompileShader(shaderVert);
1015 glCompileShader(shaderFrag);
1016 expectError(GL_NO_ERROR);
1017
1018 GLuint program = glCreateProgram();
1019 glAttachShader(program, shaderVert);
1020 glAttachShader(program, shaderFrag);
1021 glLinkProgram(program);
1022 expectError(GL_NO_ERROR);
1023
1024 verifyShaderParam(m_testCtx, *this, shaderVert, GL_COMPILE_STATUS, GL_TRUE);
1025 verifyShaderParam(m_testCtx, *this, shaderFrag, GL_COMPILE_STATUS, GL_FALSE);
1026 verifyProgramParam(m_testCtx, *this, program, GL_LINK_STATUS, GL_FALSE);
1027
1028 glValidateProgram(program);
1029 verifyProgramParam(m_testCtx, *this, program, GL_VALIDATE_STATUS, GL_FALSE);
1030
1031 glDeleteShader(shaderVert);
1032 glDeleteShader(shaderFrag);
1033 glDeleteProgram(program);
1034 expectError(GL_NO_ERROR);
1035 }
1036 }
1037 };
1038
1039 class ProgramAttachedShadersCase : public ApiCase
1040 {
1041 public:
ProgramAttachedShadersCase(Context & context,const char * name,const char * description)1042 ProgramAttachedShadersCase(Context &context, const char *name, const char *description)
1043 : ApiCase(context, name, description)
1044 {
1045 }
1046
test(void)1047 void test(void)
1048 {
1049 using tcu::TestLog;
1050
1051 GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
1052 GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
1053
1054 glShaderSource(shaderVert, 1, &commonTestVertSource, DE_NULL);
1055 glShaderSource(shaderFrag, 1, &commonTestFragSource, DE_NULL);
1056
1057 glCompileShader(shaderVert);
1058 glCompileShader(shaderFrag);
1059 expectError(GL_NO_ERROR);
1060
1061 // check ATTACHED_SHADERS
1062
1063 GLuint program = glCreateProgram();
1064 verifyProgramParam(m_testCtx, *this, program, GL_ATTACHED_SHADERS, 0);
1065 expectError(GL_NO_ERROR);
1066
1067 glAttachShader(program, shaderVert);
1068 verifyProgramParam(m_testCtx, *this, program, GL_ATTACHED_SHADERS, 1);
1069 expectError(GL_NO_ERROR);
1070
1071 glAttachShader(program, shaderFrag);
1072 verifyProgramParam(m_testCtx, *this, program, GL_ATTACHED_SHADERS, 2);
1073 expectError(GL_NO_ERROR);
1074
1075 // check GetAttachedShaders
1076 {
1077 GLuint shaders[2] = {0, 0};
1078 GLint count = 0;
1079 glGetAttachedShaders(program, DE_LENGTH_OF_ARRAY(shaders), &count, shaders);
1080
1081 if (count != 2)
1082 {
1083 m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected 2; got " << count << TestLog::EndMessage;
1084 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1085 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong shader count");
1086 }
1087 // shaders are the attached shaders?
1088 if (!((shaders[0] == shaderVert && shaders[1] == shaderFrag) ||
1089 (shaders[0] == shaderFrag && shaders[1] == shaderVert)))
1090 {
1091 m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected {" << shaderVert << ", " << shaderFrag
1092 << "}; got {" << shaders[0] << ", " << shaders[1] << "}" << TestLog::EndMessage;
1093 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1094 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong shader count");
1095 }
1096 }
1097
1098 // check GetAttachedShaders with too small buffer
1099 {
1100 GLuint shaders[2] = {0, 0};
1101 GLint count = 0;
1102
1103 glGetAttachedShaders(program, 0, &count, shaders);
1104 if (count != 0)
1105 {
1106 m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected 0; got " << count << TestLog::EndMessage;
1107 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1108 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong shader count");
1109 }
1110
1111 count = 0;
1112 glGetAttachedShaders(program, 1, &count, shaders);
1113 if (count != 1)
1114 {
1115 m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected 1; got " << count << TestLog::EndMessage;
1116 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1117 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong shader count");
1118 }
1119 }
1120
1121 glDeleteShader(shaderVert);
1122 glDeleteShader(shaderFrag);
1123 glDeleteProgram(program);
1124 expectError(GL_NO_ERROR);
1125 }
1126 };
1127
1128 class ProgramActiveUniformNameCase : public ApiCase
1129 {
1130 public:
ProgramActiveUniformNameCase(Context & context,const char * name,const char * description)1131 ProgramActiveUniformNameCase(Context &context, const char *name, const char *description)
1132 : ApiCase(context, name, description)
1133 {
1134 }
1135
test(void)1136 void test(void)
1137 {
1138 using tcu::TestLog;
1139
1140 static const char *testVertSource = "uniform highp float uniformNameWithLength23;\n"
1141 "uniform highp vec2 uniformVec2;\n"
1142 "uniform highp mat4 uniformMat4;\n"
1143 "void main (void)\n"
1144 "{\n"
1145 " gl_Position = vec4(0.0) + vec4(uniformNameWithLength23) + "
1146 "vec4(uniformVec2.x) + vec4(uniformMat4[2][3]);\n"
1147 "}\n\0";
1148 static const char *testFragSource =
1149
1150 "void main (void)\n"
1151 "{\n"
1152 " gl_FragColor = vec4(0.0);\n"
1153 "}\n\0";
1154
1155 GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
1156 GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
1157
1158 glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
1159 glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
1160
1161 glCompileShader(shaderVert);
1162 glCompileShader(shaderFrag);
1163 expectError(GL_NO_ERROR);
1164
1165 GLuint program = glCreateProgram();
1166 glAttachShader(program, shaderVert);
1167 glAttachShader(program, shaderFrag);
1168 glLinkProgram(program);
1169 expectError(GL_NO_ERROR);
1170
1171 verifyProgramParam(m_testCtx, *this, program, GL_ACTIVE_UNIFORMS, 3);
1172 verifyProgramParam(m_testCtx, *this, program, GL_ACTIVE_UNIFORM_MAX_LENGTH,
1173 (GLint)std::string("uniformNameWithLength23").length() + 1); // including a null terminator
1174 expectError(GL_NO_ERROR);
1175
1176 const char *uniformNames[] = {"uniformNameWithLength23", "uniformVec2", "uniformMat4"};
1177
1178 // check names
1179 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(uniformNames); ++ndx)
1180 {
1181 char buffer[2048] = {'x'};
1182 char *bufferEnd = (buffer + 1);
1183
1184 GLint written = 0; // null terminator not included
1185 GLint size = 0;
1186 GLenum type = 0;
1187 glGetActiveUniform(program, ndx, DE_LENGTH_OF_ARRAY(buffer), &written, &size, &type, buffer);
1188
1189 if (written < DE_LENGTH_OF_ARRAY(buffer))
1190 bufferEnd = &buffer[written];
1191
1192 // find matching uniform
1193 {
1194 const std::string uniformName(buffer, bufferEnd);
1195 bool found = false;
1196
1197 for (int uniformNdx = 0; uniformNdx < DE_LENGTH_OF_ARRAY(uniformNames); ++uniformNdx)
1198 {
1199 if (uniformName == uniformNames[uniformNdx])
1200 {
1201 found = true;
1202 break;
1203 }
1204 }
1205
1206 if (!found)
1207 {
1208 m_testCtx.getLog() << TestLog::Message << "// ERROR: Got unknown uniform name: " << uniformName
1209 << TestLog::EndMessage;
1210 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1211 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong uniform name");
1212 }
1213 }
1214
1215 // and with too small buffer
1216 written = 0;
1217 glGetActiveUniform(program, ndx, 1, &written, &size, &type, buffer);
1218
1219 if (written != 0)
1220 {
1221 m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected 0 got " << written << TestLog::EndMessage;
1222 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1223 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong uniform name length");
1224 }
1225 }
1226
1227 glDeleteShader(shaderVert);
1228 glDeleteShader(shaderFrag);
1229 glDeleteProgram(program);
1230 expectError(GL_NO_ERROR);
1231 }
1232 };
1233
1234 class ProgramUniformCase : public ApiCase
1235 {
1236 public:
ProgramUniformCase(Context & context,const char * name,const char * description)1237 ProgramUniformCase(Context &context, const char *name, const char *description)
1238 : ApiCase(context, name, description)
1239 {
1240 }
1241
test(void)1242 void test(void)
1243 {
1244 const struct UniformType
1245 {
1246 const char *declaration;
1247 const char *postDeclaration;
1248 const char *precision;
1249 const char *layout;
1250 const char *getter;
1251 GLenum type;
1252 GLint size;
1253 GLint isRowMajor;
1254 } uniformTypes[] = {
1255 {"float", "", "highp", "", "uniformValue", GL_FLOAT, 1, GL_FALSE},
1256 {"float", "[2]", "highp", "", "uniformValue[1]", GL_FLOAT, 2, GL_FALSE},
1257 {"vec2", "", "highp", "", "uniformValue.x", GL_FLOAT_VEC2, 1, GL_FALSE},
1258 {"vec3", "", "highp", "", "uniformValue.x", GL_FLOAT_VEC3, 1, GL_FALSE},
1259 {"vec4", "", "highp", "", "uniformValue.x", GL_FLOAT_VEC4, 1, GL_FALSE},
1260 {"int", "", "highp", "", "float(uniformValue)", GL_INT, 1, GL_FALSE},
1261 {"ivec2", "", "highp", "", "float(uniformValue.x)", GL_INT_VEC2, 1, GL_FALSE},
1262 {"ivec3", "", "highp", "", "float(uniformValue.x)", GL_INT_VEC3, 1, GL_FALSE},
1263 {"ivec4", "", "highp", "", "float(uniformValue.x)", GL_INT_VEC4, 1, GL_FALSE},
1264 {"bool", "", "", "", "float(uniformValue)", GL_BOOL, 1, GL_FALSE},
1265 {"bvec2", "", "", "", "float(uniformValue.x)", GL_BOOL_VEC2, 1, GL_FALSE},
1266 {"bvec3", "", "", "", "float(uniformValue.x)", GL_BOOL_VEC3, 1, GL_FALSE},
1267 {"bvec4", "", "", "", "float(uniformValue.x)", GL_BOOL_VEC4, 1, GL_FALSE},
1268 {"mat2", "", "highp", "", "float(uniformValue[0][0])", GL_FLOAT_MAT2, 1, GL_FALSE},
1269 {"mat3", "", "highp", "", "float(uniformValue[0][0])", GL_FLOAT_MAT3, 1, GL_FALSE},
1270 {"mat4", "", "highp", "", "float(uniformValue[0][0])", GL_FLOAT_MAT4, 1, GL_FALSE},
1271 {"sampler2D", "", "highp", "", "float(texture2D(uniformValue, vec2(0.0, 0.0)).r)", GL_SAMPLER_2D, 1,
1272 GL_FALSE},
1273 {"samplerCube", "", "highp", "", "float(textureCube(uniformValue, vec3(0.0, 0.0, 0.0)).r)", GL_SAMPLER_CUBE,
1274 1, GL_FALSE},
1275 };
1276
1277 static const char *vertSource = "void main (void)\n"
1278 "{\n"
1279 " gl_Position = vec4(0.0);\n"
1280 "}\n\0";
1281
1282 GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
1283 GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
1284 GLuint program = glCreateProgram();
1285
1286 glAttachShader(program, shaderVert);
1287 glAttachShader(program, shaderFrag);
1288
1289 glShaderSource(shaderVert, 1, &vertSource, DE_NULL);
1290 glCompileShader(shaderVert);
1291 expectError(GL_NO_ERROR);
1292
1293 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(uniformTypes); ++ndx)
1294 {
1295 tcu::ScopedLogSection(m_log, uniformTypes[ndx].declaration,
1296 std::string("Verify type of ") + uniformTypes[ndx].declaration + " variable" +
1297 uniformTypes[ndx].postDeclaration);
1298
1299 // gen fragment shader
1300
1301 std::ostringstream frag;
1302 frag << uniformTypes[ndx].layout << "uniform " << uniformTypes[ndx].precision << " "
1303 << uniformTypes[ndx].declaration << " uniformValue" << uniformTypes[ndx].postDeclaration << ";\n";
1304 frag << "void main (void)\n";
1305 frag << "{\n";
1306 frag << " gl_FragColor = vec4(" << uniformTypes[ndx].getter << ");\n";
1307 frag << "}\n";
1308
1309 {
1310 std::string fragmentSource = frag.str();
1311 const char *fragmentSourceCStr = fragmentSource.c_str();
1312 glShaderSource(shaderFrag, 1, &fragmentSourceCStr, DE_NULL);
1313 }
1314
1315 // compile & link
1316
1317 glCompileShader(shaderFrag);
1318 glLinkProgram(program);
1319
1320 // test
1321 if (verifyProgramParam(m_testCtx, *this, program, GL_LINK_STATUS, GL_TRUE))
1322 {
1323 const GLint index = 0; // first and only active uniform
1324
1325 char buffer[] = "not written to"; // not written to
1326 GLint written = 0;
1327 GLint size = 0;
1328 GLenum type = 0;
1329 glGetActiveUniform(program, index, 0, &written, &size, &type, buffer);
1330
1331 checkIntEquals(m_testCtx, type, uniformTypes[ndx].type);
1332 checkIntEquals(m_testCtx, size, uniformTypes[ndx].size);
1333 }
1334 }
1335
1336 glDeleteShader(shaderVert);
1337 glDeleteShader(shaderFrag);
1338 glDeleteProgram(program);
1339 expectError(GL_NO_ERROR);
1340 }
1341 };
1342
1343 class ActiveAttributesCase : public ApiCase
1344 {
1345 public:
ActiveAttributesCase(Context & context,const char * name,const char * description)1346 ActiveAttributesCase(Context &context, const char *name, const char *description)
1347 : ApiCase(context, name, description)
1348 {
1349 }
1350
test(void)1351 void test(void)
1352 {
1353 using tcu::TestLog;
1354
1355 static const char *testVertSource = "attribute highp vec2 longInputAttributeName;\n"
1356 "attribute highp vec2 shortName;\n"
1357 "void main (void)\n"
1358 "{\n"
1359 " gl_Position = longInputAttributeName.yxxy + shortName.xyxy;\n"
1360 "}\n\0";
1361 static const char *testFragSource = "void main (void)\n"
1362 "{\n"
1363 " gl_FragColor = vec4(0.0);\n"
1364 "}\n\0";
1365
1366 GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
1367 GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
1368
1369 glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
1370 glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
1371
1372 glCompileShader(shaderVert);
1373 glCompileShader(shaderFrag);
1374 expectError(GL_NO_ERROR);
1375
1376 GLuint program = glCreateProgram();
1377 glAttachShader(program, shaderVert);
1378 glAttachShader(program, shaderFrag);
1379 glLinkProgram(program);
1380 expectError(GL_NO_ERROR);
1381
1382 verifyProgramParam(m_testCtx, *this, program, GL_ACTIVE_ATTRIBUTES, 2);
1383 verifyProgramParam(m_testCtx, *this, program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH,
1384 (GLint)std::string("longInputAttributeName").length() + 1); // does include null-terminator
1385
1386 // check names
1387 for (int attributeNdx = 0; attributeNdx < 2; ++attributeNdx)
1388 {
1389 char buffer[2048] = {'x'};
1390
1391 GLint written = 0;
1392 GLint size = 0;
1393 GLenum type = 0;
1394 glGetActiveAttrib(program, attributeNdx, DE_LENGTH_OF_ARRAY(buffer), &written, &size, &type, buffer);
1395 expectError(GL_NO_ERROR);
1396
1397 if (deStringBeginsWith(buffer, "longInputAttributeName"))
1398 {
1399 checkIntEquals(
1400 m_testCtx, written,
1401 (GLint)std::string("longInputAttributeName").length()); // does NOT include null-terminator
1402 }
1403 else if (deStringBeginsWith(buffer, "shortName"))
1404 {
1405 checkIntEquals(m_testCtx, written,
1406 (GLint)std::string("shortName").length()); // does NOT include null-terminator
1407 }
1408 else
1409 {
1410 m_testCtx.getLog() << TestLog::Message << "// ERROR: Got unexpected attribute name."
1411 << TestLog::EndMessage;
1412 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1413 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected name");
1414 }
1415 }
1416
1417 // and with too short buffer
1418 {
1419 char buffer[2048] = {'x'};
1420
1421 GLint written = 0;
1422 GLint size = 0;
1423 GLenum type = 0;
1424
1425 glGetActiveAttrib(program, 0, 1, &written, &size, &type, buffer);
1426 expectError(GL_NO_ERROR);
1427 checkIntEquals(m_testCtx, written, 0);
1428 }
1429
1430 glDeleteShader(shaderVert);
1431 glDeleteShader(shaderFrag);
1432 glDeleteProgram(program);
1433 expectError(GL_NO_ERROR);
1434 }
1435 };
1436
1437 struct PointerData
1438 {
1439 GLint size;
1440 GLenum type;
1441 GLint stride;
1442 GLboolean normalized;
1443 void *pointer;
1444 };
1445
1446 class VertexAttributeSizeCase : public ApiCase
1447 {
1448 public:
VertexAttributeSizeCase(Context & context,const char * name,const char * description)1449 VertexAttributeSizeCase(Context &context, const char *name, const char *description)
1450 : ApiCase(context, name, description)
1451 {
1452 }
1453
test(void)1454 void test(void)
1455 {
1456 GLfloat vertexData[4] = {0.0f}; // never accessed
1457
1458 // test VertexAttribPointer
1459 const PointerData pointers[] = {
1460 // size test
1461 {4, GL_FLOAT, 0, GL_FALSE, vertexData}, {3, GL_FLOAT, 0, GL_FALSE, vertexData},
1462 {2, GL_FLOAT, 0, GL_FALSE, vertexData}, {1, GL_FLOAT, 0, GL_FALSE, vertexData},
1463 {4, GL_SHORT, 0, GL_FALSE, vertexData}, {3, GL_SHORT, 0, GL_FALSE, vertexData},
1464 {2, GL_SHORT, 0, GL_FALSE, vertexData}, {1, GL_SHORT, 0, GL_FALSE, vertexData},
1465 };
1466
1467 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
1468 {
1469 glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].normalized,
1470 pointers[ndx].stride, pointers[ndx].pointer);
1471 expectError(GL_NO_ERROR);
1472
1473 verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_SIZE, pointers[ndx].size);
1474 }
1475 }
1476 };
1477
1478 class VertexAttributeTypeCase : public ApiCase
1479 {
1480 public:
VertexAttributeTypeCase(Context & context,const char * name,const char * description)1481 VertexAttributeTypeCase(Context &context, const char *name, const char *description)
1482 : ApiCase(context, name, description)
1483 {
1484 }
1485
test(void)1486 void test(void)
1487 {
1488 GLfloat vertexData[4] = {0.0f}; // never accessed
1489
1490 const PointerData pointers[] = {
1491 {1, GL_BYTE, 0, GL_FALSE, vertexData}, {1, GL_UNSIGNED_BYTE, 0, GL_FALSE, vertexData},
1492 {1, GL_SHORT, 0, GL_FALSE, vertexData}, {1, GL_UNSIGNED_SHORT, 0, GL_FALSE, vertexData},
1493 {1, GL_FIXED, 0, GL_FALSE, vertexData}, {1, GL_FLOAT, 0, GL_FALSE, vertexData},
1494 };
1495
1496 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
1497 {
1498 glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].normalized,
1499 pointers[ndx].stride, pointers[ndx].pointer);
1500 expectError(GL_NO_ERROR);
1501
1502 verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_TYPE, pointers[ndx].type);
1503 }
1504 }
1505 };
1506
1507 class VertexAttributeStrideCase : public ApiCase
1508 {
1509 public:
VertexAttributeStrideCase(Context & context,const char * name,const char * description)1510 VertexAttributeStrideCase(Context &context, const char *name, const char *description)
1511 : ApiCase(context, name, description)
1512 {
1513 }
1514
test(void)1515 void test(void)
1516 {
1517 GLfloat vertexData[4] = {0.0f}; // never accessed
1518
1519 struct StridePointerData
1520 {
1521 GLint size;
1522 GLenum type;
1523 GLint stride;
1524 void *pointer;
1525 };
1526
1527 // test VertexAttribPointer
1528 {
1529 const StridePointerData pointers[] = {
1530 {1, GL_FLOAT, 0, vertexData}, {1, GL_FLOAT, 1, vertexData},
1531 {1, GL_FLOAT, 4, vertexData}, {1, GL_SHORT, 0, vertexData},
1532 {1, GL_SHORT, 1, vertexData}, {1, GL_SHORT, 4, vertexData},
1533 {1, GL_FIXED, 0, vertexData}, {1, GL_FIXED, 1, vertexData},
1534 {1, GL_FIXED, 4, vertexData}, {1, GL_BYTE, 0, vertexData},
1535 {1, GL_UNSIGNED_SHORT, 1, vertexData}, {1, GL_UNSIGNED_SHORT, 4, vertexData},
1536 {4, GL_UNSIGNED_BYTE, 0, vertexData}, {4, GL_UNSIGNED_BYTE, 1, vertexData},
1537 {4, GL_UNSIGNED_BYTE, 4, vertexData},
1538 };
1539
1540 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
1541 {
1542 glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, GL_FALSE, pointers[ndx].stride,
1543 pointers[ndx].pointer);
1544 expectError(GL_NO_ERROR);
1545
1546 verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_STRIDE, pointers[ndx].stride);
1547 }
1548 }
1549 }
1550 };
1551
1552 class VertexAttributeNormalizedCase : public ApiCase
1553 {
1554 public:
VertexAttributeNormalizedCase(Context & context,const char * name,const char * description)1555 VertexAttributeNormalizedCase(Context &context, const char *name, const char *description)
1556 : ApiCase(context, name, description)
1557 {
1558 }
1559
test(void)1560 void test(void)
1561 {
1562 GLfloat vertexData[4] = {0.0f}; // never accessed
1563
1564 // test VertexAttribPointer
1565 {
1566 const PointerData pointers[] = {
1567 {1, GL_BYTE, 0, GL_FALSE, vertexData}, {1, GL_SHORT, 0, GL_FALSE, vertexData},
1568 {1, GL_UNSIGNED_BYTE, 0, GL_FALSE, vertexData}, {1, GL_UNSIGNED_SHORT, 0, GL_FALSE, vertexData},
1569 {1, GL_BYTE, 0, GL_TRUE, vertexData}, {1, GL_SHORT, 0, GL_TRUE, vertexData},
1570 {1, GL_UNSIGNED_BYTE, 0, GL_TRUE, vertexData}, {1, GL_UNSIGNED_SHORT, 0, GL_TRUE, vertexData},
1571 };
1572
1573 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
1574 {
1575 glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].normalized,
1576 pointers[ndx].stride, pointers[ndx].pointer);
1577 expectError(GL_NO_ERROR);
1578
1579 verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, pointers[ndx].normalized);
1580 }
1581 }
1582 }
1583 };
1584
1585 class VertexAttributeEnabledCase : public ApiCase
1586 {
1587 public:
VertexAttributeEnabledCase(Context & context,const char * name,const char * description)1588 VertexAttributeEnabledCase(Context &context, const char *name, const char *description)
1589 : ApiCase(context, name, description)
1590 {
1591 }
1592
test(void)1593 void test(void)
1594 {
1595 // VERTEX_ATTRIB_ARRAY_ENABLED
1596
1597 verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_ENABLED, GL_FALSE);
1598 glEnableVertexAttribArray(0);
1599 verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_ENABLED, GL_TRUE);
1600 glDisableVertexAttribArray(0);
1601 verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_ENABLED, GL_FALSE);
1602 }
1603 };
1604
1605 class VertexAttributeBufferBindingCase : public ApiCase
1606 {
1607 public:
VertexAttributeBufferBindingCase(Context & context,const char * name,const char * description)1608 VertexAttributeBufferBindingCase(Context &context, const char *name, const char *description)
1609 : ApiCase(context, name, description)
1610 {
1611 }
1612
test(void)1613 void test(void)
1614 {
1615 // initial
1616 verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, 0);
1617
1618 GLuint bufferID;
1619 glGenBuffers(1, &bufferID);
1620 glBindBuffer(GL_ARRAY_BUFFER, bufferID);
1621 expectError(GL_NO_ERROR);
1622
1623 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
1624 expectError(GL_NO_ERROR);
1625
1626 verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, bufferID);
1627
1628 glDeleteBuffers(1, &bufferID);
1629 expectError(GL_NO_ERROR);
1630 }
1631 };
1632
1633 class VertexAttributePointerCase : public ApiCase
1634 {
1635 public:
VertexAttributePointerCase(Context & context,const char * name,const char * description)1636 VertexAttributePointerCase(Context &context, const char *name, const char *description)
1637 : ApiCase(context, name, description)
1638 {
1639 }
1640
test(void)1641 void test(void)
1642 {
1643 StateQueryMemoryWriteGuard<GLvoid *> initialState;
1644 glGetVertexAttribPointerv(0, GL_VERTEX_ATTRIB_ARRAY_POINTER, &initialState);
1645 initialState.verifyValidity(m_testCtx);
1646 checkPointerEquals(m_testCtx, initialState, 0);
1647
1648 GLfloat vertexData[4] = {0.0f}; // never accessed
1649 const PointerData pointers[] = {
1650 {1, GL_BYTE, 0, GL_FALSE, &vertexData[2]}, {1, GL_SHORT, 0, GL_FALSE, &vertexData[1]},
1651 {1, GL_FIXED, 0, GL_FALSE, &vertexData[2]}, {1, GL_FIXED, 0, GL_FALSE, &vertexData[1]},
1652 {1, GL_FLOAT, 0, GL_FALSE, &vertexData[0]}, {1, GL_FLOAT, 0, GL_FALSE, &vertexData[3]},
1653 {1, GL_FLOAT, 0, GL_FALSE, &vertexData[2]}, {1, GL_UNSIGNED_SHORT, 0, GL_FALSE, &vertexData[0]},
1654 {4, GL_UNSIGNED_SHORT, 0, GL_FALSE, &vertexData[1]}, {4, GL_UNSIGNED_SHORT, 0, GL_FALSE, &vertexData[2]},
1655 };
1656
1657 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
1658 {
1659 glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].normalized,
1660 pointers[ndx].stride, pointers[ndx].pointer);
1661 expectError(GL_NO_ERROR);
1662
1663 StateQueryMemoryWriteGuard<GLvoid *> state;
1664 glGetVertexAttribPointerv(0, GL_VERTEX_ATTRIB_ARRAY_POINTER, &state);
1665 state.verifyValidity(m_testCtx);
1666 checkPointerEquals(m_testCtx, state, pointers[ndx].pointer);
1667 }
1668 }
1669 };
1670
1671 class UniformValueFloatCase : public ApiCase
1672 {
1673 public:
UniformValueFloatCase(Context & context,const char * name,const char * description)1674 UniformValueFloatCase(Context &context, const char *name, const char *description)
1675 : ApiCase(context, name, description)
1676 {
1677 }
1678
test(void)1679 void test(void)
1680 {
1681 static const char *testVertSource =
1682 "uniform highp float floatUniform;\n"
1683 "uniform highp vec2 float2Uniform;\n"
1684 "uniform highp vec3 float3Uniform;\n"
1685 "uniform highp vec4 float4Uniform;\n"
1686 "void main (void)\n"
1687 "{\n"
1688 " gl_Position = vec4(floatUniform + float2Uniform.x + float3Uniform.x + float4Uniform.x);\n"
1689 "}\n";
1690 static const char *testFragSource =
1691
1692 "void main (void)\n"
1693 "{\n"
1694 " gl_FragColor = vec4(0.0);\n"
1695 "}\n";
1696
1697 glu::ShaderProgram program(m_context.getRenderContext(),
1698 glu::makeVtxFragSources(testVertSource, testFragSource));
1699 if (!program.isOk())
1700 {
1701 m_log << program;
1702 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to compile shader");
1703 return;
1704 }
1705
1706 glUseProgram(program.getProgram());
1707 expectError(GL_NO_ERROR);
1708
1709 GLint location;
1710
1711 location = glGetUniformLocation(program.getProgram(), "floatUniform");
1712 glUniform1f(location, 1.0f);
1713 verifyUniformValue1f(m_testCtx, *this, program.getProgram(), location, 1.0f);
1714
1715 location = glGetUniformLocation(program.getProgram(), "float2Uniform");
1716 glUniform2f(location, 1.0f, 2.0f);
1717 verifyUniformValue2f(m_testCtx, *this, program.getProgram(), location, 1.0f, 2.0f);
1718
1719 location = glGetUniformLocation(program.getProgram(), "float3Uniform");
1720 glUniform3f(location, 1.0f, 2.0f, 3.0f);
1721 verifyUniformValue3f(m_testCtx, *this, program.getProgram(), location, 1.0f, 2.0f, 3.0f);
1722
1723 location = glGetUniformLocation(program.getProgram(), "float4Uniform");
1724 glUniform4f(location, 1.0f, 2.0f, 3.0f, 4.0f);
1725 verifyUniformValue4f(m_testCtx, *this, program.getProgram(), location, 1.0f, 2.0f, 3.0f, 4.0f);
1726
1727 glUseProgram(0);
1728 expectError(GL_NO_ERROR);
1729 }
1730 };
1731
1732 class UniformValueIntCase : public ApiCase
1733 {
1734 public:
UniformValueIntCase(Context & context,const char * name,const char * description)1735 UniformValueIntCase(Context &context, const char *name, const char *description)
1736 : ApiCase(context, name, description)
1737 {
1738 }
1739
test(void)1740 void test(void)
1741 {
1742 static const char *testVertSource =
1743 "uniform highp int intUniform;\n"
1744 "uniform highp ivec2 int2Uniform;\n"
1745 "uniform highp ivec3 int3Uniform;\n"
1746 "uniform highp ivec4 int4Uniform;\n"
1747 "void main (void)\n"
1748 "{\n"
1749 " gl_Position = vec4(float(intUniform + int2Uniform.x + int3Uniform.x + int4Uniform.x));\n"
1750 "}\n";
1751 static const char *testFragSource = "void main (void)\n"
1752 "{\n"
1753 " gl_FragColor = vec4(0.0);\n"
1754 "}\n";
1755
1756 glu::ShaderProgram program(m_context.getRenderContext(),
1757 glu::makeVtxFragSources(testVertSource, testFragSource));
1758 if (!program.isOk())
1759 {
1760 m_log << program;
1761 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to compile shader");
1762 return;
1763 }
1764
1765 glUseProgram(program.getProgram());
1766 expectError(GL_NO_ERROR);
1767
1768 GLint location;
1769
1770 location = glGetUniformLocation(program.getProgram(), "intUniform");
1771 glUniform1i(location, 1);
1772 verifyUniformValue1i(m_testCtx, *this, program.getProgram(), location, 1);
1773
1774 location = glGetUniformLocation(program.getProgram(), "int2Uniform");
1775 glUniform2i(location, 1, 2);
1776 verifyUniformValue2i(m_testCtx, *this, program.getProgram(), location, 1, 2);
1777
1778 location = glGetUniformLocation(program.getProgram(), "int3Uniform");
1779 glUniform3i(location, 1, 2, 3);
1780 verifyUniformValue3i(m_testCtx, *this, program.getProgram(), location, 1, 2, 3);
1781
1782 location = glGetUniformLocation(program.getProgram(), "int4Uniform");
1783 glUniform4i(location, 1, 2, 3, 4);
1784 verifyUniformValue4i(m_testCtx, *this, program.getProgram(), location, 1, 2, 3, 4);
1785
1786 glUseProgram(0);
1787 expectError(GL_NO_ERROR);
1788 }
1789 };
1790
1791 class UniformValueBooleanCase : public ApiCase
1792 {
1793 public:
UniformValueBooleanCase(Context & context,const char * name,const char * description)1794 UniformValueBooleanCase(Context &context, const char *name, const char *description)
1795 : ApiCase(context, name, description)
1796 {
1797 }
1798
test(void)1799 void test(void)
1800 {
1801 static const char *testVertSource = "uniform bool boolUniform;\n"
1802 "uniform bvec2 bool2Uniform;\n"
1803 "uniform bvec3 bool3Uniform;\n"
1804 "uniform bvec4 bool4Uniform;\n"
1805 "void main (void)\n"
1806 "{\n"
1807 " gl_Position = vec4(float(boolUniform) + float(bool2Uniform.x) + "
1808 "float(bool3Uniform.x) + float(bool4Uniform.x));\n"
1809 "}\n";
1810 static const char *testFragSource = "void main (void)\n"
1811 "{\n"
1812 " gl_FragColor = vec4(0.0);\n"
1813 "}\n";
1814
1815 glu::ShaderProgram program(m_context.getRenderContext(),
1816 glu::makeVtxFragSources(testVertSource, testFragSource));
1817 if (!program.isOk())
1818 {
1819 m_log << program;
1820 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to compile shader");
1821 return;
1822 }
1823
1824 glUseProgram(program.getProgram());
1825 expectError(GL_NO_ERROR);
1826
1827 GLint location;
1828
1829 // int conversion
1830
1831 location = glGetUniformLocation(program.getProgram(), "boolUniform");
1832 glUniform1i(location, 1);
1833 verifyUniformValue1i(m_testCtx, *this, program.getProgram(), location, 1);
1834
1835 location = glGetUniformLocation(program.getProgram(), "bool2Uniform");
1836 glUniform2i(location, 1, 2);
1837 verifyUniformValue2i(m_testCtx, *this, program.getProgram(), location, 1, 1);
1838
1839 location = glGetUniformLocation(program.getProgram(), "bool3Uniform");
1840 glUniform3i(location, 0, 1, 2);
1841 verifyUniformValue3i(m_testCtx, *this, program.getProgram(), location, 0, 1, 1);
1842
1843 location = glGetUniformLocation(program.getProgram(), "bool4Uniform");
1844 glUniform4i(location, 1, 0, 1, -1);
1845 verifyUniformValue4i(m_testCtx, *this, program.getProgram(), location, 1, 0, 1, 1);
1846
1847 // float conversion
1848
1849 location = glGetUniformLocation(program.getProgram(), "boolUniform");
1850 glUniform1f(location, 1.0f);
1851 verifyUniformValue1i(m_testCtx, *this, program.getProgram(), location, 1);
1852
1853 location = glGetUniformLocation(program.getProgram(), "bool2Uniform");
1854 glUniform2f(location, 1.0f, 0.1f);
1855 verifyUniformValue2i(m_testCtx, *this, program.getProgram(), location, 1, 1);
1856
1857 location = glGetUniformLocation(program.getProgram(), "bool3Uniform");
1858 glUniform3f(location, 0.0f, 0.1f, -0.1f);
1859 verifyUniformValue3i(m_testCtx, *this, program.getProgram(), location, 0, 1, 1);
1860
1861 location = glGetUniformLocation(program.getProgram(), "bool4Uniform");
1862 glUniform4f(location, 1.0f, 0.0f, 0.1f, -0.9f);
1863 verifyUniformValue4i(m_testCtx, *this, program.getProgram(), location, 1, 0, 1, 1);
1864
1865 glUseProgram(0);
1866 expectError(GL_NO_ERROR);
1867 }
1868 };
1869
1870 class UniformValueSamplerCase : public ApiCase
1871 {
1872 public:
UniformValueSamplerCase(Context & context,const char * name,const char * description)1873 UniformValueSamplerCase(Context &context, const char *name, const char *description)
1874 : ApiCase(context, name, description)
1875 {
1876 }
1877
test(void)1878 void test(void)
1879 {
1880 static const char *testVertSource = "void main (void)\n"
1881 "{\n"
1882 " gl_Position = vec4(0.0);\n"
1883 "}\n";
1884 static const char *testFragSource = "uniform highp sampler2D uniformSampler;\n"
1885
1886 "void main (void)\n"
1887 "{\n"
1888 " gl_FragColor = vec4(texture2D(uniformSampler, vec2(0.0, 0.0)).x);\n"
1889 "}\n";
1890
1891 glu::ShaderProgram program(m_context.getRenderContext(),
1892 glu::makeVtxFragSources(testVertSource, testFragSource));
1893 if (!program.isOk())
1894 {
1895 m_log << program;
1896 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to compile shader");
1897 return;
1898 }
1899
1900 glUseProgram(program.getProgram());
1901 expectError(GL_NO_ERROR);
1902
1903 GLint location;
1904
1905 location = glGetUniformLocation(program.getProgram(), "uniformSampler");
1906 glUniform1i(location, 1);
1907 verifyUniformValue1i(m_testCtx, *this, program.getProgram(), location, 1);
1908
1909 glUseProgram(0);
1910 expectError(GL_NO_ERROR);
1911 }
1912 };
1913
1914 class UniformValueArrayCase : public ApiCase
1915 {
1916 public:
UniformValueArrayCase(Context & context,const char * name,const char * description)1917 UniformValueArrayCase(Context &context, const char *name, const char *description)
1918 : ApiCase(context, name, description)
1919 {
1920 }
1921
test(void)1922 void test(void)
1923 {
1924 static const char *testVertSource = "uniform highp float arrayUniform[5];"
1925 "uniform highp vec2 array2Uniform[5];"
1926 "uniform highp vec3 array3Uniform[5];"
1927 "uniform highp vec4 array4Uniform[5];"
1928 "void main (void)\n"
1929 "{\n"
1930 " gl_Position = \n"
1931 " + vec4(arrayUniform[0] + arrayUniform[1] + "
1932 "arrayUniform[2] + arrayUniform[3] + arrayUniform[4])\n"
1933 " + vec4(array2Uniform[0].x + array2Uniform[1].x + "
1934 "array2Uniform[2].x + array2Uniform[3].x + array2Uniform[4].x)\n"
1935 " + vec4(array3Uniform[0].x + array3Uniform[1].x + "
1936 "array3Uniform[2].x + array3Uniform[3].x + array3Uniform[4].x)\n"
1937 " + vec4(array4Uniform[0].x + array4Uniform[1].x + "
1938 "array4Uniform[2].x + array4Uniform[3].x + array4Uniform[4].x);\n"
1939 "}\n";
1940 static const char *testFragSource =
1941
1942 "void main (void)\n"
1943 "{\n"
1944 " gl_FragColor = vec4(0.0);\n"
1945 "}\n";
1946
1947 glu::ShaderProgram program(m_context.getRenderContext(),
1948 glu::makeVtxFragSources(testVertSource, testFragSource));
1949 if (!program.isOk())
1950 {
1951 m_log << program;
1952 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to compile shader");
1953 return;
1954 }
1955
1956 glUseProgram(program.getProgram());
1957 expectError(GL_NO_ERROR);
1958
1959 GLint location;
1960
1961 float uniformValue[5 * 4] = {-1.0f, 0.1f, 4.0f, 800.0f, 13.0f, 55.0f, 12.0f, 91.0f, -55.1f, 1.1f,
1962 98.0f, 19.0f, 41.0f, 65.0f, 4.0f, 12.2f, 95.0f, 77.0f, 32.0f, 48.0f};
1963
1964 location = glGetUniformLocation(program.getProgram(), "arrayUniform");
1965 glUniform1fv(location, 5, uniformValue);
1966 expectError(GL_NO_ERROR);
1967
1968 verifyUniformValue1f(m_testCtx, *this, program.getProgram(),
1969 glGetUniformLocation(program.getProgram(), "arrayUniform[0]"), uniformValue[0]);
1970 verifyUniformValue1f(m_testCtx, *this, program.getProgram(),
1971 glGetUniformLocation(program.getProgram(), "arrayUniform[1]"), uniformValue[1]);
1972 verifyUniformValue1f(m_testCtx, *this, program.getProgram(),
1973 glGetUniformLocation(program.getProgram(), "arrayUniform[2]"), uniformValue[2]);
1974 verifyUniformValue1f(m_testCtx, *this, program.getProgram(),
1975 glGetUniformLocation(program.getProgram(), "arrayUniform[3]"), uniformValue[3]);
1976 verifyUniformValue1f(m_testCtx, *this, program.getProgram(),
1977 glGetUniformLocation(program.getProgram(), "arrayUniform[4]"), uniformValue[4]);
1978 expectError(GL_NO_ERROR);
1979
1980 location = glGetUniformLocation(program.getProgram(), "array2Uniform");
1981 glUniform2fv(location, 5, uniformValue);
1982 expectError(GL_NO_ERROR);
1983
1984 verifyUniformValue2f(m_testCtx, *this, program.getProgram(),
1985 glGetUniformLocation(program.getProgram(), "array2Uniform[0]"), uniformValue[2 * 0],
1986 uniformValue[(2 * 0) + 1]);
1987 verifyUniformValue2f(m_testCtx, *this, program.getProgram(),
1988 glGetUniformLocation(program.getProgram(), "array2Uniform[1]"), uniformValue[2 * 1],
1989 uniformValue[(2 * 1) + 1]);
1990 verifyUniformValue2f(m_testCtx, *this, program.getProgram(),
1991 glGetUniformLocation(program.getProgram(), "array2Uniform[2]"), uniformValue[2 * 2],
1992 uniformValue[(2 * 2) + 1]);
1993 verifyUniformValue2f(m_testCtx, *this, program.getProgram(),
1994 glGetUniformLocation(program.getProgram(), "array2Uniform[3]"), uniformValue[2 * 3],
1995 uniformValue[(2 * 3) + 1]);
1996 verifyUniformValue2f(m_testCtx, *this, program.getProgram(),
1997 glGetUniformLocation(program.getProgram(), "array2Uniform[4]"), uniformValue[2 * 4],
1998 uniformValue[(2 * 4) + 1]);
1999 expectError(GL_NO_ERROR);
2000
2001 location = glGetUniformLocation(program.getProgram(), "array3Uniform");
2002 glUniform3fv(location, 5, uniformValue);
2003 expectError(GL_NO_ERROR);
2004
2005 verifyUniformValue3f(m_testCtx, *this, program.getProgram(),
2006 glGetUniformLocation(program.getProgram(), "array3Uniform[0]"), uniformValue[3 * 0],
2007 uniformValue[(3 * 0) + 1], uniformValue[(3 * 0) + 2]);
2008 verifyUniformValue3f(m_testCtx, *this, program.getProgram(),
2009 glGetUniformLocation(program.getProgram(), "array3Uniform[1]"), uniformValue[3 * 1],
2010 uniformValue[(3 * 1) + 1], uniformValue[(3 * 1) + 2]);
2011 verifyUniformValue3f(m_testCtx, *this, program.getProgram(),
2012 glGetUniformLocation(program.getProgram(), "array3Uniform[2]"), uniformValue[3 * 2],
2013 uniformValue[(3 * 2) + 1], uniformValue[(3 * 2) + 2]);
2014 verifyUniformValue3f(m_testCtx, *this, program.getProgram(),
2015 glGetUniformLocation(program.getProgram(), "array3Uniform[3]"), uniformValue[3 * 3],
2016 uniformValue[(3 * 3) + 1], uniformValue[(3 * 3) + 2]);
2017 verifyUniformValue3f(m_testCtx, *this, program.getProgram(),
2018 glGetUniformLocation(program.getProgram(), "array3Uniform[4]"), uniformValue[3 * 4],
2019 uniformValue[(3 * 4) + 1], uniformValue[(3 * 4) + 2]);
2020 expectError(GL_NO_ERROR);
2021
2022 location = glGetUniformLocation(program.getProgram(), "array4Uniform");
2023 glUniform4fv(location, 5, uniformValue);
2024 expectError(GL_NO_ERROR);
2025
2026 verifyUniformValue4f(m_testCtx, *this, program.getProgram(),
2027 glGetUniformLocation(program.getProgram(), "array4Uniform[0]"), uniformValue[4 * 0],
2028 uniformValue[(4 * 0) + 1], uniformValue[(4 * 0) + 2], uniformValue[(4 * 0) + 3]);
2029 verifyUniformValue4f(m_testCtx, *this, program.getProgram(),
2030 glGetUniformLocation(program.getProgram(), "array4Uniform[1]"), uniformValue[4 * 1],
2031 uniformValue[(4 * 1) + 1], uniformValue[(4 * 1) + 2], uniformValue[(4 * 1) + 3]);
2032 verifyUniformValue4f(m_testCtx, *this, program.getProgram(),
2033 glGetUniformLocation(program.getProgram(), "array4Uniform[2]"), uniformValue[4 * 2],
2034 uniformValue[(4 * 2) + 1], uniformValue[(4 * 2) + 2], uniformValue[(4 * 2) + 3]);
2035 verifyUniformValue4f(m_testCtx, *this, program.getProgram(),
2036 glGetUniformLocation(program.getProgram(), "array4Uniform[3]"), uniformValue[4 * 3],
2037 uniformValue[(4 * 3) + 1], uniformValue[(4 * 3) + 2], uniformValue[(4 * 3) + 3]);
2038 verifyUniformValue4f(m_testCtx, *this, program.getProgram(),
2039 glGetUniformLocation(program.getProgram(), "array4Uniform[4]"), uniformValue[4 * 4],
2040 uniformValue[(4 * 4) + 1], uniformValue[(4 * 4) + 2], uniformValue[(4 * 4) + 3]);
2041 expectError(GL_NO_ERROR);
2042
2043 glUseProgram(0);
2044 expectError(GL_NO_ERROR);
2045 }
2046 };
2047
2048 class UniformValueMatrixCase : public ApiCase
2049 {
2050 public:
UniformValueMatrixCase(Context & context,const char * name,const char * description)2051 UniformValueMatrixCase(Context &context, const char *name, const char *description)
2052 : ApiCase(context, name, description)
2053 {
2054 }
2055
test(void)2056 void test(void)
2057 {
2058 static const char *testVertSource =
2059 "uniform highp mat2 mat2Uniform;"
2060 "uniform highp mat3 mat3Uniform;"
2061 "uniform highp mat4 mat4Uniform;"
2062 "void main (void)\n"
2063 "{\n"
2064 " gl_Position = vec4(mat2Uniform[0][0] + mat3Uniform[0][0] + mat4Uniform[0][0]);\n"
2065 "}\n";
2066 static const char *testFragSource =
2067
2068 "void main (void)\n"
2069 "{\n"
2070 " gl_FragColor = vec4(0.0);\n"
2071 "}\n";
2072
2073 glu::ShaderProgram program(m_context.getRenderContext(),
2074 glu::makeVtxFragSources(testVertSource, testFragSource));
2075 if (!program.isOk())
2076 {
2077 m_log << program;
2078 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to compile shader");
2079 return;
2080 }
2081
2082 glUseProgram(program.getProgram());
2083 expectError(GL_NO_ERROR);
2084
2085 GLint location;
2086
2087 float matrixValues[4 * 4] = {
2088 -1.0f, 0.1f, 4.0f, 800.0f, 13.0f, 55.0f, 12.0f, 91.0f,
2089 -55.1f, 1.1f, 98.0f, 19.0f, 41.0f, 65.0f, 4.0f, 12.2f,
2090 };
2091
2092 // the values of the matrix are returned in column major order but they can be given in either order
2093
2094 location = glGetUniformLocation(program.getProgram(), "mat2Uniform");
2095 glUniformMatrix2fv(location, 1, GL_FALSE, matrixValues);
2096 verifyUniformMatrixValues<2>(m_testCtx, *this, program.getProgram(), location, matrixValues, false);
2097
2098 location = glGetUniformLocation(program.getProgram(), "mat3Uniform");
2099 glUniformMatrix3fv(location, 1, GL_FALSE, matrixValues);
2100 verifyUniformMatrixValues<3>(m_testCtx, *this, program.getProgram(), location, matrixValues, false);
2101
2102 location = glGetUniformLocation(program.getProgram(), "mat4Uniform");
2103 glUniformMatrix4fv(location, 1, GL_FALSE, matrixValues);
2104 verifyUniformMatrixValues<4>(m_testCtx, *this, program.getProgram(), location, matrixValues, false);
2105
2106 glUseProgram(0);
2107 expectError(GL_NO_ERROR);
2108 }
2109 };
2110
2111 class PrecisionFormatCase : public ApiCase
2112 {
2113 public:
2114 struct RequiredFormat
2115 {
2116 int negativeRange;
2117 int positiveRange;
2118 int precision;
2119 };
2120
PrecisionFormatCase(Context & context,const char * name,const char * description,glw::GLenum shaderType,glw::GLenum precisionType)2121 PrecisionFormatCase(Context &context, const char *name, const char *description, glw::GLenum shaderType,
2122 glw::GLenum precisionType)
2123 : ApiCase(context, name, description)
2124 , m_shaderType(shaderType)
2125 , m_precisionType(precisionType)
2126 {
2127 }
2128
2129 private:
test(void)2130 void test(void)
2131 {
2132 const RequiredFormat expected = getRequiredFormat();
2133 bool error = false;
2134 gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLboolean> shaderCompiler;
2135 gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint[2]> range;
2136 gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint> precision;
2137
2138 // requires SHADER_COMPILER = true
2139 glGetBooleanv(GL_SHADER_COMPILER, &shaderCompiler);
2140 expectError(GL_NO_ERROR);
2141
2142 if (!shaderCompiler.verifyValidity(m_testCtx))
2143 return;
2144 if (shaderCompiler != GL_TRUE)
2145 throw tcu::NotSupportedError("SHADER_COMPILER = TRUE required");
2146
2147 // query values
2148 glGetShaderPrecisionFormat(m_shaderType, m_precisionType, range, &precision);
2149 expectError(GL_NO_ERROR);
2150
2151 if (!range.verifyValidity(m_testCtx))
2152 return;
2153 if (!precision.verifyValidity(m_testCtx))
2154 return;
2155
2156 m_log << tcu::TestLog::Message << "range[0] = " << range[0] << "\n"
2157 << "range[1] = " << range[1] << "\n"
2158 << "precision = " << precision << tcu::TestLog::EndMessage;
2159
2160 // special case for highp and fragment shader
2161
2162 if (m_shaderType == GL_FRAGMENT_SHADER && (m_precisionType == GL_HIGH_FLOAT || m_precisionType == GL_HIGH_INT))
2163 {
2164 // not supported is a valid return value
2165 if (range[0] == 0 && range[1] == 0 && precision == 0)
2166 return;
2167 }
2168
2169 // verify the returned values
2170
2171 if (range[0] < expected.negativeRange)
2172 {
2173 m_log << tcu::TestLog::Message << "// ERROR: Invalid range[0], expected greater or equal to "
2174 << expected.negativeRange << tcu::TestLog::EndMessage;
2175 error = true;
2176 }
2177
2178 if (range[1] < expected.positiveRange)
2179 {
2180 m_log << tcu::TestLog::Message << "// ERROR: Invalid range[1], expected greater or equal to "
2181 << expected.positiveRange << tcu::TestLog::EndMessage;
2182 error = true;
2183 }
2184
2185 if (precision < expected.precision)
2186 {
2187 m_log << tcu::TestLog::Message << "// ERROR: Invalid precision, expected greater or equal to "
2188 << expected.precision << tcu::TestLog::EndMessage;
2189 error = true;
2190 }
2191
2192 if (error)
2193 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid precision/range");
2194 }
2195
getRequiredFormat(void) const2196 RequiredFormat getRequiredFormat(void) const
2197 {
2198 // Precisions for different types.
2199 // For example highp float: range: (-2^62, 2^62) => min = -2^62 + e, max = 2^62 - e
2200 const RequiredFormat requirements[] = {
2201 {0, 0, 8}, //!< lowp float
2202 {13, 13, 10}, //!< mediump float
2203 {61, 61, 16}, //!< highp float
2204 {7, 7, 0}, //!< lowp int
2205 {9, 9, 0}, //!< mediump int
2206 {15, 15, 0}, //!< highp int
2207 };
2208 const int ndx = (int)m_precisionType - (int)GL_LOW_FLOAT;
2209
2210 DE_ASSERT(ndx >= 0);
2211 DE_ASSERT(ndx < DE_LENGTH_OF_ARRAY(requirements));
2212 return requirements[ndx];
2213 }
2214
2215 const glw::GLenum m_shaderType;
2216 const glw::GLenum m_precisionType;
2217 };
2218
2219 } // namespace
2220
ShaderStateQueryTests(Context & context)2221 ShaderStateQueryTests::ShaderStateQueryTests(Context &context)
2222 : TestCaseGroup(context, "shader", "Shader State Query tests")
2223 {
2224 }
2225
init(void)2226 void ShaderStateQueryTests::init(void)
2227 {
2228 // shader
2229 addChild(new ShaderTypeCase(m_context, "shader_type", "SHADER_TYPE"));
2230 addChild(new ShaderCompileStatusCase(m_context, "shader_compile_status", "COMPILE_STATUS"));
2231 addChild(new ShaderInfoLogCase(m_context, "shader_info_log_length", "INFO_LOG_LENGTH"));
2232 addChild(new ShaderSourceCase(m_context, "shader_source_length", "SHADER_SOURCE_LENGTH"));
2233
2234 // shader and program
2235 addChild(new DeleteStatusCase(m_context, "delete_status", "DELETE_STATUS"));
2236
2237 // vertex-attrib
2238 addChild(new CurrentVertexAttribInitialCase(m_context, "current_vertex_attrib_initial", "CURRENT_VERTEX_ATTRIB"));
2239 addChild(new CurrentVertexAttribFloatCase(m_context, "current_vertex_attrib_float", "CURRENT_VERTEX_ATTRIB"));
2240 addChild(new CurrentVertexAttribConversionCase(m_context, "current_vertex_attrib_float_to_int",
2241 "CURRENT_VERTEX_ATTRIB"));
2242
2243 // program
2244 addChild(new ProgramInfoLogCase(m_context, "program_info_log_length", "INFO_LOG_LENGTH"));
2245 addChild(new ProgramValidateStatusCase(m_context, "program_validate_status", "VALIDATE_STATUS"));
2246 addChild(new ProgramAttachedShadersCase(m_context, "program_attached_shaders", "ATTACHED_SHADERS"));
2247
2248 addChild(new ProgramActiveUniformNameCase(m_context, "program_active_uniform_name",
2249 "ACTIVE_UNIFORMS and ACTIVE_UNIFORM_MAX_LENGTH"));
2250 addChild(new ProgramUniformCase(m_context, "program_active_uniform_types", "UNIFORM_TYPE and UNIFORM_SIZE"));
2251
2252 // attribute related
2253 addChild(
2254 new ActiveAttributesCase(m_context, "active_attributes", "ACTIVE_ATTRIBUTES and ACTIVE_ATTRIBUTE_MAX_LENGTH"));
2255 addChild(new VertexAttributeSizeCase(m_context, "vertex_attrib_size", "VERTEX_ATTRIB_ARRAY_SIZE"));
2256 addChild(new VertexAttributeTypeCase(m_context, "vertex_attrib_type", "VERTEX_ATTRIB_ARRAY_TYPE"));
2257 addChild(new VertexAttributeStrideCase(m_context, "vertex_attrib_stride", "VERTEX_ATTRIB_ARRAY_STRIDE"));
2258 addChild(
2259 new VertexAttributeNormalizedCase(m_context, "vertex_attrib_normalized", "VERTEX_ATTRIB_ARRAY_NORMALIZED"));
2260 addChild(new VertexAttributeEnabledCase(m_context, "vertex_attrib_array_enabled", "VERTEX_ATTRIB_ARRAY_ENABLED"));
2261 addChild(new VertexAttributeBufferBindingCase(m_context, "vertex_attrib_array_buffer_binding",
2262 "VERTEX_ATTRIB_ARRAY_BUFFER_BINDING"));
2263 addChild(new VertexAttributePointerCase(m_context, "vertex_attrib_pointerv", "GetVertexAttribPointerv"));
2264
2265 // uniform values
2266 addChild(new UniformValueFloatCase(m_context, "uniform_value_float", "GetUniform*"));
2267 addChild(new UniformValueIntCase(m_context, "uniform_value_int", "GetUniform*"));
2268 addChild(new UniformValueBooleanCase(m_context, "uniform_value_boolean", "GetUniform*"));
2269 addChild(new UniformValueSamplerCase(m_context, "uniform_value_sampler", "GetUniform*"));
2270 addChild(new UniformValueArrayCase(m_context, "uniform_value_array", "GetUniform*"));
2271 addChild(new UniformValueMatrixCase(m_context, "uniform_value_matrix", "GetUniform*"));
2272
2273 // precision format query
2274 addChild(new PrecisionFormatCase(m_context, "precision_vertex_lowp_float", "GetShaderPrecisionFormat",
2275 GL_VERTEX_SHADER, GL_LOW_FLOAT));
2276 addChild(new PrecisionFormatCase(m_context, "precision_vertex_mediump_float", "GetShaderPrecisionFormat",
2277 GL_VERTEX_SHADER, GL_MEDIUM_FLOAT));
2278 addChild(new PrecisionFormatCase(m_context, "precision_vertex_highp_float", "GetShaderPrecisionFormat",
2279 GL_VERTEX_SHADER, GL_HIGH_FLOAT));
2280 addChild(new PrecisionFormatCase(m_context, "precision_vertex_lowp_int", "GetShaderPrecisionFormat",
2281 GL_VERTEX_SHADER, GL_LOW_INT));
2282 addChild(new PrecisionFormatCase(m_context, "precision_vertex_mediump_int", "GetShaderPrecisionFormat",
2283 GL_VERTEX_SHADER, GL_MEDIUM_INT));
2284 addChild(new PrecisionFormatCase(m_context, "precision_vertex_highp_int", "GetShaderPrecisionFormat",
2285 GL_VERTEX_SHADER, GL_HIGH_INT));
2286 addChild(new PrecisionFormatCase(m_context, "precision_fragment_lowp_float", "GetShaderPrecisionFormat",
2287 GL_FRAGMENT_SHADER, GL_LOW_FLOAT));
2288 addChild(new PrecisionFormatCase(m_context, "precision_fragment_mediump_float", "GetShaderPrecisionFormat",
2289 GL_FRAGMENT_SHADER, GL_MEDIUM_FLOAT));
2290 addChild(new PrecisionFormatCase(m_context, "precision_fragment_highp_float", "GetShaderPrecisionFormat",
2291 GL_FRAGMENT_SHADER, GL_HIGH_FLOAT));
2292 addChild(new PrecisionFormatCase(m_context, "precision_fragment_lowp_int", "GetShaderPrecisionFormat",
2293 GL_FRAGMENT_SHADER, GL_LOW_INT));
2294 addChild(new PrecisionFormatCase(m_context, "precision_fragment_mediump_int", "GetShaderPrecisionFormat",
2295 GL_FRAGMENT_SHADER, GL_MEDIUM_INT));
2296 addChild(new PrecisionFormatCase(m_context, "precision_fragment_highp_int", "GetShaderPrecisionFormat",
2297 GL_FRAGMENT_SHADER, GL_HIGH_INT));
2298 }
2299
2300 } // namespace Functional
2301 } // namespace gles2
2302 } // namespace deqp
2303