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 "should have generated a GL_INVALID_OPERATION error. Instead, "
1237 "["
1238 << error_code << "] error was reported." << tcu::TestLog::EndMessage;
1239
1240 TCU_FAIL("GL_INVALID_OPERATION was not returned by invalid glBlitFramebuffer() call.");
1241 }
1242 } /* for (all valid filter argument values) */
1243
1244 /* All done */
1245 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1246
1247 return STOP;
1248 }
1249
1250 /** Constructor.
1251 *
1252 * @param context Rendering context handle.
1253 **/
1254 MultisampleTextureFunctionalTestsSampleMaskingForNonIntegerColorRenderableTexturesTest::
MultisampleTextureFunctionalTestsSampleMaskingForNonIntegerColorRenderableTexturesTest(Context & context)1255 MultisampleTextureFunctionalTestsSampleMaskingForNonIntegerColorRenderableTexturesTest(Context& context)
1256 : TestCase(context, "verify_sample_masking_for_non_integer_color_renderable_internalformats",
1257 "Verifies sample masking mechanism for non-integer color-renderable "
1258 "internalformats used for 2D multisample textures")
1259 , bo_id(0)
1260 , fbo_id(0)
1261 , fs_draw_id(0)
1262 , po_draw_id(0)
1263 , po_verify_id(0)
1264 , tfo_id(0)
1265 , to_2d_multisample_id(0)
1266 , vs_draw_id(0)
1267 , vs_verify_id(0)
1268 {
1269 /* Left blank on purpose */
1270 }
1271
1272 /** Deinitializes ES objects created during test execution */
deinit()1273 void MultisampleTextureFunctionalTestsSampleMaskingForNonIntegerColorRenderableTexturesTest::deinit()
1274 {
1275 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1276
1277 /* Unset used program */
1278 gl.useProgram(0);
1279
1280 /* Unbind transform feedback object bound to GL_TRANSFORM_FEEDBACK target */
1281 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
1282
1283 /* Unbind buffer object bound to GL_TRANSFORM_FEEDBACK_BUFFER target */
1284 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
1285
1286 /* Unbind framebuffer object bound to GL_DRAW_FRAMEBUFFER target */
1287 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
1288
1289 /* Unbind texture object bound to GL_TEXTURE_2D_MULTISAMPLE texture target */
1290 gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
1291
1292 /* Delete a 2D multisample texture object of id to_2d_multisample_id */
1293 if (to_2d_multisample_id != 0)
1294 {
1295 gl.deleteTextures(1, &to_2d_multisample_id);
1296
1297 to_2d_multisample_id = 0;
1298 }
1299
1300 /* Delete a buffer object of id bo_id */
1301 if (bo_id != 0)
1302 {
1303 gl.deleteBuffers(1, &bo_id);
1304
1305 bo_id = 0;
1306 }
1307
1308 /* Delete a framebuffer object of id fbo_id */
1309 if (fbo_id != 0)
1310 {
1311 gl.deleteFramebuffers(1, &fbo_id);
1312
1313 fbo_id = 0;
1314 }
1315
1316 /* Delete a transform feedback object of id tfo_id */
1317 if (tfo_id != 0)
1318 {
1319 gl.deleteTransformFeedbacks(1, &tfo_id);
1320
1321 tfo_id = 0;
1322 }
1323
1324 /* Delete fs_draw_id shader */
1325 if (fs_draw_id != 0)
1326 {
1327 gl.deleteShader(fs_draw_id);
1328
1329 fs_draw_id = 0;
1330 }
1331
1332 /* Delete vs_verify_id shader */
1333 if (vs_verify_id != 0)
1334 {
1335 gl.deleteShader(vs_verify_id);
1336
1337 vs_verify_id = 0;
1338 }
1339
1340 /* Delete vs_draw_id shader */
1341 if (vs_draw_id != 0)
1342 {
1343 gl.deleteShader(vs_draw_id);
1344
1345 vs_draw_id = 0;
1346 }
1347
1348 /* Delete program objects po_verify_id */
1349 if (po_verify_id != 0)
1350 {
1351 gl.deleteProgram(po_verify_id);
1352
1353 po_verify_id = 0;
1354 }
1355
1356 /* Delete program objects po_draw_id */
1357 if (po_draw_id != 0)
1358 {
1359 gl.deleteProgram(po_draw_id);
1360
1361 po_draw_id = 0;
1362 }
1363
1364 /* Call base class' deinit() */
1365 TestCase::deinit();
1366 }
1367
1368 /** Initializes test-specific ES objects */
initInternals()1369 void MultisampleTextureFunctionalTestsSampleMaskingForNonIntegerColorRenderableTexturesTest::initInternals()
1370 {
1371 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1372
1373 /* Generate a 2D multisample texture object of id to_2d_multisample_id */
1374 gl.genTextures(1, &to_2d_multisample_id);
1375
1376 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed");
1377
1378 if (to_2d_multisample_id == 0)
1379 {
1380 TCU_FAIL("Texture object has not been generated properly");
1381 }
1382
1383 /* Generate a buffer object of id bo_id */
1384 gl.genBuffers(1, &bo_id);
1385
1386 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed");
1387
1388 if (bo_id == 0)
1389 {
1390 TCU_FAIL("Buffer object has not been generated properly");
1391 }
1392
1393 /* Generate a framebuffer object of id fbo_id */
1394 gl.genFramebuffers(1, &fbo_id);
1395
1396 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed");
1397
1398 if (fbo_id == 0)
1399 {
1400 TCU_FAIL("Framebuffer object has not been generated properly");
1401 }
1402
1403 /* Generate a transform feedback object of id tfo_id */
1404 gl.genTransformFeedbacks(1, &tfo_id);
1405
1406 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks() call failed");
1407
1408 if (tfo_id == 0)
1409 {
1410 TCU_FAIL("Transform feedback object has not been generated properly");
1411 }
1412
1413 /* Create a vertex shader vs_draw_id */
1414 vs_draw_id = gl.createShader(GL_VERTEX_SHADER);
1415
1416 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed for vs_draw_id");
1417
1418 /* Create a vertex shader vs_verify_id */
1419 vs_verify_id = gl.createShader(GL_VERTEX_SHADER);
1420
1421 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed for vs_verify_id");
1422
1423 /* Create a fragment shader fs_draw_id */
1424 fs_draw_id = gl.createShader(GL_FRAGMENT_SHADER);
1425
1426 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed for fs_draw_id");
1427
1428 /* Create program objects po_draw_id */
1429 po_draw_id = gl.createProgram();
1430
1431 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed for po_draw_id");
1432
1433 /* Create program objects po_verify_id */
1434 po_verify_id = gl.createProgram();
1435
1436 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed for po_verify_id");
1437 }
1438
1439 /** Executes test iteration.
1440 *
1441 * @return Always STOP.
1442 */
1443 tcu::TestNode::IterateResult MultisampleTextureFunctionalTestsSampleMaskingForNonIntegerColorRenderableTexturesTest::
iterate()1444 iterate()
1445 {
1446 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1447
1448 initInternals();
1449
1450 /* Constants */
1451 const glw::GLfloat epsilon = 1e-5f;
1452 const glw::GLfloat expected_value = 1.0f;
1453 const glw::GLchar* fs_draw_body = "#version 310 es\n"
1454 "\n"
1455 "precision highp float;\n"
1456 "\n"
1457 "out vec4 out_color;\n"
1458 "\n"
1459 "void main()\n"
1460 "{\n"
1461 " out_color = vec4(1, 1, 1, 1);\n"
1462 "}\n";
1463
1464 const glw::GLchar* vs_draw_body = "#version 310 es\n"
1465 "\n"
1466 "precision highp float;\n"
1467 "\n"
1468 "void main()\n"
1469 "{\n"
1470 " switch (gl_VertexID)\n"
1471 " {\n"
1472 " case 0: gl_Position = vec4(-1, 1, 0, 1); break;\n"
1473 " case 1: gl_Position = vec4( 1, 1, 0, 1); break;\n"
1474 " case 2: gl_Position = vec4( 1, -1, 0, 1); break;\n"
1475 " case 3: gl_Position = vec4(-1, -1, 0, 1); break;\n"
1476 " }\n"
1477 "}\n";
1478
1479 const glw::GLchar* vs_verify_body = "#version 310 es\n"
1480 "\n"
1481 "precision highp float;\n"
1482 "\n"
1483 "uniform uint n_bit_on;\n"
1484 "uniform uint n_bits;\n"
1485 "uniform highp sampler2DMS sampler;\n"
1486 "\n"
1487 "out float result;\n"
1488 "\n"
1489 "void main()\n"
1490 "{\n"
1491 " vec4 one = vec4(1);\n"
1492 " vec4 zero = vec4(0.0, 0.0, 0.0, 1.0);\n"
1493 "\n"
1494 " result = 1.0;\n"
1495 "\n"
1496 " for (uint n_current_bit = 0u; n_current_bit < n_bits; n_current_bit++)\n"
1497 " {\n"
1498 " vec4 value = texelFetch(sampler, ivec2(0), int(n_current_bit));\n"
1499 "\n"
1500 " if (n_bit_on == n_current_bit)\n"
1501 " {\n"
1502 " if (any(notEqual(value, one)))\n"
1503 " {\n"
1504 " result = 0.1 + float(n_current_bit)/1000.0;\n"
1505 " break;\n"
1506 " }\n"
1507 " }\n"
1508 " else\n"
1509 " {\n"
1510 " if (any(notEqual(value, zero)))\n"
1511 " {\n"
1512 " result = 0.2 + float(n_current_bit)/1000.0;\n"
1513 " break;\n"
1514 " }\n"
1515 " }\n"
1516 " }\n"
1517 "}\n";
1518
1519 /* Configure the vertex shader vs_draw_id */
1520 compileShader(vs_draw_id, vs_draw_body);
1521
1522 /* Configure the vertex shader vs_verify_id */
1523 compileShader(vs_verify_id, vs_verify_body);
1524
1525 /* Configure the fragment shader fs_draw_id */
1526 compileShader(fs_draw_id, fs_draw_body);
1527
1528 /* Attach the shaders vs_draw_id and fs_draw_id to program object po_draw_id */
1529 gl.attachShader(po_draw_id, vs_draw_id);
1530 gl.attachShader(po_draw_id, fs_draw_id);
1531
1532 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure po_draw_id program object");
1533
1534 /* Attach the shaders vs_verify_id and fs_draw_id to program object po_verify_id */
1535 gl.attachShader(po_verify_id, vs_verify_id);
1536 gl.attachShader(po_verify_id, fs_draw_id);
1537
1538 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure po_verify_id program object");
1539
1540 /* 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. */
1541 const glw::GLchar* vs_verify_varying_name = "result";
1542
1543 gl.transformFeedbackVaryings(po_verify_id, 1, &vs_verify_varying_name, GL_SEPARATE_ATTRIBS);
1544
1545 /* Link the program objects po_draw_id */
1546 linkProgram(po_draw_id);
1547
1548 /* Link the program objects po_verify_id */
1549 linkProgram(po_verify_id);
1550
1551 /* Retrieve uniform locations */
1552 glw::GLuint n_bits_location = gl.getUniformLocation(po_verify_id, "n_bits");
1553 glw::GLuint n_bit_on_location = gl.getUniformLocation(po_verify_id, "n_bit_on");
1554
1555 /* Bind the to_2d_multisample_id texture object to GL_TEXTURE_2D_MULTISAMPLE texture target */
1556 gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id);
1557
1558 /* Bind the fbo_id framebuffer object to GL_DRAW_FRAMEBUFFER target */
1559 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_id);
1560
1561 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a framebuffer object");
1562
1563 /* Bind the bo_id buffer object to GL_TRANSFORM_FEEDBACK_BUFFER generic target */
1564 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, bo_id);
1565
1566 /* Bind the tfo_id transform feedback object go GL_TRANSFORM_FEEDBACK target */
1567 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, tfo_id);
1568
1569 /* Bind the bo_id buffer object to zeroth binding point of GL_TRANSFORM_FEEDBACK_BUFFER */
1570 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, bo_id);
1571
1572 /* Initialize buffer object's storage to hold a total of 4 bytes (sizeof(float) );*/
1573 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(glw::GLfloat), NULL, GL_STATIC_DRAW);
1574
1575 /* Attach the 2D multisample texture object to the framebuffer object's zeroth color attachment */
1576 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id,
1577 0); /* level */
1578
1579 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up zeroth color attachment");
1580
1581 /* Enable GL_SAMPLE_MASK mode */
1582 gl.enable(GL_SAMPLE_MASK);
1583
1584 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_SAMPLE_MASK) call generated an unexpected error");
1585
1586 /* Color-renderable internalformats to test, note that GL_R8 will not work since sampling from
1587 * such format will never return {1,1,1,1} or {0,0,0,1} which current shader uses for sample validation */
1588 const glw::GLenum internalformat_list[] = { GL_RGBA8, GL_RGB565, GL_SRGB8_ALPHA8 };
1589 const int internalformat_list_count = sizeof(internalformat_list) / sizeof(internalformat_list[0]);
1590
1591 /* Get GL_MAX_SAMPLES value */
1592 glw::GLint gl_max_samples_value = 0;
1593
1594 gl.getIntegerv(GL_MAX_SAMPLES, &gl_max_samples_value);
1595
1596 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to retrieve GL_MAX_SAMPLES value");
1597
1598 if (gl_max_samples_value > 32)
1599 {
1600 m_testCtx.getLog() << tcu::TestLog::Message << "The test case checks only first 32 samples out of "
1601 << gl_max_samples_value << " reported by GL_MAX_SAMPLES." << tcu::TestLog::EndMessage;
1602 }
1603
1604 /* Work with no more than 32 bits of mask's first word */
1605 const glw::GLint mask_bits_to_check = de::min(gl_max_samples_value, 32);
1606
1607 /* Keep the results but continue running all cases */
1608 bool test_fail = false;
1609
1610 /* Iterate through all internal formats test case should check */
1611 for (int internalformat_index = 0; internalformat_index < internalformat_list_count; internalformat_index++)
1612 {
1613 /* Configure the texture object storage */
1614 gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, mask_bits_to_check, /* samples */
1615 internalformat_list[internalformat_index], 1, /* width */
1616 1, /* height */
1617 GL_TRUE); /* fixedsamplelocations */
1618
1619 /* Make sure no errors were reported. The framebuffer should be considered complete at this moment. */
1620 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample() call failed");
1621
1622 /* Following code does not affect test method. Just checks if FBO is complete
1623 To catch errors earlier */
1624
1625 glw::GLenum fbo_completeness_status = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER);
1626
1627 if (fbo_completeness_status != GL_FRAMEBUFFER_COMPLETE)
1628 {
1629 m_testCtx.getLog() << tcu::TestLog::Message
1630 << "Draw FBO completeness status is: " << fbo_completeness_status
1631 << ", expected: GL_FRAMEBUFFER_COMPLETE" << tcu::TestLog::EndMessage;
1632
1633 TCU_FAIL("Draw FBO is considered incomplete which is invalid");
1634 }
1635
1636 /* For all values of n_bit from range <0, GL_MAX_SAMPLES pname value) */
1637 for (int n_bit = 0; n_bit < mask_bits_to_check; n_bit++)
1638 {
1639
1640 /* We need to clear render buffer, otherwise masked samples will have undefined values */
1641 glw::GLfloat clear_color_src[] = { 0.0f, 0.0f, 0.0f, 1.0f };
1642
1643 gl.clearBufferfv(GL_COLOR, 0, clear_color_src);
1644 GLU_EXPECT_NO_ERROR(gl.getError(), "clearBufferfv() call failed");
1645
1646 /* Use program object po_draw_id */
1647 gl.useProgram(po_draw_id);
1648
1649 /* Configure sample mask to only render n_bit-th sample using glSampleMaski() function */
1650 gl.sampleMaski(0, 1 << n_bit);
1651
1652 /* Draw a triangle fan of 4 vertices. This fills to_2d_id with multisampled data.
1653 * However, due to active GL_SAMPLE_MASK and the way we configured it, only one sample should have been rendered.
1654 * The only way we can check if this is the case is by using a special shader,
1655 * because we have no way of downloading multisampled data to process space in ES3.0+.
1656 */
1657 gl.drawArrays(GL_TRIANGLE_FAN, 0, /* first */
1658 4 /* count */);
1659
1660 /* Unbind fbo_id before sourcing from the texture attached to it */
1661 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
1662
1663 /* Enable GL_RASTERIZER_DISCARD mode */
1664 gl.enable(GL_RASTERIZER_DISCARD);
1665 {
1666 /* Use program object po_verify_id */
1667 gl.useProgram(po_verify_id);
1668
1669 /* Specify input arguments for vertex shader */
1670 gl.uniform1ui(n_bits_location, mask_bits_to_check);
1671 gl.uniform1ui(n_bit_on_location, n_bit);
1672
1673 /* Bind to_2d_multisample_id to GL_TEXTURE_2D_MULTISAMPLE texture target. Current texture unit is GL_TEXTURE0 */
1674 gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id);
1675
1676 /* Begin transform feedback (primitiveMode: GL_POINTS) */
1677 gl.beginTransformFeedback(GL_POINTS);
1678 {
1679 /* Draw a single point. This will fill our transform feedback buffer with result */
1680 gl.drawArrays(GL_POINTS, 0, 1);
1681 }
1682 /* End transform feedback */
1683 gl.endTransformFeedback();
1684 }
1685 /* Disable GL_RASTERIZER_DISCARD mode */
1686 gl.disable(GL_RASTERIZER_DISCARD);
1687
1688 /* Make sure no errors were generated */
1689 GLU_EXPECT_NO_ERROR(gl.getError(), "Transform feedback failed");
1690
1691 /* Rebind the fbo_id framebuffer object to GL_DRAW_FRAMEBUFFER target */
1692 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_id);
1693
1694 /* Map buffer object bo_id's contents to user-space */
1695 const glw::GLfloat* mapped_bo =
1696 (glw::GLfloat*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 4, GL_MAP_READ_BIT);
1697
1698 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed");
1699
1700 /* Copy result from buffer */
1701 glw::GLfloat result = *mapped_bo;
1702
1703 /* Unmap the buffer object */
1704 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
1705
1706 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed");
1707
1708 /* Verify the value stored by verification program is not 0. If it is 0, the test has failed. */
1709 if (de::abs(result - expected_value) > epsilon)
1710 {
1711 m_testCtx.getLog() << tcu::TestLog::Message << "Unexpected value stored by verification program: ["
1712 << result << "],"
1713 << "Format index: " << internalformat_index << ", "
1714 << "Bit to check: [" << n_bit << "." << tcu::TestLog::EndMessage;
1715 /* Notice test failure */
1716 test_fail = true;
1717 }
1718 }
1719
1720 /* 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 */
1721 gl.deleteTextures(1, &to_2d_multisample_id);
1722
1723 to_2d_multisample_id = 0;
1724
1725 /* Recreate to_2d_multisample_id texture object. */
1726 /* Generate a 2D multisample texture object of id to_2d_multisample_id */
1727 gl.genTextures(1, &to_2d_multisample_id);
1728
1729 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed");
1730
1731 if (to_2d_multisample_id == 0)
1732 {
1733 TCU_FAIL("Texture object has not been generated properly");
1734 }
1735
1736 /* Bind the to_2d_id texture object to GL_TEXTURE_2D_MULTISAMPLE texture target */
1737 gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id);
1738
1739 /* Attach the 2D multisample texture object to the framebuffer object's zeroth color attachment */
1740 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
1741 to_2d_multisample_id, 0); /* level */
1742
1743 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up zeroth color attachment");
1744 }
1745
1746 if (test_fail)
1747 {
1748 TCU_FAIL("Value stored by verification program is not 1.0. Test has failed.");
1749 }
1750
1751 /* Test case passed */
1752 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1753
1754 return STOP;
1755 }
1756
1757 /** Links a program object. Shaders should be attached to program id before call.
1758 * If an error reported throws an exception.
1759 *
1760 * @param id Program id
1761 */
linkProgram(glw::GLuint id)1762 void MultisampleTextureFunctionalTestsSampleMaskingForNonIntegerColorRenderableTexturesTest::linkProgram(glw::GLuint id)
1763 {
1764 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1765
1766 /* Link the test program object */
1767 glw::GLint link_status = GL_FALSE;
1768
1769 gl.linkProgram(id);
1770 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed");
1771
1772 gl.getProgramiv(id, GL_LINK_STATUS, &link_status);
1773
1774 if (link_status != GL_TRUE)
1775 {
1776 TCU_FAIL("Program linking failed");
1777 }
1778 }
1779
1780 /** Compiles the shader. Should the shader not compile, a TestError exception will be thrown.
1781 *
1782 * @param id Generated shader id
1783 * @param source NULL-terminated shader source code string
1784 */
compileShader(glw::GLuint id,const glw::GLchar * source)1785 void MultisampleTextureFunctionalTestsSampleMaskingForNonIntegerColorRenderableTexturesTest::compileShader(
1786 glw::GLuint id, const glw::GLchar* source)
1787 {
1788 glw::GLint compile_status = GL_FALSE;
1789 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1790
1791 gl.shaderSource(id, 1, &source, NULL);
1792 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed");
1793
1794 gl.compileShader(id);
1795 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed");
1796
1797 gl.getShaderiv(id, GL_COMPILE_STATUS, &compile_status);
1798
1799 if (compile_status != GL_TRUE)
1800 {
1801 /* Retrieve adn dump compliation fail reason */
1802 char infoLog[1024];
1803 glw::GLsizei length = 0;
1804
1805 gl.getShaderInfoLog(id, 1024, &length, infoLog);
1806
1807 m_testCtx.getLog() << tcu::TestLog::Message << "Shader compilation failed, shader id=" << id
1808 << ", infoLog: " << infoLog << tcu::TestLog::EndMessage;
1809
1810 TCU_FAIL("Shader compilation failed");
1811 }
1812 }
1813
1814 /** Constructor.
1815 *
1816 * @param context Rendering context handle.
1817 **/
MultisampleTextureFunctionalTestsSampleMaskingTexturesTest(Context & context)1818 MultisampleTextureFunctionalTestsSampleMaskingTexturesTest::MultisampleTextureFunctionalTestsSampleMaskingTexturesTest(
1819 Context& context)
1820 : TestCase(context, "verify_sample_masking_textures",
1821 "Verifies sample masking mechanism for non-integer, integer/unsigned, "
1822 "integer/signed color-renderable internalformats and "
1823 "depth-renderable internalformats. All internalformats "
1824 "are used for 2D multisample textures.")
1825 , bo_id(0)
1826 , fbo_id(0)
1827 , fs_draw_id(0)
1828 , po_draw_id(0)
1829 , po_verify_id(0)
1830 , tfo_id(0)
1831 , to_2d_multisample_id(0)
1832 , vs_draw_id(0)
1833 , vs_verify_id(0)
1834 {
1835 /* Left blank on purpose */
1836 }
1837
1838 /** Deinitializes ES objects created during test execution */
deinit()1839 void MultisampleTextureFunctionalTestsSampleMaskingTexturesTest::deinit()
1840 {
1841 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1842
1843 /* Unset used program */
1844 gl.useProgram(0);
1845
1846 /* Unbind transform feedback object bound to GL_TRANSFORM_FEEDBACK target */
1847 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
1848
1849 /* Unbind buffer object bound to GL_TRANSFORM_FEEDBACK_BUFFER target */
1850 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
1851
1852 /* Unbind framebuffer object bound to GL_DRAW_FRAMEBUFFER target */
1853 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
1854
1855 /* Unbind texture object bound to GL_TEXTURE_2D_MULTISAMPLE texture target */
1856 gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
1857
1858 /* Delete a 2D multisample texture object of id to_2d_multisample_id */
1859 if (to_2d_multisample_id != 0)
1860 {
1861 gl.deleteTextures(1, &to_2d_multisample_id);
1862
1863 to_2d_multisample_id = 0;
1864 }
1865
1866 /* Delete a buffer object of id bo_id */
1867 if (bo_id != 0)
1868 {
1869 gl.deleteBuffers(1, &bo_id);
1870
1871 bo_id = 0;
1872 }
1873
1874 /* Delete a framebuffer object of id fbo_id */
1875 if (fbo_id != 0)
1876 {
1877 gl.deleteFramebuffers(1, &fbo_id);
1878
1879 fbo_id = 0;
1880 }
1881
1882 /* Delete a transform feedback object of id tfo_id */
1883 if (tfo_id != 0)
1884 {
1885 gl.deleteTransformFeedbacks(1, &tfo_id);
1886
1887 tfo_id = 0;
1888 }
1889
1890 /* Delete fs_draw_id shader */
1891 if (fs_draw_id != 0)
1892 {
1893 gl.deleteShader(fs_draw_id);
1894
1895 fs_draw_id = 0;
1896 }
1897
1898 /* Delete vs_verify_id shader */
1899 if (vs_verify_id != 0)
1900 {
1901 gl.deleteShader(vs_verify_id);
1902
1903 vs_verify_id = 0;
1904 }
1905
1906 /* Delete vs_draw_id shader */
1907 if (vs_draw_id != 0)
1908 {
1909 gl.deleteShader(vs_draw_id);
1910
1911 vs_draw_id = 0;
1912 }
1913
1914 /* Delete program objects po_verify_id */
1915 if (po_verify_id != 0)
1916 {
1917 gl.deleteProgram(po_verify_id);
1918
1919 po_verify_id = 0;
1920 }
1921
1922 /* Delete program objects po_draw_id */
1923 if (po_draw_id != 0)
1924 {
1925 gl.deleteProgram(po_draw_id);
1926
1927 po_draw_id = 0;
1928 }
1929
1930 /* Call base class' deinit() */
1931 TestCase::deinit();
1932 }
1933
1934 /** Initializes test-specific ES objects */
initInternals()1935 void MultisampleTextureFunctionalTestsSampleMaskingTexturesTest::initInternals()
1936 {
1937 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1938
1939 /* Generate a 2D multisample texture object of id to_2d_multisample_id */
1940 gl.genTextures(1, &to_2d_multisample_id);
1941
1942 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed");
1943
1944 if (to_2d_multisample_id == 0)
1945 {
1946 TCU_FAIL("Texture object has not been generated properly");
1947 }
1948
1949 /* Generate a buffer object of id bo_id */
1950 gl.genBuffers(1, &bo_id);
1951
1952 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed");
1953
1954 if (bo_id == 0)
1955 {
1956 TCU_FAIL("Buffer object has not been generated properly");
1957 }
1958
1959 /* Generate a framebuffer object of id fbo_id */
1960 gl.genFramebuffers(1, &fbo_id);
1961
1962 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed");
1963
1964 if (fbo_id == 0)
1965 {
1966 TCU_FAIL("Framebuffer object has not been generated properly");
1967 }
1968
1969 /* Generate a transform feedback object of id tfo_id */
1970 gl.genTransformFeedbacks(1, &tfo_id);
1971
1972 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks() call failed");
1973
1974 if (tfo_id == 0)
1975 {
1976 TCU_FAIL("Transform feedback object has not been generated properly");
1977 }
1978
1979 /* Create a vertex shader vs_draw_id */
1980 vs_draw_id = gl.createShader(GL_VERTEX_SHADER);
1981
1982 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed for vs_draw_id");
1983
1984 /* Create a vertex shader vs_verify_id */
1985 vs_verify_id = gl.createShader(GL_VERTEX_SHADER);
1986
1987 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed for vs_verify_id");
1988
1989 /* Create a fragment shader fs_draw_id */
1990 fs_draw_id = gl.createShader(GL_FRAGMENT_SHADER);
1991
1992 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed for fs_draw_id");
1993
1994 /* Create program objects po_draw_id */
1995 po_draw_id = gl.createProgram();
1996
1997 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed for po_draw_id");
1998
1999 /* Create program objects po_verify_id */
2000 po_verify_id = gl.createProgram();
2001
2002 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed for po_verify_id");
2003 }
2004
2005 /** Executes test iteration.
2006 *
2007 * @return Always STOP.
2008 */
iterate()2009 tcu::TestNode::IterateResult MultisampleTextureFunctionalTestsSampleMaskingTexturesTest::iterate()
2010 {
2011 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2012
2013 initInternals();
2014
2015 /* Constants */
2016 const glw::GLfloat epsilon = 1e-5f;
2017 const glw::GLchar* fs_draw_body = "#version 310 es\n"
2018 "\n"
2019 "out vec4 out_color;\n"
2020 "\n"
2021 "void main()\n"
2022 "{\n"
2023 " out_color = vec4(1, 1, 1, 1);\n"
2024 "}\n";
2025
2026 const glw::GLchar* vs_draw_body = "#version 310 es\n"
2027 "\n"
2028 "void main()\n"
2029 "{\n"
2030 " switch (gl_VertexID)\n"
2031 " {\n"
2032 " case 0: gl_Position = vec4(-1, 1, 0, 1); break;\n"
2033 " case 1: gl_Position = vec4( 1, 1, 0, 1); break;\n"
2034 " case 2: gl_Position = vec4( 1, -1, 0, 1); break;\n"
2035 " case 3: gl_Position = vec4(-1, -1, 0, 1); break;\n"
2036 " }\n"
2037 "}\n";
2038
2039 const glw::GLchar* vs_verify_body = "#version 310 es\n"
2040 "\n"
2041 "precision highp float;\n"
2042 "\n"
2043 "uniform uint n_bit_on;\n"
2044 "uniform uint n_bits;\n"
2045 "uniform highp sampler2DMS sampler;\n"
2046 "\n"
2047 "out float result;\n"
2048 "\n"
2049 "void main()\n"
2050 "{\n"
2051 " vec4 one = vec4(1);\n"
2052 " vec4 zero = vec4(0);\n"
2053 "\n"
2054 " result = 1.0;\n"
2055 "\n"
2056 " for (uint n_current_bit = 0u; n_current_bit < n_bits; n_current_bit++)\n"
2057 " {\n"
2058 " vec4 value = texelFetch(sampler, ivec2(0), int(n_current_bit));\n"
2059 "\n"
2060 " if (n_bit_on == n_current_bit)\n"
2061 " {\n"
2062 " if (any(notEqual(value, one)))\n"
2063 " {\n"
2064 " result = 0.0;\n"
2065 " }\n"
2066 " }\n"
2067 " else\n"
2068 " {\n"
2069 " if (any(notEqual(value, zero)))\n"
2070 " {\n"
2071 " result = 0.0;\n"
2072 " }\n"
2073 " }\n"
2074 " }\n"
2075 "}\n";
2076
2077 /* Configure the vertex shader vs_draw_id */
2078 compileShader(vs_draw_id, vs_draw_body);
2079
2080 /* Configure the vertex shader vs_verify_id */
2081 compileShader(vs_verify_id, vs_verify_body);
2082
2083 /* Configure the fragment shader fs_draw_id */
2084 compileShader(fs_draw_id, fs_draw_body);
2085
2086 /* Attach the shaders vs_draw_id and fs_draw_id to program object po_draw_id */
2087 gl.attachShader(po_draw_id, vs_draw_id);
2088 gl.attachShader(po_draw_id, fs_draw_id);
2089
2090 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure po_draw_id program object");
2091
2092 /* Attach the shaders vs_verify_id and fs_draw_id to program object po_verify_id */
2093 gl.attachShader(po_verify_id, vs_verify_id);
2094 gl.attachShader(po_verify_id, fs_draw_id);
2095
2096 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure po_verify_id program object");
2097
2098 /* 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. */
2099 const glw::GLchar* vs_verify_varying_name = "result";
2100
2101 gl.transformFeedbackVaryings(po_verify_id, 1, &vs_verify_varying_name, GL_SEPARATE_ATTRIBS);
2102
2103 /* Link the program objects po_draw_id */
2104 linkProgram(po_draw_id);
2105
2106 /* Link the program objects po_verify_id */
2107 linkProgram(po_verify_id);
2108
2109 /* Retrieve uniform locations */
2110 glw::GLuint n_bits_location = gl.getUniformLocation(po_verify_id, "n_bits");
2111 glw::GLuint n_bit_on_location = gl.getUniformLocation(po_verify_id, "n_bit_on");
2112
2113 /* Bind the to_2d_multisample_id texture object to GL_TEXTURE_2D_MULTISAMPLE texture target */
2114 gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id);
2115
2116 /* Bind the fbo_id framebuffer object to GL_DRAW_FRAMEBUFFER target */
2117 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_id);
2118
2119 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a framebuffer object");
2120
2121 /* Bind the bo_id buffer object to GL_TRANSFORM_FEEDBACK_BUFFER generic target */
2122 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, bo_id);
2123
2124 /* Bind the bo_id buffer object to zeroth binding point of GL_TRANSFORM_FEEDBACK_BUFFER */
2125 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, bo_id);
2126
2127 /* Bind the tfo_id transform feedback object go GL_TRANSFORM_FEEDBACK target */
2128 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, tfo_id);
2129
2130 /* Initialize buffer object's storage to hold a total of 4 bytes (sizeof(float) );*/
2131 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(glw::GLfloat), NULL, GL_STATIC_DRAW);
2132
2133 /* Attach the 2D multisample texture object to the framebuffer object's zeroth color attachment */
2134 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id,
2135 0); /* level */
2136
2137 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up zeroth color attachment");
2138
2139 /* Enable GL_SAMPLE_MASK mode */
2140 gl.enable(GL_SAMPLE_MASK);
2141
2142 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_SAMPLE_MASK) call generated an unexpected error");
2143
2144 /* Iterate through color-normalized-, color-unsigned-integer-, color-signed-integer- and depth-renderable internalformats */
2145 const glw::GLenum normalized_color_internalformats[] = { GL_R8, GL_RGB565, GL_SRGB8_ALPHA8 };
2146 const glw::GLenum unsigned_color_internalformats[] = { GL_RGBA32UI, GL_RG16UI };
2147 const glw::GLenum signed_color_internalformats[] = { GL_RGBA32I, GL_RG16I };
2148 const glw::GLenum depth_internalformats[] = { GL_DEPTH_COMPONENT32F };
2149 const unsigned int n_normalized_color_internalformats =
2150 sizeof(normalized_color_internalformats) / sizeof(normalized_color_internalformats[0]);
2151 const unsigned int n_unsigned_color_internalformats =
2152 sizeof(unsigned_color_internalformats) / sizeof(unsigned_color_internalformats[0]);
2153 const unsigned int n_signed_color_internalformats =
2154 sizeof(signed_color_internalformats) / sizeof(signed_color_internalformats[0]);
2155 const unsigned int n_depth_internalformats = sizeof(depth_internalformats) / sizeof(depth_internalformats[0]);
2156
2157 for (unsigned int n_iteration = 0; n_iteration < 4 /* normalized/unsigned/signed/depth */; ++n_iteration)
2158 {
2159 glw::GLenum attachment = 0;
2160 const glw::GLenum* internalformats = NULL;
2161 unsigned int n_internalformats = 0;
2162
2163 switch (n_iteration)
2164 {
2165 case 0:
2166 {
2167 attachment = GL_COLOR_ATTACHMENT0;
2168 internalformats = normalized_color_internalformats;
2169 n_internalformats = n_normalized_color_internalformats;
2170
2171 break;
2172 }
2173
2174 case 1:
2175 {
2176 attachment = GL_COLOR_ATTACHMENT0;
2177 internalformats = unsigned_color_internalformats;
2178 n_internalformats = n_unsigned_color_internalformats;
2179
2180 break;
2181 }
2182
2183 case 2:
2184 {
2185 attachment = GL_COLOR_ATTACHMENT0;
2186 internalformats = signed_color_internalformats;
2187 n_internalformats = n_signed_color_internalformats;
2188
2189 break;
2190 }
2191
2192 case 3:
2193 {
2194 attachment = GL_DEPTH_ATTACHMENT;
2195 internalformats = depth_internalformats;
2196 n_internalformats = n_depth_internalformats;
2197
2198 break;
2199 }
2200
2201 default:
2202 {
2203 TCU_FAIL("Unrecognized iteration index");
2204 }
2205 } /* switch (n_iteration) */
2206
2207 /* Iterate through internalformats */
2208 for (unsigned int n_internalformat = 0; n_internalformat < n_internalformats; ++n_internalformat)
2209 {
2210 glw::GLenum internalformat = internalformats[n_internalformat];
2211 glw::GLint internalformat_max_samples = 0;
2212
2213 /* Retrieve internalformat-specific GL_MAX_SAMPLES value */
2214 gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, /* target */
2215 internalformat, GL_SAMPLES, 1, /* bufSize */
2216 &internalformat_max_samples);
2217
2218 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetInternalformativ() failed");
2219
2220 if (internalformat_max_samples > 32)
2221 {
2222 m_testCtx.getLog() << tcu::TestLog::Message << "The test case checks only first 32 samples out of "
2223 << internalformat_max_samples
2224 << " reported by GL_SAMPLES reported by getInternalformativ() "
2225 << "for internalformat " << internalformat << "." << tcu::TestLog::EndMessage;
2226 }
2227
2228 /* Work with no more than 32 bits of mask's first word */
2229 const glw::GLint mask_bits_to_check = de::min(internalformat_max_samples, 32);
2230
2231 /* Recreate to_2d_multisample_id texture object. */
2232 if (to_2d_multisample_id == 0)
2233 {
2234 /* Generate a 2D multisample texture object of id to_2d_multisample_id */
2235 gl.genTextures(1, &to_2d_multisample_id);
2236
2237 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed");
2238
2239 if (to_2d_multisample_id == 0)
2240 {
2241 TCU_FAIL("Texture object has not been generated properly");
2242 }
2243
2244 /* Bind the to_2d_id texture object to GL_TEXTURE_2D_MULTISAMPLE texture target */
2245 gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id);
2246
2247 /* Attach the 2D multisample texture object to the framebuffer object's attachment */
2248 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, GL_TEXTURE_2D_MULTISAMPLE,
2249 to_2d_multisample_id, 0); /* level */
2250
2251 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up attachment");
2252 }
2253
2254 /* Configure the texture object storage */
2255 gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, internalformat_max_samples, /* samples */
2256 internalformat, 1, /* width */
2257 1, /* height */
2258 GL_TRUE); /* fixedsamplelocations */
2259
2260 /* Make sure no errors were reported. The framebuffer should be considered complete at this moment. */
2261 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample() call failed");
2262
2263 /* For all values of n_bit from range <0, GL_MAX_SAMPLES pname value) */
2264 for (int n_bit = 0; n_bit < mask_bits_to_check; n_bit++)
2265 {
2266 /* Use program object po_draw_id */
2267 gl.useProgram(po_draw_id);
2268
2269 /* Configure sample mask to only render n_bit-th sample using glSampleMaski() function */
2270 gl.sampleMaski(0, 1 << n_bit);
2271
2272 /* Draw a triangle fan of 4 vertices. This fills to_2d_id with multisampled data.
2273 * However, due to active GL_SAMPLE_MASK and the way we configured it, only one sample should have been rendered.
2274 * The only way we can check if this is the case is by using a special shader,
2275 * because we have no way of downloading multisampled data to process space in ES3.0+.
2276 */
2277 gl.drawArrays(GL_TRIANGLE_FAN, 0, /* first */
2278 4 /* count */);
2279
2280 /* Enable GL_RASTERIZER_DISCARD mode */
2281 gl.enable(GL_RASTERIZER_DISCARD);
2282 {
2283 /* Use program object po_verify_id */
2284 gl.useProgram(po_verify_id);
2285
2286 /* Specify input arguments for vertex shader */
2287 gl.uniform1i(n_bits_location, mask_bits_to_check);
2288 gl.uniform1i(n_bit_on_location, n_bit);
2289
2290 /* Bind to_2d_multisample_id to GL_TEXTURE_2D_MULTISAMPLE texture target. Current texture unit is GL_TEXTURE0 */
2291 gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id);
2292
2293 /* Begin transform feedback (primitiveMode: GL_POINTS) */
2294 gl.beginTransformFeedback(GL_POINTS);
2295 {
2296 /* Draw a single point. This will fill our transform feedback buffer with result */
2297 gl.drawArrays(GL_POINTS, 0, 1);
2298 }
2299 /* End transform feedback */
2300 gl.endTransformFeedback();
2301 }
2302 /* Disable GL_RASTERIZER_DISCARD mode */
2303 gl.disable(GL_RASTERIZER_DISCARD);
2304
2305 /* Make sure no errors were generated */
2306 GLU_EXPECT_NO_ERROR(gl.getError(), "Transform feedback failed");
2307
2308 /* Map buffer object bo_id's contents to user-space */
2309 const glw::GLfloat* mapped_bo = (glw::GLfloat*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
2310
2311 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed");
2312
2313 /* Copy result from buffer */
2314 glw::GLfloat result = *mapped_bo;
2315
2316 /* Unmap the buffer object */
2317 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
2318
2319 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed");
2320
2321 /* Verify the value stored by verification program is not 0. If it is 0, the test has failed. */
2322 if (de::abs(result) < epsilon)
2323 {
2324 TCU_FAIL("Value stored by verification program is zero. Test has failed.");
2325 }
2326 }
2327
2328 /* 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 */
2329 gl.deleteTextures(1, &to_2d_multisample_id);
2330
2331 to_2d_multisample_id = 0;
2332 } /* for (all renderable internalformats) */
2333 } /* for (all iterations) */
2334
2335 /* Test case passed */
2336 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2337
2338 return STOP;
2339 }
2340
2341 /** Links a program object. Shaders should be attached to program id before call.
2342 * If an error reported throws an exception.
2343 *
2344 * @param id Program id
2345 */
linkProgram(glw::GLuint id)2346 void MultisampleTextureFunctionalTestsSampleMaskingTexturesTest::linkProgram(glw::GLuint id)
2347 {
2348 /* Link the test program object */
2349 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2350 glw::GLint link_status = GL_FALSE;
2351
2352 gl.linkProgram(id);
2353 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed");
2354
2355 gl.getProgramiv(id, GL_LINK_STATUS, &link_status);
2356
2357 if (link_status != GL_TRUE)
2358 {
2359 TCU_FAIL("Program linking failed");
2360 }
2361 }
2362
2363 /** Compiles the shader. Should the shader not compile, a TestError exception will be thrown.
2364 *
2365 * @param id Generated shader id
2366 * @param source NULL-terminated shader source code string
2367 */
compileShader(glw::GLuint id,const glw::GLchar * source)2368 void MultisampleTextureFunctionalTestsSampleMaskingTexturesTest::compileShader(glw::GLuint id,
2369 const glw::GLchar* source)
2370 {
2371 glw::GLint compile_status = GL_FALSE;
2372 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2373
2374 gl.shaderSource(id, 1, &source, NULL);
2375 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed");
2376
2377 gl.compileShader(id);
2378 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed");
2379
2380 gl.getShaderiv(id, GL_COMPILE_STATUS, &compile_status);
2381
2382 if (compile_status != GL_TRUE)
2383 {
2384 TCU_FAIL("Shader compilation failed");
2385 }
2386 }
2387
2388 /** Constructor.
2389 *
2390 * @param context CTS context handle.
2391 **/
2392 MultisampleTextureFunctionalTestsTextureSizeFragmentShadersTest::
MultisampleTextureFunctionalTestsTextureSizeFragmentShadersTest(Context & context)2393 MultisampleTextureFunctionalTestsTextureSizeFragmentShadersTest(Context& context)
2394 : TestCase(context, "texture_size_in_fragment_shaders",
2395 "Verifies textureSize() works for multisample textures when used in fragment shaders")
2396 , fbo_id(0)
2397 , fs_id(0)
2398 , po_id(0)
2399 , to_2d_multisample_id(0)
2400 , to_2d_multisample_array_id(0)
2401 , vs_id(0)
2402 {
2403 /* Left blank on purpose */
2404 }
2405
2406 /** Deinitializes ES objects created during test execution */
deinit()2407 void MultisampleTextureFunctionalTestsTextureSizeFragmentShadersTest::deinit()
2408 {
2409 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2410
2411 if (fbo_id != 0)
2412 {
2413 gl.deleteFramebuffers(1, &fbo_id);
2414
2415 fbo_id = 0;
2416 }
2417
2418 if (fs_id != 0)
2419 {
2420 gl.deleteShader(fs_id);
2421
2422 fs_id = 0;
2423 }
2424
2425 if (po_id != 0)
2426 {
2427 gl.deleteProgram(po_id);
2428
2429 po_id = 0;
2430 }
2431
2432 if (to_2d_multisample_id != 0)
2433 {
2434 gl.deleteTextures(1, &to_2d_multisample_id);
2435
2436 to_2d_multisample_id = 0;
2437 }
2438
2439 if (to_2d_multisample_array_id != 0)
2440 {
2441 gl.deleteTextures(1, &to_2d_multisample_array_id);
2442
2443 to_2d_multisample_array_id = 0;
2444 }
2445
2446 if (vs_id != 0)
2447 {
2448 gl.deleteShader(vs_id);
2449
2450 vs_id = 0;
2451 }
2452
2453 /* Call base class' deinit() */
2454 TestCase::deinit();
2455 }
2456
2457 /** Executes test iteration.
2458 *
2459 * @return Returns STOP when test has finished executing.
2460 */
iterate()2461 tcu::TestNode::IterateResult MultisampleTextureFunctionalTestsTextureSizeFragmentShadersTest::iterate()
2462 {
2463 bool are_2d_array_ms_tos_supported =
2464 m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array");
2465 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2466
2467 /* Set up texture objects */
2468 if (are_2d_array_ms_tos_supported)
2469 {
2470 gl.genTextures(1, &to_2d_multisample_array_id);
2471 }
2472
2473 gl.genTextures(1, &to_2d_multisample_id);
2474
2475 if (are_2d_array_ms_tos_supported)
2476 {
2477 gl.activeTexture(GL_TEXTURE0);
2478 gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, to_2d_multisample_array_id);
2479 gl.texStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2, /* samples */
2480 GL_RGBA8, 16, /* width */
2481 32, /* height */
2482 8, /* depth */
2483 GL_TRUE); /* fixedsamplelocations */
2484
2485 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up 2D multisample array texture storage");
2486 }
2487
2488 gl.activeTexture(GL_TEXTURE1);
2489 gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id);
2490 gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, /* samples */
2491 GL_RGBA8, 16, /* width */
2492 32, /* height */
2493 GL_TRUE);
2494
2495 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up 2D multisample texture storage");
2496
2497 /* Set up a fragment shader */
2498 static const char* fs_body =
2499 "#version 310 es\n"
2500 "\n"
2501 "#ifdef GL_OES_texture_storage_multisample_2d_array\n"
2502 " #extension GL_OES_texture_storage_multisample_2d_array : enable\n"
2503 "#endif\n"
2504 "\n"
2505 "precision highp float;\n"
2506 "\n"
2507 "uniform highp sampler2DMS sampler_2d;\n"
2508 "\n"
2509 "#ifdef GL_OES_texture_storage_multisample_2d_array\n"
2510 " uniform highp sampler2DMSArray sampler_2d_array;\n"
2511 "#endif"
2512 "\n"
2513 "out vec4 result;\n"
2514 "\n"
2515 "void main()\n"
2516 "{\n"
2517 " #ifdef GL_OES_texture_storage_multisample_2d_array\n"
2518 " ivec3 sampler_2d_array_size = textureSize(sampler_2d_array);\n"
2519 " #else\n"
2520 " ivec3 sampler_2d_array_size = ivec3(16, 32, 8);\n"
2521 " #endif\n"
2522 "\n"
2523 " ivec2 sampler_2d_size = textureSize(sampler_2d);\n"
2524 "\n"
2525 " if (sampler_2d_size.x == 16 && sampler_2d_size.y == 32 &&\n"
2526 " sampler_2d_array_size.x == 16 && sampler_2d_array_size.y == 32 && sampler_2d_array_size.z == 8)\n"
2527 " {\n"
2528 " result = vec4(0, 1, 0, 0);\n"
2529 " }\n"
2530 " else\n"
2531 " {\n"
2532 " result = vec4(1, 0, 0, 0);\n"
2533 " }\n"
2534 "}\n";
2535 glw::GLint compile_status = GL_FALSE;
2536
2537 fs_id = gl.createShader(GL_FRAGMENT_SHADER);
2538
2539 gl.shaderSource(fs_id, 1 /* count */, &fs_body, NULL);
2540 gl.compileShader(fs_id);
2541 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a fragment shader");
2542
2543 gl.getShaderiv(fs_id, GL_COMPILE_STATUS, &compile_status);
2544 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not query fragment shader's compile status");
2545
2546 if (compile_status == GL_FALSE)
2547 {
2548 TCU_FAIL("Could not compile fragment shader");
2549 }
2550
2551 /* Set up a vertex shader for 2D multisample texture case */
2552 static const char* vs_body = "#version 310 es\n"
2553 "\n"
2554 "precision highp float;\n"
2555 "\n"
2556 "void main()\n"
2557 "{\n"
2558 " switch (gl_VertexID)\n"
2559 " {\n"
2560 " case 0: gl_Position = vec4(-1, -1, 0, 1); break;\n"
2561 " case 1: gl_Position = vec4(-1, 1, 0, 1); break;\n"
2562 " case 2: gl_Position = vec4( 1, 1, 0, 1); break;\n"
2563 " case 3: gl_Position = vec4( 1, -1, 0, 1); break;\n"
2564 " }\n"
2565 "}\n";
2566
2567 vs_id = gl.createShader(GL_VERTEX_SHADER);
2568
2569 gl.shaderSource(vs_id, 1 /* count */, &vs_body, NULL);
2570 gl.compileShader(vs_id);
2571 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a vertex shader");
2572
2573 gl.getShaderiv(vs_id, GL_COMPILE_STATUS, &compile_status);
2574 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not query vertex shader's compile status");
2575
2576 if (compile_status == GL_FALSE)
2577 {
2578 TCU_FAIL("Could not compile vertex shader");
2579 }
2580
2581 /* Set up a program object */
2582 po_id = gl.createProgram();
2583
2584 gl.attachShader(po_id, fs_id);
2585 gl.attachShader(po_id, vs_id);
2586
2587 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a program object");
2588
2589 /* Link the program object */
2590 glw::GLint link_status = GL_FALSE;
2591
2592 gl.linkProgram(po_id);
2593 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
2594
2595 gl.getProgramiv(po_id, GL_LINK_STATUS, &link_status);
2596 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
2597
2598 if (link_status != GL_TRUE)
2599 {
2600 TCU_FAIL("Program object linking failed");
2601 }
2602
2603 /* Set up uniforms */
2604 glw::GLint sampler_2d_array_location = gl.getUniformLocation(po_id, "sampler_2d_array");
2605 glw::GLint sampler_2d_location = gl.getUniformLocation(po_id, "sampler_2d");
2606
2607 if ((sampler_2d_array_location == -1 && are_2d_array_ms_tos_supported) || sampler_2d_location == -1)
2608 {
2609 TCU_FAIL("At least one of the required uniforms is not considered active");
2610 }
2611
2612 gl.useProgram(po_id);
2613 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
2614
2615 gl.uniform1i(sampler_2d_array_location, 0);
2616 gl.uniform1i(sampler_2d_location, 1);
2617 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i() call(s) failed.");
2618
2619 /* Render a full-screen quad */
2620 gl.drawArrays(GL_TRIANGLE_FAN, 0 /* first */, 4 /* count */);
2621 GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed");
2622
2623 /* Verify the results */
2624 const tcu::RenderTarget& rt = m_context.getRenderContext().getRenderTarget();
2625
2626 unsigned char* buffer = NULL;
2627 unsigned char* data_ptr = NULL;
2628 int rt_bits_alpha = 0;
2629 int rt_bits_blue = 0;
2630 int rt_bits_green = 0;
2631 int rt_bits_red = 0;
2632 int rt_height = rt.getHeight();
2633 int rt_width = rt.getWidth();
2634 const int row_width = 4 /* RGBA */ * rt_width;
2635
2636 gl.getIntegerv(GL_ALPHA_BITS, &rt_bits_alpha);
2637 gl.getIntegerv(GL_BLUE_BITS, &rt_bits_blue);
2638 gl.getIntegerv(GL_GREEN_BITS, &rt_bits_green);
2639 gl.getIntegerv(GL_RED_BITS, &rt_bits_red);
2640
2641 buffer = new unsigned char[rt_height * rt_width * 4];
2642
2643 gl.readPixels(0, 0, rt_width, rt_height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
2644 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed");
2645
2646 data_ptr = buffer + row_width * (rt_height / 2) + rt_width / 2 * 4;
2647
2648 if (((data_ptr[0] != 0) && (rt_bits_red != 0)) || ((data_ptr[1] != 255) && (rt_bits_green != 0)) ||
2649 ((data_ptr[2] != 0) && (rt_bits_blue != 0)) || ((data_ptr[3] != 0) && (rt_bits_alpha != 0)))
2650 {
2651 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid data rendered: expected:(0, 255, 0, 0) rendered:"
2652 << "(" << data_ptr[0] << ", " << data_ptr[1] << ", " << data_ptr[2] << ", " << data_ptr[3]
2653 << ")" << tcu::TestLog::EndMessage;
2654
2655 delete[] buffer;
2656 buffer = NULL;
2657
2658 TCU_FAIL("Invalid data rendered");
2659 }
2660
2661 if (buffer != NULL)
2662 {
2663 delete[] buffer;
2664 buffer = NULL;
2665 }
2666
2667 /* All done */
2668 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2669
2670 return STOP;
2671 }
2672
2673 /** Constructor.
2674 *
2675 * @param context CTS context handle.
2676 **/
2677 MultisampleTextureFunctionalTestsTextureSizeVertexShadersTest::
MultisampleTextureFunctionalTestsTextureSizeVertexShadersTest(Context & context)2678 MultisampleTextureFunctionalTestsTextureSizeVertexShadersTest(Context& context)
2679 : TestCase(context, "texture_size_in_vertex_shaders",
2680 "Verifies textureSize() works for multisample textures when used in vertex shaders")
2681 , bo_id(0)
2682 , fbo_id(0)
2683 , fs_id(0)
2684 , po_id(0)
2685 , tfo_id(0)
2686 , to_2d_multisample_id(0)
2687 , to_2d_multisample_array_id(0)
2688 , vs_2d_array_id(0)
2689 , vs_2d_id(0)
2690 {
2691 /* Left blank on purpose */
2692 }
2693
2694 /** Deinitializes ES objects created during test execution */
deinit()2695 void MultisampleTextureFunctionalTestsTextureSizeVertexShadersTest::deinit()
2696 {
2697 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2698
2699 if (bo_id != 0)
2700 {
2701 gl.deleteBuffers(1, &bo_id);
2702
2703 bo_id = 0;
2704 }
2705
2706 if (fbo_id != 0)
2707 {
2708 gl.deleteFramebuffers(1, &fbo_id);
2709
2710 fbo_id = 0;
2711 }
2712
2713 if (fs_id != 0)
2714 {
2715 gl.deleteShader(fs_id);
2716
2717 fs_id = 0;
2718 }
2719
2720 if (po_id != 0)
2721 {
2722 gl.deleteProgram(po_id);
2723
2724 po_id = 0;
2725 }
2726
2727 if (tfo_id != 0)
2728 {
2729 gl.deleteTransformFeedbacks(1, &tfo_id);
2730
2731 tfo_id = 0;
2732 }
2733
2734 if (to_2d_multisample_id != 0)
2735 {
2736 gl.deleteTextures(1, &to_2d_multisample_id);
2737
2738 to_2d_multisample_id = 0;
2739 }
2740
2741 if (to_2d_multisample_array_id != 0)
2742 {
2743 gl.deleteTextures(1, &to_2d_multisample_array_id);
2744
2745 to_2d_multisample_array_id = 0;
2746 }
2747
2748 if (vs_2d_id != 0)
2749 {
2750 gl.deleteShader(vs_2d_id);
2751
2752 vs_2d_id = 0;
2753 }
2754
2755 if (vs_2d_array_id != 0)
2756 {
2757 gl.deleteShader(vs_2d_array_id);
2758
2759 vs_2d_array_id = 0;
2760 }
2761
2762 /* Call base class' deinit() */
2763 TestCase::deinit();
2764 }
2765
2766 /** Executes test iteration.
2767 *
2768 * @return Returns STOP when test has finished executing.
2769 */
iterate()2770 tcu::TestNode::IterateResult MultisampleTextureFunctionalTestsTextureSizeVertexShadersTest::iterate()
2771 {
2772 bool are_multisample_2d_array_tos_supported =
2773 m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array");
2774 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2775
2776 /* Set up a TFO */
2777 gl.genTransformFeedbacks(1, &tfo_id);
2778 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, tfo_id);
2779
2780 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a transform feedback object");
2781
2782 /* Set up a buffer object */
2783 gl.genBuffers(1, &bo_id);
2784 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, bo_id);
2785 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(float), NULL, GL_STATIC_READ);
2786
2787 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a buffer object");
2788
2789 /* Set up texture objects */
2790 if (are_multisample_2d_array_tos_supported)
2791 {
2792 gl.genTextures(1, &to_2d_multisample_array_id);
2793 }
2794
2795 gl.genTextures(1, &to_2d_multisample_id);
2796
2797 /* NOTE: Since we're binding the textures to zero texture unit,
2798 * we don't need to do glUniform1i() calls to configure
2799 * the texture samplers in the vertex shaders later on.
2800 */
2801 if (are_multisample_2d_array_tos_supported)
2802 {
2803 gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, to_2d_multisample_array_id);
2804 }
2805
2806 gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, to_2d_multisample_id);
2807
2808 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up texture objects");
2809
2810 gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, /* samples */
2811 GL_RGBA8, 16, /* width */
2812 32, /* height */
2813 GL_TRUE);
2814 GLU_EXPECT_NO_ERROR(gl.getError(),
2815 "glTexStorage2DMultisample() call failed for GL_TEXTURE_2D_MULTISAMPLE texture target");
2816
2817 if (are_multisample_2d_array_tos_supported)
2818 {
2819 gl.texStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 2, /* samples */
2820 GL_RGBA8, 16, /* width */
2821 32, /* height */
2822 8, /* depth */
2823 GL_TRUE); /* fixedsamplelocations */
2824 GLU_EXPECT_NO_ERROR(
2825 gl.getError(),
2826 "gltexStorage3DMultisample() call failed for GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES texture target");
2827 }
2828
2829 /* Set up a fragment shader */
2830 glw::GLint compile_status = GL_FALSE;
2831 static const char* fs_body = "#version 310 es\n"
2832 "\n"
2833 "void main()\n"
2834 "{\n"
2835 "}\n";
2836
2837 fs_id = gl.createShader(GL_FRAGMENT_SHADER);
2838
2839 gl.shaderSource(fs_id, 1 /* count */, &fs_body, NULL);
2840 gl.compileShader(fs_id);
2841 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a fragment shader");
2842
2843 gl.getShaderiv(fs_id, GL_COMPILE_STATUS, &compile_status);
2844 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not query fragment shader's compile status");
2845
2846 if (compile_status == GL_FALSE)
2847 {
2848 TCU_FAIL("Could not compile fragment shader");
2849 }
2850
2851 /* Set up a vertex shader for 2D multisample texture case */
2852 static const char* vs_2d_body = "#version 310 es\n"
2853 "\n"
2854 "precision highp float;\n"
2855 "\n"
2856 "uniform highp sampler2DMS sampler;\n"
2857 "out float is_size_correct;\n"
2858 "\n"
2859 "void main()\n"
2860 "{\n"
2861 " ivec2 size = textureSize(sampler);\n"
2862 "\n"
2863 " if (size.x == 16 && size.y == 32)\n"
2864 " {\n"
2865 " is_size_correct = 1.0f;\n"
2866 " }\n"
2867 " else\n"
2868 " {\n"
2869 " is_size_correct = 0.0f;\n"
2870 " }\n"
2871 "}\n";
2872
2873 vs_2d_id = gl.createShader(GL_VERTEX_SHADER);
2874
2875 gl.shaderSource(vs_2d_id, 1 /* count */, &vs_2d_body, NULL);
2876 gl.compileShader(vs_2d_id);
2877 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a vertex shader for 2D multisample texture case");
2878
2879 gl.getShaderiv(vs_2d_id, GL_COMPILE_STATUS, &compile_status);
2880 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not query 2D multisample texture vertex shader's compile status");
2881
2882 if (compile_status == GL_FALSE)
2883 {
2884 TCU_FAIL("Could not compile vertex shader for 2D multisample texture");
2885 }
2886
2887 /* Set up a vertex shader for 2D multisample array texture case */
2888 if (are_multisample_2d_array_tos_supported)
2889 {
2890 static const char* vs_2d_array_body = "#version 310 es\n"
2891 "\n"
2892 "#extension GL_OES_texture_storage_multisample_2d_array : enable\n"
2893 "precision highp float;\n"
2894 "\n"
2895 "uniform highp sampler2DMSArray sampler;\n"
2896 "out float is_size_correct;\n"
2897 "\n"
2898 "void main()\n"
2899 "{\n"
2900 " ivec3 size = textureSize(sampler);\n"
2901 "\n"
2902 " if (size.x == 16 && size.y == 32 && size.z == 8)\n"
2903 " {\n"
2904 " is_size_correct = 1.0f;\n"
2905 " }\n"
2906 " else\n"
2907 " {\n"
2908 " is_size_correct = 0.0f;\n"
2909 " }\n"
2910 "}\n";
2911
2912 vs_2d_array_id = gl.createShader(GL_VERTEX_SHADER);
2913
2914 gl.shaderSource(vs_2d_array_id, 1 /* count */, &vs_2d_array_body, NULL);
2915 gl.compileShader(vs_2d_array_id);
2916 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up a vertex shader for 2D multisample array texture case");
2917
2918 gl.getShaderiv(vs_2d_array_id, GL_COMPILE_STATUS, &compile_status);
2919 GLU_EXPECT_NO_ERROR(gl.getError(),
2920 "Could not query 2D multisample array texture vertex shader's compile status");
2921
2922 if (compile_status == GL_FALSE)
2923 {
2924 TCU_FAIL("Could not compile vertex shader for 2D multisample array texture");
2925 }
2926 }
2927
2928 /* Execute two iterations:
2929 *
2930 * a) Create a program object using fs and vs_2d shaders;
2931 * b) Create a program object using fs and vs_2d_array shaders.
2932 *
2933 * Case b) should only be executed if 2D Array MS textures are
2934 * supported.
2935 */
2936 for (int n_iteration = 0; n_iteration < 2 /* iterations */; ++n_iteration)
2937 {
2938 if (n_iteration == 1 && !are_multisample_2d_array_tos_supported)
2939 {
2940 /* Skip the iteration */
2941 continue;
2942 }
2943
2944 if (po_id != 0)
2945 {
2946 gl.deleteProgram(po_id);
2947
2948 po_id = 0;
2949 }
2950
2951 po_id = gl.createProgram();
2952
2953 /* Attach iteration-specific shaders */
2954 switch (n_iteration)
2955 {
2956 case 0:
2957 {
2958 gl.attachShader(po_id, fs_id);
2959 gl.attachShader(po_id, vs_2d_id);
2960
2961 break;
2962 }
2963
2964 case 1:
2965 {
2966 gl.attachShader(po_id, fs_id);
2967 gl.attachShader(po_id, vs_2d_array_id);
2968
2969 break;
2970 }
2971
2972 default:
2973 TCU_FAIL("Unrecognized iteration index");
2974 }
2975
2976 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed.");
2977
2978 /* Configure the program object for XFB */
2979 const char* varying_name = "is_size_correct";
2980
2981 gl.transformFeedbackVaryings(po_id, 1 /* count */, &varying_name, GL_INTERLEAVED_ATTRIBS);
2982 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
2983
2984 /* Link the program object */
2985 glw::GLint link_status = GL_FALSE;
2986
2987 gl.linkProgram(po_id);
2988 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
2989
2990 gl.getProgramiv(po_id, GL_LINK_STATUS, &link_status);
2991 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
2992
2993 if (link_status != GL_TRUE)
2994 {
2995 m_testCtx.getLog() << tcu::TestLog::Message << "Linking failed for program object in iteration "
2996 << n_iteration << tcu::TestLog::EndMessage;
2997
2998 TCU_FAIL("Program object linking failed");
2999 }
3000
3001 /* Render a point using the program */
3002 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, bo_id);
3003 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed");
3004
3005 gl.useProgram(po_id);
3006 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
3007
3008 gl.beginTransformFeedback(GL_POINTS);
3009 {
3010 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
3011 }
3012 gl.endTransformFeedback();
3013
3014 GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed");
3015
3016 /* Read the captured data. Reset the contents of the BO before the buffer
3017 * object is unmapped.
3018 */
3019 void* data_ptr = NULL;
3020 const float epsilon = (float)1e-5;
3021 float result = 0.0f;
3022
3023 data_ptr = gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* offset */, sizeof(float) /* size */,
3024 GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
3025 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed");
3026
3027 result = *((const float*)data_ptr);
3028 memset(data_ptr, 0, sizeof(float));
3029
3030 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
3031 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed");
3032
3033 if (de::abs(result - 1.0f) > epsilon)
3034 {
3035 m_testCtx.getLog() << tcu::TestLog::Message << "Retrieved value: " << result << ", expected: 1.0"
3036 << tcu::TestLog::EndMessage;
3037
3038 TCU_FAIL("Invalid value reported.");
3039 }
3040 }
3041
3042 /* All done */
3043 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3044
3045 return STOP;
3046 }
3047 } /* glcts namespace */
3048