1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
4 *
5 * Copyright (c) 2015-2016 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 * \file gl3GPUShader5Tests.cpp
26 * \brief Implements conformance tests for "GPU Shader 5" functionality.
27 */ /*-------------------------------------------------------------------*/
28
29 #include "gl3cGPUShader5Tests.hpp"
30 #include "gluContextInfo.hpp"
31 #include "glwFunctions.hpp"
32 #include "tcuMatrix.hpp"
33 #include "tcuTestLog.hpp"
34
35 #include <iomanip>
36
37 #include <deMath.h>
38 #include <tcuMatrixUtil.hpp>
39 #include <tcuVectorUtil.hpp>
40
41 #include <cstdlib>
42 #include <cstring>
43 #include <limits>
44 #include <memory>
45
46 namespace gl3cts
47 {
48
49 /** Constructor
50 *
51 * @param context Test context
52 **/
programInfo(deqp::Context & context)53 Utils::programInfo::programInfo(deqp::Context& context)
54 : m_context(context), m_fragment_shader_id(0), m_program_object_id(0), m_vertex_shader_id(0)
55 {
56 /* Nothing to be done here */
57 }
58
59 /** Destructor
60 *
61 **/
~programInfo()62 Utils::programInfo::~programInfo()
63 {
64 /* GL entry points */
65 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
66
67 /* Make sure program object is no longer used by GL */
68 gl.useProgram(0);
69
70 /* Clean program object */
71 if (0 != m_program_object_id)
72 {
73 gl.deleteProgram(m_program_object_id);
74 m_program_object_id = 0;
75 }
76
77 /* Clean shaders */
78 if (0 != m_fragment_shader_id)
79 {
80 gl.deleteShader(m_fragment_shader_id);
81 m_fragment_shader_id = 0;
82 }
83
84 if (0 != m_vertex_shader_id)
85 {
86 gl.deleteShader(m_vertex_shader_id);
87 m_vertex_shader_id = 0;
88 }
89 }
90
91 /** Build program
92 *
93 * @param fragment_shader_code Fragment shader source code
94 * @param vertex_shader_code Vertex shader source code
95 * @param varying_names Array of strings containing names of varyings to be captured with transfrom feedback
96 * @param n_varying_names Number of varyings to be captured with transfrom feedback
97 **/
build(const glw::GLchar * fragment_shader_code,const glw::GLchar * vertex_shader_code)98 void Utils::programInfo::build(const glw::GLchar* fragment_shader_code, const glw::GLchar* vertex_shader_code)
99 {
100 /* GL entry points */
101 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
102
103 /* Create shader objects and compile */
104 if (0 != fragment_shader_code)
105 {
106 m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER);
107 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
108
109 compile(m_fragment_shader_id, fragment_shader_code);
110 }
111
112 if (0 != vertex_shader_code)
113 {
114 m_vertex_shader_id = gl.createShader(GL_VERTEX_SHADER);
115 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
116
117 compile(m_vertex_shader_id, vertex_shader_code);
118 }
119
120 /* Create program object */
121 m_program_object_id = gl.createProgram();
122 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
123
124 /* Link program */
125 link();
126 }
127
128 /** Compile shader
129 *
130 * @param shader_id Shader object id
131 * @param shader_code Shader source code
132 **/
compile(glw::GLuint shader_id,const glw::GLchar * shader_code) const133 void Utils::programInfo::compile(glw::GLuint shader_id, const glw::GLchar* shader_code) const
134 {
135 /* GL entry points */
136 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
137
138 /* Compilation status */
139 glw::GLint status = GL_FALSE;
140
141 /* Set source code */
142 gl.shaderSource(shader_id, 1 /* count */, &shader_code, 0);
143 GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource");
144
145 /* Compile */
146 gl.compileShader(shader_id);
147 GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader");
148
149 /* Get compilation status */
150 gl.getShaderiv(shader_id, GL_COMPILE_STATUS, &status);
151 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
152
153 /* Log compilation error */
154 if (GL_TRUE != status)
155 {
156 glw::GLint length = 0;
157 std::vector<glw::GLchar> message;
158
159 /* Error log length */
160 gl.getShaderiv(shader_id, GL_INFO_LOG_LENGTH, &length);
161 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
162
163 /* Prepare storage */
164 message.resize(length);
165
166 /* Get error log */
167 gl.getShaderInfoLog(shader_id, length, 0, &message[0]);
168 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog");
169
170 /* Log */
171 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to compile shader:\n"
172 << &message[0] << "\nShader source\n"
173 << shader_code << tcu::TestLog::EndMessage;
174
175 TCU_FAIL("Failed to compile shader");
176 }
177 }
178
179 /** Attach shaders and link program
180 *
181 **/
link() const182 void Utils::programInfo::link() const
183 {
184 /* GL entry points */
185 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
186
187 /* Link status */
188 glw::GLint status = GL_FALSE;
189
190 /* Attach shaders */
191 if (0 != m_fragment_shader_id)
192 {
193 gl.attachShader(m_program_object_id, m_fragment_shader_id);
194 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
195 }
196
197 if (0 != m_vertex_shader_id)
198 {
199 gl.attachShader(m_program_object_id, m_vertex_shader_id);
200 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
201 }
202
203 /* Link */
204 gl.linkProgram(m_program_object_id);
205 GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram");
206
207 /* Get link status */
208 gl.getProgramiv(m_program_object_id, GL_LINK_STATUS, &status);
209 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
210
211 /* Log link error */
212 if (GL_TRUE != status)
213 {
214 glw::GLint length = 0;
215 std::vector<glw::GLchar> message;
216
217 /* Get error log length */
218 gl.getProgramiv(m_program_object_id, GL_INFO_LOG_LENGTH, &length);
219 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
220
221 message.resize(length);
222
223 /* Get error log */
224 gl.getProgramInfoLog(m_program_object_id, length, 0, &message[0]);
225 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog");
226
227 /* Log */
228 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to link program:\n"
229 << &message[0] << tcu::TestLog::EndMessage;
230
231 TCU_FAIL("Failed to link program");
232 }
233 }
234
235 /** Set the uniform variable with provided data.
236 *
237 * @param type Type of variable
238 * @param name Name of variable
239 * @param data Data
240 */
setUniform(Utils::_variable_type type,const glw::GLchar * name,const glw::GLvoid * data)241 void Utils::programInfo::setUniform(Utils::_variable_type type, const glw::GLchar* name, const glw::GLvoid* data)
242 {
243 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
244
245 const glw::GLfloat* f_data = (glw::GLfloat*)data;
246 const glw::GLint* i_data = (glw::GLint*)data;
247 const glw::GLuint* u_data = (glw::GLuint*)data;
248
249 /* Get location */
250 glw::GLint location = gl.getUniformLocation(m_program_object_id, name);
251 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() call failed.");
252
253 if (-1 == location)
254 {
255 TCU_FAIL("Uniform variable is unavailable");
256 }
257
258 /* Set data */
259 switch (type)
260 {
261 case Utils::VARIABLE_TYPE_FLOAT:
262 gl.uniform1fv(location, 1, f_data);
263 break;
264 case Utils::VARIABLE_TYPE_INT:
265 gl.uniform1iv(location, 1, i_data);
266 break;
267 case Utils::VARIABLE_TYPE_IVEC2:
268 gl.uniform2iv(location, 1, i_data);
269 break;
270 case Utils::VARIABLE_TYPE_IVEC3:
271 gl.uniform3iv(location, 1, i_data);
272 break;
273 case Utils::VARIABLE_TYPE_IVEC4:
274 gl.uniform4iv(location, 1, i_data);
275 break;
276 case Utils::VARIABLE_TYPE_UINT:
277 gl.uniform1uiv(location, 1, u_data);
278 break;
279 case Utils::VARIABLE_TYPE_UVEC2:
280 gl.uniform2uiv(location, 1, u_data);
281 break;
282 case Utils::VARIABLE_TYPE_UVEC3:
283 gl.uniform3uiv(location, 1, u_data);
284 break;
285 case Utils::VARIABLE_TYPE_UVEC4:
286 gl.uniform4uiv(location, 1, u_data);
287 break;
288 case Utils::VARIABLE_TYPE_VEC2:
289 gl.uniform2fv(location, 1, f_data);
290 break;
291 case Utils::VARIABLE_TYPE_VEC3:
292 gl.uniform3fv(location, 1, f_data);
293 break;
294 case Utils::VARIABLE_TYPE_VEC4:
295 gl.uniform4fv(location, 1, f_data);
296 break;
297 default:
298 TCU_FAIL("Invalid enum");
299 break;
300 }
301
302 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform");
303 }
304
305 /** Replace first occurance of <token> with <text> in <string> starting at <search_posistion>
306 *
307 * @param token Token string
308 * @param search_position Position at which find will start, it is updated to position at which replaced text ends
309 * @param text String that will be used as replacement for <token>
310 * @param string String to work on
311 **/
replaceToken(const glw::GLchar * token,size_t & search_position,const glw::GLchar * text,std::string & string)312 void Utils::replaceToken(const glw::GLchar* token, size_t& search_position, const glw::GLchar* text,
313 std::string& string)
314 {
315 const size_t text_length = strlen(text);
316 const size_t token_length = strlen(token);
317 const size_t token_position = string.find(token, search_position);
318
319 string.replace(token_position, token_length, text, text_length);
320
321 search_position = token_position + text_length;
322 }
323
324 /* Constants used by GPUShader5ImplicitConversionsTest */
325 const glw::GLsizei GPUShader5ImplicitConversionsTest::m_width = 8;
326 const glw::GLsizei GPUShader5ImplicitConversionsTest::m_height = 8;
327
328 /** Constructor.
329 *
330 * @param context Rendering context.
331 **/
GPUShader5ImplicitConversionsTest(deqp::Context & context)332 GPUShader5ImplicitConversionsTest::GPUShader5ImplicitConversionsTest(deqp::Context& context)
333 : TestCase(context, "implicit_conversions",
334 "Verifies that implicit conversions are accepted and executed as explicit ones")
335 , m_fbo_id(0)
336 , m_tex_id(0)
337 , m_vao_id(0)
338
339 {
340 /* Left blank intentionally */
341 }
342
343 /** Constructor.
344 *
345 * @param context Rendering context.
346 * @param name Name of test
347 * @param description Describes test
348 **/
GPUShader5ImplicitConversionsTest(deqp::Context & context,const char * name,const char * description)349 GPUShader5ImplicitConversionsTest::GPUShader5ImplicitConversionsTest(deqp::Context& context, const char* name,
350 const char* description)
351 : TestCase(context, name, description), m_fbo_id(0), m_tex_id(0), m_vao_id(0)
352
353 {
354 /* Left blank intentionally */
355 }
356
357 /** Deinitializes all GL objects that may have been created during
358 * test execution.
359 **/
deinit()360 void GPUShader5ImplicitConversionsTest::deinit()
361 {
362 if (m_fbo_id != 0)
363 {
364 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
365 gl.deleteFramebuffers(1, &m_fbo_id);
366
367 m_fbo_id = 0;
368 }
369
370 if (m_tex_id != 0)
371 {
372 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
373 gl.deleteTextures(1, &m_tex_id);
374
375 m_tex_id = 0;
376 }
377
378 if (m_vao_id != 0)
379 {
380 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
381 gl.deleteVertexArrays(1, &m_vao_id);
382
383 m_vao_id = 0;
384 }
385 }
386
387 /** Executes test iteration.
388 *
389 * @return Returns STOP.
390 */
iterate()391 tcu::TestNode::IterateResult GPUShader5ImplicitConversionsTest::iterate()
392 {
393 /* Defines data used as u1 and u2 uniforms */
394 static const glw::GLint uni_data_int_1[4] = { 112, -1122, 111222, -1222111222 };
395 static const glw::GLint uni_data_int_2[4] = { -112, 1122, -111222, 1222111222 };
396 static const glw::GLuint uni_data_uint_1[4] = { 0xffff0000, 0x0000ffff, 0x00ffffff, 0xffffffff };
397 static const glw::GLuint uni_data_uint_2[4] = { 0xfff70000, 0x00007fff, 0x007fffff, 0xfffffff7 };
398
399 /* Defines test cases */
400 static const testCase test_cases[] = {
401 { "uint", false, "int", Utils::VARIABLE_TYPE_INT, uni_data_int_1, uni_data_int_2 } /* int >> uint */,
402 { "uint", true, "int", Utils::VARIABLE_TYPE_INT, uni_data_int_1, uni_data_int_1 },
403 { "float", false, "int", Utils::VARIABLE_TYPE_INT, uni_data_int_1, uni_data_int_2 } /* int >> float */,
404 { "float", true, "int", Utils::VARIABLE_TYPE_INT, uni_data_int_2, uni_data_int_2 },
405 { "uvec2", false, "ivec2", Utils::VARIABLE_TYPE_IVEC2, uni_data_int_1, uni_data_int_2 } /* ivec2 >> uvec2 */,
406 { "uvec2", true, "ivec2", Utils::VARIABLE_TYPE_IVEC2, uni_data_int_1, uni_data_int_1 },
407 { "vec2", false, "ivec2", Utils::VARIABLE_TYPE_IVEC2, uni_data_int_1, uni_data_int_2 } /* ivec2 >> vec2 */,
408 { "vec2", true, "ivec2", Utils::VARIABLE_TYPE_IVEC2, uni_data_int_1, uni_data_int_1 },
409 { "uvec3", false, "ivec3", Utils::VARIABLE_TYPE_IVEC3, uni_data_int_1, uni_data_int_2 } /* ivec3 >> uvec3 */,
410 { "uvec3", true, "ivec3", Utils::VARIABLE_TYPE_IVEC3, uni_data_int_2, uni_data_int_2 },
411 { "vec3", false, "ivec3", Utils::VARIABLE_TYPE_IVEC3, uni_data_int_1, uni_data_int_2 } /* ivec3 >> vec3 */,
412 { "vec3", true, "ivec3", Utils::VARIABLE_TYPE_IVEC3, uni_data_int_2, uni_data_int_2 },
413 { "uvec4", false, "ivec4", Utils::VARIABLE_TYPE_IVEC4, uni_data_int_1, uni_data_int_2 } /* ivec4 >> uvec4 */,
414 { "uvec4", true, "ivec4", Utils::VARIABLE_TYPE_IVEC4, uni_data_int_1, uni_data_int_1 },
415 { "vec4", false, "ivec4", Utils::VARIABLE_TYPE_IVEC4, uni_data_int_1, uni_data_int_2 } /* ivec4 >> vec4 */,
416 { "vec4", true, "ivec4", Utils::VARIABLE_TYPE_IVEC4, uni_data_int_1, uni_data_int_1 },
417 { "float", false, "uint", Utils::VARIABLE_TYPE_UINT, uni_data_uint_1, uni_data_uint_2 } /* uint >> float */,
418 { "float", true, "uint", Utils::VARIABLE_TYPE_UINT, uni_data_uint_2, uni_data_uint_2 },
419 { "vec2", false, "uvec2", Utils::VARIABLE_TYPE_UVEC2, uni_data_uint_1, uni_data_uint_2 } /* uvec2 >> vec2 */,
420 { "vec2", true, "uvec2", Utils::VARIABLE_TYPE_UVEC2, uni_data_uint_1, uni_data_uint_1 },
421 { "vec3", false, "uvec3", Utils::VARIABLE_TYPE_UVEC3, uni_data_uint_1, uni_data_uint_2 } /* uvec3 >> vec3 */,
422 { "vec3", true, "uvec3", Utils::VARIABLE_TYPE_UVEC3, uni_data_uint_2, uni_data_uint_2 },
423 { "vec4", false, "uvec4", Utils::VARIABLE_TYPE_UVEC4, uni_data_uint_1, uni_data_uint_2 } /* uvec4 >> vec4 */,
424 { "vec4", true, "uvec4", Utils::VARIABLE_TYPE_UVEC4, uni_data_uint_1, uni_data_uint_1 },
425 };
426 static const size_t n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
427
428 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader5"))
429 {
430 throw tcu::NotSupportedError("GL_ARB_gpu_shader5 is not supported.");
431 }
432
433 testInit();
434
435 /* Execute test cases */
436 for (size_t i = 0; i < n_test_cases; ++i)
437 {
438 const testCase& test_case = test_cases[i];
439
440 executeTestCase(test_case);
441 }
442
443 /* Set result - exceptions are thrown in case of any error */
444 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
445
446 /* Done */
447 return STOP;
448 }
449
450 /** Initializes frame buffer and vertex array
451 *
452 **/
testInit()453 void GPUShader5ImplicitConversionsTest::testInit()
454 {
455 /* */
456 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
457
458 /* Prepare texture for color attachment 0 */
459 gl.genTextures(1, &m_tex_id);
460 GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
461
462 gl.bindTexture(GL_TEXTURE_2D, m_tex_id);
463 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
464
465 gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, m_width, m_height);
466 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
467
468 /* Prepare FBO with color attachment 0 */
469 gl.genFramebuffers(1, &m_fbo_id);
470 GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
471
472 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
473 GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
474
475 gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_tex_id, 0 /* level */);
476 GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture2D");
477
478 /* Set Viewport */
479 gl.viewport(0 /* x */, 0 /* y */, m_width, m_height);
480 GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
481
482 /* Prepare blank VAO */
483 gl.genVertexArrays(1, &m_vao_id);
484 GLU_EXPECT_NO_ERROR(gl.getError(), "genVertexArrays");
485
486 gl.bindVertexArray(m_vao_id);
487 GLU_EXPECT_NO_ERROR(gl.getError(), "bindVertexArray");
488 }
489
490 /** Verifies if image is filled with <color>
491 *
492 * @param color Color to be checked
493 * @param is_expected Selects if image is expected to be filled with given color or not
494 **/
verifyImage(glw::GLuint color,bool is_expected) const495 void GPUShader5ImplicitConversionsTest::verifyImage(glw::GLuint color, bool is_expected) const
496 {
497 /* */
498 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
499
500 /* Storage for image data */
501 glw::GLuint result_image[m_width * m_height];
502
503 /* Get image data */
504 gl.getTexImage(GL_TEXTURE_2D, 0 /* level */, GL_RGBA, GL_UNSIGNED_BYTE, result_image);
505 GLU_EXPECT_NO_ERROR(gl.getError(), "getTexImage");
506
507 /* Inspect data */
508 if (true == is_expected)
509 {
510 for (size_t i = 0; i < m_width * m_height; ++i)
511 {
512 const glw::GLuint pixel_data = result_image[i];
513
514 if (color != pixel_data)
515 {
516 TCU_FAIL("Found invalid pixel during verification of drawn image");
517 }
518 }
519 }
520 else
521 {
522 for (size_t i = 0; i < m_width * m_height; ++i)
523 {
524 const glw::GLuint pixel_data = result_image[i];
525
526 if (color == pixel_data)
527 {
528 TCU_FAIL("Found invalid pixel during verification of drawn image");
529 }
530 }
531 }
532 }
533
534 /** Executes test case
535 *
536 * @param test_case Defines test case parameters
537 */
executeTestCase(const testCase & test_case)538 void GPUShader5ImplicitConversionsTest::executeTestCase(const testCase& test_case)
539 {
540 static const glw::GLuint white_color = 0xffffffff;
541
542 /* */
543 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
544
545 /* Run test case */
546 {
547 /* Get shaders */
548 const std::string& fs = getFragmentShader();
549 const std::string& vs = getVertexShader(test_case.m_destination_type, test_case.m_source_type);
550
551 /* Prepare program */
552 Utils::programInfo program(m_context);
553
554 program.build(fs.c_str(), vs.c_str());
555
556 gl.useProgram(program.m_program_object_id);
557 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
558
559 program.setUniform(test_case.m_source_variable_type, "u1", test_case.m_u1_data);
560 program.setUniform(test_case.m_source_variable_type, "u2", test_case.m_u2_data);
561
562 /* Clear FBO */
563 gl.clearColor(0.5f, 0.5f, 0.5f, 0.5f);
564 GLU_EXPECT_NO_ERROR(gl.getError(), "clearColor");
565
566 gl.clear(GL_COLOR_BUFFER_BIT);
567 GLU_EXPECT_NO_ERROR(gl.getError(), "clear");
568
569 /* Draw a triangle strip */
570 gl.drawArrays(GL_TRIANGLE_STRIP, 0 /* first */, 4 /* count */);
571 GLU_EXPECT_NO_ERROR(gl.getError(), "drawArrays");
572 }
573
574 /* Verification */
575 verifyImage(white_color, test_case.m_is_white_expected);
576 }
577
578 /** Get vertex shader source.
579 *
580 * @param destination_type Name of type
581 * @param source_type Name of type
582 *
583 * @return String with source of shader
584 */
getVertexShader(const glw::GLchar * destination_type,const glw::GLchar * source_type)585 std::string GPUShader5ImplicitConversionsTest::getVertexShader(const glw::GLchar* destination_type,
586 const glw::GLchar* source_type)
587 {
588 /* Vertex shader template */
589 const char* vs_body_template = "#version 150\n"
590 "#extension GL_ARB_gpu_shader5 : require\n"
591 "\n"
592 "uniform SOURCE_TYPE u1;\n"
593 "uniform SOURCE_TYPE u2;\n"
594 "\n"
595 "out vec4 result;\n"
596 "\n"
597 "void main()\n"
598 "{\n"
599 " DESTINATION_TYPE v = ZERO;\n"
600 "\n"
601 " v = DESTINATION_TYPE(u2) - u1;\n"
602 "\n"
603 " result = vec4(0.0, 0.0, 0.0, 0.0);\n"
604 " if (ZERO == v)\n"
605 " {\n"
606 " result = vec4(1.0, 1.0, 1.0, 1.0);\n"
607 " }\n"
608 "\n"
609 " switch (gl_VertexID)\n"
610 " {\n"
611 " case 0: gl_Position = vec4(-1.0, 1.0, 0.0, 1.0); break; \n"
612 " case 1: gl_Position = vec4( 1.0, 1.0, 0.0, 1.0); break; \n"
613 " case 2: gl_Position = vec4(-1.0,-1.0, 0.0, 1.0); break; \n"
614 " case 3: gl_Position = vec4( 1.0,-1.0, 0.0, 1.0); break; \n"
615 " }\n"
616 "}\n"
617 "\n";
618
619 std::string vs_body = vs_body_template;
620
621 /* Tokens */
622 size_t search_position = 0;
623
624 Utils::replaceToken("SOURCE_TYPE", search_position, source_type, vs_body);
625 Utils::replaceToken("SOURCE_TYPE", search_position, source_type, vs_body);
626
627 search_position = 0;
628 Utils::replaceToken("DESTINATION_TYPE", search_position, destination_type, vs_body);
629 Utils::replaceToken("DESTINATION_TYPE", search_position, destination_type, vs_body);
630
631 search_position = 0;
632 if (!strcmp(destination_type, "int") || !strcmp(destination_type, "uint"))
633 {
634 Utils::replaceToken("ZERO", search_position, "0", vs_body);
635 Utils::replaceToken("ZERO", search_position, "0", vs_body);
636 }
637 else if (!strcmp(destination_type, "float"))
638 {
639 Utils::replaceToken("ZERO", search_position, "0.0", vs_body);
640 Utils::replaceToken("ZERO", search_position, "0.0", vs_body);
641 }
642 else if (!strcmp(destination_type, "ivec2"))
643 {
644 Utils::replaceToken("ZERO", search_position, "ivec2(0,0)", vs_body);
645 Utils::replaceToken("ZERO", search_position, "ivec2(0,0)", vs_body);
646 }
647 else if (!strcmp(destination_type, "ivec3"))
648 {
649 Utils::replaceToken("ZERO", search_position, "ivec3(0,0,0)", vs_body);
650 Utils::replaceToken("ZERO", search_position, "ivec3(0,0,0)", vs_body);
651 }
652 else if (!strcmp(destination_type, "ivec4"))
653 {
654 Utils::replaceToken("ZERO", search_position, "ivec4(0,0,0,0)", vs_body);
655 Utils::replaceToken("ZERO", search_position, "ivec4(0,0,0,0)", vs_body);
656 }
657 else if (!strcmp(destination_type, "uvec2"))
658 {
659 Utils::replaceToken("ZERO", search_position, "uvec2(0,0)", vs_body);
660 Utils::replaceToken("ZERO", search_position, "uvec2(0,0)", vs_body);
661 }
662 else if (!strcmp(destination_type, "uvec3"))
663 {
664 Utils::replaceToken("ZERO", search_position, "uvec3(0,0,0)", vs_body);
665 Utils::replaceToken("ZERO", search_position, "uvec3(0,0,0)", vs_body);
666 }
667 else if (!strcmp(destination_type, "uvec4"))
668 {
669 Utils::replaceToken("ZERO", search_position, "uvec4(0,0,0,0)", vs_body);
670 Utils::replaceToken("ZERO", search_position, "uvec4(0,0,0,0)", vs_body);
671 }
672 else if (!strcmp(destination_type, "vec2"))
673 {
674 Utils::replaceToken("ZERO", search_position, "vec2(0,0)", vs_body);
675 Utils::replaceToken("ZERO", search_position, "vec2(0,0)", vs_body);
676 }
677 else if (!strcmp(destination_type, "vec3"))
678 {
679 Utils::replaceToken("ZERO", search_position, "vec3(0,0,0)", vs_body);
680 Utils::replaceToken("ZERO", search_position, "vec3(0,0,0)", vs_body);
681 }
682 else if (!strcmp(destination_type, "vec4"))
683 {
684 Utils::replaceToken("ZERO", search_position, "vec4(0,0,0,0)", vs_body);
685 Utils::replaceToken("ZERO", search_position, "vec4(0,0,0,0)", vs_body);
686 }
687
688 return vs_body;
689 }
690
691 /** Get fragment shader source.
692 *
693 * @return String with source of shader
694 */
getFragmentShader()695 std::string GPUShader5ImplicitConversionsTest::getFragmentShader()
696 {
697 const char* fs_body_template = "#version 150\n"
698 "\n"
699 "in vec4 result;\n"
700 "out vec4 color;\n"
701 "\n"
702 "void main()\n"
703 "{\n"
704 " color = result;\n"
705 "}\n"
706 "\n";
707
708 std::string fs_body = fs_body_template;
709
710 return fs_body;
711 }
712
713 /** Constructor.
714 *
715 * @param context Rendering context.
716 *
717 **/
GPUShader5FunctionOverloadingTest(deqp::Context & context)718 GPUShader5FunctionOverloadingTest::GPUShader5FunctionOverloadingTest(deqp::Context& context)
719 : GPUShader5ImplicitConversionsTest(context, "function_overloading",
720 "Verifies that function overloading is accepted")
721 {
722 /* Left blank intentionally */
723 }
724
725 /** Executes test iteration.
726 *
727 * @return Returns STOP.
728 */
iterate()729 tcu::TestNode::IterateResult GPUShader5FunctionOverloadingTest::iterate()
730 {
731 /* Defines data used as u1 and u2 uniforms */
732 static const glw::GLint u1_data_1[4] = { (glw::GLint)0xffff0000, 0x0000ffff, 0x00ffffff, (glw::GLint)0xffffffff };
733 static const glw::GLint u1_data_2[4] = { -112, 1122, -111222, 1222111222 };
734 static const glw::GLuint u2_data_1[4] = { 0xffff0000, 0x0000ffff, 0x00ffffff, 0xffffffff };
735 static const glw::GLuint u2_data_2[4] = { 0xfff70000, 0x00007fff, 0x007fffff, 0xfffffff7 };
736
737 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader5"))
738 {
739 throw tcu::NotSupportedError("GL_ARB_gpu_shader5 is not supported.");
740 }
741
742 testInit();
743
744 /* Execute test case */
745 execute(u1_data_1, u2_data_1, true);
746 execute(u1_data_2, u2_data_2, false);
747
748 /* Set result - exceptions are thrown in case of any error */
749 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
750
751 /* Done */
752 return STOP;
753 }
754
755 /** Executes test case
756 *
757 * @param u1_data Pointer to data that will used as u1 uniform
758 * @param u2_data Pointer to data that will used as u2 uniform
759 * @param test_case Defines test case parameters
760 */
execute(const glw::GLint * u1_data,const glw::GLuint * u2_data,bool is_black_expected)761 void GPUShader5FunctionOverloadingTest::execute(const glw::GLint* u1_data, const glw::GLuint* u2_data,
762 bool is_black_expected)
763 {
764 static const glw::GLuint black_color = 0x00000000;
765
766 /* */
767 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
768
769 /* Run test case */
770 {
771 /* Shaders */
772 const char* fs = "#version 150\n"
773 "\n"
774 "in vec4 result;\n"
775 "out vec4 color;\n"
776 "\n"
777 "void main()\n"
778 "{\n"
779 " color = result;\n"
780 "}\n"
781 "\n";
782
783 const char* vs = "#version 150\n"
784 "#extension GL_ARB_gpu_shader5 : require\n"
785 "\n"
786 "uniform ivec4 u1;\n"
787 "uniform uvec4 u2;\n"
788 "\n"
789 "out vec4 result;\n"
790 "\n"
791 "vec4 f(in vec4 a, in vec4 b)\n"
792 "{\n"
793 " return a * b;\n"
794 "}\n"
795 "\n"
796 "vec4 f(in uvec4 a, in uvec4 b)\n"
797 "{\n"
798 " return vec4(a - b);\n"
799 "}\n"
800 "\n"
801 "void main()\n"
802 "{\n"
803 " result = f(u1, u2);\n"
804 "\n"
805 " switch (gl_VertexID)\n"
806 " {\n"
807 " case 0: gl_Position = vec4(-1.0, 1.0, 0.0, 1.0); break; \n"
808 " case 1: gl_Position = vec4( 1.0, 1.0, 0.0, 1.0); break; \n"
809 " case 2: gl_Position = vec4(-1.0,-1.0, 0.0, 1.0); break; \n"
810 " case 3: gl_Position = vec4( 1.0,-1.0, 0.0, 1.0); break; \n"
811 " }\n"
812 "}\n"
813 "\n";
814
815 /* Prepare program */
816 Utils::programInfo program(m_context);
817
818 program.build(fs, vs);
819
820 gl.useProgram(program.m_program_object_id);
821 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
822
823 program.setUniform(Utils::VARIABLE_TYPE_IVEC4, "u1", u1_data);
824 program.setUniform(Utils::VARIABLE_TYPE_UVEC4, "u2", u2_data);
825
826 /* Clear FBO */
827 gl.clearColor(0.5f, 0.5f, 0.5f, 0.5f);
828 GLU_EXPECT_NO_ERROR(gl.getError(), "clearColor");
829
830 gl.clear(GL_COLOR_BUFFER_BIT);
831 GLU_EXPECT_NO_ERROR(gl.getError(), "clear");
832
833 /* Draw a triangle strip */
834 gl.drawArrays(GL_TRIANGLE_STRIP, 0 /* first */, 4 /* count */);
835 GLU_EXPECT_NO_ERROR(gl.getError(), "drawArrays");
836 }
837
838 /* Verification */
839 verifyImage(black_color, is_black_expected);
840 }
841
842 /** Constructor.
843 *
844 * @param context Rendering context.
845 *
846 **/
GPUShader5FloatEncodingTest(deqp::Context & context)847 GPUShader5FloatEncodingTest::GPUShader5FloatEncodingTest(deqp::Context& context)
848 : GPUShader5ImplicitConversionsTest(context, "float_encoding",
849 "Verifies that functions encoding floats as bits work as expected")
850 {
851 /* Left blank intentionally */
852 }
853
854 /** Executes test iteration.
855 *
856 * @return Returns STOP.
857 */
iterate()858 tcu::TestNode::IterateResult GPUShader5FloatEncodingTest::iterate()
859 {
860 /* Defines data used as u1 and u2 uniforms */
861 static const glw::GLfloat floats[4] = { -1.0f, -1234.0f, 1.0f, 1234.0f };
862 static const glw::GLint ints[4] = { -1, -1234, 1, 1234 };
863 static const glw::GLuint uints[4] = { 0xffffffff, 0xfffffb2e, 1, 0x4d2 };
864
865 /* Defines tested cases */
866 static const testCase test_cases[] = {
867 { /* float >> int - invalid */
868 { Utils::VARIABLE_TYPE_INT, "int", ints },
869 { Utils::VARIABLE_TYPE_FLOAT, "float", floats },
870 "floatBitsToInt",
871 false },
872 { /* float >> int - valid */
873 { Utils::VARIABLE_TYPE_INT, "int", floats },
874 { Utils::VARIABLE_TYPE_FLOAT, "float", floats },
875 "floatBitsToInt",
876 true },
877 { /* vec2 >> ivec2 - invalid */
878 { Utils::VARIABLE_TYPE_IVEC2, "ivec2", ints },
879 { Utils::VARIABLE_TYPE_VEC2, "vec2", floats },
880 "floatBitsToInt",
881 false },
882 { /* vec2 >> ivec2 - valid */
883 { Utils::VARIABLE_TYPE_IVEC2, "ivec2", floats },
884 { Utils::VARIABLE_TYPE_VEC2, "vec2", floats },
885 "floatBitsToInt",
886 true },
887 { /* vec3 >> ivec3 - invalid */
888 { Utils::VARIABLE_TYPE_IVEC3, "ivec3", ints },
889 { Utils::VARIABLE_TYPE_VEC3, "vec3", floats },
890 "floatBitsToInt",
891 false },
892 { /* vec3 >> ivec3 - valid */
893 { Utils::VARIABLE_TYPE_IVEC3, "ivec3", floats },
894 { Utils::VARIABLE_TYPE_VEC3, "vec3", floats },
895 "floatBitsToInt",
896 true },
897 { /* vec4 >> ivec4 - invalid */
898 { Utils::VARIABLE_TYPE_IVEC4, "ivec4", ints },
899 { Utils::VARIABLE_TYPE_VEC4, "vec4", floats },
900 "floatBitsToInt",
901 false },
902 { /* vec4 >> ivec4 - valid */
903 { Utils::VARIABLE_TYPE_IVEC4, "ivec4", floats },
904 { Utils::VARIABLE_TYPE_VEC4, "vec4", floats },
905 "floatBitsToInt",
906 true },
907 { /* float >> uint - invalid */
908 { Utils::VARIABLE_TYPE_UINT, "uint", uints },
909 { Utils::VARIABLE_TYPE_FLOAT, "float", floats },
910 "floatBitsToUint",
911 false },
912 { /* float >> uint - valid */
913 { Utils::VARIABLE_TYPE_UINT, "uint", floats },
914 { Utils::VARIABLE_TYPE_FLOAT, "float", floats },
915 "floatBitsToUint",
916 true },
917 { /* vec2 >> uvec2 - invalid */
918 { Utils::VARIABLE_TYPE_UVEC2, "uvec2", uints },
919 { Utils::VARIABLE_TYPE_VEC2, "vec2", floats },
920 "floatBitsToUint",
921 false },
922 { /* vec2 >> uvec2 - valid */
923 { Utils::VARIABLE_TYPE_UVEC2, "uvec2", floats },
924 { Utils::VARIABLE_TYPE_VEC2, "vec2", floats },
925 "floatBitsToUint",
926 true },
927 { /* vec3 >> uvec3 - invalid */
928 { Utils::VARIABLE_TYPE_UVEC3, "uvec3", uints },
929 { Utils::VARIABLE_TYPE_VEC3, "vec3", floats },
930 "floatBitsToUint",
931 false },
932 { /* vec3 >> uvec3 - valid */
933 { Utils::VARIABLE_TYPE_UVEC3, "uvec3", floats },
934 { Utils::VARIABLE_TYPE_VEC3, "vec3", floats },
935 "floatBitsToUint",
936 true },
937 { /* vec4 >> ivec4 - invalid */
938 { Utils::VARIABLE_TYPE_UVEC4, "uvec4", uints },
939 { Utils::VARIABLE_TYPE_VEC4, "vec4", floats },
940 "floatBitsToUint",
941 false },
942 { /* vec4 >> uvec4 - valid */
943 { Utils::VARIABLE_TYPE_UVEC4, "uvec4", floats },
944 { Utils::VARIABLE_TYPE_VEC4, "vec4", floats },
945 "floatBitsToUint",
946 true },
947 { /* int >> float - invalid */
948 { Utils::VARIABLE_TYPE_FLOAT, "float", floats },
949 { Utils::VARIABLE_TYPE_INT, "int", ints },
950 "intBitsToFloat",
951 false },
952 { /* int >> float - valid */
953 { Utils::VARIABLE_TYPE_FLOAT, "float", floats },
954 { Utils::VARIABLE_TYPE_INT, "int", floats },
955 "intBitsToFloat",
956 true },
957 { /* ivec2 >> vec2 - invalid */
958 { Utils::VARIABLE_TYPE_VEC2, "vec2", floats },
959 { Utils::VARIABLE_TYPE_IVEC2, "ivec2", ints },
960 "intBitsToFloat",
961 false },
962 { /* ivec2 >> vec2 - valid */
963 { Utils::VARIABLE_TYPE_VEC2, "vec2", floats },
964 { Utils::VARIABLE_TYPE_IVEC2, "ivec2", floats },
965 "intBitsToFloat",
966 true },
967 { /* ivec3 >> vec3 - invalid */
968 { Utils::VARIABLE_TYPE_VEC3, "vec3", floats },
969 { Utils::VARIABLE_TYPE_IVEC3, "ivec3", ints },
970 "intBitsToFloat",
971 false },
972 { /* ivec3 >> vec3 - valid */
973 { Utils::VARIABLE_TYPE_VEC3, "vec3", floats },
974 { Utils::VARIABLE_TYPE_IVEC3, "ivec3", floats },
975 "intBitsToFloat",
976 true },
977 { /* ivec4 >> vec4 - invalid */
978 { Utils::VARIABLE_TYPE_VEC4, "vec4", floats },
979 { Utils::VARIABLE_TYPE_IVEC4, "ivec4", ints },
980 "intBitsToFloat",
981 false },
982 { /* ivec4 >> vec4 - valid */
983 { Utils::VARIABLE_TYPE_VEC4, "vec4", floats },
984 { Utils::VARIABLE_TYPE_IVEC4, "ivec4", floats },
985 "intBitsToFloat",
986 true },
987 { /* uint >> float - invalid */
988 { Utils::VARIABLE_TYPE_FLOAT, "float", floats },
989 { Utils::VARIABLE_TYPE_UINT, "uint", uints },
990 "uintBitsToFloat",
991 false },
992 { /* uint >> float - valid */
993 { Utils::VARIABLE_TYPE_FLOAT, "float", floats },
994 { Utils::VARIABLE_TYPE_UINT, "uint", floats },
995 "uintBitsToFloat",
996 true },
997 { /* uvec2 >> vec2 - invalid */
998 { Utils::VARIABLE_TYPE_VEC2, "vec2", floats },
999 { Utils::VARIABLE_TYPE_UVEC2, "uvec2", uints },
1000 "uintBitsToFloat",
1001 false },
1002 { /* uvec2 >> vec2 - valid */
1003 { Utils::VARIABLE_TYPE_VEC2, "vec2", floats },
1004 { Utils::VARIABLE_TYPE_UVEC2, "uvec2", floats },
1005 "uintBitsToFloat",
1006 true },
1007 { /* uvec3 >> vec3 - invalid */
1008 { Utils::VARIABLE_TYPE_VEC3, "vec3", floats },
1009 { Utils::VARIABLE_TYPE_UVEC3, "uvec3", uints },
1010 "uintBitsToFloat",
1011 false },
1012 { /* uvec3 >> vec3 - valid */
1013 { Utils::VARIABLE_TYPE_VEC3, "vec3", floats },
1014 { Utils::VARIABLE_TYPE_UVEC3, "uvec3", floats },
1015 "uintBitsToFloat",
1016 true },
1017 { /* uvec4 >> vec4 - invalid */
1018 { Utils::VARIABLE_TYPE_VEC4, "vec4", floats },
1019 { Utils::VARIABLE_TYPE_UVEC4, "uvec4", uints },
1020 "uintBitsToFloat",
1021 false },
1022 { /* uvec4 >> vec4 - valid */
1023 { Utils::VARIABLE_TYPE_VEC4, "vec4", floats },
1024 { Utils::VARIABLE_TYPE_UVEC4, "uvec4", floats },
1025 "uintBitsToFloat",
1026 true },
1027 };
1028 static const size_t n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
1029
1030 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader5"))
1031 {
1032 throw tcu::NotSupportedError("GL_ARB_gpu_shader5 is not supported.");
1033 }
1034
1035 testInit();
1036
1037 /* Execute test case */
1038 for (size_t i = 0; i < n_test_cases; ++i)
1039 {
1040 const testCase& test_case = test_cases[i];
1041
1042 execute(test_case);
1043 }
1044
1045 /* Set result - exceptions are thrown in case of any error */
1046 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1047
1048 /* Done */
1049 return STOP;
1050 }
1051
1052 /** Executes test case
1053 *
1054 * @param test_case Tested case
1055 *
1056 * @param test_case Defines test case parameters
1057 */
execute(const testCase & test_case)1058 void GPUShader5FloatEncodingTest::execute(const testCase& test_case)
1059 {
1060 static const glw::GLuint white_color = 0xffffffff;
1061
1062 /* */
1063 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1064
1065 /* Run test case */
1066 {
1067 /* Shaders */
1068 const char* fs = "#version 150\n"
1069 "\n"
1070 "in vec4 result;\n"
1071 "out vec4 color;\n"
1072 "\n"
1073 "void main()\n"
1074 "{\n"
1075 " color = result;\n"
1076 "}\n"
1077 "\n";
1078
1079 const std::string& vs = getVertexShader(test_case);
1080
1081 /* Prepare program */
1082 Utils::programInfo program(m_context);
1083
1084 program.build(fs, vs.c_str());
1085
1086 gl.useProgram(program.m_program_object_id);
1087 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
1088
1089 program.setUniform(test_case.m_expected_value.m_type, "expected_value", test_case.m_expected_value.m_data);
1090 program.setUniform(test_case.m_value.m_type, "value", test_case.m_value.m_data);
1091
1092 /* Clear FBO */
1093 gl.clearColor(0.5f, 0.5f, 0.5f, 0.5f);
1094 GLU_EXPECT_NO_ERROR(gl.getError(), "clearColor");
1095
1096 gl.clear(GL_COLOR_BUFFER_BIT);
1097 GLU_EXPECT_NO_ERROR(gl.getError(), "clear");
1098
1099 /* Draw a triangle strip */
1100 gl.drawArrays(GL_TRIANGLE_STRIP, 0 /* first */, 4 /* count */);
1101 GLU_EXPECT_NO_ERROR(gl.getError(), "drawArrays");
1102 }
1103
1104 /* Verification */
1105 verifyImage(white_color, test_case.m_is_white_expected);
1106 }
1107
1108 /** Get vertex shader source.
1109 *
1110 * @param test_case Tested case
1111 *
1112 * @return String with source of shader
1113 */
getVertexShader(const testCase & test_case) const1114 std::string GPUShader5FloatEncodingTest::getVertexShader(const testCase& test_case) const
1115 {
1116 /* Vertex shader template */
1117 const char* vs_body_template = "#version 150\n"
1118 "#extension GL_ARB_gpu_shader5 : require\n"
1119 "\n"
1120 "uniform EXPECTED_VALUE_TYPE expected_value;\n"
1121 "uniform VALUE_TYPE value;\n"
1122 "\n"
1123 "out vec4 result;\n"
1124 "\n"
1125 "void main()\n"
1126 "{\n"
1127 " result = vec4(1.0, 1.0, 1.0, 1.0);\n"
1128 "\n"
1129 " EXPECTED_VALUE_TYPE ret_val = TESTED_FUNCTION(value);\n"
1130 "\n"
1131 " if (expected_value != ret_val)\n"
1132 " {\n"
1133 " result = vec4(0.0, 0.0, 0.0, 0.0);\n"
1134 " }\n"
1135 "\n"
1136 " switch (gl_VertexID)\n"
1137 " {\n"
1138 " case 0: gl_Position = vec4(-1.0, 1.0, 0.0, 1.0); break; \n"
1139 " case 1: gl_Position = vec4( 1.0, 1.0, 0.0, 1.0); break; \n"
1140 " case 2: gl_Position = vec4(-1.0,-1.0, 0.0, 1.0); break; \n"
1141 " case 3: gl_Position = vec4( 1.0,-1.0, 0.0, 1.0); break; \n"
1142 " }\n"
1143 "}\n"
1144 "\n";
1145
1146 std::string vs_body = vs_body_template;
1147
1148 /* Tokens */
1149 size_t search_position = 0;
1150
1151 Utils::replaceToken("EXPECTED_VALUE_TYPE", search_position, test_case.m_expected_value.m_type_name, vs_body);
1152 Utils::replaceToken("VALUE_TYPE", search_position, test_case.m_value.m_type_name, vs_body);
1153 Utils::replaceToken("EXPECTED_VALUE_TYPE", search_position, test_case.m_expected_value.m_type_name, vs_body);
1154 Utils::replaceToken("TESTED_FUNCTION", search_position, test_case.m_function_name, vs_body);
1155
1156 return vs_body;
1157 }
1158
1159 /** Constructor.
1160 *
1161 * @param context Rendering context.
1162 **/
GPUShader5Tests(deqp::Context & context)1163 GPUShader5Tests::GPUShader5Tests(deqp::Context& context)
1164 : TestCaseGroup(context, "gpu_shader5_gl", "Verifies \"gpu_shader5\" functionality")
1165 {
1166 /* Left blank on purpose */
1167 }
1168
1169 /** Initializes a texture_storage_multisample test group.
1170 *
1171 **/
init(void)1172 void GPUShader5Tests::init(void)
1173 {
1174 addChild(new GPUShader5ImplicitConversionsTest(m_context));
1175 addChild(new GPUShader5FunctionOverloadingTest(m_context));
1176 addChild(new GPUShader5FloatEncodingTest(m_context));
1177 }
1178 } /* glcts namespace */
1179