1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2014-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  */ /*!
26  * \file  es31cTextureStorageMultisampleFunctionalTests.cpp
27  * \brief Implements conformance tests that verify behavior of
28  *        multisample texture functionality (ES3.1 only).
29  */ /*-------------------------------------------------------------------*/
30 
31 #include "es31cTextureStorageMultisampleFunctionalTests.hpp"
32 #include "gluContextInfo.hpp"
33 #include "gluDefs.hpp"
34 #include "glwEnums.hpp"
35 #include "glwFunctions.hpp"
36 #include "tcuRenderTarget.hpp"
37 #include "tcuTestLog.hpp"
38 
39 #include <algorithm>
40 #include <string.h>
41 #include <string>
42 #include <vector>
43 
44 namespace glcts
45 {
46 /** Constructor.
47  *
48  *  @param context CTS context handle.
49  **/
MultisampleTextureFunctionalTestsBlittingTest(Context & context)50 MultisampleTextureFunctionalTestsBlittingTest::MultisampleTextureFunctionalTestsBlittingTest(Context &context)
51     : TestCase(context, "multisampled_fbo_to_singlesampled_fbo_blit",
52                "Verifies that blitting from a multi-sampled framebuffer object "
53                "to a single-sampled framebuffer object does not generate an error.")
54     , dst_fbo_id(0)
55     , dst_to_color_id(0)
56     , dst_to_depth_stencil_id(0)
57     , src_fbo_id(0)
58     , src_to_color_id(0)
59     , src_to_depth_stencil_id(0)
60 {
61     /* Left blank on purpose */
62 }
63 
64 /** Deinitializes ES objects created during test execution */
deinit()65 void MultisampleTextureFunctionalTestsBlittingTest::deinit()
66 {
67     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
68 
69     if (dst_fbo_id != 0)
70     {
71         gl.deleteFramebuffers(1, &dst_fbo_id);
72 
73         dst_fbo_id = 0;
74     }
75 
76     if (src_fbo_id != 0)
77     {
78         gl.deleteFramebuffers(1, &src_fbo_id);
79 
80         src_fbo_id = 0;
81     }
82 
83     if (dst_to_color_id != 0)
84     {
85         gl.deleteTextures(1, &dst_to_color_id);
86 
87         dst_to_color_id = 0;
88     }
89 
90     if (dst_to_depth_stencil_id != 0)
91     {
92         gl.deleteTextures(1, &dst_to_depth_stencil_id);
93 
94         dst_to_depth_stencil_id = 0;
95     }
96 
97     if (src_to_color_id != 0)
98     {
99         gl.deleteTextures(1, &src_to_color_id);
100 
101         src_to_color_id = 0;
102     }
103 
104     if (src_to_depth_stencil_id != 0)
105     {
106         gl.deleteTextures(1, &src_to_depth_stencil_id);
107 
108         src_to_depth_stencil_id = 0;
109     }
110 
111     /* Call base class' deinit() */
112     TestCase::deinit();
113 }
114 
115 /** Executes test iteration.
116  *
117  *  @return Returns STOP when test has finished executing.
118  */
iterate()119 tcu::TestNode::IterateResult MultisampleTextureFunctionalTestsBlittingTest::iterate()
120 {
121     bool are_2d_ms_array_tos_supported =
122         m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array");
123     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
124 
125     /* Set up texture objects */
126     gl.genTextures(1, &dst_to_color_id);
127     gl.genTextures(1, &dst_to_depth_stencil_id);
128     gl.genTextures(1, &src_to_color_id);
129     gl.genTextures(1, &src_to_depth_stencil_id);
130 
131     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up texture objects");
132 
133     if (are_2d_ms_array_tos_supported)
134     {
135         gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, src_to_color_id);
136         gl.texStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2, /* samples */
137                                    GL_RGBA8, 4,                            /* width */
138                                    4,                                      /* height */
139                                    4,                                      /* depth */
140                                    GL_TRUE);                               /* fixedsamplelocations */
141         GLU_EXPECT_NO_ERROR(gl.getError(),
142                             "gltexStorage3DMultisample() call failed for texture object src_to_color_id");
143     }
144     else
145     {
146         gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, src_to_color_id);
147         gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, /* samples */
148                                    GL_RGBA8, 4,                  /* width */
149                                    4,                            /* height */
150                                    GL_TRUE);                     /* fixedsamplelocations */
151 
152         GLU_EXPECT_NO_ERROR(gl.getError(),
153                             "gltexStorage3DMultisample() call failed for texture object src_to_color_id");
154     }
155 
156     gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, src_to_depth_stencil_id);
157     gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, /* samples */
158                                GL_DEPTH32F_STENCIL8, 4,      /* width */
159                                4,                            /* height */
160                                GL_TRUE);                     /* fixedsamplelocations */
161     GLU_EXPECT_NO_ERROR(gl.getError(),
162                         "glTexStorage2DMultisample() call failed for texture object src_to_depth_stencil_id");
163 
164     gl.bindTexture(GL_TEXTURE_2D, dst_to_color_id);
165     gl.texImage2D(GL_TEXTURE_2D, 0,                 /* level */
166                   GL_RGBA8, 4,                      /* width */
167                   4,                                /* height */
168                   0,                                /* border */
169                   GL_RGBA, GL_UNSIGNED_BYTE, NULL); /* data */
170     GLU_EXPECT_NO_ERROR(gl.getError(), "glTexImage2D() call failed for texture object dst_to_color_id");
171 
172     gl.bindTexture(GL_TEXTURE_2D_ARRAY, dst_to_depth_stencil_id);
173     gl.texImage3D(GL_TEXTURE_2D_ARRAY, 0,                                     /* level */
174                   GL_DEPTH32F_STENCIL8, 4,                                    /* width */
175                   4,                                                          /* height */
176                   4,                                                          /* depth */
177                   0,                                                          /* border */
178                   GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, NULL); /* data */
179     GLU_EXPECT_NO_ERROR(gl.getError(), "glTexImage3D9) call failed for texture object dst_to_depth_stencil_id");
180 
181     /* Set up framebuffer objects */
182     gl.genFramebuffers(1, &dst_fbo_id);
183     gl.genFramebuffers(1, &src_fbo_id);
184     gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, dst_fbo_id);
185     gl.bindFramebuffer(GL_READ_FRAMEBUFFER, src_fbo_id);
186 
187     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up framebuffer objects");
188 
189     /* Set up source FBO attachments. */
190     glw::GLenum fbo_completeness_status = 0;
191 
192     if (are_2d_ms_array_tos_supported)
193     {
194         gl.framebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, src_to_color_id, 0, /* level */
195                                    0);                                                            /* layer */
196     }
197     else
198     {
199         gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, src_to_color_id,
200                                 0); /* level */
201     }
202 
203     gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE,
204                             src_to_depth_stencil_id, 0); /* level */
205 
206     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up source framebuffer's attachments");
207 
208     fbo_completeness_status = gl.checkFramebufferStatus(GL_READ_FRAMEBUFFER);
209 
210     if (fbo_completeness_status != GL_FRAMEBUFFER_COMPLETE)
211     {
212         m_testCtx.getLog() << tcu::TestLog::Message << "Source FBO completeness status is: " << fbo_completeness_status
213                            << ", expected: GL_FRAMEBUFFER_COMPLETE" << tcu::TestLog::EndMessage;
214 
215         TCU_FAIL("Source FBO is considered incomplete which is invalid");
216     }
217 
218     /* Set up draw FBO attachments */
219     gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst_to_color_id, 0);   /* level */
220     gl.framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, dst_to_depth_stencil_id, 0, /* level */
221                                0);                                                                           /* layer */
222     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up draw framebuffer's attachments");
223 
224     fbo_completeness_status = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER);
225 
226     if (fbo_completeness_status != GL_FRAMEBUFFER_COMPLETE)
227     {
228         m_testCtx.getLog() << tcu::TestLog::Message << "Draw FBO completeness status is: " << fbo_completeness_status
229                            << ", expected: GL_FRAMEBUFFER_COMPLETE" << tcu::TestLog::EndMessage;
230 
231         TCU_FAIL("Draw FBO is considered incomplete which is invalid");
232     }
233 
234     /* Perform the blitting operation */
235     gl.blitFramebuffer(0, /* srcX0 */
236                        0, /* srcY0 */
237                        4, /* srcX1 */
238                        4, /* srcY1 */
239                        0, /* dstX0 */
240                        0, /* dstY0 */
241                        4, /* dstX1 */
242                        4, /* dstY1 */
243                        GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
244                        GL_NEAREST); /* An INVALID_OPERATION error is generated if ...., and filter is not NEAREST. */
245 
246     /* Make sure no error was generated */
247     GLU_EXPECT_NO_ERROR(gl.getError(), "glBlitFramebuffer() call failed.");
248 
249     /* All done */
250     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
251 
252     return STOP;
253 }
254 
255 /** Constructor.
256  *
257  *  @param context CTS context handle.
258  **/
259 MultisampleTextureFunctionalTestsBlittingMultisampledDepthAttachmentTest::
MultisampleTextureFunctionalTestsBlittingMultisampledDepthAttachmentTest(Context & context)260     MultisampleTextureFunctionalTestsBlittingMultisampledDepthAttachmentTest(Context &context)
261     : TestCase(context, "blitting_multisampled_depth_attachment",
262                "Verifies that blitting a multi-sampled depth attachment to "
263                "a single-sampled depth attachment gives valid results")
264     , fbo_dst_id(0)
265     , fbo_src_id(0)
266     , fs_depth_preview_id(0)
267     , fs_id(0)
268     , po_depth_preview_id(0)
269     , po_id(0)
270     , to_dst_preview_id(0)
271     , to_dst_id(0)
272     , to_src_id(0)
273     , vao_id(0)
274     , vs_id(0)
275 {
276     /* Left blank on purpose */
277 }
278 
279 /** Deinitializes ES objects created during test execution */
deinit()280 void MultisampleTextureFunctionalTestsBlittingMultisampledDepthAttachmentTest::deinit()
281 {
282     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
283 
284     if (fbo_dst_id != 0)
285     {
286         gl.deleteFramebuffers(1, &fbo_dst_id);
287 
288         fbo_dst_id = 0;
289     }
290 
291     if (fbo_src_id != 0)
292     {
293         gl.deleteFramebuffers(1, &fbo_src_id);
294 
295         fbo_src_id = 0;
296     }
297 
298     if (to_dst_preview_id != 0)
299     {
300         gl.deleteTextures(1, &to_dst_preview_id);
301 
302         to_dst_preview_id = 0;
303     }
304 
305     if (to_dst_id != 0)
306     {
307         gl.deleteTextures(1, &to_dst_id);
308 
309         to_dst_id = 0;
310     }
311 
312     if (to_src_id != 0)
313     {
314         gl.deleteTextures(1, &to_src_id);
315 
316         to_src_id = 0;
317     }
318 
319     if (fs_id != 0)
320     {
321         gl.deleteShader(fs_id);
322 
323         fs_id = 0;
324     }
325 
326     if (fs_depth_preview_id != 0)
327     {
328         gl.deleteShader(fs_depth_preview_id);
329 
330         fs_depth_preview_id = 0;
331     }
332 
333     if (po_depth_preview_id != 0)
334     {
335         gl.deleteProgram(po_depth_preview_id);
336 
337         po_depth_preview_id = 0;
338     }
339 
340     if (po_id != 0)
341     {
342         gl.deleteProgram(po_id);
343 
344         po_id = 0;
345     }
346 
347     if (vao_id != 0)
348     {
349         gl.deleteVertexArrays(1, &vao_id);
350 
351         vao_id = 0;
352     }
353 
354     if (vs_id != 0)
355     {
356         gl.deleteShader(vs_id);
357 
358         vs_id = 0;
359     }
360 
361     /* Call base class' deinit() */
362     TestCase::deinit();
363 }
364 
365 /** Executes test iteration.
366  *
367  *  @return Returns STOP when test has finished executing.
368  */
iterate()369 tcu::TestNode::IterateResult MultisampleTextureFunctionalTestsBlittingMultisampledDepthAttachmentTest::iterate()
370 {
371     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
372 
373     /* Generate all objects this test will use */
374     fs_depth_preview_id = gl.createShader(GL_FRAGMENT_SHADER);
375     fs_id               = gl.createShader(GL_FRAGMENT_SHADER);
376     vs_id               = gl.createShader(GL_VERTEX_SHADER);
377 
378     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() failed");
379 
380     po_depth_preview_id = gl.createProgram();
381     po_id               = gl.createProgram();
382 
383     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed");
384 
385     gl.genTextures(1, &to_src_id);
386     gl.genTextures(1, &to_dst_preview_id);
387     gl.genTextures(1, &to_dst_id);
388 
389     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed");
390 
391     gl.genFramebuffers(1, &fbo_src_id);
392     gl.genFramebuffers(1, &fbo_dst_id);
393 
394     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() failed");
395 
396     gl.genVertexArrays(1, &vao_id);
397 
398     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() failed");
399 
400     /* Bind FBOs to relevant FB targets */
401     gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_dst_id);
402     gl.bindFramebuffer(GL_READ_FRAMEBUFFER, fbo_src_id);
403 
404     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call(s) failed");
405 
406     /* Configure body of vs_id vertex shader */
407     const glw::GLchar *vs_body = "#version 310 es\n"
408                                  "\n"
409                                  "precision highp float;\n"
410                                  "\n"
411                                  "out vec2 uv;\n"
412                                  "\n"
413                                  "void main()\n"
414                                  "{\n"
415                                  "    switch(gl_VertexID)\n"
416                                  "    {\n"
417                                  "        case 0: gl_Position = vec4(-1, -1, 0, 1); uv = vec2(0, 0); break;\n"
418                                  "        case 1: gl_Position = vec4(-1,  1, 0, 1); uv = vec2(0, 1); break;\n"
419                                  "        case 2: gl_Position = vec4( 1,  1, 0, 1); uv = vec2(1, 1); break;\n"
420                                  "        case 3: gl_Position = vec4( 1, -1, 0, 1); uv = vec2(1, 0); break;\n"
421                                  "    }\n"
422                                  "}\n";
423 
424     gl.shaderSource(vs_id, 1 /* count */, &vs_body, NULL);
425     GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for vertex shader of vs_id id");
426 
427     /* Configure body of fs_id fragment shader */
428     const glw::GLchar *fs_body = "#version 310 es\n"
429                                  "\n"
430                                  "precision highp float;\n"
431                                  "\n"
432                                  "in vec2 uv;\n"
433                                  "\n"
434                                  "void main()\n"
435                                  "{\n"
436                                  "    gl_FragDepth = uv.x * uv.y;\n"
437                                  "}\n";
438 
439     gl.shaderSource(fs_id, 1 /* count */, &fs_body, NULL);
440     GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for fragment shader of fs_id id");
441 
442     /* Configure body of fs_depth_preview_id fragment shader */
443     const glw::GLchar *fs_depth_preview_body = "#version 310 es\n"
444                                                "\n"
445                                                "precision highp int;\n"
446                                                "precision highp float;\n"
447                                                "\n"
448                                                "in      vec2      uv;\n"
449                                                "out     uint      result;\n"
450                                                "uniform sampler2D tex;\n"
451                                                "\n"
452                                                "void main()\n"
453                                                "{\n"
454                                                "    result = floatBitsToUint(textureLod(tex, uv, 0.0).x);\n"
455                                                "}\n";
456 
457     gl.shaderSource(fs_depth_preview_id, 1 /* count */, &fs_depth_preview_body, NULL);
458     GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed for fragment shader of fs_depth_preview_id id");
459 
460     /* Compile all the shaders */
461     const glw::GLuint shader_ids[]  = {fs_id, fs_depth_preview_id, vs_id};
462     const unsigned int n_shader_ids = sizeof(shader_ids) / sizeof(shader_ids[0]);
463 
464     for (unsigned int n_shader_id = 0; n_shader_id < n_shader_ids; ++n_shader_id)
465     {
466         glw::GLint compile_status = GL_FALSE;
467 
468         gl.compileShader(shader_ids[n_shader_id]);
469         GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() failed");
470 
471         gl.getShaderiv(shader_ids[n_shader_id], GL_COMPILE_STATUS, &compile_status);
472         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() failed");
473 
474         if (compile_status != GL_TRUE)
475         {
476             TCU_FAIL("Shader compilation failure");
477         }
478     } /* for (all shader ids) */
479 
480     /* Configure and link both program objects */
481     const glw::GLuint program_ids[]  = {po_depth_preview_id, po_id};
482     const unsigned int n_program_ids = sizeof(program_ids) / sizeof(program_ids[0]);
483 
484     gl.attachShader(po_depth_preview_id, fs_depth_preview_id);
485     gl.attachShader(po_depth_preview_id, vs_id);
486     gl.attachShader(po_id, fs_id);
487     gl.attachShader(po_id, vs_id);
488     GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() failed");
489 
490     for (unsigned int n_program_id = 0; n_program_id < n_program_ids; ++n_program_id)
491     {
492         glw::GLint link_status = GL_FALSE;
493 
494         gl.linkProgram(program_ids[n_program_id]);
495         GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() failed");
496 
497         gl.getProgramiv(program_ids[n_program_id], GL_LINK_STATUS, &link_status);
498         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() failed");
499 
500         if (link_status != GL_TRUE)
501         {
502             TCU_FAIL("Program linking failure");
503         }
504     } /* for (all program ids) */
505 
506     /* Retrieve maximum amount of samples that can be used for GL_DEPTH_COMPONENT32F internalformat */
507     glw::GLint n_depth_component32f_max_samples = 0;
508 
509     gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_DEPTH_COMPONENT32F, GL_SAMPLES, 1, /* bufSize */
510                            &n_depth_component32f_max_samples);
511     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetInternalformativ() failed");
512 
513     /* Configure texture storage for to_src_id */
514     gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_src_id);
515     gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, n_depth_component32f_max_samples, GL_DEPTH_COMPONENT32F,
516                                64,        /* width */
517                                64,        /* height */
518                                GL_FALSE); /* fixedsamplelocations */
519 
520     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure texture storage for texture object to_src_id");
521 
522     gl.texParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
523 
524     /* When <target> is TEXTURE_2D_MULTISAMPLE  or
525      TEXTURE_2D_MULTISAMPLE_ARRAY_XXX, certain texture parameters may not be
526      specified. In this case, an INVALID_ENUM error is generated if the
527      parameter is any sampler state value from table 6.10. */
528     glw::GLenum error_code = gl.getError();
529     if (error_code != GL_INVALID_ENUM)
530     {
531         m_testCtx.getLog() << tcu::TestLog::Message << "glTexParameteri() call generated an error " << error_code
532                            << " instead of the expected error code " << GL_INVALID_ENUM << tcu::TestLog::EndMessage;
533 
534         TCU_FAIL("glTexParameterf() with target GL_TEXTURE_2D_MULTISAMPLE and pname=GL_TEXTURE_MIN_FILTER did not "
535                  "generate GL_INVALID_ENUM.");
536     }
537 
538     /* Configure texture storage for to_dst_id */
539     gl.bindTexture(GL_TEXTURE_2D, to_dst_id);
540     gl.texStorage2D(GL_TEXTURE_2D, 1,          /* levels */
541                     GL_DEPTH_COMPONENT32F, 64, /* width */
542                     64);                       /* height */
543 
544     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure texture storage for texture object to_dst_id");
545 
546     gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
547     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set nearest minification filter for texture object to_dst_id");
548 
549     gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
550     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set nearest magnification filter for texture object to_dst_id");
551 
552     /* Configure draw framebuffer */
553     gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE, to_src_id,
554                             0); /* level */
555     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure draw framebuffer for depth data rendering");
556 
557     /* Render the test geometry.
558      *
559      * NOTE: Original test spec rendered to fbo_dst_id which would have been invalid,
560      *       since fbo_dst_id is the assumed destination for the blitting operation.
561      *       Actual FBO management code has been rewritten to improve code clarity.
562      *
563      * NOTE: Original test spec didn't enable the depth tests, which are necessary
564      *       for the depth buffer to be updated.
565      **/
566     gl.viewport(0, 0, 64 /* rt width */, 64 /* rt height */);
567     GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() failed");
568 
569     gl.enable(GL_DEPTH_TEST);
570     GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_DEPTH_TEST) failed");
571 
572     gl.depthFunc(GL_ALWAYS);
573     GLU_EXPECT_NO_ERROR(gl.getError(), "gldepthFunc(GL_ALWAYS) failed");
574 
575     gl.useProgram(po_id);
576     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() for program object po_id failed");
577 
578     gl.bindVertexArray(vao_id);
579     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() failed");
580 
581     gl.drawArrays(GL_TRIANGLE_FAN, 0 /* first */, 4 /* count */);
582     GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed");
583 
584     /* Configure FBOs for blitting */
585     gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE, to_src_id,
586                             0); /* level */
587 
588     gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, to_dst_id, 0); /* level */
589 
590     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure FBOs for blitting");
591 
592     /* Blit source FBO to destination FBO */
593     gl.blitFramebuffer(0,  /* srcX0 */
594                        0,  /* srcY0 */
595                        64, /* srcX1 */
596                        64, /* srcY1 */
597                        0,  /* dstX0 */
598                        0,  /* dstY0 */
599                        64, /* dstX1 */
600                        64, /* dstY1 */
601                        GL_DEPTH_BUFFER_BIT, GL_NEAREST);
602     GLU_EXPECT_NO_ERROR(gl.getError(), "glBlitFramebuffer() failed");
603 
604     /* Single-sampled depth data is now stored in dst_to_id in GL_DEPTH_COMPONENT32F which may
605      * not work too well with glReadPixels().
606      *
607      * We will now convert it to GL_R32UI using the other program */
608     gl.useProgram(po_depth_preview_id);
609     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed for program object po_depth_preview_id");
610 
611     /* Configure texture storage for the destination texture object */
612     gl.bindTexture(GL_TEXTURE_2D, to_dst_preview_id);
613     gl.texStorage2D(GL_TEXTURE_2D, 1, /* levels */
614                     GL_R32UI, 64,     /* width */
615                     64);              /* height */
616 
617     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up texcture storage for texture object to_dst_preview_id");
618 
619     gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
620     GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() failed for texture object to_dst_preview_id");
621 
622     /* Update draw framebuffer configuration */
623     gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, /* texture */
624                             0);                                                         /* level */
625 
626     gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, to_dst_preview_id, 0); /* level */
627 
628     GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() failed for depth preview pass");
629 
630     /* Render a full-screen quad */
631     gl.bindTexture(GL_TEXTURE_2D, to_dst_id);
632 
633     gl.drawArrays(GL_TRIANGLE_FAN, 0 /* first */, 4 /* count */);
634     GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed for depth preview pass");
635 
636     /* to_dst_id now contains the result data.
637      *
638      * Before we do a glReadPixels() call, we need to re-configure the read FBO */
639     gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, /* texture */
640                             0);                                                         /* level */
641 
642     gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, to_dst_preview_id, 0); /* level */
643 
644     GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() failed for depth data download pass");
645 
646     /* Read the data */
647     unsigned int buffer[64 /* width */ * 64 /* height */ * 4 /* components */];
648 
649     gl.readPixels(0,  /* x */
650                   0,  /* y */
651                   64, /* width */
652                   64, /* height */
653                   GL_RGBA_INTEGER, GL_UNSIGNED_INT, buffer);
654     GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() failed for depth data download pass");
655 
656     /* Verify the rendered data */
657     const float epsilon = 1.0f / 64.0f + (float)1e-5;
658 
659     for (int y = 0; y < 64 /* height */; ++y)
660     {
661         /* NOTE: data_y is used to take the bottom-top orientation of the data downloaded
662          *       by glReadPixels() into account.
663          */
664         const int data_y     = (64 /* height */ - y - 1 /* counting starts from 0 */);
665         const int pixel_size = 4; /* components */
666         const int row_width  = 64 /* width */ * pixel_size;
667         float *row_ptr       = (float *)buffer + row_width * data_y;
668 
669         for (int x = 0; x < 64 /* width */; ++x)
670         {
671             float *data_ptr          = row_ptr + x * pixel_size;
672             float depth              = data_ptr[0];
673             float expected_value_max = float(x) * float(data_y) / (64.0f * 64.0f) + epsilon;
674             float expected_value_min = float(x) * float(data_y) / (64.0f * 64.0f) - epsilon;
675 
676             if (!(depth >= expected_value_min && depth <= expected_value_max))
677             {
678                 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid data rendered at (" << x << ", " << y << "): "
679                                    << "Expected value from " << expected_value_min << " to " << expected_value_max
680                                    << ", "
681                                    << "rendered: " << depth << tcu::TestLog::EndMessage;
682 
683                 TCU_FAIL("Invalid data rendered");
684             }
685         } /* for (all x argument values) */
686     }     /* for (all y argument values) */
687 
688     /* All done */
689     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
690 
691     return STOP;
692 }
693 
694 /** Constructor.
695  *
696  *  @param context CTS context handle.
697  **/
698 MultisampleTextureFunctionalTestsBlittingMultisampledIntegerAttachmentTest::
MultisampleTextureFunctionalTestsBlittingMultisampledIntegerAttachmentTest(Context & context)699     MultisampleTextureFunctionalTestsBlittingMultisampledIntegerAttachmentTest(Context &context)
700     : TestCase(context, "blitting_multisampled_integer_attachment",
701                "Verifies that blitting a multi-sampled integer attachment "
702                "to a single-sampled integer attachment gives valid results")
703     , dst_to_id(0)
704     , fbo_draw_id(0)
705     , fbo_read_id(0)
706     , fs_id(0)
707     , po_id(0)
708     , src_to_id(0)
709     , vs_id(0)
710 {
711     /* Left blank on purpose */
712 }
713 
714 /** Deinitializes ES objects created during test execution */
deinit()715 void MultisampleTextureFunctionalTestsBlittingMultisampledIntegerAttachmentTest::deinit()
716 {
717     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
718 
719     if (fbo_draw_id != 0)
720     {
721         gl.deleteFramebuffers(1, &fbo_draw_id);
722 
723         fbo_draw_id = 0;
724     }
725 
726     if (fbo_read_id != 0)
727     {
728         gl.deleteFramebuffers(1, &fbo_read_id);
729 
730         fbo_read_id = 0;
731     }
732 
733     if (dst_to_id != 0)
734     {
735         gl.deleteTextures(1, &dst_to_id);
736 
737         dst_to_id = 0;
738     }
739 
740     if (src_to_id != 0)
741     {
742         gl.deleteTextures(1, &src_to_id);
743 
744         src_to_id = 0;
745     }
746 
747     if (fs_id != 0)
748     {
749         gl.deleteShader(fs_id);
750 
751         fs_id = 0;
752     }
753 
754     if (po_id != 0)
755     {
756         gl.deleteProgram(po_id);
757 
758         po_id = 0;
759     }
760 
761     if (vs_id != 0)
762     {
763         gl.deleteShader(vs_id);
764 
765         vs_id = 0;
766     }
767 
768     /* Call base class' deinit() */
769     TestCase::deinit();
770 }
771 
772 /** Executes test iteration.
773  *
774  *  @return Returns STOP when test has finished executing.
775  */
iterate()776 tcu::TestNode::IterateResult MultisampleTextureFunctionalTestsBlittingMultisampledIntegerAttachmentTest::iterate()
777 {
778     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
779 
780     /* Make sure GL_MAX_INTEGER_SAMPLES is at least 2 */
781     glw::GLint gl_max_integer_samples_value = 0;
782 
783     gl.getIntegerv(GL_MAX_INTEGER_SAMPLES, &gl_max_integer_samples_value);
784     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not query GL_MAX_INTEGER_SAMPLES pname value");
785 
786     if (gl_max_integer_samples_value < 2)
787     {
788         throw tcu::NotSupportedError("GL_MAX_INTEGER_SAMPLES is lower than 2");
789     }
790 
791     /* Retrieve maximum amount of samples for GL_R16UI internalformat */
792     glw::GLint r16ui_max_samples = 0;
793 
794     gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, GL_R16UI, GL_SAMPLES, 1 /* bufSize */, &r16ui_max_samples);
795     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetInternalformativ() call failed.");
796 
797     /* Set up texture objects */
798     gl.genTextures(1, &dst_to_id);
799     gl.genTextures(1, &src_to_id);
800 
801     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up texture objects");
802 
803     gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, src_to_id);
804     gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, r16ui_max_samples, GL_R16UI, 16, /* width */
805                                16,                                                         /* height */
806                                GL_FALSE);                                                  /* fixedsamplelocations */
807     GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample() call failed for texture object src_to_id");
808 
809     gl.bindTexture(GL_TEXTURE_2D, dst_to_id);
810     gl.texStorage2D(GL_TEXTURE_2D, 1, /* levels */
811                     GL_R16UI, 16,     /* width */
812                     16);              /* height */
813 
814     GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed for texture object dst_to_id");
815 
816     /* Create a program object */
817     po_id = gl.createProgram();
818     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed");
819 
820     /* Create two shader objects */
821     fs_id = gl.createShader(GL_FRAGMENT_SHADER);
822     vs_id = gl.createShader(GL_VERTEX_SHADER);
823 
824     GLU_EXPECT_NO_ERROR(gl.getError(), "Either of the glCreateShader() calls failed");
825 
826     /* Set up framebuffer objects */
827     gl.genFramebuffers(1, &fbo_draw_id);
828     gl.genFramebuffers(1, &fbo_read_id);
829     gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_draw_id);
830     gl.bindFramebuffer(GL_READ_FRAMEBUFFER, fbo_read_id);
831 
832     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up framebuffer objects");
833 
834     /* Set up draw FBO's color attachment. */
835     gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, src_to_id,
836                             0); /* level */
837 
838     GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed");
839 
840     /* Set up shader objects.
841      *
842      * NOTE: Original test spec specified an invalid case 3 for the vertex shader.
843      * NOTE: Original test case used a float output value. This would not be valid,
844      *       as the color buffer's attachment uses GL_R16UI format.
845      */
846     glw::GLint compile_status  = GL_FALSE;
847     static const char *fs_body = "#version 310 es\n"
848                                  "\n"
849                                  "precision highp float;\n"
850                                  "\n"
851                                  "uniform uint  n_sample;\n"
852                                  "uniform uint  n_max_samples;\n"
853                                  "uniform highp uvec2 x1y1;\n"
854                                  "out     uint  result;\n"
855                                  "\n"
856                                  "void main()\n"
857                                  "{\n"
858                                  "    uint row_index    = x1y1.y;\n"
859                                  "    uint column_index = x1y1.x;\n"
860                                  "\n"
861                                  "    if (n_sample < n_max_samples / 2u)\n"
862                                  "    {\n"
863                                  "        result = row_index * 16u + column_index;\n"
864                                  "    }\n"
865                                  "    else\n"
866                                  "    {\n"
867                                  "        result = row_index * 16u + column_index + 1u;\n"
868                                  "    }\n"
869                                  "}\n";
870     static const char *vs_body = "#version 310 es\n"
871                                  "\n"
872                                  "uniform uvec2 x1y1;\n"
873                                  "\n"
874                                  "void main()\n"
875                                  "{\n"
876                                  "    switch (gl_VertexID)\n"
877                                  "    {\n"
878                                  "        case 0: gl_Position = vec4( (float(x1y1.x) + 0.0 - 8.0)/8.0, (float(x1y1.y) "
879                                  "+ 0.0 - 8.0)/8.0, 0.0, 1.0); break;\n"
880                                  "        case 1: gl_Position = vec4( (float(x1y1.x) + 1.0 - 8.0)/8.0, (float(x1y1.y) "
881                                  "+ 0.0 - 8.0)/8.0, 0.0, 1.0); break;\n"
882                                  "        case 2: gl_Position = vec4( (float(x1y1.x) + 1.0 - 8.0)/8.0, (float(x1y1.y) "
883                                  "+ 1.0 - 8.0)/8.0, 0.0, 1.0); break;\n"
884                                  "        case 3: gl_Position = vec4( (float(x1y1.x) + 0.0 - 8.0)/8.0, (float(x1y1.y) "
885                                  "+ 1.0 - 8.0)/8.0, 0.0, 1.0); break;\n"
886                                  "    }\n"
887                                  "}\n";
888 
889     gl.attachShader(po_id, fs_id);
890     gl.attachShader(po_id, vs_id);
891     GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed.");
892 
893     gl.shaderSource(fs_id, 1 /* count */, &fs_body, NULL);
894     gl.shaderSource(vs_id, 1 /* count */, &vs_body, NULL);
895     GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call(s) failed.");
896 
897     gl.compileShader(fs_id);
898     gl.compileShader(vs_id);
899     GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call(s) failed.");
900 
901     gl.getShaderiv(fs_id, GL_COMPILE_STATUS, &compile_status);
902     if (compile_status != GL_TRUE)
903     {
904         TCU_FAIL("Could not compile fragment shader");
905     }
906 
907     gl.getShaderiv(vs_id, GL_COMPILE_STATUS, &compile_status);
908     if (compile_status != GL_TRUE)
909     {
910         /* Retrieve and dump compilation fail reason */
911         char infoLog[1024];
912         glw::GLsizei length = 0;
913 
914         gl.getShaderInfoLog(vs_id, 1024, &length, infoLog);
915 
916         m_testCtx.getLog() << tcu::TestLog::Message << "Vertex shader compilation failed, infoLog: " << infoLog
917                            << tcu::TestLog::EndMessage;
918 
919         TCU_FAIL("Could not compile vertex shader");
920     }
921 
922     /* Link the program object */
923     glw::GLint link_status = GL_FALSE;
924 
925     gl.linkProgram(po_id);
926     GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() failed");
927 
928     gl.getProgramiv(po_id, GL_LINK_STATUS, &link_status);
929     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() failed");
930 
931     if (link_status != GL_TRUE)
932     {
933         TCU_FAIL("Could not link program object");
934     }
935 
936     /* Enable GL_SAMPLE_MASK mode */
937     gl.enable(GL_SAMPLE_MASK);
938 
939     GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_SAMPLE_MASK) call generated an unexpected error");
940 
941     /* Prepare for rendering */
942     glw::GLint n_max_samples_uniform_location = gl.getUniformLocation(po_id, "n_max_samples");
943     glw::GLint n_sample_uniform_location      = gl.getUniformLocation(po_id, "n_sample");
944     glw::GLint x1y1_uniform_location          = gl.getUniformLocation(po_id, "x1y1");
945 
946     if (n_max_samples_uniform_location == -1)
947     {
948         TCU_FAIL("n_max_samples is not considered an active uniform.");
949     }
950 
951     if (n_sample_uniform_location == -1)
952     {
953         TCU_FAIL("n_sample is not considered an active uniform.");
954     }
955 
956     if (x1y1_uniform_location == -1)
957     {
958         TCU_FAIL("x1y1 is not considered an active uniform.");
959     }
960 
961     gl.viewport(0 /* x */, 0 /* y */, 16 /* width */, 16 /* height */);
962     GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed");
963 
964     gl.useProgram(po_id);
965     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed");
966 
967     gl.uniform1ui(n_max_samples_uniform_location, r16ui_max_samples);
968     GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1ui() call failed");
969 
970     /* Clear color buffer before drawing to it, not strictly neccesary
971      * but helps debugging */
972     glw::GLuint clear_color_src[] = {11, 22, 33, 44};
973 
974     gl.clearBufferuiv(GL_COLOR, 0, clear_color_src);
975     GLU_EXPECT_NO_ERROR(gl.getError(), "glClearBufferiv() call failed");
976 
977     /* Render */
978     for (int x = 0; x < 16 /* width */; ++x)
979     {
980         for (int y = 0; y < 16 /* height */; ++y)
981         {
982             for (int n_sample = 0; n_sample < r16ui_max_samples; ++n_sample)
983             {
984                 gl.uniform1ui(n_sample_uniform_location, n_sample);
985                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1ui() call failed");
986 
987                 gl.uniform2ui(x1y1_uniform_location, x, y);
988                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform2f() call failed");
989 
990                 gl.sampleMaski(n_sample / 32, 1 << (n_sample % 32));
991                 GLU_EXPECT_NO_ERROR(gl.getError(), "glSampleMaski() call failed.");
992 
993                 gl.drawArrays(GL_TRIANGLE_FAN, 0 /* first */, 4 /* count */);
994                 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
995             } /* for (all n_sample values) */
996         }     /* for (all y values) */
997     }         /* for (all x values) */
998 
999     /* Now, configure the framebuffer binding points for the blitting operation */
1000     gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst_to_id, 0); /* level */
1001     gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, src_to_id,
1002                             0); /* level */
1003     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up framebuffer objects for the blitting operation");
1004 
1005     /* Clear color buffer before drawing to it, not strictly neccesary
1006      * but helps debugging */
1007     glw::GLuint clear_color_dst[] = {55, 66, 77, 88};
1008 
1009     gl.clearBufferuiv(GL_COLOR, 0, clear_color_dst);
1010     GLU_EXPECT_NO_ERROR(gl.getError(), "glClearBufferiv() call failed");
1011 
1012     /* Blit the data.
1013      *
1014      * NOTE: Original test spec specified GL_LINEAR filter which would not have worked
1015      *       because the read buffer contains integer data.
1016      **/
1017     gl.blitFramebuffer(0,  /* srcX0 */
1018                        0,  /* srcY0 */
1019                        16, /* srcX1 */
1020                        16, /* srcY1 */
1021                        0,  /* dstX0 */
1022                        0,  /* dstY0 */
1023                        16, /* dstX1 */
1024                        16, /* dstY1 */
1025                        GL_COLOR_BUFFER_BIT, GL_NEAREST);
1026     GLU_EXPECT_NO_ERROR(gl.getError(), "glBlitFramebuffer() call failed.");
1027 
1028     /* Configure the read framebuffer for upcoming glReadPixels() call */
1029     gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst_to_id, 0); /* level */
1030     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure the read framebuffer");
1031 
1032     /* Allocate a buffer to hold the result data and then download the result texture's
1033      * contents */
1034     unsigned int *buffer = new unsigned int[16 /* width */ * 16 /* height */ * 4 /* components */];
1035 
1036     gl.readPixels(0,  /* x */
1037                   0,  /* y */
1038                   16, /* width */
1039                   16, /* height */
1040                   GL_RGBA_INTEGER, GL_UNSIGNED_INT, buffer);
1041     GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed");
1042 
1043     /* Verify the downloaded contents */
1044     int has_test_fail = 0;
1045     int pixel_size    = sizeof(unsigned int) * 4 /* components */;
1046     int row_width     = pixel_size * 16 /* width */;
1047 
1048     for (unsigned int y = 0; y < 16 /* height */; ++y)
1049     {
1050         /* NOTE: Vertical flipping should not be needed, but we cannot confirm this at the moment.
1051          *       Should it be the case, please change data_y to 15 - y */
1052         /* TODO: Remove NOTE above when verified on actual ES3.1 implementation */
1053         unsigned int data_y         = y;
1054         const unsigned int *row_ptr = (unsigned int *)((char *)buffer + data_y * row_width);
1055 
1056         for (unsigned int x = 0; x < 16 /* width */; ++x)
1057         {
1058             const unsigned int *data_ptr = (unsigned int *)((char *)row_ptr + x * pixel_size);
1059             const unsigned int r         = data_ptr[0];
1060             const unsigned int g         = data_ptr[1];
1061             const unsigned int b         = data_ptr[2];
1062             const unsigned int a         = data_ptr[3];
1063             bool is_r_valid              = (r == (data_y * 16 + x)) || (r == (data_y * 16 + x + 1));
1064             bool is_g_valid              = (g == 0);
1065             bool is_b_valid              = (b == 0);
1066             bool is_a_valid              = (a == 1);
1067 
1068             if (!is_r_valid || !is_g_valid || !is_b_valid || !is_a_valid)
1069             {
1070                 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid texture data at (" << x << ", " << y << "):"
1071                                    << " Expected (" << (data_y * 16 + x) << ", 0, 0, 1)"
1072                                    << " or (" << (data_y * 16 + x + 1) << ", 0, 0, 1)"
1073                                    << ", found (" << r << ", " << g << ", " << b << ", " << a << ")."
1074                                    << tcu::TestLog::EndMessage;
1075 
1076                 has_test_fail++;
1077             }
1078         } /* for (all x values) */
1079     }     /* for (all y values) */
1080 
1081     if (has_test_fail)
1082     {
1083         TCU_FAIL("Invalid texture data");
1084     }
1085 
1086     /* All done */
1087     if (buffer != NULL)
1088     {
1089         delete[] buffer;
1090         buffer = NULL;
1091     }
1092 
1093     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1094 
1095     return STOP;
1096 }
1097 
1098 /** Constructor.
1099  *
1100  *  @param context CTS context handle.
1101  **/
1102 MultisampleTextureFunctionalTestsBlittingToMultisampledFBOIsForbiddenTest::
MultisampleTextureFunctionalTestsBlittingToMultisampledFBOIsForbiddenTest(Context & context)1103     MultisampleTextureFunctionalTestsBlittingToMultisampledFBOIsForbiddenTest(Context &context)
1104     : TestCase(context, "blitting_to_multisampled_fbo_is_forbidden",
1105                "Verifies that blitting to a multisampled framebuffer "
1106                "object results in a GL_INVALID_OPERATION error.")
1107     , dst_to_id(0)
1108     , fbo_draw_id(0)
1109     , fbo_read_id(0)
1110     , src_to_id(0)
1111 {
1112     /* Left blank on purpose */
1113 }
1114 
1115 /** Deinitializes ES objects created during test execution */
deinit()1116 void MultisampleTextureFunctionalTestsBlittingToMultisampledFBOIsForbiddenTest::deinit()
1117 {
1118     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1119 
1120     if (fbo_draw_id != 0)
1121     {
1122         gl.deleteFramebuffers(1, &fbo_draw_id);
1123 
1124         fbo_draw_id = 0;
1125     }
1126 
1127     if (fbo_read_id != 0)
1128     {
1129         gl.deleteFramebuffers(1, &fbo_read_id);
1130 
1131         fbo_read_id = 0;
1132     }
1133 
1134     if (dst_to_id != 0)
1135     {
1136         gl.deleteTextures(1, &dst_to_id);
1137 
1138         dst_to_id = 0;
1139     }
1140 
1141     if (src_to_id != 0)
1142     {
1143         gl.deleteTextures(1, &src_to_id);
1144 
1145         src_to_id = 0;
1146     }
1147 
1148     /* Call base class' deinit() */
1149     TestCase::deinit();
1150 }
1151 
1152 /** Executes test iteration.
1153  *
1154  *  @return Returns STOP when test has finished executing.
1155  */
iterate()1156 tcu::TestNode::IterateResult MultisampleTextureFunctionalTestsBlittingToMultisampledFBOIsForbiddenTest::iterate()
1157 {
1158     const std::vector<std::string> &exts = m_context.getContextInfo().getExtensions();
1159     const bool has_NV_framebuffer_blit   = std::find(exts.begin(), exts.end(), "GL_NV_framebuffer_blit") != exts.end();
1160     const glw::Functions &gl             = m_context.getRenderContext().getFunctions();
1161 
1162     /* Set up texture objects */
1163     gl.genTextures(1, &dst_to_id);
1164     gl.genTextures(1, &src_to_id);
1165 
1166     gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, dst_to_id);
1167     gl.bindTexture(GL_TEXTURE_2D, src_to_id);
1168 
1169     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up texture objects");
1170 
1171     gl.texStorage2D(GL_TEXTURE_2D, 2, /* levels */
1172                     GL_RGB10_A2, 64,  /* width */
1173                     64);              /* height */
1174 
1175     GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed for GL_TEXTURE_2D texture target");
1176 
1177     gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, /* samples */
1178                                GL_RGB10_A2, 64,              /* width */
1179                                64,                           /* height */
1180                                GL_FALSE);                    /* fixedsamplelocations */
1181 
1182     GLU_EXPECT_NO_ERROR(gl.getError(),
1183                         "gl.texStorage2DMultisample() call failed for GL_TEXTURE_2D_MULTISAMPLE texture target");
1184 
1185     /* Set up framebuffer objects */
1186     gl.genFramebuffers(1, &fbo_draw_id);
1187     gl.genFramebuffers(1, &fbo_read_id);
1188     gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_draw_id);
1189     gl.bindFramebuffer(GL_READ_FRAMEBUFFER, fbo_read_id);
1190 
1191     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up framebuffer objects");
1192 
1193     /* Set up FBO attachments.
1194      *
1195      * NOTE: The draw/read FBO configuration in original test spec was the other
1196      *       way around which was wrong.
1197      */
1198     gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, src_to_id, 0); /* level */
1199 
1200     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up read framebuffer's attachments");
1201 
1202     gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1203                             dst_to_id, /* texture */
1204                             0);        /* layer */
1205 
1206     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up draw framebuffer's attachments");
1207 
1208     /* Try to perform blitting operations. */
1209     const glw::GLenum filters[]  = {GL_NEAREST, GL_LINEAR};
1210     const unsigned int n_filters = sizeof(filters) / sizeof(filters[0]);
1211 
1212     for (unsigned int n_filter = 0; n_filter < n_filters; ++n_filter)
1213     {
1214         glw::GLenum filter = filters[n_filter];
1215 
1216         // This blit would be supported by NV_framebuffer_blit if sizes match.
1217         // Alter the size of destination if extension is present to make it invalid.
1218         int dstY1 = has_NV_framebuffer_blit ? 63 : 64;
1219         gl.blitFramebuffer(0,     /* srcX0 */
1220                            0,     /* srcY0 */
1221                            64,    /* srcX1 */
1222                            64,    /* srcY1 */
1223                            0,     /* dstX0 */
1224                            0,     /* dstY0 */
1225                            64,    /* dstX1 */
1226                            dstY1, /* dstY1 */
1227                            GL_COLOR_BUFFER_BIT, filter);
1228 
1229         /* Verify GL_INVALID_OPERATION was returned */
1230         glw::GLenum error_code = gl.getError();
1231 
1232         if (error_code != GL_INVALID_OPERATION)
1233         {
1234             m_testCtx.getLog() << tcu::TestLog::Message << "Invalid glBlitFramebuffer() call for filter argument ["
1235                                << filter
1236                                << "]"
1237                                   "should have generated a GL_INVALID_OPERATION error. Instead, "
1238                                   "["
1239                                << error_code << "] error was reported." << tcu::TestLog::EndMessage;
1240 
1241             TCU_FAIL("GL_INVALID_OPERATION was not returned by invalid glBlitFramebuffer() call.");
1242         }
1243     } /* for (all valid filter argument values) */
1244 
1245     /* All done */
1246     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1247 
1248     return STOP;
1249 }
1250 
1251 /** Constructor.
1252  *
1253  *  @param context Rendering context handle.
1254  **/
1255 MultisampleTextureFunctionalTestsSampleMaskingForNonIntegerColorRenderableTexturesTest::
MultisampleTextureFunctionalTestsSampleMaskingForNonIntegerColorRenderableTexturesTest(Context & context)1256     MultisampleTextureFunctionalTestsSampleMaskingForNonIntegerColorRenderableTexturesTest(Context &context)
1257     : TestCase(context, "verify_sample_masking_for_non_integer_color_renderable_internalformats",
1258                "Verifies sample masking mechanism for non-integer color-renderable "
1259                "internalformats used for 2D multisample textures")
1260     , bo_id(0)
1261     , fbo_id(0)
1262     , fs_draw_id(0)
1263     , po_draw_id(0)
1264     , po_verify_id(0)
1265     , tfo_id(0)
1266     , to_2d_multisample_id(0)
1267     , vs_draw_id(0)
1268     , vs_verify_id(0)
1269 {
1270     /* Left blank on purpose */
1271 }
1272 
1273 /** Deinitializes ES objects created during test execution */
deinit()1274 void MultisampleTextureFunctionalTestsSampleMaskingForNonIntegerColorRenderableTexturesTest::deinit()
1275 {
1276     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1277 
1278     /* Unset used program */
1279     gl.useProgram(0);
1280 
1281     /* Unbind transform feedback object bound to GL_TRANSFORM_FEEDBACK target */
1282     gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
1283 
1284     /* Unbind buffer object bound to GL_TRANSFORM_FEEDBACK_BUFFER target */
1285     gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
1286 
1287     /* Unbind framebuffer object bound to GL_DRAW_FRAMEBUFFER target */
1288     gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
1289 
1290     /* Unbind texture object bound to GL_TEXTURE_2D_MULTISAMPLE texture target */
1291     gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
1292 
1293     /* Delete a 2D multisample texture object of id to_2d_multisample_id */
1294     if (to_2d_multisample_id != 0)
1295     {
1296         gl.deleteTextures(1, &to_2d_multisample_id);
1297 
1298         to_2d_multisample_id = 0;
1299     }
1300 
1301     /* Delete a buffer object of id bo_id */
1302     if (bo_id != 0)
1303     {
1304         gl.deleteBuffers(1, &bo_id);
1305 
1306         bo_id = 0;
1307     }
1308 
1309     /* Delete a framebuffer object of id fbo_id */
1310     if (fbo_id != 0)
1311     {
1312         gl.deleteFramebuffers(1, &fbo_id);
1313 
1314         fbo_id = 0;
1315     }
1316 
1317     /* Delete a transform feedback object of id tfo_id */
1318     if (tfo_id != 0)
1319     {
1320         gl.deleteTransformFeedbacks(1, &tfo_id);
1321 
1322         tfo_id = 0;
1323     }
1324 
1325     /* Delete fs_draw_id shader */
1326     if (fs_draw_id != 0)
1327     {
1328         gl.deleteShader(fs_draw_id);
1329 
1330         fs_draw_id = 0;
1331     }
1332 
1333     /* Delete vs_verify_id shader */
1334     if (vs_verify_id != 0)
1335     {
1336         gl.deleteShader(vs_verify_id);
1337 
1338         vs_verify_id = 0;
1339     }
1340 
1341     /* Delete vs_draw_id shader */
1342     if (vs_draw_id != 0)
1343     {
1344         gl.deleteShader(vs_draw_id);
1345 
1346         vs_draw_id = 0;
1347     }
1348 
1349     /* Delete program objects po_verify_id */
1350     if (po_verify_id != 0)
1351     {
1352         gl.deleteProgram(po_verify_id);
1353 
1354         po_verify_id = 0;
1355     }
1356 
1357     /* Delete program objects po_draw_id */
1358     if (po_draw_id != 0)
1359     {
1360         gl.deleteProgram(po_draw_id);
1361 
1362         po_draw_id = 0;
1363     }
1364 
1365     /* Call base class' deinit() */
1366     TestCase::deinit();
1367 }
1368 
1369 /** Initializes test-specific ES objects */
initInternals()1370 void MultisampleTextureFunctionalTestsSampleMaskingForNonIntegerColorRenderableTexturesTest::initInternals()
1371 {
1372     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1373 
1374     /* Generate a 2D multisample texture object of id to_2d_multisample_id */
1375     gl.genTextures(1, &to_2d_multisample_id);
1376 
1377     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed");
1378 
1379     if (to_2d_multisample_id == 0)
1380     {
1381         TCU_FAIL("Texture object has not been generated properly");
1382     }
1383 
1384     /* Generate a buffer object of id bo_id */
1385     gl.genBuffers(1, &bo_id);
1386 
1387     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed");
1388 
1389     if (bo_id == 0)
1390     {
1391         TCU_FAIL("Buffer object has not been generated properly");
1392     }
1393 
1394     /* Generate a framebuffer object of id fbo_id */
1395     gl.genFramebuffers(1, &fbo_id);
1396 
1397     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed");
1398 
1399     if (fbo_id == 0)
1400     {
1401         TCU_FAIL("Framebuffer object has not been generated properly");
1402     }
1403 
1404     /* Generate a transform feedback object of id tfo_id */
1405     gl.genTransformFeedbacks(1, &tfo_id);
1406 
1407     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks() call failed");
1408 
1409     if (tfo_id == 0)
1410     {
1411         TCU_FAIL("Transform feedback object has not been generated properly");
1412     }
1413 
1414     /* Create a vertex shader vs_draw_id */
1415     vs_draw_id = gl.createShader(GL_VERTEX_SHADER);
1416 
1417     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed for vs_draw_id");
1418 
1419     /* Create a vertex shader vs_verify_id */
1420     vs_verify_id = gl.createShader(GL_VERTEX_SHADER);
1421 
1422     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed for vs_verify_id");
1423 
1424     /* Create a fragment shader fs_draw_id */
1425     fs_draw_id = gl.createShader(GL_FRAGMENT_SHADER);
1426 
1427     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed for fs_draw_id");
1428 
1429     /* Create program objects po_draw_id */
1430     po_draw_id = gl.createProgram();
1431 
1432     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed for po_draw_id");
1433 
1434     /* Create program objects po_verify_id */
1435     po_verify_id = gl.createProgram();
1436 
1437     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed for po_verify_id");
1438 }
1439 
1440 /** Executes test iteration.
1441  *
1442  *  @return Always STOP.
1443  */
1444 tcu::TestNode::IterateResult MultisampleTextureFunctionalTestsSampleMaskingForNonIntegerColorRenderableTexturesTest::
iterate()1445     iterate()
1446 {
1447     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1448 
1449     initInternals();
1450 
1451     /* Constants */
1452     const glw::GLfloat epsilon        = 1e-5f;
1453     const glw::GLfloat expected_value = 1.0f;
1454     const glw::GLchar *fs_draw_body   = "#version 310 es\n"
1455                                         "\n"
1456                                         "precision highp float;\n"
1457                                         "\n"
1458                                         "out vec4 out_color;\n"
1459                                         "\n"
1460                                         "void main()\n"
1461                                         "{\n"
1462                                         "    out_color = vec4(1, 1, 1, 1);\n"
1463                                         "}\n";
1464 
1465     const glw::GLchar *vs_draw_body = "#version 310 es\n"
1466                                       "\n"
1467                                       "precision highp float;\n"
1468                                       "\n"
1469                                       "void main()\n"
1470                                       "{\n"
1471                                       "    switch (gl_VertexID)\n"
1472                                       "    {\n"
1473                                       "        case 0: gl_Position = vec4(-1,  1, 0, 1); break;\n"
1474                                       "        case 1: gl_Position = vec4( 1,  1, 0, 1); break;\n"
1475                                       "        case 2: gl_Position = vec4( 1, -1, 0, 1); break;\n"
1476                                       "        case 3: gl_Position = vec4(-1, -1, 0, 1); break;\n"
1477                                       "    }\n"
1478                                       "}\n";
1479 
1480     const glw::GLchar *vs_verify_body = "#version 310 es\n"
1481                                         "\n"
1482                                         "precision highp float;\n"
1483                                         "\n"
1484                                         "uniform uint              n_bit_on;\n"
1485                                         "uniform uint              n_bits;\n"
1486                                         "uniform highp sampler2DMS sampler;\n"
1487                                         "\n"
1488                                         "out float result;\n"
1489                                         "\n"
1490                                         "void main()\n"
1491                                         "{\n"
1492                                         "    vec4 one  = vec4(1);\n"
1493                                         "    vec4 zero = vec4(0.0, 0.0, 0.0, 1.0);\n"
1494                                         "\n"
1495                                         "    result = 1.0;\n"
1496                                         "\n"
1497                                         "    for (uint n_current_bit = 0u; n_current_bit < n_bits; n_current_bit++)\n"
1498                                         "    {\n"
1499                                         "        vec4 value = texelFetch(sampler, ivec2(0), int(n_current_bit));\n"
1500                                         "\n"
1501                                         "        if (n_bit_on == n_current_bit)\n"
1502                                         "        {\n"
1503                                         "            if (any(notEqual(value, one)))\n"
1504                                         "            {\n"
1505                                         "                result = 0.1 + float(n_current_bit)/1000.0;\n"
1506                                         "                break;\n"
1507                                         "            }\n"
1508                                         "        }\n"
1509                                         "        else\n"
1510                                         "        {\n"
1511                                         "            if (any(notEqual(value, zero)))\n"
1512                                         "            {\n"
1513                                         "                result = 0.2 + float(n_current_bit)/1000.0;\n"
1514                                         "                break;\n"
1515                                         "            }\n"
1516                                         "        }\n"
1517                                         "    }\n"
1518                                         "}\n";
1519 
1520     /* Configure the vertex shader vs_draw_id */
1521     compileShader(vs_draw_id, vs_draw_body);
1522 
1523     /* Configure the vertex shader vs_verify_id */
1524     compileShader(vs_verify_id, vs_verify_body);
1525 
1526     /* Configure the fragment shader fs_draw_id */
1527     compileShader(fs_draw_id, fs_draw_body);
1528 
1529     /* Attach the shaders vs_draw_id and fs_draw_id to program object po_draw_id */
1530     gl.attachShader(po_draw_id, vs_draw_id);
1531     gl.attachShader(po_draw_id, fs_draw_id);
1532 
1533     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure po_draw_id program object");
1534 
1535     /* Attach the shaders vs_verify_id and fs_draw_id to program object po_verify_id */
1536     gl.attachShader(po_verify_id, vs_verify_id);
1537     gl.attachShader(po_verify_id, fs_draw_id);
1538 
1539     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure po_verify_id program object");
1540 
1541     /* Configure vs_verify_id for transform feedback - our varying of choice is result and we're happy to use either of the TF modes since we'll be outputting a single float anyway. */
1542     const glw::GLchar *vs_verify_varying_name = "result";
1543 
1544     gl.transformFeedbackVaryings(po_verify_id, 1, &vs_verify_varying_name, GL_SEPARATE_ATTRIBS);
1545 
1546     /* Link the program objects po_draw_id */
1547     linkProgram(po_draw_id);
1548 
1549     /* Link the program objects po_verify_id */
1550     linkProgram(po_verify_id);
1551 
1552     /* Retrieve uniform locations */
1553     glw::GLuint n_bits_location   = gl.getUniformLocation(po_verify_id, "n_bits");
1554     glw::GLuint n_bit_on_location = gl.getUniformLocation(po_verify_id, "n_bit_on");
1555 
1556     /* Bind the to_2d_multisample_id texture object to GL_TEXTURE_2D_MULTISAMPLE texture target */
1557     gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id);
1558 
1559     /* Bind the fbo_id framebuffer object to GL_DRAW_FRAMEBUFFER target */
1560     gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_id);
1561 
1562     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a framebuffer object");
1563 
1564     /* Bind the bo_id buffer object to GL_TRANSFORM_FEEDBACK_BUFFER generic target */
1565     gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, bo_id);
1566 
1567     /* Bind the tfo_id transform feedback object go GL_TRANSFORM_FEEDBACK target */
1568     gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, tfo_id);
1569 
1570     /* Bind the bo_id buffer object to zeroth binding point of GL_TRANSFORM_FEEDBACK_BUFFER */
1571     gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, bo_id);
1572 
1573     /* Initialize buffer object's storage to hold a total of 4 bytes (sizeof(float) );*/
1574     gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(glw::GLfloat), NULL, GL_STATIC_DRAW);
1575 
1576     /* Attach the 2D multisample texture object to the framebuffer object's zeroth color attachment */
1577     gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id,
1578                             0); /* level */
1579 
1580     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up zeroth color attachment");
1581 
1582     /* Enable GL_SAMPLE_MASK mode */
1583     gl.enable(GL_SAMPLE_MASK);
1584 
1585     GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_SAMPLE_MASK) call generated an unexpected error");
1586 
1587     /* Color-renderable internalformats to test, note that GL_R8 will not work since sampling from
1588      * such format will never return {1,1,1,1} or {0,0,0,1} which current shader uses for sample validation */
1589     const glw::GLenum internalformat_list[] = {GL_RGBA8, GL_RGB565, GL_SRGB8_ALPHA8};
1590     const int internalformat_list_count     = sizeof(internalformat_list) / sizeof(internalformat_list[0]);
1591 
1592     /* Get GL_MAX_SAMPLES value */
1593     glw::GLint gl_max_samples_value = 0;
1594 
1595     gl.getIntegerv(GL_MAX_SAMPLES, &gl_max_samples_value);
1596 
1597     GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to retrieve GL_MAX_SAMPLES value");
1598 
1599     if (gl_max_samples_value > 32)
1600     {
1601         m_testCtx.getLog() << tcu::TestLog::Message << "The test case checks only first 32 samples out of "
1602                            << gl_max_samples_value << " reported by GL_MAX_SAMPLES." << tcu::TestLog::EndMessage;
1603     }
1604 
1605     /* Work with no more than 32 bits of mask's first word */
1606     const glw::GLint mask_bits_to_check = de::min(gl_max_samples_value, 32);
1607 
1608     /* Keep the results but continue running all cases */
1609     bool test_fail = false;
1610 
1611     /* Iterate through all internal formats test case should check */
1612     for (int internalformat_index = 0; internalformat_index < internalformat_list_count; internalformat_index++)
1613     {
1614         /* Configure the texture object storage */
1615         gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, mask_bits_to_check, /* samples */
1616                                    internalformat_list[internalformat_index], 1,  /* width */
1617                                    1,                                             /* height */
1618                                    GL_TRUE);                                      /* fixedsamplelocations */
1619 
1620         /* Make sure no errors were reported. The framebuffer should be considered complete at this moment. */
1621         GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample() call failed");
1622 
1623         /* Following code does not affect test method. Just checks if FBO is complete
1624          To catch errors earlier */
1625 
1626         glw::GLenum fbo_completeness_status = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER);
1627 
1628         if (fbo_completeness_status != GL_FRAMEBUFFER_COMPLETE)
1629         {
1630             m_testCtx.getLog() << tcu::TestLog::Message
1631                                << "Draw FBO completeness status is: " << fbo_completeness_status
1632                                << ", expected: GL_FRAMEBUFFER_COMPLETE" << tcu::TestLog::EndMessage;
1633 
1634             TCU_FAIL("Draw FBO is considered incomplete which is invalid");
1635         }
1636 
1637         /* For all values of n_bit from range <0, GL_MAX_SAMPLES pname value) */
1638         for (int n_bit = 0; n_bit < mask_bits_to_check; n_bit++)
1639         {
1640 
1641             /* We need to clear render buffer, otherwise masked samples will have undefined values */
1642             glw::GLfloat clear_color_src[] = {0.0f, 0.0f, 0.0f, 1.0f};
1643 
1644             gl.clearBufferfv(GL_COLOR, 0, clear_color_src);
1645             GLU_EXPECT_NO_ERROR(gl.getError(), "clearBufferfv() call failed");
1646 
1647             /* Use program object po_draw_id */
1648             gl.useProgram(po_draw_id);
1649 
1650             /* Configure sample mask to only render n_bit-th sample using glSampleMaski() function */
1651             gl.sampleMaski(0, 1 << n_bit);
1652 
1653             /* Draw a triangle fan of 4 vertices. This fills to_2d_id with multisampled data.
1654              * However, due to active GL_SAMPLE_MASK and the way we configured it, only one sample should have been rendered.
1655              * The only way we can check if this is the case is by using a special shader,
1656              * because we have no way of downloading multisampled data to process space in ES3.0+.
1657              */
1658             gl.drawArrays(GL_TRIANGLE_FAN, 0, /* first */
1659                           4 /* count */);
1660 
1661             /* Unbind fbo_id before sourcing from the texture attached to it */
1662             gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
1663 
1664             /* Enable GL_RASTERIZER_DISCARD mode */
1665             gl.enable(GL_RASTERIZER_DISCARD);
1666             {
1667                 /* Use program object po_verify_id */
1668                 gl.useProgram(po_verify_id);
1669 
1670                 /* Specify input arguments for vertex shader */
1671                 gl.uniform1ui(n_bits_location, mask_bits_to_check);
1672                 gl.uniform1ui(n_bit_on_location, n_bit);
1673 
1674                 /* Bind to_2d_multisample_id to GL_TEXTURE_2D_MULTISAMPLE texture target. Current texture unit is GL_TEXTURE0 */
1675                 gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id);
1676 
1677                 /* Begin transform feedback (primitiveMode: GL_POINTS) */
1678                 gl.beginTransformFeedback(GL_POINTS);
1679                 {
1680                     /* Draw a single point. This will fill our transform feedback buffer with result */
1681                     gl.drawArrays(GL_POINTS, 0, 1);
1682                 }
1683                 /* End transform feedback */
1684                 gl.endTransformFeedback();
1685             }
1686             /* Disable GL_RASTERIZER_DISCARD mode */
1687             gl.disable(GL_RASTERIZER_DISCARD);
1688 
1689             /* Make sure no errors were generated */
1690             GLU_EXPECT_NO_ERROR(gl.getError(), "Transform feedback failed");
1691 
1692             /* Rebind the fbo_id framebuffer object to GL_DRAW_FRAMEBUFFER target */
1693             gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_id);
1694 
1695             /* Map buffer object bo_id's contents to user-space */
1696             const glw::GLfloat *mapped_bo =
1697                 (glw::GLfloat *)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 4, GL_MAP_READ_BIT);
1698 
1699             GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed");
1700 
1701             /* Copy result from buffer */
1702             glw::GLfloat result = *mapped_bo;
1703 
1704             /* Unmap the buffer object */
1705             gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
1706 
1707             GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed");
1708 
1709             /* Verify the value stored by verification program is not 0. If it is 0, the test has failed. */
1710             if (de::abs(result - expected_value) > epsilon)
1711             {
1712                 m_testCtx.getLog() << tcu::TestLog::Message << "Unexpected value stored by verification program: ["
1713                                    << result << "],"
1714                                    << "Format index: " << internalformat_index << ", "
1715                                    << "Bit to check: [" << n_bit << "." << tcu::TestLog::EndMessage;
1716                 /* Notice test failure */
1717                 test_fail = true;
1718             }
1719         }
1720 
1721         /* Delete the 2D multisample texture object with glDeleteTextures() call and re-bind the object to a GL_TEXTURE_2D_MULTISAMPLE texture target with a glBindTexture() call */
1722         gl.deleteTextures(1, &to_2d_multisample_id);
1723 
1724         to_2d_multisample_id = 0;
1725 
1726         /* Recreate to_2d_multisample_id texture object. */
1727         /* Generate a 2D multisample texture object of id to_2d_multisample_id */
1728         gl.genTextures(1, &to_2d_multisample_id);
1729 
1730         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed");
1731 
1732         if (to_2d_multisample_id == 0)
1733         {
1734             TCU_FAIL("Texture object has not been generated properly");
1735         }
1736 
1737         /* Bind the to_2d_id texture object to GL_TEXTURE_2D_MULTISAMPLE texture target */
1738         gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id);
1739 
1740         /* Attach the 2D multisample texture object to the framebuffer object's zeroth color attachment */
1741         gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1742                                 to_2d_multisample_id, 0); /* level */
1743 
1744         GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up zeroth color attachment");
1745     }
1746 
1747     if (test_fail)
1748     {
1749         TCU_FAIL("Value stored by verification program is not 1.0. Test has failed.");
1750     }
1751 
1752     /* Test case passed */
1753     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1754 
1755     return STOP;
1756 }
1757 
1758 /** Links a program object. Shaders should be attached to program id before call.
1759  *  If an error reported throws an exception.
1760  *
1761  *  @param id Program id
1762  */
linkProgram(glw::GLuint id)1763 void MultisampleTextureFunctionalTestsSampleMaskingForNonIntegerColorRenderableTexturesTest::linkProgram(glw::GLuint id)
1764 {
1765     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1766 
1767     /* Link the test program object */
1768     glw::GLint link_status = GL_FALSE;
1769 
1770     gl.linkProgram(id);
1771     GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed");
1772 
1773     gl.getProgramiv(id, GL_LINK_STATUS, &link_status);
1774 
1775     if (link_status != GL_TRUE)
1776     {
1777         TCU_FAIL("Program linking failed");
1778     }
1779 }
1780 
1781 /** Compiles the shader. Should the shader not compile, a TestError exception will be thrown.
1782  *
1783  *  @param id     Generated shader id
1784  *  @param source NULL-terminated shader source code string
1785  */
compileShader(glw::GLuint id,const glw::GLchar * source)1786 void MultisampleTextureFunctionalTestsSampleMaskingForNonIntegerColorRenderableTexturesTest::compileShader(
1787     glw::GLuint id, const glw::GLchar *source)
1788 {
1789     glw::GLint compile_status = GL_FALSE;
1790     const glw::Functions &gl  = m_context.getRenderContext().getFunctions();
1791 
1792     gl.shaderSource(id, 1, &source, NULL);
1793     GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed");
1794 
1795     gl.compileShader(id);
1796     GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed");
1797 
1798     gl.getShaderiv(id, GL_COMPILE_STATUS, &compile_status);
1799 
1800     if (compile_status != GL_TRUE)
1801     {
1802         /* Retrieve adn dump compliation fail reason */
1803         char infoLog[1024];
1804         glw::GLsizei length = 0;
1805 
1806         gl.getShaderInfoLog(id, 1024, &length, infoLog);
1807 
1808         m_testCtx.getLog() << tcu::TestLog::Message << "Shader compilation failed, shader id=" << id
1809                            << ", infoLog: " << infoLog << tcu::TestLog::EndMessage;
1810 
1811         TCU_FAIL("Shader compilation failed");
1812     }
1813 }
1814 
1815 /** Constructor.
1816  *
1817  *  @param context Rendering context handle.
1818  **/
MultisampleTextureFunctionalTestsSampleMaskingTexturesTest(Context & context)1819 MultisampleTextureFunctionalTestsSampleMaskingTexturesTest::MultisampleTextureFunctionalTestsSampleMaskingTexturesTest(
1820     Context &context)
1821     : TestCase(context, "verify_sample_masking_textures",
1822                "Verifies sample masking mechanism for non-integer, integer/unsigned, "
1823                "integer/signed color-renderable internalformats and "
1824                "depth-renderable internalformats. All internalformats "
1825                "are used for 2D multisample textures.")
1826     , bo_id(0)
1827     , fbo_id(0)
1828     , fs_draw_id(0)
1829     , po_draw_id(0)
1830     , po_verify_id(0)
1831     , tfo_id(0)
1832     , to_2d_multisample_id(0)
1833     , vs_draw_id(0)
1834     , vs_verify_id(0)
1835 {
1836     /* Left blank on purpose */
1837 }
1838 
1839 /** Deinitializes ES objects created during test execution */
deinit()1840 void MultisampleTextureFunctionalTestsSampleMaskingTexturesTest::deinit()
1841 {
1842     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1843 
1844     /* Unset used program */
1845     gl.useProgram(0);
1846 
1847     /* Unbind transform feedback object bound to GL_TRANSFORM_FEEDBACK target */
1848     gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
1849 
1850     /* Unbind buffer object bound to GL_TRANSFORM_FEEDBACK_BUFFER target */
1851     gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
1852 
1853     /* Unbind framebuffer object bound to GL_DRAW_FRAMEBUFFER target */
1854     gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
1855 
1856     /* Unbind texture object bound to GL_TEXTURE_2D_MULTISAMPLE texture target */
1857     gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
1858 
1859     /* Delete a 2D multisample texture object of id to_2d_multisample_id */
1860     if (to_2d_multisample_id != 0)
1861     {
1862         gl.deleteTextures(1, &to_2d_multisample_id);
1863 
1864         to_2d_multisample_id = 0;
1865     }
1866 
1867     /* Delete a buffer object of id bo_id */
1868     if (bo_id != 0)
1869     {
1870         gl.deleteBuffers(1, &bo_id);
1871 
1872         bo_id = 0;
1873     }
1874 
1875     /* Delete a framebuffer object of id fbo_id */
1876     if (fbo_id != 0)
1877     {
1878         gl.deleteFramebuffers(1, &fbo_id);
1879 
1880         fbo_id = 0;
1881     }
1882 
1883     /* Delete a transform feedback object of id tfo_id */
1884     if (tfo_id != 0)
1885     {
1886         gl.deleteTransformFeedbacks(1, &tfo_id);
1887 
1888         tfo_id = 0;
1889     }
1890 
1891     /* Delete fs_draw_id shader */
1892     if (fs_draw_id != 0)
1893     {
1894         gl.deleteShader(fs_draw_id);
1895 
1896         fs_draw_id = 0;
1897     }
1898 
1899     /* Delete vs_verify_id shader */
1900     if (vs_verify_id != 0)
1901     {
1902         gl.deleteShader(vs_verify_id);
1903 
1904         vs_verify_id = 0;
1905     }
1906 
1907     /* Delete vs_draw_id shader */
1908     if (vs_draw_id != 0)
1909     {
1910         gl.deleteShader(vs_draw_id);
1911 
1912         vs_draw_id = 0;
1913     }
1914 
1915     /* Delete program objects po_verify_id */
1916     if (po_verify_id != 0)
1917     {
1918         gl.deleteProgram(po_verify_id);
1919 
1920         po_verify_id = 0;
1921     }
1922 
1923     /* Delete program objects po_draw_id */
1924     if (po_draw_id != 0)
1925     {
1926         gl.deleteProgram(po_draw_id);
1927 
1928         po_draw_id = 0;
1929     }
1930 
1931     /* Call base class' deinit() */
1932     TestCase::deinit();
1933 }
1934 
1935 /** Initializes test-specific ES objects */
initInternals()1936 void MultisampleTextureFunctionalTestsSampleMaskingTexturesTest::initInternals()
1937 {
1938     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1939 
1940     /* Generate a 2D multisample texture object of id to_2d_multisample_id */
1941     gl.genTextures(1, &to_2d_multisample_id);
1942 
1943     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed");
1944 
1945     if (to_2d_multisample_id == 0)
1946     {
1947         TCU_FAIL("Texture object has not been generated properly");
1948     }
1949 
1950     /* Generate a buffer object of id bo_id */
1951     gl.genBuffers(1, &bo_id);
1952 
1953     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed");
1954 
1955     if (bo_id == 0)
1956     {
1957         TCU_FAIL("Buffer object has not been generated properly");
1958     }
1959 
1960     /* Generate a framebuffer object of id fbo_id */
1961     gl.genFramebuffers(1, &fbo_id);
1962 
1963     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed");
1964 
1965     if (fbo_id == 0)
1966     {
1967         TCU_FAIL("Framebuffer object has not been generated properly");
1968     }
1969 
1970     /* Generate a transform feedback object of id tfo_id */
1971     gl.genTransformFeedbacks(1, &tfo_id);
1972 
1973     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks() call failed");
1974 
1975     if (tfo_id == 0)
1976     {
1977         TCU_FAIL("Transform feedback object has not been generated properly");
1978     }
1979 
1980     /* Create a vertex shader vs_draw_id */
1981     vs_draw_id = gl.createShader(GL_VERTEX_SHADER);
1982 
1983     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed for vs_draw_id");
1984 
1985     /* Create a vertex shader vs_verify_id */
1986     vs_verify_id = gl.createShader(GL_VERTEX_SHADER);
1987 
1988     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed for vs_verify_id");
1989 
1990     /* Create a fragment shader fs_draw_id */
1991     fs_draw_id = gl.createShader(GL_FRAGMENT_SHADER);
1992 
1993     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed for fs_draw_id");
1994 
1995     /* Create program objects po_draw_id */
1996     po_draw_id = gl.createProgram();
1997 
1998     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed for po_draw_id");
1999 
2000     /* Create program objects po_verify_id */
2001     po_verify_id = gl.createProgram();
2002 
2003     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed for po_verify_id");
2004 }
2005 
2006 /** Executes test iteration.
2007  *
2008  *  @return Always STOP.
2009  */
iterate()2010 tcu::TestNode::IterateResult MultisampleTextureFunctionalTestsSampleMaskingTexturesTest::iterate()
2011 {
2012     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2013 
2014     initInternals();
2015 
2016     /* Constants */
2017     const glw::GLfloat epsilon      = 1e-5f;
2018     const glw::GLchar *fs_draw_body = "#version 310 es\n"
2019                                       "\n"
2020                                       "out vec4 out_color;\n"
2021                                       "\n"
2022                                       "void main()\n"
2023                                       "{\n"
2024                                       "    out_color = vec4(1, 1, 1, 1);\n"
2025                                       "}\n";
2026 
2027     const glw::GLchar *vs_draw_body = "#version 310 es\n"
2028                                       "\n"
2029                                       "void main()\n"
2030                                       "{\n"
2031                                       "    switch (gl_VertexID)\n"
2032                                       "    {\n"
2033                                       "        case 0: gl_Position = vec4(-1,  1, 0, 1); break;\n"
2034                                       "        case 1: gl_Position = vec4( 1,  1, 0, 1); break;\n"
2035                                       "        case 2: gl_Position = vec4( 1, -1, 0, 1); break;\n"
2036                                       "        case 3: gl_Position = vec4(-1, -1, 0, 1); break;\n"
2037                                       "    }\n"
2038                                       "}\n";
2039 
2040     const glw::GLchar *vs_verify_body = "#version 310 es\n"
2041                                         "\n"
2042                                         "precision highp float;\n"
2043                                         "\n"
2044                                         "uniform uint              n_bit_on;\n"
2045                                         "uniform uint              n_bits;\n"
2046                                         "uniform highp sampler2DMS sampler;\n"
2047                                         "\n"
2048                                         "out float result;\n"
2049                                         "\n"
2050                                         "void main()\n"
2051                                         "{\n"
2052                                         "    vec4 one  = vec4(1);\n"
2053                                         "    vec4 zero = vec4(0);\n"
2054                                         "\n"
2055                                         "    result = 1.0;\n"
2056                                         "\n"
2057                                         "    for (uint n_current_bit = 0u; n_current_bit < n_bits; n_current_bit++)\n"
2058                                         "    {\n"
2059                                         "        vec4 value = texelFetch(sampler, ivec2(0), int(n_current_bit));\n"
2060                                         "\n"
2061                                         "        if (n_bit_on == n_current_bit)\n"
2062                                         "        {\n"
2063                                         "            if (any(notEqual(value, one)))\n"
2064                                         "            {\n"
2065                                         "                result = 0.0;\n"
2066                                         "            }\n"
2067                                         "        }\n"
2068                                         "        else\n"
2069                                         "        {\n"
2070                                         "            if (any(notEqual(value, zero)))\n"
2071                                         "            {\n"
2072                                         "                result = 0.0;\n"
2073                                         "            }\n"
2074                                         "        }\n"
2075                                         "    }\n"
2076                                         "}\n";
2077 
2078     /* Configure the vertex shader vs_draw_id */
2079     compileShader(vs_draw_id, vs_draw_body);
2080 
2081     /* Configure the vertex shader vs_verify_id */
2082     compileShader(vs_verify_id, vs_verify_body);
2083 
2084     /* Configure the fragment shader fs_draw_id */
2085     compileShader(fs_draw_id, fs_draw_body);
2086 
2087     /* Attach the shaders vs_draw_id and fs_draw_id to program object po_draw_id */
2088     gl.attachShader(po_draw_id, vs_draw_id);
2089     gl.attachShader(po_draw_id, fs_draw_id);
2090 
2091     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure po_draw_id program object");
2092 
2093     /* Attach the shaders vs_verify_id and fs_draw_id to program object po_verify_id */
2094     gl.attachShader(po_verify_id, vs_verify_id);
2095     gl.attachShader(po_verify_id, fs_draw_id);
2096 
2097     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure po_verify_id program object");
2098 
2099     /* Configure vs_verify_id for transform feedback - our varying of choice is result and we're happy to use either of the TF modes since we'll be outputting a single float anyway. */
2100     const glw::GLchar *vs_verify_varying_name = "result";
2101 
2102     gl.transformFeedbackVaryings(po_verify_id, 1, &vs_verify_varying_name, GL_SEPARATE_ATTRIBS);
2103 
2104     /* Link the program objects po_draw_id */
2105     linkProgram(po_draw_id);
2106 
2107     /* Link the program objects po_verify_id */
2108     linkProgram(po_verify_id);
2109 
2110     /* Retrieve uniform locations */
2111     glw::GLuint n_bits_location   = gl.getUniformLocation(po_verify_id, "n_bits");
2112     glw::GLuint n_bit_on_location = gl.getUniformLocation(po_verify_id, "n_bit_on");
2113 
2114     /* Bind the to_2d_multisample_id texture object to GL_TEXTURE_2D_MULTISAMPLE texture target */
2115     gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id);
2116 
2117     /* Bind the fbo_id framebuffer object to GL_DRAW_FRAMEBUFFER target */
2118     gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_id);
2119 
2120     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a framebuffer object");
2121 
2122     /* Bind the bo_id buffer object to GL_TRANSFORM_FEEDBACK_BUFFER generic target */
2123     gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, bo_id);
2124 
2125     /* Bind the bo_id buffer object to zeroth binding point of GL_TRANSFORM_FEEDBACK_BUFFER */
2126     gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, bo_id);
2127 
2128     /* Bind the tfo_id transform feedback object go GL_TRANSFORM_FEEDBACK target */
2129     gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, tfo_id);
2130 
2131     /* Initialize buffer object's storage to hold a total of 4 bytes (sizeof(float) );*/
2132     gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(glw::GLfloat), NULL, GL_STATIC_DRAW);
2133 
2134     /* Attach the 2D multisample texture object to the framebuffer object's zeroth color attachment */
2135     gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id,
2136                             0); /* level */
2137 
2138     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up zeroth color attachment");
2139 
2140     /* Enable GL_SAMPLE_MASK mode */
2141     gl.enable(GL_SAMPLE_MASK);
2142 
2143     GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_SAMPLE_MASK) call generated an unexpected error");
2144 
2145     /* Iterate through color-normalized-, color-unsigned-integer-, color-signed-integer- and depth-renderable internalformats */
2146     const glw::GLenum normalized_color_internalformats[] = {GL_R8, GL_RGB565, GL_SRGB8_ALPHA8};
2147     const glw::GLenum unsigned_color_internalformats[]   = {GL_RGBA32UI, GL_RG16UI};
2148     const glw::GLenum signed_color_internalformats[]     = {GL_RGBA32I, GL_RG16I};
2149     const glw::GLenum depth_internalformats[]            = {GL_DEPTH_COMPONENT32F};
2150     const unsigned int n_normalized_color_internalformats =
2151         sizeof(normalized_color_internalformats) / sizeof(normalized_color_internalformats[0]);
2152     const unsigned int n_unsigned_color_internalformats =
2153         sizeof(unsigned_color_internalformats) / sizeof(unsigned_color_internalformats[0]);
2154     const unsigned int n_signed_color_internalformats =
2155         sizeof(signed_color_internalformats) / sizeof(signed_color_internalformats[0]);
2156     const unsigned int n_depth_internalformats = sizeof(depth_internalformats) / sizeof(depth_internalformats[0]);
2157 
2158     for (unsigned int n_iteration = 0; n_iteration < 4 /* normalized/unsigned/signed/depth */; ++n_iteration)
2159     {
2160         glw::GLenum attachment             = 0;
2161         const glw::GLenum *internalformats = NULL;
2162         unsigned int n_internalformats     = 0;
2163 
2164         switch (n_iteration)
2165         {
2166         case 0:
2167         {
2168             attachment        = GL_COLOR_ATTACHMENT0;
2169             internalformats   = normalized_color_internalformats;
2170             n_internalformats = n_normalized_color_internalformats;
2171 
2172             break;
2173         }
2174 
2175         case 1:
2176         {
2177             attachment        = GL_COLOR_ATTACHMENT0;
2178             internalformats   = unsigned_color_internalformats;
2179             n_internalformats = n_unsigned_color_internalformats;
2180 
2181             break;
2182         }
2183 
2184         case 2:
2185         {
2186             attachment        = GL_COLOR_ATTACHMENT0;
2187             internalformats   = signed_color_internalformats;
2188             n_internalformats = n_signed_color_internalformats;
2189 
2190             break;
2191         }
2192 
2193         case 3:
2194         {
2195             attachment        = GL_DEPTH_ATTACHMENT;
2196             internalformats   = depth_internalformats;
2197             n_internalformats = n_depth_internalformats;
2198 
2199             break;
2200         }
2201 
2202         default:
2203         {
2204             TCU_FAIL("Unrecognized iteration index");
2205         }
2206         } /* switch (n_iteration) */
2207 
2208         /* Iterate through internalformats */
2209         for (unsigned int n_internalformat = 0; n_internalformat < n_internalformats; ++n_internalformat)
2210         {
2211             glw::GLenum internalformat            = internalformats[n_internalformat];
2212             glw::GLint internalformat_max_samples = 0;
2213 
2214             /* Retrieve internalformat-specific GL_MAX_SAMPLES value */
2215             gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE,     /* target */
2216                                    internalformat, GL_SAMPLES, 1, /* bufSize */
2217                                    &internalformat_max_samples);
2218 
2219             GLU_EXPECT_NO_ERROR(gl.getError(), "glGetInternalformativ() failed");
2220 
2221             if (internalformat_max_samples > 32)
2222             {
2223                 m_testCtx.getLog() << tcu::TestLog::Message << "The test case checks only first 32 samples out of "
2224                                    << internalformat_max_samples
2225                                    << " reported by GL_SAMPLES reported by getInternalformativ() "
2226                                    << "for internalformat " << internalformat << "." << tcu::TestLog::EndMessage;
2227             }
2228 
2229             /* Work with no more than 32 bits of mask's first word */
2230             const glw::GLint mask_bits_to_check = de::min(internalformat_max_samples, 32);
2231 
2232             /* Recreate to_2d_multisample_id texture object. */
2233             if (to_2d_multisample_id == 0)
2234             {
2235                 /* Generate a 2D multisample texture object of id to_2d_multisample_id */
2236                 gl.genTextures(1, &to_2d_multisample_id);
2237 
2238                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed");
2239 
2240                 if (to_2d_multisample_id == 0)
2241                 {
2242                     TCU_FAIL("Texture object has not been generated properly");
2243                 }
2244 
2245                 /* Bind the to_2d_id texture object to GL_TEXTURE_2D_MULTISAMPLE texture target */
2246                 gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id);
2247 
2248                 /* Attach the 2D multisample texture object to the framebuffer object's attachment */
2249                 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, GL_TEXTURE_2D_MULTISAMPLE,
2250                                         to_2d_multisample_id, 0); /* level */
2251 
2252                 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up attachment");
2253             }
2254 
2255             /* Configure the texture object storage */
2256             gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, internalformat_max_samples, /* samples */
2257                                        internalformat, 1,                                     /* width */
2258                                        1,                                                     /* height */
2259                                        GL_TRUE);                                              /* fixedsamplelocations */
2260 
2261             /* Make sure no errors were reported. The framebuffer should be considered complete at this moment. */
2262             GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample() call failed");
2263 
2264             /* For all values of n_bit from range <0, GL_MAX_SAMPLES pname value) */
2265             for (int n_bit = 0; n_bit < mask_bits_to_check; n_bit++)
2266             {
2267                 /* Use program object po_draw_id */
2268                 gl.useProgram(po_draw_id);
2269 
2270                 /* Configure sample mask to only render n_bit-th sample using glSampleMaski() function */
2271                 gl.sampleMaski(0, 1 << n_bit);
2272 
2273                 /* Draw a triangle fan of 4 vertices. This fills to_2d_id with multisampled data.
2274                  * However, due to active GL_SAMPLE_MASK and the way we configured it, only one sample should have been rendered.
2275                  * The only way we can check if this is the case is by using a special shader,
2276                  * because we have no way of downloading multisampled data to process space in ES3.0+.
2277                  */
2278                 gl.drawArrays(GL_TRIANGLE_FAN, 0, /* first */
2279                               4 /* count */);
2280 
2281                 /* Enable GL_RASTERIZER_DISCARD mode */
2282                 gl.enable(GL_RASTERIZER_DISCARD);
2283                 {
2284                     /* Use program object po_verify_id */
2285                     gl.useProgram(po_verify_id);
2286 
2287                     /* Specify input arguments for vertex shader */
2288                     gl.uniform1i(n_bits_location, mask_bits_to_check);
2289                     gl.uniform1i(n_bit_on_location, n_bit);
2290 
2291                     /* Bind to_2d_multisample_id to GL_TEXTURE_2D_MULTISAMPLE texture target. Current texture unit is GL_TEXTURE0 */
2292                     gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id);
2293 
2294                     /* Begin transform feedback (primitiveMode: GL_POINTS) */
2295                     gl.beginTransformFeedback(GL_POINTS);
2296                     {
2297                         /* Draw a single point. This will fill our transform feedback buffer with result */
2298                         gl.drawArrays(GL_POINTS, 0, 1);
2299                     }
2300                     /* End transform feedback */
2301                     gl.endTransformFeedback();
2302                 }
2303                 /* Disable GL_RASTERIZER_DISCARD mode */
2304                 gl.disable(GL_RASTERIZER_DISCARD);
2305 
2306                 /* Make sure no errors were generated */
2307                 GLU_EXPECT_NO_ERROR(gl.getError(), "Transform feedback failed");
2308 
2309                 /* Map buffer object bo_id's contents to user-space */
2310                 const glw::GLfloat *mapped_bo =
2311                     (glw::GLfloat *)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
2312 
2313                 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed");
2314 
2315                 /* Copy result from buffer */
2316                 glw::GLfloat result = *mapped_bo;
2317 
2318                 /* Unmap the buffer object */
2319                 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
2320 
2321                 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed");
2322 
2323                 /* Verify the value stored by verification program is not 0. If it is 0, the test has failed. */
2324                 if (de::abs(result) < epsilon)
2325                 {
2326                     TCU_FAIL("Value stored by verification program is zero. Test has failed.");
2327                 }
2328             }
2329 
2330             /* Delete the 2D multisample texture object with glDeleteTextures() call and re-bind the object to a GL_TEXTURE_2D_MULTISAMPLE texture target with a glBindTexture() call */
2331             gl.deleteTextures(1, &to_2d_multisample_id);
2332 
2333             to_2d_multisample_id = 0;
2334         } /* for (all renderable internalformats) */
2335     }     /* for (all iterations) */
2336 
2337     /* Test case passed */
2338     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2339 
2340     return STOP;
2341 }
2342 
2343 /** Links a program object. Shaders should be attached to program id before call.
2344  *  If an error reported throws an exception.
2345  *
2346  *  @param id Program id
2347  */
linkProgram(glw::GLuint id)2348 void MultisampleTextureFunctionalTestsSampleMaskingTexturesTest::linkProgram(glw::GLuint id)
2349 {
2350     /* Link the test program object */
2351     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2352     glw::GLint link_status   = GL_FALSE;
2353 
2354     gl.linkProgram(id);
2355     GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed");
2356 
2357     gl.getProgramiv(id, GL_LINK_STATUS, &link_status);
2358 
2359     if (link_status != GL_TRUE)
2360     {
2361         TCU_FAIL("Program linking failed");
2362     }
2363 }
2364 
2365 /** Compiles the shader. Should the shader not compile, a TestError exception will be thrown.
2366  *
2367  *  @param id     Generated shader id
2368  *  @param source NULL-terminated shader source code string
2369  */
compileShader(glw::GLuint id,const glw::GLchar * source)2370 void MultisampleTextureFunctionalTestsSampleMaskingTexturesTest::compileShader(glw::GLuint id,
2371                                                                                const glw::GLchar *source)
2372 {
2373     glw::GLint compile_status = GL_FALSE;
2374     const glw::Functions &gl  = m_context.getRenderContext().getFunctions();
2375 
2376     gl.shaderSource(id, 1, &source, NULL);
2377     GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed");
2378 
2379     gl.compileShader(id);
2380     GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed");
2381 
2382     gl.getShaderiv(id, GL_COMPILE_STATUS, &compile_status);
2383 
2384     if (compile_status != GL_TRUE)
2385     {
2386         TCU_FAIL("Shader compilation failed");
2387     }
2388 }
2389 
2390 /** Constructor.
2391  *
2392  *  @param context CTS context handle.
2393  **/
2394 MultisampleTextureFunctionalTestsTextureSizeFragmentShadersTest::
MultisampleTextureFunctionalTestsTextureSizeFragmentShadersTest(Context & context)2395     MultisampleTextureFunctionalTestsTextureSizeFragmentShadersTest(Context &context)
2396     : TestCase(context, "texture_size_in_fragment_shaders",
2397                "Verifies textureSize() works for multisample textures when used in fragment shaders")
2398     , fbo_id(0)
2399     , fs_id(0)
2400     , po_id(0)
2401     , to_2d_multisample_id(0)
2402     , to_2d_multisample_array_id(0)
2403     , vs_id(0)
2404 {
2405     /* Left blank on purpose */
2406 }
2407 
2408 /** Deinitializes ES objects created during test execution */
deinit()2409 void MultisampleTextureFunctionalTestsTextureSizeFragmentShadersTest::deinit()
2410 {
2411     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2412 
2413     if (fbo_id != 0)
2414     {
2415         gl.deleteFramebuffers(1, &fbo_id);
2416 
2417         fbo_id = 0;
2418     }
2419 
2420     if (fs_id != 0)
2421     {
2422         gl.deleteShader(fs_id);
2423 
2424         fs_id = 0;
2425     }
2426 
2427     if (po_id != 0)
2428     {
2429         gl.deleteProgram(po_id);
2430 
2431         po_id = 0;
2432     }
2433 
2434     if (to_2d_multisample_id != 0)
2435     {
2436         gl.deleteTextures(1, &to_2d_multisample_id);
2437 
2438         to_2d_multisample_id = 0;
2439     }
2440 
2441     if (to_2d_multisample_array_id != 0)
2442     {
2443         gl.deleteTextures(1, &to_2d_multisample_array_id);
2444 
2445         to_2d_multisample_array_id = 0;
2446     }
2447 
2448     if (vs_id != 0)
2449     {
2450         gl.deleteShader(vs_id);
2451 
2452         vs_id = 0;
2453     }
2454 
2455     /* Call base class' deinit() */
2456     TestCase::deinit();
2457 }
2458 
2459 /** Executes test iteration.
2460  *
2461  *  @return Returns STOP when test has finished executing.
2462  */
iterate()2463 tcu::TestNode::IterateResult MultisampleTextureFunctionalTestsTextureSizeFragmentShadersTest::iterate()
2464 {
2465     bool are_2d_array_ms_tos_supported =
2466         m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array");
2467     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2468 
2469     /* Set up texture objects */
2470     if (are_2d_array_ms_tos_supported)
2471     {
2472         gl.genTextures(1, &to_2d_multisample_array_id);
2473     }
2474 
2475     gl.genTextures(1, &to_2d_multisample_id);
2476 
2477     if (are_2d_array_ms_tos_supported)
2478     {
2479         gl.activeTexture(GL_TEXTURE0);
2480         gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, to_2d_multisample_array_id);
2481         gl.texStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2, /* samples */
2482                                    GL_RGBA8, 16,                           /* width */
2483                                    32,                                     /* height */
2484                                    8,                                      /* depth */
2485                                    GL_TRUE);                               /* fixedsamplelocations */
2486 
2487         GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up 2D multisample array texture storage");
2488     }
2489 
2490     gl.activeTexture(GL_TEXTURE1);
2491     gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id);
2492     gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, /* samples */
2493                                GL_RGBA8, 16,                 /* width */
2494                                32,                           /* height */
2495                                GL_TRUE);
2496 
2497     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up 2D multisample texture storage");
2498 
2499     /* Set up a fragment shader */
2500     static const char *fs_body =
2501         "#version 310 es\n"
2502         "\n"
2503         "#ifdef GL_OES_texture_storage_multisample_2d_array\n"
2504         "    #extension GL_OES_texture_storage_multisample_2d_array : enable\n"
2505         "#endif\n"
2506         "\n"
2507         "precision highp float;\n"
2508         "\n"
2509         "uniform highp sampler2DMS sampler_2d;\n"
2510         "\n"
2511         "#ifdef GL_OES_texture_storage_multisample_2d_array\n"
2512         "    uniform highp sampler2DMSArray sampler_2d_array;\n"
2513         "#endif"
2514         "\n"
2515         "out vec4 result;\n"
2516         "\n"
2517         "void main()\n"
2518         "{\n"
2519         "    #ifdef GL_OES_texture_storage_multisample_2d_array\n"
2520         "        ivec3 sampler_2d_array_size = textureSize(sampler_2d_array);\n"
2521         "    #else\n"
2522         "        ivec3 sampler_2d_array_size = ivec3(16, 32, 8);\n"
2523         "    #endif\n"
2524         "\n"
2525         "    ivec2 sampler_2d_size = textureSize(sampler_2d);\n"
2526         "\n"
2527         "    if (sampler_2d_size.x       == 16 && sampler_2d_size.y       == 32 &&\n"
2528         "        sampler_2d_array_size.x == 16 && sampler_2d_array_size.y == 32 && sampler_2d_array_size.z == 8)\n"
2529         "    {\n"
2530         "        result = vec4(0, 1, 0, 0);\n"
2531         "    }\n"
2532         "    else\n"
2533         "    {\n"
2534         "        result = vec4(1, 0, 0, 0);\n"
2535         "    }\n"
2536         "}\n";
2537     glw::GLint compile_status = GL_FALSE;
2538 
2539     fs_id = gl.createShader(GL_FRAGMENT_SHADER);
2540 
2541     gl.shaderSource(fs_id, 1 /* count */, &fs_body, NULL);
2542     gl.compileShader(fs_id);
2543     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a fragment shader");
2544 
2545     gl.getShaderiv(fs_id, GL_COMPILE_STATUS, &compile_status);
2546     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not query fragment shader's compile status");
2547 
2548     if (compile_status == GL_FALSE)
2549     {
2550         TCU_FAIL("Could not compile fragment shader");
2551     }
2552 
2553     /* Set up a vertex shader for 2D multisample texture case */
2554     static const char *vs_body = "#version 310 es\n"
2555                                  "\n"
2556                                  "precision highp float;\n"
2557                                  "\n"
2558                                  "void main()\n"
2559                                  "{\n"
2560                                  "   switch (gl_VertexID)\n"
2561                                  "   {\n"
2562                                  "       case 0: gl_Position = vec4(-1, -1, 0, 1); break;\n"
2563                                  "       case 1: gl_Position = vec4(-1,  1, 0, 1); break;\n"
2564                                  "       case 2: gl_Position = vec4( 1,  1, 0, 1); break;\n"
2565                                  "       case 3: gl_Position = vec4( 1, -1, 0, 1); break;\n"
2566                                  "   }\n"
2567                                  "}\n";
2568 
2569     vs_id = gl.createShader(GL_VERTEX_SHADER);
2570 
2571     gl.shaderSource(vs_id, 1 /* count */, &vs_body, NULL);
2572     gl.compileShader(vs_id);
2573     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a vertex shader");
2574 
2575     gl.getShaderiv(vs_id, GL_COMPILE_STATUS, &compile_status);
2576     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not query vertex shader's compile status");
2577 
2578     if (compile_status == GL_FALSE)
2579     {
2580         TCU_FAIL("Could not compile vertex shader");
2581     }
2582 
2583     /* Set up a program object */
2584     po_id = gl.createProgram();
2585 
2586     gl.attachShader(po_id, fs_id);
2587     gl.attachShader(po_id, vs_id);
2588 
2589     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a program object");
2590 
2591     /* Link the program object */
2592     glw::GLint link_status = GL_FALSE;
2593 
2594     gl.linkProgram(po_id);
2595     GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
2596 
2597     gl.getProgramiv(po_id, GL_LINK_STATUS, &link_status);
2598     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
2599 
2600     if (link_status != GL_TRUE)
2601     {
2602         TCU_FAIL("Program object linking failed");
2603     }
2604 
2605     /* Set up uniforms */
2606     glw::GLint sampler_2d_array_location = gl.getUniformLocation(po_id, "sampler_2d_array");
2607     glw::GLint sampler_2d_location       = gl.getUniformLocation(po_id, "sampler_2d");
2608 
2609     if ((sampler_2d_array_location == -1 && are_2d_array_ms_tos_supported) || sampler_2d_location == -1)
2610     {
2611         TCU_FAIL("At least one of the required uniforms is not considered active");
2612     }
2613 
2614     gl.useProgram(po_id);
2615     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
2616 
2617     gl.uniform1i(sampler_2d_array_location, 0);
2618     gl.uniform1i(sampler_2d_location, 1);
2619     GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i() call(s) failed.");
2620 
2621     /* Render a full-screen quad */
2622     gl.drawArrays(GL_TRIANGLE_FAN, 0 /* first */, 4 /* count */);
2623     GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed");
2624 
2625     /* Verify the results */
2626     const tcu::RenderTarget &rt = m_context.getRenderContext().getRenderTarget();
2627 
2628     unsigned char *buffer   = NULL;
2629     unsigned char *data_ptr = NULL;
2630     int rt_bits_alpha       = 0;
2631     int rt_bits_blue        = 0;
2632     int rt_bits_green       = 0;
2633     int rt_bits_red         = 0;
2634     int rt_height           = rt.getHeight();
2635     int rt_width            = rt.getWidth();
2636     const int row_width     = 4 /* RGBA */ * rt_width;
2637 
2638     gl.getIntegerv(GL_ALPHA_BITS, &rt_bits_alpha);
2639     gl.getIntegerv(GL_BLUE_BITS, &rt_bits_blue);
2640     gl.getIntegerv(GL_GREEN_BITS, &rt_bits_green);
2641     gl.getIntegerv(GL_RED_BITS, &rt_bits_red);
2642 
2643     buffer = new unsigned char[rt_height * rt_width * 4];
2644 
2645     gl.readPixels(0, 0, rt_width, rt_height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
2646     GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed");
2647 
2648     data_ptr = buffer + row_width * (rt_height / 2) + rt_width / 2 * 4;
2649 
2650     if (((data_ptr[0] != 0) && (rt_bits_red != 0)) || ((data_ptr[1] != 255) && (rt_bits_green != 0)) ||
2651         ((data_ptr[2] != 0) && (rt_bits_blue != 0)) || ((data_ptr[3] != 0) && (rt_bits_alpha != 0)))
2652     {
2653         m_testCtx.getLog() << tcu::TestLog::Message << "Invalid data rendered: expected:(0, 255, 0, 0) rendered:"
2654                            << "(" << data_ptr[0] << ", " << data_ptr[1] << ", " << data_ptr[2] << ", " << data_ptr[3]
2655                            << ")" << tcu::TestLog::EndMessage;
2656 
2657         delete[] buffer;
2658         buffer = NULL;
2659 
2660         TCU_FAIL("Invalid data rendered");
2661     }
2662 
2663     if (buffer != NULL)
2664     {
2665         delete[] buffer;
2666         buffer = NULL;
2667     }
2668 
2669     /* All done */
2670     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2671 
2672     return STOP;
2673 }
2674 
2675 /** Constructor.
2676  *
2677  *  @param context CTS context handle.
2678  **/
2679 MultisampleTextureFunctionalTestsTextureSizeVertexShadersTest::
MultisampleTextureFunctionalTestsTextureSizeVertexShadersTest(Context & context)2680     MultisampleTextureFunctionalTestsTextureSizeVertexShadersTest(Context &context)
2681     : TestCase(context, "texture_size_in_vertex_shaders",
2682                "Verifies textureSize() works for multisample textures when used in vertex shaders")
2683     , bo_id(0)
2684     , fbo_id(0)
2685     , fs_id(0)
2686     , po_id(0)
2687     , tfo_id(0)
2688     , to_2d_multisample_id(0)
2689     , to_2d_multisample_array_id(0)
2690     , vs_2d_array_id(0)
2691     , vs_2d_id(0)
2692 {
2693     /* Left blank on purpose */
2694 }
2695 
2696 /** Deinitializes ES objects created during test execution */
deinit()2697 void MultisampleTextureFunctionalTestsTextureSizeVertexShadersTest::deinit()
2698 {
2699     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2700 
2701     if (bo_id != 0)
2702     {
2703         gl.deleteBuffers(1, &bo_id);
2704 
2705         bo_id = 0;
2706     }
2707 
2708     if (fbo_id != 0)
2709     {
2710         gl.deleteFramebuffers(1, &fbo_id);
2711 
2712         fbo_id = 0;
2713     }
2714 
2715     if (fs_id != 0)
2716     {
2717         gl.deleteShader(fs_id);
2718 
2719         fs_id = 0;
2720     }
2721 
2722     if (po_id != 0)
2723     {
2724         gl.deleteProgram(po_id);
2725 
2726         po_id = 0;
2727     }
2728 
2729     if (tfo_id != 0)
2730     {
2731         gl.deleteTransformFeedbacks(1, &tfo_id);
2732 
2733         tfo_id = 0;
2734     }
2735 
2736     if (to_2d_multisample_id != 0)
2737     {
2738         gl.deleteTextures(1, &to_2d_multisample_id);
2739 
2740         to_2d_multisample_id = 0;
2741     }
2742 
2743     if (to_2d_multisample_array_id != 0)
2744     {
2745         gl.deleteTextures(1, &to_2d_multisample_array_id);
2746 
2747         to_2d_multisample_array_id = 0;
2748     }
2749 
2750     if (vs_2d_id != 0)
2751     {
2752         gl.deleteShader(vs_2d_id);
2753 
2754         vs_2d_id = 0;
2755     }
2756 
2757     if (vs_2d_array_id != 0)
2758     {
2759         gl.deleteShader(vs_2d_array_id);
2760 
2761         vs_2d_array_id = 0;
2762     }
2763 
2764     /* Call base class' deinit() */
2765     TestCase::deinit();
2766 }
2767 
2768 /** Executes test iteration.
2769  *
2770  *  @return Returns STOP when test has finished executing.
2771  */
iterate()2772 tcu::TestNode::IterateResult MultisampleTextureFunctionalTestsTextureSizeVertexShadersTest::iterate()
2773 {
2774     bool are_multisample_2d_array_tos_supported =
2775         m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array");
2776     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2777 
2778     /* Set up a TFO */
2779     gl.genTransformFeedbacks(1, &tfo_id);
2780     gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, tfo_id);
2781 
2782     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a transform feedback object");
2783 
2784     /* Set up a buffer object */
2785     gl.genBuffers(1, &bo_id);
2786     gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, bo_id);
2787     gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(float), NULL, GL_STATIC_READ);
2788 
2789     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a buffer object");
2790 
2791     /* Set up texture objects */
2792     if (are_multisample_2d_array_tos_supported)
2793     {
2794         gl.genTextures(1, &to_2d_multisample_array_id);
2795     }
2796 
2797     gl.genTextures(1, &to_2d_multisample_id);
2798 
2799     /* NOTE: Since we're binding the textures to zero texture unit,
2800      *       we don't need to do glUniform1i() calls to configure
2801      *       the texture samplers in the vertex shaders later on.
2802      */
2803     if (are_multisample_2d_array_tos_supported)
2804     {
2805         gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, to_2d_multisample_array_id);
2806     }
2807 
2808     gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id);
2809 
2810     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up texture objects");
2811 
2812     gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, /* samples */
2813                                GL_RGBA8, 16,                 /* width */
2814                                32,                           /* height */
2815                                GL_TRUE);
2816     GLU_EXPECT_NO_ERROR(gl.getError(),
2817                         "glTexStorage2DMultisample() call failed for GL_TEXTURE_2D_MULTISAMPLE texture target");
2818 
2819     if (are_multisample_2d_array_tos_supported)
2820     {
2821         gl.texStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2, /* samples */
2822                                    GL_RGBA8, 16,                           /* width */
2823                                    32,                                     /* height */
2824                                    8,                                      /* depth */
2825                                    GL_TRUE);                               /* fixedsamplelocations */
2826         GLU_EXPECT_NO_ERROR(
2827             gl.getError(),
2828             "gltexStorage3DMultisample() call failed for GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES texture target");
2829     }
2830 
2831     /* Set up a fragment shader */
2832     glw::GLint compile_status  = GL_FALSE;
2833     static const char *fs_body = "#version 310 es\n"
2834                                  "\n"
2835                                  "void main()\n"
2836                                  "{\n"
2837                                  "}\n";
2838 
2839     fs_id = gl.createShader(GL_FRAGMENT_SHADER);
2840 
2841     gl.shaderSource(fs_id, 1 /* count */, &fs_body, NULL);
2842     gl.compileShader(fs_id);
2843     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a fragment shader");
2844 
2845     gl.getShaderiv(fs_id, GL_COMPILE_STATUS, &compile_status);
2846     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not query fragment shader's compile status");
2847 
2848     if (compile_status == GL_FALSE)
2849     {
2850         TCU_FAIL("Could not compile fragment shader");
2851     }
2852 
2853     /* Set up a vertex shader for 2D multisample texture case */
2854     static const char *vs_2d_body = "#version 310 es\n"
2855                                     "\n"
2856                                     "precision highp float;\n"
2857                                     "\n"
2858                                     "uniform highp sampler2DMS sampler;\n"
2859                                     "out           float       is_size_correct;\n"
2860                                     "\n"
2861                                     "void main()\n"
2862                                     "{\n"
2863                                     "    ivec2 size = textureSize(sampler);\n"
2864                                     "\n"
2865                                     "    if (size.x == 16 && size.y == 32)\n"
2866                                     "    {\n"
2867                                     "        is_size_correct = 1.0f;\n"
2868                                     "    }\n"
2869                                     "    else\n"
2870                                     "    {\n"
2871                                     "        is_size_correct = 0.0f;\n"
2872                                     "    }\n"
2873                                     "}\n";
2874 
2875     vs_2d_id = gl.createShader(GL_VERTEX_SHADER);
2876 
2877     gl.shaderSource(vs_2d_id, 1 /* count */, &vs_2d_body, NULL);
2878     gl.compileShader(vs_2d_id);
2879     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a vertex shader for 2D multisample texture case");
2880 
2881     gl.getShaderiv(vs_2d_id, GL_COMPILE_STATUS, &compile_status);
2882     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not query 2D multisample texture vertex shader's compile status");
2883 
2884     if (compile_status == GL_FALSE)
2885     {
2886         TCU_FAIL("Could not compile vertex shader for 2D multisample texture");
2887     }
2888 
2889     /* Set up a vertex shader for 2D multisample array texture case */
2890     if (are_multisample_2d_array_tos_supported)
2891     {
2892         static const char *vs_2d_array_body = "#version 310 es\n"
2893                                               "\n"
2894                                               "#extension GL_OES_texture_storage_multisample_2d_array : enable\n"
2895                                               "precision highp float;\n"
2896                                               "\n"
2897                                               "uniform highp sampler2DMSArray sampler;\n"
2898                                               "out           float            is_size_correct;\n"
2899                                               "\n"
2900                                               "void main()\n"
2901                                               "{\n"
2902                                               "    ivec3 size = textureSize(sampler);\n"
2903                                               "\n"
2904                                               "    if (size.x == 16 && size.y == 32 && size.z == 8)\n"
2905                                               "    {\n"
2906                                               "        is_size_correct = 1.0f;\n"
2907                                               "    }\n"
2908                                               "    else\n"
2909                                               "    {\n"
2910                                               "        is_size_correct = 0.0f;\n"
2911                                               "    }\n"
2912                                               "}\n";
2913 
2914         vs_2d_array_id = gl.createShader(GL_VERTEX_SHADER);
2915 
2916         gl.shaderSource(vs_2d_array_id, 1 /* count */, &vs_2d_array_body, NULL);
2917         gl.compileShader(vs_2d_array_id);
2918         GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a vertex shader for 2D multisample array texture case");
2919 
2920         gl.getShaderiv(vs_2d_array_id, GL_COMPILE_STATUS, &compile_status);
2921         GLU_EXPECT_NO_ERROR(gl.getError(),
2922                             "Could not query 2D multisample array texture vertex shader's compile status");
2923 
2924         if (compile_status == GL_FALSE)
2925         {
2926             TCU_FAIL("Could not compile vertex shader for 2D multisample array texture");
2927         }
2928     }
2929 
2930     /* Execute two iterations:
2931      *
2932      * a) Create a program object using fs and vs_2d shaders;
2933      * b) Create a program object using fs and vs_2d_array shaders.
2934      *
2935      * Case b) should only be executed if 2D Array MS textures are
2936      * supported.
2937      */
2938     for (int n_iteration = 0; n_iteration < 2 /* iterations */; ++n_iteration)
2939     {
2940         if (n_iteration == 1 && !are_multisample_2d_array_tos_supported)
2941         {
2942             /* Skip the iteration */
2943             continue;
2944         }
2945 
2946         if (po_id != 0)
2947         {
2948             gl.deleteProgram(po_id);
2949 
2950             po_id = 0;
2951         }
2952 
2953         po_id = gl.createProgram();
2954 
2955         /* Attach iteration-specific shaders */
2956         switch (n_iteration)
2957         {
2958         case 0:
2959         {
2960             gl.attachShader(po_id, fs_id);
2961             gl.attachShader(po_id, vs_2d_id);
2962 
2963             break;
2964         }
2965 
2966         case 1:
2967         {
2968             gl.attachShader(po_id, fs_id);
2969             gl.attachShader(po_id, vs_2d_array_id);
2970 
2971             break;
2972         }
2973 
2974         default:
2975             TCU_FAIL("Unrecognized iteration index");
2976         }
2977 
2978         GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed.");
2979 
2980         /* Configure the program object for XFB */
2981         const char *varying_name = "is_size_correct";
2982 
2983         gl.transformFeedbackVaryings(po_id, 1 /* count */, &varying_name, GL_INTERLEAVED_ATTRIBS);
2984         GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
2985 
2986         /* Link the program object */
2987         glw::GLint link_status = GL_FALSE;
2988 
2989         gl.linkProgram(po_id);
2990         GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
2991 
2992         gl.getProgramiv(po_id, GL_LINK_STATUS, &link_status);
2993         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
2994 
2995         if (link_status != GL_TRUE)
2996         {
2997             m_testCtx.getLog() << tcu::TestLog::Message << "Linking failed for program object in iteration "
2998                                << n_iteration << tcu::TestLog::EndMessage;
2999 
3000             TCU_FAIL("Program object linking failed");
3001         }
3002 
3003         /* Render a point using the program */
3004         gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, bo_id);
3005         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed");
3006 
3007         gl.useProgram(po_id);
3008         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
3009 
3010         gl.beginTransformFeedback(GL_POINTS);
3011         {
3012             gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
3013         }
3014         gl.endTransformFeedback();
3015 
3016         GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed");
3017 
3018         /* Read the captured data. Reset the contents of the BO before the buffer
3019          * object is unmapped.
3020          */
3021         void *data_ptr      = NULL;
3022         const float epsilon = (float)1e-5;
3023         float result        = 0.0f;
3024 
3025         data_ptr = gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* offset */, sizeof(float) /* size */,
3026                                      GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
3027         GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed");
3028 
3029         result = *((const float *)data_ptr);
3030         memset(data_ptr, 0, sizeof(float));
3031 
3032         gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
3033         GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed");
3034 
3035         if (de::abs(result - 1.0f) > epsilon)
3036         {
3037             m_testCtx.getLog() << tcu::TestLog::Message << "Retrieved value: " << result << ", expected: 1.0"
3038                                << tcu::TestLog::EndMessage;
3039 
3040             TCU_FAIL("Invalid value reported.");
3041         }
3042     }
3043 
3044     /* All done */
3045     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3046 
3047     return STOP;
3048 }
3049 } // namespace glcts
3050