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 #include "gl4cStencilTexturingTests.hpp"
25
26 #include "gluContextInfo.hpp"
27 #include "gluDefs.hpp"
28 #include "gluStrUtil.hpp"
29 #include "glwEnums.hpp"
30 #include "glwFunctions.hpp"
31 #include "tcuTestLog.hpp"
32
33 #include <algorithm>
34 #include <string>
35 #include <vector>
36
37 #define DEBUG_REPLACE_TOKEN 0
38
39 using namespace glw;
40
41 namespace gl4cts
42 {
43 namespace StencilTexturing
44 {
45 class Utils
46 {
47 public:
48 static GLuint createAndBuildProgram(deqp::Context &context, const GLchar *cs_code, const GLchar *fs_code,
49 const GLchar *gs_code, const GLchar *tcs_code, const GLchar *tes_code,
50 const GLchar *vs_code);
51
52 static GLuint createAndCompileShader(deqp::Context &context, const GLenum type, const GLchar *code);
53
54 static GLuint createAndFill2DTexture(deqp::Context &context, GLuint width, GLuint height, GLenum internal_format,
55 GLenum format, GLenum type, const GLvoid *data);
56
57 static void deleteProgram(deqp::Context &context, const GLuint id);
58 static void deleteShader(deqp::Context &context, const GLuint id);
59 static void deleteTexture(deqp::Context &context, const GLuint id);
60 static bool isExtensionSupported(deqp::Context &context, const GLchar *extension_name);
61
62 static void replaceToken(const GLchar *token, size_t &search_position, const GLchar *text, std::string &string);
63 };
64
65 /** Create and build program from provided sources
66 *
67 * @param context Test context
68 * @param cs_code Source code for compute shader stage
69 * @param fs_code Source code for fragment shader stage
70 * @param gs_code Source code for geometry shader stage
71 * @param tcs_code Source code for tesselation control shader stage
72 * @param tes_code Source code for tesselation evaluation shader stage
73 * @param vs_code Source code for vertex shader stage
74 *
75 * @return ID of program object
76 **/
createAndBuildProgram(deqp::Context & context,const GLchar * cs_code,const GLchar * fs_code,const GLchar * gs_code,const GLchar * tcs_code,const GLchar * tes_code,const GLchar * vs_code)77 GLuint Utils::createAndBuildProgram(deqp::Context &context, const GLchar *cs_code, const GLchar *fs_code,
78 const GLchar *gs_code, const GLchar *tcs_code, const GLchar *tes_code,
79 const GLchar *vs_code)
80 {
81 #define N_SHADER_STAGES 6
82
83 const Functions &gl = context.getRenderContext().getFunctions();
84 GLuint id = 0;
85 GLuint shader_ids[N_SHADER_STAGES] = {0};
86
87 const GLchar *shader_sources[N_SHADER_STAGES] = {cs_code, fs_code, gs_code, tcs_code, tes_code, vs_code};
88
89 const GLenum shader_types[N_SHADER_STAGES] = {GL_COMPUTE_SHADER, GL_FRAGMENT_SHADER, GL_GEOMETRY_SHADER,
90 GL_TESS_CONTROL_SHADER, GL_TESS_EVALUATION_SHADER, GL_VERTEX_SHADER};
91 GLint status = GL_FALSE;
92
93 /* Compile all shaders */
94 try
95 {
96 for (GLuint i = 0; i < N_SHADER_STAGES; ++i)
97 {
98 if (0 != shader_sources[i])
99 {
100 shader_ids[i] = createAndCompileShader(context, shader_types[i], shader_sources[i]);
101 }
102 }
103
104 /* Check compilation */
105 for (GLuint i = 0; i < N_SHADER_STAGES; ++i)
106 {
107 if ((0 != shader_sources[i]) && (0 == shader_ids[i]))
108 {
109 context.getTestContext().getLog()
110 << tcu::TestLog::Message << "Failed to build program due to compilation problems"
111 << tcu::TestLog::EndMessage;
112
113 /* Delete shaders */
114 for (GLuint j = 0; j < N_SHADER_STAGES; ++j)
115 {
116 deleteShader(context, shader_ids[j]);
117 }
118
119 /* Done */
120 return 0;
121 }
122 }
123
124 /* Create program */
125 id = gl.createProgram();
126 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
127
128 /* Attach shaders */
129 for (GLuint i = 0; i < N_SHADER_STAGES; ++i)
130 {
131 if (0 != shader_ids[i])
132 {
133 gl.attachShader(id, shader_ids[i]);
134 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
135 }
136 }
137
138 /* Link program */
139 gl.linkProgram(id);
140 GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram");
141
142 /* Clean shaders */
143 for (GLuint j = 0; j < N_SHADER_STAGES; ++j)
144 {
145 deleteShader(context, shader_ids[j]);
146 }
147
148 /* Get link status */
149 gl.getProgramiv(id, GL_LINK_STATUS, &status);
150 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
151
152 /* Log link error */
153 if (GL_TRUE != status)
154 {
155 glw::GLint length = 0;
156 std::string message;
157
158 /* Get error log length */
159 gl.getProgramiv(id, GL_INFO_LOG_LENGTH, &length);
160 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
161
162 message.resize(length, 0);
163
164 /* Get error log */
165 gl.getProgramInfoLog(id, length, 0, &message[0]);
166 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog");
167
168 context.getTestContext().getLog()
169 << tcu::TestLog::Message << "Program linking failed: " << message << tcu::TestLog::EndMessage;
170
171 /* Clean program */
172 deleteProgram(context, id);
173
174 /* Done */
175 return 0;
176 }
177 }
178 catch (std::exception &exc)
179 {
180 /* Delete shaders */
181 for (GLuint j = 0; j < N_SHADER_STAGES; ++j)
182 {
183 deleteShader(context, shader_ids[j]);
184 }
185
186 throw exc;
187 }
188
189 return id;
190 }
191
192 /** Create and compile shader
193 *
194 * @param context Test context
195 * @param type Type of shader
196 * @param code Source code for shader
197 *
198 * @return ID of shader object
199 **/
createAndCompileShader(deqp::Context & context,const GLenum type,const GLchar * code)200 GLuint Utils::createAndCompileShader(deqp::Context &context, const GLenum type, const GLchar *code)
201 {
202 const Functions &gl = context.getRenderContext().getFunctions();
203 GLuint id = gl.createShader(type);
204 GLint status = GL_FALSE;
205
206 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
207
208 try
209 {
210 gl.shaderSource(id, 1 /* count */, &code, 0 /* lengths */);
211 GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource");
212
213 /* Compile */
214 gl.compileShader(id);
215 GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader");
216
217 /* Get compilation status */
218 gl.getShaderiv(id, GL_COMPILE_STATUS, &status);
219 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
220
221 /* Log compilation error */
222 if (GL_TRUE != status)
223 {
224 glw::GLint length = 0;
225 std::string message;
226
227 /* Error log length */
228 gl.getShaderiv(id, GL_INFO_LOG_LENGTH, &length);
229 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
230
231 /* Prepare storage */
232 message.resize(length, 0);
233
234 /* Get error log */
235 gl.getShaderInfoLog(id, length, 0, &message[0]);
236 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog");
237
238 context.getTestContext().getLog() << tcu::TestLog::Message << "Shader (" << glu::getShaderTypeStr(type)
239 << ") compilation failed: " << message << tcu::TestLog::EndMessage;
240
241 deleteShader(context, id);
242 id = 0;
243 }
244 }
245 catch (std::exception &exc)
246 {
247 deleteShader(context, id);
248 throw exc;
249 }
250
251 return id;
252 }
253
254 /** Generate and fill 2d texture
255 *
256 * @param context Test context
257 * @param width Width of texture
258 * @param height Height of texture
259 * @param internal_format Internal format of texture
260 * @param format Format of data
261 * @param type Type of data
262 * @param data Data
263 *
264 * @return ID of texture object
265 **/
createAndFill2DTexture(deqp::Context & context,GLuint width,GLuint height,GLenum internal_format,GLenum format,GLenum type,const GLvoid * data)266 GLuint Utils::createAndFill2DTexture(deqp::Context &context, GLuint width, GLuint height, GLenum internal_format,
267 GLenum format, GLenum type, const GLvoid *data)
268 {
269 const Functions &gl = context.getRenderContext().getFunctions();
270 GLuint id = 0;
271
272 gl.genTextures(1, &id);
273 GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
274
275 try
276 {
277 gl.bindTexture(GL_TEXTURE_2D, id);
278 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
279
280 gl.texImage2D(GL_TEXTURE_2D, 0 /* level */, internal_format, width, height, 0 /* border */, format, type, data);
281 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage2D");
282
283 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
284 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
285 GLU_EXPECT_NO_ERROR(gl.getError(), "TexParameteri");
286
287 gl.bindTexture(GL_TEXTURE_2D, 0);
288 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
289 }
290 catch (std::exception &exc)
291 {
292 gl.deleteTextures(1, &id);
293 id = 0;
294
295 throw exc;
296 }
297
298 return id;
299 }
300
301 /** Delete program
302 *
303 * @param context Test context
304 * @param id ID of program
305 **/
deleteProgram(deqp::Context & context,const GLuint id)306 void Utils::deleteProgram(deqp::Context &context, const GLuint id)
307 {
308 const glw::Functions &gl = context.getRenderContext().getFunctions();
309
310 if (0 != id)
311 {
312 gl.deleteProgram(id);
313 }
314 }
315
316 /** Delete shader
317 *
318 * @param context Test context
319 * @param id ID of shader
320 **/
deleteShader(deqp::Context & context,const GLuint id)321 void Utils::deleteShader(deqp::Context &context, const GLuint id)
322 {
323 const glw::Functions &gl = context.getRenderContext().getFunctions();
324
325 if (0 != id)
326 {
327 gl.deleteShader(id);
328 }
329 }
330
331 /** Delete texture
332 *
333 * @param context Test context
334 * @param id ID of texture
335 **/
deleteTexture(deqp::Context & context,const GLuint id)336 void Utils::deleteTexture(deqp::Context &context, const GLuint id)
337 {
338 const glw::Functions &gl = context.getRenderContext().getFunctions();
339
340 if (0 != id)
341 {
342 gl.deleteTextures(1, &id);
343 }
344 }
345
346 /** Checks if extensions is not available.
347 *
348 * @param context Test context
349 * @param extension_name Name of extension
350 *
351 * @return true if extension is reported as available, false otherwise
352 **/
isExtensionSupported(deqp::Context & context,const GLchar * extension_name)353 bool Utils::isExtensionSupported(deqp::Context &context, const GLchar *extension_name)
354 {
355 const std::vector<std::string> &extensions = context.getContextInfo().getExtensions();
356
357 if (std::find(extensions.begin(), extensions.end(), extension_name) == extensions.end())
358 {
359 std::string message = "Required extension is not supported: ";
360 message.append(extension_name);
361
362 return false;
363 }
364
365 return true;
366 }
367
368 /** Replace first occurance of <token> with <text> in <string> starting at <search_posistion>
369 *
370 * @param token Token string
371 * @param search_position Position at which find will start, it is updated to position at which replaced text ends
372 * @param text String that will be used as replacement for <token>
373 * @param string String to work on
374 **/
replaceToken(const GLchar * token,size_t & search_position,const GLchar * text,std::string & string)375 void Utils::replaceToken(const GLchar *token, size_t &search_position, const GLchar *text, std::string &string)
376 {
377 const size_t text_length = strlen(text);
378 const size_t token_length = strlen(token);
379 const size_t token_position = string.find(token, search_position);
380
381 #if DEBUG_REPLACE_TOKEN
382 if (std::string::npos == token_position)
383 {
384 string.append("\n\nInvalid token: ");
385 string.append(token);
386
387 TCU_FAIL(string.c_str());
388 }
389 #endif /* DEBUG_REPLACE_TOKEN */
390
391 string.replace(token_position, token_length, text, text_length);
392
393 search_position = token_position + text_length;
394 }
395
396 /* FunctionalTest */
397 /* Shader sources */
398 const GLchar *FunctionalTest::m_compute_shader_code =
399 "#version 430 core\n"
400 "\n"
401 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
402 "\n"
403 "IMAGE_DEFINITION;\n"
404 "SAMPLER_DEFINITION;\n"
405 "\n"
406 "void main()\n"
407 "{\n"
408 " vec2 tex_coord = vec2(gl_GlobalInvocationID.xy) / 8.0;\n"
409 "\n"
410 " imageStore(uni_image,\n"
411 " ivec2(gl_GlobalInvocationID.xy),\n"
412 " TYPE(texture(uni_sampler, tex_coord).r, 0, 0, 0));\n"
413 "}\n"
414 "\n";
415
416 const GLchar *FunctionalTest::m_fragment_shader_code =
417 "#version 430 core\n"
418 "\n"
419 " in vec2 gs_fs_tex_coord;\n"
420 "flat in uint gs_fs_result;\n"
421 " out TYPE fs_out_result;\n"
422 "\n"
423 "SAMPLER_DEFINITION;\n"
424 "\n"
425 "void main()\n"
426 "{\n"
427 " if (1 != gs_fs_result)\n"
428 " {\n"
429 " fs_out_result = texture(uni_sampler, vec2(0.9375, 0.9375));\n"
430 " }\n"
431 " else\n"
432 " {\n"
433 " fs_out_result = texture(uni_sampler, gs_fs_tex_coord);\n"
434 " }\n"
435 "}\n"
436 "\n";
437
438 const GLchar *FunctionalTest::m_geometry_shader_code =
439 "#version 430 core\n"
440 "\n"
441 "layout(points) in;\n"
442 "layout(triangle_strip, max_vertices = 4) out;\n"
443 "\n"
444 " in uint tes_gs_result[];\n"
445 "flat out uint gs_fs_result;\n"
446 " out vec2 gs_fs_tex_coord;\n"
447 "\n"
448 "SAMPLER_DEFINITION;\n"
449 "\n"
450 "void main()\n"
451 "{\n"
452 " uint result = 1u;\n"
453 "\n"
454 " if (1 != tes_gs_result[0])\n"
455 " {\n"
456 " result = 0u;\n"
457 " }\n"
458 "\n"
459 " if (EXPECTED_VALUE != texture(uni_sampler, vec2(0.9375, 0.9375)).r)\n"
460 " {\n"
461 " result = 0u;\n"
462 " }\n"
463 "\n"
464 " gs_fs_result = result;\n"
465 " gs_fs_tex_coord = vec2(0, 0);\n"
466 " gl_Position = vec4(-1, -1, 0, 1);\n"
467 " EmitVertex();\n"
468 " gs_fs_result = result;\n"
469 " gs_fs_tex_coord = vec2(0, 1);\n"
470 " gl_Position = vec4(-1, 1, 0, 1);\n"
471 " EmitVertex();\n"
472 " gs_fs_result = result;\n"
473 " gs_fs_tex_coord = vec2(1, 0);\n"
474 " gl_Position = vec4(1, -1, 0, 1);\n"
475 " EmitVertex();\n"
476 " gs_fs_result = result;\n"
477 " gs_fs_tex_coord = vec2(1, 1);\n"
478 " gl_Position = vec4(1, 1, 0, 1);\n"
479 " EmitVertex();\n"
480 "}\n"
481 "\n";
482
483 const GLchar *FunctionalTest::m_tesselation_control_shader_code =
484 "#version 430 core\n"
485 "\n"
486 "layout(vertices = 1) out;\n"
487 "\n"
488 "in uint vs_tcs_result[];\n"
489 "out uint tcs_tes_result[];\n"
490 "\n"
491 "SAMPLER_DEFINITION;\n"
492 "\n"
493 "void main()\n"
494 "{\n"
495 " uint result = 1u;\n"
496 "\n"
497 " if (1u != vs_tcs_result[gl_InvocationID])\n"
498 " {\n"
499 " result = 0u;\n"
500 " }\n"
501 "\n"
502 " if (EXPECTED_VALUE != texture(uni_sampler, vec2(0.9375, 0.9375)).r)\n"
503 " {\n"
504 " result = 0u;\n"
505 " }\n"
506 "\n"
507 " tcs_tes_result[gl_InvocationID] = result;\n"
508 "\n"
509 " gl_TessLevelOuter[0] = 1.0;\n"
510 " gl_TessLevelOuter[1] = 1.0;\n"
511 " gl_TessLevelOuter[2] = 1.0;\n"
512 " gl_TessLevelOuter[3] = 1.0;\n"
513 " gl_TessLevelInner[0] = 1.0;\n"
514 " gl_TessLevelInner[1] = 1.0;\n"
515 "}\n"
516 "\n";
517
518 const GLchar *FunctionalTest::m_tesselation_evaluation_shader_code =
519 "#version 430 core\n"
520 "\n"
521 "layout(isolines, point_mode) in;\n"
522 "\n"
523 "in uint tcs_tes_result[];\n"
524 "out uint tes_gs_result;\n"
525 "\n"
526 "SAMPLER_DEFINITION;\n"
527 "\n"
528 "void main()\n"
529 "{\n"
530 " uint result = 1u;\n"
531 "\n"
532 " if (1u != tcs_tes_result[0])\n"
533 " {\n"
534 " result = 0u;\n"
535 " }\n"
536 "\n"
537 " if (EXPECTED_VALUE != texture(uni_sampler, vec2(0.9375, 0.9375)).r)\n"
538 " {\n"
539 " result = 0u;\n"
540 " }\n"
541 "\n"
542 " tes_gs_result = result;\n"
543 "}\n"
544 "\n";
545
546 const GLchar *FunctionalTest::m_vertex_shader_code =
547 "#version 430 core\n"
548 "\n"
549 "out uint vs_tcs_result;\n"
550 "\n"
551 "SAMPLER_DEFINITION;\n"
552 "\n"
553 "void main()\n"
554 "{\n"
555 " uint result = 1u;\n"
556 "\n"
557 " if (EXPECTED_VALUE != texture(uni_sampler, vec2(0.9375, 0.9375)).r)\n"
558 " {\n"
559 " result = 0u;\n"
560 " }\n"
561 "\n"
562 " vs_tcs_result = result;\n"
563 "}\n"
564 "\n";
565
566 const GLchar *FunctionalTest::m_expected_value_depth = "0.0";
567
568 const GLchar *FunctionalTest::m_expected_value_stencil = "15u";
569
570 const GLchar *FunctionalTest::m_image_definition_depth = "writeonly uniform image2D uni_image";
571
572 const GLchar *FunctionalTest::m_image_definition_stencil = "writeonly uniform uimage2D uni_image";
573
574 const GLchar *FunctionalTest::m_output_type_depth = "vec4";
575
576 const GLchar *FunctionalTest::m_output_type_stencil = "uvec4";
577
578 const GLchar *FunctionalTest::m_sampler_definition_depth = "uniform sampler2D uni_sampler";
579
580 const GLchar *FunctionalTest::m_sampler_definition_stencil = "uniform usampler2D uni_sampler";
581
582 /* Constants */
583 const GLuint FunctionalTest::m_height = 8;
584 const GLint FunctionalTest::m_image_unit = 1;
585 const GLint FunctionalTest::m_texture_unit = 1;
586 const GLuint FunctionalTest::m_width = 8;
587
588 /** Constructor
589 *
590 * @param context Test context
591 **/
FunctionalTest(deqp::Context & context)592 FunctionalTest::FunctionalTest(deqp::Context &context)
593 : TestCase(context, "functional", "Checks if sampling stencil texture gives expected results")
594 {
595 /* Nothing to be done here */
596 }
597
598 /** Execute test
599 *
600 * @return tcu::TestNode::STOP
601 **/
iterate()602 tcu::TestNode::IterateResult FunctionalTest::iterate()
603 {
604 bool test_result = true;
605
606 if (false == test(GL_DEPTH24_STENCIL8, true))
607 {
608 m_context.getTestContext().getLog()
609 << tcu::TestLog::Message << "Test failed. Case format: GL_DEPTH24_STENCIL8, channel: S"
610 << tcu::TestLog::EndMessage;
611 test_result = false;
612 }
613
614 if (false == test(GL_DEPTH24_STENCIL8, false))
615 {
616 m_context.getTestContext().getLog()
617 << tcu::TestLog::Message << "Test failed. Case format: GL_DEPTH24_STENCIL8, channel: D"
618 << tcu::TestLog::EndMessage;
619 test_result = false;
620 }
621
622 if (false == test(GL_DEPTH32F_STENCIL8, true))
623 {
624 m_context.getTestContext().getLog()
625 << tcu::TestLog::Message << "Test failed. Case format: GL_DEPTH32F_STENCIL8, channel: S"
626 << tcu::TestLog::EndMessage;
627 test_result = false;
628 }
629
630 if (false == test(GL_DEPTH32F_STENCIL8, false))
631 {
632 m_context.getTestContext().getLog()
633 << tcu::TestLog::Message << "Test failed. Case format: GL_DEPTH32F_STENCIL8, channel: D"
634 << tcu::TestLog::EndMessage;
635 test_result = false;
636 }
637
638 /* Set result */
639 if (true == test_result)
640 {
641 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
642 }
643 else
644 {
645 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
646 }
647
648 /* Done */
649 return tcu::TestNode::STOP;
650 }
651
652 /** Execute compute program
653 *
654 * @param program_id ID of program
655 * @param is_stencil Selects if stencil or depth channel is sampled
656 * @param dst_texture_id ID of destination texture
657 * @param src_texture_id ID of source texture
658 **/
dispatch(GLuint program_id,bool is_stencil,GLuint dst_texture_id,GLuint src_texture_id)659 void FunctionalTest::dispatch(GLuint program_id, bool is_stencil, GLuint dst_texture_id, GLuint src_texture_id)
660 {
661 const Functions &gl = m_context.getRenderContext().getFunctions();
662 GLenum internal_format = GL_R8UI;
663 GLint uni_image_loc = -1;
664 GLint uni_sampler_loc = -1;
665
666 if (false == is_stencil)
667 {
668 internal_format = GL_R32F;
669 }
670
671 /* Set program */
672 gl.useProgram(program_id);
673 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
674
675 /* Get uniform location and bind texture to proper image unit */
676 uni_image_loc = gl.getUniformLocation(program_id, "uni_image");
677 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation");
678
679 gl.bindImageTexture(m_image_unit, dst_texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* Layer */,
680 GL_WRITE_ONLY, internal_format);
681 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
682
683 gl.uniform1i(uni_image_loc, m_image_unit);
684 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
685
686 /* Get uniform location and bind texture to proper texture unit */
687 uni_sampler_loc = gl.getUniformLocation(program_id, "uni_sampler");
688 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation");
689
690 gl.activeTexture(GL_TEXTURE0 + m_texture_unit);
691 GLU_EXPECT_NO_ERROR(gl.getError(), "ActiveTexture");
692
693 gl.bindTexture(GL_TEXTURE_2D, src_texture_id);
694 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
695
696 gl.uniform1i(uni_sampler_loc, m_texture_unit);
697 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
698
699 /* Dispatch program */
700 gl.dispatchCompute(m_width, m_height, 1);
701 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
702
703 /* Sync */
704 gl.memoryBarrier(GL_ALL_BARRIER_BITS);
705 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
706 }
707
708 /** Execute draw program
709 *
710 * @param program_id ID of program
711 * @param dst_texture_id ID of destination texture
712 * @param src_texture_id ID of source texture
713 **/
draw(GLuint program_id,GLuint dst_texture_id,GLuint src_texture_id)714 void FunctionalTest::draw(GLuint program_id, GLuint dst_texture_id, GLuint src_texture_id)
715 {
716 GLuint fb_id = 0;
717 const Functions &gl = m_context.getRenderContext().getFunctions();
718 GLint uni_sampler_loc = -1;
719 GLuint vao_id = 0;
720
721 try
722 {
723 /* Tesselation patch set up */
724 gl.patchParameteri(GL_PATCH_VERTICES, 1);
725 GLU_EXPECT_NO_ERROR(gl.getError(), "PatchParameteri");
726
727 /* Prepare VAO */
728 gl.genVertexArrays(1, &vao_id);
729 GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
730
731 gl.bindVertexArray(vao_id);
732 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
733
734 /* Prepare FBO */
735 gl.genFramebuffers(1, &fb_id);
736 GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
737
738 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fb_id);
739 GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
740
741 gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, dst_texture_id, 0 /* level */);
742 GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture");
743
744 gl.viewport(0 /* x */, 0 /* y */, m_width, m_height);
745 GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
746
747 /* Set program */
748 gl.useProgram(program_id);
749 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
750
751 /* Get uniform location and bind texture to proper texture unit */
752 uni_sampler_loc = gl.getUniformLocation(program_id, "uni_sampler");
753 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation");
754
755 gl.activeTexture(GL_TEXTURE0 + m_texture_unit);
756 GLU_EXPECT_NO_ERROR(gl.getError(), "ActiveTexture");
757
758 gl.bindTexture(GL_TEXTURE_2D, src_texture_id);
759 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
760
761 gl.uniform1i(uni_sampler_loc, m_texture_unit);
762 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
763
764 /* Draw */
765 gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
766 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
767
768 /* Sync */
769 gl.memoryBarrier(GL_ALL_BARRIER_BITS);
770 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
771 }
772 catch (std::exception &exc)
773 {
774 gl.bindVertexArray(0);
775 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
776 gl.bindTexture(GL_TEXTURE_2D, 0);
777
778 if (0 != vao_id)
779 {
780 gl.deleteVertexArrays(1, &vao_id);
781 }
782
783 if (0 != fb_id)
784 {
785 gl.deleteFramebuffers(1, &fb_id);
786 }
787
788 throw exc;
789 }
790
791 gl.bindVertexArray(0);
792 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
793 gl.bindTexture(GL_TEXTURE_2D, 0);
794
795 if (0 != vao_id)
796 {
797 gl.deleteVertexArrays(1, &vao_id);
798 }
799
800 if (0 != fb_id)
801 {
802 gl.deleteFramebuffers(1, &fb_id);
803 }
804 }
805
806 /** Prepare destination texture
807 *
808 * @param is_stencil Selects if stencil or depth channel is sampled
809 *
810 * @return ID of texture
811 **/
prepareDestinationTexture(bool is_stencil)812 GLuint FunctionalTest::prepareDestinationTexture(bool is_stencil)
813 {
814 static const GLuint n_pixels = m_width * m_height;
815 GLenum format = 0;
816 GLenum internal_format = 0;
817 GLuint pixel_size = 0;
818 std::vector<GLubyte> texture_data;
819 GLuint texture_id = 0;
820 GLuint texture_size = 0;
821 GLenum type = 0;
822
823 /* Select size of pixel */
824 if (true == is_stencil)
825 {
826 format = GL_RED_INTEGER;
827 internal_format = GL_R8UI;
828 pixel_size = 1;
829 type = GL_UNSIGNED_BYTE;
830 }
831 else
832 {
833 format = GL_RED;
834 internal_format = GL_R32F;
835 pixel_size = 4;
836 type = GL_FLOAT;
837 }
838
839 /* Allocate storage */
840 texture_size = pixel_size * n_pixels;
841 texture_data.resize(texture_size);
842
843 /* Fill texture data */
844 memset(&texture_data[0], 0, texture_size);
845
846 /* Create texture */
847 texture_id =
848 Utils::createAndFill2DTexture(m_context, m_width, m_height, internal_format, format, type, &texture_data[0]);
849
850 /* Done */
851 return texture_id;
852 }
853
854 /** Prepare program
855 *
856 * @param is_draw Selects if draw or compute program is prepared
857 * @param is_stencil Selects if stencil or depth channel is sampled
858 *
859 * @return ID of texture
860 **/
prepareProgram(bool is_draw,bool is_stencil)861 GLuint FunctionalTest::prepareProgram(bool is_draw, bool is_stencil)
862 {
863 GLuint program_id = 0;
864
865 if (true != is_draw)
866 {
867 std::string cs_code = m_compute_shader_code;
868 const GLchar *image_definition = m_image_definition_stencil;
869 size_t position = 0;
870 const GLchar *sampler_definition = m_sampler_definition_stencil;
871 const GLchar *type = m_output_type_stencil;
872
873 if (false == is_stencil)
874 {
875 image_definition = m_image_definition_depth;
876 sampler_definition = m_sampler_definition_depth;
877 type = m_output_type_depth;
878 }
879
880 Utils::replaceToken("IMAGE_DEFINITION", position, image_definition, cs_code);
881 Utils::replaceToken("SAMPLER_DEFINITION", position, sampler_definition, cs_code);
882 Utils::replaceToken("TYPE", position, type, cs_code);
883
884 program_id = Utils::createAndBuildProgram(m_context, cs_code.c_str(), 0 /* fs_code */, 0 /* gs_code */,
885 0 /* tcs_code */, 0 /* tes_code */, 0 /* vs_code */);
886 }
887 else
888 {
889 #define N_FUNCTIONAL_TEST_SHADER_STAGES 5
890
891 const GLchar *expected_value = m_expected_value_stencil;
892 const GLchar *sampler_definition = m_sampler_definition_stencil;
893 std::string shader_code[N_FUNCTIONAL_TEST_SHADER_STAGES];
894 const GLchar *shader_templates[N_FUNCTIONAL_TEST_SHADER_STAGES] = {
895 m_fragment_shader_code, m_geometry_shader_code, m_tesselation_control_shader_code,
896 m_tesselation_evaluation_shader_code, m_vertex_shader_code};
897 const GLchar *type = m_output_type_stencil;
898
899 if (false == is_stencil)
900 {
901 expected_value = m_expected_value_depth;
902 sampler_definition = m_sampler_definition_depth;
903 type = m_output_type_depth;
904 }
905
906 for (GLuint i = 0; i < N_FUNCTIONAL_TEST_SHADER_STAGES; ++i)
907 {
908 size_t position = 0;
909
910 shader_code[i] = shader_templates[i];
911
912 if (0 == i)
913 {
914 Utils::replaceToken("TYPE", position, type, shader_code[i]);
915 Utils::replaceToken("SAMPLER_DEFINITION", position, sampler_definition, shader_code[i]);
916 //Utils::replaceToken("TYPE", position, type, shader_code[i]);
917 }
918 else
919 {
920 Utils::replaceToken("SAMPLER_DEFINITION", position, sampler_definition, shader_code[i]);
921 Utils::replaceToken("EXPECTED_VALUE", position, expected_value, shader_code[i]);
922 }
923 }
924
925 program_id =
926 Utils::createAndBuildProgram(m_context, 0 /* cs_code */, shader_code[0].c_str() /* fs_code */,
927 shader_code[1].c_str() /* gs_code */, shader_code[2].c_str() /* tcs_code */,
928 shader_code[3].c_str() /* tes_code */, shader_code[4].c_str() /* vs_code */);
929 }
930
931 /* Done */
932 return program_id;
933 }
934
935 /** Prepare source texture
936 *
937 * @param internal_format Internal format of texture
938 * @param is_stencil Selects if stencil or depth channel is sampled
939 * @param texture_data Texture contents
940 *
941 * @return ID of texture
942 **/
prepareSourceTexture(GLenum internal_format,bool is_stencil,const std::vector<glw::GLubyte> & texture_data)943 GLuint FunctionalTest::prepareSourceTexture(GLenum internal_format, bool is_stencil,
944 const std::vector<glw::GLubyte> &texture_data)
945 {
946 const Functions &gl = m_context.getRenderContext().getFunctions();
947 GLuint texture_id = 0;
948 GLenum type = 0;
949
950 /* Select size of pixel */
951 switch (internal_format)
952 {
953 case GL_DEPTH24_STENCIL8:
954 type = GL_UNSIGNED_INT_24_8;
955 break;
956 case GL_DEPTH32F_STENCIL8:
957 type = GL_FLOAT_32_UNSIGNED_INT_24_8_REV;
958 break;
959 default:
960 TCU_FAIL("Invalid enum");
961 }
962
963 /* Create texture */
964 texture_id = Utils::createAndFill2DTexture(m_context, m_width, m_height, internal_format, GL_DEPTH_STENCIL, type,
965 &texture_data[0]);
966
967 /* Set DS texture mode */
968 gl.bindTexture(GL_TEXTURE_2D, texture_id);
969 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
970
971 if (true == is_stencil)
972 {
973 gl.texParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_STENCIL_INDEX);
974 GLU_EXPECT_NO_ERROR(gl.getError(), "TexParameteri");
975 }
976 else
977 {
978 gl.texParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_DEPTH_COMPONENT);
979 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
980 GLU_EXPECT_NO_ERROR(gl.getError(), "TexParameteri");
981 }
982
983 /* Set nearest filtering */
984 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
985 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
986 GLU_EXPECT_NO_ERROR(gl.getError(), "TexParameteri");
987
988 /* Unbind */
989 gl.bindTexture(GL_TEXTURE_2D, 0);
990 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
991
992 /* Done */
993 return texture_id;
994 }
995
996 /** Prepare data for source texture
997 *
998 * @param internal_format Internal format of texture
999 * @param texture_data Texture contents
1000 *
1001 * @return ID of texture
1002 **/
prepareSourceTextureData(GLenum internal_format,std::vector<GLubyte> & texture_data)1003 void FunctionalTest::prepareSourceTextureData(GLenum internal_format, std::vector<GLubyte> &texture_data)
1004 {
1005 static const GLfloat depth_step_h = -0.5f / ((GLfloat)(m_width - 1));
1006 static const GLfloat depth_step_v = -0.5f / ((GLfloat)(m_height - 1));
1007 static const GLuint stencil_step_h = 1;
1008 static const GLuint stencil_step_v = 1;
1009 static const GLuint n_pixels = m_width * m_height;
1010 GLuint pixel_size = 0;
1011 GLuint line_size = 0;
1012 GLuint texture_size = 0;
1013
1014 /* Select size of pixel */
1015 switch (internal_format)
1016 {
1017 case GL_DEPTH24_STENCIL8:
1018 pixel_size = 4;
1019 break;
1020 case GL_DEPTH32F_STENCIL8:
1021 pixel_size = 8;
1022 break;
1023 default:
1024 TCU_FAIL("Invalid enum");
1025 }
1026
1027 line_size = pixel_size * m_width;
1028 texture_size = pixel_size * n_pixels;
1029
1030 /* Allocate storage */
1031 texture_data.resize(texture_size);
1032
1033 /* Fill texture data */
1034 for (GLuint y = 0; y < m_height; ++y)
1035 {
1036 const GLfloat depth_v = depth_step_v * (GLfloat)y;
1037 const GLuint line_offset = line_size * y;
1038 const GLuint stencil_v = stencil_step_v * y;
1039
1040 for (GLuint x = 0; x < m_width; ++x)
1041 {
1042 const GLfloat depth_h = depth_step_h * (GLfloat)x;
1043 const GLfloat depth_f = 1 + depth_h + depth_v;
1044 const GLuint depth_i = (GLuint)(((GLfloat)0xffffff) * depth_f);
1045 const GLuint pixel_offset = pixel_size * x;
1046 const GLuint stencil_h = stencil_step_h * x;
1047 const GLuint stencil = 1 + stencil_h + stencil_v;
1048
1049 GLubyte *depth_f_data = (GLubyte *)&depth_f;
1050 GLubyte *depth_i_data = (GLubyte *)&depth_i;
1051 GLubyte *pixel_data = &texture_data[0] + line_offset + pixel_offset;
1052 GLubyte *stencil_data = (GLubyte *)&stencil;
1053
1054 switch (pixel_size)
1055 {
1056 case 4:
1057 memcpy(pixel_data, stencil_data, 1);
1058 memcpy(pixel_data + 1, depth_i_data, 3);
1059 break;
1060 case 8:
1061 memcpy(pixel_data, depth_f_data, 4);
1062 memcpy(pixel_data + 4, stencil_data, 1);
1063 break;
1064 default:
1065 TCU_FAIL("Invalid value");
1066 }
1067 }
1068 }
1069 }
1070
1071 /** Verifies that destination texture contents match expectations
1072 *
1073 * @param id ID of destination texture
1074 * @param source_internal_format Internal format of source texture
1075 * @param is_stencil Selects if stencil of depth channel is sampled
1076 * @param src_texture_data Contents of source texture
1077 *
1078 * @return true if everything is fine, false otherwise
1079 **/
verifyTexture(GLuint id,GLenum source_internal_format,bool is_stencil,const std::vector<GLubyte> & src_texture_data)1080 bool FunctionalTest::verifyTexture(GLuint id, GLenum source_internal_format, bool is_stencil,
1081 const std::vector<GLubyte> &src_texture_data)
1082 {
1083 static const GLuint n_pixels = m_width * m_height;
1084 const Functions &gl = m_context.getRenderContext().getFunctions();
1085 GLuint dst_pixel_size = 0;
1086 std::vector<GLubyte> dst_texture_data;
1087 GLuint dst_texture_size = 0;
1088 GLenum format = 0;
1089 GLuint src_pixel_size = 0;
1090 GLuint src_stencil_off = 0;
1091 GLenum type = 0;
1092
1093 /* Select size of pixel */
1094 if (true == is_stencil)
1095 {
1096 format = GL_RED_INTEGER;
1097 dst_pixel_size = 1;
1098 type = GL_UNSIGNED_BYTE;
1099 }
1100 else
1101 {
1102 format = GL_RED;
1103 dst_pixel_size = 4;
1104 type = GL_FLOAT;
1105 }
1106
1107 if (GL_DEPTH24_STENCIL8 == source_internal_format)
1108 {
1109 src_pixel_size = 4;
1110 }
1111 else
1112 {
1113 src_pixel_size = 8;
1114 src_stencil_off = 4;
1115 }
1116
1117 /* Allocate storage */
1118 dst_texture_size = dst_pixel_size * n_pixels;
1119 dst_texture_data.resize(dst_texture_size);
1120
1121 /* Get texture contents */
1122 gl.bindTexture(GL_TEXTURE_2D, id);
1123 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
1124
1125 gl.getTexImage(GL_TEXTURE_2D, 0 /* level */, format, type, &dst_texture_data[0]);
1126 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
1127
1128 gl.bindTexture(GL_TEXTURE_2D, 0);
1129 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
1130
1131 /* For each pixel */
1132 for (GLuint i = 0; i < n_pixels; ++i)
1133 {
1134 const GLuint dst_pixel_offset = dst_pixel_size * i;
1135 const GLuint src_pixel_offset = src_pixel_size * i;
1136
1137 const GLubyte *dst_pixel_data = &dst_texture_data[0] + dst_pixel_offset;
1138 const GLubyte *src_pixel_data = &src_texture_data[0] + src_pixel_offset;
1139
1140 if (true == is_stencil) /* Stencil channel */
1141 {
1142 const GLubyte dst_stencil = dst_pixel_data[0];
1143 const GLubyte src_stencil = src_pixel_data[src_stencil_off];
1144
1145 if (src_stencil != dst_stencil)
1146 {
1147 m_context.getTestContext().getLog()
1148 << tcu::TestLog::Message << "Invalid pixel [" << i << "], got: " << (GLuint)dst_stencil
1149 << " expected: " << (GLuint)src_stencil << tcu::TestLog::EndMessage;
1150
1151 return false;
1152 }
1153 }
1154 else /* Depth channel */
1155 {
1156 if (GL_DEPTH24_STENCIL8 == source_internal_format) /* DEPTH24 */
1157 {
1158 GLfloat dst_depth = 0.0f;
1159 GLuint src_depth_i = 0;
1160 GLfloat src_depth_f = 0.0f;
1161
1162 memcpy(&dst_depth, dst_pixel_data, 4);
1163 memcpy(&src_depth_i, src_pixel_data + 1, 3);
1164
1165 src_depth_f = ((GLfloat)src_depth_i) / ((GLfloat)0xffffff);
1166
1167 if (de::abs(src_depth_f - dst_depth) > 0.0001f)
1168 {
1169 m_context.getTestContext().getLog()
1170 << tcu::TestLog::Message << "Invalid pixel [" << i << "], got: " << dst_depth
1171 << " expected: " << src_depth_f << tcu::TestLog::EndMessage;
1172
1173 return false;
1174 }
1175 }
1176 else /* DEPTH32F */
1177 {
1178 GLfloat dst_depth = 0.0f;
1179 GLfloat src_depth = 0.0f;
1180
1181 memcpy(&dst_depth, dst_pixel_data, 4);
1182 memcpy(&src_depth, src_pixel_data, 4);
1183
1184 if (de::abs(src_depth - dst_depth) > 0.0001f)
1185 {
1186 m_context.getTestContext().getLog()
1187 << tcu::TestLog::Message << "Invalid pixel [" << i << "], got: " << dst_depth
1188 << " expected: " << src_depth << tcu::TestLog::EndMessage;
1189
1190 return false;
1191 }
1192 }
1193 }
1194 }
1195
1196 return true;
1197 }
1198
1199 /** Test given internal format and channel
1200 *
1201 * @param internal_format Internal fromat of source texture
1202 * @param is_stencil Selects if stencil or depth channel is sampled
1203 *
1204 * @return true if results from compute and draw programs are positive, false otherwise
1205 **/
test(GLenum internal_format,bool is_stencil)1206 bool FunctionalTest::test(GLenum internal_format, bool is_stencil)
1207 {
1208 GLuint compute_dst_tex_id = 0;
1209 GLuint compute_program_id = 0;
1210 GLuint compute_src_tex_id = 0;
1211 GLuint draw_dst_tex_id = 0;
1212 GLuint draw_program_id = 0;
1213 GLuint draw_src_tex_id = 0;
1214 const Functions &gl = m_context.getRenderContext().getFunctions();
1215 bool test_result = true;
1216 std::vector<GLubyte> texture_data;
1217
1218 prepareSourceTextureData(internal_format, texture_data);
1219
1220 try
1221 {
1222 if (true == Utils::isExtensionSupported(m_context, "GL_ARB_compute_shader"))
1223 {
1224 compute_dst_tex_id = prepareDestinationTexture(is_stencil);
1225 compute_program_id = prepareProgram(false, is_stencil);
1226 compute_src_tex_id = prepareSourceTexture(internal_format, is_stencil, texture_data);
1227
1228 dispatch(compute_program_id, is_stencil, compute_dst_tex_id, compute_src_tex_id);
1229
1230 if (false == verifyTexture(compute_dst_tex_id, internal_format, is_stencil, texture_data))
1231 {
1232 test_result = false;
1233 }
1234 }
1235
1236 {
1237 draw_dst_tex_id = prepareDestinationTexture(is_stencil);
1238 draw_program_id = prepareProgram(true, is_stencil);
1239 draw_src_tex_id = prepareSourceTexture(internal_format, is_stencil, texture_data);
1240
1241 draw(draw_program_id, draw_dst_tex_id, draw_src_tex_id);
1242
1243 if (false == verifyTexture(draw_dst_tex_id, internal_format, is_stencil, texture_data))
1244 {
1245 test_result = false;
1246 }
1247 }
1248 }
1249 catch (std::exception &exc)
1250 {
1251 gl.bindVertexArray(0);
1252 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
1253 gl.useProgram(0);
1254
1255 Utils::deleteProgram(m_context, compute_program_id);
1256 Utils::deleteProgram(m_context, draw_program_id);
1257
1258 Utils::deleteTexture(m_context, compute_dst_tex_id);
1259 Utils::deleteTexture(m_context, compute_src_tex_id);
1260 Utils::deleteTexture(m_context, draw_dst_tex_id);
1261 Utils::deleteTexture(m_context, draw_src_tex_id);
1262
1263 TCU_FAIL(exc.what());
1264 }
1265
1266 gl.bindVertexArray(0);
1267 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
1268 gl.useProgram(0);
1269
1270 Utils::deleteProgram(m_context, compute_program_id);
1271 Utils::deleteProgram(m_context, draw_program_id);
1272
1273 Utils::deleteTexture(m_context, compute_dst_tex_id);
1274 Utils::deleteTexture(m_context, compute_src_tex_id);
1275 Utils::deleteTexture(m_context, draw_dst_tex_id);
1276 Utils::deleteTexture(m_context, draw_src_tex_id);
1277
1278 /* Done */
1279 return test_result;
1280 }
1281 } /* namespace StencilTexturing */
1282
StencilTexturingTests(deqp::Context & context)1283 StencilTexturingTests::StencilTexturingTests(deqp::Context &context) : TestCaseGroup(context, "stencil_texturing", "")
1284 {
1285 }
1286
~StencilTexturingTests(void)1287 StencilTexturingTests::~StencilTexturingTests(void)
1288 {
1289 }
1290
init()1291 void StencilTexturingTests::init()
1292 {
1293 addChild(new StencilTexturing::FunctionalTest(m_context));
1294 }
1295 } /* namespace gl4cts */
1296