xref: /aosp_15_r20/external/deqp/external/openglcts/modules/gl/gl4cStencilTexturingTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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